diff --git a/himbaechel/uarch/gowin/globals.cc b/himbaechel/uarch/gowin/globals.cc index 01ebaf8c..ecb99e43 100644 --- a/himbaechel/uarch/gowin/globals.cc +++ b/himbaechel/uarch/gowin/globals.cc @@ -52,7 +52,7 @@ struct GowinGlobalRouter bool src_valid = src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O); bool dst_valid = dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_IO_I); - if (ctx->debug) { + if (ctx->debug && false) { log_info("%s <- %s [%s <- %s]\n", ctx->getWireName(ctx->getPipDstWire(pip)).str(ctx).c_str(), ctx->getWireName(ctx->getPipSrcWire(pip)).str(ctx).c_str(), dst_type.c_str(ctx), src_type.c_str(ctx)); diff --git a/himbaechel/uarch/gowin/gowin.h b/himbaechel/uarch/gowin/gowin.h index 2a931480..8f21c23a 100644 --- a/himbaechel/uarch/gowin/gowin.h +++ b/himbaechel/uarch/gowin/gowin.h @@ -5,6 +5,10 @@ NEXTPNR_NAMESPACE_BEGIN +namespace BelFlags { +static constexpr uint32_t FLAG_SIMPLE_IO = 0x100; +} + namespace { // Return true if a cell is a LUT inline bool type_is_lut(IdString cell_type) { return cell_type.in(id_LUT1, id_LUT2, id_LUT3, id_LUT4); } @@ -39,6 +43,12 @@ NPNR_PACKED_STRUCT(struct Bottom_io_POD { NPNR_PACKED_STRUCT(struct Extra_chip_data_POD { Bottom_io_POD bottom_io; }); +inline bool have_bottom_io_cnds(const ChipInfoPOD *chip) +{ + const Extra_chip_data_POD *extra = reinterpret_cast(chip->extra_data.get()); + return extra->bottom_io.conditions.size() != 0; +} + inline IdString get_bottom_io_wire_a_net(const ChipInfoPOD *chip, int8_t condition) { const Extra_chip_data_POD *extra = reinterpret_cast(chip->extra_data.get()); @@ -51,6 +61,10 @@ inline IdString get_bottom_io_wire_b_net(const ChipInfoPOD *chip, int8_t conditi return IdString(extra->bottom_io.conditions[condition].wire_b_net); } +inline bool getBelSimpleIO(const ChipInfoPOD *chip, BelId bel) +{ + return chip_bel_info(chip, bel).flags & BelFlags::FLAG_SIMPLE_IO; +} } // namespace // Bels Z ranges. It is desirable that these numbers be synchronized with the chipdb generator diff --git a/himbaechel/uarch/gowin/gowin_arch_gen.py b/himbaechel/uarch/gowin/gowin_arch_gen.py index 1fee760b..d2482ad7 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -11,6 +11,9 @@ sys.path.append(path.join(path.dirname(__file__), "../..")) from himbaechel_dbgen.chip import * from apycula import chipdb +# Bel flags +BEL_FLAG_SIMPLE_IO = 0x100 + # Z of the bels # sync with C++ part! LUT0_Z = 0 # z(DFFx) = z(LUTx) + 1 @@ -171,7 +174,10 @@ def create_nodes(chip: Chip, db: chipdb): wire_type, node = node_hdr for y, x, wire in node: if wire_type: - chip.tile_type_at(x, y).set_wire_type(wire, wire_type) + if not chip.tile_type_at(x, y).has_wire(wire): + chip.tile_type_at(x, y).create_wire(wire, wire_type) + else: + chip.tile_type_at(x, y).set_wire_type(wire, wire_type) new_node = NodeWire(x, y, wire) gl_nodes = global_nodes.setdefault(node_name, []) if new_node not in gl_nodes: @@ -200,7 +206,7 @@ def create_switch_matrix(tt: TileType, db: chipdb, x: int, y: int): tt.create_wire(src, get_wire_type(src)) tt.create_pip(src, dst) # clock wires - for dst, srcs in db.grid[y][x].clock_pips.items(): + for dst, srcs in db.grid[y][x].pure_clock_pips.items(): if not tt.has_wire(dst): tt.create_wire(dst, "GLOBAL_CLK") for src in srcs.keys(): @@ -234,6 +240,12 @@ def create_corner_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int): tt.create_wire('VCC', 'VCC') gnd = tt.create_bel('VCC', 'VCC', z = VCC_Z) tt.add_bel_pin(gnd, "V", "VCC", PinType.OUTPUT) + # also here may be GSR + if 'GSR' in db.grid[y][x].bels.keys(): + portmap = db.grid[y][x].bels['GSR'].portmap + tt.create_wire(portmap['GSRI'], "GSRI") + io = tt.create_bel("GSR", "GSR", z = GSR_Z) + tt.add_bel_pin(io, "GSRI", portmap['GSRI'], PinType.INPUT) create_switch_matrix(tt, db, x, y) return (ttyp, tt) @@ -262,15 +274,27 @@ def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int): tt = chip.create_tile_type(f"{typename}_{ttyp}") tt.extra_data = TileExtraData(chip.strs.id(typename)) - for i in range(2): - name = ['IOBA', 'IOBB'][i] + simple_io = y in db.simplio_rows and chip.name in {'GW1N-1', 'GW1NZ-1'} + if simple_io: + rng = 10 + else: + rng = 2 + for i in range(rng): + name = 'IOB' + 'ABCDEFGHIJ'[i] + # XXX some IOBs excluded from generic chipdb for some reason + if name not in db.grid[y][x].bels.keys(): + continue # wires portmap = db.grid[y][x].bels[name].portmap tt.create_wire(portmap['I'], "IO_I") tt.create_wire(portmap['O'], "IO_O") + tt.create_wire(portmap['OE'], "IO_OE") # bels io = tt.create_bel(name, "IOB", z = IOBA_Z + i) + if simple_io: + io.flags |= BEL_FLAG_SIMPLE_IO tt.add_bel_pin(io, "I", portmap['I'], PinType.INPUT) + tt.add_bel_pin(io, "OE", portmap['OE'], PinType.INPUT) tt.add_bel_pin(io, "O", portmap['O'], PinType.OUTPUT) # bottom io if 'BOTTOM_IO_PORT_A' in portmap.keys(): @@ -510,11 +534,11 @@ def main(): # The manufacturer distinguishes by externally identical tiles, so keep # these differences (in case it turns out later that there is a slightly # different routing or something like that). - logic_tiletypes = {12, 13, 14, 15, 16} - io_tiletypes = {52, 53, 54, 55, 58, 59, 64, 65, 66} + logic_tiletypes = db.tile_types['C'] + io_tiletypes = db.tile_types['I'] ssram_tiletypes = {17, 18, 19} gsr_tiletypes = {1} - pll_tiletypes = {86, 87, 42, 45} + pll_tiletypes = db.tile_types['P'] # Setup tile grid for x in range(X): for y in range(Y): diff --git a/himbaechel/uarch/gowin/pack.cc b/himbaechel/uarch/gowin/pack.cc index c91763f5..ec8816cf 100644 --- a/himbaechel/uarch/gowin/pack.cc +++ b/himbaechel/uarch/gowin/pack.cc @@ -21,8 +21,26 @@ struct GowinPacker // =================================== // IO // =================================== + void config_simple_io(CellInfo &ci) + { + if (ci.type.in(id_TBUF, id_IOBUF)) { + return; + } + log_info("simple:%s\n", ctx->nameOf(&ci)); + ci.addInput(id_OE); + if (ci.type == id_OBUF) { + ci.connectPort(id_OE, ctx->nets[ctx->id("$PACKER_GND")].get()); + } else { + NPNR_ASSERT(ci.type == id_IBUF); + ci.connectPort(id_OE, ctx->nets[ctx->id("$PACKER_VCC")].get()); + } + } + void config_bottom_row(CellInfo &ci, Loc loc, uint8_t cnd = Bottom_io_POD::NORMAL) { + if (!have_bottom_io_cnds(ctx->chip_info)) { + return; + } if (!ci.type.in(id_OBUF, id_TBUF, id_IOBUF)) { return; } @@ -93,6 +111,7 @@ struct GowinPacker BelId bind_io(CellInfo &ci) { BelId bel = ctx->getBelByName(IdStringList::parse(ctx, ci.attrs.at(id_BEL).as_string())); + NPNR_ASSERT(bel != BelId()); ci.unsetAttr(id_BEL); ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_LOCKED); return bel; @@ -115,6 +134,9 @@ struct GowinPacker if (io_loc.y == ctx->getGridDimY() - 1) { config_bottom_row(ci, io_loc); } + if (getBelSimpleIO(ctx->chip_info, io_bel)) { + config_simple_io(ci); + } } } @@ -138,10 +160,11 @@ struct GowinPacker NetInfo *constnet = net->second.get(); for (auto user : constnet->users) { CellInfo *uc = user.cell; - if (ctx->debug) - log_info("%s user %s/%s\n", ctx->nameOf(constnet), ctx->nameOf(uc), user.port.c_str(ctx)); - if (is_lut(uc) && (user.port.str(ctx).at(0) == 'I')) { + if (ctx->debug) { + log_info("%s user %s/%s\n", ctx->nameOf(constnet), ctx->nameOf(uc), user.port.c_str(ctx)); + } + auto it_param = uc->params.find(id_INIT); if (it_param == uc->params.end()) log_error("No initialization for lut found.\n"); @@ -318,9 +341,9 @@ struct GowinPacker // CIN from logic cin_ci->addInput(id_I1); cin_ci->addInput(id_I3); - cin_ci->addInput(id_I2); cin_ci->connectPort(id_I1, cin_net); cin_ci->connectPort(id_I3, cin_net); + cin_ci->addInput(id_I2); cin_ci->connectPort(id_I2, ctx->nets[ctx->id("$PACKER_VCC")].get()); cin_ci->params[id_ALU_MODE] = std::string("0"); // ADD return cin_ci; @@ -342,6 +365,8 @@ struct GowinPacker cout_ci->connectPort(id_CIN, cin_net); cout_ci->addOutput(id_SUM); cout_ci->connectPort(id_SUM, cout_net); + cout_ci->addInput(id_I2); + cout_ci->connectPort(id_I2, ctx->nets[ctx->id("$PACKER_VCC")].get()); cout_ci->params[id_ALU_MODE] = std::string("C2L"); return cout_ci; @@ -425,8 +450,8 @@ struct GowinPacker cout_block_ci->constr_y = 0; cout_block_ci->constr_z = alu_chain_len % 6; if (ctx->debug) { - log_info("Add ALU carry out to the chain (len:%d): %s\n", alu_chain_len, - ctx->nameOf(cout_block_ci)); + log_info("Add ALU carry out to the chain (len:%d): %s COUT-net: %s\n", alu_chain_len, + ctx->nameOf(cout_block_ci), ctx->nameOf(cout_net)); } ++alu_chain_len; @@ -566,7 +591,7 @@ struct GowinPacker // =================================== void pack_gsr(void) { - log_info("Packing GSR..\n"); + log_info("Pack GSR..\n"); bool user_gsr = false; for (auto &cell : ctx->cells) { @@ -603,7 +628,7 @@ struct GowinPacker // =================================== void pack_pll(void) { - log_info("Packing PLL..\n"); + log_info("Pack PLL..\n"); for (auto &cell : ctx->cells) { auto &ci = *cell.second;