Merge pull request #682 from YosysHQ/gatecat/default-cellpins
interchange: Handle missing/disconnected cell pins
This commit is contained in:
commit
95698827b8
2
.github/workflows/interchange_ci.yml
vendored
2
.github/workflows/interchange_ci.yml
vendored
@ -108,7 +108,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
RAPIDWRIGHT_PATH: ${{ github.workspace }}/RapidWright
|
RAPIDWRIGHT_PATH: ${{ github.workspace }}/RapidWright
|
||||||
PYTHON_INTERCHANGE_PATH: ${{ github.workspace }}/python-fpga-interchange
|
PYTHON_INTERCHANGE_PATH: ${{ github.workspace }}/python-fpga-interchange
|
||||||
PYTHON_INTERCHANGE_TAG: v0.0.9
|
PYTHON_INTERCHANGE_TAG: v0.0.10
|
||||||
PRJOXIDE_REVISION: a85135648c3ef2f7b3fd53ae2187ef6460e34b16
|
PRJOXIDE_REVISION: a85135648c3ef2f7b3fd53ae2187ef6460e34b16
|
||||||
DEVICE: ${{ matrix.device }}
|
DEVICE: ${{ matrix.device }}
|
||||||
run: |
|
run: |
|
||||||
|
2
3rdparty/fpga-interchange-schema
vendored
2
3rdparty/fpga-interchange-schema
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 8ec5b1739d7b91b84df3e92ccc70c7a7ee644089
|
Subproject commit 5208d794d318e9151b93120d7e5ba75d8aef45e7
|
@ -727,6 +727,7 @@ bool Arch::pack()
|
|||||||
decode_lut_cells();
|
decode_lut_cells();
|
||||||
merge_constant_nets();
|
merge_constant_nets();
|
||||||
pack_ports();
|
pack_ports();
|
||||||
|
pack_default_conns();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1984,6 +1985,58 @@ DelayQuad Arch::getPipDelay(PipId pip) const
|
|||||||
return DelayQuad(100 * (1 + pip_data.pseudo_cell_wires.size()));
|
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.
|
// Instance constraint templates.
|
||||||
template void Arch::ArchConstraints::bindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange);
|
template void Arch::ArchConstraints::bindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange);
|
||||||
template void Arch::ArchConstraints::unbindBel(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 unmask_bel_pins();
|
||||||
|
|
||||||
void explain_bel_status(BelId bel) const;
|
void explain_bel_status(BelId bel) const;
|
||||||
|
|
||||||
|
const DefaultCellConnsPOD *get_default_conns(IdString cell_type) const;
|
||||||
|
void pack_default_conns();
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -34,7 +34,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
* kExpectedChipInfoVersion
|
* kExpectedChipInfoVersion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static constexpr int32_t kExpectedChipInfoVersion = 6;
|
static constexpr int32_t kExpectedChipInfoVersion = 7;
|
||||||
|
|
||||||
// Flattened site indexing.
|
// Flattened site indexing.
|
||||||
//
|
//
|
||||||
@ -255,6 +255,26 @@ NPNR_PACKED_STRUCT(struct PackagePOD {
|
|||||||
RelSlice<PackagePinPOD> pins;
|
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 {
|
NPNR_PACKED_STRUCT(struct ConstantsPOD {
|
||||||
// Cell type and port for the GND and VCC global source.
|
// Cell type and port for the GND and VCC global source.
|
||||||
int32_t gnd_cell_name; // constid
|
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?
|
// If a choice is available, which constant net should be used?
|
||||||
// Can be ''/0 if either constant net are equivilent.
|
// Can be ''/0 if either constant net are equivilent.
|
||||||
int32_t best_constant_net; // constid
|
int32_t best_constant_net; // constid
|
||||||
|
|
||||||
|
// Default cell pin connections
|
||||||
|
RelSlice<DefaultCellConnsPOD> default_conns;
|
||||||
});
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||||
|
@ -1065,12 +1065,6 @@ ModuleReader::ModuleReader(const LogicalNetlistImpl *root,
|
|||||||
if(iter == net_indicies.end()) {
|
if(iter == net_indicies.end()) {
|
||||||
PortKey port_key = port_connections.first;
|
PortKey port_key = port_connections.first;
|
||||||
auto port = ports[port_key.port_idx];
|
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);
|
disconnected_nets[net_idx] = stringf("%s.%d", root->strings.at(port.getName()).c_str(), i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user