1
0
mirror of https://github.com/YosysHQ/nextpnr.git synced 2026-01-11 23:53:21 +00:00

Gowin. Remove the special status of corner tiles. (#1565)

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 <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2025-10-04 23:02:53 +10:00 committed by GitHub
parent ad76625d4d
commit 57f70aeeb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 30 deletions

View File

@ -184,7 +184,7 @@ NPNR_PACKED_STRUCT(struct Extra_package_data_POD { RelSlice<Constraint_POD> cst;
NPNR_PACKED_STRUCT(struct Extra_chip_data_POD { NPNR_PACKED_STRUCT(struct Extra_chip_data_POD {
int32_t chip_flags; int32_t chip_flags;
IdString dcs_prefix; int32_t dcs_prefix;
Bottom_io_POD bottom_io; Bottom_io_POD bottom_io;
RelSlice<IdString> diff_io_types; RelSlice<IdString> diff_io_types;
RelSlice<Spine_bel_POD> dqce_bels; RelSlice<Spine_bel_POD> dqce_bels;

View File

@ -786,6 +786,17 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int):
for pin, wire in desc['inputs'].items(): for pin, wire in desc['inputs'].items():
tt.create_wire(wire, "PLL_I") tt.create_wire(wire, "PLL_I")
tt.add_bel_pin(pll, pin, wire, PinType.INPUT) 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): def set_wire_flags(tt: TileType, tdesc: TypeDesc):
if tdesc.extra_func and 'clock_gates' in tdesc.extra_func: 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 tdesc.tiletype = tiletype
return tt 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 # IO
def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: TypeDesc): def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: TypeDesc):
typename = "IO" 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")]: 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"]))) 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(): def main():
parser = argparse.ArgumentParser(description='Make Gowin BBA') parser = argparse.ArgumentParser(description='Make Gowin BBA')
parser.add_argument('-d', '--device', required=True) parser.add_argument('-d', '--device', required=True)
@ -1639,15 +1636,15 @@ def main():
bsram_tiletypes = db.tile_types.get('B', set()) bsram_tiletypes = db.tile_types.get('B', set())
dsp_tiletypes = db.tile_types.get('D', 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 # Setup tile grid
for x in range(X): for x in range(X):
for y in range(Y): for y in range(Y):
ttyp = db.grid[y][x].ttyp ttyp = db.grid[y][x].ttyp
if (x == 0 or x == X - 1) and (y == 0 or y == Y - 1): if ttyp in logic_tiletypes:
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:
create_tiletype(create_logic_tiletype, ch, db, x, y, ttyp) create_tiletype(create_logic_tiletype, ch, db, x, y, ttyp)
elif ttyp in ssram_tiletypes: elif ttyp in ssram_tiletypes:
create_tiletype(create_ssram_tiletype, ch, db, x, y, ttyp) create_tiletype(create_ssram_tiletype, ch, db, x, y, ttyp)

View File

@ -293,7 +293,7 @@ BelId GowinUtils::get_dhcen_bel(WireId hclkin_wire, IdString &side)
IdString GowinUtils::get_dcs_prefix(void) IdString GowinUtils::get_dcs_prefix(void)
{ {
const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get()); const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get());
return extra->dcs_prefix; return IdString(extra->dcs_prefix);
} }
bool GowinUtils::is_simple_io_bel(BelId bel) bool GowinUtils::is_simple_io_bel(BelId bel)