Create BFRs properly
This commit is contained in:
parent
0140b2e831
commit
f8680e413d
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
NetInfo *net = ci.getPort(id_C);
|
||||
if (net && net->name.in(ctx->id("$PACKER_GND"), ctx->id("$PACKER_VCC")))
|
||||
{
|
||||
to_update.push_back(&ci);
|
||||
}
|
||||
}
|
||||
int dfr_as_bfr = 0, ddrf_as_bfr = 0;
|
||||
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"));
|
||||
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));
|
||||
|
||||
{
|
||||
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);
|
||||
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 (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);
|
||||
}
|
||||
}
|
||||
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");
|
||||
|
Loading…
Reference in New Issue
Block a user