diff --git a/himbaechel/uarch/ng-ultra/gen/arch_gen.py b/himbaechel/uarch/ng-ultra/gen/arch_gen.py index 14295736..ae66d002 100644 --- a/himbaechel/uarch/ng-ultra/gen/arch_gen.py +++ b/himbaechel/uarch/ng-ultra/gen/arch_gen.py @@ -381,12 +381,6 @@ def create_tile_types(ch: Chip, bels, bel_pins, crossbars, interconnects, muxes, pd = tt.create_pip(f"{name}."+inp,f"{name}."+out,"MATRIX_PIP") pd.extra_data = PipExtraData(ch.strs.id(f"{name}."+inp),PIP_EXTRA_MUX,int(inp[1:])-1,int(out[1:])-1) - elif (tile_type.startswith("IOB") and bel=="DFR"): - by = tt.create_pip(f"{name}.I",f"{name}.O","BYPASS") - by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0) - elif (tile_type.startswith("IOB") and bel=="DDFR"): - by = tt.create_pip(f"{name}.I",f"{name}.O","BYPASS") - by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0) elif (tile_type.startswith("CKG") and bel=="WFG"): by = tt.create_pip(f"{name}.ZI",f"{name}.ZO","BYPASS") by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0) diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.cc b/himbaechel/uarch/ng-ultra/ng_ultra.cc index 66a25f2e..677fa92e 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.cc +++ b/himbaechel/uarch/ng-ultra/ng_ultra.cc @@ -114,7 +114,7 @@ void NgUltraImpl::postRoute() ctx->assignArchInfo(); log_break(); log_info("Resources spent on routing:\n"); - int dff_bypass = 0, fe_new = 0, wfg_bypass = 0, gck_bypass = 0, ddfr_bypass = 0; + int dff_bypass = 0, fe_new = 0, wfg_bypass = 0, gck_bypass = 0; for (auto &net : ctx->nets) { NetInfo *ni = net.second.get(); for (auto &w : ni->wires) { @@ -132,7 +132,6 @@ void NgUltraImpl::postRoute() if (type==id_BEYOND_FE) fe_new++; } CellInfo *cell = ctx->getBoundBelCell(bel); - std::string bel_name = ctx->getBelName(cell->bel)[1].c_str(ctx); switch(type.index) { case id_BEYOND_FE.index : dff_bypass++; @@ -144,26 +143,6 @@ void NgUltraImpl::postRoute() cell->setParam(ctx->id("type"), Property("WFB")); break; case id_GCK.index : gck_bypass++; break; - case id_DDFR.index : - case id_DFR.index : ddfr_bypass++; - { - Loc loc = ctx->getBelLocation(bel); - cell->setParam(ctx->id("type"), Property("BFR")); - cell->setParam(ctx->id("mode"), Property(2, 2)); - cell->setParam(ctx->id("data_inv"), Property(0, 1)); - if (boost::ends_with(bel_name, "CD")) { - loc.z -= 3; - } else if (boost::ends_with(bel_name, "OD")) { - loc.z -= 2; - } else { - loc.z -= 1; - } - CellInfo *iob = ctx->getBoundBelCell(ctx->getBelByLocation(loc)); - if (!iob || iob->params.count(ctx->id("iobname"))==0) - log_error("IOB for '%s' must have iobname defined.\n", cell->name.c_str(ctx)); - cell->setParam(ctx->id("iobname"), iob->params[ctx->id("iobname")]); - } - break; default: log_error("Unmaped bel type '%s' for routing\n",type.c_str(ctx)); } @@ -174,7 +153,6 @@ void NgUltraImpl::postRoute() log_info(" %6d DFFs used as BFF (%d new allocated FEs)\n", dff_bypass, fe_new); log_info(" %6d WFGs used as WFB\n", wfg_bypass); log_info(" %6d GCK\n", gck_bypass); - log_info(" %6d DFR/DDFR as BFR\n", ddfr_bypass); // Handle LUT permutation for (auto &cell : ctx->cells) { diff --git a/himbaechel/uarch/ng-ultra/pack.cc b/himbaechel/uarch/ng-ultra/pack.cc index 8875a44b..42d8d5eb 100644 --- a/himbaechel/uarch/ng-ultra/pack.cc +++ b/himbaechel/uarch/ng-ultra/pack.cc @@ -44,6 +44,9 @@ inline bool is_dff(const BaseCtx *ctx, const CellInfo *cell) { return cell->type // Return true if a cell is a FE inline bool is_fe(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_BEYOND_FE; } +// Return true if a cell is a DFR +inline bool is_dfr(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_NX_DFR; } + // Process the contents of packed_cells void NgUltraPacker::flush_cells() { @@ -397,31 +400,106 @@ void NgUltraPacker::pack_iobs(void) ci.type = new_type; ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_LOCKED); + to_update.push_back(&ci); + } + int dfr_as_bfr = 0, ddrf_as_bfr = 0; + for (auto cell : to_update) { + NetInfo *c_net = cell->getPort(id_C); + if (!c_net) + log_error("C input of IO primitive %s must be connected.\n", cell->name.c_str(ctx)); + if (c_net->name == ctx->id("$PACKER_GND") && !cell->getPort(id_O)) + log_error("O port of IO primitive %s must be connected.\n", cell->name.c_str(ctx)); + if (c_net->name == ctx->id("$PACKER_VCC") && !cell->getPort(id_I)) + log_error("I port of IO primitive %s must be connected.\n", cell->name.c_str(ctx)); + if (!cell->getPort(id_I) && !cell->getPort(id_O)) + log_error("I or O port of IO primitive %s must be connected.\n", cell->name.c_str(ctx)); - NetInfo *net = ci.getPort(id_C); - if (net && net->name.in(ctx->id("$PACKER_GND"), ctx->id("$PACKER_VCC"))) { - to_update.push_back(&ci); + CellInfo *iod = net_driven_by(ctx, c_net, is_dfr, id_O); + if (iod && c_net->users.entries()!=1) + log_error("NX_DFR '%s can only directly drive IOB.\n", iod->name.c_str(ctx)); + if (!iod) { + if (cell->type==id_IOTP) ddrf_as_bfr++; else dfr_as_bfr++; + iod = create_cell_ptr((cell->type==id_IOTP) ? id_DDFR : id_DFR, ctx->id(cell->name.str(ctx) + "$iod_cd")); + NetInfo *new_out = ctx->createNet(ctx->id(iod->name.str(ctx) + "$O")); + iod->setParam(ctx->id("iobname"),str_or_default(cell->params, ctx->id("iobname"), "")); + iod->setParam(ctx->id("type"), Property("BFR")); + cell->disconnectPort(id_C); + if (c_net->name == ctx->id("$PACKER_GND")) + iod->setParam(ctx->id("mode"), Property(0, 2)); + else if (c_net->name == ctx->id("$PACKER_VCC")) + iod->setParam(ctx->id("mode"), Property(1, 2)); + else { + iod->connectPort(id_I, c_net); + iod->setParam(ctx->id("mode"), Property(2, 2)); + iod->setParam(ctx->id("data_inv"), Property(0, 1)); + } + iod->connectPort(id_O, new_out); + cell->connectPort(id_C,new_out); + } else log_error("TODO handle DFR"); + Loc cd_loc = cell->getLocation(); + cd_loc.z += 3; + BelId bel = ctx->getBelByLocation(cd_loc); + ctx->bindBel(bel, iod, PlaceStrength::STRENGTH_LOCKED); + } + NetInfo *i_net = cell->getPort(id_I); + if (i_net) { + CellInfo *iod = net_driven_by(ctx, i_net, is_dfr, id_O); + if (iod && i_net->users.entries()!=1) + log_error("NX_DFR '%s can only directly drive IOB.\n", iod->name.c_str(ctx)); + if (!iod) { + if (cell->type==id_IOTP) ddrf_as_bfr++; else dfr_as_bfr++; + iod = create_cell_ptr((cell->type==id_IOTP) ? id_DDFR : id_DFR, ctx->id(cell->name.str(ctx) + "$iod_od")); + NetInfo *new_out = ctx->createNet(ctx->id(iod->name.str(ctx) + "$O")); + iod->setParam(ctx->id("iobname"),str_or_default(cell->params, ctx->id("iobname"), "")); + iod->setParam(ctx->id("type"), Property("BFR")); + cell->disconnectPort(id_I); + if (i_net->name == ctx->id("$PACKER_GND")) + iod->setParam(ctx->id("mode"), Property(0, 2)); + else if (i_net->name == ctx->id("$PACKER_VCC")) + iod->setParam(ctx->id("mode"), Property(1, 2)); + else { + iod->connectPort(id_I, i_net); + iod->setParam(ctx->id("mode"), Property(2, 2)); + iod->setParam(ctx->id("data_inv"), Property(0, 1)); + } + iod->connectPort(id_O, new_out); + cell->connectPort(id_I,new_out); + } else log_error("TODO handle DFR"); + Loc cd_loc = cell->getLocation(); + cd_loc.z += 2; + BelId bel = ctx->getBelByLocation(cd_loc); + ctx->bindBel(bel, iod, PlaceStrength::STRENGTH_LOCKED); + } + + NetInfo *o_net = cell->getPort(id_O); + if (o_net) { + CellInfo *iod = net_only_drives(ctx, o_net, is_dfr, id_I, true); + if (!iod) { + if (cell->type==id_IOTP) ddrf_as_bfr++; else dfr_as_bfr++; + iod = create_cell_ptr((cell->type==id_IOTP) ? id_DDFR : id_DFR, ctx->id(cell->name.str(ctx) + "$iod_id")); + NetInfo *new_in = ctx->createNet(ctx->id(iod->name.str(ctx) + "$I")); + iod->setParam(ctx->id("iobname"),str_or_default(cell->params, ctx->id("iobname"), "")); + iod->setParam(ctx->id("type"), Property("BFR")); + cell->disconnectPort(id_O); + iod->connectPort(id_O, o_net); + iod->setParam(ctx->id("mode"), Property(2, 2)); + iod->setParam(ctx->id("data_inv"), Property(0, 1)); + iod->connectPort(id_I, new_in); + cell->connectPort(id_O,new_in); + } else log_error("TODO handle DFR"); + Loc cd_loc = cell->getLocation(); + cd_loc.z += 1; + BelId bel = ctx->getBelByLocation(cd_loc); + ctx->bindBel(bel, iod, PlaceStrength::STRENGTH_LOCKED); } } - for (auto cell : to_update) { - CellInfo *iod_cd = create_cell_ptr((cell->type==id_IOTP) ? id_DDFR : id_DFR, ctx->id(cell->name.str(ctx) + "$iod_cd")); - cell->disconnectPort(id_C); - NetInfo *new_out = ctx->createNet(ctx->id(iod_cd->name.str(ctx) + "$O")); - iod_cd->connectPort(id_O, new_out); - iod_cd->setParam(ctx->id("iobname"),str_or_default(cell->params, ctx->id("iobname"), "")); - iod_cd->setParam(ctx->id("type"), Property("BFR")); - if (cell->params[ctx->id("type")].as_string()=="IP") - iod_cd->setParam(ctx->id("mode"), Property(0, 2)); - else - iod_cd->setParam(ctx->id("mode"), Property(1, 2)); - cell->connectPort(id_C,new_out); - Loc loc = cell->getLocation(); - loc.z += 3; - BelId bel = ctx->getBelByLocation(loc); - ctx->bindBel(bel, iod_cd, PlaceStrength::STRENGTH_LOCKED); - } + if (dfr_as_bfr) + log_info(" %6d DFRs used as BFR\n", dfr_as_bfr); + if (ddrf_as_bfr) + log_info(" %6d DDFRs used as BFR\n", ddrf_as_bfr); } + void NgUltraPacker::pack_ioms(void) { log_info("Pack IOMs...\n");