diff --git a/himbaechel/uarch/ng-ultra/extra_data.h b/himbaechel/uarch/ng-ultra/extra_data.h index c4aca007..e6552a5a 100644 --- a/himbaechel/uarch/ng-ultra/extra_data.h +++ b/himbaechel/uarch/ng-ultra/extra_data.h @@ -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, diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.cc b/himbaechel/uarch/ng-ultra/ng_ultra.cc index f634ae48..7b17d9b6 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.cc +++ b/himbaechel/uarch/ng-ultra/ng_ultra.cc @@ -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 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); } diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.h b/himbaechel/uarch/ng-ultra/ng_ultra.h index 41383810..364480ef 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.h +++ b/himbaechel/uarch/ng-ultra/ng_ultra.h @@ -71,7 +71,7 @@ public: dict bank_voltage; dict global_capable_bels; dict locations; - dict> gck_per_lobe; + dict> gck_per_lobe; pool blocked_pips; dict> bank_to_ckg; diff --git a/himbaechel/uarch/ng-ultra/pack.cc b/himbaechel/uarch/ng-ultra/pack.cc index de481379..5f77316c 100644 --- a/himbaechel/uarch/ng-ultra/pack.cc +++ b/himbaechel/uarch/ng-ultra/pack.cc @@ -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& 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& 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))); diff --git a/himbaechel/uarch/ng-ultra/pack.h b/himbaechel/uarch/ng-ultra/pack.h index 1ac8a0a6..428f689a 100644 --- a/himbaechel/uarch/ng-ultra/pack.h +++ b/himbaechel/uarch/ng-ultra/pack.h @@ -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 *attrs); + BelId get_available_gck(int lobe, NetInfo *si1, NetInfo *si2); // General helper functions void flush_cells();