Improved attributes API and handling of "src" attributes
authorClifford Wolf <clifford@clifford.at>
Fri, 24 Apr 2015 20:04:05 +0000 (22:04 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 24 Apr 2015 20:04:05 +0000 (22:04 +0200)
README
kernel/rtlil.cc
kernel/rtlil.h
kernel/yosys.cc
kernel/yosys.h
passes/techmap/simplemap.cc
passes/techmap/techmap.cc

diff --git a/README b/README
index af78a31ca80af5eb8d957e2b64ac948b85790261..3f5e61dd3dc6834b8506c2366a732c888be2d410 100644 (file)
--- 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
+  "<hdl-file-name>:<line-number>" 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
index 2dff53b7bbc469ccb6ccea190f051c8c66b75388..8c0b41d09ba8cb0a711c3a028183a46aad78f4c8 100644 (file)
@@ -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<string> &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<string> &data)
+{
+       pool<string> union_data = get_strpool_attribute(id);
+       union_data.insert(data.begin(), data.end());
+       if (!union_data.empty())
+               set_strpool_attribute(id, union_data);
+}
+
+pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const
+{
+       pool<string> 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)
index 9b9afcee04e594756db20ea3fc470dbc1c7cb0e8..956b303fdaf32e0d12344bac2233019cfeddd86b 100644 (file)
@@ -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<RTLIL::IdString, RTLIL::Const> 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<string> &data);
+       void add_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
+       pool<string> get_strpool_attribute(RTLIL::IdString id) const;
+};
+
 struct RTLIL::SigChunk
 {
        RTLIL::Wire *wire;
@@ -849,18 +861,7 @@ struct RTLIL::Design
        std::vector<RTLIL::Module*> selected_whole_modules_warn() const;
 };
 
-#define RTLIL_ATTRIBUTE_MEMBERS                                \
-       dict<RTLIL::IdString, RTLIL::Const> 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<RTLIL::IdString> avail_parameters;
        dict<RTLIL::IdString, RTLIL::Memory*> memories;
        dict<RTLIL::IdString, RTLIL::Process*> 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<RTLIL::IdString, RTLIL::SigSpec> connections_;
        dict<RTLIL::IdString, RTLIL::Const> 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<RTLIL::CaseRule*> 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<RTLIL::SyncRule*> syncs;
 
index 7494b7e3c74e33b870b14f2a89113b82edf0025b..1d6e7113b289fe6f388e562e5222d9fd3ae154d2 100644 (file)
@@ -209,6 +209,26 @@ std::string next_token(std::string &text, const char *sep, bool long_strings)
        return token;
 }
 
+std::vector<std::string> split_tokens(const std::string &text, const char *sep)
+{
+       std::vector<std::string> 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:
 //
index e442c3e2eb3738ba2b7f54790548ceac9a126659..db8161c5d2ebb826ca0660dc51474e0900f13812 100644 (file)
@@ -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<std::string> 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<void(const std::string&)> process_line = std::function<void(const std::string&)>());
 std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX");
index 9cea5f45df607b80fa2f7e52016a28bf1b629cde..170b7b04f8c759ace534cb79bee15a0e78f1930c 100644 (file)
@@ -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]);
index 46215e9d7986aedee220a4101fb8deebb6c9a525..c404eb9dbb10f6ebbc18559e138a54579247aa94 100644 (file)
@@ -170,7 +170,10 @@ struct TechmapWorker
                }
 
                std::string orig_cell_name;
+               pool<string> 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<IdString, IdString> 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()) {