Add IOM insertion
This commit is contained in:
parent
f8680e413d
commit
3dedb11434
@ -84,6 +84,11 @@ CellInfo *NgUltraPacker::create_cell_ptr(IdString type, IdString name)
|
|||||||
add_port("I2", PORT_IN);
|
add_port("I2", PORT_IN);
|
||||||
add_port("O2", PORT_OUT);
|
add_port("O2", PORT_OUT);
|
||||||
add_port("CKF", PORT_IN);
|
add_port("CKF", PORT_IN);
|
||||||
|
} else if (type == id_IOM) {
|
||||||
|
add_port("P17RI", PORT_IN);
|
||||||
|
add_port("CKO1", PORT_OUT);
|
||||||
|
add_port("P19RI", PORT_IN);
|
||||||
|
add_port("CKO2", PORT_OUT);
|
||||||
}
|
}
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,12 @@ void NgUltraImpl::init(Context *ctx)
|
|||||||
std::deque<BelId> wfgs;
|
std::deque<BelId> wfgs;
|
||||||
IdString bank = tile_name_id(bel.tile);
|
IdString bank = tile_name_id(bel.tile);
|
||||||
iom_bels.emplace(bank,bel);
|
iom_bels.emplace(bank,bel);
|
||||||
|
} else if (ctx->getBelType(bel) == id_IOTP) {
|
||||||
|
if (ctx->getBelName(bel)[1] == ctx->id("D08P_CLK.IOTP")) {
|
||||||
|
global_capable_bels.emplace(bel,id_P17RI);
|
||||||
|
} else if (ctx->getBelName(bel)[1] == ctx->id("D09P_CLK.IOTP")) {
|
||||||
|
global_capable_bels.emplace(bel,id_P19RI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ public:
|
|||||||
|
|
||||||
dict<IdString,BelId> iom_bels;
|
dict<IdString,BelId> iom_bels;
|
||||||
dict<std::string, std::string> bank_voltage;
|
dict<std::string, std::string> bank_voltage;
|
||||||
|
dict<BelId,IdString> global_capable_bels;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void write_bitstream_json(const std::string &filename);
|
void write_bitstream_json(const std::string &filename);
|
||||||
|
@ -697,6 +697,82 @@ void NgUltraPacker::pack_cys(void)
|
|||||||
flush_cells();
|
flush_cells();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There are 20 dedicated clock inputs capable of being routed using global network
|
||||||
|
// to be able to best route them, IOM needs to be used to propagate these clock signals
|
||||||
|
void NgUltraPacker::promote_globals()
|
||||||
|
{
|
||||||
|
std::vector<std::pair<int, IdString>> glb_fanout;
|
||||||
|
int available_globals = 20;
|
||||||
|
for (auto &net : ctx->nets) {
|
||||||
|
NetInfo *ni = net.second.get();
|
||||||
|
// Skip undriven nets; and nets that are already global
|
||||||
|
if (ni->driver.cell == nullptr)
|
||||||
|
continue;
|
||||||
|
if (ni->name.in(ctx->id("$PACKER_GND_NET"), ctx->id("$PACKER_VCC_NET")))
|
||||||
|
continue;
|
||||||
|
if (ni->driver.cell->type == id_IOM) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ni->driver.cell->type == id_GCK) {
|
||||||
|
--available_globals;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!ni->driver.cell->type.in(id_DDFR)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Loc iotp_loc = ni->driver.cell->getLocation();
|
||||||
|
iotp_loc.z -= 1;
|
||||||
|
BelId bel = ctx->getBelByLocation(iotp_loc);
|
||||||
|
if (uarch->global_capable_bels.count(bel)==0)
|
||||||
|
continue;
|
||||||
|
// Count the number of clock ports
|
||||||
|
int glb_count = 0;
|
||||||
|
for (const auto &usr : ni->users) {
|
||||||
|
if (usr.cell->type == id_BEYOND_FE && usr.port == id_CK)
|
||||||
|
glb_count++;
|
||||||
|
}
|
||||||
|
if (glb_count > 0)
|
||||||
|
glb_fanout.emplace_back(glb_count, ni->name);
|
||||||
|
}
|
||||||
|
if (available_globals <= 0)
|
||||||
|
return;
|
||||||
|
// Sort clocks by max fanout
|
||||||
|
std::sort(glb_fanout.begin(), glb_fanout.end(), std::greater<std::pair<int, IdString>>());
|
||||||
|
log_info("Promoting globals...\n");
|
||||||
|
// 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();
|
||||||
|
log_info(" promoting clock net '%s'\n", ctx->nameOf(net));
|
||||||
|
Loc iotp_loc = net->driver.cell->getLocation();
|
||||||
|
iotp_loc.z -= 1;
|
||||||
|
BelId iotp_bel = ctx->getBelByLocation(iotp_loc);
|
||||||
|
|
||||||
|
IdString iob = uarch->tile_name_id(iotp_bel.tile);
|
||||||
|
BelId bel = uarch->iom_bels[iob];
|
||||||
|
|
||||||
|
CellInfo *iom = nullptr;
|
||||||
|
IdString port = uarch->global_capable_bels.at(iotp_bel);
|
||||||
|
if (!ctx->checkBelAvail(bel)) {
|
||||||
|
iom = ctx->getBoundBelCell(bel);
|
||||||
|
} else {
|
||||||
|
iom = create_cell_ptr(id_IOM, ctx->id(std::string(iob.c_str(ctx)) + "$iom"));
|
||||||
|
}
|
||||||
|
if (iom->getPort(port)) {
|
||||||
|
log_error("Port '%s' of IOM cell '%s' is already used.\n", port.c_str(ctx), iom->name.c_str(ctx));
|
||||||
|
}
|
||||||
|
CellInfo *input_pad = ctx->getBoundBelCell(iotp_bel);
|
||||||
|
NetInfo *iom_to_clk = ctx->createNet(ctx->id(std::string(net->name.c_str(ctx)) + "$iom"));
|
||||||
|
for (const auto &usr : net->users) {
|
||||||
|
if (usr.cell->type == id_BEYOND_FE && usr.port == id_CK) {
|
||||||
|
usr.cell->disconnectPort(id_CK);
|
||||||
|
usr.cell->connectPort(id_CK, iom_to_clk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
void NgUltraImpl::pack()
|
void NgUltraImpl::pack()
|
||||||
{
|
{
|
||||||
const ArchArgs &args = ctx->args;
|
const ArchArgs &args = ctx->args;
|
||||||
@ -713,6 +789,7 @@ void NgUltraImpl::pack()
|
|||||||
packer.pack_lut_dffs();
|
packer.pack_lut_dffs();
|
||||||
packer.pack_dffs();
|
packer.pack_dffs();
|
||||||
packer.remove_constants();
|
packer.remove_constants();
|
||||||
|
packer.promote_globals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NgUltraImpl::route_clocks()
|
void NgUltraImpl::route_clocks()
|
||||||
|
@ -53,6 +53,8 @@ struct NgUltraPacker
|
|||||||
void pack_iobs();
|
void pack_iobs();
|
||||||
void pack_ioms();
|
void pack_ioms();
|
||||||
|
|
||||||
|
void promote_globals();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_lut_input_if_constant(CellInfo *cell, IdString input);
|
void set_lut_input_if_constant(CellInfo *cell, IdString input);
|
||||||
void lut_to_fe(CellInfo *lut, CellInfo *fe, bool no_dff, Property lut_table);
|
void lut_to_fe(CellInfo *lut, CellInfo *fe, bool no_dff, Property lut_table);
|
||||||
|
Loading…
Reference in New Issue
Block a user