Merge pull request #638 from litghost/fixup_physical_netlist_writer
Correct some bugs in writing of physical netlist w.r.t. site sources.
This commit is contained in:
commit
9ef412c2cc
@ -114,14 +114,12 @@ static PhysicalNetlist::PhysNetlist::RouteBranch::Builder emit_branch(
|
|||||||
WireId src_wire = ctx->getPipSrcWire(pip);
|
WireId src_wire = ctx->getPipSrcWire(pip);
|
||||||
WireId dst_wire = ctx->getPipDstWire(pip);
|
WireId dst_wire = ctx->getPipDstWire(pip);
|
||||||
|
|
||||||
IdString src_pin;
|
NPNR_ASSERT(src_wire.index == bel_data.wires[pip_data.extra_data]);
|
||||||
|
|
||||||
|
IdString src_pin(bel_data.ports[pip_data.extra_data]);
|
||||||
|
|
||||||
IdString dst_pin;
|
IdString dst_pin;
|
||||||
for(IdString pin : ctx->getBelPins(bel)) {
|
for(IdString pin : ctx->getBelPins(bel)) {
|
||||||
if(ctx->getBelPinWire(bel, pin) == src_wire) {
|
|
||||||
NPNR_ASSERT(src_pin == IdString());
|
|
||||||
src_pin = pin;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ctx->getBelPinWire(bel, pin) == dst_wire) {
|
if(ctx->getBelPinWire(bel, pin) == dst_wire) {
|
||||||
NPNR_ASSERT(dst_pin == IdString());
|
NPNR_ASSERT(dst_pin == IdString());
|
||||||
dst_pin = pin;
|
dst_pin = pin;
|
||||||
@ -274,6 +272,65 @@ static void emit_net(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given a site wire, find the source BEL pin.
|
||||||
|
//
|
||||||
|
// All site wires should have exactly 1 source BEL pin.
|
||||||
|
//
|
||||||
|
// FIXME: Consider making sure that wire_data.bel_pins[0] is always the
|
||||||
|
// source BEL pin in the BBA generator.
|
||||||
|
static BelPin find_source(const Context *ctx, WireId source_wire) {
|
||||||
|
const TileTypeInfoPOD & tile_type = loc_info(ctx->chip_info, source_wire);
|
||||||
|
const TileWireInfoPOD & wire_data = tile_type.wire_data[source_wire.index];
|
||||||
|
|
||||||
|
// Make sure this is a site wire, otherwise something odd is happening
|
||||||
|
// here.
|
||||||
|
if(wire_data.site == -1) {
|
||||||
|
return BelPin();
|
||||||
|
}
|
||||||
|
|
||||||
|
BelPin source_bel_pin;
|
||||||
|
for(const BelPin & bel_pin : ctx->getWireBelPins(source_wire)) {
|
||||||
|
if(ctx->getBelPinType(bel_pin.bel, bel_pin.pin) == PORT_OUT) {
|
||||||
|
// Synthetic BEL's (like connection to the VCC/GND network) are
|
||||||
|
// ignored here, because synthetic BEL's don't exists outside of
|
||||||
|
// the BBA.
|
||||||
|
if(ctx->is_bel_synthetic(bel_pin.bel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
NPNR_ASSERT(source_bel_pin.bel == BelId());
|
||||||
|
source_bel_pin = bel_pin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NPNR_ASSERT(source_bel_pin.bel != BelId());
|
||||||
|
NPNR_ASSERT(source_bel_pin.pin != IdString());
|
||||||
|
|
||||||
|
return source_bel_pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial a local signal source (usually VCC/GND).
|
||||||
|
static PhysicalNetlist::PhysNetlist::RouteBranch::Builder init_local_source(
|
||||||
|
const Context *ctx,
|
||||||
|
StringEnumerator * strings,
|
||||||
|
PhysicalNetlist::PhysNetlist::RouteBranch::Builder source_branch,
|
||||||
|
PipId root,
|
||||||
|
const std::unordered_map<PipId, PlaceStrength> &pip_place_strength,
|
||||||
|
WireId *root_wire) {
|
||||||
|
WireId source_wire = ctx->getPipSrcWire(root);
|
||||||
|
BelPin source_bel_pin = find_source(ctx, source_wire);
|
||||||
|
if(source_bel_pin.bel != BelId()) {
|
||||||
|
// This branch should first emit the BEL pin that is the source, followed
|
||||||
|
// by the pip that brings the source to the net.
|
||||||
|
init_bel_pin(ctx, strings, source_bel_pin, source_branch);
|
||||||
|
|
||||||
|
source_branch = source_branch.initBranches(1)[0];
|
||||||
|
}
|
||||||
|
*root_wire = ctx->getPipDstWire(root);
|
||||||
|
return emit_branch(ctx, strings, pip_place_strength, root, source_branch);
|
||||||
|
}
|
||||||
|
|
||||||
static void find_non_synthetic_edges(const Context * ctx, WireId root_wire,
|
static void find_non_synthetic_edges(const Context * ctx, WireId root_wire,
|
||||||
const std::unordered_map<WireId, std::vector<PipId>> &pip_downhill,
|
const std::unordered_map<WireId, std::vector<PipId>> &pip_downhill,
|
||||||
std::vector<PipId> *root_pips) {
|
std::vector<PipId> *root_pips) {
|
||||||
@ -330,6 +387,15 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str
|
|||||||
for(auto & cell_name : placed_cells) {
|
for(auto & cell_name : placed_cells) {
|
||||||
const CellInfo & cell = *ctx->cells.at(cell_name);
|
const CellInfo & cell = *ctx->cells.at(cell_name);
|
||||||
|
|
||||||
|
if(cell.bel == BelId()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ctx->isBelLocationValid(cell.bel)) {
|
||||||
|
log_error("Cell '%s' is placed at BEL '%s', but this location is currently invalid. Not writing physical netlist.\n",
|
||||||
|
cell.name.c_str(ctx), ctx->nameOfBel(cell.bel));
|
||||||
|
}
|
||||||
|
|
||||||
if(ctx->is_bel_synthetic(cell.bel)) {
|
if(ctx->is_bel_synthetic(cell.bel)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -345,6 +411,13 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str
|
|||||||
|
|
||||||
for(auto & cell_name : placed_cells) {
|
for(auto & cell_name : placed_cells) {
|
||||||
const CellInfo & cell = *ctx->cells.at(cell_name);
|
const CellInfo & cell = *ctx->cells.at(cell_name);
|
||||||
|
|
||||||
|
if(cell.bel == BelId()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
NPNR_ASSERT(ctx->isBelLocationValid(cell.bel));
|
||||||
|
|
||||||
if(ctx->is_bel_synthetic(cell.bel)) {
|
if(ctx->is_bel_synthetic(cell.bel)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -446,7 +519,7 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str
|
|||||||
std::unordered_map<WireId, std::vector<PipId>> pip_downhill;
|
std::unordered_map<WireId, std::vector<PipId>> pip_downhill;
|
||||||
std::unordered_set<PipId> pips;
|
std::unordered_set<PipId> pips;
|
||||||
|
|
||||||
if (driver_cell != nullptr && driver_cell->bel != BelId()) {
|
if (driver_cell != nullptr && driver_cell->bel != BelId() && ctx->isBelLocationValid(driver_cell->bel)) {
|
||||||
for(IdString bel_pin_name : driver_cell->cell_bel_pins.at(net.driver.port)) {
|
for(IdString bel_pin_name : driver_cell->cell_bel_pins.at(net.driver.port)) {
|
||||||
BelPin driver_bel_pin;
|
BelPin driver_bel_pin;
|
||||||
driver_bel_pin.bel = driver_cell->bel;
|
driver_bel_pin.bel = driver_cell->bel;
|
||||||
@ -461,8 +534,17 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str
|
|||||||
|
|
||||||
std::unordered_map<WireId, std::vector<BelPin>> sinks;
|
std::unordered_map<WireId, std::vector<BelPin>> sinks;
|
||||||
for(const auto &port_ref : net.users) {
|
for(const auto &port_ref : net.users) {
|
||||||
if(port_ref.cell != nullptr && port_ref.cell->bel != BelId()) {
|
if(port_ref.cell != nullptr && port_ref.cell->bel != BelId() && ctx->isBelLocationValid(port_ref.cell->bel)) {
|
||||||
for(IdString bel_pin_name : port_ref.cell->cell_bel_pins.at(port_ref.port)) {
|
auto pin_iter = port_ref.cell->cell_bel_pins.find(port_ref.port);
|
||||||
|
if(pin_iter == port_ref.cell->cell_bel_pins.end()) {
|
||||||
|
log_warning("Cell %s port %s on net %s is legal, but has no BEL pins?\n",
|
||||||
|
port_ref.cell->name.c_str(ctx),
|
||||||
|
port_ref.port.c_str(ctx),
|
||||||
|
net.name.c_str(ctx));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(IdString bel_pin_name : pin_iter->second) {
|
||||||
BelPin sink_bel_pin;
|
BelPin sink_bel_pin;
|
||||||
sink_bel_pin.bel = port_ref.cell->bel;
|
sink_bel_pin.bel = port_ref.cell->bel;
|
||||||
sink_bel_pin.pin = bel_pin_name;
|
sink_bel_pin.pin = bel_pin_name;
|
||||||
@ -531,8 +613,8 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str
|
|||||||
PhysicalNetlist::PhysNetlist::RouteBranch::Builder source_branch = *source_iter++;
|
PhysicalNetlist::PhysNetlist::RouteBranch::Builder source_branch = *source_iter++;
|
||||||
|
|
||||||
NPNR_ASSERT(pips.erase(root) == 1);
|
NPNR_ASSERT(pips.erase(root) == 1);
|
||||||
WireId root_wire = ctx->getPipDstWire(root);
|
WireId root_wire;
|
||||||
source_branch = emit_branch(ctx, &strings, pip_place_strength, root, source_branch);
|
source_branch = init_local_source(ctx, &strings, source_branch, root, pip_place_strength, &root_wire);
|
||||||
emit_net(ctx, &strings, pip_downhill, sinks, &pips, pip_place_strength, root_wire, source_branch);
|
emit_net(ctx, &strings, pip_downhill, sinks, &pips, pip_place_strength, root_wire, source_branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user