Improved attributes API and handling of "src" attributes

This commit is contained in:
Clifford Wolf 2015-04-24 22:04:05 +02:00
parent 687f5a5b12
commit 49859393bb
7 changed files with 119 additions and 27 deletions

5
README
View File

@ -300,6 +300,11 @@ Verilog Attributes and non-standard features
with "-top". Other commands, such as "flatten" and various backends with "-top". Other commands, such as "flatten" and various backends
use this attribute to determine the top module. 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 - In addition to the (* ... *) attribute syntax, yosys supports
the non-standard {* ... *} attribute syntax to set default attributes the non-standard {* ... *} attribute syntax to set default attributes
for everything that comes after the {* ... *} statement. (Reset for everything that comes after the {* ... *} statement. (Reset

View File

@ -161,6 +161,46 @@ std::string RTLIL::Const::decode_string() const
return string; 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 bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const
{ {
if (full_selection) if (full_selection)

View File

@ -53,6 +53,7 @@ namespace RTLIL
}; };
struct Const; struct Const;
struct AttrObject;
struct Selection; struct Selection;
struct Monitor; struct Monitor;
struct Design; 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 struct RTLIL::SigChunk
{ {
RTLIL::Wire *wire; RTLIL::Wire *wire;
@ -849,18 +861,7 @@ struct RTLIL::Design
std::vector<RTLIL::Module*> selected_whole_modules_warn() const; std::vector<RTLIL::Module*> selected_whole_modules_warn() const;
}; };
#define RTLIL_ATTRIBUTE_MEMBERS \ struct RTLIL::Module : public RTLIL::AttrObject
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
{ {
unsigned int hashidx_; unsigned int hashidx_;
unsigned int hash() const { return hashidx_; } unsigned int hash() const { return hashidx_; }
@ -884,7 +885,6 @@ public:
pool<RTLIL::IdString> avail_parameters; pool<RTLIL::IdString> avail_parameters;
dict<RTLIL::IdString, RTLIL::Memory*> memories; dict<RTLIL::IdString, RTLIL::Memory*> memories;
dict<RTLIL::IdString, RTLIL::Process*> processes; dict<RTLIL::IdString, RTLIL::Process*> processes;
RTLIL_ATTRIBUTE_MEMBERS
Module(); Module();
virtual ~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); 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 hashidx_;
unsigned int hash() const { return hashidx_; } unsigned int hash() const { return hashidx_; }
@ -1115,10 +1115,9 @@ public:
RTLIL::IdString name; RTLIL::IdString name;
int width, start_offset, port_id; int width, start_offset, port_id;
bool port_input, port_output, upto; bool port_input, port_output, upto;
RTLIL_ATTRIBUTE_MEMBERS
}; };
struct RTLIL::Memory struct RTLIL::Memory : public RTLIL::AttrObject
{ {
unsigned int hashidx_; unsigned int hashidx_;
unsigned int hash() const { return hashidx_; } unsigned int hash() const { return hashidx_; }
@ -1127,10 +1126,9 @@ struct RTLIL::Memory
RTLIL::IdString name; RTLIL::IdString name;
int width, start_offset, size; int width, start_offset, size;
RTLIL_ATTRIBUTE_MEMBERS
}; };
struct RTLIL::Cell struct RTLIL::Cell : public RTLIL::AttrObject
{ {
unsigned int hashidx_; unsigned int hashidx_;
unsigned int hash() const { return hashidx_; } unsigned int hash() const { return hashidx_; }
@ -1150,7 +1148,6 @@ public:
RTLIL::IdString type; RTLIL::IdString type;
dict<RTLIL::IdString, RTLIL::SigSpec> connections_; dict<RTLIL::IdString, RTLIL::SigSpec> connections_;
dict<RTLIL::IdString, RTLIL::Const> parameters; dict<RTLIL::IdString, RTLIL::Const> parameters;
RTLIL_ATTRIBUTE_MEMBERS
// access cell ports // access cell ports
bool hasPort(RTLIL::IdString portname) const; bool hasPort(RTLIL::IdString portname) const;
@ -1195,10 +1192,9 @@ struct RTLIL::CaseRule
RTLIL::CaseRule *clone() const; RTLIL::CaseRule *clone() const;
}; };
struct RTLIL::SwitchRule struct RTLIL::SwitchRule : public RTLIL::AttrObject
{ {
RTLIL::SigSpec signal; RTLIL::SigSpec signal;
RTLIL_ATTRIBUTE_MEMBERS
std::vector<RTLIL::CaseRule*> cases; std::vector<RTLIL::CaseRule*> cases;
~SwitchRule(); ~SwitchRule();
@ -1217,10 +1213,9 @@ struct RTLIL::SyncRule
RTLIL::SyncRule *clone() const; RTLIL::SyncRule *clone() const;
}; };
struct RTLIL::Process struct RTLIL::Process : public RTLIL::AttrObject
{ {
RTLIL::IdString name; RTLIL::IdString name;
RTLIL_ATTRIBUTE_MEMBERS
RTLIL::CaseRule root_case; RTLIL::CaseRule root_case;
std::vector<RTLIL::SyncRule*> syncs; std::vector<RTLIL::SyncRule*> syncs;

View File

@ -209,6 +209,26 @@ std::string next_token(std::string &text, const char *sep, bool long_strings)
return token; 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 // this is very similar to fnmatch(). the exact rules used by this
// function are: // function are:
// //

View 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); std::string vstringf(const char *fmt, va_list ap);
int readsome(std::istream &f, char *s, int n); 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::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); 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&)>()); 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"); std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX");

View File

@ -35,6 +35,7 @@ void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
for (int i = 0; i < GetSize(sig_y); i++) { for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); 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("\\A", sig_a[i]);
gate->setPort("\\Y", sig_y[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++) { for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); 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("\\A", sig_t[i]);
gate->setPort("\\Y", sig_y[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++) { for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); 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("\\A", sig_a[i]);
gate->setPort("\\B", sig_b[i]); gate->setPort("\\B", sig_b[i]);
gate->setPort("\\Y", sig_y[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); 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("\\A", sig_a[i]);
gate->setPort("\\B", sig_a[i+1]); gate->setPort("\\B", sig_a[i+1]);
gate->setPort("\\Y", sig_t[i/2]); 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") { if (cell->type == "$reduce_xnor") {
RTLIL::SigSpec sig_t = module->addWire(NEW_ID); RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); 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("\\A", sig_a);
gate->setPort("\\Y", sig_t); gate->setPort("\\Y", sig_t);
last_output_cell = gate; 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) 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_"); 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("\\A", sig[i]);
gate->setPort("\\B", sig[i+1]); gate->setPort("\\B", sig[i+1]);
gate->setPort("\\Y", sig_t[i/2]); 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) void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); 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"); 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_"); 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("\\A", sig_a);
gate->setPort("\\Y", sig_y); 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) void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); 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"); 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"); 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()); log_assert(!gate_type.empty());
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); 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("\\A", sig_a);
gate->setPort("\\B", sig_b); gate->setPort("\\B", sig_b);
gate->setPort("\\Y", sig_y); 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::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); 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); simplemap_bitop(module, xor_cell);
module->remove(xor_cell); module->remove(xor_cell);
RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID);
RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); 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); simplemap_reduce(module, reduce_cell);
module->remove(reduce_cell); module->remove(reduce_cell);
if (!is_ne) { if (!is_ne) {
RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y); 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); simplemap_lognot(module, not_cell);
module->remove(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++) { for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_MUX_"); 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("\\A", sig_a[i]);
gate->setPort("\\B", sig_b[i]); gate->setPort("\\B", sig_b[i]);
gate->setPort("\\S", cell->getPort("\\S")); 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++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); 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("\\S", sig_s[i]);
gate->setPort("\\R", sig_r[i]); gate->setPort("\\R", sig_r[i]);
gate->setPort("\\Q", sig_q[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++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); 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("\\C", sig_clk);
gate->setPort("\\D", sig_d[i]); gate->setPort("\\D", sig_d[i]);
gate->setPort("\\Q", sig_q[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++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); 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("\\C", sig_clk);
gate->setPort("\\E", sig_en); gate->setPort("\\E", sig_en);
gate->setPort("\\D", sig_d[i]); 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++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); 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("\\C", sig_clk);
gate->setPort("\\S", sig_s[i]); gate->setPort("\\S", sig_s[i]);
gate->setPort("\\R", sig_r[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++) { 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); 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("\\C", sig_clk);
gate->setPort("\\R", sig_rst); gate->setPort("\\R", sig_rst);
gate->setPort("\\D", sig_d[i]); 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++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); 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("\\E", sig_en);
gate->setPort("\\D", sig_d[i]); gate->setPort("\\D", sig_d[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort("\\Q", sig_q[i]);

View File

@ -170,7 +170,10 @@ struct TechmapWorker
} }
std::string orig_cell_name; std::string orig_cell_name;
pool<string> extra_src_attrs;
if (!flatten_mode) if (!flatten_mode)
{
for (auto &it : tpl->cells_) for (auto &it : tpl->cells_)
if (it.first == "\\_TECHMAP_REPLACE_") { if (it.first == "\\_TECHMAP_REPLACE_") {
orig_cell_name = cell->name.str(); orig_cell_name = cell->name.str();
@ -178,6 +181,9 @@ struct TechmapWorker
break; break;
} }
extra_src_attrs = cell->get_strpool_attribute("\\src");
}
dict<IdString, IdString> memory_renames; dict<IdString, IdString> memory_renames;
for (auto &it : tpl->memories) { for (auto &it : tpl->memories) {
@ -189,6 +195,8 @@ struct TechmapWorker
m->start_offset = it.second->start_offset; m->start_offset = it.second->start_offset;
m->size = it.second->size; m->size = it.second->size;
m->attributes = it.second->attributes; m->attributes = it.second->attributes;
if (m->attributes.count("\\src"))
m->add_strpool_attribute("\\src", extra_src_attrs);
module->memories[m->name] = m; module->memories[m->name] = m;
memory_renames[it.first] = m->name; memory_renames[it.first] = m->name;
design->select(module, m); design->select(module, m);
@ -207,6 +215,8 @@ struct TechmapWorker
w->port_id = 0; w->port_id = 0;
if (it.second->get_bool_attribute("\\_techmap_special_")) if (it.second->get_bool_attribute("\\_techmap_special_"))
w->attributes.clear(); w->attributes.clear();
if (w->attributes.count("\\src"))
w->add_strpool_attribute("\\src", extra_src_attrs);
design->select(module, w); design->select(module, w);
} }
@ -281,6 +291,9 @@ struct TechmapWorker
log_assert(memory_renames.count(memid)); log_assert(memory_renames.count(memid));
c->setParam("\\MEMID", Const(memory_renames[memid].str())); 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()) { for (auto &it : tpl->connections()) {