mirror of
https://github.com/YosysHQ/yosys.git
synced 2026-10-06 18:13:40 +02:00
backends: trivial twine damage
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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<int, string> input_lines;
|
||||
dict<int, string> output_lines;
|
||||
|
||||
|
||||
@@ -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<SigBit, HierCursor> HierBit;
|
||||
std::vector<HierBit> pos;
|
||||
std::vector<HierBit> 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);
|
||||
|
||||
@@ -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<const RTLIL::Module*, SigMap> sigmaps;
|
||||
dict<const RTLIL::Module*, std::vector<Mem>> mod_memories;
|
||||
pool<std::pair<const RTLIL::Module*, RTLIL::IdString>> 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<RTLIL::Module*> modules;
|
||||
using Order = IdString::compare_ptr_by_name<RTLIL::NamedObject>;
|
||||
using Order = IdString::compare_ptr_by_name<RTLIL::Module>;
|
||||
TopoSort<RTLIL::Module*, Order> 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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -71,14 +71,14 @@ using CxxWriter = Functional::Writer;
|
||||
|
||||
struct CxxStruct {
|
||||
std::string name;
|
||||
dict<IdString, CxxType> types;
|
||||
dict<PooledName, CxxType> types;
|
||||
CxxScope<IdString> 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<class NodePrinter> 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); }
|
||||
};
|
||||
|
||||
@@ -72,13 +72,13 @@ class SmtStruct {
|
||||
SmtSort sort;
|
||||
std::string accessor;
|
||||
};
|
||||
idict<IdString> field_names;
|
||||
idict<PooledName> field_names;
|
||||
vector<Field> 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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,14 +73,14 @@ class SmtrStruct {
|
||||
std::string accessor;
|
||||
std::string name;
|
||||
};
|
||||
idict<IdString> field_names;
|
||||
idict<PooledName> field_names;
|
||||
vector<Field> 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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
+7
-4
@@ -44,6 +44,8 @@ struct JnyWriter
|
||||
// but for now for the PoC this looks to be sufficient
|
||||
std::unordered_map<std::string, std::vector<Cell*>> _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<RTLIL::IdString, RTLIL::SigSpec>& 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;
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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<size_t> &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<IdString> ids;
|
||||
for (IdString id : design->twines.slots())
|
||||
ids.push_back(id);
|
||||
pool<size_t> 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);
|
||||
|
||||
@@ -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<IdString, 1> &inums)
|
||||
static string spice_id2str(PooledName id, bool use_inames, idict<IdString, 1> &inums)
|
||||
{
|
||||
if (!use_inames && *id.c_str() == '$')
|
||||
if (!use_inames && !id.isPublic())
|
||||
return stringf("%d", inums(id));
|
||||
return spice_id2str(id);
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user