diff --git a/Makefile b/Makefile index 0f0a7d77d..8547acb11 100644 --- a/Makefile +++ b/Makefile @@ -566,6 +566,7 @@ $(eval $(call add_include_file,kernel/celledges.h)) $(eval $(call add_include_file,kernel/celltypes.h)) $(eval $(call add_include_file,kernel/consteval.h)) $(eval $(call add_include_file,kernel/constids.inc)) +$(eval $(call add_include_file,kernel/compat.h)) $(eval $(call add_include_file,kernel/cost.h)) $(eval $(call add_include_file,kernel/ff.h)) $(eval $(call add_include_file,kernel/ffinit.h)) @@ -606,7 +607,7 @@ $(eval $(call add_include_file,backends/rtlil/rtlil_backend.h)) # See -DTRACY_ENABLE OBJS += tracy/public/TracyClient.o -OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o +OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o kernel/compat.o OBJS += kernel/binding.o OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o ifeq ($(ENABLE_ZLIB),1) diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index 574eb3aaa..fa54e035f 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -165,7 +165,7 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: f << stringf("\n"); } f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); - for (auto &it : cell->parameters) { + for (auto &&it : cell->parameters) { f << stringf("%s parameter%s%s %s ", indent.c_str(), (it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", (it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "", diff --git a/kernel/compat.h b/kernel/compat.h index 197550942..c6ea3f7f7 100644 --- a/kernel/compat.h +++ b/kernel/compat.h @@ -2,5 +2,11 @@ #ifndef COMPAT_H #define COMPAT_H + +YOSYS_NAMESPACE_BEGIN + dict cell_to_mod_params (const RTLIL::Cell::FakeParams& cell_params); + +YOSYS_NAMESPACE_END + #endif diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 635bc8fd8..df99ad40e 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3525,9 +3525,9 @@ const RTLIL::SigSpec &RTLIL::Cell::getPort(const RTLIL::IdString &portname) cons throw std::out_of_range("Cell::setPort()"); } } -const RTLIL::SigSpec &RTLIL::Cell::getPort(const RTLIL::IdString &portname) { +RTLIL::SigSpec &RTLIL::Cell::getMutPort(const RTLIL::IdString &portname) { if (is_legacy()) - return legacy->getPort(portname); + return legacy->connections_[portname]; if (type == ID($not)) { if (portname == ID::A) { @@ -3562,24 +3562,6 @@ void RTLIL::Cell::setParam(const RTLIL::IdString ¶mname, RTLIL::Const value) } } -// // TODO autogen -// const RTLIL::Const RTLIL::Cell::getParam(const RTLIL::IdString ¶mname) const { -// if (is_legacy()) -// return legacy->getParam(paramname); - -// if (type == ID($not)) { -// if (paramname == ID::A_WIDTH) { -// return RTLIL::Const(not_.a_width); -// } else if (paramname == ID::Y_WIDTH) { -// return RTLIL::Const(not_.y_width); -// } else { -// throw std::out_of_range("Cell::getParam()"); -// } -// } else { -// throw std::out_of_range("Cell::getParam()"); -// } -// } - const RTLIL::Const& RTLIL::Cell::getParam(const RTLIL::IdString ¶mname) const { if (is_legacy()) return legacy->getParam(paramname); @@ -3597,23 +3579,22 @@ const RTLIL::Const& RTLIL::Cell::getParam(const RTLIL::IdString ¶mname) cons } } -// // Compatibility layer. Avoid using it -// inline RTLIL::Const &RTLIL::Cell::getParam(const RTLIL::IdString& paramname) const -// { -// if (is_legacy()) { -// return legacy->getParam(paramname); -// } else { -// // TODO auto-generate this -// if (type == ID($not)) { -// if (paramname == ID::A_WIDTH) { -// return RTLIL::Const(not_.a_width); -// // ...else if... -// } else { -// throw std::out_of_range("Cell::getParam()"); -// } -// } -// } -// } +RTLIL::Const& RTLIL::Cell::getMutParam(const RTLIL::IdString ¶mname) { + if (is_legacy()) + return legacy->parameters[paramname]; + + if (type == ID($not)) { + if (paramname == ID::A_WIDTH) { + return not_.a_width; + } else if (paramname == ID::Y_WIDTH) { + return not_.y_width; + } else { + throw std::out_of_range("Cell::getParam()"); + } + } else { + throw std::out_of_range("Cell::getParam()"); + } +} RTLIL::OldCell::OldCell() : module(nullptr) { @@ -4256,11 +4237,58 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec other->check(); } +void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec &other) const +{ + log_assert(width_ == other.width_); + log_assert(pattern.width_ == with.width_); + + pattern.unpack(); + with.unpack(); + unpack(); + other.unpack(); + + dict pattern_to_with; + for (int i = 0; i < GetSize(pattern.bits_); i++) { + if (pattern.bits_[i].wire != NULL) { + pattern_to_with.emplace(pattern.bits_[i], i); + } + } + + for (int j = 0; j < GetSize(bits_); j++) { + auto it = pattern_to_with.find(bits_[j]); + if (it != pattern_to_with.end()) { + other.bits_[j] = with.bits_[it->second]; + } + } + + other.check(); +} + void RTLIL::SigSpec::replace(const dict &rules) { replace(rules, this); } +// TODO is this one even used? +void RTLIL::SigSpec::replace(const dict &rules, RTLIL::SigSpec &other) const +{ + cover("kernel.rtlil.sigspec.replace_dict"); + + log_assert(width_ == other.width_); + + if (rules.empty()) return; + unpack(); + other.unpack(); + + for (int i = 0; i < GetSize(bits_); i++) { + auto it = rules.find(bits_[i]); + if (it != rules.end()) + other.bits_[i] = it->second; + } + + other.check(); +} + void RTLIL::SigSpec::replace(const dict &rules, RTLIL::SigSpec *other) const { cover("kernel.rtlil.sigspec.replace_dict"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 882197872..00740c030 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -911,9 +911,11 @@ public: void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with); void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const; + void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec &other) const; void replace(const dict &rules); void replace(const dict &rules, RTLIL::SigSpec *other) const; + void replace(const dict &rules, RTLIL::SigSpec &other) const; void replace(const std::map &rules); void replace(const std::map &rules, RTLIL::SigSpec *other) const; @@ -1683,8 +1685,26 @@ public: // Watch out! This is different semantics than what dict has! // but we rely on RTLIL::Cell always being constructed correctly // since its layout is fixed as defined by InternalOldCellChecker - RTLIL::Const operator[](RTLIL::IdString name) { - return parent->getParam(name); + RTLIL::Const& operator[](RTLIL::IdString name) { + return parent->getMutParam(name); + } + bool operator==(const FakeParams& other) const { + auto this_it = this->begin(); + auto other_it = other.begin(); + while (this_it != this->end() && other_it != other.end()) { + if (*this_it != *other_it) + return false; + ++this_it; + ++other_it; + } + if (this_it != this->end() || other_it != other.end()) { + // One has more params than the other + return false; + } + return true; + } + bool operator!=(const FakeParams& other) const { + return !operator==(other); } int count(RTLIL::IdString name) const { try { @@ -1712,6 +1732,8 @@ public: } // The need for this function implies setPort will be used on incompat types void erase(const RTLIL::IdString& paramname) { (void)paramname; } + // The need for this function implies setPort will be used on incompat types + void clear() {} // AAA class iterator { typedef std::bidirectional_iterator_tag iterator_category; @@ -1747,7 +1769,7 @@ public: } else if (parent->type == ID($not)) { return parent->not_.parameters()[position]; } else { - throw std::out_of_range("FakeParams.iterator::operator*()"); + throw std::out_of_range("FakeParams::iterator::operator*()"); } } // std::pair operator->() { return operator*(); } @@ -1766,7 +1788,7 @@ public: } else if (parent->type == ID($not)) { return parent->not_.parameters()[position]; } else { - throw std::out_of_range("FakeParams.iterator::operator*() const"); + throw std::out_of_range("FakeParams::iterator::operator*() const"); } } }; @@ -1789,7 +1811,7 @@ public: } else if (parent->type == ID($not)) { return iterator(parent, parent->not_.connections().size()); } else { - throw std::out_of_range("FakeParams.iterator::end()"); + throw std::out_of_range("FakeParams::iterator::end()"); } } // AAA CONST ITERATOR @@ -1827,7 +1849,7 @@ public: } else if (parent->type == ID($not)) { return parent->not_.parameters()[position]; } else { - throw std::out_of_range("FakeConns.const_iterator::operator*() const"); + throw std::out_of_range("FakeParams::const_iterator::operator*() const"); } } }; @@ -1860,10 +1882,10 @@ public: // Watch out! This is different semantics than what dict has! // but we rely on RTLIL::Cell always being constructed correctly // since its layout is fixed as defined by InternalOldCellChecker - RTLIL::SigSpec operator[](RTLIL::IdString portname) { - return parent->getPort(portname); + RTLIL::SigSpec& operator[](RTLIL::IdString portname) { + return parent->getMutPort(portname); } - int count(RTLIL::IdString portname) { + int count(RTLIL::IdString portname) const { try { parent->getPort(portname); } catch (const std::out_of_range& e) { @@ -1884,6 +1906,10 @@ public: throw std::out_of_range("FakeConns::size()"); } } + // The need for this function implies setPort will be used on incompat types + void erase(const RTLIL::IdString& portname) { (void)portname; } + // The need for this function implies setPort will be used on incompat types + void clear() {} bool empty() { return !size(); } @@ -1923,7 +1949,7 @@ public: } else if (parent->type == ID($not)) { return parent->not_.connections()[position]; } else { - throw std::out_of_range("FakeConns.iterator::operator*()"); + throw std::out_of_range("FakeConns::iterator::operator*()"); } } // std::pair operator->() { return operator*(); } @@ -1943,7 +1969,7 @@ public: } else if (parent->type == ID($not)) { return parent->not_.connections()[position]; } else { - throw std::out_of_range("FakeConns.iterator::operator*() const"); + throw std::out_of_range("FakeConns::iterator::operator*() const"); } } }; @@ -1966,7 +1992,7 @@ public: } else if (parent->type == ID($not)) { return iterator(parent, parent->not_.connections().size()); } else { - throw std::out_of_range("FakeConns.iterator::end()"); + throw std::out_of_range("FakeConns::iterator::end()"); } } // AAA CONST ITERATOR @@ -2004,7 +2030,7 @@ public: } else if (parent->type == ID($not)) { return parent->not_.connections()[position]; } else { - throw std::out_of_range("FakeConns.const_iterator::operator*() const"); + throw std::out_of_range("FakeConns::const_iterator::operator*() const"); } } }; @@ -2072,7 +2098,7 @@ public: void setPort(const RTLIL::IdString &portname, RTLIL::SigSpec signal); // TODO is this reasonable at all? const RTLIL::SigSpec &getPort(const RTLIL::IdString &portname) const; - const RTLIL::SigSpec &getPort(const RTLIL::IdString &portname); + RTLIL::SigSpec &getMutPort(const RTLIL::IdString &portname); bool hasPort(const RTLIL::IdString &portname) { return connections_.count(portname); } @@ -2081,8 +2107,7 @@ public: void setParam(const RTLIL::IdString ¶mname, RTLIL::Const value); // TODO is this reasonable at all? const RTLIL::Const& getParam(const RTLIL::IdString ¶mname) const; - // const RTLIL::Const& getParam(const RTLIL::IdString ¶mname); - RTLIL::Const& getParam(const RTLIL::IdString ¶mname); + RTLIL::Const& getMutParam(const RTLIL::IdString ¶mname); bool hasParam(const RTLIL::IdString ¶mname) { return parameters.count(paramname); } diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc index 7a4202bd6..4202e6412 100644 --- a/passes/cmds/sta.cc +++ b/passes/cmds/sta.cc @@ -21,6 +21,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/timinginfo.h" +#include "kernel/compat.h" #include USING_YOSYS_NAMESPACE @@ -74,7 +75,7 @@ struct StaWorker continue; } - IdString derived_type = inst_module->derive(design, cell->parameters); + IdString derived_type = inst_module->derive(design, cell_to_mod_params(cell->parameters)); inst_module = design->module(derived_type); log_assert(inst_module); diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc index 9d87e203a..4b737d728 100644 --- a/passes/equiv/equiv_struct.cc +++ b/passes/equiv/equiv_struct.cc @@ -162,7 +162,7 @@ struct EquivStructWorker Cell *cell = module->cell(cell_name); key.type = cell->type; - for (auto &it : cell->parameters) + for (auto &&it : cell->parameters) key.parameters.push_back(it); std::sort(key.parameters.begin(), key.parameters.end()); diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index 96bc032ad..c499a8488 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -395,7 +395,8 @@ static void extract_fsm(RTLIL::Wire *wire) RTLIL::SigSpec port_sig = assign_map(cell->getPort(cellport.second)); RTLIL::SigSpec unconn_sig = port_sig.extract(ctrl_out); RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%d", autoidx++), unconn_sig.size()); - port_sig.replace(unconn_sig, RTLIL::SigSpec(unconn_wire), &cell->connections_[cellport.second]); + auto &x = cell->connections_[cellport.second]; + port_sig.replace(unconn_sig, RTLIL::SigSpec(unconn_wire), x); } } diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h index 97371efab..21de73153 100644 --- a/passes/fsm/fsmdata.h +++ b/passes/fsm/fsmdata.h @@ -48,7 +48,8 @@ struct FsmData cell->parameters[ID::STATE_TABLE] = RTLIL::Const(); for (int i = 0; i < int(state_table.size()); i++) { - std::vector &bits_table = cell->parameters[ID::STATE_TABLE].bits; + auto thing = cell->parameters[ID::STATE_TABLE]; + std::vector &bits_table = thing.bits; std::vector &bits_state = state_table[i].bits; bits_table.insert(bits_table.end(), bits_state.begin(), bits_state.end()); } diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 43fad8692..69382dc17 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -19,6 +19,7 @@ */ #include "kernel/yosys.h" +#include "kernel/compat.h" #include "frontends/verific/verific.h" #include #include @@ -69,7 +70,7 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, portnames.insert(conn.first); portwidths[conn.first] = max(portwidths[conn.first], conn.second.size()); } - for (auto ¶ : cell->parameters) + for (auto &¶ : cell->parameters) parameters.insert(para.first); } @@ -334,7 +335,7 @@ RTLIL::Module *get_module(RTLIL::Design &design, std::string cell_type = cell.type.str(); RTLIL::Module *abs_mod = design.module("$abstract" + cell_type); if (abs_mod) { - cell.type = abs_mod->derive(&design, cell.parameters); + cell.type = abs_mod->derive(&design, cell_to_mod_params(cell.parameters)); cell.parameters.clear(); RTLIL::Module *mod = design.module(cell.type); log_assert(mod); @@ -418,7 +419,7 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI log_id(conn.first)); } } - for (auto ¶m : cell.parameters) { + for (auto param : cell.parameters) { if (read_id_num(param.first, &id)) { if (id <= 0 || id > GetSize(mod.avail_parameters)) log_error("Module `%s' referenced in module `%s' in cell `%s' " @@ -528,7 +529,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check } cell->type = mod->derive(design, - cell->parameters, + cell_to_mod_params(cell->parameters), if_expander.interfaces_to_add_to_submodule, if_expander.modports_used_in_submodule); cell->parameters.clear(); @@ -1237,7 +1238,7 @@ struct HierarchyPass : public Pass { // Need accurate port widths for error checking; so must derive blackboxes with dynamic port widths if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute(ID::dynports)) { - IdString new_m_name = m->derive(design, cell->parameters, true); + IdString new_m_name = m->derive(design, cell_to_mod_params(cell->parameters), true); if (new_m_name.empty()) continue; if (new_m_name != m->name) { @@ -1420,7 +1421,7 @@ struct HierarchyPass : public Pass { continue; if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute(ID::dynports)) { - IdString new_m_name = m->derive(design, cell->parameters, true); + IdString new_m_name = m->derive(design, cell_to_mod_params(cell->parameters), true); if (new_m_name.empty()) continue; if (new_m_name != m->name) { diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 8a63c2a07..2341e779a 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -208,7 +208,7 @@ struct SubmodWorker for (RTLIL::Cell *cell : submod.cells) { RTLIL::Cell *new_cell = new_mod->addCell(cell->name, cell); - for (auto &conn : new_cell->connections_) + for (auto conn : new_cell->connections_) for (auto &bit : conn.second) if (bit.wire != nullptr) { log_assert(wire_flags.count(bit.wire) > 0); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index c9fd56ac1..5f9491cb4 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -140,7 +140,7 @@ struct OptMergeWorker hash_conn_strings.push_back(s + "\n"); } - for (auto &it : cell->parameters) + for (auto &&it : cell->parameters) hash_conn_strings.push_back("P " + it.first.str() + "=" + it.second.as_string() + "\n"); std::sort(hash_conn_strings.begin(), hash_conn_strings.end()); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index a2c74dd26..fb350ad1e 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -23,6 +23,7 @@ #include "kernel/utils.h" #include "kernel/celltypes.h" #include "kernel/timinginfo.h" +#include "kernel/compat.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -113,7 +114,7 @@ void check(RTLIL::Design *design, bool dff_mode) // but not its existence) if (!inst_module->has_attribute(ID::abc9_flop)) continue; - derived_type = inst_module->derive(design, cell->parameters); + derived_type = inst_module->derive(design, cell_to_mod_params(cell->parameters)); derived_module = design->module(derived_type); log_assert(derived_module); } @@ -170,7 +171,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) derived_module = inst_module; } else { - derived_type = inst_module->derive(design, cell->parameters); + derived_type = inst_module->derive(design, cell_to_mod_params(cell->parameters)); derived_module = design->module(derived_type); unused_derived.insert(derived_type); }