aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/opt/opt_lut_ins.cc10
-rw-r--r--passes/techmap/iopadmap.cc29
2 files changed, 30 insertions, 9 deletions
diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc
index 99043ef7e..2f7c392b2 100644
--- a/passes/opt/opt_lut_ins.cc
+++ b/passes/opt/opt_lut_ins.cc
@@ -193,6 +193,12 @@ struct OptLutInsPass : public Pass {
swz += extra;
}
}
+ if (techname == "gowin") {
+ // Pad the LUT to 1 input, adding consts from the front.
+ if (new_inputs.empty()) {
+ new_inputs.insert(new_inputs.begin(), State::S0);
+ }
+ }
Const new_lut(0, 1 << GetSize(new_inputs));
for (int i = 0; i < GetSize(new_lut); i++) {
int lidx = 0;
@@ -209,9 +215,9 @@ struct OptLutInsPass : public Pass {
}
new_lut[i] = lut[lidx];
}
- // For ecp5, do not replace with a const driver — the nextpnr
+ // For ecp5, and gowin do not replace with a const driver — the nextpnr
// packer requires a complete set of LUTs for wide LUT muxes.
- if (new_inputs.empty() && techname != "ecp5") {
+ if (new_inputs.empty() && techname != "ecp5" && techname != "gowin") {
// const driver.
remove_cells.push_back(cell);
module->connect(output, new_lut[0]);
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 45fa5f226..990e28876 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -43,26 +43,28 @@ struct IopadmapPass : public Pass {
log("can only map to very simple PAD cells. Use 'techmap' to further map\n");
log("the resulting cells to more sophisticated PAD cells.\n");
log("\n");
- log(" -inpad <celltype> <portname>[:<portname>]\n");
+ log(" -inpad <celltype> <in_port>[:<ext_port>]\n");
log(" Map module input ports to the given cell type with the\n");
log(" given output port name. if a 2nd portname is given, the\n");
log(" signal is passed through the pad call, using the 2nd\n");
log(" portname as the port facing the module port.\n");
log("\n");
- log(" -outpad <celltype> <portname>[:<portname>]\n");
- log(" -inoutpad <celltype> <portname>[:<portname>]\n");
+ log(" -outpad <celltype> <out_port>[:<ext_port>]\n");
+ log(" -inoutpad <celltype> <io_port>[:<ext_port>]\n");
log(" Similar to -inpad, but for output and inout ports.\n");
log("\n");
- log(" -toutpad <celltype> <portname>:<portname>[:<portname>]\n");
+ log(" -toutpad <celltype> <oe_port>:<out_port>[:<ext_port>]\n");
log(" Merges $_TBUF_ cells into the output pad cell. This takes precedence\n");
log(" over the other -outpad cell. The first portname is the enable input\n");
- log(" of the tristate driver.\n");
+ log(" of the tristate driver, which can be prefixed with `~` for negative\n");
+ log(" polarity enable.\n");
log("\n");
- log(" -tinoutpad <celltype> <portname>:<portname>:<portname>[:<portname>]\n");
+ log(" -tinoutpad <celltype> <oe_port>:<in_port>:<out_port>[:<ext_port>]\n");
log(" Merges $_TBUF_ cells into the inout pad cell. This takes precedence\n");
log(" over the other -inoutpad cell. The first portname is the enable input\n");
log(" of the tristate driver and the 2nd portname is the internal output\n");
- log(" buffering the external signal.\n");
+ log(" buffering the external signal. Like with `-toutpad`, the enable can\n");
+ log(" be marked as negative polarity by prefixing the name with `~`.\n");
log("\n");
log(" -ignore <celltype> <portname>[:<portname>]*\n");
log(" Skips mapping inputs/outputs that are already connected to given\n");
@@ -106,6 +108,7 @@ struct IopadmapPass : public Pass {
std::string inoutpad_celltype, inoutpad_portname_io, inoutpad_portname_pad;
std::string toutpad_celltype, toutpad_portname_oe, toutpad_portname_i, toutpad_portname_pad;
std::string tinoutpad_celltype, tinoutpad_portname_oe, tinoutpad_portname_o, tinoutpad_portname_i, tinoutpad_portname_pad;
+ bool toutpad_neg_oe = false, tinoutpad_neg_oe = false;
std::string widthparam, nameparam;
pool<pair<IdString, IdString>> ignore;
bool flag_bits = false;
@@ -137,6 +140,10 @@ struct IopadmapPass : public Pass {
toutpad_portname_oe = args[++argidx];
split_portname_pair(toutpad_portname_oe, toutpad_portname_i);
split_portname_pair(toutpad_portname_i, toutpad_portname_pad);
+ if (toutpad_portname_oe[0] == '~') {
+ toutpad_neg_oe = true;
+ toutpad_portname_oe = toutpad_portname_oe.substr(1);
+ }
continue;
}
if (arg == "-tinoutpad" && argidx+2 < args.size()) {
@@ -145,6 +152,10 @@ struct IopadmapPass : public Pass {
split_portname_pair(tinoutpad_portname_oe, tinoutpad_portname_o);
split_portname_pair(tinoutpad_portname_o, tinoutpad_portname_i);
split_portname_pair(tinoutpad_portname_i, tinoutpad_portname_pad);
+ if (tinoutpad_portname_oe[0] == '~') {
+ tinoutpad_neg_oe = true;
+ tinoutpad_portname_oe = tinoutpad_portname_oe.substr(1);
+ }
continue;
}
if (arg == "-ignore" && argidx+2 < args.size()) {
@@ -318,6 +329,8 @@ struct IopadmapPass : public Pass {
module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
RTLIL::escape_id(tinoutpad_celltype));
+ if (tinoutpad_neg_oe)
+ en_sig = module->NotGate(NEW_ID, en_sig);
cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig);
cell->attributes[ID::keep] = RTLIL::Const(1);
@@ -340,6 +353,8 @@ struct IopadmapPass : public Pass {
module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
RTLIL::escape_id(toutpad_celltype));
+ if (toutpad_neg_oe)
+ en_sig = module->NotGate(NEW_ID, en_sig);
cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig);
cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig);
cell->attributes[ID::keep] = RTLIL::Const(1);