From 85e8570a73dce11d3cfd2ce82a3b6c47214758af Mon Sep 17 00:00:00 2001 From: YRabbit Date: Sun, 3 Apr 2022 10:05:27 +1000 Subject: gowin: handle the GW1N-9 feature. This chip has a different default state for one type of I/O buffer --- you have to explicitly switch it to the normal state by feeding VCC/VSS to certain inputs. Signed-off-by: YRabbit --- gowin/arch.cc | 19 +++++++++++++++++-- gowin/arch.h | 2 ++ gowin/constids.inc | 2 ++ gowin/pack.cc | 19 +++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/gowin/arch.cc b/gowin/arch.cc index 89bdade3..7bfef36e 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -1119,7 +1119,7 @@ Arch::Arch(ArchArgs args) : args(args) z++; /* fall-through*/ case ID_IOBB: z++; /* fall-through*/ - case ID_IOBA: + case ID_IOBA: { snprintf(buf, 32, "R%dC%d_IOB%c", row + 1, col + 1, 'A' + z); belname = id(buf); addBel(belname, id_IOB, Loc(col, row, z), false); @@ -1132,7 +1132,22 @@ Arch::Arch(ArchArgs args) : args(args) portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_OE)->src_id); snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); addBelInput(belname, id_OEN, id(buf)); - break; + // GW1NR-9 quirk + const PairPOD *xxx_port = pairLookup(bel->ports.get(), bel->num_ports, ID_XXX_VSS0); + if (xxx_port != nullptr) { + gw1n9_quirk = true; + portname = IdString(xxx_port->src_id); + snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); + addBelInput(belname, id_XXX_VSS0, id(buf)); + } + xxx_port = pairLookup(bel->ports.get(), bel->num_ports, ID_XXX_VSS1); + if (xxx_port != nullptr) { + gw1n9_quirk = true; + portname = IdString(xxx_port->src_id); + snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); + addBelInput(belname, id_XXX_VSS1, id(buf)); + } + } break; // Simplified IO case ID_IOBJS: z++; /* fall-through*/ diff --git a/gowin/arch.h b/gowin/arch.h index c5804bc4..14181d79 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -472,6 +472,8 @@ struct Arch : BaseArch // XXX GW1N-9C DDR quirk bool ddr_has_extra_inputs = false; + // XXX GW1NR-9 iobuf quirk + bool gw1n9_quirk = false; // Permissible combinations of modes in a single slice std::map dff_comp_mode; diff --git a/gowin/constids.inc b/gowin/constids.inc index d2a6b171..3691c506 100644 --- a/gowin/constids.inc +++ b/gowin/constids.inc @@ -683,6 +683,8 @@ X(IOBJS) X(TX) X(XXX_VSS) X(XXX_VCC) +X(XXX_VSS0) +X(XXX_VSS1) X(OBUF_TYPE) X(SBUF) X(DBUF) diff --git a/gowin/pack.cc b/gowin/pack.cc index 28370a75..4adfec1a 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -805,6 +805,14 @@ static void pack_iologic(Context *ctx) ci->addInput(id_XXX_VCC); ci->connectPort(id_XXX_VCC, ctx->nets[ctx->id("$PACKER_VCC_NET")].get()); } + if (ctx->gw1n9_quirk && iob_bel != q0_dst->attrs.end()) { + bool have_XXX_VSS0 = + ctx->bels[ctx->getBelByNameStr(iob_bel->second.as_string())].pins.count(id_XXX_VSS0); + if (have_XXX_VSS0) { + q0_dst->disconnectPort(id_XXX_VSS0); + q0_dst->connectPort(id_XXX_VSS0, ctx->nets[ctx->id("$PACKER_VCC_NET")].get()); + } + } } break; default: break; @@ -933,6 +941,7 @@ static void pack_io(Context *ctx) // what type to create IdString new_cell_type = id_IOB; std::string constr_bel_name = std::string(""); + bool have_xxx_port = false; // check whether the given IO is limited to simplified IO cells auto constr_bel = ci->attrs.find(id_BEL); if (constr_bel != ci->attrs.end()) { @@ -946,6 +955,9 @@ static void pack_io(Context *ctx) BelId constr_bel = ctx->getBelByNameStr(constr_bel_name); if (constr_bel != BelId()) { new_cell_type = ctx->bels[constr_bel].type; + if (ctx->gw1n9_quirk) { + have_xxx_port = ctx->bels[constr_bel].pins.count(id_XXX_VSS0) != 0; + } } } @@ -954,6 +966,13 @@ static void pack_io(Context *ctx) gwio_to_iob(ctx, ci, ice_cell.get(), packed_cells); new_cells.push_back(std::move(ice_cell)); auto gwiob = new_cells.back().get(); + // XXX GW1NR-9 quirks + if (have_xxx_port && ci->type != id_IBUF) { + gwiob->addInput(id_XXX_VSS0); + gwiob->connectPort(id_XXX_VSS0, ctx->nets[ctx->id("$PACKER_GND_NET")].get()); + gwiob->addInput(id_XXX_VSS1); + gwiob->connectPort(id_XXX_VSS1, ctx->nets[ctx->id("$PACKER_GND_NET")].get()); + } packed_cells.insert(ci->name); if (iob != nullptr) { -- cgit v1.2.3