aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/aiger/aigerparse.cc60
-rw-r--r--frontends/ast/ast.cc198
-rw-r--r--frontends/ast/ast.h8
-rw-r--r--frontends/ast/genrtlil.cc346
-rw-r--r--frontends/ast/simplify.cc180
-rw-r--r--frontends/blif/blifparse.cc64
-rw-r--r--frontends/liberty/liberty.cc152
-rw-r--r--frontends/rpc/rpc_frontend.cc4
-rw-r--r--frontends/verific/verific.cc98
-rw-r--r--frontends/verilog/Makefile.inc2
-rw-r--r--frontends/verilog/const2ast.cc3
-rw-r--r--frontends/verilog/preproc.cc620
-rw-r--r--frontends/verilog/preproc.h77
-rw-r--r--frontends/verilog/verilog_frontend.cc47
-rw-r--r--frontends/verilog/verilog_frontend.h11
-rw-r--r--frontends/verilog/verilog_lexer.l72
-rw-r--r--frontends/verilog/verilog_parser.y302
17 files changed, 1463 insertions, 781 deletions
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index a42569301..cbce0c990 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -117,7 +117,7 @@ struct ConstEvalAig
sig2deps[output].insert(output);
RTLIL::Cell *cell = sig2driver.at(output);
- RTLIL::SigBit sig_a = cell->getPort("\\A");
+ RTLIL::SigBit sig_a = cell->getPort(ID::A);
sig2deps[sig_a].reserve(sig2deps[sig_a].size() + sig2deps[output].size()); // Reserve so that any invalidation
// that may occur does so here, and
// not mid insertion (below)
@@ -125,8 +125,8 @@ struct ConstEvalAig
if (!inputs.count(sig_a))
compute_deps(sig_a, inputs);
- if (cell->type == "$_AND_") {
- RTLIL::SigSpec sig_b = cell->getPort("\\B");
+ if (cell->type == ID($_AND_)) {
+ RTLIL::SigSpec sig_b = cell->getPort(ID::B);
sig2deps[sig_b].reserve(sig2deps[sig_b].size() + sig2deps[output].size()); // Reserve so that any invalidation
// that may occur does so here, and
// not mid insertion (below)
@@ -135,34 +135,34 @@ struct ConstEvalAig
if (!inputs.count(sig_b))
compute_deps(sig_b, inputs);
}
- else if (cell->type == "$_NOT_") {
+ else if (cell->type == ID($_NOT_)) {
}
else log_abort();
}
bool eval(RTLIL::Cell *cell)
{
- RTLIL::SigBit sig_y = cell->getPort("\\Y");
+ RTLIL::SigBit sig_y = cell->getPort(ID::Y);
if (values_map.count(sig_y))
return true;
- RTLIL::SigBit sig_a = cell->getPort("\\A");
+ RTLIL::SigBit sig_a = cell->getPort(ID::A);
if (!eval(sig_a))
return false;
RTLIL::State eval_ret = RTLIL::Sx;
- if (cell->type == "$_NOT_") {
+ if (cell->type == ID($_NOT_)) {
if (sig_a == State::S0) eval_ret = State::S1;
else if (sig_a == State::S1) eval_ret = State::S0;
}
- else if (cell->type == "$_AND_") {
+ else if (cell->type == ID($_AND_)) {
if (sig_a == State::S0) {
eval_ret = State::S0;
goto eval_end;
}
{
- RTLIL::SigBit sig_b = cell->getPort("\\B");
+ RTLIL::SigBit sig_b = cell->getPort(ID::B);
if (!eval(sig_b))
return false;
if (sig_b == State::S0) {
@@ -444,7 +444,7 @@ void AigerReader::parse_xaiger()
}
}
else if (c == 'r') {
- uint32_t dataSize = parse_xaiger_literal(f);
+ uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
flopNum = parse_xaiger_literal(f);
log_debug("flopNum = %u\n", flopNum);
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
@@ -478,9 +478,9 @@ void AigerReader::parse_xaiger()
log_assert(boxUniqueId > 0);
uint32_t oldBoxNum = parse_xaiger_literal(f);
RTLIL::Cell* cell = module->addCell(stringf("$box%u", oldBoxNum), stringf("$__boxid%u", boxUniqueId));
- cell->setPort("\\i", SigSpec(State::S0, boxInputs));
- cell->setPort("\\o", SigSpec(State::S0, boxOutputs));
- cell->attributes["\\abc9_box_seq"] = oldBoxNum;
+ cell->setPort(ID(i), SigSpec(State::S0, boxInputs));
+ cell->setPort(ID(o), SigSpec(State::S0, boxOutputs));
+ cell->attributes[ID::abc9_box_seq] = oldBoxNum;
boxes.emplace_back(cell);
}
}
@@ -548,18 +548,18 @@ void AigerReader::parse_aiger_ascii()
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0)
- q_wire->attributes["\\init"] = State::S0;
+ q_wire->attributes[ID::init] = State::S0;
else if (l3 == 1)
- q_wire->attributes["\\init"] = State::S1;
+ q_wire->attributes[ID::init] = State::S1;
else if (l3 == l1) {
- //q_wire->attributes["\\init"] = RTLIL::Sx;
+ //q_wire->attributes[ID::init] = RTLIL::Sx;
}
else
log_error("Line %u has invalid reset literal for latch!\n", line_count);
}
else {
// AIGER latches are assumed to be initialized to zero
- q_wire->attributes["\\init"] = State::S0;
+ q_wire->attributes[ID::init] = State::S0;
}
latches.push_back(q_wire);
}
@@ -673,18 +673,18 @@ void AigerReader::parse_aiger_binary()
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0)
- q_wire->attributes["\\init"] = State::S0;
+ q_wire->attributes[ID::init] = State::S0;
else if (l3 == 1)
- q_wire->attributes["\\init"] = State::S1;
+ q_wire->attributes[ID::init] = State::S1;
else if (l3 == l1) {
- //q_wire->attributes["\\init"] = RTLIL::Sx;
+ //q_wire->attributes[ID::init] = RTLIL::Sx;
}
else
log_error("Line %u has invalid reset literal for latch!\n", line_count);
}
else {
// AIGER latches are assumed to be initialized to zero
- q_wire->attributes["\\init"] = State::S0;
+ q_wire->attributes[ID::init] = State::S0;
}
latches.push_back(q_wire);
}
@@ -747,7 +747,7 @@ void AigerReader::post_process()
{
unsigned ci_count = 0, co_count = 0;
for (auto cell : boxes) {
- for (auto &bit : cell->connections_.at("\\i")) {
+ for (auto &bit : cell->connections_.at(ID(i))) {
log_assert(bit == State::S0);
log_assert(co_count < outputs.size());
bit = outputs[co_count++];
@@ -755,7 +755,7 @@ void AigerReader::post_process()
log_assert(bit.wire->port_output);
bit.wire->port_output = false;
}
- for (auto &bit : cell->connections_.at("\\o")) {
+ for (auto &bit : cell->connections_.at(ID(o))) {
log_assert(bit == State::S0);
log_assert((piNum + ci_count) < inputs.size());
bit = inputs[piNum + ci_count++];
@@ -776,10 +776,10 @@ void AigerReader::post_process()
log_assert(q->port_input);
q->port_input = false;
- auto ff = module->addCell(NEW_ID, "$__ABC9_FF_");
- ff->setPort("\\D", d);
- ff->setPort("\\Q", q);
- ff->attributes["\\abc9_mergeability"] = mergeability[i];
+ auto ff = module->addCell(NEW_ID, ID($__ABC9_FF_));
+ ff->setPort(ID::D, d);
+ ff->setPort(ID::Q, q);
+ ff->attributes[ID::abc9_mergeability] = mergeability[i];
}
dict<RTLIL::IdString, int> wideports_cache;
@@ -866,7 +866,7 @@ void AigerReader::post_process()
int init;
mf >> init;
if (init < 2)
- wire->attributes["\\init"] = init;
+ wire->attributes[ID::init] = init;
}
else if (type == "box") {
RTLIL::Cell* cell = module->cell(stringf("$box%d", variable));
@@ -929,8 +929,8 @@ void AigerReader::post_process()
design->add(module);
for (auto cell : module->cells().to_vector()) {
- if (cell->type != "$lut") continue;
- auto y_port = cell->getPort("\\Y").as_bit();
+ if (cell->type != ID($lut)) continue;
+ auto y_port = cell->getPort(ID::Y).as_bit();
if (y_port.wire->width == 1)
module->rename(cell, stringf("$lut%s", y_port.wire->name.c_str()));
else
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 650c7a937..2b6002548 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -952,9 +952,9 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
current_module = new AstModule;
current_module->ast = NULL;
current_module->name = ast->str;
- current_module->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line,
+ current_module->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line,
ast->location.first_column, ast->location.last_line, ast->location.last_column);
- current_module->set_bool_attribute("\\cells_not_processed");
+ current_module->set_bool_attribute(ID::cells_not_processed);
current_ast_mod = ast;
AstNode *ast_before_simplify;
@@ -1007,61 +1007,61 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
log("--- END OF AST DUMP ---\n");
}
- if (flag_nowb && ast->attributes.count("\\whitebox")) {
- delete ast->attributes.at("\\whitebox");
- ast->attributes.erase("\\whitebox");
+ if (flag_nowb && ast->attributes.count(ID::whitebox)) {
+ delete ast->attributes.at(ID::whitebox);
+ ast->attributes.erase(ID::whitebox);
}
- if (ast->attributes.count("\\lib_whitebox")) {
+ if (ast->attributes.count(ID::lib_whitebox)) {
if (!flag_lib || flag_nowb) {
- delete ast->attributes.at("\\lib_whitebox");
- ast->attributes.erase("\\lib_whitebox");
+ delete ast->attributes.at(ID::lib_whitebox);
+ ast->attributes.erase(ID::lib_whitebox);
} else {
- if (ast->attributes.count("\\whitebox")) {
- delete ast->attributes.at("\\whitebox");
- ast->attributes.erase("\\whitebox");
+ if (ast->attributes.count(ID::whitebox)) {
+ delete ast->attributes.at(ID::whitebox);
+ ast->attributes.erase(ID::whitebox);
}
- AstNode *n = ast->attributes.at("\\lib_whitebox");
- ast->attributes["\\whitebox"] = n;
- ast->attributes.erase("\\lib_whitebox");
+ AstNode *n = ast->attributes.at(ID::lib_whitebox);
+ ast->attributes[ID::whitebox] = n;
+ ast->attributes.erase(ID::lib_whitebox);
}
}
- if (!blackbox_module && ast->attributes.count("\\blackbox")) {
- AstNode *n = ast->attributes.at("\\blackbox");
+ if (!blackbox_module && ast->attributes.count(ID::blackbox)) {
+ AstNode *n = ast->attributes.at(ID::blackbox);
if (n->type != AST_CONSTANT)
log_file_error(ast->filename, ast->location.first_line, "Got blackbox attribute with non-constant value!\n");
blackbox_module = n->asBool();
}
- if (blackbox_module && ast->attributes.count("\\whitebox")) {
- AstNode *n = ast->attributes.at("\\whitebox");
+ if (blackbox_module && ast->attributes.count(ID::whitebox)) {
+ AstNode *n = ast->attributes.at(ID::whitebox);
if (n->type != AST_CONSTANT)
log_file_error(ast->filename, ast->location.first_line, "Got whitebox attribute with non-constant value!\n");
blackbox_module = !n->asBool();
}
- if (ast->attributes.count("\\noblackbox")) {
+ if (ast->attributes.count(ID::noblackbox)) {
if (blackbox_module) {
- AstNode *n = ast->attributes.at("\\noblackbox");
+ AstNode *n = ast->attributes.at(ID::noblackbox);
if (n->type != AST_CONSTANT)
log_file_error(ast->filename, ast->location.first_line, "Got noblackbox attribute with non-constant value!\n");
blackbox_module = !n->asBool();
}
- delete ast->attributes.at("\\noblackbox");
- ast->attributes.erase("\\noblackbox");
+ delete ast->attributes.at(ID::noblackbox);
+ ast->attributes.erase(ID::noblackbox);
}
if (blackbox_module)
{
- if (ast->attributes.count("\\whitebox")) {
- delete ast->attributes.at("\\whitebox");
- ast->attributes.erase("\\whitebox");
+ if (ast->attributes.count(ID::whitebox)) {
+ delete ast->attributes.at(ID::whitebox);
+ ast->attributes.erase(ID::whitebox);
}
- if (ast->attributes.count("\\lib_whitebox")) {
- delete ast->attributes.at("\\lib_whitebox");
- ast->attributes.erase("\\lib_whitebox");
+ if (ast->attributes.count(ID::lib_whitebox)) {
+ delete ast->attributes.at(ID::lib_whitebox);
+ ast->attributes.erase(ID::lib_whitebox);
}
std::vector<AstNode*> new_children;
@@ -1082,8 +1082,8 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
ast->children.swap(new_children);
- if (ast->attributes.count("\\blackbox") == 0) {
- ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false);
+ if (ast->attributes.count(ID::blackbox) == 0) {
+ ast->attributes[ID::blackbox] = AstNode::mkconst_int(1, false);
}
}
@@ -1124,7 +1124,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
}
if (ast->type == AST_INTERFACE)
- current_module->set_bool_attribute("\\is_interface");
+ current_module->set_bool_attribute(ID::is_interface);
current_module->ast = ast_before_simplify;
current_module->nolatches = flag_nolatches;
current_module->nomeminit = flag_nomeminit;
@@ -1179,12 +1179,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
for (auto n : design->verilog_globals)
(*it)->children.push_back(n->clone());
- for (auto n : design->verilog_packages){
- for (auto o : n->children) {
+ // append nodes from previous packages using package-qualified names
+ for (auto &n : design->verilog_packages) {
+ for (auto &o : n->children) {
AstNode *cloned_node = o->clone();
- log("cloned node %s\n", type2str(cloned_node->type).c_str());
- if (cloned_node->type == AST_ENUM){
- for (auto e : cloned_node->children){
+ // log("cloned node %s\n", type2str(cloned_node->type).c_str());
+ if (cloned_node->type == AST_ENUM) {
+ for (auto &e : cloned_node->children) {
log_assert(e->type == AST_ENUM_ITEM);
e->str = n->str + std::string("::") + e->str.substr(1);
}
@@ -1211,7 +1212,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
continue;
} else {
log("Replacing existing%s module `%s' at %s:%d.%d-%d.%d.\n",
- existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "",
+ existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "",
(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->location.first_line, (*it)->location.first_column, (*it)->location.last_line, (*it)->location.last_column);
design->remove(existing_mod);
}
@@ -1220,6 +1221,8 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
design->add(process_module(*it, defer));
}
else if ((*it)->type == AST_PACKAGE) {
+ // process enum/other declarations
+ (*it)->simplify(true, false, false, 1, -1, false, false);
design->verilog_packages.push_back((*it)->clone());
}
else {
@@ -1281,9 +1284,9 @@ AstNode * AST::find_modport(AstNode *intf, std::string name)
// Iterate over all wires in an interface and add them as wires in the AST module:
void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport)
{
- for (auto &wire_it : intfmodule->wires_){
- AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true)));
- std::string origname = log_id(wire_it.first);
+ for (auto w : intfmodule->wires()){
+ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
+ std::string origname = log_id(w->name);
std::string newname = intfname + "." + origname;
wire->str = newname;
if (modport != NULL) {
@@ -1317,7 +1320,7 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule
// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
// from AST. The interface members are copied into the AST module with the prefix of the interface.
-void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module*> local_interfaces)
+void AstModule::reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module*> &local_interfaces)
{
loadconfig();
@@ -1326,9 +1329,9 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
for (auto &intf : local_interfaces) {
std::string intfname = intf.first.str();
RTLIL::Module *intfmodule = intf.second;
- for (auto &wire_it : intfmodule->wires_){
- AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true)));
- std::string newname = log_id(wire_it.first);
+ for (auto w : intfmodule->wires()){
+ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
+ std::string newname = log_id(w->name);
newname = intfname + "." + newname;
wire->str = newname;
new_ast->children.push_back(wire);
@@ -1352,7 +1355,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
std::pair<std::string,std::string> res = split_modport_from_type(ch->str);
std::string interface_type = res.first;
std::string interface_modport = res.second; // Is "", if no modport
- if (design->modules_.count(interface_type) > 0) {
+ if (design->module(interface_type) != nullptr) {
// Add a cell to the module corresponding to the interface port such that
// it can further propagated down if needed:
AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE);
@@ -1362,7 +1365,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
new_ast->children.push_back(cell_for_intf);
// Get all members of this non-overridden dummy interface instance:
- RTLIL::Module *intfmodule = design->modules_[interface_type]; // All interfaces should at this point in time (assuming
+ RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming
// reprocess_module is called from the hierarchy pass) be
// present in design->modules_
AstModule *ast_module_of_interface = (AstModule*)intfmodule;
@@ -1382,12 +1385,12 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
std::string original_name = this->name.str();
std::string changed_name = original_name + "_before_replacing_local_interfaces";
design->rename(this, changed_name);
- this->set_bool_attribute("\\to_delete");
+ this->set_bool_attribute(ID::to_delete);
// Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
// new module.
- if (this->get_bool_attribute("\\initial_top")) {
- this->attributes.erase("\\initial_top");
+ if (this->get_bool_attribute(ID::initial_top)) {
+ this->attributes.erase(ID::initial_top);
is_top = true;
}
@@ -1397,15 +1400,15 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
design->add(newmod);
RTLIL::Module* mod = design->module(original_name);
if (is_top)
- mod->set_bool_attribute("\\top");
+ mod->set_bool_attribute(ID::top);
// Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
- mod->set_bool_attribute("\\interfaces_replaced_in_module");
+ mod->set_bool_attribute(ID::interfaces_replaced_in_module);
}
// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
// This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
-RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool /*mayfail*/)
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool /*mayfail*/)
{
AstNode *new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast);
@@ -1457,13 +1460,20 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
// Now that the interfaces have been exploded, we can delete the dummy port related to every interface.
for(auto &intf : interfaces) {
- if(mod->wires_.count(intf.first)) {
- mod->wires_.erase(intf.first);
+ if(mod->wire(intf.first) != nullptr) {
+ // Normally, removing wires would be batched together as it's an
+ // expensive operation, however, in this case doing so would mean
+ // that a cell with the same name cannot be created (below)...
+ // Since we won't expect many interfaces to exist in a module,
+ // we can let this slide...
+ pool<RTLIL::Wire*> to_remove;
+ to_remove.insert(mod->wire(intf.first));
+ mod->remove(to_remove);
mod->fixup_ports();
- // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated
- // down to sub-sub-modules etc.
- RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name);
- new_subcell->set_bool_attribute("\\is_interface");
+ // We copy the cell of the interface to the sub-module such that it
+ // can further be found if it is propagated down to sub-sub-modules etc.
+ RTLIL::Cell *new_subcell = mod->addCell(intf.first, intf.second->name);
+ new_subcell->set_bool_attribute(ID::is_interface);
}
else {
log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str());
@@ -1472,7 +1482,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
// If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
if (interfaces.size() > 0) {
- mod->set_bool_attribute("\\interfaces_replaced_in_module");
+ mod->set_bool_attribute(ID::interfaces_replaced_in_module);
}
} else {
@@ -1484,9 +1494,9 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
}
// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
-RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool /*mayfail*/)
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool /*mayfail*/)
{
- bool quiet = lib || attributes.count(ID(blackbox)) || attributes.count(ID(whitebox));
+ bool quiet = lib || attributes.count(ID::blackbox) || attributes.count(ID::whitebox);
AstNode *new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast, quiet);
@@ -1504,7 +1514,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
}
// create a new parametric module (when needed) and return the name of the generated module
-std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool quiet)
+std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet)
{
std::string stripped_name = name.str();
@@ -1518,18 +1528,18 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
if (child->type != AST_PARAMETER)
continue;
para_counter++;
- std::string para_id = child->str;
- if (parameters.count(para_id) > 0) {
+ auto it = parameters.find(child->str);
+ if (it != parameters.end()) {
if (!quiet)
- log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
- para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
+ log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second));
+ para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second));
continue;
}
- para_id = stringf("$%d", para_counter);
- if (parameters.count(para_id) > 0) {
+ it = parameters.find(stringf("$%d", para_counter));
+ if (it != parameters.end()) {
if (!quiet)
- log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
- para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
+ log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second));
+ para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second));
continue;
}
}
@@ -1549,46 +1559,52 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
loadconfig();
+ pool<IdString> rewritten;
+ rewritten.reserve(GetSize(parameters));
+
AstNode *new_ast = ast->clone();
para_counter = 0;
for (auto child : new_ast->children) {
if (child->type != AST_PARAMETER)
continue;
para_counter++;
- std::string para_id = child->str;
- if (parameters.count(para_id) > 0) {
+ auto it = parameters.find(child->str);
+ if (it != parameters.end()) {
if (!quiet)
- log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
+ log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second));
goto rewrite_parameter;
}
- para_id = stringf("$%d", para_counter);
- if (parameters.count(para_id) > 0) {
+ it = parameters.find(stringf("$%d", para_counter));
+ if (it != parameters.end()) {
if (!quiet)
- log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
+ log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second));
goto rewrite_parameter;
}
continue;
rewrite_parameter:
delete child->children.at(0);
- if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) {
+ if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) {
child->children[0] = new AstNode(AST_REALVALUE);
- child->children[0]->realvalue = std::stod(parameters[para_id].decode_string());
- } else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
- child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
+ child->children[0]->realvalue = std::stod(it->second.decode_string());
+ } else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
+ child->children[0] = AstNode::mkconst_str(it->second.decode_string());
else
- child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
- parameters.erase(para_id);
+ child->children[0] = AstNode::mkconst_bits(it->second.bits, (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0);
+ rewritten.insert(it->first);
}
- for (auto param : parameters) {
- AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER));
- defparam->children[0]->str = param.first.str();
- if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0)
- defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string()));
- else
- defparam->children.push_back(AstNode::mkconst_bits(param.second.bits, (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0));
- new_ast->children.push_back(defparam);
- }
+ if (GetSize(rewritten) < GetSize(parameters))
+ for (const auto &param : parameters) {
+ if (rewritten.count(param.first))
+ continue;
+ AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER));
+ defparam->children[0]->str = param.first.str();
+ if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0)
+ defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string()));
+ else
+ defparam->children.push_back(AstNode::mkconst_bits(param.second.bits, (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0));
+ new_ast->children.push_back(defparam);
+ }
(*new_ast_out) = new_ast;
return modname;
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index e27ab10c2..3dd40238f 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -312,10 +312,10 @@ namespace AST
AstNode *ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire;
~AstModule() YS_OVERRIDE;
- RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
- RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
- std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool quiet = false);
- void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE;
+ RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) YS_OVERRIDE;
+ RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail) YS_OVERRIDE;
+ std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet = false);
+ void reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) YS_OVERRIDE;
RTLIL::Module *clone() const YS_OVERRIDE;
void loadconfig() const;
};
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 54d8a11fa..c0539252c 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -41,16 +41,14 @@ using namespace AST;
using namespace AST_INTERNAL;
// helper function for creating RTLIL code for unary operations
-static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
+static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
{
- std::stringstream sstr;
- sstr << type << "$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++);
-
- RTLIL::Cell *cell = current_module->addCell(sstr.str(), type);
- cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);
+ RTLIL::Cell *cell = current_module->addCell(name, type);
+ cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
- wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
if (gen_attributes)
for (auto &attr : that->attributes) {
@@ -59,12 +57,12 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi
cell->attributes[attr.first] = attr.second->asAttrConst();
}
- cell->parameters["\\A_SIGNED"] = RTLIL::Const(that->children[0]->is_signed);
- cell->parameters["\\A_WIDTH"] = RTLIL::Const(arg.size());
- cell->setPort("\\A", arg);
+ cell->parameters[ID::A_SIGNED] = RTLIL::Const(that->children[0]->is_signed);
+ cell->parameters[ID::A_WIDTH] = RTLIL::Const(arg.size());
+ cell->setPort(ID::A, arg);
- cell->parameters["\\Y_WIDTH"] = result_width;
- cell->setPort("\\Y", wire);
+ cell->parameters[ID::Y_WIDTH] = result_width;
+ cell->setPort(ID::Y, wire);
return wire;
}
@@ -76,14 +74,12 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
return;
}
- std::stringstream sstr;
- sstr << "$extend" << "$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++);
-
- RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$pos");
- cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ IdString name = stringf("$extend$%s:%d$%d", that->filename.c_str(), that->location.first_line, autoidx++);
+ RTLIL::Cell *cell = current_module->addCell(name, ID($pos));
+ cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", width);
- wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
if (that != NULL)
for (auto &attr : that->attributes) {
@@ -92,26 +88,24 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
cell->attributes[attr.first] = attr.second->asAttrConst();
}
- cell->parameters["\\A_SIGNED"] = RTLIL::Const(is_signed);
- cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig.size());
- cell->setPort("\\A", sig);
+ cell->parameters[ID::A_SIGNED] = RTLIL::Const(is_signed);
+ cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig.size());
+ cell->setPort(ID::A, sig);
- cell->parameters["\\Y_WIDTH"] = width;
- cell->setPort("\\Y", wire);
+ cell->parameters[ID::Y_WIDTH] = width;
+ cell->setPort(ID::Y, wire);
sig = wire;
}
// helper function for creating RTLIL code for binary operations
-static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
+static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
{
- std::stringstream sstr;
- sstr << type << "$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++);
-
- RTLIL::Cell *cell = current_module->addCell(sstr.str(), type);
- cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);
+ RTLIL::Cell *cell = current_module->addCell(name, type);
+ cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
- wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -119,17 +113,17 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi
cell->attributes[attr.first] = attr.second->asAttrConst();
}
- cell->parameters["\\A_SIGNED"] = RTLIL::Const(that->children[0]->is_signed);
- cell->parameters["\\B_SIGNED"] = RTLIL::Const(that->children[1]->is_signed);
+ cell->parameters[ID::A_SIGNED] = RTLIL::Const(that->children[0]->is_signed);
+ cell->parameters[ID::B_SIGNED] = RTLIL::Const(that->children[1]->is_signed);
- cell->parameters["\\A_WIDTH"] = RTLIL::Const(left.size());
- cell->parameters["\\B_WIDTH"] = RTLIL::Const(right.size());
+ cell->parameters[ID::A_WIDTH] = RTLIL::Const(left.size());
+ cell->parameters[ID::B_WIDTH] = RTLIL::Const(right.size());
- cell->setPort("\\A", left);
- cell->setPort("\\B", right);
+ cell->setPort(ID::A, left);
+ cell->setPort(ID::B, right);
- cell->parameters["\\Y_WIDTH"] = result_width;
- cell->setPort("\\Y", wire);
+ cell->parameters[ID::Y_WIDTH] = result_width;
+ cell->setPort(ID::Y, wire);
return wire;
}
@@ -141,11 +135,11 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
std::stringstream sstr;
sstr << "$ternary$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++);
- RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$mux");
- cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux));
+ cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", left.size());
- wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
+ wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line);
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -153,12 +147,12 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
cell->attributes[attr.first] = attr.second->asAttrConst();
}
- cell->parameters["\\WIDTH"] = RTLIL::Const(left.size());
+ cell->parameters[ID::WIDTH] = RTLIL::Const(left.size());
- cell->setPort("\\A", right);
- cell->setPort("\\B", left);
- cell->setPort("\\S", cond);
- cell->setPort("\\Y", wire);
+ cell->setPort(ID::A, right);
+ cell->setPort(ID::B, left);
+ cell->setPort(ID::S, cond);
+ cell->setPort(ID::Y, wire);
return wire;
}
@@ -199,7 +193,7 @@ struct AST_INTERNAL::ProcessGenerator
{
// generate process and simple root case
proc = new RTLIL::Process;
- proc->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
+ proc->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->location.first_line, autoidx++);
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -221,7 +215,7 @@ struct AST_INTERNAL::ProcessGenerator
for (auto child : always->children)
{
if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER &&
- child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk")) {
+ child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) {
found_global_syncs = true;
}
if (child->type == AST_EDGE) {
@@ -245,7 +239,7 @@ struct AST_INTERNAL::ProcessGenerator
for (auto child : always->children)
if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast &&
- child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk"))
+ child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk))
continue;
found_clocked_sync = true;
if (found_global_syncs || found_anyedge_syncs)
@@ -267,7 +261,7 @@ struct AST_INTERNAL::ProcessGenerator
}
// create initial assignments for the temporary signals
- if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) {
+ if ((flag_nolatches || always->get_bool_attribute(ID::nolatches) || current_module->get_bool_attribute(ID::nolatches)) && !found_clocked_sync) {
subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from)));
} else {
addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from);
@@ -335,7 +329,7 @@ struct AST_INTERNAL::ProcessGenerator
} while (current_module->wires_.count(wire_name) > 0);
RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
- wire->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
+ wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
chunk.wire = wire;
chunk.offset = 0;
@@ -420,7 +414,7 @@ struct AST_INTERNAL::ProcessGenerator
for (auto &lvalue_c : lvalue.chunks()) {
RTLIL::SigSpec lhs = lvalue_c;
RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue_c.width);
- if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute("\\nosync"))
+ if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute(ID::nosync))
rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.size());
remove_unwanted_lvalue_bits(lhs, rhs);
actions.push_back(RTLIL::SigSig(lhs, rhs));
@@ -470,7 +464,7 @@ struct AST_INTERNAL::ProcessGenerator
case AST_CASE:
{
RTLIL::SwitchRule *sw = new RTLIL::SwitchRule;
- sw->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line, ast->location.first_column, ast->location.last_line, ast->location.last_column);
+ sw->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line, ast->location.first_column, ast->location.last_line, ast->location.last_column);
sw->signal = ast->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
current_case->switches.push_back(sw);
@@ -504,7 +498,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule;
- current_case->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", child->filename.c_str(), child->location.first_line, child->location.first_column, child->location.last_line, child->location.last_column);
+ current_case->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", child->filename.c_str(), child->location.first_line, child->location.first_column, child->location.last_line, child->location.last_column);
last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
for (auto node : child->children) {
@@ -525,7 +519,7 @@ struct AST_INTERNAL::ProcessGenerator
subst_rvalue_map.restore();
}
- if (last_generated_case != NULL && ast->get_bool_attribute("\\full_case") && default_case == NULL) {
+ if (last_generated_case != NULL && ast->get_bool_attribute(ID::full_case) && default_case == NULL) {
#if 0
// this is a valid transformation, but as optimization it is premature.
// better: add a default case that assigns 'x' to everything, and let later
@@ -842,7 +836,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// Clifford's Device (http://www.clifford.at/cfun/cliffdev/). In this
// cases this variable is used to hold the type of the cell that should
// be instantiated for this type of AST node.
- std::string type_name;
+ IdString type_name;
current_filename = filename;
@@ -873,19 +867,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// This is used by the hierarchy pass to know when it can replace interface connection with the individual
// signals.
RTLIL::Wire *wire = current_module->addWire(str, 1);
- wire->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
wire->start_offset = 0;
wire->port_id = port_id;
wire->port_input = true;
wire->port_output = true;
- wire->set_bool_attribute("\\is_interface");
+ wire->set_bool_attribute(ID::is_interface);
if (children.size() > 0) {
for(size_t i=0; i<children.size();i++) {
if(children[i]->type == AST_INTERFACEPORTTYPE) {
std::pair<std::string,std::string> res = AST::split_modport_from_type(children[i]->str);
- wire->attributes["\\interface_type"] = res.first;
+ wire->attributes[ID::interface_type] = res.first;
if (res.second != "")
- wire->attributes["\\interface_modport"] = res.second;
+ wire->attributes[ID::interface_modport] = res.second;
break;
}
}
@@ -910,8 +904,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::Wire *wire = current_module->addWire(str, GetSize(val));
current_module->connect(wire, val);
- wire->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
- wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1;
+ wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ wire->attributes[type == AST_PARAMETER ? ID::parameter : ID::localparam] = 1;
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -932,7 +926,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
- wire->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
wire->start_offset = range_right;
wire->port_id = port_id;
wire->port_input = is_input;
@@ -945,8 +939,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
wire->attributes[attr.first] = attr.second->asAttrConst();
}
- if (is_wand) wire->set_bool_attribute("\\wand");
- if (is_wor) wire->set_bool_attribute("\\wor");
+ if (is_wand) wire->set_bool_attribute(ID::wand);
+ if (is_wor) wire->set_bool_attribute(ID::wor);
}
break;
@@ -963,7 +957,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Memory `%s' with non-constant width or size!\n", str.c_str());
RTLIL::Memory *memory = new RTLIL::Memory;
- memory->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ memory->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
memory->name = str;
memory->width = children[0]->range_left - children[0]->range_right + 1;
if (children[1]->range_right < children[1]->range_left) {
@@ -1018,7 +1012,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (id2ast && id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
RTLIL::Wire *wire = current_module->addWire(str);
- wire->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
wire->name = str;
if (flag_autowire)
log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str());
@@ -1033,7 +1027,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
RTLIL::Wire *current_wire = current_module->wire(str);
- if (current_wire->get_bool_attribute("\\is_interface"))
+ if (current_wire->get_bool_attribute(ID::is_interface))
is_interface = true;
// Ignore
}
@@ -1052,16 +1046,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// This makes it possible for the hierarchy pass to see what are interface connections and then replace them
// with the individual signals:
if (is_interface) {
- RTLIL::Wire *dummy_wire;
- std::string dummy_wire_name = "$dummywireforinterface" + str;
- if (current_module->wires_.count(dummy_wire_name))
- dummy_wire = current_module->wires_[dummy_wire_name];
- else {
+ IdString dummy_wire_name = stringf("$dummywireforinterface%s", str.c_str());
+ RTLIL::Wire *dummy_wire = current_module->wire(dummy_wire_name);
+ if (!dummy_wire) {
dummy_wire = current_module->addWire(dummy_wire_name);
- dummy_wire->set_bool_attribute("\\is_interface");
+ dummy_wire->set_bool_attribute(ID::is_interface);
}
- RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire);
- return tmp;
+ return dummy_wire;
}
wire = current_module->wires_[str];
@@ -1097,7 +1088,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
if (GetSize(shift_val) >= 32)
fake_ast->children[1]->is_signed = true;
- RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val);
+ RTLIL::SigSpec sig = binop2rtlil(fake_ast, ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val);
delete left_at_zero_ast;
delete right_at_zero_ast;
delete fake_ast;
@@ -1181,9 +1172,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
// generate cells for unary operations: $not, $pos, $neg
- if (0) { case AST_BIT_NOT: type_name = "$not"; }
- if (0) { case AST_POS: type_name = "$pos"; }
- if (0) { case AST_NEG: type_name = "$neg"; }
+ if (0) { case AST_BIT_NOT: type_name = ID($not); }
+ if (0) { case AST_POS: type_name = ID($pos); }
+ if (0) { case AST_NEG: type_name = ID($neg); }
{
RTLIL::SigSpec arg = children[0]->genRTLIL(width_hint, sign_hint);
is_signed = children[0]->is_signed;
@@ -1196,10 +1187,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
// generate cells for binary operations: $and, $or, $xor, $xnor
- if (0) { case AST_BIT_AND: type_name = "$and"; }
- if (0) { case AST_BIT_OR: type_name = "$or"; }
- if (0) { case AST_BIT_XOR: type_name = "$xor"; }
- if (0) { case AST_BIT_XNOR: type_name = "$xnor"; }
+ if (0) { case AST_BIT_AND: type_name = ID($and); }
+ if (0) { case AST_BIT_OR: type_name = ID($or); }
+ if (0) { case AST_BIT_XOR: type_name = ID($xor); }
+ if (0) { case AST_BIT_XNOR: type_name = ID($xnor); }
{
if (width_hint < 0)
detectSignWidth(width_hint, sign_hint);
@@ -1213,10 +1204,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
// generate cells for unary operations: $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor
- if (0) { case AST_REDUCE_AND: type_name = "$reduce_and"; }
- if (0) { case AST_REDUCE_OR: type_name = "$reduce_or"; }
- if (0) { case AST_REDUCE_XOR: type_name = "$reduce_xor"; }
- if (0) { case AST_REDUCE_XNOR: type_name = "$reduce_xnor"; }
+ if (0) { case AST_REDUCE_AND: type_name = ID($reduce_and); }
+ if (0) { case AST_REDUCE_OR: type_name = ID($reduce_or); }
+ if (0) { case AST_REDUCE_XOR: type_name = ID($reduce_xor); }
+ if (0) { case AST_REDUCE_XNOR: type_name = ID($reduce_xnor); }
{
RTLIL::SigSpec arg = children[0]->genRTLIL();
RTLIL::SigSpec sig = uniop2rtlil(this, type_name, max(width_hint, 1), arg);
@@ -1225,7 +1216,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// generate cells for unary operations: $reduce_bool
// (this is actually just an $reduce_or, but for clarity a different cell type is used)
- if (0) { case AST_REDUCE_BOOL: type_name = "$reduce_bool"; }
+ if (0) { case AST_REDUCE_BOOL: type_name = ID($reduce_bool); }
{
RTLIL::SigSpec arg = children[0]->genRTLIL();
RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, max(width_hint, 1), arg) : arg;
@@ -1233,10 +1224,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
// generate cells for binary operations: $shl, $shr, $sshl, $sshr
- if (0) { case AST_SHIFT_LEFT: type_name = "$shl"; }
- if (0) { case AST_SHIFT_RIGHT: type_name = "$shr"; }
- if (0) { case AST_SHIFT_SLEFT: type_name = "$sshl"; }
- if (0) { case AST_SHIFT_SRIGHT: type_name = "$sshr"; }
+ if (0) { case AST_SHIFT_LEFT: type_name = ID($shl); }
+ if (0) { case AST_SHIFT_RIGHT: type_name = ID($shr); }
+ if (0) { case AST_SHIFT_SLEFT: type_name = ID($sshl); }
+ if (0) { case AST_SHIFT_SRIGHT: type_name = ID($sshr); }
{
if (width_hint < 0)
detectSignWidth(width_hint, sign_hint);
@@ -1260,19 +1251,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int width = width_hint > 0 ? width_hint : left.size();
is_signed = children[0]->is_signed;
if (!flag_noopt && left.is_fully_const() && left.as_int() == 2 && !right_signed)
- return binop2rtlil(this, "$shl", width, RTLIL::SigSpec(1, left.size()), right);
- return binop2rtlil(this, "$pow", width, left, right);
+ return binop2rtlil(this, ID($shl), width, RTLIL::SigSpec(1, left.size()), right);
+ return binop2rtlil(this, ID($pow), width, left, right);
}
// generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt
- if (0) { case AST_LT: type_name = "$lt"; }
- if (0) { case AST_LE: type_name = "$le"; }
- if (0) { case AST_EQ: type_name = "$eq"; }
- if (0) { case AST_NE: type_name = "$ne"; }
- if (0) { case AST_EQX: type_name = "$eqx"; }
- if (0) { case AST_NEX: type_name = "$nex"; }
- if (0) { case AST_GE: type_name = "$ge"; }
- if (0) { case AST_GT: type_name = "$gt"; }
+ if (0) { case AST_LT: type_name = ID($lt); }
+ if (0) { case AST_LE: type_name = ID($le); }
+ if (0) { case AST_EQ: type_name = ID($eq); }
+ if (0) { case AST_NE: type_name = ID($ne); }
+ if (0) { case AST_EQX: type_name = ID($eqx); }
+ if (0) { case AST_NEX: type_name = ID($nex); }
+ if (0) { case AST_GE: type_name = ID($ge); }
+ if (0) { case AST_GT: type_name = ID($gt); }
{
int width = max(width_hint, 1);
width_hint = -1, sign_hint = true;
@@ -1285,11 +1276,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
// generate cells for binary operations: $add, $sub, $mul, $div, $mod
- if (0) { case AST_ADD: type_name = "$add"; }
- if (0) { case AST_SUB: type_name = "$sub"; }
- if (0) { case AST_MUL: type_name = "$mul"; }
- if (0) { case AST_DIV: type_name = "$div"; }
- if (0) { case AST_MOD: type_name = "$mod"; }
+ if (0) { case AST_ADD: type_name = ID($add); }
+ if (0) { case AST_SUB: type_name = ID($sub); }
+ if (0) { case AST_MUL: type_name = ID($mul); }
+ if (0) { case AST_DIV: type_name = ID($div); }
+ if (0) { case AST_MOD: type_name = ID($mod); }
{
if (width_hint < 0)
detectSignWidth(width_hint, sign_hint);
@@ -1315,8 +1306,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
// generate cells for binary operations: $logic_and, $logic_or
- if (0) { case AST_LOGIC_AND: type_name = "$logic_and"; }
- if (0) { case AST_LOGIC_OR: type_name = "$logic_or"; }
+ if (0) { case AST_LOGIC_AND: type_name = ID($logic_and); }
+ if (0) { case AST_LOGIC_OR: type_name = ID($logic_or); }
{
RTLIL::SigSpec left = children[0]->genRTLIL();
RTLIL::SigSpec right = children[1]->genRTLIL();
@@ -1327,7 +1318,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_LOGIC_NOT:
{
RTLIL::SigSpec arg = children[0]->genRTLIL();
- return uniop2rtlil(this, "$logic_not", max(width_hint, 1), arg);
+ return uniop2rtlil(this, ID($logic_not), max(width_hint, 1), arg);
}
// generate multiplexer for ternary operator (aka ?:-operator)
@@ -1353,7 +1344,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint);
if (cond.size() > 1)
- cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false);
+ cond = uniop2rtlil(this, ID($reduce_bool), 1, cond, false);
int width = max(val1.size(), val2.size());
is_signed = children[1]->is_signed && children[2]->is_signed;
@@ -1374,11 +1365,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
std::stringstream sstr;
sstr << "$memrd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
- RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$memrd");
- cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), location.first_line);
+ RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd));
+ cell->attributes[ID::src] = stringf("%s:%d", filename.c_str(), location.first_line);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width);
- wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), location.first_line);
+ wire->attributes[ID::src] = stringf("%s:%d", filename.c_str(), location.first_line);
int mem_width, mem_size, addr_bits;
is_signed = id2ast->is_signed;
@@ -1386,18 +1377,18 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::SigSpec addr_sig = children[0]->genRTLIL();
- cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
- cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1));
- cell->setPort("\\ADDR", addr_sig);
- cell->setPort("\\DATA", RTLIL::SigSpec(wire));
+ cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1));
+ cell->setPort(ID::EN, RTLIL::SigSpec(RTLIL::State::Sx, 1));
+ cell->setPort(ID::ADDR, addr_sig);
+ cell->setPort(ID::DATA, RTLIL::SigSpec(wire));
- cell->parameters["\\MEMID"] = RTLIL::Const(str);
- cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig));
- cell->parameters["\\WIDTH"] = RTLIL::Const(wire->width);
+ cell->parameters[ID::MEMID] = RTLIL::Const(str);
+ cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
+ cell->parameters[ID::WIDTH] = RTLIL::Const(wire->width);
- cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
- cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
- cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
+ cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0);
+ cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0);
+ cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0);
if (!sign_hint)
is_signed = false;
@@ -1412,8 +1403,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
std::stringstream sstr;
sstr << (type == AST_MEMWR ? "$memwr$" : "$meminit$") << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
- RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? "$memwr" : "$meminit");
- cell->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? ID($memwr) : ID($meminit));
+ cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
int mem_width, mem_size, addr_bits;
id2ast->meminfo(mem_width, mem_size, addr_bits);
@@ -1423,26 +1414,26 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (children[2]->type != AST_CONSTANT)
log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n");
num_words = int(children[2]->asInt(false));
- cell->parameters["\\WORDS"] = RTLIL::Const(num_words);
+ cell->parameters[ID::WORDS] = RTLIL::Const(num_words);
}
SigSpec addr_sig = children[0]->genRTLIL();
- cell->setPort("\\ADDR", addr_sig);
- cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words));
+ cell->setPort(ID::ADDR, addr_sig);
+ cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words));
- cell->parameters["\\MEMID"] = RTLIL::Const(str);
- cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig));
- cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width);
+ cell->parameters[ID::MEMID] = RTLIL::Const(str);
+ cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
+ cell->parameters[ID::WIDTH] = RTLIL::Const(current_module->memories[str]->width);
if (type == AST_MEMWR) {
- cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
- cell->setPort("\\EN", children[2]->genRTLIL());
- cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
- cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
+ cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1));
+ cell->setPort(ID::EN, children[2]->genRTLIL());
+ cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0);
+ cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0);
}
- cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1);
+ cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1);
}
break;
@@ -1453,12 +1444,12 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_FAIR:
case AST_COVER:
{
- const char *celltype = nullptr;
- if (type == AST_ASSERT) celltype = "$assert";
- if (type == AST_ASSUME) celltype = "$assume";
- if (type == AST_LIVE) celltype = "$live";
- if (type == AST_FAIR) celltype = "$fair";
- if (type == AST_COVER) celltype = "$cover";
+ IdString celltype;
+ if (type == AST_ASSERT) celltype = ID($assert);
+ if (type == AST_ASSUME) celltype = ID($assume);
+ if (type == AST_LIVE) celltype = ID($live);
+ if (type == AST_FAIR) celltype = ID($fair);
+ if (type == AST_COVER) celltype = ID($cover);
log_assert(children.size() == 2);
@@ -1471,16 +1462,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
en = current_module->ReduceBool(NEW_ID, en);
IdString cellname;
- if (str.empty()) {
- std::stringstream sstr;
- sstr << celltype << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
- cellname = sstr.str();
- } else {
+ if (str.empty())
+ cellname = stringf("%s$%s:%d$%d", celltype.c_str(), filename.c_str(), location.first_line, autoidx++);
+ else
cellname = str;
- }
RTLIL::Cell *cell = current_module->addCell(cellname, celltype);
- cell->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -1488,8 +1476,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cell->attributes[attr.first] = attr.second->asAttrConst();
}
- cell->setPort("\\A", check);
- cell->setPort("\\EN", en);
+ cell->setPort(ID::A, check);
+ cell->setPort(ID::EN, en);
}
break;
@@ -1525,9 +1513,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Re-definition of cell `%s'!\n", str.c_str());
RTLIL::Cell *cell = current_module->addCell(str, "");
- cell->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
// Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass
- cell->set_bool_attribute("\\module_not_derived");
+ cell->set_bool_attribute(ID::module_not_derived);
for (auto it = children.begin(); it != children.end(); it++) {
AstNode *child = *it;
@@ -1575,29 +1563,29 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value.\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
- if (cell->type == "$specify2") {
- int src_width = GetSize(cell->getPort("\\SRC"));
- int dst_width = GetSize(cell->getPort("\\DST"));
- bool full = cell->getParam("\\FULL").as_bool();
+ if (cell->type == ID($specify2)) {
+ int src_width = GetSize(cell->getPort(ID::SRC));
+ int dst_width = GetSize(cell->getPort(ID::DST));
+ bool full = cell->getParam(ID::FULL).as_bool();
if (!full && src_width != dst_width)
log_file_error(filename, location.first_line, "Parallel specify SRC width does not match DST width.\n");
- cell->setParam("\\SRC_WIDTH", Const(src_width));
- cell->setParam("\\DST_WIDTH", Const(dst_width));
+ cell->setParam(ID::SRC_WIDTH, Const(src_width));
+ cell->setParam(ID::DST_WIDTH, Const(dst_width));
}
- else if (cell->type == "$specify3") {
- int dat_width = GetSize(cell->getPort("\\DAT"));
- int dst_width = GetSize(cell->getPort("\\DST"));
+ else if (cell->type == ID($specify3)) {
+ int dat_width = GetSize(cell->getPort(ID::DAT));
+ int dst_width = GetSize(cell->getPort(ID::DST));
if (dat_width != dst_width)
log_file_error(filename, location.first_line, "Specify DAT width does not match DST width.\n");
- int src_width = GetSize(cell->getPort("\\SRC"));
- cell->setParam("\\SRC_WIDTH", Const(src_width));
- cell->setParam("\\DST_WIDTH", Const(dst_width));
+ int src_width = GetSize(cell->getPort(ID::SRC));
+ cell->setParam(ID::SRC_WIDTH, Const(src_width));
+ cell->setParam(ID::DST_WIDTH, Const(dst_width));
}
- else if (cell->type == "$specrule") {
- int src_width = GetSize(cell->getPort("\\SRC"));
- int dst_width = GetSize(cell->getPort("\\DST"));
- cell->setParam("\\SRC_WIDTH", Const(src_width));
- cell->setParam("\\DST_WIDTH", Const(dst_width));
+ else if (cell->type == ID($specrule)) {
+ int src_width = GetSize(cell->getPort(ID::SRC));
+ int dst_width = GetSize(cell->getPort(ID::DST));
+ cell->setParam(ID::SRC_WIDTH, Const(src_width));
+ cell->setParam(ID::DST_WIDTH, Const(dst_width));
}
}
break;
@@ -1668,19 +1656,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str());
Cell *cell = current_module->addCell(myid, str.substr(1));
- cell->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
- cell->parameters["\\WIDTH"] = width;
+ cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ cell->parameters[ID::WIDTH] = width;
- if (attributes.count("\\reg")) {
- auto &attr = attributes.at("\\reg");
+ if (attributes.count(ID::reg)) {
+ auto &attr = attributes.at(ID::reg);
if (attr->type != AST_CONSTANT)
log_file_error(filename, location.first_line, "Attribute `reg' with non-constant value!\n");
- cell->attributes["\\reg"] = attr->asAttrConst();
+ cell->attributes[ID::reg] = attr->asAttrConst();
}
Wire *wire = current_module->addWire(myid + "_wire", width);
- wire->attributes["\\src"] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
- cell->setPort("\\Y", wire);
+ wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ cell->setPort(ID::Y, wire);
is_signed = sign_hint;
return SigSpec(wire);
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 26c1cc7a9..b87af0f8c 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -172,7 +172,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
deep_recursion_warning = true;
while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
- if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg"))
+ if (!flag_nomem2reg && !get_bool_attribute(ID::nomem2reg))
{
dict<AstNode*, pool<std::string>> mem2reg_places;
dict<AstNode*, uint32_t> mem2reg_candidates, dummy_proc_flags;
@@ -187,10 +187,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
bool this_nomeminit = flag_nomeminit;
log_assert((memflags & ~0x00ffff00) == 0);
- if (mem->get_bool_attribute("\\nomem2reg"))
+ if (mem->get_bool_attribute(ID::nomem2reg))
continue;
- if (mem->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit"))
+ if (mem->get_bool_attribute(ID::nomeminit) || get_bool_attribute(ID::nomeminit))
this_nomeminit = true;
if (memflags & AstNode::MEM2REG_FL_FORCED)
@@ -248,7 +248,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
reg->is_reg = true;
reg->is_signed = node->is_signed;
for (auto &it : node->attributes)
- if (it.first != ID(mem2reg))
+ if (it.first != ID::mem2reg)
reg->attributes.emplace(it.first, it.second->clone());
reg->filename = node->filename;
reg->location = node->location;
@@ -345,9 +345,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
for (auto c : node->children[0]->children) {
if (!c->is_simple_const_expr()) {
- if (attributes.count("\\dynports"))
- delete attributes.at("\\dynports");
- attributes["\\dynports"] = AstNode::mkconst_int(1, true);
+ if (attributes.count(ID::dynports))
+ delete attributes.at(ID::dynports);
+ attributes[ID::dynports] = AstNode::mkconst_int(1, true);
}
}
}
@@ -432,7 +432,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
did_something = true;
if (node->type == AST_ENUM) {
- for (auto enode : node->children){
+ for (auto enode YS_ATTRIBUTE(unused) : node->children){
log_assert(enode->type==AST_ENUM_ITEM);
while (node->simplify(true, false, false, 1, -1, false, in_param))
did_something = true;
@@ -1219,7 +1219,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
wire->str = wire_id;
if (current_block)
- wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
current_ast_mod->children.push_back(wire);
while (wire->simplify(true, false, false, 1, -1, false, false)) { }
@@ -1812,6 +1812,7 @@ skip_dynamic_range_lvalue_expansion:;
newNode->children.push_back(assign_en);
AstNode *assertnode = new AstNode(type);
+ assertnode->location = location;
assertnode->str = str;
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
@@ -1856,7 +1857,7 @@ skip_dynamic_range_lvalue_expansion:;
wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", filename.c_str(), location.first_line, autoidx++);
current_ast_mod->children.push_back(wire_tmp);
current_scope[wire_tmp->str] = wire_tmp;
- wire_tmp->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire_tmp->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
while (wire_tmp->simplify(true, false, false, 1, -1, false, false)) { }
wire_tmp->is_logic = true;
@@ -1898,6 +1899,9 @@ skip_dynamic_range_lvalue_expansion:;
bool mem_signed = children[0]->id2ast->is_signed;
children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
+ newNode = new AstNode(AST_BLOCK);
+ AstNode *defNode = new AstNode(AST_BLOCK);
+
int data_range_left = children[0]->id2ast->children[0]->range_left;
int data_range_right = children[0]->id2ast->children[0]->range_right;
int mem_data_range_offset = std::min(data_range_left, data_range_right);
@@ -1907,31 +1911,6 @@ skip_dynamic_range_lvalue_expansion:;
children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint);
addr_bits = std::max(addr_bits, addr_width_hint);
- AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
- wire_addr->str = id_addr;
- wire_addr->was_checked = true;
- current_ast_mod->children.push_back(wire_addr);
- current_scope[wire_addr->str] = wire_addr;
- while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
-
- AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
- wire_data->str = id_data;
- wire_data->was_checked = true;
- wire_data->is_signed = mem_signed;
- current_ast_mod->children.push_back(wire_data);
- current_scope[wire_data->str] = wire_data;
- while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
-
- AstNode *wire_en = nullptr;
- if (current_always->type != AST_INITIAL) {
- wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
- wire_en->str = id_en;
- wire_en->was_checked = true;
- current_ast_mod->children.push_back(wire_en);
- current_scope[wire_en->str] = wire_en;
- while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
- }
-
std::vector<RTLIL::State> x_bits_addr, x_bits_data, set_bits_en;
for (int i = 0; i < addr_bits; i++)
x_bits_addr.push_back(RTLIL::State::Sx);
@@ -1940,32 +1919,79 @@ skip_dynamic_range_lvalue_expansion:;
for (int i = 0; i < mem_width; i++)
set_bits_en.push_back(RTLIL::State::S1);
- AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
- assign_addr->children[0]->str = id_addr;
- assign_addr->children[0]->was_checked = true;
+ AstNode *node_addr = nullptr;
+ if (children[0]->children[0]->children[0]->isConst()) {
+ node_addr = children[0]->children[0]->children[0]->clone();
+ } else {
+ AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
+ wire_addr->str = id_addr;
+ wire_addr->was_checked = true;
+ current_ast_mod->children.push_back(wire_addr);
+ current_scope[wire_addr->str] = wire_addr;
+ while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
- AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
- assign_data->children[0]->str = id_data;
- assign_data->children[0]->was_checked = true;
+ AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
+ assign_addr->children[0]->str = id_addr;
+ assign_addr->children[0]->was_checked = true;
+ defNode->children.push_back(assign_addr);
- AstNode *assign_en = nullptr;
- if (current_always->type != AST_INITIAL) {
- assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
+ assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
+ assign_addr->children[0]->str = id_addr;
+ assign_addr->children[0]->was_checked = true;
+ newNode->children.push_back(assign_addr);
+
+ node_addr = new AstNode(AST_IDENTIFIER);
+ node_addr->str = id_addr;
+ }
+
+ AstNode *node_data = nullptr;
+ if (children[0]->children.size() == 1 && children[1]->isConst()) {
+ node_data = children[1]->clone();
+ } else {
+ AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
+ wire_data->str = id_data;
+ wire_data->was_checked = true;
+ wire_data->is_signed = mem_signed;
+ current_ast_mod->children.push_back(wire_data);
+ current_scope[wire_data->str] = wire_data;
+ while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
+
+ AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
+ assign_data->children[0]->str = id_data;
+ assign_data->children[0]->was_checked = true;
+ defNode->children.push_back(assign_data);
+
+ node_data = new AstNode(AST_IDENTIFIER);
+ node_data->str = id_data;
+ }
+
+ AstNode *node_en = nullptr;
+ if (current_always->type == AST_INITIAL) {
+ node_en = AstNode::mkconst_int(1, false);
+ } else {
+ AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
+ wire_en->str = id_en;
+ wire_en->was_checked = true;
+ current_ast_mod->children.push_back(wire_en);
+ current_scope[wire_en->str] = wire_en;
+ while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
+
+ AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
assign_en->children[0]->str = id_en;
assign_en->children[0]->was_checked = true;
- }
+ defNode->children.push_back(assign_en);
- AstNode *default_signals = new AstNode(AST_BLOCK);
- default_signals->children.push_back(assign_addr);
- default_signals->children.push_back(assign_data);
- if (current_always->type != AST_INITIAL)
- default_signals->children.push_back(assign_en);
- current_top_block->children.insert(current_top_block->children.begin(), default_signals);
+ node_en = new AstNode(AST_IDENTIFIER);
+ node_en->str = id_en;
+ }
- assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
- assign_addr->children[0]->str = id_addr;
- assign_addr->children[0]->was_checked = true;
+ if (!defNode->children.empty())
+ current_top_block->children.insert(current_top_block->children.begin(), defNode);
+ else
+ delete defNode;
+ AstNode *assign_data = nullptr;
+ AstNode *assign_en = nullptr;
if (children[0]->children.size() == 2)
{
if (children[0]->children[1]->range_valid)
@@ -2026,9 +2052,11 @@ skip_dynamic_range_lvalue_expansion:;
}
else
{
- assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
- assign_data->children[0]->str = id_data;
- assign_data->children[0]->was_checked = true;
+ if (!(children[0]->children.size() == 1 && children[1]->isConst())) {
+ assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
+ assign_data->children[0]->str = id_data;
+ assign_data->children[0]->was_checked = true;
+ }
if (current_always->type != AST_INITIAL) {
assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
@@ -2036,28 +2064,20 @@ skip_dynamic_range_lvalue_expansion:;
assign_en->children[0]->was_checked = true;
}
}
-
- newNode = new AstNode(AST_BLOCK);
- newNode->children.push_back(assign_addr);
- newNode->children.push_back(assign_data);
- if (current_always->type != AST_INITIAL)
+ if (assign_data)
+ newNode->children.push_back(assign_data);
+ if (assign_en)
newNode->children.push_back(assign_en);
- AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR);
- wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
- wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
- if (current_always->type != AST_INITIAL)
- wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
- else
- wrnode->children.push_back(AstNode::mkconst_int(1, false));
+ AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR, node_addr, node_data, node_en);
wrnode->str = children[0]->str;
wrnode->id2ast = children[0]->id2ast;
- wrnode->children[0]->str = id_addr;
- wrnode->children[1]->str = id_data;
- if (current_always->type != AST_INITIAL)
- wrnode->children[2]->str = id_en;
current_ast_mod->children.push_back(wrnode);
+ if (newNode->children.empty()) {
+ delete newNode;
+ newNode = new AstNode();
+ }
goto apply_newNode;
}
@@ -2657,7 +2677,7 @@ skip_dynamic_range_lvalue_expansion:;
wire->is_input = false;
wire->is_output = false;
wire->is_reg = true;
- wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
if (child->type == AST_ENUM_ITEM)
wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"];
@@ -3345,10 +3365,10 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
}
// also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
- if (type == AST_MEMORY && (get_bool_attribute("\\mem2reg") || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg))
+ if (type == AST_MEMORY && (get_bool_attribute(ID::mem2reg) || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg))
mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED;
- if (type == AST_MODULE && get_bool_attribute("\\mem2reg"))
+ if (type == AST_MODULE && get_bool_attribute(ID::mem2reg))
children_flags |= AstNode::MEM2REG_FL_ALL;
dict<AstNode*, uint32_t> *proc_flags_p = NULL;
@@ -3511,7 +3531,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
wire_addr->str = id_addr;
wire_addr->is_reg = true;
wire_addr->was_checked = true;
- wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
mod->children.push_back(wire_addr);
while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
@@ -3520,7 +3540,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
wire_data->is_reg = true;
wire_data->was_checked = true;
wire_data->is_signed = mem_signed;
- wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
mod->children.push_back(wire_data);
while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
@@ -3591,7 +3611,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
wire_addr->is_reg = true;
wire_addr->was_checked = true;
if (block)
- wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
mod->children.push_back(wire_addr);
while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
@@ -3601,7 +3621,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
wire_data->was_checked = true;
wire_data->is_signed = mem_signed;
if (block)
- wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
mod->children.push_back(wire_data);
while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc
index cab210605..7cc157e49 100644
--- a/frontends/blif/blifparse.cc
+++ b/frontends/blif/blifparse.cc
@@ -176,7 +176,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (!strcmp(cmd, ".blackbox"))
{
- module->attributes["\\blackbox"] = RTLIL::Const(1);
+ module->attributes[ID::blackbox] = RTLIL::Const(1);
continue;
}
@@ -215,17 +215,17 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
vector<Cell*> remove_cells;
for (auto cell : module->cells())
- if (cell->type == "$lut" && cell->getParam("\\LUT") == buffer_lut) {
- module->connect(cell->getPort("\\Y"), cell->getPort("\\A"));
+ if (cell->type == ID($lut) && cell->getParam(ID::LUT) == buffer_lut) {
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
remove_cells.push_back(cell);
}
for (auto cell : remove_cells)
module->remove(cell);
- Wire *true_wire = module->wire("$true");
- Wire *false_wire = module->wire("$false");
- Wire *undef_wire = module->wire("$undef");
+ Wire *true_wire = module->wire(ID($true));
+ Wire *false_wire = module->wire(ID($false));
+ Wire *undef_wire = module->wire(ID($undef));
if (true_wire != nullptr)
module->rename(true_wire, stringf("$true$%d", ++blif_maxnum));
@@ -337,7 +337,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
}
if (init != nullptr && (init[0] == '0' || init[0] == '1'))
- blif_wire(q)->attributes["\\init"] = Const(init[0] == '1' ? 1 : 0, 1);
+ blif_wire(q)->attributes[ID::init] = Const(init[0] == '1' ? 1 : 0, 1);
if (clock == nullptr)
goto no_latch_clock;
@@ -356,8 +356,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
cell = module->addFf(NEW_ID, blif_wire(d), blif_wire(q));
} else {
cell = module->addCell(NEW_ID, dff_name);
- cell->setPort("\\D", blif_wire(d));
- cell->setPort("\\Q", blif_wire(q));
+ cell->setPort(ID::D, blif_wire(d));
+ cell->setPort(ID::Q, blif_wire(q));
}
}
@@ -476,7 +476,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
finished_parsing_constval:
if (state == RTLIL::State::Sa)
state = RTLIL::State::S0;
- if (output_sig.as_wire()->name == "$undef")
+ if (output_sig.as_wire()->name == ID($undef))
state = RTLIL::State::Sx;
module->connect(RTLIL::SigSig(output_sig, state));
goto continue_without_read;
@@ -484,23 +484,23 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (sop_mode)
{
- sopcell = module->addCell(NEW_ID, "$sop");
- sopcell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size());
- sopcell->parameters["\\DEPTH"] = 0;
- sopcell->parameters["\\TABLE"] = RTLIL::Const();
- sopcell->setPort("\\A", input_sig);
- sopcell->setPort("\\Y", output_sig);
+ sopcell = module->addCell(NEW_ID, ID($sop));
+ sopcell->parameters[ID::WIDTH] = RTLIL::Const(input_sig.size());
+ sopcell->parameters[ID::DEPTH] = 0;
+ sopcell->parameters[ID::TABLE] = RTLIL::Const();
+ sopcell->setPort(ID::A, input_sig);
+ sopcell->setPort(ID::Y, output_sig);
sopmode = -1;
lastcell = sopcell;
}
else
{
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut");
- cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size());
- cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size());
- cell->setPort("\\A", input_sig);
- cell->setPort("\\Y", output_sig);
- lutptr = &cell->parameters.at("\\LUT");
+ RTLIL::Cell *cell = module->addCell(NEW_ID, ID($lut));
+ cell->parameters[ID::WIDTH] = RTLIL::Const(input_sig.size());
+ cell->parameters[ID::LUT] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size());
+ cell->setPort(ID::A, input_sig);
+ cell->setPort(ID::Y, output_sig);
+ lutptr = &cell->parameters.at(ID::LUT);
lut_default_state = RTLIL::State::Sx;
lastcell = cell;
}
@@ -523,32 +523,32 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (sopcell)
{
- log_assert(sopcell->parameters["\\WIDTH"].as_int() == input_len);
- sopcell->parameters["\\DEPTH"] = sopcell->parameters["\\DEPTH"].as_int() + 1;
+ log_assert(sopcell->parameters[ID::WIDTH].as_int() == input_len);
+ sopcell->parameters[ID::DEPTH] = sopcell->parameters[ID::DEPTH].as_int() + 1;
for (int i = 0; i < input_len; i++)
switch (input[i]) {
case '0':
- sopcell->parameters["\\TABLE"].bits.push_back(State::S1);
- sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
+ sopcell->parameters[ID::TABLE].bits.push_back(State::S1);
+ sopcell->parameters[ID::TABLE].bits.push_back(State::S0);
break;
case '1':
- sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
- sopcell->parameters["\\TABLE"].bits.push_back(State::S1);
+ sopcell->parameters[ID::TABLE].bits.push_back(State::S0);
+ sopcell->parameters[ID::TABLE].bits.push_back(State::S1);
break;
default:
- sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
- sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
+ sopcell->parameters[ID::TABLE].bits.push_back(State::S0);
+ sopcell->parameters[ID::TABLE].bits.push_back(State::S0);
break;
}
if (sopmode == -1) {
sopmode = (*output == '1');
if (!sopmode) {
- SigSpec outnet = sopcell->getPort("\\Y");
+ SigSpec outnet = sopcell->getPort(ID::Y);
SigSpec tempnet = module->addWire(NEW_ID);
module->addNotGate(NEW_ID, tempnet, outnet);
- sopcell->setPort("\\Y", tempnet);
+ sopcell->setPort(ID::Y, tempnet);
}
} else
log_assert(sopmode == (*output == '1'));
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index 14de95e07..6f0c3fefa 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -55,37 +55,37 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
static RTLIL::SigSpec create_inv_cell(RTLIL::Module *module, RTLIL::SigSpec A)
{
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$_NOT_");
- cell->setPort("\\A", A);
- cell->setPort("\\Y", module->addWire(NEW_ID));
- return cell->getPort("\\Y");
+ RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_));
+ cell->setPort(ID::A, A);
+ cell->setPort(ID::Y, module->addWire(NEW_ID));
+ return cell->getPort(ID::Y);
}
static RTLIL::SigSpec create_xor_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
{
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$_XOR_");
- cell->setPort("\\A", A);
- cell->setPort("\\B", B);
- cell->setPort("\\Y", module->addWire(NEW_ID));
- return cell->getPort("\\Y");
+ RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_XOR_));
+ cell->setPort(ID::A, A);
+ cell->setPort(ID::B, B);
+ cell->setPort(ID::Y, module->addWire(NEW_ID));
+ return cell->getPort(ID::Y);
}
static RTLIL::SigSpec create_and_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
{
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$_AND_");
- cell->setPort("\\A", A);
- cell->setPort("\\B", B);
- cell->setPort("\\Y", module->addWire(NEW_ID));
- return cell->getPort("\\Y");
+ RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_AND_));
+ cell->setPort(ID::A, A);
+ cell->setPort(ID::B, B);
+ cell->setPort(ID::Y, module->addWire(NEW_ID));
+ return cell->getPort(ID::Y);
}
static RTLIL::SigSpec create_or_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
{
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$_OR_");
- cell->setPort("\\A", A);
- cell->setPort("\\B", B);
- cell->setPort("\\Y", module->addWire(NEW_ID));
- return cell->getPort("\\Y");
+ RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_OR_));
+ cell->setPort(ID::A, A);
+ cell->setPort(ID::B, B);
+ cell->setPort(ID::Y, module->addWire(NEW_ID));
+ return cell->getPort(ID::Y);
}
static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack, token_t next_token)
@@ -241,32 +241,32 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node)
rerun_invert_rollback = false;
for (auto &it : module->cells_) {
- if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == clk_sig) {
- clk_sig = it.second->getPort("\\A");
+ if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == clk_sig) {
+ clk_sig = it.second->getPort(ID::A);
clk_polarity = !clk_polarity;
rerun_invert_rollback = true;
}
- if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == clear_sig) {
- clear_sig = it.second->getPort("\\A");
+ if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == clear_sig) {
+ clear_sig = it.second->getPort(ID::A);
clear_polarity = !clear_polarity;
rerun_invert_rollback = true;
}
- if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == preset_sig) {
- preset_sig = it.second->getPort("\\A");
+ if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == preset_sig) {
+ preset_sig = it.second->getPort(ID::A);
preset_polarity = !preset_polarity;
rerun_invert_rollback = true;
}
}
}
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$_NOT_");
- cell->setPort("\\A", iq_sig);
- cell->setPort("\\Y", iqn_sig);
+ RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_));
+ cell->setPort(ID::A, iq_sig);
+ cell->setPort(ID::Y, iqn_sig);
cell = module->addCell(NEW_ID, "");
- cell->setPort("\\D", data_sig);
- cell->setPort("\\Q", iq_sig);
- cell->setPort("\\C", clk_sig);
+ cell->setPort(ID::D, data_sig);
+ cell->setPort(ID::Q, iq_sig);
+ cell->setPort(ID::C, clk_sig);
if (clear_sig.size() == 0 && preset_sig.size() == 0) {
cell->type = stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N');
@@ -274,18 +274,18 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node)
if (clear_sig.size() == 1 && preset_sig.size() == 0) {
cell->type = stringf("$_DFF_%c%c0_", clk_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N');
- cell->setPort("\\R", clear_sig);
+ cell->setPort(ID::R, clear_sig);
}
if (clear_sig.size() == 0 && preset_sig.size() == 1) {
cell->type = stringf("$_DFF_%c%c1_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N');
- cell->setPort("\\R", preset_sig);
+ cell->setPort(ID::R, preset_sig);
}
if (clear_sig.size() == 1 && preset_sig.size() == 1) {
cell->type = stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N');
- cell->setPort("\\S", preset_sig);
- cell->setPort("\\R", clear_sig);
+ cell->setPort(ID::S, preset_sig);
+ cell->setPort(ID::R, clear_sig);
}
log_assert(!cell->type.empty());
@@ -324,27 +324,27 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno
rerun_invert_rollback = false;
for (auto &it : module->cells_) {
- if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == enable_sig) {
- enable_sig = it.second->getPort("\\A");
+ if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == enable_sig) {
+ enable_sig = it.second->getPort(ID::A);
enable_polarity = !enable_polarity;
rerun_invert_rollback = true;
}
- if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == clear_sig) {
- clear_sig = it.second->getPort("\\A");
+ if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == clear_sig) {
+ clear_sig = it.second->getPort(ID::A);
clear_polarity = !clear_polarity;
rerun_invert_rollback = true;
}
- if (it.second->type == "$_NOT_" && it.second->getPort("\\Y") == preset_sig) {
- preset_sig = it.second->getPort("\\A");
+ if (it.second->type == ID($_NOT_) && it.second->getPort(ID::Y) == preset_sig) {
+ preset_sig = it.second->getPort(ID::A);
preset_polarity = !preset_polarity;
rerun_invert_rollback = true;
}
}
}
- RTLIL::Cell *cell = module->addCell(NEW_ID, "$_NOT_");
- cell->setPort("\\A", iq_sig);
- cell->setPort("\\Y", iqn_sig);
+ RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_));
+ cell->setPort(ID::A, iq_sig);
+ cell->setPort(ID::Y, iqn_sig);
if (clear_sig.size() == 1)
{
@@ -353,25 +353,25 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno
if (clear_polarity == true || clear_polarity != enable_polarity)
{
- RTLIL::Cell *inv = module->addCell(NEW_ID, "$_NOT_");
- inv->setPort("\\A", clear_sig);
- inv->setPort("\\Y", module->addWire(NEW_ID));
+ RTLIL::Cell *inv = module->addCell(NEW_ID, ID($_NOT_));
+ inv->setPort(ID::A, clear_sig);
+ inv->setPort(ID::Y, module->addWire(NEW_ID));
if (clear_polarity == true)
- clear_negative = inv->getPort("\\Y");
+ clear_negative = inv->getPort(ID::Y);
if (clear_polarity != enable_polarity)
- clear_enable = inv->getPort("\\Y");
+ clear_enable = inv->getPort(ID::Y);
}
- RTLIL::Cell *data_gate = module->addCell(NEW_ID, "$_AND_");
- data_gate->setPort("\\A", data_sig);
- data_gate->setPort("\\B", clear_negative);
- data_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID));
+ RTLIL::Cell *data_gate = module->addCell(NEW_ID, ID($_AND_));
+ data_gate->setPort(ID::A, data_sig);
+ data_gate->setPort(ID::B, clear_negative);
+ data_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID));
- RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? "$_OR_" : "$_AND_");
- enable_gate->setPort("\\A", enable_sig);
- enable_gate->setPort("\\B", clear_enable);
- enable_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID));
+ RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_));
+ enable_gate->setPort(ID::A, enable_sig);
+ enable_gate->setPort(ID::B, clear_enable);
+ enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID));
}
if (preset_sig.size() == 1)
@@ -381,31 +381,31 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno
if (preset_polarity == false || preset_polarity != enable_polarity)
{
- RTLIL::Cell *inv = module->addCell(NEW_ID, "$_NOT_");
- inv->setPort("\\A", preset_sig);
- inv->setPort("\\Y", module->addWire(NEW_ID));
+ RTLIL::Cell *inv = module->addCell(NEW_ID, ID($_NOT_));
+ inv->setPort(ID::A, preset_sig);
+ inv->setPort(ID::Y, module->addWire(NEW_ID));
if (preset_polarity == false)
- preset_positive = inv->getPort("\\Y");
+ preset_positive = inv->getPort(ID::Y);
if (preset_polarity != enable_polarity)
- preset_enable = inv->getPort("\\Y");
+ preset_enable = inv->getPort(ID::Y);
}
- RTLIL::Cell *data_gate = module->addCell(NEW_ID, "$_OR_");
- data_gate->setPort("\\A", data_sig);
- data_gate->setPort("\\B", preset_positive);
- data_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID));
+ RTLIL::Cell *data_gate = module->addCell(NEW_ID, ID($_OR_));
+ data_gate->setPort(ID::A, data_sig);
+ data_gate->setPort(ID::B, preset_positive);
+ data_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID));
- RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? "$_OR_" : "$_AND_");
- enable_gate->setPort("\\A", enable_sig);
- enable_gate->setPort("\\B", preset_enable);
- enable_gate->setPort("\\Y", data_sig = module->addWire(NEW_ID));
+ RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_));
+ enable_gate->setPort(ID::A, enable_sig);
+ enable_gate->setPort(ID::B, preset_enable);
+ enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID));
}
cell = module->addCell(NEW_ID, stringf("$_DLATCH_%c_", enable_polarity ? 'P' : 'N'));
- cell->setPort("\\D", data_sig);
- cell->setPort("\\Q", iq_sig);
- cell->setPort("\\E", enable_sig);
+ cell->setPort(ID::D, data_sig);
+ cell->setPort(ID::Q, iq_sig);
+ cell->setPort(ID::E, enable_sig);
return true;
}
@@ -550,13 +550,13 @@ struct LibertyFrontend : public Frontend {
if (design->has(cell_name)) {
Module *existing_mod = design->module(cell_name);
- if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
+ if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
log_error("Re-definition of cell/module %s!\n", log_id(cell_name));
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", log_id(cell_name));
continue;
} else {
- log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", log_id(cell_name));
+ log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", log_id(cell_name));
design->remove(existing_mod);
}
}
@@ -570,7 +570,7 @@ struct LibertyFrontend : public Frontend {
module->name = cell_name;
if (flag_lib)
- module->set_bool_attribute("\\blackbox");
+ module->set_bool_attribute(ID::blackbox);
for (auto &attr : attributes)
module->attributes[attr] = 1;
diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc
index add17c243..a23f7548e 100644
--- a/frontends/rpc/rpc_frontend.cc
+++ b/frontends/rpc/rpc_frontend.cc
@@ -157,7 +157,7 @@ struct RpcServer {
struct RpcModule : RTLIL::Module {
std::shared_ptr<RpcServer> server;
- RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool /*mayfail*/) YS_OVERRIDE {
+ RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool /*mayfail*/) YS_OVERRIDE {
std::string stripped_name = name.str();
if (stripped_name.compare(0, 9, "$abstract") == 0)
stripped_name = stripped_name.substr(9);
@@ -216,7 +216,7 @@ struct RpcModule : RTLIL::Module {
module.second->name = mangled_name;
module.second->design = design;
- module.second->attributes.erase("\\top");
+ module.second->attributes.erase(ID::top);
design->modules_[mangled_name] = module.second;
derived_design->modules_.erase(module.first);
}
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index ae5815f8e..519151310 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -155,7 +155,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
Att *attr;
if (obj->Linefile())
- attributes["\\src"] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile()));
+ attributes[ID::src] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile()));
// FIXME: Parse numeric attributes
FOREACH_ATTRIBUTE(obj, mi, attr) {
@@ -738,7 +738,7 @@ void VerificImporter::merge_past_ffs_clock(pool<RTLIL::Cell*> &candidates, SigBi
SigSpec dbits;
for (auto cell : candidates) {
- SigBit bit = sigmap(cell->getPort("\\D"));
+ SigBit bit = sigmap(cell->getPort(ID::D));
dbits_db[bit].insert(cell);
dbits.append(bit);
}
@@ -764,7 +764,7 @@ void VerificImporter::merge_past_ffs_clock(pool<RTLIL::Cell*> &candidates, SigBi
if (verific_verbose)
log(" replacing old ff %s on bit %d.\n", log_id(old_ff), i);
- SigBit old_q = old_ff->getPort("\\Q");
+ SigBit old_q = old_ff->getPort(ID::Q);
SigBit new_q = sig_q[i];
sigmap.add(old_q, new_q);
@@ -783,8 +783,8 @@ void VerificImporter::merge_past_ffs(pool<RTLIL::Cell*> &candidates)
for (auto cell : candidates)
{
- SigBit clock = cell->getPort("\\CLK");
- bool clock_pol = cell->getParam("\\CLK_POLARITY").as_bool();
+ SigBit clock = cell->getPort(ID::CLK);
+ bool clock_pol = cell->getParam(ID::CLK_POLARITY).as_bool();
database[make_pair(clock, int(clock_pol))].insert(cell);
}
@@ -822,7 +822,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (is_blackbox(nl)) {
log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name));
- module->set_bool_attribute("\\blackbox");
+ module->set_bool_attribute(ID::blackbox);
} else {
log("Importing module %s.\n", RTLIL::id2cstr(module->name));
}
@@ -952,17 +952,17 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
ascii_initdata++;
}
if (initval_valid) {
- RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit");
- cell->parameters["\\WORDS"] = 1;
+ RTLIL::Cell *cell = module->addCell(new_verific_id(net), ID($meminit));
+ cell->parameters[ID::WORDS] = 1;
if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound())
- cell->setPort("\\ADDR", word_idx);
+ cell->setPort(ID::ADDR, word_idx);
else
- cell->setPort("\\ADDR", memory->size - word_idx - 1);
- cell->setPort("\\DATA", initval);
- cell->parameters["\\MEMID"] = RTLIL::Const(memory->name.str());
- cell->parameters["\\ABITS"] = 32;
- cell->parameters["\\WIDTH"] = memory->width;
- cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1);
+ cell->setPort(ID::ADDR, memory->size - word_idx - 1);
+ cell->setPort(ID::DATA, initval);
+ cell->parameters[ID::MEMID] = RTLIL::Const(memory->name.str());
+ cell->parameters[ID::ABITS] = 32;
+ cell->parameters[ID::WIDTH] = memory->width;
+ cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1);
}
}
}
@@ -1079,7 +1079,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
}
if (initval_valid)
- wire->attributes["\\init"] = initval;
+ wire->attributes[ID::init] = initval;
}
else
{
@@ -1133,8 +1133,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
SigBit bit = net_map_at(it.first);
log_assert(bit.wire);
- if (bit.wire->attributes.count("\\init"))
- initval = bit.wire->attributes.at("\\init");
+ if (bit.wire->attributes.count(ID::init))
+ initval = bit.wire->attributes.at(ID::init);
while (GetSize(initval) < GetSize(bit.wire))
initval.bits.push_back(State::Sx);
@@ -1144,7 +1144,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (it.second == '1')
initval.bits.at(bit.offset) = State::S1;
- bit.wire->attributes["\\init"] = initval;
+ bit.wire->attributes[ID::init] = initval;
}
for (auto net : anyconst_nets)
@@ -1212,17 +1212,17 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
RTLIL::SigSpec data = operatorOutput(inst).extract(i * memory->width, memory->width);
RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name :
- RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memrd");
- cell->parameters["\\MEMID"] = memory->name.str();
- cell->parameters["\\CLK_ENABLE"] = false;
- cell->parameters["\\CLK_POLARITY"] = true;
- cell->parameters["\\TRANSPARENT"] = false;
- cell->parameters["\\ABITS"] = GetSize(addr);
- cell->parameters["\\WIDTH"] = GetSize(data);
- cell->setPort("\\CLK", RTLIL::State::Sx);
- cell->setPort("\\EN", RTLIL::State::Sx);
- cell->setPort("\\ADDR", addr);
- cell->setPort("\\DATA", data);
+ RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memrd));
+ cell->parameters[ID::MEMID] = memory->name.str();
+ cell->parameters[ID::CLK_ENABLE] = false;
+ cell->parameters[ID::CLK_POLARITY] = true;
+ cell->parameters[ID::TRANSPARENT] = false;
+ cell->parameters[ID::ABITS] = GetSize(addr);
+ cell->parameters[ID::WIDTH] = GetSize(data);
+ cell->setPort(ID::CLK, RTLIL::State::Sx);
+ cell->setPort(ID::EN, RTLIL::State::Sx);
+ cell->setPort(ID::ADDR, addr);
+ cell->setPort(ID::DATA, data);
}
continue;
}
@@ -1242,21 +1242,21 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
RTLIL::SigSpec data = operatorInput2(inst).extract(i * memory->width, memory->width);
RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name :
- RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memwr");
- cell->parameters["\\MEMID"] = memory->name.str();
- cell->parameters["\\CLK_ENABLE"] = false;
- cell->parameters["\\CLK_POLARITY"] = true;
- cell->parameters["\\PRIORITY"] = 0;
- cell->parameters["\\ABITS"] = GetSize(addr);
- cell->parameters["\\WIDTH"] = GetSize(data);
- cell->setPort("\\EN", RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data)));
- cell->setPort("\\CLK", RTLIL::State::S0);
- cell->setPort("\\ADDR", addr);
- cell->setPort("\\DATA", data);
+ RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memwr));
+ cell->parameters[ID::MEMID] = memory->name.str();
+ cell->parameters[ID::CLK_ENABLE] = false;
+ cell->parameters[ID::CLK_POLARITY] = true;
+ cell->parameters[ID::PRIORITY] = 0;
+ cell->parameters[ID::ABITS] = GetSize(addr);
+ cell->parameters[ID::WIDTH] = GetSize(data);
+ cell->setPort(ID::EN, RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data)));
+ cell->setPort(ID::CLK, RTLIL::State::S0);
+ cell->setPort(ID::ADDR, addr);
+ cell->setPort(ID::DATA, data);
if (inst->Type() == OPER_CLOCKED_WRITE_PORT) {
- cell->parameters["\\CLK_ENABLE"] = true;
- cell->setPort("\\CLK", net_map_at(inst->GetClock()));
+ cell->parameters[ID::CLK_ENABLE] = true;
+ cell->setPort(ID::CLK, net_map_at(inst->GetClock()));
}
}
continue;
@@ -1431,7 +1431,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
RTLIL::Cell *cell = module->addCell(inst_name, inst_type);
if (inst->IsPrimitive() && mode_keep)
- cell->attributes["\\keep"] = 1;
+ cell->attributes[ID::keep] = 1;
dict<IdString, vector<SigBit>> cell_port_conns;
@@ -1514,10 +1514,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
for (auto wire : module->wires())
{
- if (!wire->attributes.count("\\init"))
+ if (!wire->attributes.count(ID::init))
continue;
- Const &initval = wire->attributes.at("\\init");
+ Const &initval = wire->attributes.at(ID::init);
for (int i = 0; i < GetSize(initval); i++)
{
if (initval[i] != State::S0 && initval[i] != State::S1)
@@ -1528,7 +1528,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
}
if (initval.is_fully_undef())
- wire->attributes.erase("\\init");
+ wire->attributes.erase(ID::init);
}
}
}
@@ -1652,10 +1652,10 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const
if (GetSize(init_value) != 0) {
log_assert(GetSize(sig_q) == GetSize(init_value));
if (sig_q.is_wire()) {
- sig_q.as_wire()->attributes["\\init"] = init_value;
+ sig_q.as_wire()->attributes[ID::init] = init_value;
} else {
Wire *w = module->addWire(NEW_ID, GetSize(sig_q));
- w->attributes["\\init"] = init_value;
+ w->attributes[ID::init] = init_value;
module->connect(sig_q, w);
sig_q = w;
}
diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc
index 6a8462b41..cf9b9531e 100644
--- a/frontends/verilog/Makefile.inc
+++ b/frontends/verilog/Makefile.inc
@@ -10,7 +10,7 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc
-frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l
+frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc
$(Q) mkdir -p $(dir $@)
$(P) flex -o frontends/verilog/verilog_lexer.cc $<
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc
index 49281f7e7..230dfadbf 100644
--- a/frontends/verilog/const2ast.cc
+++ b/frontends/verilog/const2ast.cc
@@ -139,6 +139,9 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
data.resize(len_in_bits, msb);
}
+ if (len_in_bits == 0)
+ log_file_error(current_filename, get_line_num(), "Illegal integer constant size of zero (IEEE 1800-2012, 5.7).\n");
+
if (len > len_in_bits)
log_warning("Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n",
len_in_bits, len, current_filename.c_str(), get_line_num());
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index 161253a99..7905ea598 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -32,8 +32,10 @@
*
*/
+#include "preproc.h"
#include "verilog_frontend.h"
#include "kernel/log.h"
+#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@@ -199,6 +201,175 @@ static std::string next_token(bool pass_newline = false)
return token;
}
+struct macro_arg_t
+{
+ macro_arg_t(const std::string &name_, const char *default_value_)
+ : name(name_),
+ has_default(default_value_ != nullptr),
+ default_value(default_value_ ? default_value_ : "")
+ {}
+
+ std::string name;
+ bool has_default;
+ std::string default_value;
+};
+
+static bool all_white(const std::string &str)
+{
+ for (char c : str)
+ if (!isspace(c))
+ return false;
+ return true;
+}
+
+struct arg_map_t
+{
+ arg_map_t()
+ {}
+
+ void add_arg(const std::string &name, const char *default_value)
+ {
+ if (find(name)) {
+ log_error("Duplicate macro arguments with name `%s'.\n", name.c_str());
+ }
+
+ name_to_pos[name] = args.size();
+ args.push_back(macro_arg_t(name, default_value));
+ }
+
+ // Find an argument by name; return nullptr if it doesn't exist. If pos is not null, write
+ // the argument's position to it on success.
+ const macro_arg_t *find(const std::string &name, int *pos = nullptr) const
+ {
+ auto it = name_to_pos.find(name);
+ if (it == name_to_pos.end())
+ return nullptr;
+
+ if (pos) *pos = it->second;
+ return &args[it->second];
+ }
+
+ // Construct the name for the local macro definition we use for the given argument
+ // (something like macro_foobar_arg2). This doesn't include the leading backtick.
+ static std::string str_token(const std::string &macro_name, int pos)
+ {
+ return stringf("macro_%s_arg%d", macro_name.c_str(), pos);
+ }
+
+ // Return definitions for the macro arguments (so that substituting in the macro body and
+ // then performing macro expansion will do argument substitution properly).
+ std::vector<std::pair<std::string, std::string>>
+ get_vals(const std::string &macro_name, const std::vector<std::string> &arg_vals) const
+ {
+ std::vector<std::pair<std::string, std::string>> ret;
+ for (int i = 0; i < GetSize(args); ++ i) {
+ // The SystemVerilog rules are:
+ //
+ // - If the call site specifies an argument and it's not whitespace, use
+ // it.
+ //
+ // - Otherwise, if the argument has a default value, use it.
+ //
+ // - Otherwise, if the call site specified whitespace, use that.
+ //
+ // - Otherwise, error.
+ const std::string *dflt = nullptr;
+ if (args[i].has_default)
+ dflt = &args[i].default_value;
+
+ const std::string *given = nullptr;
+ if (i < GetSize(arg_vals))
+ given = &arg_vals[i];
+
+ const std::string *val = nullptr;
+ if (given && (! (dflt && all_white(*given))))
+ val = given;
+ else if (dflt)
+ val = dflt;
+ else if (given)
+ val = given;
+ else
+ log_error("Cannot expand macro `%s by giving only %d argument%s "
+ "(argument %d has no default).\n",
+ macro_name.c_str(), GetSize(arg_vals),
+ (GetSize(arg_vals) == 1 ? "" : "s"), i + 1);
+
+ assert(val);
+ ret.push_back(std::make_pair(str_token(macro_name, i), * val));
+ }
+ return ret;
+ }
+
+
+ std::vector<macro_arg_t> args;
+ std::map<std::string, int> name_to_pos;
+};
+
+struct define_body_t
+{
+ define_body_t(const std::string &body, const arg_map_t *args = nullptr)
+ : body(body),
+ has_args(args != nullptr),
+ args(args ? *args : arg_map_t())
+ {}
+
+ std::string body;
+ bool has_args;
+ arg_map_t args;
+};
+
+define_map_t::define_map_t()
+{
+ add("YOSYS", "1");
+ add(formal_mode ? "FORMAL" : "SYNTHESIS", "1");
+}
+
+// We must define this destructor here (rather than relying on the default), because we need to
+// define it somewhere we've got a complete definition of define_body_t.
+define_map_t::~define_map_t()
+{}
+
+void
+define_map_t::add(const std::string &name, const std::string &txt, const arg_map_t *args)
+{
+ defines[name] = std::unique_ptr<define_body_t>(new define_body_t(txt, args));
+}
+
+void define_map_t::merge(const define_map_t &map)
+{
+ for (const auto &pr : map.defines) {
+ // These contortions are so that we take a copy of each definition body in
+ // map.defines.
+ defines[pr.first] = std::unique_ptr<define_body_t>(new define_body_t(*pr.second));
+ }
+}
+
+const define_body_t *define_map_t::find(const std::string &name) const
+{
+ auto it = defines.find(name);
+ return (it == defines.end()) ? nullptr : it->second.get();
+}
+
+void define_map_t::erase(const std::string &name)
+{
+ defines.erase(name);
+}
+
+void define_map_t::clear()
+{
+ defines.clear();
+}
+
+void define_map_t::log() const
+{
+ for (auto &it : defines) {
+ const std::string &name = it.first;
+ const define_body_t &body = *it.second;
+ Yosys::log("`define %s%s %s\n",
+ name.c_str(), body.has_args ? "()" : "", body.body.c_str());
+ }
+}
+
static void input_file(std::istream &f, std::string filename)
{
char buffer[513];
@@ -215,11 +386,59 @@ static void input_file(std::istream &f, std::string filename)
input_buffer.insert(it, "\n`file_pop\n");
}
+// Read tokens to get one argument (either a macro argument at a callsite or a default argument in a
+// macro definition). Writes the argument to dest. Returns true if we finished with ')' (the end of
+// the argument list); false if we finished with ','.
+static bool read_argument(std::string &dest)
+{
+ std::vector<char> openers;
+ for (;;) {
+ skip_spaces();
+ std::string tok = next_token(true);
+ if (tok == ")") {
+ if (openers.empty())
+ return true;
+ if (openers.back() != '(')
+ log_error("Mismatched brackets in macro argument: %c and %c.\n",
+ openers.back(), tok[0]);
+
+ openers.pop_back();
+ dest += tok;
+ continue;
+ }
+ if (tok == "]") {
+ char opener = openers.empty() ? '(' : openers.back();
+ if (opener != '[')
+ log_error("Mismatched brackets in macro argument: %c and %c.\n",
+ opener, tok[0]);
+
+ openers.pop_back();
+ dest += tok;
+ continue;
+ }
+ if (tok == "}") {
+ char opener = openers.empty() ? '(' : openers.back();
+ if (opener != '{')
+ log_error("Mismatched brackets in macro argument: %c and %c.\n",
+ opener, tok[0]);
+
+ openers.pop_back();
+ dest += tok;
+ continue;
+ }
+
+ if (tok == "," && openers.empty()) {
+ return false;
+ }
+
+ if (tok == "(" || tok == "[" || tok == "{")
+ openers.push_back(tok[0]);
-static bool try_expand_macro(std::set<std::string> &defines_with_args,
- std::map<std::string, std::string> &defines_map,
- std::string &tok
- )
+ dest += tok;
+ }
+}
+
+static bool try_expand_macro(define_map_t &defines, std::string &tok)
{
if (tok == "`\"") {
std::string literal("\"");
@@ -229,54 +448,272 @@ static bool try_expand_macro(std::set<std::string> &defines_with_args,
if (ntok == "`\"") {
insert_input(literal+"\"");
return true;
- } else if (!try_expand_macro(defines_with_args, defines_map, ntok)) {
+ } else if (!try_expand_macro(defines, ntok)) {
literal += ntok;
}
}
return false; // error - unmatched `"
- } else if (tok.size() > 1 && tok[0] == '`' && defines_map.count(tok.substr(1)) > 0) {
- std::string name = tok.substr(1);
- // printf("expand: >>%s<< -> >>%s<<\n", name.c_str(), defines_map[name].c_str());
- std::string skipped_spaces = skip_spaces();
- tok = next_token(false);
- if (tok == "(" && defines_with_args.count(name) > 0) {
- int level = 1;
- std::vector<std::string> args;
- args.push_back(std::string());
- while (1)
- {
- skip_spaces();
- tok = next_token(true);
- if (tok == ")" || tok == "}" || tok == "]")
- level--;
- if (level == 0)
- break;
- if (level == 1 && tok == ",")
- args.push_back(std::string());
- else
- args.back() += tok;
- if (tok == "(" || tok == "{" || tok == "[")
- level++;
- }
- for (int i = 0; i < GetSize(args); i++)
- defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i];
- } else {
- insert_input(tok);
- insert_input(skipped_spaces);
- }
- insert_input(defines_map[name]);
- return true;
- } else if (tok == "``") {
+ }
+
+ if (tok == "``") {
// Swallow `` in macro expansion
return true;
- } else return false;
+ }
+
+ if (tok.size() <= 1 || tok[0] != '`')
+ return false;
+
+ // This token looks like a macro name (`foo).
+ std::string macro_name = tok.substr(1);
+ const define_body_t *body = defines.find(tok.substr(1));
+
+ if (! body) {
+ // Apparently not a name we know.
+ return false;
+ }
+
+ std::string name = tok.substr(1);
+ std::string skipped_spaces = skip_spaces();
+ tok = next_token(false);
+ if (tok == "(" && body->has_args) {
+ std::vector<std::string> args;
+ bool done = false;
+ while (!done) {
+ std::string arg;
+ done = read_argument(arg);
+ args.push_back(arg);
+ }
+ for (const auto &pr : body->args.get_vals(name, args)) {
+ defines.add(pr.first, pr.second);
+ }
+ } else {
+ insert_input(tok);
+ insert_input(skipped_spaces);
+ }
+ insert_input(body->body);
+ return true;
}
-std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map<std::string, std::string> &pre_defines_map,
- dict<std::string, std::pair<std::string, bool>> &global_defines_cache, const std::list<std::string> &include_dirs)
+// Read the arguments for a `define preprocessor directive with formal arguments. This is called
+// just after reading the token containing "(". Returns the number of newlines to emit afterwards to
+// keep line numbers in sync, together with the map from argument name to data (pos and default
+// value).
+static std::pair<int, arg_map_t>
+read_define_args()
{
- std::set<std::string> defines_with_args;
- std::map<std::string, std::string> defines_map(pre_defines_map);
+ // Each argument looks like one of the following:
+ //
+ // identifier
+ // identifier = default_text
+ // identifier =
+ //
+ // The first example is an argument with no default value. The second is an argument whose
+ // default value is default_text. The third is an argument with default value the empty
+ // string.
+
+ int newline_count = 0;
+ arg_map_t args;
+
+ // FSM state.
+ //
+ // 0: At start of identifier
+ // 1: After identifier (stored in arg_name)
+ // 2: After closing paren
+ int state = 0;
+
+ std::string arg_name, default_val;
+
+ skip_spaces();
+ for (;;) {
+ if (state == 2)
+ // We've read the closing paren.
+ break;
+
+ std::string tok = next_token();
+
+ // Cope with escaped EOLs
+ if (tok == "\\") {
+ char ch = next_char();
+ if (ch == '\n') {
+ // Eat the \, the \n and any trailing space and keep going.
+ skip_spaces();
+ continue;
+ } else {
+ // There aren't any other situations where a backslash makes sense.
+ log_error("Backslash in macro arguments (not at end of line).\n");
+ }
+ }
+
+ switch (state) {
+ case 0:
+ // At start of argument. If the token is ')', we've presumably just seen
+ // something like "`define foo() ...". Set state to 2 to finish. Otherwise,
+ // the token should be a valid simple identifier, but we'll allow anything
+ // here.
+ if (tok == ")") {
+ state = 2;
+ } else {
+ arg_name = tok;
+ state = 1;
+ }
+ skip_spaces();
+ break;
+
+ case 1:
+ // After argument. The token should either be an equals sign or a comma or
+ // closing paren.
+ if (tok == "=") {
+ std::string default_val;
+ //Read an argument into default_val and set state to 2 if we're at
+ // the end; 0 if we hit a comma.
+ state = read_argument(default_val) ? 2 : 0;
+ args.add_arg(arg_name, default_val.c_str());
+ skip_spaces();
+ break;
+ }
+ if (tok == ",") {
+ // Take the identifier as an argument with no default value.
+ args.add_arg(arg_name, nullptr);
+ state = 0;
+ skip_spaces();
+ break;
+ }
+ if (tok == ")") {
+ // As with comma, but set state to 2 (end of args)
+ args.add_arg(arg_name, nullptr);
+ state = 2;
+ skip_spaces();
+ break;
+ }
+ log_error("Trailing contents after identifier in macro argument `%s': "
+ "expected '=', ',' or ')'.\n",
+ arg_name.c_str());
+
+ default:
+ // The only FSM states are 0-2 and we dealt with 2 at the start of the loop.
+ __builtin_unreachable();
+ }
+ }
+
+ return std::make_pair(newline_count, args);
+}
+
+// Read a `define preprocessor directive. This is called just after reading the token containing
+// "`define".
+static void
+read_define(const std::string &filename,
+ define_map_t &defines_map,
+ define_map_t &global_defines_cache)
+{
+ std::string name, value;
+ arg_map_t args;
+
+ skip_spaces();
+ name = next_token(true);
+
+ bool here_doc_mode = false;
+ int newline_count = 0;
+
+ // The FSM state starts at 0. If it sees space (or enters here_doc_mode), it assumes this is
+ // a macro without formal arguments and jumps to state 1.
+ //
+ // In state 0, if it sees an opening parenthesis, it assumes this is a macro with formal
+ // arguments. It reads the arguments with read_define_args() and then jumps to state 2.
+ //
+ // In states 1 or 2, the FSM reads tokens to the end of line (or end of here_doc): this is
+ // the body of the macro definition.
+ int state = 0;
+
+ if (skip_spaces() != "")
+ state = 1;
+
+ for (;;) {
+ std::string tok = next_token();
+ if (tok.empty())
+ break;
+
+ // printf("define-tok: >>%s<<\n", tok != "\n" ? tok.c_str() : "NEWLINE");
+
+ if (tok == "\"\"\"") {
+ here_doc_mode = !here_doc_mode;
+ continue;
+ }
+
+ if (state == 0 && tok == "(") {
+ auto pr = read_define_args();
+ newline_count += pr.first;
+ args = pr.second;
+
+ state = 2;
+ continue;
+ }
+
+ // This token isn't an opening parenthesis immediately following the macro name, so
+ // it's presumably at or after the start of the macro body. If state isn't already 2
+ // (which would mean we'd parsed an argument list), set it to 1.
+ if (state == 0) {
+ state = 1;
+ }
+
+ if (tok == "\n") {
+ if (here_doc_mode) {
+ value += " ";
+ newline_count++;
+ } else {
+ return_char('\n');
+ break;
+ }
+ continue;
+ }
+
+ if (tok == "\\") {
+ char ch = next_char();
+ if (ch == '\n') {
+ value += " ";
+ newline_count++;
+ } else {
+ value += std::string("\\");
+ return_char(ch);
+ }
+ continue;
+ }
+
+ // Is this token the name of a macro argument? If so, replace it with a magic symbol
+ // that we'll replace with the argument value.
+ int arg_pos;
+ if (args.find(tok, &arg_pos)) {
+ value += '`' + args.str_token(name, arg_pos);
+ continue;
+ }
+
+ // This token is nothing special. Insert it verbatim into the macro body.
+ value += tok;
+ }
+
+ // Append some newlines so that we don't mess up line counts in error messages.
+ while (newline_count-- > 0)
+ return_char('\n');
+
+ if (strchr("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789", name[0])) {
+ // printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str());
+ defines_map.add(name, value, (state == 2) ? &args : nullptr);
+ global_defines_cache.add(name, value, (state == 2) ? &args : nullptr);
+ } else {
+ log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str());
+ }
+}
+
+std::string
+frontend_verilog_preproc(std::istream &f,
+ std::string filename,
+ const define_map_t &pre_defines,
+ define_map_t &global_defines_cache,
+ const std::list<std::string> &include_dirs)
+{
+ define_map_t defines;
+ defines.merge(pre_defines);
+ defines.merge(global_defines_cache);
+
std::vector<std::string> filename_stack;
int ifdef_fail_level = 0;
bool in_elseif = false;
@@ -287,18 +724,6 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
input_file(f, filename);
- defines_map["YOSYS"] = "1";
- defines_map[formal_mode ? "FORMAL" : "SYNTHESIS"] = "1";
-
- for (auto &it : pre_defines_map)
- defines_map[it.first] = it.second;
-
- for (auto &it : global_defines_cache) {
- if (it.second.second)
- defines_with_args.insert(it.first);
- defines_map[it.first] = it.second.first;
- }
-
while (!input_buffer.empty())
{
std::string tok = next_token();
@@ -325,7 +750,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
std::string name = next_token(true);
if (ifdef_fail_level == 0)
ifdef_fail_level = 1, in_elseif = true;
- else if (ifdef_fail_level == 1 && defines_map.count(name) != 0)
+ else if (ifdef_fail_level == 1 && defines.find(name))
ifdef_fail_level = 0, in_elseif = true;
continue;
}
@@ -333,7 +758,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
if (tok == "`ifdef") {
skip_spaces();
std::string name = next_token(true);
- if (ifdef_fail_level > 0 || defines_map.count(name) == 0)
+ if (ifdef_fail_level > 0 || !defines.find(name))
ifdef_fail_level++;
continue;
}
@@ -341,7 +766,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
if (tok == "`ifndef") {
skip_spaces();
std::string name = next_token(true);
- if (ifdef_fail_level > 0 || defines_map.count(name) != 0)
+ if (ifdef_fail_level > 0 || defines.find(name))
ifdef_fail_level++;
continue;
}
@@ -355,7 +780,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
if (tok == "`include") {
skip_spaces();
std::string fn = next_token(true);
- while (try_expand_macro(defines_with_args, defines_map, fn)) {
+ while (try_expand_macro(defines, fn)) {
fn = next_token();
}
while (1) {
@@ -433,74 +858,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
}
if (tok == "`define") {
- std::string name, value;
- std::map<std::string, int> args;
- skip_spaces();
- name = next_token(true);
- bool here_doc_mode = false;
- int newline_count = 0;
- int state = 0;
- if (skip_spaces() != "")
- state = 3;
- while (!tok.empty()) {
- tok = next_token();
- if (tok == "\"\"\"") {
- here_doc_mode = !here_doc_mode;
- continue;
- }
- if (state == 0 && tok == "(") {
- state = 1;
- skip_spaces();
- } else
- if (state == 1) {
- if (tok == ")")
- state = 2;
- else if (tok != ",") {
- int arg_idx = args.size()+1;
- args[tok] = arg_idx;
- }
- skip_spaces();
- } else {
- if (state != 2)
- state = 3;
- if (tok == "\n") {
- if (here_doc_mode) {
- value += " ";
- newline_count++;
- } else {
- return_char('\n');
- break;
- }
- } else
- if (tok == "\\") {
- char ch = next_char();
- if (ch == '\n') {
- value += " ";
- newline_count++;
- } else {
- value += std::string("\\");
- return_char(ch);
- }
- } else
- if (args.count(tok) > 0)
- value += stringf("`macro_%s_arg%d", name.c_str(), args.at(tok));
- else
- value += tok;
- }
- }
- while (newline_count-- > 0)
- return_char('\n');
- if (strchr("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789", name[0])) {
- // printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str());
- defines_map[name] = value;
- if (state == 2)
- defines_with_args.insert(name);
- else
- defines_with_args.erase(name);
- global_defines_cache[name] = std::pair<std::string, bool>(value, state == 2);
- } else {
- log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str());
- }
+ read_define(filename, defines, global_defines_cache);
continue;
}
@@ -509,8 +867,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
skip_spaces();
name = next_token(true);
// printf("undef: >>%s<<\n", name.c_str());
- defines_map.erase(name);
- defines_with_args.erase(name);
+ defines.erase(name);
global_defines_cache.erase(name);
continue;
}
@@ -525,13 +882,12 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
}
if (tok == "`resetall") {
- defines_map.clear();
- defines_with_args.clear();
+ defines.clear();
global_defines_cache.clear();
continue;
}
- if (try_expand_macro(defines_with_args, defines_map, tok))
+ if (try_expand_macro(defines, tok))
continue;
output_code.push_back(tok);
diff --git a/frontends/verilog/preproc.h b/frontends/verilog/preproc.h
new file mode 100644
index 000000000..673d633c0
--- /dev/null
+++ b/frontends/verilog/preproc.h
@@ -0,0 +1,77 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * ---
+ *
+ * The Verilog preprocessor.
+ *
+ */
+#ifndef VERILOG_PREPROC_H
+#define VERILOG_PREPROC_H
+
+#include "kernel/yosys.h"
+
+#include <iosfwd>
+#include <list>
+#include <memory>
+#include <string>
+
+YOSYS_NAMESPACE_BEGIN
+
+struct define_body_t;
+struct arg_map_t;
+
+struct define_map_t
+{
+ define_map_t();
+ ~ define_map_t();
+
+ // Add a definition, overwriting any existing definition for name.
+ void add(const std::string &name, const std::string &txt, const arg_map_t *args = nullptr);
+
+ // Merge in another map of definitions (which take precedence
+ // over anything currently defined).
+ void merge(const define_map_t &map);
+
+ // Find a definition by name. If no match, returns null.
+ const define_body_t *find(const std::string &name) const;
+
+ // Erase a definition by name (no effect if not defined).
+ void erase(const std::string &name);
+
+ // Clear any existing definitions
+ void clear();
+
+ // Print a list of definitions, using the log function
+ void log() const;
+
+ std::map<std::string, std::unique_ptr<define_body_t>> defines;
+};
+
+
+struct define_map_t;
+
+std::string
+frontend_verilog_preproc(std::istream &f,
+ std::string filename,
+ const define_map_t &pre_defines,
+ define_map_t &global_defines_cache,
+ const std::list<std::string> &include_dirs);
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 42eabc02d..6879e0943 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -27,6 +27,7 @@
*/
#include "verilog_frontend.h"
+#include "preproc.h"
#include "kernel/yosys.h"
#include "libs/sha1/sha1.h"
#include <stdarg.h>
@@ -47,6 +48,23 @@ static void error_on_dpi_function(AST::AstNode *node)
error_on_dpi_function(child);
}
+static void add_package_types(std::map<std::string, AST::AstNode *> &user_types, std::vector<AST::AstNode *> &package_list)
+{
+ // prime the parser's user type lookup table with the package qualified names
+ // of typedefed names in the packages seen so far.
+ for (const auto &pkg : package_list) {
+ log_assert(pkg->type==AST::AST_PACKAGE);
+ for (const auto &node: pkg->children) {
+ if (node->type == AST::AST_TYPEDEF) {
+ std::string s = pkg->str + "::" + node->str.substr(1);
+ user_types[s] = node;
+ }
+ }
+ }
+ user_type_stack.clear();
+ user_type_stack.push_back(new UserTypeMap());
+}
+
struct VerilogFrontend : public Frontend {
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
void help() YS_OVERRIDE
@@ -237,7 +255,8 @@ struct VerilogFrontend : public Frontend {
bool flag_defer = false;
bool flag_noblackbox = false;
bool flag_nowb = false;
- std::map<std::string, std::string> defines_map;
+ define_map_t defines_map;
+
std::list<std::string> include_dirs;
std::list<std::string> attributes;
@@ -353,7 +372,7 @@ struct VerilogFrontend : public Frontend {
}
if (arg == "-lib") {
lib_mode = true;
- defines_map["BLACKBOX"] = string();
+ defines_map.add("BLACKBOX", "");
continue;
}
if (arg == "-nowb") {
@@ -405,7 +424,7 @@ struct VerilogFrontend : public Frontend {
value = name.substr(equal+1);
name = name.substr(0, equal);
}
- defines_map[name] = value;
+ defines_map.add(name, value);
continue;
}
if (arg.compare(0, 2, "-D") == 0) {
@@ -414,7 +433,7 @@ struct VerilogFrontend : public Frontend {
std::string value;
if (equal != std::string::npos)
value = arg.substr(equal+1);
- defines_map[name] = value;
+ defines_map.add(name, value);
continue;
}
if (arg == "-I" && argidx+1 < args.size()) {
@@ -444,12 +463,15 @@ struct VerilogFrontend : public Frontend {
std::string code_after_preproc;
if (!flag_nopp) {
- code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, design->verilog_defines, include_dirs);
+ code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, *design->verilog_defines, include_dirs);
if (flag_ppdump)
log("-- Verilog code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc.c_str());
lexin = new std::istringstream(code_after_preproc);
}
+ // make package typedefs available to parser
+ add_package_types(pkg_user_types, design->verilog_packages);
+
frontend_verilog_yyset_lineno(1);
frontend_verilog_yyrestart(NULL);
frontend_verilog_yyparse();
@@ -468,6 +490,7 @@ struct VerilogFrontend : public Frontend {
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
+
if (!flag_nopp)
delete lexin;
@@ -572,7 +595,7 @@ struct VerilogDefines : public Pass {
value = name.substr(equal+1);
name = name.substr(0, equal);
}
- design->verilog_defines[name] = std::pair<std::string, bool>(value, false);
+ design->verilog_defines->add(name, value);
continue;
}
if (arg.compare(0, 2, "-D") == 0) {
@@ -581,27 +604,25 @@ struct VerilogDefines : public Pass {
std::string value;
if (equal != std::string::npos)
value = arg.substr(equal+1);
- design->verilog_defines[name] = std::pair<std::string, bool>(value, false);
+ design->verilog_defines->add(name, value);
continue;
}
if (arg == "-U" && argidx+1 < args.size()) {
std::string name = args[++argidx];
- design->verilog_defines.erase(name);
+ design->verilog_defines->erase(name);
continue;
}
if (arg.compare(0, 2, "-U") == 0) {
std::string name = arg.substr(2);
- design->verilog_defines.erase(name);
+ design->verilog_defines->erase(name);
continue;
}
if (arg == "-reset") {
- design->verilog_defines.clear();
+ design->verilog_defines->clear();
continue;
}
if (arg == "-list") {
- for (auto &it : design->verilog_defines) {
- log("`define %s%s %s\n", it.first.c_str(), it.second.second ? "()" : "", it.second.first.c_str());
- }
+ design->verilog_defines->log();
continue;
}
break;
diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h
index a2e06f0e4..444cc7297 100644
--- a/frontends/verilog/verilog_frontend.h
+++ b/frontends/verilog/verilog_frontend.h
@@ -45,6 +45,13 @@ namespace VERILOG_FRONTEND
// this function converts a Verilog constant to an AST_CONSTANT node
AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false);
+ // names of locally typedef'ed types in a stack
+ typedef std::map<std::string, AST::AstNode*> UserTypeMap;
+ extern std::vector<UserTypeMap *> user_type_stack;
+
+ // names of package typedef'ed types
+ extern std::map<std::string, AST::AstNode*> pkg_user_types;
+
// state of `default_nettype
extern bool default_nettype_wire;
@@ -79,10 +86,6 @@ namespace VERILOG_FRONTEND
extern std::istream *lexin;
}
-// the pre-processor
-std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map<std::string, std::string> &pre_defines_map,
- dict<std::string, std::pair<std::string, bool>> &global_defines_cache, const std::list<std::string> &include_dirs);
-
YOSYS_NAMESPACE_END
// the usual bison/flex stuff
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index 0a7c34ec0..f6a3ac4db 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -99,6 +99,18 @@ YYLTYPE old_location;
#define YY_BUF_SIZE 65536
extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param);
+
+static bool isUserType(std::string &s)
+{
+ // check current scope then outer scopes for a name
+ for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) {
+ if ((*it)->count(s) > 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
%}
%option yylineno
@@ -113,8 +125,10 @@ extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param);
%x SYNOPSYS_TRANSLATE_OFF
%x SYNOPSYS_FLAGS
%x IMPORT_DPI
+%x BASED_CONST
%%
+ int comment_caller;
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* {
fn_stack.push_back(current_filename);
@@ -273,9 +287,21 @@ extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param);
return TOK_CONSTVAL;
}
-[0-9]*[ \t]*\'[sS]?[bodhBODH]?[ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
+\'[01zxZX] {
yylval->string = new std::string(yytext);
- return TOK_CONSTVAL;
+ return TOK_UNBASED_UNSIZED_CONSTVAL;
+}
+
+\'[sS]?[bodhBODH] {
+ BEGIN(BASED_CONST);
+ yylval->string = new std::string(yytext);
+ return TOK_BASE;
+}
+
+<BASED_CONST>[0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* {
+ BEGIN(0);
+ yylval->string = new std::string(yytext);
+ return TOK_BASED_CONSTVAL;
}
[0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? {
@@ -358,9 +384,34 @@ supply1 { return TOK_SUPPLY1; }
"$signed" { return TOK_TO_SIGNED; }
"$unsigned" { return TOK_TO_UNSIGNED; }
+[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* {
+ // package qualifier
+ auto s = std::string("\\") + yytext;
+ if (pkg_user_types.count(s) > 0) {
+ // package qualified typedefed name
+ yylval->string = new std::string(s);
+ return TOK_PKG_USER_TYPE;
+ }
+ else {
+ // backup before :: just return first part
+ size_t len = strchr(yytext, ':') - yytext;
+ yyless(len);
+ yylval->string = new std::string(std::string("\\") + yytext);
+ return TOK_ID;
+ }
+}
+
[a-zA-Z_$][a-zA-Z0-9_$]* {
- yylval->string = new std::string(std::string("\\") + yytext);
- return TOK_ID;
+ auto s = std::string("\\") + yytext;
+ if (isUserType(s)) {
+ // previously typedefed name
+ yylval->string = new std::string(s);
+ return TOK_USER_TYPE;
+ }
+ else {
+ yylval->string = new std::string(std::string("\\") + yytext);
+ return TOK_ID;
+ }
}
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
@@ -478,16 +529,17 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
return TOK_SPECIFY_AND;
}
-"/*" { BEGIN(COMMENT); }
+<INITIAL,BASED_CONST>"/*" { comment_caller=YY_START; BEGIN(COMMENT); }
<COMMENT>. /* ignore comment body */
<COMMENT>\n /* ignore comment body */
-<COMMENT>"*/" { BEGIN(0); }
+<COMMENT>"*/" { BEGIN(comment_caller); }
-[ \t\r\n] /* ignore whitespaces */
-\\[\r\n] /* ignore continuation sequence */
-"//"[^\r\n]* /* ignore one-line comments */
+<INITIAL,BASED_CONST>[ \t\r\n] /* ignore whitespaces */
+<INITIAL,BASED_CONST>\\[\r\n] /* ignore continuation sequence */
+<INITIAL,BASED_CONST>"//"[^\r\n]* /* ignore one-line comments */
-. { return *yytext; }
+<INITIAL>. { return *yytext; }
+<*>. { BEGIN(0); return *yytext; }
%%
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 91982e2a3..3bffa3986 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -54,6 +54,8 @@ namespace VERILOG_FRONTEND {
std::map<std::string, AstNode*> *attr_list, default_attr_list;
std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
std::map<std::string, AstNode*> *albuf;
+ std::vector<UserTypeMap*> user_type_stack;
+ std::map<std::string, AstNode*> pkg_user_types;
std::vector<AstNode*> ast_stack;
struct AstNode *astbuf1, *astbuf2, *astbuf3;
struct AstNode *current_function_or_task;
@@ -125,6 +127,40 @@ struct specify_rise_fall {
specify_triple fall;
};
+static void addTypedefNode(std::string *name, AstNode *node)
+{
+ log_assert(node);
+ auto *tnode = new AstNode(AST_TYPEDEF, node);
+ tnode->str = *name;
+ auto user_types = user_type_stack.back();
+ (*user_types)[*name] = tnode;
+ if (current_ast_mod && current_ast_mod->type == AST_PACKAGE) {
+ // typedef inside a package so we need the qualified name
+ auto qname = current_ast_mod->str + "::" + (*name).substr(1);
+ pkg_user_types[qname] = tnode;
+ }
+ delete name;
+ ast_stack.back()->children.push_back(tnode);
+}
+
+static void enterTypeScope()
+{
+ auto user_types = new UserTypeMap();
+ user_type_stack.push_back(user_types);
+}
+
+static void exitTypeScope()
+{
+ user_type_stack.pop_back();
+}
+
+static bool isInLocalScope(const std::string *name)
+{
+ // tests if a name was declared in the current block scope
+ auto user_types = user_type_stack.back();
+ return (user_types->count(*name) > 0);
+}
+
static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true)
{
auto range = new AstNode(AST_RANGE);
@@ -166,6 +202,8 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS
+%token <string> TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL
+%token <string> TOK_USER_TYPE TOK_PKG_USER_TYPE
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
@@ -188,7 +226,8 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
-%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id
+%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
+%type <string> type_name
%type <ast> opt_enum_init
%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
%type <al> attr case_attr
@@ -329,10 +368,15 @@ hierarchical_id:
};
hierarchical_type_id:
- '(' hierarchical_id ')' { $$ = $2; };
+ TOK_USER_TYPE
+ | TOK_PKG_USER_TYPE // package qualified type name
+ | '(' TOK_USER_TYPE ')' { $$ = $2; } // non-standard grammar
+ ;
module:
- attr TOK_MODULE TOK_ID {
+ attr TOK_MODULE {
+ enterTypeScope();
+ } TOK_ID {
do_not_require_port_stubs = false;
AstNode *mod = new AstNode(AST_MODULE);
ast_stack.back()->children.push_back(mod);
@@ -340,9 +384,9 @@ module:
current_ast_mod = mod;
port_stubs.clear();
port_counter = 0;
- mod->str = *$3;
+ mod->str = *$4;
append_attr(mod, $1);
- delete $3;
+ delete $4;
} module_para_opt module_args_opt ';' module_body TOK_ENDMODULE {
if (port_stubs.size() != 0)
frontend_verilog_yyerror("Missing details for module port `%s'.",
@@ -351,6 +395,7 @@ module:
ast_stack.pop_back();
log_assert(ast_stack.size() == 1);
current_ast_mod = NULL;
+ exitTypeScope();
};
module_para_opt:
@@ -391,9 +436,9 @@ module_arg_opt_assignment:
wire->str = ast_stack.back()->children.back()->str;
if (ast_stack.back()->children.back()->is_input) {
AstNode *n = ast_stack.back()->children.back();
- if (n->attributes.count("\\defaultvalue"))
- delete n->attributes.at("\\defaultvalue");
- n->attributes["\\defaultvalue"] = $2;
+ if (n->attributes.count(ID::defaultvalue))
+ delete n->attributes.at(ID::defaultvalue);
+ n->attributes[ID::defaultvalue] = $2;
} else
if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic)
ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
@@ -454,16 +499,19 @@ module_arg:
};
package:
- attr TOK_PACKAGE TOK_ID {
+ attr TOK_PACKAGE {
+ enterTypeScope();
+ } TOK_ID {
AstNode *mod = new AstNode(AST_PACKAGE);
ast_stack.back()->children.push_back(mod);
ast_stack.push_back(mod);
current_ast_mod = mod;
- mod->str = *$3;
+ mod->str = *$4;
append_attr(mod, $1);
} ';' package_body TOK_ENDPACKAGE {
ast_stack.pop_back();
current_ast_mod = NULL;
+ exitTypeScope();
};
package_body:
@@ -476,7 +524,9 @@ package_body_stmt:
localparam_decl;
interface:
- TOK_INTERFACE TOK_ID {
+ TOK_INTERFACE {
+ enterTypeScope();
+ } TOK_ID {
do_not_require_port_stubs = false;
AstNode *intf = new AstNode(AST_INTERFACE);
ast_stack.back()->children.push_back(intf);
@@ -484,8 +534,8 @@ interface:
current_ast_mod = intf;
port_stubs.clear();
port_counter = 0;
- intf->str = *$2;
- delete $2;
+ intf->str = *$3;
+ delete $3;
} module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE {
if (port_stubs.size() != 0)
frontend_verilog_yyerror("Missing details for module port `%s'.",
@@ -493,6 +543,7 @@ interface:
ast_stack.pop_back();
log_assert(ast_stack.size() == 1);
current_ast_mod = NULL;
+ exitTypeScope();
};
interface_body:
@@ -1460,24 +1511,24 @@ wire_name_and_opt_assign:
bool attr_anyseq = false;
bool attr_allconst = false;
bool attr_allseq = false;
- if (ast_stack.back()->children.back()->get_bool_attribute("\\anyconst")) {
- delete ast_stack.back()->children.back()->attributes.at("\\anyconst");
- ast_stack.back()->children.back()->attributes.erase("\\anyconst");
+ if (ast_stack.back()->children.back()->get_bool_attribute(ID::anyconst)) {
+ delete ast_stack.back()->children.back()->attributes.at(ID::anyconst);
+ ast_stack.back()->children.back()->attributes.erase(ID::anyconst);
attr_anyconst = true;
}
- if (ast_stack.back()->children.back()->get_bool_attribute("\\anyseq")) {
- delete ast_stack.back()->children.back()->attributes.at("\\anyseq");
- ast_stack.back()->children.back()->attributes.erase("\\anyseq");
+ if (ast_stack.back()->children.back()->get_bool_attribute(ID::anyseq)) {
+ delete ast_stack.back()->children.back()->attributes.at(ID::anyseq);
+ ast_stack.back()->children.back()->attributes.erase(ID::anyseq);
attr_anyseq = true;
}
- if (ast_stack.back()->children.back()->get_bool_attribute("\\allconst")) {
- delete ast_stack.back()->children.back()->attributes.at("\\allconst");
- ast_stack.back()->children.back()->attributes.erase("\\allconst");
+ if (ast_stack.back()->children.back()->get_bool_attribute(ID::allconst)) {
+ delete ast_stack.back()->children.back()->attributes.at(ID::allconst);
+ ast_stack.back()->children.back()->attributes.erase(ID::allconst);
attr_allconst = true;
}
- if (ast_stack.back()->children.back()->get_bool_attribute("\\allseq")) {
- delete ast_stack.back()->children.back()->attributes.at("\\allseq");
- ast_stack.back()->children.back()->attributes.erase("\\allseq");
+ if (ast_stack.back()->children.back()->get_bool_attribute(ID::allseq)) {
+ delete ast_stack.back()->children.back()->attributes.at(ID::allseq);
+ ast_stack.back()->children.back()->attributes.erase(ID::allseq);
attr_allseq = true;
}
if (current_wire_rand || attr_anyconst || attr_anyseq || attr_allconst || attr_allseq) {
@@ -1493,7 +1544,7 @@ wire_name_and_opt_assign:
fcall->str = "\\$allconst";
if (attr_allseq)
fcall->str = "\\$allseq";
- fcall->attributes["\\reg"] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str));
+ fcall->attributes[ID::reg] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str));
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, fcall));
}
} |
@@ -1501,9 +1552,9 @@ wire_name_and_opt_assign:
AstNode *wire = new AstNode(AST_IDENTIFIER);
wire->str = ast_stack.back()->children.back()->str;
if (astbuf1->is_input) {
- if (astbuf1->attributes.count("\\defaultvalue"))
- delete astbuf1->attributes.at("\\defaultvalue");
- astbuf1->attributes["\\defaultvalue"] = $3;
+ if (astbuf1->attributes.count(ID::defaultvalue))
+ delete astbuf1->attributes.at(ID::defaultvalue);
+ astbuf1->attributes[ID::defaultvalue] = $3;
}
else if (astbuf1->is_reg || astbuf1->is_logic){
AstNode *assign = new AstNode(AST_ASSIGN_LE, wire, $3);
@@ -1590,8 +1641,12 @@ assign_expr:
ast_stack.back()->children.push_back(node);
};
+type_name: TOK_ID // first time seen
+ | TOK_USER_TYPE { if (isInLocalScope($1)) frontend_verilog_yyerror("Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); }
+ ;
+
typedef_decl:
- TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' {
+ TOK_TYPEDEF wire_type range type_name range_or_multirange ';' {
astbuf1 = $2;
astbuf2 = $3;
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
@@ -1624,13 +1679,10 @@ typedef_decl:
}
astbuf1->children.push_back(rangeNode);
}
-
- ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
- ast_stack.back()->children.back()->str = *$4;
+ addTypedefNode($4, astbuf1);
} |
- TOK_TYPEDEF enum_type TOK_ID ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
- ast_stack.back()->children.back()->str = *$3;
+ TOK_TYPEDEF enum_type type_name ';' {
+ addTypedefNode($3, astbuf1);
}
;
@@ -1787,7 +1839,7 @@ cell_port:
attr TOK_WILDCARD_CONNECT {
if (!sv_mode)
frontend_verilog_yyerror("Wildcard port connections are only supported in SystemVerilog mode.");
- astbuf2->attributes[ID(wildcard_port_conns)] = AstNode::mkconst_int(1, false);
+ astbuf2->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false);
};
always_comb_or_latch:
@@ -1811,7 +1863,7 @@ always_stmt:
AstNode *node = new AstNode(AST_ALWAYS);
append_attr(node, $1);
if ($2)
- node->attributes[ID(always_ff)] = AstNode::mkconst_int(1, false);
+ node->attributes[ID::always_ff] = AstNode::mkconst_int(1, false);
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} always_cond {
@@ -1831,9 +1883,9 @@ always_stmt:
AstNode *node = new AstNode(AST_ALWAYS);
append_attr(node, $1);
if ($2)
- node->attributes[ID(always_latch)] = AstNode::mkconst_int(1, false);
+ node->attributes[ID::always_latch] = AstNode::mkconst_int(1, false);
else
- node->attributes[ID(always_comb)] = AstNode::mkconst_int(1, false);
+ node->attributes[ID::always_comb] = AstNode::mkconst_int(1, false);
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
AstNode *block = new AstNode(AST_BLOCK);
@@ -1954,6 +2006,7 @@ assert:
delete $5;
} else {
AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1966,6 +2019,7 @@ assert:
delete $5;
} else {
AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1978,6 +2032,7 @@ assert:
delete $6;
} else {
AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1990,6 +2045,7 @@ assert:
delete $6;
} else {
AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1999,6 +2055,7 @@ assert:
} |
opt_sva_label TOK_COVER opt_property '(' expr ')' ';' {
AstNode *node = new AstNode(AST_COVER, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr) {
node->str = *$1;
delete $1;
@@ -2007,6 +2064,7 @@ assert:
} |
opt_sva_label TOK_COVER opt_property '(' ')' ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
+ SET_AST_NODE_LOC(node, @1, @5);
if ($1 != nullptr) {
node->str = *$1;
delete $1;
@@ -2015,6 +2073,7 @@ assert:
} |
opt_sva_label TOK_COVER ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
+ SET_AST_NODE_LOC(node, @1, @2);
if ($1 != nullptr) {
node->str = *$1;
delete $1;
@@ -2026,6 +2085,7 @@ assert:
delete $5;
} else {
AstNode *node = new AstNode(AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -2040,6 +2100,7 @@ assert:
delete $6;
} else {
AstNode *node = new AstNode(AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -2052,35 +2113,45 @@ assert:
assert_property:
opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
+ AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
+ AstNode *node = new AstNode(AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
+ AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
+ AstNode *node = new AstNode(AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
+ AstNode *node = new AstNode(AST_COVER, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
@@ -2090,7 +2161,9 @@ assert_property:
if (norestrict_mode) {
delete $5;
} else {
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
+ AstNode *node = new AstNode(AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
@@ -2101,7 +2174,9 @@ assert_property:
if (norestrict_mode) {
delete $6;
} else {
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
+ AstNode *node = new AstNode(AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
@@ -2113,18 +2188,22 @@ simple_behavioral_stmt:
lvalue '=' delay expr {
AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4);
ast_stack.back()->children.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @4);
} |
lvalue TOK_INCREMENT {
AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true)));
ast_stack.back()->children.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @2);
} |
lvalue TOK_DECREMENT {
AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true)));
ast_stack.back()->children.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @2);
} |
lvalue OP_LE delay expr {
AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4);
ast_stack.back()->children.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @4);
};
// this production creates the obligatory if-else shift/reduce conflict
@@ -2152,20 +2231,21 @@ behavioral_stmt:
} opt_arg_list ';'{
ast_stack.pop_back();
} |
- attr TOK_BEGIN opt_label {
+ attr TOK_BEGIN {
+ enterTypeScope();
+ } opt_label {
AstNode *node = new AstNode(AST_BLOCK);
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
append_attr(node, $1);
- if ($3 != NULL)
- node->str = *$3;
+ if ($4 != NULL)
+ node->str = *$4;
} behavioral_stmt_list TOK_END opt_label {
- if ($3 != NULL && $7 != NULL && *$3 != *$7)
- frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1);
- if ($3 != NULL)
- delete $3;
- if ($7 != NULL)
- delete $7;
+ exitTypeScope();
+ if ($4 != NULL && $8 != NULL && *$4 != *$8)
+ frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $4->c_str()+1, $8->c_str()+1);
+ delete $4;
+ delete $8;
ast_stack.pop_back();
} |
attr TOK_FOR '(' {
@@ -2182,6 +2262,7 @@ behavioral_stmt:
} behavioral_stmt {
SET_AST_NODE_LOC(ast_stack.back(), @13, @13);
ast_stack.pop_back();
+ SET_AST_NODE_LOC(ast_stack.back(), @2, @13);
ast_stack.pop_back();
} |
attr TOK_WHILE '(' expr ')' {
@@ -2242,6 +2323,8 @@ behavioral_stmt:
ast_stack.pop_back();
};
+ ;
+
unique_case_attr:
/* empty */ {
$$ = false;
@@ -2272,12 +2355,12 @@ case_type:
opt_synopsys_attr:
opt_synopsys_attr TOK_SYNOPSYS_FULL_CASE {
- if (ast_stack.back()->attributes.count("\\full_case") == 0)
- ast_stack.back()->attributes["\\full_case"] = AstNode::mkconst_int(1, false);
+ if (ast_stack.back()->attributes.count(ID::full_case) == 0)
+ ast_stack.back()->attributes[ID::full_case] = AstNode::mkconst_int(1, false);
} |
opt_synopsys_attr TOK_SYNOPSYS_PARALLEL_CASE {
- if (ast_stack.back()->attributes.count("\\parallel_case") == 0)
- ast_stack.back()->attributes["\\parallel_case"] = AstNode::mkconst_int(1, false);
+ if (ast_stack.back()->attributes.count(ID::parallel_case) == 0)
+ ast_stack.back()->attributes[ID::parallel_case] = AstNode::mkconst_int(1, false);
} |
/* empty */;
@@ -2335,6 +2418,7 @@ gen_case_item:
ast_stack.push_back(node);
} case_select {
case_type_stack.push_back(0);
+ SET_AST_NODE_LOC(ast_stack.back(), @2, @2);
} gen_stmt_or_null {
case_type_stack.pop_back();
ast_stack.pop_back();
@@ -2346,10 +2430,14 @@ case_select:
case_expr_list:
TOK_DEFAULT {
- ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT));
+ AstNode *node = new AstNode(AST_DEFAULT);
+ SET_AST_NODE_LOC(node, @1, @1);
+ ast_stack.back()->children.push_back(node);
} |
TOK_SVA_LABEL {
- ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER));
+ AstNode *node = new AstNode(AST_IDENTIFIER);
+ SET_AST_NODE_LOC(node, @1, @1);
+ ast_stack.back()->children.push_back(node);
ast_stack.back()->children.back()->str = *$1;
delete $1;
} |
@@ -2369,6 +2457,7 @@ rvalue:
hierarchical_id range {
$$ = new AstNode(AST_IDENTIFIER, $2);
$$->str = *$1;
+ SET_AST_NODE_LOC($$, @1, @1);
delete $1;
if ($2 == nullptr && ($$->str == "\\$initstate" ||
$$->str == "\\$anyconst" || $$->str == "\\$anyseq" ||
@@ -2378,6 +2467,7 @@ rvalue:
hierarchical_id non_opt_multirange {
$$ = new AstNode(AST_IDENTIFIER, $2);
$$->str = *$1;
+ SET_AST_NODE_LOC($$, @1, @1);
delete $1;
};
@@ -2432,6 +2522,7 @@ gen_stmt:
} simple_behavioral_stmt ';' expr {
ast_stack.back()->children.push_back($6);
} ';' simple_behavioral_stmt ')' gen_stmt_block {
+ SET_AST_NODE_LOC(ast_stack.back(), @1, @11);
ast_stack.pop_back();
} |
TOK_IF '(' expr ')' {
@@ -2440,6 +2531,7 @@ gen_stmt:
ast_stack.push_back(node);
ast_stack.back()->children.push_back($3);
} gen_stmt_block opt_gen_else {
+ SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
case_type '(' expr ')' {
@@ -2448,18 +2540,21 @@ gen_stmt:
ast_stack.push_back(node);
} gen_case_body TOK_ENDCASE {
case_type_stack.pop_back();
+ SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
- TOK_BEGIN opt_label {
+ TOK_BEGIN {
+ enterTypeScope();
+ } opt_label {
AstNode *node = new AstNode(AST_GENBLOCK);
- node->str = $2 ? *$2 : std::string();
+ node->str = $3 ? *$3 : std::string();
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} module_gen_body TOK_END opt_label {
- if ($2 != NULL)
- delete $2;
- if ($6 != NULL)
- delete $6;
+ exitTypeScope();
+ delete $3;
+ delete $7;
+ SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
TOK_MSG_TASKS {
@@ -2469,6 +2564,7 @@ gen_stmt:
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} opt_arg_list ';'{
+ SET_AST_NODE_LOC(ast_stack.back(), @1, @3);
ast_stack.pop_back();
};
@@ -2478,6 +2574,7 @@ gen_stmt_block:
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} gen_stmt_or_module_body_stmt {
+ SET_AST_NODE_LOC(ast_stack.back(), @2, @2);
ast_stack.pop_back();
};
@@ -2496,6 +2593,7 @@ expr:
$$->children.push_back($1);
$$->children.push_back($4);
$$->children.push_back($6);
+ SET_AST_NODE_LOC($$, @1, @$);
append_attr($$, $3);
};
@@ -2503,7 +2601,7 @@ basic_expr:
rvalue {
$$ = $1;
} |
- '(' expr ')' TOK_CONSTVAL {
+ '(' expr ')' integral_number {
if ($4->compare(0, 1, "'") != 0)
frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
AstNode *bits = $2;
@@ -2513,11 +2611,12 @@ basic_expr:
$$ = new AstNode(AST_TO_BITS, bits, val);
delete $4;
} |
- hierarchical_id TOK_CONSTVAL {
+ hierarchical_id integral_number {
if ($2->compare(0, 1, "'") != 0)
frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
AstNode *bits = new AstNode(AST_IDENTIFIER);
bits->str = *$1;
+ SET_AST_NODE_LOC(bits, @1, @1);
AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
if (val == NULL)
log_error("Value conversion failed: `%s'\n", $2->c_str());
@@ -2525,14 +2624,7 @@ basic_expr:
delete $1;
delete $2;
} |
- TOK_CONSTVAL TOK_CONSTVAL {
- $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
- if ($$ == NULL || (*$2)[0] != '\'')
- log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str());
- delete $1;
- delete $2;
- } |
- TOK_CONSTVAL {
+ integral_number {
$$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
if ($$ == NULL)
log_error("Value conversion failed: `%s'\n", $1->c_str());
@@ -2545,6 +2637,7 @@ basic_expr:
if ((*$1)[j] != '_')
p[i++] = (*$1)[j], p[i] = 0;
$$->realvalue = strtod(p, &q);
+ SET_AST_NODE_LOC($$, @1, @1);
log_assert(*q == 0);
delete $1;
free(p);
@@ -2558,6 +2651,7 @@ basic_expr:
node->str = *$1;
delete $1;
ast_stack.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @1);
append_attr(node, $2);
} '(' arg_list optional_comma ')' {
$$ = ast_stack.back();
@@ -2587,148 +2681,185 @@ basic_expr:
} |
'~' attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_BIT_NOT, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
} |
basic_expr '&' attr basic_expr {
$$ = new AstNode(AST_BIT_AND, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_NAND attr basic_expr {
$$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_AND, $1, $4));
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '|' attr basic_expr {
$$ = new AstNode(AST_BIT_OR, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_NOR attr basic_expr {
$$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_OR, $1, $4));
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '^' attr basic_expr {
$$ = new AstNode(AST_BIT_XOR, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_XNOR attr basic_expr {
$$ = new AstNode(AST_BIT_XNOR, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
'&' attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_REDUCE_AND, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
} |
OP_NAND attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_REDUCE_AND, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
$$ = new AstNode(AST_LOGIC_NOT, $$);
} |
'|' attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_REDUCE_OR, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
} |
OP_NOR attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_REDUCE_OR, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
$$ = new AstNode(AST_LOGIC_NOT, $$);
+ SET_AST_NODE_LOC($$, @1, @3);
} |
'^' attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_REDUCE_XOR, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
} |
OP_XNOR attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_REDUCE_XNOR, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
} |
basic_expr OP_SHL attr basic_expr {
$$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_SHR attr basic_expr {
$$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_SSHL attr basic_expr {
$$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_SSHR attr basic_expr {
$$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '<' attr basic_expr {
$$ = new AstNode(AST_LT, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_LE attr basic_expr {
$$ = new AstNode(AST_LE, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_EQ attr basic_expr {
$$ = new AstNode(AST_EQ, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_NE attr basic_expr {
$$ = new AstNode(AST_NE, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_EQX attr basic_expr {
$$ = new AstNode(AST_EQX, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_NEX attr basic_expr {
$$ = new AstNode(AST_NEX, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_GE attr basic_expr {
$$ = new AstNode(AST_GE, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '>' attr basic_expr {
$$ = new AstNode(AST_GT, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '+' attr basic_expr {
$$ = new AstNode(AST_ADD, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '-' attr basic_expr {
$$ = new AstNode(AST_SUB, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '*' attr basic_expr {
$$ = new AstNode(AST_MUL, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '/' attr basic_expr {
$$ = new AstNode(AST_DIV, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr '%' attr basic_expr {
$$ = new AstNode(AST_MOD, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_POW attr basic_expr {
$$ = new AstNode(AST_POW, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
'+' attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_POS, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
} |
'-' attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_NEG, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
} |
basic_expr OP_LAND attr basic_expr {
$$ = new AstNode(AST_LOGIC_AND, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
basic_expr OP_LOR attr basic_expr {
$$ = new AstNode(AST_LOGIC_OR, $1, $4);
+ SET_AST_NODE_LOC($$, @1, @4);
append_attr($$, $3);
} |
'!' attr basic_expr %prec UNARY_OPS {
$$ = new AstNode(AST_LOGIC_NOT, $3);
+ SET_AST_NODE_LOC($$, @1, @3);
append_attr($$, $2);
};
@@ -2740,3 +2871,18 @@ concat_list:
$$ = $3;
$$->children.push_back($1);
};
+
+integral_number:
+ TOK_CONSTVAL { $$ = $1; } |
+ TOK_UNBASED_UNSIZED_CONSTVAL { $$ = $1; } |
+ TOK_BASE TOK_BASED_CONSTVAL {
+ $1->append(*$2);
+ $$ = $1;
+ delete $2;
+ } |
+ TOK_CONSTVAL TOK_BASE TOK_BASED_CONSTVAL {
+ $1->append(*$2).append(*$3);
+ $$ = $1;
+ delete $2;
+ delete $3;
+ };