API change: Use CellInfo* and NetInfo* as cell/net handles (common, ice40)

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2018-08-05 15:25:42 +02:00
parent ba97c233fb
commit 5e53075990
10 changed files with 156 additions and 155 deletions

View File

@ -232,25 +232,26 @@ void Context::check() const
auto ni = n.second.get(); auto ni = n.second.get();
NPNR_ASSERT(n.first == ni->name); NPNR_ASSERT(n.first == ni->name);
for (auto &w : ni->wires) { for (auto &w : ni->wires) {
NPNR_ASSERT(n.first == getBoundWireNet(w.first)); NPNR_ASSERT(ni == getBoundWireNet(w.first));
if (w.second.pip != PipId()) { if (w.second.pip != PipId()) {
NPNR_ASSERT(w.first == getPipDstWire(w.second.pip)); NPNR_ASSERT(w.first == getPipDstWire(w.second.pip));
NPNR_ASSERT(n.first == getBoundPipNet(w.second.pip)); NPNR_ASSERT(ni == getBoundPipNet(w.second.pip));
} }
} }
} }
for (auto w : getWires()) { for (auto w : getWires()) {
IdString net = getBoundWireNet(w); auto ni = getBoundWireNet(w);
if (net != IdString()) { if (ni != nullptr) {
NPNR_ASSERT(nets.at(net)->wires.count(w)); NPNR_ASSERT(ni->wires.count(w));
} }
} }
for (auto &c : cells) { for (auto &c : cells) {
NPNR_ASSERT(c.first == c.second->name); auto ci = c.second.get();
if (c.second->bel != BelId()) NPNR_ASSERT(c.first == ci->name);
NPNR_ASSERT(getBoundBelCell(c.second->bel) == c.first); if (ci->bel != BelId())
NPNR_ASSERT(getBoundBelCell(c.second->bel) == ci);
for (auto &port : c.second->ports) { for (auto &port : c.second->ports) {
NetInfo *net = port.second.net; NetInfo *net = port.second.net;
if (net != nullptr) { if (net != nullptr) {

View File

@ -437,6 +437,13 @@ struct BaseCtx
const Context *getCtx() const { return reinterpret_cast<const Context *>(this); } const Context *getCtx() const { return reinterpret_cast<const Context *>(this); }
template<typename T> const char *nameOf(const T *obj)
{
if (obj == nullptr)
return "";
return obj->name.c_str(getCtx());
}
// -------------------------------------------------------------- // --------------------------------------------------------------
bool allUiReload = true; bool allUiReload = true;

View File

@ -131,7 +131,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
if (iters >= 4) if (iters >= 4)
wirelen += ctx->rng(25); wirelen += ctx->rng(25);
if (wirelen <= best_ripup_wirelen) { if (wirelen <= best_ripup_wirelen) {
CellInfo *curr_cell = ctx->cells.at(ctx->getBoundBelCell(bel)).get(); CellInfo *curr_cell = ctx->getBoundBelCell(bel);
if (curr_cell->belStrength < STRENGTH_STRONG) { if (curr_cell->belStrength < STRENGTH_STRONG) {
best_ripup_wirelen = wirelen; best_ripup_wirelen = wirelen;
ripup_bel = bel; ripup_bel = bel;
@ -158,7 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
if (ctx->verbose) if (ctx->verbose)
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx),
ctx->getBelName(best_bel).c_str(ctx)); ctx->getBelName(best_bel).c_str(ctx));
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK); ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
cell = ripup_target; cell = ripup_target;
} }
@ -232,8 +232,8 @@ class ConstraintLegaliseWorker
return false; return false;
} }
if (!ctx->checkBelAvail(locBel)) { if (!ctx->checkBelAvail(locBel)) {
IdString confCell = ctx->getConflictingBelCell(locBel); CellInfo *confCell = ctx->getConflictingBelCell(locBel);
if (ctx->cells[confCell]->belStrength >= STRENGTH_STRONG) { if (confCell->belStrength >= STRENGTH_STRONG) {
return false; return false;
} }
} }
@ -362,18 +362,17 @@ class ConstraintLegaliseWorker
cp.second.y, cp.second.z); cp.second.y, cp.second.z);
BelId target = ctx->getBelByLocation(cp.second); BelId target = ctx->getBelByLocation(cp.second);
if (!ctx->checkBelAvail(target)) { if (!ctx->checkBelAvail(target)) {
IdString conflicting = ctx->getConflictingBelCell(target); CellInfo *confl_cell = ctx->getConflictingBelCell(target);
if (conflicting != IdString()) { if (confl_cell != nullptr) {
CellInfo *confl_cell = ctx->cells.at(conflicting).get();
if (ctx->verbose) if (ctx->verbose)
log_info(" '%s' already placed at '%s'\n", conflicting.c_str(ctx), log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell),
ctx->getBelName(confl_cell->bel).c_str(ctx)); ctx->getBelName(confl_cell->bel).c_str(ctx));
NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG); NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
ctx->unbindBel(target); ctx->unbindBel(target);
rippedCells.insert(conflicting); rippedCells.insert(confl_cell->name);
} }
} }
ctx->bindBel(target, cp.first, STRENGTH_LOCKED); ctx->bindBel(target, ctx->cells.at(cp.first).get(), STRENGTH_LOCKED);
rippedCells.erase(cp.first); rippedCells.erase(cp.first);
} }
NPNR_ASSERT(constraints_satisfied(cell)); NPNR_ASSERT(constraints_satisfied(cell));

View File

@ -105,7 +105,7 @@ class SAPlacer
cell->type.c_str(ctx)); cell->type.c_str(ctx));
} }
ctx->bindBel(bel, cell->name, STRENGTH_USER); ctx->bindBel(bel, cell, STRENGTH_USER);
locked_bels.insert(bel); locked_bels.insert(bel);
placed_cells++; placed_cells++;
} }
@ -256,11 +256,11 @@ class SAPlacer
// Final post-pacement validitiy check // Final post-pacement validitiy check
ctx->yield(); ctx->yield();
for (auto bel : ctx->getBels()) { for (auto bel : ctx->getBels()) {
IdString cell = ctx->getBoundBelCell(bel); CellInfo *cell = ctx->getBoundBelCell(bel);
if (!ctx->isBelLocationValid(bel)) { if (!ctx->isBelLocationValid(bel)) {
std::string cell_text = "no cell"; std::string cell_text = "no cell";
if (cell != IdString()) if (cell != nullptr)
cell_text = std::string("cell '") + cell.str(ctx) + "'"; cell_text = std::string("cell '") + ctx->nameOf(cell) + "'";
if (ctx->force) { if (ctx->force) {
log_warning("post-placement validity check failed for Bel '%s' " log_warning("post-placement validity check failed for Bel '%s' "
"(%s)\n", "(%s)\n",
@ -309,7 +309,7 @@ class SAPlacer
uint64_t score = ctx->rng64(); uint64_t score = ctx->rng64();
if (score <= best_ripup_score) { if (score <= best_ripup_score) {
best_ripup_score = score; best_ripup_score = score;
ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get(); ripup_target = ctx->getBoundBelCell(bel);
ripup_bel = bel; ripup_bel = bel;
} }
} }
@ -324,7 +324,7 @@ class SAPlacer
} else { } else {
all_placed = true; all_placed = true;
} }
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK); ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
// Back annotate location // Back annotate location
cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx); cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
@ -340,20 +340,17 @@ class SAPlacer
new_lengths.clear(); new_lengths.clear();
update.clear(); update.clear();
BelId oldBel = cell->bel; BelId oldBel = cell->bel;
IdString other = ctx->getBoundBelCell(newBel); CellInfo *other_cell = ctx->getBoundBelCell(newBel);
CellInfo *other_cell = nullptr; if (other_cell != nullptr && other_cell->belStrength > STRENGTH_WEAK) {
if (other != IdString()) { return false;
other_cell = ctx->cells[other].get();
if (other_cell->belStrength > STRENGTH_WEAK)
return false;
} }
int old_dist = get_constraints_distance(ctx, cell); int old_dist = get_constraints_distance(ctx, cell);
int new_dist; int new_dist;
if (other != IdString()) if (other_cell != nullptr)
old_dist += get_constraints_distance(ctx, other_cell); old_dist += get_constraints_distance(ctx, other_cell);
wirelen_t new_metric = 0, delta; wirelen_t new_metric = 0, delta;
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
if (other != IdString()) { if (other_cell != nullptr) {
ctx->unbindBel(newBel); ctx->unbindBel(newBel);
} }
@ -361,20 +358,20 @@ class SAPlacer
if (port.second.net != nullptr) if (port.second.net != nullptr)
update.insert(port.second.net); update.insert(port.second.net);
if (other != IdString()) { if (other_cell != nullptr) {
for (const auto &port : other_cell->ports) for (const auto &port : other_cell->ports)
if (port.second.net != nullptr) if (port.second.net != nullptr)
update.insert(port.second.net); update.insert(port.second.net);
} }
ctx->bindBel(newBel, cell->name, STRENGTH_WEAK); ctx->bindBel(newBel, cell, STRENGTH_WEAK);
if (other != IdString()) { if (other_cell != nullptr) {
ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK); ctx->bindBel(oldBel, other_cell, STRENGTH_WEAK);
} }
if (!ctx->isBelLocationValid(newBel) || ((other != IdString() && !ctx->isBelLocationValid(oldBel)))) { if (!ctx->isBelLocationValid(newBel) || ((other_cell != nullptr && !ctx->isBelLocationValid(oldBel)))) {
ctx->unbindBel(newBel); ctx->unbindBel(newBel);
if (other != IdString()) if (other_cell != nullptr)
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
goto swap_fail; goto swap_fail;
} }
@ -391,7 +388,7 @@ class SAPlacer
} }
new_dist = get_constraints_distance(ctx, cell); new_dist = get_constraints_distance(ctx, cell);
if (other != IdString()) if (other_cell != nullptr)
new_dist += get_constraints_distance(ctx, other_cell); new_dist += get_constraints_distance(ctx, other_cell);
delta = new_metric - curr_metric; delta = new_metric - curr_metric;
delta += (cfg.constraintWeight / temp) * (new_dist - old_dist); delta += (cfg.constraintWeight / temp) * (new_dist - old_dist);
@ -400,7 +397,7 @@ class SAPlacer
if (delta < 0 || (temp > 1e-6 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) { if (delta < 0 || (temp > 1e-6 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
n_accept++; n_accept++;
} else { } else {
if (other != IdString()) if (other_cell != nullptr)
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
ctx->unbindBel(newBel); ctx->unbindBel(newBel);
goto swap_fail; goto swap_fail;
@ -411,9 +408,9 @@ class SAPlacer
return true; return true;
swap_fail: swap_fail:
ctx->bindBel(oldBel, cell->name, STRENGTH_WEAK); ctx->bindBel(oldBel, cell, STRENGTH_WEAK);
if (other != IdString()) { if (other_cell != nullptr) {
ctx->bindBel(newBel, other, STRENGTH_WEAK); ctx->bindBel(newBel, other_cell, STRENGTH_WEAK);
} }
return false; return false;
} }

View File

@ -159,15 +159,15 @@ struct Router
if (!ctx->checkWireAvail(next_wire)) { if (!ctx->checkWireAvail(next_wire)) {
if (!ripup) if (!ripup)
continue; continue;
IdString ripupWireNet = ctx->getConflictingWireNet(next_wire); NetInfo *ripupWireNet = ctx->getConflictingWireNet(next_wire);
if (ripupWireNet == net_name || ripupWireNet == IdString()) if (ripupWireNet == nullptr || ripupWireNet->name == net_name)
continue; continue;
auto it1 = scores.wireScores.find(next_wire); auto it1 = scores.wireScores.find(next_wire);
if (it1 != scores.wireScores.end()) if (it1 != scores.wireScores.end())
next_delay += (it1->second * ripup_penalty) / 8; next_delay += (it1->second * ripup_penalty) / 8;
auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet, next_wire)); auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet->name, next_wire));
if (it2 != scores.netWireScores.end()) if (it2 != scores.netWireScores.end())
next_delay += it2->second * ripup_penalty; next_delay += it2->second * ripup_penalty;
@ -177,15 +177,15 @@ struct Router
if (!ctx->checkPipAvail(pip)) { if (!ctx->checkPipAvail(pip)) {
if (!ripup) if (!ripup)
continue; continue;
IdString ripupPipNet = ctx->getConflictingPipNet(pip); NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip);
if (ripupPipNet == net_name || ripupPipNet == IdString()) if (ripupPipNet == nullptr || ripupPipNet->name == net_name)
continue; continue;
auto it1 = scores.pipScores.find(pip); auto it1 = scores.pipScores.find(pip);
if (it1 != scores.pipScores.end()) if (it1 != scores.pipScores.end())
next_delay += (it1->second * ripup_penalty) / 8; next_delay += (it1->second * ripup_penalty) / 8;
auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet, pip)); auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet->name, pip));
if (it2 != scores.netPipScores.end()) if (it2 != scores.netPipScores.end())
next_delay += it2->second * ripup_penalty; next_delay += it2->second * ripup_penalty;
@ -294,12 +294,12 @@ struct Router
if (reroute) { if (reroute) {
// complete ripup // complete ripup
ripup_net(ctx, net_name); ripup_net(ctx, net_name);
ctx->bindWire(src_wire, net_name, STRENGTH_WEAK); ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay(); src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
} else { } else {
// re-use existing routes as much as possible // re-use existing routes as much as possible
if (net_info->wires.count(src_wire) == 0) if (net_info->wires.count(src_wire) == 0)
ctx->bindWire(src_wire, net_name, STRENGTH_WEAK); ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay(); src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
@ -399,42 +399,42 @@ struct Router
if (src_wires.count(cursor)) if (src_wires.count(cursor))
break; break;
IdString conflicting_wire_net = ctx->getConflictingWireNet(cursor); NetInfo *conflicting_wire_net = ctx->getConflictingWireNet(cursor);
if (conflicting_wire_net != IdString()) { if (conflicting_wire_net != nullptr) {
NPNR_ASSERT(ripup); NPNR_ASSERT(ripup);
NPNR_ASSERT(conflicting_wire_net != net_name); NPNR_ASSERT(conflicting_wire_net->name != net_name);
ctx->unbindWire(cursor); ctx->unbindWire(cursor);
if (!ctx->checkWireAvail(cursor)) if (!ctx->checkWireAvail(cursor))
ripup_net(ctx, conflicting_wire_net); ripup_net(ctx, conflicting_wire_net->name);
rippedNets.insert(conflicting_wire_net); rippedNets.insert(conflicting_wire_net->name);
scores.wireScores[cursor]++; scores.wireScores[cursor]++;
scores.netWireScores[std::make_pair(net_name, cursor)]++; scores.netWireScores[std::make_pair(net_name, cursor)]++;
scores.netWireScores[std::make_pair(conflicting_wire_net, cursor)]++; scores.netWireScores[std::make_pair(conflicting_wire_net->name, cursor)]++;
} }
PipId pip = visited[cursor].pip; PipId pip = visited[cursor].pip;
IdString conflicting_pip_net = ctx->getConflictingPipNet(pip); NetInfo *conflicting_pip_net = ctx->getConflictingPipNet(pip);
if (conflicting_pip_net != IdString()) { if (conflicting_pip_net != nullptr) {
NPNR_ASSERT(ripup); NPNR_ASSERT(ripup);
NPNR_ASSERT(conflicting_pip_net != net_name); NPNR_ASSERT(conflicting_pip_net->name != net_name);
if (ctx->getBoundPipNet(pip) == conflicting_pip_net) if (ctx->getBoundPipNet(pip) == conflicting_pip_net)
ctx->unbindPip(pip); ctx->unbindPip(pip);
if (!ctx->checkPipAvail(pip)) if (!ctx->checkPipAvail(pip))
ripup_net(ctx, conflicting_pip_net); ripup_net(ctx, conflicting_pip_net->name);
rippedNets.insert(conflicting_pip_net); rippedNets.insert(conflicting_pip_net->name);
scores.pipScores[visited[cursor].pip]++; scores.pipScores[visited[cursor].pip]++;
scores.netPipScores[std::make_pair(net_name, visited[cursor].pip)]++; scores.netPipScores[std::make_pair(net_name, visited[cursor].pip)]++;
scores.netPipScores[std::make_pair(conflicting_pip_net, visited[cursor].pip)]++; scores.netPipScores[std::make_pair(conflicting_pip_net->name, visited[cursor].pip)]++;
} }
ctx->bindPip(visited[cursor].pip, net_name, STRENGTH_WEAK); ctx->bindPip(visited[cursor].pip, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
src_wires[cursor] = visited[cursor].delay; src_wires[cursor] = visited[cursor].delay;
cursor = ctx->getPipSrcWire(visited[cursor].pip); cursor = ctx->getPipSrcWire(visited[cursor].pip);
} }

View File

@ -407,8 +407,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->belTypeToId(ctx->getBelType(bel)).c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->belTypeToId(ctx->getBelType(bel)).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel));
addProperty(topItem, QVariant::String, "Bound Cell", ctx->getBoundBelCell(bel).c_str(ctx), ElementType::CELL); addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL);
addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->getConflictingBelCell(bel).c_str(ctx), addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->nameOf(ctx->getConflictingBelCell(bel)),
ElementType::CELL); ElementType::CELL);
QtProperty *belpinsItem = addSubGroup(topItem, "Ports"); QtProperty *belpinsItem = addSubGroup(topItem, "Ports");
@ -429,8 +429,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundWireNet(wire).c_str(ctx), ElementType::NET); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingWireNet(wire).c_str(ctx), addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
ElementType::NET); ElementType::NET);
DelayInfo delay = ctx->getWireDelay(wire); DelayInfo delay = ctx->getWireDelay(wire);
@ -484,8 +484,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundPipNet(pip).c_str(ctx), ElementType::NET); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingPipNet(pip).c_str(ctx), addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
ElementType::NET); ElementType::NET);
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx), addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
ElementType::WIRE); ElementType::WIRE);

View File

@ -672,7 +672,7 @@ DecalXY Arch::getBelDecal(BelId bel) const
DecalXY decalxy; DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_BEL; decalxy.decal.type = DecalId::TYPE_BEL;
decalxy.decal.index = bel.index; decalxy.decal.index = bel.index;
decalxy.decal.active = bel_to_cell.at(bel.index) != IdString(); decalxy.decal.active = bel_to_cell.at(bel.index) != nullptr;
return decalxy; return decalxy;
} }
@ -681,7 +681,7 @@ DecalXY Arch::getWireDecal(WireId wire) const
DecalXY decalxy; DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_WIRE; decalxy.decal.type = DecalId::TYPE_WIRE;
decalxy.decal.index = wire.index; decalxy.decal.index = wire.index;
decalxy.decal.active = wire_to_net.at(wire.index) != IdString(); decalxy.decal.active = wire_to_net.at(wire.index) != nullptr;
return decalxy; return decalxy;
} }
@ -690,7 +690,7 @@ DecalXY Arch::getPipDecal(PipId pip) const
DecalXY decalxy; DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_PIP; decalxy.decal.type = DecalId::TYPE_PIP;
decalxy.decal.index = pip.index; decalxy.decal.index = pip.index;
decalxy.decal.active = pip_to_net.at(pip.index) != IdString(); decalxy.decal.active = pip_to_net.at(pip.index) != nullptr;
return decalxy; return decalxy;
}; };

View File

@ -400,10 +400,10 @@ struct Arch : BaseCtx
mutable std::unordered_map<Loc, int> bel_by_loc; mutable std::unordered_map<Loc, int> bel_by_loc;
std::vector<bool> bel_carry; std::vector<bool> bel_carry;
std::vector<IdString> bel_to_cell; std::vector<CellInfo*> bel_to_cell;
std::vector<IdString> wire_to_net; std::vector<NetInfo*> wire_to_net;
std::vector<IdString> pip_to_net; std::vector<NetInfo*> pip_to_net;
std::vector<IdString> switches_locked; std::vector<NetInfo*> switches_locked;
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
@ -437,26 +437,25 @@ struct Arch : BaseCtx
uint32_t getBelChecksum(BelId bel) const { return bel.index; } uint32_t getBelChecksum(BelId bel) const { return bel.index; }
void bindBel(BelId bel, IdString cell, PlaceStrength strength) void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] == IdString()); NPNR_ASSERT(bel_to_cell[bel.index] == nullptr);
auto &c = cells[cell];
bel_to_cell[bel.index] = cell; bel_to_cell[bel.index] = cell;
bel_carry[bel.index] = (c->type == id_icestorm_lc && c->lcInfo.carryEnable); bel_carry[bel.index] = (cell->type == id_icestorm_lc && cell->lcInfo.carryEnable);
c->bel = bel; cell->bel = bel;
c->belStrength = strength; cell->belStrength = strength;
refreshUiBel(bel); refreshUiBel(bel);
} }
void unbindBel(BelId bel) void unbindBel(BelId bel)
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] != IdString()); NPNR_ASSERT(bel_to_cell[bel.index] != nullptr);
cells[bel_to_cell[bel.index]]->bel = BelId(); bel_to_cell[bel.index]->bel = BelId();
cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE; bel_to_cell[bel.index]->belStrength = STRENGTH_NONE;
bel_to_cell[bel.index] = IdString(); bel_to_cell[bel.index] = nullptr;
bel_carry[bel.index] = false; bel_carry[bel.index] = false;
refreshUiBel(bel); refreshUiBel(bel);
} }
@ -464,16 +463,16 @@ struct Arch : BaseCtx
bool checkBelAvail(BelId bel) const bool checkBelAvail(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index] == IdString(); return bel_to_cell[bel.index] == nullptr;
} }
IdString getBoundBelCell(BelId bel) const CellInfo *getBoundBelCell(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index]; return bel_to_cell[bel.index];
} }
IdString getConflictingBelCell(BelId bel) const CellInfo *getConflictingBelCell(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index]; return bel_to_cell[bel.index];
@ -525,49 +524,49 @@ struct Arch : BaseCtx
uint32_t getWireChecksum(WireId wire) const { return wire.index; } uint32_t getWireChecksum(WireId wire) const { return wire.index; }
void bindWire(WireId wire, IdString net, PlaceStrength strength) void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] == IdString()); NPNR_ASSERT(wire_to_net[wire.index] == nullptr);
wire_to_net[wire.index] = net; wire_to_net[wire.index] = net;
nets[net]->wires[wire].pip = PipId(); net->wires[wire].pip = PipId();
nets[net]->wires[wire].strength = strength; net->wires[wire].strength = strength;
refreshUiWire(wire); refreshUiWire(wire);
} }
void unbindWire(WireId wire) void unbindWire(WireId wire)
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] != IdString()); NPNR_ASSERT(wire_to_net[wire.index] != nullptr);
auto &net_wires = nets[wire_to_net[wire.index]]->wires; auto &net_wires = wire_to_net[wire.index]->wires;
auto it = net_wires.find(wire); auto it = net_wires.find(wire);
NPNR_ASSERT(it != net_wires.end()); NPNR_ASSERT(it != net_wires.end());
auto pip = it->second.pip; auto pip = it->second.pip;
if (pip != PipId()) { if (pip != PipId()) {
pip_to_net[pip.index] = IdString(); pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr;
} }
net_wires.erase(it); net_wires.erase(it);
wire_to_net[wire.index] = IdString(); wire_to_net[wire.index] = nullptr;
refreshUiWire(wire); refreshUiWire(wire);
} }
bool checkWireAvail(WireId wire) const bool checkWireAvail(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index] == IdString(); return wire_to_net[wire.index] == nullptr;
} }
IdString getBoundWireNet(WireId wire) const NetInfo *getBoundWireNet(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index]; return wire_to_net[wire.index];
} }
IdString getConflictingWireNet(WireId wire) const NetInfo *getConflictingWireNet(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index]; return wire_to_net[wire.index];
@ -605,21 +604,21 @@ struct Arch : BaseCtx
PipId getPipByName(IdString name) const; PipId getPipByName(IdString name) const;
void bindPip(PipId pip, IdString net, PlaceStrength strength) void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] == IdString()); NPNR_ASSERT(pip_to_net[pip.index] == nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString()); NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == nullptr);
pip_to_net[pip.index] = net; pip_to_net[pip.index] = net;
switches_locked[chip_info->pip_data[pip.index].switch_index] = net; switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
WireId dst; WireId dst;
dst.index = chip_info->pip_data[pip.index].dst; dst.index = chip_info->pip_data[pip.index].dst;
NPNR_ASSERT(wire_to_net[dst.index] == IdString()); NPNR_ASSERT(wire_to_net[dst.index] == nullptr);
wire_to_net[dst.index] = net; wire_to_net[dst.index] = net;
nets[net]->wires[dst].pip = pip; net->wires[dst].pip = pip;
nets[net]->wires[dst].strength = strength; net->wires[dst].strength = strength;
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(dst); refreshUiWire(dst);
} }
@ -627,17 +626,17 @@ struct Arch : BaseCtx
void unbindPip(PipId pip) void unbindPip(PipId pip)
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] != IdString()); NPNR_ASSERT(pip_to_net[pip.index] != nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != IdString()); NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != nullptr);
WireId dst; WireId dst;
dst.index = chip_info->pip_data[pip.index].dst; dst.index = chip_info->pip_data[pip.index].dst;
NPNR_ASSERT(wire_to_net[dst.index] != IdString()); NPNR_ASSERT(wire_to_net[dst.index] != nullptr);
wire_to_net[dst.index] = IdString(); wire_to_net[dst.index] = nullptr;
nets[pip_to_net[pip.index]]->wires.erase(dst); pip_to_net[pip.index]->wires.erase(dst);
pip_to_net[pip.index] = IdString(); pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr;
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(dst); refreshUiWire(dst);
} }
@ -648,12 +647,12 @@ struct Arch : BaseCtx
auto &pi = chip_info->pip_data[pip.index]; auto &pi = chip_info->pip_data[pip.index];
auto &si = chip_info->bits_info->switches[pi.switch_index]; auto &si = chip_info->bits_info->switches[pi.switch_index];
if (switches_locked[pi.switch_index] != IdString()) if (switches_locked[pi.switch_index] != nullptr)
return false; return false;
if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) { if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
NPNR_ASSERT(si.bel >= 0); NPNR_ASSERT(si.bel >= 0);
if (bel_to_cell[si.bel] != IdString()) if (bel_to_cell[si.bel] != nullptr)
return false; return false;
} }
@ -666,13 +665,13 @@ struct Arch : BaseCtx
return true; return true;
} }
IdString getBoundPipNet(PipId pip) const NetInfo *getBoundPipNet(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
return pip_to_net[pip.index]; return pip_to_net[pip.index];
} }
IdString getConflictingPipNet(PipId pip) const NetInfo *getConflictingPipNet(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
return switches_locked[chip_info->pip_data[pip.index].switch_index]; return switches_locked[chip_info->pip_data[pip.index].switch_index];

View File

@ -74,19 +74,18 @@ bool Arch::isBelLocationValid(BelId bel) const
std::vector<const CellInfo *> bel_cells; std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel); Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other); CellInfo *ci_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) { if (ci_other != nullptr) {
const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other); bel_cells.push_back(ci_other);
} }
} }
return logicCellsCompatible(bel_cells); return logicCellsCompatible(bel_cells);
} else { } else {
IdString cellId = getBoundBelCell(bel); CellInfo *ci = getBoundBelCell(bel);
if (cellId == IdString()) if (ci == nullptr)
return true; return true;
else else
return isValidBelForCell(cells.at(cellId).get(), bel); return isValidBelForCell(ci, bel);
} }
} }
@ -98,9 +97,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
std::vector<const CellInfo *> bel_cells; std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel); Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other); CellInfo *ci_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) { if (ci_other != nullptr && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other); bel_cells.push_back(ci_other);
} }
} }
@ -126,12 +124,12 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
if (pll_bel.index != -1) { if (pll_bel.index != -1) {
auto pll_cell = getBoundBelCell(pll_bel); auto pll_cell = getBoundBelCell(pll_bel);
// Is a PLL placed in this PLL bel? // Is a PLL placed in this PLL bel?
if (pll_cell != IdString()) { if (pll_cell != nullptr) {
// Is the shared port driving a net? // Is the shared port driving a net?
auto pi = cells.at(pll_cell)->ports[portPinToId(pll_bel_pin)]; auto pi = pll_cell->ports[portPinToId(pll_bel_pin)];
if (pi.net != nullptr) { if (pi.net != nullptr) {
// Are we perhaps a PAD INPUT Bel that can be placed here? // Are we perhaps a PAD INPUT Bel that can be placed here?
if (cells.at(pll_cell)->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) { if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) {
return true; return true;
} }
return false; return false;

View File

@ -291,7 +291,7 @@ void write_asc(const Context *ctx, std::ostream &out)
} }
// Set pips // Set pips
for (auto pip : ctx->getPips()) { for (auto pip : ctx->getPips()) {
if (ctx->pip_to_net[pip.index] != IdString()) { if (ctx->pip_to_net[pip.index] != nullptr) {
const PipInfoPOD &pi = ci.pip_data[pip.index]; const PipInfoPOD &pi = ci.pip_data[pip.index];
const SwitchInfoPOD &swi = bi.switches[pi.switch_index]; const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
int sw_bel_idx = swi.bel; int sw_bel_idx = swi.bel;
@ -310,7 +310,7 @@ void write_asc(const Context *ctx, std::ostream &out)
WireId permWire; WireId permWire;
for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) { for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) {
if (ctx->getBoundPipNet(permPip) != IdString()) { if (ctx->getBoundPipNet(permPip) != nullptr) {
permWire = ctx->getPipSrcWire(permPip); permWire = ctx->getPipSrcWire(permPip);
} }
} }
@ -384,7 +384,7 @@ void write_asc(const Context *ctx, std::ostream &out)
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
WireId lut_wire = ctx->getBelPinWire(bel, PortPin(PIN_I0 + i)); WireId lut_wire = ctx->getBelPinWire(bel, PortPin(PIN_I0 + i));
for (auto pip : ctx->getPipsUphill(lut_wire)) { for (auto pip : ctx->getPipsUphill(lut_wire)) {
if (ctx->getBoundPipNet(pip) != IdString()) { if (ctx->getBoundPipNet(pip) != nullptr) {
std::string name = ci.wire_data[ctx->getPipSrcWire(pip).index].name.get(); std::string name = ci.wire_data[ctx->getPipSrcWire(pip).index].name.get();
switch (name.back()) { switch (name.back()) {
case '0': case '0':
@ -458,8 +458,8 @@ void write_asc(const Context *ctx, std::ostream &out)
NPNR_ASSERT(iez != -1); NPNR_ASSERT(iez != -1);
bool input_en = false; bool input_en = false;
if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).index] != IdString()) || if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).index] != nullptr) ||
(ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != IdString())) { (ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != nullptr)) {
input_en = true; input_en = true;
} }
@ -618,7 +618,7 @@ void write_asc(const Context *ctx, std::ostream &out)
} }
// Set config bits in unused IO and RAM // Set config bits in unused IO and RAM
for (auto bel : ctx->getBels()) { for (auto bel : ctx->getBels()) {
if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_SB_IO) { if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == TYPE_SB_IO) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
const BelInfoPOD &beli = ci.bel_data[bel.index]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z; int x = beli.x, y = beli.y, z = beli.z;
@ -633,7 +633,7 @@ void write_asc(const Context *ctx, std::ostream &out)
set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true); set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true);
set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false); set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false);
} }
} else if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) { } else if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) {
const BelInfoPOD &beli = ci.bel_data[bel.index]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y; int x = beli.x, y = beli.y;
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB];
@ -751,9 +751,9 @@ void write_asc(const Context *ctx, std::ostream &out)
// Write symbols // Write symbols
// const bool write_symbols = 1; // const bool write_symbols = 1;
for (auto wire : ctx->getWires()) { for (auto wire : ctx->getWires()) {
IdString net = ctx->getBoundWireNet(wire); NetInfo *net = ctx->getBoundWireNet(wire);
if (net != IdString()) if (net != nullptr)
out << ".sym " << wire.index << " " << net.str(ctx) << std::endl; out << ".sym " << wire.index << " " << net->name.str(ctx) << std::endl;
} }
} }
@ -825,7 +825,7 @@ void read_config(Context *ctx, std::istream &in, chipconfig_t &config)
WireId wire; WireId wire;
wire.index = wireIndex; wire.index = wireIndex;
ctx->bindWire(wire, netName, STRENGTH_WEAK); ctx->bindWire(wire, ctx->nets.at(netName).get(), STRENGTH_WEAK);
} }
} else if (line_nr >= 0 && strlen(buffer) > 0) { } else if (line_nr >= 0 && strlen(buffer) > 0) {
if (line_nr > int(config.at(tile_y).at(tile_x).size() - 1)) if (line_nr > int(config.at(tile_y).at(tile_x).size() - 1))
@ -869,7 +869,7 @@ bool read_asc(Context *ctx, std::istream &in)
isUsed &= !(bool(cbit) ^ val); isUsed &= !(bool(cbit) ^ val);
} }
if (isUsed) { if (isUsed) {
IdString net = ctx->wire_to_net[pi.dst]; NetInfo *net = ctx->wire_to_net[pi.dst];
WireId wire; WireId wire;
wire.index = pi.dst; wire.index = pi.dst;
ctx->unbindWire(wire); ctx->unbindWire(wire);
@ -896,7 +896,7 @@ bool read_asc(Context *ctx, std::istream &in)
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(bel, name, STRENGTH_WEAK); ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets and assign values of properties // TODO: Add port mapping to nets and assign values of properties
} }
} }
@ -916,7 +916,7 @@ bool read_asc(Context *ctx, std::istream &in)
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(bel, name, STRENGTH_WEAK); ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets and assign values of properties // TODO: Add port mapping to nets and assign values of properties
} }
} }
@ -933,35 +933,35 @@ bool read_asc(Context *ctx, std::istream &in)
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) { if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) { if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_GB")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_GB"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) { if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) { if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
} }
@ -975,17 +975,17 @@ bool read_asc(Context *ctx, std::istream &in)
PortPin pin = ctx->portPinFromId(port.first); PortPin pin = ctx->portPinFromId(port.first);
WireId wire = ctx->getBelPinWire(cell.second->bel, pin); WireId wire = ctx->getBelPinWire(cell.second->bel, pin);
if (wire != WireId()) { if (wire != WireId()) {
IdString name = ctx->getBoundWireNet(wire); NetInfo *net = ctx->getBoundWireNet(wire);
if (name != IdString()) { if (net != nullptr) {
port.second.net = ctx->nets[name].get(); port.second.net = net;
PortRef ref; PortRef ref;
ref.cell = cell.second.get(); ref.cell = cell.second.get();
ref.port = port.second.name; ref.port = port.second.name;
if (port.second.type == PORT_OUT) if (port.second.type == PORT_OUT)
ctx->nets[name]->driver = ref; net->driver = ref;
else else
ctx->nets[name]->users.push_back(ref); net->users.push_back(ref);
} }
} }
} }