Add control to whether GenericFrontend splits IO ports.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2021-02-11 13:33:55 -08:00
parent e376f950fe
commit 73710416b4
3 changed files with 27 additions and 18 deletions

View File

@ -833,6 +833,7 @@ struct BaseCtx
// Top-level ports // Top-level ports
std::unordered_map<IdString, PortInfo> ports; std::unordered_map<IdString, PortInfo> ports;
std::unordered_map<IdString, CellInfo *> port_cells;
// Floorplanning regions // Floorplanning regions
std::unordered_map<IdString, std::unique_ptr<Region>> region; std::unordered_map<IdString, std::unique_ptr<Region>> region;

View File

@ -123,7 +123,7 @@ struct ModuleInfo
template <typename FrontendType> struct GenericFrontend template <typename FrontendType> struct GenericFrontend
{ {
GenericFrontend(Context *ctx, const FrontendType &impl) : ctx(ctx), impl(impl) {} GenericFrontend(Context *ctx, const FrontendType &impl, bool split_io) : ctx(ctx), impl(impl), split_io(split_io) {}
void operator()() void operator()()
{ {
// Find which module is top // Find which module is top
@ -139,6 +139,7 @@ template <typename FrontendType> struct GenericFrontend
Context *ctx; Context *ctx;
const FrontendType &impl; const FrontendType &impl;
const bool split_io;
using mod_dat_t = typename FrontendType::ModuleDataType; using mod_dat_t = typename FrontendType::ModuleDataType;
using mod_port_dat_t = typename FrontendType::ModulePortDataType; using mod_port_dat_t = typename FrontendType::ModulePortDataType;
using cell_dat_t = typename FrontendType::CellDataType; using cell_dat_t = typename FrontendType::CellDataType;
@ -146,7 +147,7 @@ template <typename FrontendType> struct GenericFrontend
using bitvector_t = typename FrontendType::BitVectorDataType; using bitvector_t = typename FrontendType::BitVectorDataType;
std::unordered_map<IdString, ModuleInfo> mods; std::unordered_map<IdString, ModuleInfo> mods;
std::unordered_map<IdString, const mod_dat_t &> mod_refs; std::unordered_map<IdString, const mod_dat_t> mod_refs;
IdString top; IdString top;
// Process the list of modules and determine // Process the list of modules and determine
@ -583,6 +584,8 @@ template <typename FrontendType> struct GenericFrontend
connect_port(ctx, net, iobuf, ctx->id("I")); connect_port(ctx, net, iobuf, ctx->id("I"));
} else if (dir == PORT_INOUT) { } else if (dir == PORT_INOUT) {
iobuf->type = ctx->id("$nextpnr_iobuf"); iobuf->type = ctx->id("$nextpnr_iobuf");
if (split_io) {
iobuf->addInput(ctx->id("I")); iobuf->addInput(ctx->id("I"));
iobuf->addOutput(ctx->id("O")); iobuf->addOutput(ctx->id("O"));
// Need to bifurcate the net to avoid multiple drivers and split // Need to bifurcate the net to avoid multiple drivers and split
@ -599,6 +602,10 @@ template <typename FrontendType> struct GenericFrontend
connect_port(ctx, split_iobuf_i, iobuf, ctx->id("I")); connect_port(ctx, split_iobuf_i, iobuf, ctx->id("I"));
NPNR_ASSERT(net->driver.cell == nullptr); NPNR_ASSERT(net->driver.cell == nullptr);
connect_port(ctx, net, iobuf, ctx->id("O")); connect_port(ctx, net, iobuf, ctx->id("O"));
} else {
iobuf->addInout(ctx->id("IO"));
connect_port(ctx, net, iobuf, ctx->id("IO"));
}
} }
PortInfo pinfo; PortInfo pinfo;
@ -606,6 +613,7 @@ template <typename FrontendType> struct GenericFrontend
pinfo.net = net; pinfo.net = net;
pinfo.type = dir; pinfo.type = dir;
ctx->ports[pinfo.name] = pinfo; ctx->ports[pinfo.name] = pinfo;
ctx->port_cells[pinfo.name] = iobuf;
return iobuf; return iobuf;
} }

View File

@ -197,7 +197,7 @@ bool parse_json(std::istream &in, const std::string &filename, Context *ctx)
log_error("JSON file '%s' doesn't look like a netlist (doesn't contain \"modules\" key)\n", log_error("JSON file '%s' doesn't look like a netlist (doesn't contain \"modules\" key)\n",
filename.c_str()); filename.c_str());
} }
GenericFrontend<JsonFrontendImpl>(ctx, JsonFrontendImpl(root))(); GenericFrontend<JsonFrontendImpl>(ctx, JsonFrontendImpl(root), /*split_io=*/true)();
return true; return true;
} }