aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-04-20 11:33:51 +0100
committerGitHub <noreply@github.com>2021-04-20 11:33:51 +0100
commit95698827b876c5afa368ed8746d155d68a8b6bbf (patch)
tree2af311119f6ff54222020691248d0509ccd9ad69
parent6fbefb8f1388dbb2bfe059624f7cb76ee9a81c5e (diff)
parent0e6955a08dabf744cb57e6c440ff3ab62fd2a507 (diff)
downloadnextpnr-95698827b876c5afa368ed8746d155d68a8b6bbf.tar.gz
nextpnr-95698827b876c5afa368ed8746d155d68a8b6bbf.tar.bz2
nextpnr-95698827b876c5afa368ed8746d155d68a8b6bbf.zip
Merge pull request #682 from YosysHQ/gatecat/default-cellpins
interchange: Handle missing/disconnected cell pins
-rw-r--r--.github/workflows/interchange_ci.yml2
m---------3rdparty/fpga-interchange-schema0
-rw-r--r--fpga_interchange/arch.cc53
-rw-r--r--fpga_interchange/arch.h3
-rw-r--r--fpga_interchange/chipdb.h25
-rw-r--r--fpga_interchange/fpga_interchange.cpp6
6 files changed, 81 insertions, 8 deletions
diff --git a/.github/workflows/interchange_ci.yml b/.github/workflows/interchange_ci.yml
index 31036465..e8f1c153 100644
--- a/.github/workflows/interchange_ci.yml
+++ b/.github/workflows/interchange_ci.yml
@@ -108,7 +108,7 @@ jobs:
env:
RAPIDWRIGHT_PATH: ${{ github.workspace }}/RapidWright
PYTHON_INTERCHANGE_PATH: ${{ github.workspace }}/python-fpga-interchange
- PYTHON_INTERCHANGE_TAG: v0.0.9
+ PYTHON_INTERCHANGE_TAG: v0.0.10
PRJOXIDE_REVISION: a85135648c3ef2f7b3fd53ae2187ef6460e34b16
DEVICE: ${{ matrix.device }}
run: |
diff --git a/3rdparty/fpga-interchange-schema b/3rdparty/fpga-interchange-schema
-Subproject 8ec5b1739d7b91b84df3e92ccc70c7a7ee64408
+Subproject 5208d794d318e9151b93120d7e5ba75d8aef45e
diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc
index c1446245..441c2e1f 100644
--- a/fpga_interchange/arch.cc
+++ b/fpga_interchange/arch.cc
@@ -727,6 +727,7 @@ bool Arch::pack()
decode_lut_cells();
merge_constant_nets();
pack_ports();
+ pack_default_conns();
return true;
}
@@ -1984,6 +1985,58 @@ DelayQuad Arch::getPipDelay(PipId pip) const
return DelayQuad(100 * (1 + pip_data.pseudo_cell_wires.size()));
}
+const DefaultCellConnsPOD *Arch::get_default_conns(IdString cell_type) const
+{
+ for (const auto &conn : chip_info->constants->default_conns) {
+ if (IdString(conn.cell_type) == cell_type)
+ return &conn;
+ }
+ return nullptr;
+}
+
+void Arch::pack_default_conns()
+{
+ IdString vcc_net_name(chip_info->constants->vcc_net_name);
+ IdString gnd_net_name(chip_info->constants->gnd_net_name);
+ Context *ctx = getCtx();
+
+ std::vector<IdString> dead_nets;
+
+ for (auto cell : sorted(ctx->cells)) {
+ CellInfo *ci = cell.second;
+ const DefaultCellConnsPOD *conns = get_default_conns(ci->type);
+ if (conns == nullptr)
+ continue;
+ for (const auto &pin : conns->pins) {
+ IdString pin_name(pin.pin_name);
+ // pin missing, create it
+ if (!ci->ports.count(pin_name))
+ ci->addInput(pin_name);
+ const NetInfo *net = ci->ports.at(pin_name).net;
+ if (net != nullptr) {
+ // pin is connected, and driven, nothing to do
+ if (net->driver.cell != nullptr)
+ continue;
+ // pin is connected but undriven, disconnect the existing net
+ ctx->disconnectPort(ci->name, pin_name);
+ // remove net if it has no remaining users
+ if (net->users.empty())
+ dead_nets.push_back(net->name);
+ }
+ if (pin.value == PIN_VALUE_GND)
+ ctx->connectPort(gnd_net_name, ci->name, pin_name);
+ else if (pin.value == PIN_VALUE_VCC)
+ ctx->connectPort(vcc_net_name, ci->name, pin_name);
+ else
+ NPNR_ASSERT(pin.value == PIN_VALUE_FLOAT);
+ }
+ }
+
+ // Remove any left-behind nets with no users and no drivers
+ for (auto net : dead_nets)
+ ctx->nets.erase(net);
+}
+
// Instance constraint templates.
template void Arch::ArchConstraints::bindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange);
template void Arch::ArchConstraints::unbindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange);
diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h
index 9b369c92..da620699 100644
--- a/fpga_interchange/arch.h
+++ b/fpga_interchange/arch.h
@@ -1100,6 +1100,9 @@ struct Arch : ArchAPI<ArchRanges>
void unmask_bel_pins();
void explain_bel_status(BelId bel) const;
+
+ const DefaultCellConnsPOD *get_default_conns(IdString cell_type) const;
+ void pack_default_conns();
};
NEXTPNR_NAMESPACE_END
diff --git a/fpga_interchange/chipdb.h b/fpga_interchange/chipdb.h
index 6c7b8c83..b66640e3 100644
--- a/fpga_interchange/chipdb.h
+++ b/fpga_interchange/chipdb.h
@@ -34,7 +34,7 @@ NEXTPNR_NAMESPACE_BEGIN
* kExpectedChipInfoVersion
*/
-static constexpr int32_t kExpectedChipInfoVersion = 6;
+static constexpr int32_t kExpectedChipInfoVersion = 7;
// Flattened site indexing.
//
@@ -255,6 +255,26 @@ NPNR_PACKED_STRUCT(struct PackagePOD {
RelSlice<PackagePinPOD> pins;
});
+enum CellPinValue
+{
+ // leave floating
+ PIN_VALUE_FLOAT = 0,
+ // connect to ground
+ PIN_VALUE_GND = 1,
+ // connect to vcc
+ PIN_VALUE_VCC = 2,
+};
+
+NPNR_PACKED_STRUCT(struct DefaultCellConnPOD {
+ int32_t pin_name; // constid
+ int32_t value; // CellPinValue
+});
+
+NPNR_PACKED_STRUCT(struct DefaultCellConnsPOD {
+ int32_t cell_type; // constid
+ RelSlice<DefaultCellConnPOD> pins;
+});
+
NPNR_PACKED_STRUCT(struct ConstantsPOD {
// Cell type and port for the GND and VCC global source.
int32_t gnd_cell_name; // constid
@@ -280,6 +300,9 @@ NPNR_PACKED_STRUCT(struct ConstantsPOD {
// If a choice is available, which constant net should be used?
// Can be ''/0 if either constant net are equivilent.
int32_t best_constant_net; // constid
+
+ // Default cell pin connections
+ RelSlice<DefaultCellConnsPOD> default_conns;
});
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
diff --git a/fpga_interchange/fpga_interchange.cpp b/fpga_interchange/fpga_interchange.cpp
index 52d49fa2..60331382 100644
--- a/fpga_interchange/fpga_interchange.cpp
+++ b/fpga_interchange/fpga_interchange.cpp
@@ -1065,12 +1065,6 @@ ModuleReader::ModuleReader(const LogicalNetlistImpl *root,
if(iter == net_indicies.end()) {
PortKey port_key = port_connections.first;
auto port = ports[port_key.port_idx];
- if(port_key.inst_idx != -1 && port.getDir() != LogicalNetlist::Netlist::Direction::OUTPUT) {
- log_error("Cell instance %s port %s is disconnected!\n",
- root->strings.at(root->root.getInstList()[port_key.inst_idx].getName()).c_str(),
- root->strings.at(ports[port_key.port_idx].getName()).c_str()
- );
- }
disconnected_nets[net_idx] = stringf("%s.%d", root->strings.at(port.getName()).c_str(), i);
}
}