diff --git a/himbaechel/uarch/gowin/globals.cc b/himbaechel/uarch/gowin/globals.cc index fa7bb2aa..ee90b5d9 100644 --- a/himbaechel/uarch/gowin/globals.cc +++ b/himbaechel/uarch/gowin/globals.cc @@ -150,7 +150,7 @@ struct GowinGlobalRouter bool src_valid = ((!src_is_spine) && src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O, id_HCLK)) || src_name.in(id_SPINE6, id_SPINE7, id_SPINE14, id_SPINE15, id_SPINE22, id_SPINE23, id_SPINE30, id_SPINE31); - bool dst_valid = dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_IO_I, id_HCLK); + bool dst_valid = dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_PLL_O, id_IO_I, id_HCLK); bool res = (src_valid && dst_valid) || (src_valid && is_local(dst_type)) || (is_local(src_type) && dst_valid); if (ctx->debug && false /*&& res*/) { @@ -207,6 +207,7 @@ struct GowinGlobalRouter if (!pip_filter(pip, src)) { continue; } + // Add to the queue visit.push(prev); backtrace[prev] = pip; @@ -399,6 +400,8 @@ struct GowinGlobalRouter void route_dcs_net(NetInfo *net) { + IdString dcs_clock_input_prefix = gwu.get_dcs_prefix(); + const char *dcs_clock_input_prefix_str = dcs_clock_input_prefix.c_str(ctx); // Since CLKOUT is responsible for only one quadrant, we will do // routing not from it, but from any CLK0-3 input actually connected to // the clock source. @@ -406,7 +409,7 @@ struct GowinGlobalRouter NetInfo *net_before_dcs; PortRef driver; for (int i = 0; i < 4; ++i) { - net_before_dcs = dcs_ci->getPort(ctx->idf("CLK%d", i)); + net_before_dcs = dcs_ci->getPort(ctx->idf("%s%d", dcs_clock_input_prefix_str, i)); if (net_before_dcs == nullptr) { continue; } @@ -449,7 +452,8 @@ struct GowinGlobalRouter } WireId dst = ctx->getPipDstWire(pip); IdString dst_name = ctx->getWireName(dst)[1]; - if (dst_name.str(ctx).rfind("PCLK", 0) == 0 || dst_name.str(ctx).rfind("LWSPINE", 0) == 0) { + if (dst_name.str(ctx).rfind("PCLK", 0) == 0 || dst_name.str(ctx).rfind("LWSPINE", 0) == 0 || + dst_name.str(ctx).rfind("PLL") == 0) { // step over dummy pip for (PipId next_pip : ctx->getPipsDownhill(dst)) { if (ctx->getBoundPipNet(next_pip) != nullptr) { @@ -498,7 +502,7 @@ struct GowinGlobalRouter // The input networks must bs same for all hardware dcs. dcs_ci->copyPortTo(id_SELFORCE, hw_dcs, id_SELFORCE); - dcs_ci->copyPortBusTo(id_CLK, 0, false, hw_dcs, id_CLK, 0, false, 4); + dcs_ci->copyPortBusTo(dcs_clock_input_prefix, 0, false, hw_dcs, dcs_clock_input_prefix, 0, false, 4); dcs_ci->copyPortBusTo(id_CLKSEL, 0, true, hw_dcs, id_CLKSEL, 0, false, 4); } @@ -507,7 +511,7 @@ struct GowinGlobalRouter dcs_ci->disconnectPort(id_CLKOUT); for (int i = 0; i < 4; ++i) { dcs_ci->disconnectPort(ctx->idf("CLKSEL[%d]", i)); - dcs_ci->disconnectPort(ctx->idf("CLK%d", i)); + dcs_ci->disconnectPort(ctx->idf("%s%d", dcs_clock_input_prefix_str, i)); } log_info(" '%s' net was routed.\n", ctx->nameOf(net)); ctx->cells.erase(dcs_ci->name); @@ -1281,7 +1285,7 @@ struct GowinGlobalRouter } if (route_clk_net(ni) == NOT_ROUTED) { if (ctx->verbose) { - log_info(" try to route as a segmented network.\n"); + log_info(" will try to route it as a segmented network.\n"); } seg_nets.push_back(net_name); } diff --git a/himbaechel/uarch/gowin/gowin.h b/himbaechel/uarch/gowin/gowin.h index 1a79243c..0300bbc7 100644 --- a/himbaechel/uarch/gowin/gowin.h +++ b/himbaechel/uarch/gowin/gowin.h @@ -184,6 +184,7 @@ NPNR_PACKED_STRUCT(struct Extra_package_data_POD { RelSlice cst; NPNR_PACKED_STRUCT(struct Extra_chip_data_POD { int32_t chip_flags; + IdString dcs_prefix; Bottom_io_POD bottom_io; RelSlice diff_io_types; RelSlice dqce_bels; diff --git a/himbaechel/uarch/gowin/gowin_arch_gen.py b/himbaechel/uarch/gowin/gowin_arch_gen.py index c4fb0651..93ac46c1 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -266,7 +266,8 @@ class Segment(BBAStruct): class ChipExtraData(BBAStruct): strs: StringPool flags: int - bottom_io: BottomIO + dcs_prefix: IdString = field(default = None) + bottom_io: BottomIO = field(default = None) diff_io_types: list[IdString] = field(default_factory = list) dqce_bels: list[SpineBel] = field(default_factory = list) dcs_bels: list[SpineBel] = field(default_factory = list) @@ -274,6 +275,9 @@ class ChipExtraData(BBAStruct): io_dlldly_bels: list[IoBel] = field(default_factory = list) segments: list[Segment] = field(default_factory = list) + def set_dcs_prefix(self, prefix: str): + self.dcs_prefix = self.strs.id(prefix) + def create_bottom_io(self): self.bottom_io = BottomIO() @@ -334,6 +338,7 @@ class ChipExtraData(BBAStruct): def serialise(self, context: str, bba: BBAWriter): bba.u32(self.flags) + bba.u32(self.dcs_prefix.index) self.bottom_io.serialise(f"{context}_bottom_io", bba) bba.slice(f"{context}_diff_io_types", len(self.diff_io_types)) bba.slice(f"{context}_dqce_bels", len(self.dqce_bels)) @@ -662,6 +667,9 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int): for idx in range(2): if idx not in desc: continue + dcs_prefix = 'CLK' + if hasattr(db, "dcs_prefix"): + dcs_prefix = db.dcs_prefix bel_z = DCS_Z + idx bel = tt.create_bel(f"DCS{idx}", "DCS", bel_z) wire = desc[idx]['clkout'] @@ -672,7 +680,7 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int): for clk_idx, wire in enumerate(desc[idx]['clk']): if not tt.has_wire(wire): tt.create_wire(wire, "GLOBAL_CLK") - tt.add_bel_pin(bel, f"CLK{clk_idx}", wire, PinType.INPUT) + tt.add_bel_pin(bel, f"{dcs_prefix}{clk_idx}", wire, PinType.INPUT) # This is a fake PIP that allows routing “through” this # primitive from the CLK input to the CLKOUT output. tt.create_pip(wire, clkout_wire) @@ -1413,7 +1421,11 @@ def create_packages(chip: Chip, db: chipdb): # Extra chip data def create_extra_data(chip: Chip, db: chipdb, chip_flags: int): - chip.extra_data = ChipExtraData(chip.strs, chip_flags, None) + chip.extra_data = ChipExtraData(chip.strs, chip_flags) + if hasattr(db, "dcs_prefix"): + chip.extra_data.set_dcs_prefix(db.dcs_prefix) + else: + chip.extra_data.set_dcs_prefix("CLK") chip.extra_data.create_bottom_io() for net_a, net_b in db.bottom_io[2]: chip.extra_data.add_bottom_io_cnd(net_a, net_b) diff --git a/himbaechel/uarch/gowin/gowin_utils.cc b/himbaechel/uarch/gowin/gowin_utils.cc index b2b41569..475b9902 100644 --- a/himbaechel/uarch/gowin/gowin_utils.cc +++ b/himbaechel/uarch/gowin/gowin_utils.cc @@ -290,6 +290,12 @@ BelId GowinUtils::get_dhcen_bel(WireId hclkin_wire, IdString &side) return BelId(); } +IdString GowinUtils::get_dcs_prefix(void) +{ + const Extra_chip_data_POD *extra = reinterpret_cast(ctx->chip_info->extra_data.get()); + return extra->dcs_prefix; +} + bool GowinUtils::is_simple_io_bel(BelId bel) { return chip_bel_info(ctx->chip_info, bel).flags & BelFlags::FLAG_SIMPLE_IO; diff --git a/himbaechel/uarch/gowin/gowin_utils.h b/himbaechel/uarch/gowin/gowin_utils.h index c3a598ea..425162d4 100644 --- a/himbaechel/uarch/gowin/gowin_utils.h +++ b/himbaechel/uarch/gowin/gowin_utils.h @@ -49,6 +49,7 @@ struct GowinUtils BelId get_dcs_bel(IdString spine_name); BelId get_dhcen_bel(WireId hclkin_wire, IdString &side); BelId get_dlldly_bel(BelId io_bel); + IdString get_dcs_prefix(void); // Segments int get_segments_count(void) const; diff --git a/himbaechel/uarch/gowin/pack.cc b/himbaechel/uarch/gowin/pack.cc index 0a8d7155..6530615d 100644 --- a/himbaechel/uarch/gowin/pack.cc +++ b/himbaechel/uarch/gowin/pack.cc @@ -4141,12 +4141,7 @@ struct GowinPacker if (dcs_bel != BelId()) { IdString dcs_name = ctx->idf("$PACKER_DCS_SPINE%d", 8 * (i % 4) + 6 + (i >> 2)); CellInfo *dcs = ctx->createCell(dcs_name, id_DCS); - dcs->addInput(id_SELFORCE); - for (int j = 0; j < 4; ++j) { - dcs->addInput(ctx->idf("CLK%d", j)); - dcs->addInput(ctx->idf("CLKSEL%d", j)); - } - dcs->addOutput(id_CLKOUT); + ctx->copyBelPorts(dcs_name, dcs_bel); ctx->bindBel(dcs_bel, dcs, STRENGTH_LOCKED); } }