interchange: Handle disconnected/missing cell pins
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
872b3aa63d
commit
18459a9e4c
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user