Use cell type where applicable
This commit is contained in:
parent
04653621e8
commit
1c596ada4d
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user