From 57f70aeeb811e96753b4b9e075a45eba5a974fd1 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Sat, 4 Oct 2025 23:02:53 +1000 Subject: [PATCH] Gowin. Remove the special status of corner tiles. (#1565) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Over time, it became clear that the special status of corner tiles is handled in other parts of the toolchain, and in the GW5A chip series, it began to interfere—in this series, IO can be located in the corners. So we move the only function (creating VCC and GND) to the extra function itself, and at the same time create a mechanism for explicitly specifying the location of these sources in Apicula when necessary. Signed-off-by: YRabbit --- himbaechel/uarch/gowin/gowin.h | 2 +- himbaechel/uarch/gowin/gowin_arch_gen.py | 53 +++++++++++------------- himbaechel/uarch/gowin/gowin_utils.cc | 2 +- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/himbaechel/uarch/gowin/gowin.h b/himbaechel/uarch/gowin/gowin.h index 0300bbc7..52094314 100644 --- a/himbaechel/uarch/gowin/gowin.h +++ b/himbaechel/uarch/gowin/gowin.h @@ -184,7 +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; + int32_t 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 93ac46c1..c27de274 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -786,6 +786,17 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int): for pin, wire in desc['inputs'].items(): tt.create_wire(wire, "PLL_I") tt.add_bel_pin(pll, pin, wire, PinType.INPUT) + elif func == 'gnd_source': + # GND is the logic low level generator + tt.create_wire('VSS', 'GND', const_value = 'VSS') + gnd = tt.create_bel('GND', 'GND', z = GND_Z) + tt.add_bel_pin(gnd, "G", "VSS", PinType.OUTPUT) + elif func == 'vcc_source': + # VCC is the logic high level generator + tt.create_wire('VCC', 'VCC', const_value = 'VCC') + gnd = tt.create_bel('VCC', 'VCC', z = VCC_Z) + tt.add_bel_pin(gnd, "V", "VCC", PinType.OUTPUT) + def set_wire_flags(tt: TileType, tdesc: TypeDesc): if tdesc.extra_func and 'clock_gates' in tdesc.extra_func: @@ -869,29 +880,6 @@ def create_null_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdes tdesc.tiletype = tiletype return tt -# responsible nodes, there will be IO banks, configuration, etc. -def create_corner_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: TypeDesc): - typename = "CORNER" - tiletype = f"{typename}_{ttyp}" - if tdesc.sfx != 0: - tiletype += f"_{tdesc.sfx}" - tt = chip.create_tile_type(tiletype) - tt.extra_data = TileExtraData(chip.strs.id(typename)) - - if x == 0 and y == 0: - # GND is the logic low level generator - tt.create_wire('VSS', 'GND', const_value = 'VSS') - gnd = tt.create_bel('GND', 'GND', z = GND_Z) - tt.add_bel_pin(gnd, "G", "VSS", PinType.OUTPUT) - # VCC is the logic high level generator - tt.create_wire('VCC', 'VCC', const_value = 'VCC') - gnd = tt.create_bel('VCC', 'VCC', z = VCC_Z) - tt.add_bel_pin(gnd, "V", "VCC", PinType.OUTPUT) - - tdesc.tiletype = tiletype - return tt - - # IO def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: TypeDesc): typename = "IO" @@ -1580,6 +1568,15 @@ def create_timing_info(chip: Chip, db: chipdb.Device): for name, mapping in [("LUT_OUT", "FFan"), ("FF_OUT", "QFan"), ("OF", "OFFan")]: tmg.set_pip_class(speed, name, TimingValue(), group_to_timingvalue(groups["fanout"][mapping]), TimingValue(round(1e6 / groups["fanout"][f"{mapping}Num"]))) +# If Apicula does not specify a special location for the global GND and VCC +# sources, place them at X0Y0. +def check_place_VCC_GND(db: chipdb.Device): + for funcs in db.extra_func.values(): + if 'gnd_source' in funcs or 'vcc_source' in funcs: + return + db.extra_func.setdefault((0, 0), {}).update({'gnd_source':{}, 'vcc_source': {}}) + +# ******************************* def main(): parser = argparse.ArgumentParser(description='Make Gowin BBA') parser.add_argument('-d', '--device', required=True) @@ -1639,15 +1636,15 @@ def main(): bsram_tiletypes = db.tile_types.get('B', set()) dsp_tiletypes = db.tile_types.get('D', set()) + # If Apicula does not specify a special location for the global GND and VCC + # sources, place them at X0Y0. + check_place_VCC_GND(db) + # Setup tile grid for x in range(X): for y in range(Y): ttyp = db.grid[y][x].ttyp - if (x == 0 or x == X - 1) and (y == 0 or y == Y - 1): - assert ttyp not in created_tiletypes, "Duplication of corner types" - create_tiletype(create_corner_tiletype, ch, db, x, y, ttyp) - continue - elif ttyp in logic_tiletypes: + if ttyp in logic_tiletypes: create_tiletype(create_logic_tiletype, ch, db, x, y, ttyp) elif ttyp in ssram_tiletypes: create_tiletype(create_ssram_tiletype, ch, db, x, y, ttyp) diff --git a/himbaechel/uarch/gowin/gowin_utils.cc b/himbaechel/uarch/gowin/gowin_utils.cc index 475b9902..9bf06c6b 100644 --- a/himbaechel/uarch/gowin/gowin_utils.cc +++ b/himbaechel/uarch/gowin/gowin_utils.cc @@ -293,7 +293,7 @@ BelId GowinUtils::get_dhcen_bel(WireId hclkin_wire, IdString &side) IdString GowinUtils::get_dcs_prefix(void) { const Extra_chip_data_POD *extra = reinterpret_cast(ctx->chip_info->extra_data.get()); - return extra->dcs_prefix; + return IdString(extra->dcs_prefix); } bool GowinUtils::is_simple_io_bel(BelId bel)