diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a62607fb2..5c5492ac2 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -4038,6 +4038,34 @@ void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname) } } +struct RTLIL::Detail { + static void bufNormalizeConflict(Module* module, CellPort port, Wire* wire) + { + auto [cell, portname] = port; + log_error("Conflict between %s.%s and %s.%s driving %s in module %s\n", + log_id(cell), log_id(portname), + log_id(wire->driverCell_), log_id(wire->driverPort_), + log_id(wire), log_id(module)); + } + + static void drive(Wire* wire, CellPort port) + { + auto [cell, portname] = port; + if (wire->driverCell_) { + PortDir port_dir = cell->port_dir(portname); + if (port_dir != PD_OUTPUT) { + return; + } else if (wire->driverCell_->port_dir(wire->driverPort_) != PD_OUTPUT) { + // port_dir == PD_OUTPUT + } else { + Detail::bufNormalizeConflict(wire->module, {cell, portname}, wire); + } + } + wire->driverCell_ = cell; + wire->driverPort_ = portname; + } +}; + void RTLIL::Design::bufNormalize(bool enable) { if (!enable) @@ -4062,30 +4090,19 @@ void RTLIL::Design::bufNormalize(bool enable) for (auto module : modules()) { for (auto cell : module->cells()) - for (auto &conn : cell->connections()) { + for (auto [portname, sig] : cell->connections()) { - PortDir port_dir = cell->port_dir(conn.first); - if (port_dir == PD_INPUT || GetSize(conn.second) == 0) + PortDir port_dir = cell->port_dir(portname); + if (port_dir == PD_INPUT || GetSize(sig) == 0) + continue; + if (sig.is_wire()) { + Detail::drive(sig.as_wire(), {cell, portname}); continue; - if (conn.second.is_wire()) { - Wire *wire = conn.second.as_wire(); - if (wire->driverCell_ != nullptr) { - if (port_dir != PD_OUTPUT) { - continue; - } else if (wire->driverCell_->port_dir(wire->driverPort_) != PD_OUTPUT) { - // port_dir == PD_OUTPUT - } else { - log_error("Conflict between %s.%s and %s.%s driving %s in module %s\n", - log_id(cell), log_id(conn.first), - log_id(wire->driverCell_), log_id(wire->driverPort_), - log_id(wire), log_id(module)); - } - } - wire->driverCell_ = cell; - wire->driverPort_ = conn.first; } else { - pair key(cell, conn.first); - module->bufNormQueue.insert(key); + // SigSpec has chunks + // Defer normalization to Module::bufNormalize + CellPort port({cell, portname}); + module->bufNormQueue.insert(port); } } } @@ -4104,36 +4121,20 @@ void RTLIL::Module::bufNormalize() while (GetSize(bufNormQueue) || !connections_.empty()) { - pool> queue; + pool queue; bufNormQueue.swap(queue); SigMap sigmap(this); new_connections({}); - for (auto &key : queue) + for (const auto& [cell, portname] : queue) { - Cell *cell = key.first; - const IdString &portname = key.second; const SigSpec &sig = cell->getPort(portname); if (GetSize(sig) == 0) continue; if (sig.is_wire()) { - Wire *wire = sig.as_wire(); - if (wire->driverCell_) { - PortDir port_dir = cell->port_dir(portname); - if (port_dir != PD_OUTPUT) { - continue; - } else if (wire->driverCell_->port_dir(wire->driverPort_) != PD_OUTPUT) { - // port_dir == PD_OUTPUT - } else { - log_error("Conflict between %s.%s and %s.%s driving %s in module %s\n", - log_id(cell), log_id(portname), - log_id(wire->driverCell_), log_id(wire->driverPort_), - log_id(wire), log_id(this)); - } - } - wire->driverCell_ = cell; - wire->driverPort_ = portname; + log_error("unreachable"); + Detail::drive(sig.as_wire(), {cell, portname}); continue; } @@ -4244,7 +4245,7 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal while (module->design && module->design->flagBufferedNormalized && (pd = port_dir(portname)) != PD_INPUT) { - pair key(this, portname); + CellPort key(this, portname); if (conn_it->second.is_wire()) { Wire *w = conn_it->second.as_wire(); @@ -4267,7 +4268,7 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal Wire *w = signal.as_wire(); if (w->driverCell_ != nullptr) { if (pd == PD_OUTPUT) { - pair other_key(w->driverCell_, w->driverPort_); + CellPort other_key(w->driverCell_, w->driverPort_); module->bufNormQueue.insert(other_key); } else { break; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 365dedcf5..3e42d99c9 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -90,6 +90,7 @@ namespace RTLIL PD_INOUT = 3 }; + struct Detail; struct Const; struct AttrObject; struct NamedObject; @@ -1494,6 +1495,8 @@ struct RTLIL::Design #endif }; +using CellPort = std::pair; + struct RTLIL::Module : public RTLIL::NamedObject { Hasher::hash_t hashidx_; @@ -1547,7 +1550,7 @@ public: std::vector ports; void fixup_ports(); - pool> bufNormQueue; + pool bufNormQueue; void bufNormalize(); template void rewrite_sigspecs(T &functor); @@ -1870,6 +1873,7 @@ protected: friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); RTLIL::Cell *driverCell_ = nullptr; RTLIL::IdString driverPort_; + friend struct Detail; public: // do not simply copy wires @@ -1883,6 +1887,7 @@ public: bool driverKnown() const { return driverCell_ != nullptr; } RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; }; RTLIL::IdString driverPort() const { log_assert(driverCell_); return driverPort_; }; + void drive(Cell* cell); int from_hdl_index(int hdl_index) { int zero_index = hdl_index - start_offset; diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 86d654cc4..144bd8fa2 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -29,8 +29,8 @@ PRIVATE_NAMESPACE_BEGIN static RTLIL::Module *module; static SigMap assign_map; -typedef std::pair sig2driver_entry_t; -static SigSet sig2driver, sig2user; +typedef std::pair CellPort; +static SigSet sig2driver, sig2user; static std::set muxtree_cells; static SigPool sig_at_port; @@ -51,7 +51,7 @@ ret_false: return false; } - std::set cellport_list; + std::set cellport_list; sig2driver.find(sig, cellport_list); for (auto &cellport : cellport_list) { @@ -93,7 +93,7 @@ static bool check_state_users(RTLIL::SigSpec sig) if (sig_at_port.check_any(assign_map(sig))) return false; - std::set cellport_list; + std::set cellport_list; sig2user.find(sig, cellport_list); for (auto &cellport : cellport_list) { RTLIL::Cell *cell = cellport.first; @@ -138,7 +138,7 @@ static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) return; } - std::set cellport_list; + std::set cellport_list; sig2driver.find(RTLIL::SigSpec(wire), cellport_list); for (auto &cellport : cellport_list) @@ -163,7 +163,7 @@ static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) ConstEval ce(wire->module); - std::set cellport_list; + std::set cellport_list; sig2user.find(sig_q, cellport_list); auto sig_q_bits = sig_q.to_sigbit_pool(); @@ -322,12 +322,12 @@ struct FsmDetectPass : public Pass { if (ct.cell_output(cell->type, conn_it.first) || !ct.cell_known(cell->type)) { RTLIL::SigSpec sig = conn_it.second; assign_map.apply(sig); - sig2driver.insert(sig, sig2driver_entry_t(cell, conn_it.first)); + sig2driver.insert(sig, CellPort(cell, conn_it.first)); } if (!ct.cell_known(cell->type) || ct.cell_input(cell->type, conn_it.first)) { RTLIL::SigSpec sig = conn_it.second; assign_map.apply(sig); - sig2user.insert(sig, sig2driver_entry_t(cell, conn_it.first)); + sig2user.insert(sig, CellPort(cell, conn_it.first)); } }