From 49859393bbddfe9445757f3df0ff573c9072a594 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 24 Apr 2015 22:04:05 +0200 Subject: [PATCH] Improved attributes API and handling of "src" attributes --- README | 5 +++++ kernel/rtlil.cc | 40 ++++++++++++++++++++++++++++++++++++ kernel/rtlil.h | 41 ++++++++++++++++--------------------- kernel/yosys.cc | 20 ++++++++++++++++++ kernel/yosys.h | 1 + passes/techmap/simplemap.cc | 26 +++++++++++++++++++---- passes/techmap/techmap.cc | 13 ++++++++++++ 7 files changed, 119 insertions(+), 27 deletions(-) diff --git a/README b/README index af78a31ca..3f5e61dd3 100644 --- a/README +++ b/README @@ -300,6 +300,11 @@ Verilog Attributes and non-standard features with "-top". Other commands, such as "flatten" and various backends use this attribute to determine the top module. +- The "src" attribute is set on cells and wires created by to the string + ":" by the HDL front-end and is then carried + through the synthesis. When entities are combined, a new |-separated + string is created that contains all the string from the original entities. + - In addition to the (* ... *) attribute syntax, yosys supports the non-standard {* ... *} attribute syntax to set default attributes for everything that comes after the {* ... *} statement. (Reset diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2dff53b7b..8c0b41d09 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -161,6 +161,46 @@ std::string RTLIL::Const::decode_string() const return string; } +void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id) +{ + attributes[id] = RTLIL::Const(1); +} + +bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const +{ + if (attributes.count(id) == 0) + return false; + return attributes.at(id).as_bool(); +} + +void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool &data) +{ + string attrval; + for (auto &s : data) { + if (!attrval.empty()) + attrval += "|"; + attrval += s; + } + attributes[id] = RTLIL::Const(attrval); +} + +void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool &data) +{ + pool union_data = get_strpool_attribute(id); + union_data.insert(data.begin(), data.end()); + if (!union_data.empty()) + set_strpool_attribute(id, union_data); +} + +pool RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const +{ + pool data; + if (attributes.count(id) != 0) + for (auto s : split_tokens(attributes.at(id).decode_string(), "|")) + data.insert(s); + return data; +} + bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const { if (full_selection) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 9b9afcee0..956b303fd 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -53,6 +53,7 @@ namespace RTLIL }; struct Const; + struct AttrObject; struct Selection; struct Monitor; struct Design; @@ -493,6 +494,17 @@ struct RTLIL::Const } }; +struct RTLIL::AttrObject +{ + dict attributes; + + void set_bool_attribute(RTLIL::IdString id); + bool get_bool_attribute(RTLIL::IdString id) const; + void set_strpool_attribute(RTLIL::IdString id, const pool &data); + void add_strpool_attribute(RTLIL::IdString id, const pool &data); + pool get_strpool_attribute(RTLIL::IdString id) const; +}; + struct RTLIL::SigChunk { RTLIL::Wire *wire; @@ -849,18 +861,7 @@ struct RTLIL::Design std::vector selected_whole_modules_warn() const; }; -#define RTLIL_ATTRIBUTE_MEMBERS \ - dict attributes; \ - void set_bool_attribute(RTLIL::IdString id) { \ - attributes[id] = RTLIL::Const(1); \ - } \ - bool get_bool_attribute(RTLIL::IdString id) const { \ - if (attributes.count(id) == 0) \ - return false; \ - return attributes.at(id).as_bool(); \ - } - -struct RTLIL::Module +struct RTLIL::Module : public RTLIL::AttrObject { unsigned int hashidx_; unsigned int hash() const { return hashidx_; } @@ -884,7 +885,6 @@ public: pool avail_parameters; dict memories; dict processes; - RTLIL_ATTRIBUTE_MEMBERS Module(); virtual ~Module(); @@ -1095,7 +1095,7 @@ public: RTLIL::SigBit Oai4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d); }; -struct RTLIL::Wire +struct RTLIL::Wire : public RTLIL::AttrObject { unsigned int hashidx_; unsigned int hash() const { return hashidx_; } @@ -1115,10 +1115,9 @@ public: RTLIL::IdString name; int width, start_offset, port_id; bool port_input, port_output, upto; - RTLIL_ATTRIBUTE_MEMBERS }; -struct RTLIL::Memory +struct RTLIL::Memory : public RTLIL::AttrObject { unsigned int hashidx_; unsigned int hash() const { return hashidx_; } @@ -1127,10 +1126,9 @@ struct RTLIL::Memory RTLIL::IdString name; int width, start_offset, size; - RTLIL_ATTRIBUTE_MEMBERS }; -struct RTLIL::Cell +struct RTLIL::Cell : public RTLIL::AttrObject { unsigned int hashidx_; unsigned int hash() const { return hashidx_; } @@ -1150,7 +1148,6 @@ public: RTLIL::IdString type; dict connections_; dict parameters; - RTLIL_ATTRIBUTE_MEMBERS // access cell ports bool hasPort(RTLIL::IdString portname) const; @@ -1195,10 +1192,9 @@ struct RTLIL::CaseRule RTLIL::CaseRule *clone() const; }; -struct RTLIL::SwitchRule +struct RTLIL::SwitchRule : public RTLIL::AttrObject { RTLIL::SigSpec signal; - RTLIL_ATTRIBUTE_MEMBERS std::vector cases; ~SwitchRule(); @@ -1217,10 +1213,9 @@ struct RTLIL::SyncRule RTLIL::SyncRule *clone() const; }; -struct RTLIL::Process +struct RTLIL::Process : public RTLIL::AttrObject { RTLIL::IdString name; - RTLIL_ATTRIBUTE_MEMBERS RTLIL::CaseRule root_case; std::vector syncs; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 7494b7e3c..1d6e7113b 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -209,6 +209,26 @@ std::string next_token(std::string &text, const char *sep, bool long_strings) return token; } +std::vector split_tokens(const std::string &text, const char *sep) +{ + std::vector tokens; + std::string current_token; + for (char c : text) { + if (strchr(sep, c)) { + if (!current_token.empty()) { + tokens.push_back(current_token); + current_token.clear(); + } + } else + current_token += c; + } + if (!current_token.empty()) { + tokens.push_back(current_token); + current_token.clear(); + } + return tokens; +} + // this is very similar to fnmatch(). the exact rules used by this // function are: // diff --git a/kernel/yosys.h b/kernel/yosys.h index e442c3e2e..db8161c5d 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -205,6 +205,7 @@ std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2)); std::string vstringf(const char *fmt, va_list ap); int readsome(std::istream &f, char *s, int n); std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false); +std::vector split_tokens(const std::string &text, const char *sep = " \t\r\n"); bool patmatch(const char *pattern, const char *string); int run_command(const std::string &command, std::function process_line = std::function()); std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX"); diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 9cea5f45d..170b7b04f 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -35,6 +35,7 @@ void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_a[i]); gate->setPort("\\Y", sig_y[i]); } @@ -65,6 +66,7 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_t[i]); gate->setPort("\\Y", sig_y[i]); } @@ -81,6 +83,7 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_a[i]); gate->setPort("\\B", sig_b[i]); gate->setPort("\\Y", sig_y[i]); @@ -131,6 +134,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) } RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_a[i]); gate->setPort("\\B", sig_a[i+1]); gate->setPort("\\Y", sig_t[i/2]); @@ -143,6 +147,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) if (cell->type == "$reduce_xnor") { RTLIL::SigSpec sig_t = module->addWire(NEW_ID); RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_a); gate->setPort("\\Y", sig_t); last_output_cell = gate; @@ -156,7 +161,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) } } -static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig) +static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell *cell) { while (sig.size() > 1) { @@ -170,6 +175,7 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig) } RTLIL::Cell *gate = module->addCell(NEW_ID, "$_OR_"); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig[i]); gate->setPort("\\B", sig[i+1]); gate->setPort("\\Y", sig_t[i/2]); @@ -185,7 +191,7 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig) void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); - logic_reduce(module, sig_a); + logic_reduce(module, sig_a, cell); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); @@ -198,6 +204,7 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) } RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_a); gate->setPort("\\Y", sig_y); } @@ -205,10 +212,10 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); - logic_reduce(module, sig_a); + logic_reduce(module, sig_a, cell); RTLIL::SigSpec sig_b = cell->getPort("\\B"); - logic_reduce(module, sig_b); + logic_reduce(module, sig_b, cell); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); @@ -226,6 +233,7 @@ void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell) log_assert(!gate_type.empty()); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_a); gate->setPort("\\B", sig_b); gate->setPort("\\Y", sig_y); @@ -241,16 +249,19 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec xor_out = module->addWire(NEW_ID, std::max(GetSize(sig_a), GetSize(sig_b))); RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed); + xor_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); simplemap_bitop(module, xor_cell); module->remove(xor_cell); RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); + reduce_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); simplemap_reduce(module, reduce_cell); module->remove(reduce_cell); if (!is_ne) { RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y); + not_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); simplemap_lognot(module, not_cell); module->remove(not_cell); } @@ -264,6 +275,7 @@ void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, "$_MUX_"); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\A", sig_a[i]); gate->setPort("\\B", sig_b[i]); gate->setPort("\\S", cell->getPort("\\S")); @@ -301,6 +313,7 @@ void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\S", sig_s[i]); gate->setPort("\\R", sig_r[i]); gate->setPort("\\Q", sig_q[i]); @@ -320,6 +333,7 @@ void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\C", sig_clk); gate->setPort("\\D", sig_d[i]); gate->setPort("\\Q", sig_q[i]); @@ -341,6 +355,7 @@ void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\C", sig_clk); gate->setPort("\\E", sig_en); gate->setPort("\\D", sig_d[i]); @@ -365,6 +380,7 @@ void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\C", sig_clk); gate->setPort("\\S", sig_s[i]); gate->setPort("\\R", sig_r[i]); @@ -393,6 +409,7 @@ void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\C", sig_clk); gate->setPort("\\R", sig_rst); gate->setPort("\\D", sig_d[i]); @@ -413,6 +430,7 @@ void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < width; i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); + gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->setPort("\\E", sig_en); gate->setPort("\\D", sig_d[i]); gate->setPort("\\Q", sig_q[i]); diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 46215e9d7..c404eb9db 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -170,7 +170,10 @@ struct TechmapWorker } std::string orig_cell_name; + pool extra_src_attrs; + if (!flatten_mode) + { for (auto &it : tpl->cells_) if (it.first == "\\_TECHMAP_REPLACE_") { orig_cell_name = cell->name.str(); @@ -178,6 +181,9 @@ struct TechmapWorker break; } + extra_src_attrs = cell->get_strpool_attribute("\\src"); + } + dict memory_renames; for (auto &it : tpl->memories) { @@ -189,6 +195,8 @@ struct TechmapWorker m->start_offset = it.second->start_offset; m->size = it.second->size; m->attributes = it.second->attributes; + if (m->attributes.count("\\src")) + m->add_strpool_attribute("\\src", extra_src_attrs); module->memories[m->name] = m; memory_renames[it.first] = m->name; design->select(module, m); @@ -207,6 +215,8 @@ struct TechmapWorker w->port_id = 0; if (it.second->get_bool_attribute("\\_techmap_special_")) w->attributes.clear(); + if (w->attributes.count("\\src")) + w->add_strpool_attribute("\\src", extra_src_attrs); design->select(module, w); } @@ -281,6 +291,9 @@ struct TechmapWorker log_assert(memory_renames.count(memid)); c->setParam("\\MEMID", Const(memory_renames[memid].str())); } + + if (c->attributes.count("\\src")) + c->add_strpool_attribute("\\src", extra_src_attrs); } for (auto &it : tpl->connections()) { -- 2.30.2