aboutsummaryrefslogtreecommitdiffstats
path: root/gowin
diff options
context:
space:
mode:
authorYRabbit <rabbit@yrabbit.cyou>2022-04-03 10:05:27 +1000
committerYRabbit <rabbit@yrabbit.cyou>2022-04-03 10:05:27 +1000
commit85e8570a73dce11d3cfd2ce82a3b6c47214758af (patch)
tree60731058a0e1bdc1b1897696f24210d2512ad705 /gowin
parent2ed68a21db9d04e5688c4c0784b0817f3485926e (diff)
downloadnextpnr-85e8570a73dce11d3cfd2ce82a3b6c47214758af.tar.gz
nextpnr-85e8570a73dce11d3cfd2ce82a3b6c47214758af.tar.bz2
nextpnr-85e8570a73dce11d3cfd2ce82a3b6c47214758af.zip
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 <rabbit@yrabbit.cyou>
Diffstat (limited to 'gowin')
-rw-r--r--gowin/arch.cc19
-rw-r--r--gowin/arch.h2
-rw-r--r--gowin/constids.inc2
-rw-r--r--gowin/pack.cc19
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<ArchRanges>
// 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<const IdString, IdString> 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) {