diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 1320937a0..36c0e6ca1 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -617,7 +617,7 @@ struct AigerWriter for (auto wire : module->wires()) { - if (wire->name[0] == '$') + if (!wire->name.isPublic()) continue; SigSpec sig = sigmap(wire); @@ -691,7 +691,7 @@ struct AigerWriter for (auto wire : module->wires()) { - if (!verbose_map && wire->name[0] == '$') + if (!verbose_map && !wire->name.isPublic()) continue; SigSpec sig = sigmap(wire); diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 522929c50..82c471b83 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -681,6 +681,14 @@ struct XAigerWriter void write_map(std::ostream &f) { + return "#" + std::to_string((uint64_t)name.raw()); + } + + void write_map(std::ostream &f, bool refs) + { + if (refs) + f << "refs\n"; + dict input_lines; dict output_lines; diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index d24e4be99..97eb7421e 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -847,7 +847,7 @@ struct Index { int idx = cursor.bitwire_index(*this, bit); if (lits[idx] == Writer::EMPTY_LIT - 1) - log_error("Combinational cycle through %s in %s\n", log_signal(bit), log_id(cursor.leaf_module(*this))); + log_error("Combinational cycle through %s in %s\n", log_signal(bit), cursor.leaf_module(*this)); if (lits[idx] != Writer::EMPTY_LIT) { // literal already assigned return lits[idx]; @@ -1325,6 +1325,13 @@ struct XAigerWriter : AigerWriter { return found->second; } + std::string map_sym(IdString name) const + { + if (map_refs) + return "#" + std::to_string((uint64_t)name.raw()); + return design->twines.str(name); + } + typedef std::pair HierBit; std::vector pos; std::vector pis; @@ -1952,6 +1959,8 @@ struct XAiger2Backend : Backend { writer.map_file.open(map_filename); if (!writer.map_file) log_cmd_error("Failed to open '%s' for writing\n", map_filename); + if (writer.map_refs) + writer.map_file << "refs " << (uint64_t)top->name.ref().raw() << "\n"; } design->bufNormalize(true); diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index ac69bda27..e5eeb5c0a 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -212,7 +212,7 @@ bool is_ff_cell(RTLIL::IdString type) ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr)); } -bool is_internal_cell(RTLIL::IdString type) +bool is_internal_cell(PooledName type) { return !type.isPublic() && !type.begins_with("$paramod"); } @@ -728,6 +728,8 @@ struct CxxrtlWorker { std::string indent; int temporary = 0; + const RTLIL::Design *design = nullptr; + dict sigmaps; dict> mod_memories; pool> writable_memories; @@ -756,7 +758,7 @@ struct CxxrtlWorker { // 1b. Generated identifiers for internal names (beginning with `$`) start with `i_`. // 2. An underscore is escaped with another underscore, i.e. `__`. // 3. Any other non-alnum character is escaped with underscores around its lowercase hex code, e.g. `@` as `_40_`. - std::string mangle_name(RTLIL::IdString name) + std::string mangle_name(PooledName name) { std::string mangled; bool first = true; @@ -786,7 +788,7 @@ struct CxxrtlWorker { return mangled; } - std::string mangle_module_name(RTLIL::IdString name, bool is_blackbox = false) + std::string mangle_module_name(PooledName name, bool is_blackbox = false) { // Class namespace. if (is_blackbox) @@ -794,19 +796,19 @@ struct CxxrtlWorker { return mangle_name(name); } - std::string mangle_memory_name(RTLIL::IdString name) + std::string mangle_memory_name(PooledName name) { // Class member namespace. return "memory_" + mangle_name(name); } - std::string mangle_cell_name(RTLIL::IdString name) + std::string mangle_cell_name(PooledName name) { // Class member namespace. return "cell_" + mangle_name(name); } - std::string mangle_wire_name(RTLIL::IdString name) + std::string mangle_wire_name(PooledName name) { // Class member namespace. return mangle_name(name); @@ -904,7 +906,7 @@ struct CxxrtlWorker { params += ", "; first = false; params += "/*" + param_name + "=*/"; - RTLIL::IdString id_param_name = '\\' + param_name; + IdString id_param_name = cell->module->design->twines.find('\\' + param_name); if (!cell->hasParam(id_param_name)) log_cmd_error("Cell `%s.%s' does not have a parameter `%s', which is required by the templated module `%s'.\n", cell->module, cell, param_name.c_str(), cell_module); @@ -927,7 +929,7 @@ struct CxxrtlWorker { void dump_attrs(const RTLIL::AttrObject *object) { for (auto attr : object->attributes) { - f << indent << "// " << attr.first.str() << ": "; + f << indent << "// " << design->twines.str(attr.first) << ": "; if (attr.second.flags & RTLIL::CONST_FLAG_STRING) { f << attr.second.decode_string(); } else { @@ -1127,7 +1129,7 @@ struct CxxrtlWorker { if (is_cxxrtl_sync_port(cell, conn.first) && !conn.second.empty()) { f << indent; dump_sigspec_lhs(conn.second, for_debug); - f << " = " << mangle(cell) << access << mangle_wire_name(conn.first) << ".curr;\n"; + f << " = " << mangle(cell) << access << mangle_wire_name({design, conn.first}) << ".curr;\n"; } } @@ -1532,7 +1534,7 @@ struct CxxrtlWorker { RTLIL::Module *cell_module = cell->module->design->module(cell->type); log_assert(cell_module != nullptr && cell_module->wire(conn.first)); RTLIL::Wire *cell_module_wire = cell_module->wire(conn.first); - f << indent << mangle(cell) << access << mangle_wire_name(conn.first); + f << indent << mangle(cell) << access << mangle_wire_name({design, conn.first}); if (!is_cxxrtl_blackbox_cell(cell) && wire_types[cell_module_wire].is_buffered()) { buffered_inputs = true; f << ".next"; @@ -1564,7 +1566,7 @@ struct CxxrtlWorker { continue; // fully sync ports are handled in CELL_SYNC nodes f << indent; dump_sigspec_lhs(conn.second); - f << " = " << mangle(cell) << access << mangle_wire_name(conn.first); + f << " = " << mangle(cell) << access << mangle_wire_name({design, conn.first}); // Similarly to how there is no purpose to buffering cell inputs, there is also no purpose to buffering // combinatorial cell outputs in case the cell converges within one cycle. (To convince yourself that // this optimization is valid, consider that, since the cell converged within one cycle, it would not @@ -2296,10 +2298,10 @@ struct CxxrtlWorker { if (!metadata_item.first.isPublic()) continue; if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) { - f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n"; + f << indent << "/* attribute " << design->twines.str(metadata_item.first).substr(1) << " is over 64 bits wide */\n"; continue; } - data += metadata_item.first.str().substr(1) + '\0'; + data += design->twines.str(metadata_item.first).substr(1) + '\0'; // In Yosys, a real is a type of string. if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) { double dvalue = std::stod(metadata_item.second.decode_string()); @@ -2333,10 +2335,10 @@ struct CxxrtlWorker { if (!metadata_item.first.isPublic()) continue; if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) { - f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n"; + f << indent << "/* attribute " << design->twines.str(metadata_item.first).substr(1) << " is over 64 bits wide */\n"; continue; } - f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", "; + f << indent << "{ " << escape_cxx_string(design->twines.str(metadata_item.first).substr(1)) << ", "; // In Yosys, a real is a type of string. if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) { f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint; @@ -2774,9 +2776,10 @@ struct CxxrtlWorker { void dump_design(RTLIL::Design *design) { + this->design = design; RTLIL::Module *top_module = nullptr; std::vector modules; - using Order = IdString::compare_ptr_by_name; + using Order = IdString::compare_ptr_by_name; TopoSort topo_design; for (auto module : design->modules()) { if (!design->selected_module(module)) @@ -2911,6 +2914,7 @@ struct CxxrtlWorker { void analyze_design(RTLIL::Design *design) { + this->design = design; bool has_feedback_arcs = false; bool has_buffered_comb_wires = false; diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 51abc98bd..826bf48e4 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -30,9 +30,9 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#define EDIF_DEF(_id) edif_names(_id.unescape(), true) -#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(_id.unescape(), true, _ren, _bl, _br) -#define EDIF_REF(_id) edif_names(_id.unescape(), false) +#define EDIF_DEF(_id) edif_names(design->twines.unescaped_str(_id), true) +#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(design->twines.unescaped_str(_id), true, _ren, _bl, _br) +#define EDIF_REF(_id) edif_names(design->twines.unescaped_str(_id), false) #define EDIF_DEF_STR(_id) edif_names(RTLIL::unescape_id(_id), true) #define EDIF_REF_STR(_id) edif_names(RTLIL::unescape_id(_id), false) @@ -487,7 +487,7 @@ struct EdifBackend : public Backend { for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1) log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n", - i, module, cell, p.first.unescape(), log_signal(sig[i])); + i, module, cell, design->twines.unescaped_str(p.first), log_signal(sig[i])); else { int member_idx = lsbidx ? i : GetSize(sig)-i-1; auto m = design->module(cell->type); diff --git a/backends/functional/cxx.cc b/backends/functional/cxx.cc index d67bc9143..714e7ab3b 100644 --- a/backends/functional/cxx.cc +++ b/backends/functional/cxx.cc @@ -71,14 +71,14 @@ using CxxWriter = Functional::Writer; struct CxxStruct { std::string name; - dict types; + dict types; CxxScope scope; CxxStruct(std::string name) : name(name) { scope.reserve("fn"); scope.reserve("visit"); } - void insert(IdString name, CxxType type) { + void insert(PooledName name, CxxType type) { scope(name, name); types.insert({name, type}); } @@ -94,7 +94,7 @@ struct CxxStruct { f.print("\t\t}}\n"); f.print("\t}};\n\n"); }; - std::string operator[](IdString field) { + std::string operator[](PooledName field) { return scope(field, field); } }; @@ -151,8 +151,8 @@ template struct CxxPrintVisitor : public Functional::Abstract void arithmetic_shift_right(Node, Node a, Node b) override { print("{}.arithmetic_shift_right({})", a, b); } void mux(Node, Node a, Node b, Node s) override { print("{2}.any() ? {1} : {0}", a, b, s); } void constant(Node, RTLIL::Const const & value) override { print("{}", cxx_const(value)); } - void input(Node, IdString name, IdString kind) override { log_assert(kind == ID($input)); print("input.{}", input_struct[name]); } - void state(Node, IdString name, IdString kind) override { log_assert(kind == ID($state)); print("current_state.{}", state_struct[name]); } + void input(Node self, IdString name, IdString kind) override { log_assert(kind == ID($input)); print("input.{}", input_struct[{self.design, name}]); } + void state(Node self, IdString name, IdString kind) override { log_assert(kind == ID($state)); print("current_state.{}", state_struct[{self.design, name}]); } void memory_read(Node, Node mem, Node addr) override { print("{}.read({})", mem, addr); } void memory_write(Node, Node mem, Node addr, Node data) override { print("{}.write({}, {})", mem, addr, data); } }; diff --git a/backends/functional/smtlib.cc b/backends/functional/smtlib.cc index 128dbda6c..fb97437f7 100644 --- a/backends/functional/smtlib.cc +++ b/backends/functional/smtlib.cc @@ -72,13 +72,13 @@ class SmtStruct { SmtSort sort; std::string accessor; }; - idict field_names; + idict field_names; vector fields; SmtScope &scope; public: std::string name; SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {} - void insert(IdString field_name, SmtSort sort) { + void insert(PooledName field_name, SmtSort sort) { field_names(field_name); auto accessor = scope.unique_name("\\" + name + "_" + field_name.unescape()); fields.emplace_back(Field{sort, accessor}); @@ -105,7 +105,7 @@ public: } } SExpr access(SExpr record, IdString name) { - size_t i = field_names.at(name); + size_t i = field_names.at(PooledName(name)); return list(fields[i].accessor, std::move(record)); } }; diff --git a/backends/functional/smtlib_rosette.cc b/backends/functional/smtlib_rosette.cc index 1adceddd5..c678dbdbd 100644 --- a/backends/functional/smtlib_rosette.cc +++ b/backends/functional/smtlib_rosette.cc @@ -73,14 +73,14 @@ class SmtrStruct { std::string accessor; std::string name; }; - idict field_names; + idict field_names; vector fields; SmtrScope &global_scope; SmtrScope local_scope; public: std::string name; SmtrStruct(std::string name, SmtrScope &scope) : global_scope(scope), local_scope(), name(name) {} - void insert(IdString field_name, SmtrSort sort) { + void insert(PooledName field_name, SmtrSort sort) { field_names(field_name); auto base_name = local_scope.unique_name(field_name); auto accessor = name + "-" + base_name; @@ -111,7 +111,7 @@ public: w.close(); } SExpr access(SExpr record, IdString name) { - size_t i = field_names.at(name); + size_t i = field_names.at(PooledName(name)); return list(fields[i].accessor, std::move(record)); } }; @@ -363,7 +363,7 @@ struct FunctionalSmtrBackend : public Backend { } for (auto module : design->selected_modules()) { - log("Processing module `%s`.\n", module->name.c_str()); + log("Processing module `%s`.\n", module->name); SmtrModule smtr(module, assoc_list_helpers); smtr.write(*f); } diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 1704ba429..587843f50 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -171,18 +171,18 @@ struct IntersynthBackend : public Backend { RTLIL::SigSpec sig = sigmap(port.second); if (sig.size() != 0) { conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); - celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", port.first.unescape()); - node_code += stringf(" %s %s", port.first.unescape(), netname(conntypes_code, celltypes_code, constcells_code, sig)); + celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", design->twines.unescaped_str(port.first)); + node_code += stringf(" %s %s", design->twines.unescaped_str(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig)); } } for (auto ¶m : cell->parameters) { - celltype_code += stringf(" cfg:%d %s", int(param.second.size()), param.first.unescape()); + celltype_code += stringf(" cfg:%d %s", int(param.second.size()), design->twines.unescaped_str(param.first)); if (param.second.size() != 32) { - node_code += stringf(" %s '", param.first.unescape()); + node_code += stringf(" %s '", design->twines.unescaped_str(param.first)); for (int i = param.second.size()-1; i >= 0; i--) node_code += param.second[i] == State::S1 ? "1" : "0"; } else - node_code += stringf(" %s 0x%x", param.first.unescape(), param.second.as_int()); + node_code += stringf(" %s 0x%x", design->twines.unescaped_str(param.first), param.second.as_int()); } celltypes_code.insert(celltype_code + "\n"); diff --git a/backends/jny/jny.cc b/backends/jny/jny.cc index 2f6899f4a..a45d59d3e 100644 --- a/backends/jny/jny.cc +++ b/backends/jny/jny.cc @@ -44,6 +44,8 @@ struct JnyWriter // but for now for the PoC this looks to be sufficient std::unordered_map> _cells{}; + Design *_design = nullptr; + bool _include_connections; bool _include_attributes; bool _include_properties; @@ -120,6 +122,7 @@ struct JnyWriter void write_metadata(Design *design, uint16_t indent_level = 0, std::string invk = "") { log_assert(design != nullptr); + _design = design; design->sort(); @@ -214,7 +217,7 @@ struct JnyWriter void write_cell_conn(const std::pair& sig, uint16_t indent_level = 0) { const auto _indent = gen_indent(indent_level); f << _indent << " {\n"; - f << _indent << " \"name\": \"" << escape_string(sig.first.unescape()) << "\",\n"; + f << _indent << " \"name\": \"" << escape_string(_design->twines.unescaped_str(sig.first)) << "\",\n"; f << _indent << " \"signals\": [\n"; write_sigspec(sig.second, indent_level + 2); @@ -280,7 +283,7 @@ struct JnyWriter f << ",\n"; f << _indent << " {\n"; - f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(con.first.unescape())); + f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(_design->twines.unescaped_str(con.first))); f << _indent << " \"direction\": \""; if (port_cell->input(con.first)) f << "i"; @@ -351,10 +354,10 @@ struct JnyWriter f << stringf(",\n"); const auto param_val = param.second; if (!param_val.empty()) { - f << stringf(" %s\"%s\": ", _indent, escape_string(param.first.unescape())); + f << stringf(" %s\"%s\": ", _indent, escape_string(_design->twines.unescaped_str(param.first))); write_param_val(param_val); } else { - f << stringf(" %s\"%s\": true", _indent, escape_string(param.first.unescape())); + f << stringf(" %s\"%s\": true", _indent, escape_string(_design->twines.unescaped_str(param.first))); } first_param = false; diff --git a/backends/json/json.cc b/backends/json/json.cc index 23d18fb15..13e72e834 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -76,7 +76,7 @@ struct JsonWriter string get_name(IdString name) { - return get_string(name.unescape()); + return get_string(design->twines.unescaped_str(name)); } string get_bits(SigSpec sig) @@ -197,7 +197,7 @@ struct JsonWriter continue; f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(c->name)); - f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0"); + f << stringf(" \"hide_name\": %s,\n", c->name.isPublic() ? "0" : "1"); f << stringf(" \"type\": %s,\n", get_name(c->type)); if (aig_mode) { Aig aig(c); @@ -246,7 +246,7 @@ struct JsonWriter continue; f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(it.second->name)); - f << stringf(" \"hide_name\": %s,\n", it.second->name[0] == '$' ? "1" : "0"); + f << stringf(" \"hide_name\": %s,\n", it.second->name.isPublic() ? "0" : "1"); f << stringf(" \"attributes\": {"); write_parameters(it.second->attributes); f << stringf("\n },\n"); @@ -266,7 +266,7 @@ struct JsonWriter continue; f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(w->name)); - f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0"); + f << stringf(" \"hide_name\": %s,\n", w->name.isPublic() ? "0" : "1"); f << stringf(" \"bits\": %s,\n", get_bits(w)); if (w->start_offset) f << stringf(" \"offset\": %d,\n", w->start_offset); @@ -316,13 +316,13 @@ struct JsonWriter f << stringf(" /* %3d */ [ ", node_idx); if (node.portbit >= 0) f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "", - node.portname.unescape(), node.portbit); + design->twines.unescaped_str(node.portname), node.portbit); else if (node.left_parent < 0 && node.right_parent < 0) f << stringf("\"%s\"", node.inverter ? "true" : "false"); else f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent); for (auto &op : node.outports) - f << stringf(", \"%s\", %d", op.first.unescape(), op.second); + f << stringf(", \"%s\", %d", design->twines.unescaped_str(op.first), op.second); f << stringf(" ]"); node_idx++; } diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index 22da071ce..7849a01a2 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -32,13 +32,23 @@ USING_YOSYS_NAMESPACE using namespace RTLIL_BACKEND; YOSYS_NAMESPACE_BEGIN -void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj) +static std::string twine_handle(IdString ref) { - for (const auto& [name, value] : reversed(obj->attributes)) { - f << stringf("%s" "attribute %s ", indent, name); - dump_const(f, value); - f << stringf("\n"); - } + return stringf("%s@%zu", ref.isPublic() ? "$pub" : "$priv", ref.untag().raw()); +} + +static std::string twine_ref(const RTLIL::Design *design, IdString ref, DumpMode mode) +{ + if (mode == DumpMode::Readable || ID::is_static(ref)) + return design->twines.str(ref); + return twine_handle(ref); +} + +static std::string twine_cmt(const RTLIL::Design *design, IdString ref, DumpMode mode) +{ + if (mode != DumpMode::Replayable || ID::is_static(ref)) + return ""; + return stringf(" # %s", design->twines.str(ref).c_str()); } void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint) @@ -103,7 +113,70 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi } } -void RTLIL_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint) +void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj, const RTLIL::Design *design, DumpMode mode) +{ + for (const auto& [name, value] : reversed(obj->attributes)) { + f << stringf("%s" "attribute %s ", indent, twine_ref(design, name, mode)); + dump_const(f, value); + f << stringf("\n"); + } +} + +static void collect_static_twine(IdString ref, pool &out) +{ + if (ref != IdString::Null && ID::is_static(ref)) + out.insert(ref.untag().raw()); +} + +void RTLIL_BACKEND::dump_twines(std::ostream &f, const RTLIL::Design *design) +{ + if (!design || design->twines.size() == 0) + return; + f << stringf("twines\n"); + std::vector ids; + for (IdString id : design->twines.slots()) + ids.push_back(id); + pool statics; + for (IdString id : ids) { + const TwineNode &n = design->twines[id]; + if (n.is_suffix()) + collect_static_twine(n.suffix().prefix, statics); + } + for (size_t value : statics) + ids.push_back(IdString(value)); + std::sort(ids.begin(), ids.end()); + for (IdString id : ids) { + const TwineNode &n = design->twines[id]; + if (n.is_leaf()) { + f << stringf(" leaf %zu ", id.raw()); + dump_const(f, RTLIL::Const(n.leaf())); + f << stringf("\n"); + } else if (n.is_suffix()) { + f << stringf(" suffix %zu %zu ", id.raw(), n.suffix().prefix.raw()); + dump_const(f, RTLIL::Const(n.suffix().tail)); + f << stringf("\n"); + } + } + f << stringf("end\n"); +} + +static std::string sigspec_str(const RTLIL::SigSpec &sig, DumpMode mode) +{ + std::ostringstream ss; + RTLIL_BACKEND::dump_sigspec(ss, sig, true, mode); + return ss.str(); +} + +static void dump_connect(std::ostream &f, const std::string &indent, DumpMode mode, + const std::string &operands, const std::string &readable) +{ + f << indent << "connect " << operands; + if (mode == DumpMode::Replayable && readable != operands) + f << " # " << readable; + f << "\n"; +} + +void RTLIL_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint, DumpMode mode) { if (chunk.wire == NULL) { dump_const(f, chunk.data, chunk.width, chunk.offset, autoint); diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 5f14a2a66..80f9a501d 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -27,7 +27,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -static string spice_id2str(IdString id) +static string spice_id2str(PooledName id) { static const char *escape_chars = "$\\[]()<>="; string s = id.unescape(); @@ -38,9 +38,9 @@ static string spice_id2str(IdString id) return s; } -static string spice_id2str(IdString id, bool use_inames, idict &inums) +static string spice_id2str(PooledName id, bool use_inames, idict &inums) { - if (!use_inames && *id.c_str() == '$') + if (!use_inames && !id.isPublic()) return stringf("%d", inums(id)); return spice_id2str(id); } diff --git a/backends/table/table.cc b/backends/table/table.cc index bbb533965..bd8f6685e 100644 --- a/backends/table/table.cc +++ b/backends/table/table.cc @@ -100,7 +100,7 @@ struct TableBackend : public Backend { *f << module->name.unescape() << "\t"; *f << cell->name.unescape() << "\t"; *f << cell->type.unescape() << "\t"; - *f << conn.first.unescape() << "\t"; + *f << design->twines.unescaped_str(conn.first) << "\t"; if (cell->input(conn.first) && cell->output(conn.first)) *f << "inout" << "\t";