diff --git a/himbaechel/uarch/ng-ultra/cells.cc b/himbaechel/uarch/ng-ultra/cells.cc index b63fdd4a..e465ed95 100644 --- a/himbaechel/uarch/ng-ultra/cells.cc +++ b/himbaechel/uarch/ng-ultra/cells.cc @@ -97,6 +97,11 @@ CellInfo *NgUltraPacker::create_cell_ptr(IdString type, IdString name) } else if (type == id_WFB) { add_port("ZI", PORT_IN); add_port("ZO", PORT_OUT); + } else if (type == id_GCK) { + add_port("SI1", PORT_IN); + add_port("SI2", PORT_IN); + add_port("CMD", PORT_IN); + add_port("SO", PORT_OUT); } else { log_error("Trying to create unknown cell type %s\n", type.c_str(ctx)); } diff --git a/himbaechel/uarch/ng-ultra/gen/arch_gen.py b/himbaechel/uarch/ng-ultra/gen/arch_gen.py index a5384d5e..39e8e7f0 100644 --- a/himbaechel/uarch/ng-ultra/gen/arch_gen.py +++ b/himbaechel/uarch/ng-ultra/gen/arch_gen.py @@ -387,13 +387,13 @@ def create_tile_types(ch: Chip, bels, bel_pins, crossbars, interconnects, muxes, #elif (tile_type.startswith("CKG") and bel=="WFG"): # by = tt.create_pip(f"{name}.ZI",f"{name}.ZO","BYPASS") # by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0) - elif (tile_type.startswith("TUBE") and bel=="GCK"): - # 20 clock signals comming to 20 GCK, SI1 is bypass - by = tt.create_pip(f"{name}.SI1",f"{name}.SO","BYPASS") - by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0) - # there are CMD signals that can be bypassed as well - by = tt.create_pip(f"{name}.CMD",f"{name}.SO","BYPASS") - by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,1,0) + #elif (tile_type.startswith("TUBE") and bel=="GCK"): + # # 20 clock signals comming to 20 GCK, SI1 is bypass + # by = tt.create_pip(f"{name}.SI1",f"{name}.SO","BYPASS") + # by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0) + # # there are CMD signals that can be bypassed as well + # by = tt.create_pip(f"{name}.CMD",f"{name}.SO","BYPASS") + # by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,1,0) # Add LUT permutation diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.cc b/himbaechel/uarch/ng-ultra/ng_ultra.cc index 7c9edf2c..bb83785a 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.cc +++ b/himbaechel/uarch/ng-ultra/ng_ultra.cc @@ -78,6 +78,9 @@ void NgUltraImpl::init(Context *ctx) } else if (ctx->getBelName(bel)[1] == ctx->id("D09P_CLK.IOTP")) { 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); } 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 4e8e7e9a..8376ead7 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.h +++ b/himbaechel/uarch/ng-ultra/ng_ultra.h @@ -62,6 +62,7 @@ struct NgUltraImpl : HimbaechelAPI bool checkPipAvail(PipId pip) const override { return blocked_pips.count(pip)==0; } bool checkPipAvailForNet(PipId pip, const NetInfo *net) const override { return checkPipAvail(pip); }; + int tile_lobe(int tile) const; public: IdString tile_name_id(int tile) const; std::string tile_name(int tile) const; @@ -70,6 +71,7 @@ public: dict bank_voltage; dict global_capable_bels; dict locations; + dict> gck_per_lobe; pool blocked_pips; dict> wfg_c_per_bank; @@ -86,7 +88,6 @@ private: bool get_mux_data(WireId wire, uint8_t *value); const NGUltraTileInstExtraDataPOD *tile_extra_data(int tile) const; - int tile_lobe(int tile) const; }; diff --git a/himbaechel/uarch/ng-ultra/pack.cc b/himbaechel/uarch/ng-ultra/pack.cc index 3403ddba..9940706c 100644 --- a/himbaechel/uarch/ng-ultra/pack.cc +++ b/himbaechel/uarch/ng-ultra/pack.cc @@ -1456,8 +1456,93 @@ void NgUltraImpl::postPlace() } } remove_constants(); + + + NgUltraPacker packer(ctx, this); + log_break(); + log_info("Running post-placement ...\n"); + packer.duplicate_gck(); + packer.insert_bypass_gck(); + //log_info("Running post-placement legalisation...\n"); + log_break(); + ctx->assignArchInfo(); } +void NgUltraPacker::duplicate_gck() +{ + //log_info("Duplicating existing GCKs...\n"); +} + +void NgUltraPacker::insert_bypass_gck() +{ + dict> glb_sources; + glb_sources[id_IOM].insert(id_CKO1); + glb_sources[id_IOM].insert(id_CKO2); + glb_sources[id_WFB].insert(id_ZO); + glb_sources[id_WFG].insert(id_ZO); + + dict> clock_sinks; + clock_sinks[id_BEYOND_FE].insert(id_CK); + //clock_sinks[id_DFF].insert(id_CK); // This is part of BEYOND_FE + clock_sinks[id_RF].insert(id_WCK); + 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); + //glb_sources[id_BFR].insert(id_O); + //glb_sources[id_GCK].insert(id_SO); + + log_info("Inserting bypass GCKs...\n"); + for (auto &net : ctx->nets) { + NetInfo *glb_net = net.second.get(); + if (!glb_net->driver.cell) + continue; + + // check if we have a global clock net, skip otherwise + if (!(glb_sources.count(glb_net->driver.cell->type) && glb_sources[glb_net->driver.cell->type].count(glb_net->driver.port))) + continue; + + log_info(" Global signal '%s'\n", glb_net->name.c_str(ctx)); + dict> connections; + for (const auto &usr : glb_net->users) { + if (clock_sinks.count(usr.cell->type) && clock_sinks[usr.cell->type].count(usr.port)) { + if (usr.cell->bel==BelId()) { + log_error("Cell '%s' not placed\n",usr.cell->name.c_str(ctx)); + } + int lobe = uarch->tile_lobe(usr.cell->bel.tile); + if (lobe > 0) { + connections[lobe].push_back(usr); + usr.cell->disconnectPort(usr.port); + } + } + } + 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(); + + 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))); + gck_cell->params[id_std_mode] = Property("BYPASS"); + gck_cell->connectPort(id_SI1, glb_net); + NetInfo *new_clk = ctx->createNet(ctx->id(gck_cell->name.str(ctx))); + gck_cell->connectPort(id_SO, new_clk); + for (const auto &usr : conn.second) { + CellInfo *cell = usr.cell; + IdString port = usr.port; + cell->connectPort(port, new_clk); + } + ctx->bindBel(bel, gck_cell, PlaceStrength::STRENGTH_LOCKED); + } + } +} void NgUltraImpl::route_clocks() { dict> glb_sources; diff --git a/himbaechel/uarch/ng-ultra/pack.h b/himbaechel/uarch/ng-ultra/pack.h index 1c2cb7a0..2c8ee60a 100644 --- a/himbaechel/uarch/ng-ultra/pack.h +++ b/himbaechel/uarch/ng-ultra/pack.h @@ -65,6 +65,10 @@ struct NgUltraPacker void setup(); + // Post placement + void duplicate_gck(); + void insert_bypass_gck(); + private: void set_lut_input_if_constant(CellInfo *cell, IdString input); void lut_to_fe(CellInfo *lut, CellInfo *fe, bool no_dff, Property lut_table);