diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 7b5c1df18..55bf9cccb 100644 --- a/kernel/rtlil_bufnorm.cc +++ b/kernel/rtlil_bufnorm.cc @@ -1113,23 +1113,21 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) if (!r.second && conn_it->second == signal) return; - if (!module) - return; - - for (auto mon : module->monitors) - mon->notify_connect(this, conn_it->first, conn_it->second, signal); - - if (module->design) - for (auto mon : module->design->monitors) + if (module) { + for (auto mon : module->monitors) mon->notify_connect(this, conn_it->first, conn_it->second, signal); + if (module->design) + for (auto mon : module->design->monitors) + mon->notify_connect(this, conn_it->first, conn_it->second, signal); + } + if (yosys_xtrace) { - log("#X# Connect %s.%s.%s = %s (%d)\n", this->module, this, portname.unescape(), log_signal(signal), GetSize(signal)); + log("#X# Connect %s.%s.%s = %s (%d)\n", this->module ? this->module : "PATCH", this, portname.unescape(), log_signal(signal), GetSize(signal)); log_backtrace("-X- ", yosys_xtrace-1); } - - if (module->sig_norm_index != nullptr && !ignored_cell(type)) { + if (module && module->sig_norm_index != nullptr && !ignored_cell(type)) { module->sig_norm_index->dirty.insert(this); if (!r.second) { if (is_input_port) { @@ -1172,7 +1170,7 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) } } - if (module->design && module->design->flagBufferedNormalized) + if (module && module->design && module->design->flagBufferedNormalized) { // We eagerly clear a driver that got disconnected by changing this port connection if (conn_it->second.is_wire()) { diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 01286c1d3..ab0549e0d 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -23,6 +23,7 @@ Cell* Patch::addCell(IdString name, IdString type) { Cell* cell = cells_.back().get(); cell->name = name; cell->type = type; + cell->module = nullptr; return cell; } @@ -32,6 +33,7 @@ Wire* Patch::addWire(IdString name, int width) { Wire* wire = wires_.back().get(); wire->name = name; wire->width = width; + wire->module = nullptr; return wire; } @@ -54,53 +56,39 @@ RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *othe void Patch::patch(Cell* old_cell, Cell* new_cell) { for (auto& wire: wires_) { + wire->module = mod; Wire* raw = wire.release(); mod->wires_[raw->name] = raw; } - pool patch_cells; - for (auto& cell: cells_) { - patch_cells.insert(cell.get()); - } log("patching:\n"); log_cell(old_cell); for (auto& cell: cells_) { - log("with:\n"); log_cell(cell.get()); - log("ptr %p\n", cell.get()); Cell* raw = cell.release(); - log("ptr2 %p\n", raw); mod->cells_[raw->name] = raw; - raw->module = mod; for (auto [port_name, sig] : raw->connections()) { auto dir = raw->port_dir(port_name); log_assert(dir != PD_UNKNOWN); - if (raw == new_cell) - if (dir == PD_OUTPUT || dir == PD_INOUT) { + if (dir == PD_OUTPUT || dir == PD_INOUT) { + SigSpec sig_to_fix = sig; + if (raw == new_cell) { // RAUW - // TODO optimized implementation for signorm fanout transfer? - old_cell->setPort(port_name, mod->addWire(NEW_ID, sig.size())); - new_cell->setPort(port_name, sig); - auto* wire = sig.as_wire(); - wire->driverCell_ = new_cell; + // TODO optimized implementation for signorm fanout transfer that avoids expensive(?) setPort? + auto yoink = old_cell->getPort(port_name); + log(">>>> RAUW %s to %s\n", port_name, log_signal(yoink)); + new_cell->setPort(port_name, yoink); + old_cell->setPort(port_name, mod->addWire(NEW_ID, yoink.size())); + sig_to_fix = yoink; + } + if (sig_to_fix.size()) { + auto* wire = sig_to_fix.as_wire(); + wire->driverCell_ = raw; wire->driverPort_ = port_name; } - // } else { - // new_cell->setPort(port_name, sig); // map? - // for (auto chunk : map(sig).chunks()) { - // if (chunk.size() == 0) - // continue; - // log_assert(chunk.is_wire()); - // auto* wire = chunk.wire; - // // TODO Use roots instead? - // if (patch_cells.count(wire->driverCell_)) { - // // How do we handle this? - // log_assert(false); - // } else { - // // mod->sig_norm_index - - // } - // } + } } + raw->module = mod; + raw->fixup_parameters(); } log_module(mod, ""); } diff --git a/passes/cmds/test_patch.cc b/passes/cmds/test_patch.cc index 727099a15..b03dcfe14 100644 --- a/passes/cmds/test_patch.cc +++ b/passes/cmds/test_patch.cc @@ -20,19 +20,16 @@ struct TestPatchPass : public Pass { Cell* add = cell; log_assert(add->getPort(ID::B).is_wire()); log_assert(add->getPort(ID::B).known_driver()); - auto neg = add->getPort(ID::B).as_wire()->driverCell(); + auto neg = add->getPort(ID::B)[0].wire->driverCell(); log_assert(neg->type == ID($not)); - - RTLIL::Patch patcher; patcher.mod = module; patcher.map = SigMap(module); - auto new_cell = patcher.addNeg(NEW_ID, patcher.Sub(NEW_ID, neg->getPort(ID::A), cell->getPort(ID::A)), SigSpec()); - // // sub->connections_ = cell->connections(); - // sub->parameters = add->parameters; - // sub->connections_[ID::A] = add->getPort(ID::A); - // sub->connections_[ID::B] = add->getPort(ID::B); - // sub->connections_[ID::Y] = add->getPort(ID::Y); + auto sub = patcher.addSub(NEW_ID, + neg->getPort(ID::A), + cell->getPort(ID::A), + patcher.addWire(NEW_ID, cell->getPort(ID::A).size())); + auto new_cell = patcher.addNeg(NEW_ID, sub->getPort(ID::Y), SigSpec()); log_cell(new_cell); patcher.patch(add, new_cell); }