Implement GCK limitations
This commit is contained in:
parent
e1837b781b
commit
9baf87e2a6
@ -20,7 +20,15 @@ NPNR_PACKED_STRUCT(struct NGUltraPipExtraDataPOD {
|
||||
});
|
||||
|
||||
NPNR_PACKED_STRUCT(struct NGUltraBelExtraDataPOD { int32_t flags; });
|
||||
|
||||
|
||||
struct GckConfig {
|
||||
explicit GckConfig(BelId belid) { bel = belid; si1 = IdString(); si2 = IdString(); used = false; }
|
||||
BelId bel;
|
||||
IdString si1;
|
||||
IdString si2;
|
||||
bool used;
|
||||
};
|
||||
|
||||
enum TILETypeZ
|
||||
{
|
||||
BEL_LUT_Z = 0,
|
||||
|
@ -52,6 +52,8 @@ void NgUltraImpl::init_database(Arch *arch)
|
||||
void NgUltraImpl::init(Context *ctx)
|
||||
{
|
||||
HimbaechelAPI::init(ctx);
|
||||
for (int i=1;i<=8;i++)
|
||||
gck_per_lobe[i].reserve(20);
|
||||
for (auto bel : ctx->getBels()) {
|
||||
if (ctx->getBelType(bel) == id_IOM) {
|
||||
std::set<IdString> ckg;
|
||||
@ -81,8 +83,10 @@ void NgUltraImpl::init(Context *ctx)
|
||||
global_capable_bels.emplace(bel,id_P19RI);
|
||||
}
|
||||
} else if (ctx->getBelType(bel) == id_GCK) {
|
||||
int lobe = ctx->getBelName(bel)[1].c_str(ctx)[1] - '0';
|
||||
gck_per_lobe[lobe].emplace(bel);
|
||||
std::string name = ctx->getBelName(bel)[1].c_str(ctx);
|
||||
int lobe = name[1] - '0';
|
||||
int num = atoi(name.substr(4,2).c_str());
|
||||
gck_per_lobe[lobe].insert(gck_per_lobe[lobe].begin()+num-1, GckConfig(bel));
|
||||
}
|
||||
locations.emplace(stringf("%s:%s",tile_name(bel.tile).c_str(), ctx->getBelName(bel)[1].c_str(ctx)),bel);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
dict<std::string, std::string> bank_voltage;
|
||||
dict<BelId,IdString> global_capable_bels;
|
||||
dict<std::string,BelId> locations;
|
||||
dict<int,pool<BelId>> gck_per_lobe;
|
||||
dict<int,std::vector<GckConfig>> gck_per_lobe;
|
||||
|
||||
pool<PipId> blocked_pips;
|
||||
dict<IdString, std::pair<IdString,IdString>> bank_to_ckg;
|
||||
|
@ -527,12 +527,21 @@ void NgUltraPacker::pack_iobs(void)
|
||||
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));
|
||||
if (c_net->name == ctx->id("$PACKER_GND") && !cell->getPort(id_O)) {
|
||||
log_warning("O port of IO primitive %s must be connected. Removing cell.\n", cell->name.c_str(ctx));
|
||||
packed_cells.emplace(cell->name);
|
||||
continue;
|
||||
}
|
||||
if (c_net->name == ctx->id("$PACKER_VCC") && !cell->getPort(id_I)) {
|
||||
log_warning("I port of IO primitive %s must be connected. Removing cell.\n", cell->name.c_str(ctx));
|
||||
packed_cells.emplace(cell->name);
|
||||
continue;
|
||||
}
|
||||
if (!cell->getPort(id_I) && !cell->getPort(id_O)) {
|
||||
log_warning("I or O port of IO primitive %s must be connected. Removing cell.\n", cell->name.c_str(ctx));
|
||||
packed_cells.emplace(cell->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
CellInfo *iod = net_driven_by(ctx, c_net, is_dfr, id_O);
|
||||
@ -633,6 +642,7 @@ void NgUltraPacker::pack_iobs(void)
|
||||
}
|
||||
if (bfr_added)
|
||||
log_info(" %6d DFRs/DDFRs used as BFR\n", bfr_added);
|
||||
flush_cells();
|
||||
}
|
||||
|
||||
void NgUltraPacker::pack_ioms(void)
|
||||
@ -2035,6 +2045,27 @@ void NgUltraImpl::postPlace()
|
||||
ctx->assignArchInfo();
|
||||
}
|
||||
|
||||
BelId NgUltraPacker::get_available_gck(int lobe, NetInfo *si1, NetInfo *si2)
|
||||
{
|
||||
auto &gcks = uarch->gck_per_lobe[lobe];
|
||||
for(int i=0;i<20;i++) {
|
||||
auto &g = gcks.at(i);
|
||||
if (g.used) continue;
|
||||
if (si1 && g.si1!=IdString() && g.si1!=si1->name) continue;
|
||||
if (si2 && g.si2!=IdString() && g.si2!=si2->name) continue;
|
||||
if (si1) g.si1 = si1->name;
|
||||
if (si2) g.si2 = si2->name;
|
||||
g.used = true;
|
||||
if (i%2==0) {
|
||||
// next GCK share inputs in reverse order
|
||||
if (si2) gcks.at(i+1).si1 = si2->name;
|
||||
if (si1) gcks.at(i+1).si2 = si1->name;
|
||||
}
|
||||
return g.bel;
|
||||
}
|
||||
log_error("No GCK left to promote global signal.\n");
|
||||
return BelId();
|
||||
}
|
||||
void NgUltraPacker::duplicate_gck()
|
||||
{
|
||||
// Unbind all GCKs that are inserted
|
||||
@ -2115,11 +2146,7 @@ void NgUltraPacker::duplicate_gck()
|
||||
NetInfo *si2 = driver->getPort(id_SI2);
|
||||
NetInfo *cmd = driver->getPort(id_CMD);
|
||||
for (auto &conn : connections) {
|
||||
pool<BelId>& gck = uarch->gck_per_lobe[conn.first];
|
||||
if (gck.size()==0)
|
||||
log_error("No GCK left to promote global signal.\n");
|
||||
|
||||
BelId bel = gck.pop();
|
||||
BelId bel = get_available_gck(conn.first, si1, si2);
|
||||
CellInfo *gck_cell = nullptr;
|
||||
if (cnt==0) {
|
||||
gck_cell = driver;
|
||||
@ -2218,11 +2245,7 @@ void NgUltraPacker::insert_bypass_gck()
|
||||
}
|
||||
}
|
||||
for (auto &conn : connections) {
|
||||
pool<BelId>& gck = uarch->gck_per_lobe[conn.first];
|
||||
if (gck.size()==0)
|
||||
log_error("No GCK left to promote global signal.\n");
|
||||
|
||||
BelId bel = gck.pop();
|
||||
BelId bel = get_available_gck(conn.first, glb_net, nullptr);
|
||||
|
||||
log_info(" Create GCK for lobe %d\n",conn.first);
|
||||
CellInfo *gck_cell = create_cell_ptr(id_GCK, ctx->id(glb_net->name.str(ctx) + "$gck_"+ std::to_string(conn.first)));
|
||||
|
@ -93,6 +93,7 @@ private:
|
||||
void mandatory_param(CellInfo *cell, IdString param);
|
||||
void disconnect_unused(CellInfo *cell, IdString port);
|
||||
void bind_attr_loc(CellInfo *cell, dict<IdString, Property> *attrs);
|
||||
BelId get_available_gck(int lobe, NetInfo *si1, NetInfo *si2);
|
||||
// General helper functions
|
||||
void flush_cells();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user