diff --git a/himbaechel/uarch/gowin/constids.inc b/himbaechel/uarch/gowin/constids.inc index 5d9a1ed3..e646f91b 100644 --- a/himbaechel/uarch/gowin/constids.inc +++ b/himbaechel/uarch/gowin/constids.inc @@ -1076,3 +1076,11 @@ X(MUX_SEL) X(ALU_CIN) X(ALU_COUT) +// fake dff inputs +X(XD0) +X(XD1) +X(XD2) +X(XD3) +X(XD4) +X(XD5) + diff --git a/himbaechel/uarch/gowin/gowin.cc b/himbaechel/uarch/gowin/gowin.cc index 416ccae2..5fe2a004 100644 --- a/himbaechel/uarch/gowin/gowin.cc +++ b/himbaechel/uarch/gowin/gowin.cc @@ -90,6 +90,7 @@ void GowinImpl::init(Context *ctx) partno = ctx->id(pn); ctx->settings[ctx->id("packer.partno")] = pn; + // package and speed class std::regex speedre = std::regex("(.*)(C[0-9]/I[0-9])$"); std::smatch match; @@ -106,7 +107,7 @@ void GowinImpl::init(Context *ctx) } if (ctx->debug) { - log_info("packages:%d\n", ctx->chip_info->packages.ssize()); + log_info("packages:%ld\n", ctx->chip_info->packages.ssize()); } for (int i = 0; i < ctx->chip_info->packages.ssize(); ++i) { if (IdString(ctx->chip_info->packages[i].name) == package_idx) { @@ -121,6 +122,7 @@ void GowinImpl::init(Context *ctx) log_error("No package for partnumber %s\n", partno.c_str(ctx)); } + // constraints if (args.options.count("cst")) { ctx->settings[ctx->id("cst.filename")] = args.options.at("cst"); } diff --git a/himbaechel/uarch/gowin/gowin_arch_gen.py b/himbaechel/uarch/gowin/gowin_arch_gen.py index 3fe8137c..8a935887 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -22,6 +22,7 @@ MUX27_Z = 29 ALU0_Z = 30 # : 35, 6 ALUs RAMW_Z = 36 # RAM16SDP4 +GSR_Z = 276 VCC_Z = 277 GND_Z = 278 @@ -140,6 +141,8 @@ def create_switch_matrix(tt: TileType, db: chipdb, x: int, y: int): def get_wire_type(name): if name.startswith('GB') or name.startswith('GT'): return "GLOBAL_CLK" + elif name in {'XD0', 'XD1', 'XD2', 'XD3', 'XD4', 'XD5',}: + return "X0" return "" for dst, srcs in db.grid[y][x].pips.items(): @@ -188,6 +191,22 @@ def create_corner_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int): create_switch_matrix(tt, db, x, y) return (ttyp, tt) +# Global set/reset. GW2A series has special cell for it +def create_gsr_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int): + if ttyp in created_tiletypes: + return ttyp, None + typename = "GSR" + tt = chip.create_tile_type(f"{typename}_{ttyp}") + tt.extra_data = TileExtraData(chip.strs.id(typename)) + + 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) + # simple IO - only A and B def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int): if ttyp in created_tiletypes: @@ -393,6 +412,7 @@ def main(): logic_tiletypes = {12, 13, 14, 15, 16} io_tiletypes = {52, 53, 55, 58, 59, 64, 65, 66} ssram_tiletypes = {17, 18, 19} + gsr_tiletypes = {1} # Setup tile grid for x in range(X): for y in range(Y): @@ -403,7 +423,11 @@ def main(): created_tiletypes.add(ttyp) ch.set_tile_type(x, y, f"CORNER_{ttyp}") continue - if ttyp in logic_tiletypes: + if ttyp in gsr_tiletypes: + ttyp, _ = create_gsr_tiletype(ch, db, x, y, ttyp) + created_tiletypes.add(ttyp) + ch.set_tile_type(x, y, f"GSR_{ttyp}") + elif ttyp in logic_tiletypes: ttyp, _ = create_logic_tiletype(ch, db, x, y, ttyp) created_tiletypes.add(ttyp) ch.set_tile_type(x, y, f"LOGIC_{ttyp}") diff --git a/himbaechel/uarch/gowin/pack.cc b/himbaechel/uarch/gowin/pack.cc index 06bc4290..07c84e29 100644 --- a/himbaechel/uarch/gowin/pack.cc +++ b/himbaechel/uarch/gowin/pack.cc @@ -249,10 +249,14 @@ struct GowinPacker if (cin_net->name == ctx->id("$PACKER_GND")) { cin_ci->params[id_ALU_MODE] = std::string("C2L"); + cin_ci->addInput(id_I2); + cin_ci->connectPort(id_I2, ctx->nets[ctx->id("$PACKER_VCC")].get()); return cin_ci; } if (cin_net->name == ctx->id("$PACKER_VCC")) { cin_ci->params[id_ALU_MODE] = std::string("ONE2C"); + cin_ci->addInput(id_I2); + cin_ci->connectPort(id_I2, ctx->nets[ctx->id("$PACKER_VCC")].get()); return cin_ci; } // CIN from logic @@ -501,10 +505,47 @@ struct GowinPacker } } + // Pack global set-reset + void pack_gsr(void) + { + log_info("Packing GSR..\n"); + + bool user_gsr = false; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + if (ctx->verbose) + log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx)); + if (ci->type == id_GSR) { + user_gsr = true; + break; + } + } + if (!user_gsr) { + bool have_gsr_bel = false; + auto bels = ctx->getBels(); + for (auto bid : bels) { + if (ctx->getBelType(bid) == id_GSR) { + have_gsr_bel = true; + break; + } + } + if (have_gsr_bel) { + // make default GSR + auto gsr_cell = std::make_unique(ctx, id_GSR, id_GSR); + gsr_cell->addInput(id_GSRI); + gsr_cell->connectPort(id_GSRI, ctx->nets[ctx->id("$PACKER_VCC")].get()); + ctx->cells[gsr_cell->name] = std::move(gsr_cell); + } else { + log_info("No GSR in the chip base\n"); + } + } + } + void run(void) { pack_iobs(); handle_constants(); + pack_gsr(); pack_wideluts(); pack_alus(); constrain_lutffs();