Use cell type where applicable

This commit is contained in:
Miodrag Milanovic 2024-05-30 13:41:26 +02:00
parent 04653621e8
commit 1c596ada4d
4 changed files with 106 additions and 76 deletions

View File

@ -198,7 +198,7 @@ struct BitstreamJsonBackend
std::vector<std::string> config;
void open_instance(CellInfo *cell, std::string type = "", std::string rename = "")
void open_instance(CellInfo *cell, std::string rename = "")
{
out << stringf("%s", first_instance ? "" : ",\n"); first_instance = false;
out << stringf("\t\t%s: {\n", get_string(cleanup_name(rename.empty() ? cell->name.c_str(ctx) : rename.c_str())).c_str());
@ -207,7 +207,7 @@ struct BitstreamJsonBackend
std::string belname = idx.c_str(ctx);
config.clear();
out << stringf("\t\t\t\"location\": %s,\n",get_string(tile_name + ":" + belname).c_str());
out << stringf("\t\t\t\"type\": %s",get_string(type.empty() ? str_or_default(cell->params, ctx->id("type"), "") : type).c_str());
out << stringf("\t\t\t\"type\": %s",get_string(cell->type.c_str(ctx)).c_str());
}
void open_instance_fe(CellInfo *cell, std::string type, std::string replace, std::string postfix = "")
@ -252,7 +252,7 @@ struct BitstreamJsonBackend
}
void write_iop(CellInfo *cell) {
open_instance(cell, "", str_or_default(cell->params, ctx->id("iobname"), ""));
open_instance(cell, str_or_default(cell->params, ctx->id("iobname"), ""));
//add_config("alias_vhdl", str_or_default(cell->params, ctx->id("alias_vhdl"), ""));
//add_config("alias_vlog", str_or_default(cell->params, ctx->id("alias_vlog"), ""));
//add_config("differential", str_or_n_value(cell->params, ctx->id("differential"), "N"));
@ -288,7 +288,7 @@ struct BitstreamJsonBackend
}
void write_dfr(CellInfo *cell) {
open_instance(cell, "BFR");
open_instance(cell);
//add_config("data_inv", bool_or_default(cell->params, ctx->id("data_inv"), false));
//add_config("dff_edge", bool_or_default(cell->params, ctx->id("dff_edge"), false));
//add_config("dff_init", bool_or_default(cell->params, ctx->id("dff_init"), false));
@ -306,7 +306,7 @@ struct BitstreamJsonBackend
}
void write_cy(CellInfo *cell) {
open_instance(cell, "CY");
open_instance(cell);
add_config("add_carry", int_or_default(cell->params, ctx->id("add_carry"), 0));
add_config("shifter", bool_or_default(cell->params, ctx->id("shifter"), false));
close_instance();
@ -334,13 +334,13 @@ struct BitstreamJsonBackend
}
void write_iom(CellInfo *cell) {
open_instance(cell, "IOM");
open_instance(cell);
add_config("pads_path", str_or_default(cell->params, ctx->id("pads_path"), ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"));
close_instance();
}
void write_gck(CellInfo *cell) {
open_instance(cell, "GCK");
open_instance(cell);
add_config("inv_in", bool_or_default(cell->params, ctx->id("inv_in"), false));
add_config("inv_out", bool_or_default(cell->params, ctx->id("inv_out"), false));
add_config("std_mode", str_or_default(cell->params, ctx->id("std_mode"), "BYPASS"));
@ -348,29 +348,19 @@ struct BitstreamJsonBackend
}
void write_wfg(CellInfo *cell) {
std::string subtype = str_or_default(cell->params, ctx->id("type"), "WFB");
open_instance(cell, subtype);
open_instance(cell);
close_instance();
}
void write_rf(CellInfo *cell) {
int mode = int_or_default(cell->params, ctx->id("mode"), 0);
switch(mode) {
case 0 : open_instance(cell, "RF"); break;
case 1 : open_instance(cell, "RFSP"); break;
case 2 : open_instance(cell, "XHRF"); break;
case 3 : open_instance(cell, "XWRF"); break;
case 4 : open_instance(cell, "XPRF"); break;
default:
log_error("Unknown mode %d for cell '%s'.\n", mode, cell->name.c_str(ctx));
}
void write_rfb(CellInfo *cell) {
open_instance(cell);
add_config("context", str_or_default(cell->params, ctx->id("mem_ctxt"), ""));
add_config("wck_edge", bool_or_default(cell->params, ctx->id("wck_edge"), false));
close_instance();
}
void write_ram(CellInfo *cell) {
open_instance(cell, "RAM");
open_instance(cell);
add_config("mcka_edge", bool_or_default(cell->params, ctx->id("mcka_edge"), false));
add_config("mckb_edge", bool_or_default(cell->params, ctx->id("mckb_edge"), false));
add_config("pcka_edge", bool_or_default(cell->params, ctx->id("pcka_edge"), false));
@ -420,20 +410,28 @@ struct BitstreamJsonBackend
first_instance = true;
for (auto &cell : ctx->cells) {
switch (cell.second->type.index) {
case id_IOP.index : write_iop(cell.second.get()); break;
case id_IOTP.index : write_iop(cell.second.get()); break;
case id_BEYOND_FE.index : write_fe(cell.second.get()); break;
case id_CY.index : write_cy(cell.second.get()); break;
case id_WFG.index : write_wfg(cell.second.get()); break;
case id_GCK.index : write_gck(cell.second.get()); break;
case id_IOM.index : write_iom(cell.second.get()); break;
case id_DDFR.index: write_dfr(cell.second.get()); break;
case id_BEYOND_FE.index: write_fe(cell.second.get()); break;
case id_IOP.index:
case id_IP.index:
case id_OP.index:
case id_IOTP.index:
case id_ITP.index:
case id_OTP.index: write_iop(cell.second.get()); break;
case id_CY.index: write_cy(cell.second.get()); break;
case id_WFB.index:
case id_WFG.index: write_wfg(cell.second.get()); break;
case id_GCK.index: write_gck(cell.second.get()); break;
case id_IOM.index: write_iom(cell.second.get()); break;
case id_BFR.index:
case id_DDFR.index:
case id_DFR.index: write_dfr(cell.second.get()); break;
//case id_XLUT.index:
case id_RAM.index: write_ram(cell.second.get()); break;
//case id_RF.index:
case id_RF.index: write_rf(cell.second.get()); break;
case id_XRF.index: write_rf(cell.second.get()); break;
case id_RF.index:
case id_RFSP.index:
case id_XHRF.index:
case id_XWRF.index:
case id_XPRF.index: write_rfb(cell.second.get()); break;
//case id_XLUT.index:
//case id_FIFO.index:
//case id_XFIFO.index:
//case id_CDC.index:
@ -445,6 +443,8 @@ struct BitstreamJsonBackend
//case id_PMA.index:
//case id_Service.index:
//case id_SOCIF.index:
default:
log_error("Unhandled cell %s of type %s\n", cell.second.get()->name.c_str(ctx), cell.second->type.c_str(ctx));
}
}
write_interconnections();

View File

@ -45,6 +45,8 @@ std::unique_ptr<CellInfo> NgUltraPacker::create_cell(IdString type, IdString nam
add_port("CK", PORT_IN);
add_port("R", PORT_IN);
add_port("DO", PORT_OUT);
} else {
log_error("Trying to create unknown cell type %s\n", type.c_str(ctx));
}
return cell;
}
@ -69,6 +71,9 @@ CellInfo *NgUltraPacker::create_cell_ptr(IdString type, IdString name)
add_port("CK", PORT_IN);
add_port("R", PORT_IN);
add_port("DO", PORT_OUT);
} else if (type == id_BFR) {
add_port("I", PORT_IN);
add_port("O", PORT_OUT);
} else if (type == id_DFR) {
add_port("I", PORT_IN);
add_port("O", PORT_OUT);
@ -89,6 +94,8 @@ CellInfo *NgUltraPacker::create_cell_ptr(IdString type, IdString name)
add_port("CKO1", PORT_OUT);
add_port("P19RI", PORT_IN);
add_port("CKO2", PORT_OUT);
} else {
log_error("Trying to create unknown cell type %s\n", type.c_str(ctx));
}
return cell;
}

View File

@ -152,7 +152,7 @@ void NgUltraImpl::postRoute()
}
break;
case id_WFG.index : wfg_bypass++;
cell->setParam(ctx->id("type"), Property("WFB"));
cell->type = id_WFB;
break;
case id_GCK.index : gck_bypass++;
cell->setParam(ctx->id("std_mode"), extra_data.input == 0 ? Property("BYPASS") : Property("CSC"));
@ -319,16 +319,39 @@ bool NgUltraImpl::isBelLocationValid(BelId bel, bool explain_invalid) const
// Bel bucket functions
IdString NgUltraImpl::getBelBucketForCellType(IdString cell_type) const
{
return cell_type;
if (cell_type.in(id_IOP,id_IP,id_OP))
return id_IOP;
else if (cell_type.in(id_IOTP,id_ITP,id_OTP))
return id_IOTP;
else if (cell_type.in(id_BFR))
return id_DFR;
else if (cell_type.in(id_RF, id_RFSP))
return id_RF;
else if (cell_type.in(id_XHRF, id_XWRF, id_XPRF))
return id_XRF;
else if (cell_type.in(id_WFB, id_WFG))
return id_WFG;
else
return cell_type;
}
bool NgUltraImpl::isValidBelForCellType(IdString cell_type, BelId bel) const
{
IdString bel_type = ctx->getBelType(bel);
if (bel_type == id_IOTP)
return cell_type.in(id_IOP,id_IOTP);
return cell_type.in(id_IOP,id_IP,id_OP,id_IOTP,id_ITP,id_OTP);
else if (bel_type == id_IOP)
return cell_type.in(id_IOP,id_IP,id_OP);
else if (bel_type == id_DDFR)
return cell_type.in(id_DFR,id_DDFR);
return cell_type.in(id_BFR,id_DFR,id_DDFR);
else if (bel_type == id_DFR)
return cell_type.in(id_BFR,id_DFR);
else if (bel_type == id_RF)
return cell_type.in(id_RF,id_RFSP);
else if (bel_type == id_XRF)
return cell_type.in(id_XHRF,id_XWRF,id_XPRF);
else if (bel_type == id_WFG)
return cell_type.in(id_WFB,id_WFG);
else
return (bel_type == cell_type);
}

View File

@ -409,21 +409,14 @@ void NgUltraPacker::pack_iobs(void)
ctx->nameOf(ctx->getBoundBelCell(bel)));
}
char last = loc.back();
IdString new_type = (last == 'N' or last == 'P') ? id_IOTP : id_IOP;
std::string subtype = "IOP";
if (ci.type==id_NX_IOB_O) subtype = "OP";
if (ci.type==id_NX_IOB_I) subtype = "IP";
ci.setParam(ctx->id("type"), Property(subtype));
IdString new_type = id_IOP;
if (ci.type==id_NX_IOB_O) new_type = id_OP;
if (ci.type==id_NX_IOB_I) new_type = id_IP;
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;
int bfr_added = 0;
for (auto cell : to_update) {
NetInfo *c_net = cell->getPort(id_C);
if (!c_net)
@ -440,11 +433,10 @@ void NgUltraPacker::pack_iobs(void)
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"));
bfr_added++;
iod = create_cell_ptr(id_BFR, 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));
@ -469,11 +461,10 @@ void NgUltraPacker::pack_iobs(void)
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"));
bfr_added++;
iod = create_cell_ptr(id_BFR, 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));
@ -499,11 +490,10 @@ void NgUltraPacker::pack_iobs(void)
if (!(o_net->users.entries()==1 && (*o_net->users.begin()).cell->type == id_NX_IOM_U)) {
bool bfr_mode = false;
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"));
bfr_added++;
iod = create_cell_ptr(id_BFR, 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));
@ -518,7 +508,7 @@ void NgUltraPacker::pack_iobs(void)
ctx->bindBel(bel, iod, PlaceStrength::STRENGTH_LOCKED);
// Depending of DDFR mode we must use one of dedicated routes (ITCs)
if (iod->type==id_DDFR) {
if (ctx->getBelType(bel)==id_DDFR) {
WireId dwire = ctx->getBelPinWire(bel, id_O);
for (PipId pip : ctx->getPipsDownhill(dwire)) {
const auto &pip_data = chip_pip_info(ctx->chip_info, pip);
@ -535,10 +525,8 @@ void NgUltraPacker::pack_iobs(void)
}
}
}
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);
if (bfr_added)
log_info(" %6d DFRs/DDFRs used as BFR\n", bfr_added);
}
void NgUltraPacker::pack_ioms(void)
@ -810,7 +798,15 @@ void NgUltraPacker::pack_rfs(void)
if (!ci.type.in(id_NX_RFB_U))
continue;
int mode = int_or_default(ci.params, ctx->id("mode"), 0);
ci.type = id_RF;
switch(mode) {
case 0 : ci.type = id_RF; break;
case 1 : ci.type = id_RFSP; break;
case 2 : ci.type = id_XHRF; break;
case 3 : ci.type = id_XWRF; break;
case 4 : ci.type = id_XPRF; break;
default:
log_error("Unknown mode %d for cell '%s'.\n", mode, ci.name.c_str(ctx));
}
ci.cluster = ci.name;
connect_gnd_if_unconnected(&ci, id_I1);
@ -1015,7 +1011,6 @@ void NgUltraPacker::pack_rfs(void)
if (mode > 1) {
// XRF
ci.type = id_XRF;
ci.ports[id_WCK1].name = id_WCK1;
ci.ports[id_WCK1].type = PORT_IN;
ci.ports[id_WCK2].name = id_WCK2;
@ -1058,7 +1053,7 @@ void NgUltraPacker::promote_globals()
--available_globals;
continue;
}
if (!ni->driver.cell->type.in(id_DDFR)) {
if (!ni->driver.cell->type.in(id_BFR)) {
continue;
}
Loc iotp_loc = ni->driver.cell->getLocation();
@ -1080,7 +1075,7 @@ void NgUltraPacker::promote_globals()
// Sort clocks by max fanout
std::sort(glb_fanout.begin(), glb_fanout.end(), std::greater<std::pair<int, IdString>>());
log_info("Promoting globals...\n");
int ddfr_removed = 0;
int bfr_removed = 0;
// Promote the N highest fanout clocks
for (size_t i = 0; i < std::min<size_t>(glb_fanout.size(), available_globals); i++) {
NetInfo *net = ctx->nets.at(glb_fanout.at(i).second).get();
@ -1114,16 +1109,16 @@ void NgUltraPacker::promote_globals()
iom->connectPort(port, input_pad->getPort(id_O));
iom->connectPort((port==id_P17RI) ? id_CKO1 : id_CKO2, iom_to_clk);
ctx->bindBel(bel, iom, PlaceStrength::STRENGTH_LOCKED);
CellInfo *ddfr = net->driver.cell;
if (ddfr->getPort(id_O)->users.empty() && str_or_default(ddfr->params, ctx->id("type"), "")=="BFR") {
ddfr->disconnectPort(id_O);
ddfr->disconnectPort(id_I);
ddfr_removed++;
ctx->cells.erase(ddfr->name);
CellInfo *bfr = net->driver.cell;
if (bfr->type == id_BFR && bfr->getPort(id_O)->users.empty()) {
bfr->disconnectPort(id_O);
bfr->disconnectPort(id_I);
bfr_removed++;
ctx->cells.erase(bfr->name);
}
}
if (ddfr_removed)
log_info(" Removed %d unused DDFRs\n", ddfr_removed);
if (bfr_removed)
log_info(" Removed %d unused BFR\n", bfr_removed);
}
void NgUltraPacker::pack_rams(void)
@ -1152,8 +1147,13 @@ void NgUltraPacker::setup()
{
clock_sinks[id_BEYOND_FE].insert(id_CK);
clock_sinks[id_RF].insert(id_WCK);
clock_sinks[id_XRF].insert(id_WCK1);
clock_sinks[id_XRF].insert(id_WCK2);
clock_sinks[id_RFSP].insert(id_WCK);
clock_sinks[id_XHRF].insert(id_WCK1);
clock_sinks[id_XHRF].insert(id_WCK2);
clock_sinks[id_XWRF].insert(id_WCK1);
clock_sinks[id_XWRF].insert(id_WCK2);
clock_sinks[id_XPRF].insert(id_WCK1);
clock_sinks[id_XPRF].insert(id_WCK2);
clock_sinks[id_RAM].insert(id_ACK);
clock_sinks[id_RAM].insert(id_BCK);
}