aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast/simplify.cc
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/ast/simplify.cc')
-rw-r--r--frontends/ast/simplify.cc692
1 files changed, 445 insertions, 247 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index b94a8d710..04c02d893 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -41,6 +41,103 @@ YOSYS_NAMESPACE_BEGIN
using namespace AST;
using namespace AST_INTERNAL;
+// Process a format string and arguments for $display, $write, $sprintf, etc
+
+std::string AstNode::process_format_str(const std::string &sformat, int next_arg, int stage, int width_hint, bool sign_hint) {
+ // Other arguments are placeholders. Process the string as we go through it
+ std::string sout;
+ for (size_t i = 0; i < sformat.length(); i++)
+ {
+ // format specifier
+ if (sformat[i] == '%')
+ {
+ // If there's no next character, that's a problem
+ if (i+1 >= sformat.length())
+ log_file_error(filename, location.first_line, "System task `%s' called with `%%' at end of string.\n", str.c_str());
+
+ char cformat = sformat[++i];
+
+ // %% is special, does not need a matching argument
+ if (cformat == '%')
+ {
+ sout += '%';
+ continue;
+ }
+
+ // Simplify the argument
+ AstNode *node_arg = nullptr;
+
+ // Everything from here on depends on the format specifier
+ switch (cformat)
+ {
+ case 's':
+ case 'S':
+ case 'd':
+ case 'D':
+ case 'x':
+ case 'X':
+ if (next_arg >= GetSize(children))
+ log_file_error(filename, location.first_line, "Missing argument for %%%c format specifier in system task `%s'.\n",
+ cformat, str.c_str());
+
+ node_arg = children[next_arg++];
+ while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
+ if (node_arg->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str());
+ break;
+
+ case 'm':
+ case 'M':
+ break;
+
+ default:
+ log_file_error(filename, location.first_line, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
+ break;
+ }
+
+ switch (cformat)
+ {
+ case 's':
+ case 'S':
+ sout += node_arg->bitsAsConst().decode_string();
+ break;
+
+ case 'd':
+ case 'D':
+ {
+ char tmp[128];
+ snprintf(tmp, sizeof(tmp), "%d", node_arg->bitsAsConst().as_int());
+ sout += tmp;
+ }
+ break;
+
+ case 'x':
+ case 'X':
+ {
+ char tmp[128];
+ snprintf(tmp, sizeof(tmp), "%x", node_arg->bitsAsConst().as_int());
+ sout += tmp;
+ }
+ break;
+
+ case 'm':
+ case 'M':
+ sout += log_id(current_module->name);
+ break;
+
+ default:
+ log_abort();
+ }
+ }
+
+ // not a format specifier
+ else
+ sout += sformat[i];
+ }
+ return sout;
+}
+
+
// convert the AST into a simpler AST that has all parameters substituted by their
// values, unrolled for-loops, expanded generate blocks, etc. when this function
// is done with an AST it can be converted into RTLIL using genRTLIL().
@@ -62,7 +159,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
#if 0
log("-------------\n");
- log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), linenum, type2str(type).c_str(), this);
+ log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), location.first_line, type2str(type).c_str(), this);
log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
int(const_fold), int(at_zero), int(in_lvalue), int(stage), int(width_hint), int(sign_hint), int(in_param));
// dumpAst(NULL, "> ");
@@ -154,7 +251,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (it.first != ID(mem2reg))
reg->attributes.emplace(it.first, it.second->clone());
reg->filename = node->filename;
- reg->linenum = node->linenum;
+ reg->location = node->location;
children.push_back(reg);
while (reg->simplify(true, false, false, 1, -1, false, false)) { }
}
@@ -176,7 +273,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
current_filename = filename;
- set_line_num(linenum);
// we do not look inside a task or function
// (but as soon as a task or function is instantiated we process the generated AST as usual)
@@ -189,13 +285,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" ||
str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) {
- log_file_warning(filename, linenum, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
+ log_file_warning(filename, location.first_line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
delete_children();
str = std::string();
}
if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) {
- log_file_warning(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
+ log_file_warning(filename, location.first_line, "System task `%s' outside initial block is unsupported.\n", str.c_str());
delete_children();
str = std::string();
}
@@ -207,108 +303,16 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
int nargs = GetSize(children);
if (nargs < 1)
- log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n",
+ log_file_error(filename, location.first_line, "System task `%s' got %d arguments, expected >= 1.\n",
str.c_str(), int(children.size()));
// First argument is the format string
AstNode *node_string = children[0];
while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_string->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str());
std::string sformat = node_string->bitsAsConst().decode_string();
-
- // Other arguments are placeholders. Process the string as we go through it
- std::string sout;
- int next_arg = 1;
- for (size_t i = 0; i < sformat.length(); i++)
- {
- // format specifier
- if (sformat[i] == '%')
- {
- // If there's no next character, that's a problem
- if (i+1 >= sformat.length())
- log_file_error(filename, linenum, "System task `%s' called with `%%' at end of string.\n", str.c_str());
-
- char cformat = sformat[++i];
-
- // %% is special, does not need a matching argument
- if (cformat == '%')
- {
- sout += '%';
- continue;
- }
-
- // Simplify the argument
- AstNode *node_arg = nullptr;
-
- // Everything from here on depends on the format specifier
- switch (cformat)
- {
- case 's':
- case 'S':
- case 'd':
- case 'D':
- case 'x':
- case 'X':
- if (next_arg >= GetSize(children))
- log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n",
- cformat, str.c_str());
-
- node_arg = children[next_arg++];
- while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
- if (node_arg->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str());
- break;
-
- case 'm':
- case 'M':
- break;
-
- default:
- log_file_error(filename, linenum, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
- break;
- }
-
- switch (cformat)
- {
- case 's':
- case 'S':
- sout += node_arg->bitsAsConst().decode_string();
- break;
-
- case 'd':
- case 'D':
- {
- char tmp[128];
- snprintf(tmp, sizeof(tmp), "%d", node_arg->bitsAsConst().as_int());
- sout += tmp;
- }
- break;
-
- case 'x':
- case 'X':
- {
- char tmp[128];
- snprintf(tmp, sizeof(tmp), "%x", node_arg->bitsAsConst().as_int());
- sout += tmp;
- }
- break;
-
- case 'm':
- case 'M':
- sout += log_id(current_module->name);
- break;
-
- default:
- log_abort();
- }
- }
-
- // not a format specifier
- else
- sout += sformat[i];
- }
-
+ std::string sout = process_format_str(sformat, 1, stage, width_hint, sign_hint);
// Finally, print the message (only include a \n for $display, not for $write)
log("%s", sout.c_str());
if (str == "$display")
@@ -318,9 +322,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
- if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
+ if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
const_fold = true;
- if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
+ if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM))
const_fold = true;
// in certain cases a function must be evaluated constant. this is what in_param controls.
@@ -400,23 +404,40 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
continue;
wires_are_incompatible:
if (stage > 1)
- log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", node->str.c_str());
+ log_file_error(filename, location.first_line, "Incompatible re-declaration of wire %s.\n", node->str.c_str());
continue;
}
this_wire_scope[node->str] = node;
}
+ // these nodes appear at the top level in a module and can define names
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL ||
node->type == AST_TYPEDEF) {
backup_scope[node->str] = current_scope[node->str];
current_scope[node->str] = node;
}
+ if (node->type == AST_ENUM) {
+ current_scope[node->str] = node;
+ for (auto enode : node->children) {
+ log_assert(enode->type==AST_ENUM_ITEM);
+ if (current_scope.count(enode->str) == 0) {
+ current_scope[enode->str] = enode;
+ }
+ }
+ }
}
for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i];
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF)
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){
+ log_assert(enode->type==AST_ENUM_ITEM);
+ while (node->simplify(true, false, false, 1, -1, false, in_param))
+ did_something = true;
+ }
+ }
}
}
@@ -429,7 +450,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_ALWAYS || type == AST_INITIAL)
{
if (current_always != nullptr)
- log_file_error(filename, linenum, "Invalid nesting of always blocks and/or initializations.\n");
+ log_file_error(filename, location.first_line, "Invalid nesting of always blocks and/or initializations.\n");
current_always = this;
current_always_clocked = false;
@@ -472,7 +493,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic)
children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)
- log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
+ log_warning("wire '%s' is assigned in a block at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
if (type == AST_ASSIGN && children[0]->id2ast->is_reg) {
bool is_rand_reg = false;
if (children[1]->type == AST_FCALL) {
@@ -486,12 +507,24 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
is_rand_reg = true;
}
if (!is_rand_reg)
- log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
+ log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
}
children[0]->was_checked = true;
}
break;
+ case AST_ENUM:
+ //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
+ if (!basic_prep) {
+ for (auto item_node : children) {
+ while (!item_node->basic_prep && item_node->simplify(false, false, false, stage, -1, false, in_param))
+ did_something = true;
+ }
+ // allocate values (called more than once)
+ allocateDefaultEnumValues();
+ }
+ break;
+
case AST_PARAMETER:
case AST_LOCALPARAM:
while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
@@ -501,7 +534,19 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true)
did_something = true;
if (!children[1]->range_valid)
- log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
+ log_file_error(filename, location.first_line, "Non-constant width range on parameter decl.\n");
+ width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1);
+ }
+ break;
+ case AST_ENUM_ITEM:
+ while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, in_param))
+ did_something = true;
+ children[0]->detectSignWidth(width_hint, sign_hint);
+ if (children.size() > 1 && children[1]->type == AST_RANGE) {
+ while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, in_param))
+ did_something = true;
+ if (!children[1]->range_valid)
+ log_file_error(filename, location.first_line, "Non-constant width range on enum item decl.\n");
width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1);
}
break;
@@ -740,7 +785,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
current_filename = filename;
- set_line_num(linenum);
if (type == AST_MODULE)
current_scope.clear();
@@ -749,7 +793,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_DEFPARAM && !children.empty())
{
if (children[0]->type != AST_IDENTIFIER)
- log_file_error(filename, linenum, "Module name in defparam contains non-constant expressions!\n");
+ log_file_error(filename, location.first_line, "Module name in defparam contains non-constant expressions!\n");
string modname, paramname = children[0]->str;
@@ -766,12 +810,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (pos == std::string::npos)
- log_file_error(filename, linenum, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str());
+ log_file_error(filename, location.first_line, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str());
paramname = "\\" + paramname.substr(pos+1);
if (current_scope.at(modname)->type != AST_CELL)
- log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n",
+ log_file_error(filename, location.first_line, "Defparam argument `%s . %s` does not match a cell!\n",
RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);
@@ -797,10 +841,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
log_assert(children.size() >= 1);
log_assert(children[0]->type == AST_WIRETYPE);
if (!current_scope.count(children[0]->str))
- log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str());
+ log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str());
AstNode *resolved_type = current_scope.at(children[0]->str);
if (resolved_type->type != AST_TYPEDEF)
- log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str());
+ log_file_error(filename, location.first_line, "`%s' does not name a type\n", children[0]->str.c_str());
log_assert(resolved_type->children.size() == 1);
AstNode *templ = resolved_type->children[0];
// Remove type reference
@@ -822,11 +866,68 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
range_swapped = templ->range_swapped;
range_left = templ->range_left;
range_right = templ->range_right;
+ attributes["\\wiretype"] = mkconst_str(resolved_type->str);
+ //check if enum
+ if (templ->attributes.count("\\enum_type")){
+ //get reference to enum node:
+ std::string enum_type = templ->attributes["\\enum_type"]->str.c_str();
+ // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
+ // log("current scope:\n");
+ // for (auto &it : current_scope)
+ // log(" %s\n", it.first.c_str());
+ log_assert(current_scope.count(enum_type) == 1);
+ AstNode *enum_node = current_scope.at(enum_type);
+ log_assert(enum_node->type == AST_ENUM);
+ //get width from 1st enum item:
+ log_assert(enum_node->children.size() >= 1);
+ AstNode *enum_item0 = enum_node->children[0];
+ log_assert(enum_item0->type == AST_ENUM_ITEM);
+ int width;
+ if (!enum_item0->range_valid)
+ width = 1;
+ else if (enum_item0->range_swapped)
+ width = enum_item0->range_right - enum_item0->range_left + 1;
+ else
+ width = enum_item0->range_left - enum_item0->range_right + 1;
+ log_assert(width > 0);
+ //add declared enum items:
+ for (auto enum_item : enum_node->children){
+ log_assert(enum_item->type == AST_ENUM_ITEM);
+ //get is_signed
+ bool is_signed;
+ if (enum_item->children.size() == 1){
+ is_signed = false;
+ } else if (enum_item->children.size() == 2){
+ log_assert(enum_item->children[1]->type == AST_RANGE);
+ is_signed = enum_item->children[1]->is_signed;
+ } else {
+ log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
+ enum_item->children.size(),
+ enum_item->str.c_str(), enum_node->str.c_str()
+ );
+ }
+ //start building attribute string
+ std::string enum_item_str = "\\enum_";
+ enum_item_str.append(std::to_string(width));
+ enum_item_str.append("_");
+ //get enum item value
+ if(enum_item->children[0]->type != AST_CONSTANT){
+ log_error("expected const, got %s for %s (%s)\n",
+ type2str(enum_item->children[0]->type).c_str(),
+ enum_item->str.c_str(), enum_node->str.c_str()
+ );
+ }
+ int val = enum_item->children[0]->asInt(is_signed);
+ enum_item_str.append(std::to_string(val));
+ //set attribute for available val to enum item name mappings
+ attributes[enum_item_str.c_str()] = mkconst_str(enum_item->str);
+ }
+ }
// Insert clones children from template at beginning
for (int i = 0; i < GetSize(templ->children); i++)
children.insert(children.begin() + i, templ->children[i]->clone());
-
+
if (type == AST_MEMORY && GetSize(children) == 1) {
// Single-bit memories must have [0:0] range
AstNode *rng = new AstNode(AST_RANGE);
@@ -846,10 +947,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
log_assert(children.size() == 2);
log_assert(children[1]->type == AST_WIRETYPE);
if (!current_scope.count(children[1]->str))
- log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str());
+ log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str());
AstNode *resolved_type = current_scope.at(children[1]->str);
if (resolved_type->type != AST_TYPEDEF)
- log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str());
+ log_file_error(filename, location.first_line, "`%s' does not name a type\n", children[1]->str.c_str());
log_assert(resolved_type->children.size() == 1);
AstNode *templ = resolved_type->children[0];
delete children[1];
@@ -859,7 +960,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
if (templ->type == AST_MEMORY)
- log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
+ log_file_error(filename, location.first_line, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
is_signed = templ->is_signed;
is_string = templ->is_string;
is_custom_type = templ->is_custom_type;
@@ -868,18 +969,19 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
range_swapped = templ->range_swapped;
range_left = templ->range_left;
range_right = templ->range_right;
+ attributes["\\wiretype"] = mkconst_str(resolved_type->str);
for (auto template_child : templ->children)
children.push_back(template_child->clone());
did_something = true;
}
log_assert(!is_custom_type);
- }
+ }
// resolve constant prefixes
if (type == AST_PREFIX) {
if (children[0]->type != AST_CONSTANT) {
// dumpAst(NULL, "> ");
- log_file_error(filename, linenum, "Index in generate block prefix syntax is not constant!\n");
+ log_file_error(filename, location.first_line, "Index in generate block prefix syntax is not constant!\n");
}
if (children[1]->type == AST_PREFIX)
children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param);
@@ -895,9 +997,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// evaluate TO_BITS nodes
if (type == AST_TO_BITS) {
if (children[0]->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Left operand of to_bits expression is not constant!\n");
+ log_file_error(filename, location.first_line, "Left operand of to_bits expression is not constant!\n");
if (children[1]->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Right operand of to_bits expression is not constant!\n");
+ log_file_error(filename, location.first_line, "Right operand of to_bits expression is not constant!\n");
RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
goto apply_newNode;
@@ -961,7 +1063,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
multirange_dimensions.clear();
for (auto range : children[1]->children) {
if (!range->range_valid)
- log_file_error(filename, linenum, "Non-constant range on memory decl.\n");
+ log_file_error(filename, location.first_line, "Non-constant range on memory decl.\n");
multirange_dimensions.push_back(min(range->range_left, range->range_right));
multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1);
total_size *= multirange_dimensions.back();
@@ -979,7 +1081,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++)
{
if (GetSize(children[0]->children) < i)
- log_file_error(filename, linenum, "Insufficient number of array indices for %s.\n", log_id(str));
+ log_file_error(filename, location.first_line, "Insufficient number of array indices for %s.\n", log_id(str));
AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
@@ -1005,14 +1107,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
// trim/extend parameters
- if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
+ if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM) {
if (children.size() > 1 && children[1]->type == AST_RANGE) {
if (!children[1]->range_valid)
- log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
+ log_file_error(filename, location.first_line, "Non-constant width range on parameter decl.\n");
int width = std::abs(children[1]->range_left - children[1]->range_right) + 1;
if (children[0]->type == AST_REALVALUE) {
RTLIL::Const constvalue = children[0]->realAsConst(width);
- log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+ log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n",
children[0]->realvalue, log_signal(constvalue));
delete children[0];
children[0] = mkconst_bits(constvalue.bits, sign_hint);
@@ -1046,9 +1148,34 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_IDENTIFIER) {
if (current_scope.count(str) == 0) {
for (auto node : current_ast_mod->children) {
- if ((node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
- node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION) && str == node->str) {
+ //log("looking at mod scope child %s\n", type2str(node->type).c_str());
+ switch (node->type) {
+ case AST_PARAMETER:
+ case AST_LOCALPARAM:
+ case AST_WIRE:
+ case AST_AUTOWIRE:
+ case AST_GENVAR:
+ case AST_MEMORY:
+ case AST_FUNCTION:
+ case AST_TASK:
+ case AST_DPI_FUNCTION:
+ //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
+ if (str == node->str) {
+ //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
+ current_scope[node->str] = node;
+ }
+ break;
+ case AST_ENUM:
current_scope[node->str] = node;
+ for (auto enum_node : node->children) {
+ log_assert(enum_node->type==AST_ENUM_ITEM);
+ if (str == enum_node->str) {
+ //log("\nadding enum item %s to scope\n", str.c_str());
+ current_scope[str] = enum_node;
+ }
+ }
+ break;
+ default:
break;
}
}
@@ -1061,7 +1188,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
current_scope[str] = auto_wire;
did_something = true;
} else {
- log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
}
}
if (id2ast != current_scope[str]) {
@@ -1074,7 +1201,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
{
if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
- log_file_error(filename, linenum, "Invalid bit-select on memory access!\n");
+ log_file_error(filename, location.first_line, "Invalid bit-select on memory access!\n");
int mem_width, mem_size, addr_bits;
id2ast->meminfo(mem_width, mem_size, addr_bits);
@@ -1086,7 +1213,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
std::swap(data_range_left, data_range_right);
std::stringstream sstr;
- sstr << "$mem2bits$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
+ sstr << "$mem2bits$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
std::string wire_id = sstr.str();
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
@@ -1127,7 +1254,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (type == AST_WHILE)
- log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n");
+ log_file_error(filename, location.first_line, "While loops are only allowed in constant functions!\n");
if (type == AST_REPEAT)
{
@@ -1138,7 +1265,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (count->simplify(true, false, false, stage, 32, true, false)) { }
if (count->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Repeat loops outside must have constant repeat counts!\n");
+ log_file_error(filename, location.first_line, "Repeat loops outside must have constant repeat counts!\n");
// convert to a block with the body repeated n times
type = AST_BLOCK;
@@ -1164,24 +1291,24 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
body_ast = body_ast->children.at(0);
if (init_ast->type != AST_ASSIGN_EQ)
- log_file_error(filename, linenum, "Unsupported 1st expression of generate for-loop!\n");
+ log_file_error(filename, location.first_line, "Unsupported 1st expression of generate for-loop!\n");
if (next_ast->type != AST_ASSIGN_EQ)
- log_file_error(filename, linenum, "Unsupported 3rd expression of generate for-loop!\n");
+ log_file_error(filename, location.first_line, "Unsupported 3rd expression of generate for-loop!\n");
if (type == AST_GENFOR) {
if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
- log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
+ log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR)
- log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
+ log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
} else {
if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE)
- log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a register!\n");
+ log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a register!\n");
if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE)
- log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
+ log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
}
if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast)
- log_file_error(filename, linenum, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
+ log_file_error(filename, location.first_line, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
// eval 1st expression
AstNode *varbuf = init_ast->children[1]->clone();
@@ -1193,19 +1320,25 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (varbuf->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n");
-
- varbuf = new AstNode(AST_LOCALPARAM, varbuf);
- varbuf->str = init_ast->children[0]->str;
+ log_file_error(filename, location.first_line, "Right hand side of 1st expression of generate for-loop is not constant!\n");
auto resolved = current_scope.at(init_ast->children[0]->str);
if (resolved->range_valid) {
- varbuf->range_left = resolved->range_left;
- varbuf->range_right = resolved->range_right;
- varbuf->range_swapped = resolved->range_swapped;
- varbuf->range_valid = resolved->range_valid;
+ int const_size = varbuf->range_left - varbuf->range_right;
+ int resolved_size = resolved->range_left - resolved->range_right;
+ if (const_size < resolved_size) {
+ for (int i = const_size; i < resolved_size; i++)
+ varbuf->bits.push_back(resolved->is_signed ? varbuf->bits.back() : State::S0);
+ varbuf->range_left = resolved->range_left;
+ varbuf->range_right = resolved->range_right;
+ varbuf->range_swapped = resolved->range_swapped;
+ varbuf->range_valid = resolved->range_valid;
+ }
}
+ varbuf = new AstNode(AST_LOCALPARAM, varbuf);
+ varbuf->str = init_ast->children[0]->str;
+
AstNode *backup_scope_varbuf = current_scope[varbuf->str];
current_scope[varbuf->str] = varbuf;
@@ -1228,7 +1361,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (buf->type != AST_CONSTANT)
- log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n");
+ log_file_error(filename, location.first_line, "2nd expression of generate for-loop is not constant!\n");
if (buf->integer == 0) {
delete buf;
@@ -1244,7 +1377,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
buf = new AstNode(AST_GENBLOCK, body_ast->clone());
if (buf->str.empty()) {
std::stringstream sstr;
- sstr << "$genblock$" << filename << ":" << linenum << "$" << (autoidx++);
+ sstr << "$genblock$" << filename << ":" << location.first_line << "$" << (autoidx++);
buf->str = sstr.str();
}
std::map<std::string, std::string> name_map;
@@ -1274,7 +1407,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (buf->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
+ log_file_error(filename, location.first_line, "Right hand side of 3rd expression of generate for-loop is not constant (%s)!\n", type2str(buf->type).c_str());
delete varbuf->children[0];
varbuf->children[0] = buf;
@@ -1298,7 +1431,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
for (size_t i = 0; i < children.size(); i++)
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF)
- log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
+ log_file_error(children[i]->filename, children[i]->location.first_line, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
}
// transform block with name
@@ -1346,7 +1479,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (buf->type != AST_CONSTANT) {
// for (auto f : log_files)
// dumpAst(f, "verilog-ast> ");
- log_file_error(filename, linenum, "Condition for generate if is not constant!\n");
+ log_file_error(filename, location.first_line, "Condition for generate if is not constant!\n");
}
if (buf->asBool() != 0) {
delete buf;
@@ -1387,7 +1520,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (buf->type != AST_CONSTANT) {
// for (auto f : log_files)
// dumpAst(f, "verilog-ast> ");
- log_file_error(filename, linenum, "Condition for generate case is not constant!\n");
+ log_file_error(filename, location.first_line, "Condition for generate case is not constant!\n");
}
bool ref_signed = buf->is_signed;
@@ -1421,7 +1554,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (buf->type != AST_CONSTANT) {
// for (auto f : log_files)
// dumpAst(f, "verilog-ast> ");
- log_file_error(filename, linenum, "Expression in generate case is not constant!\n");
+ log_file_error(filename, location.first_line, "Expression in generate case is not constant!\n");
}
bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool();
@@ -1462,7 +1595,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_CELLARRAY)
{
if (!children.at(0)->range_valid)
- log_file_error(filename, linenum, "Non-constant array range on cell array.\n");
+ log_file_error(filename, location.first_line, "Non-constant array range on cell array.\n");
newNode = new AstNode(AST_GENBLOCK);
int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1;
@@ -1473,7 +1606,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
newNode->children.push_back(new_cell);
new_cell->str += stringf("[%d]", idx);
if (new_cell->type == AST_PRIMITIVE) {
- log_file_error(filename, linenum, "Cell arrays of primitives are currently not supported.\n");
+ log_file_error(filename, location.first_line, "Cell arrays of primitives are currently not supported.\n");
} else {
log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
@@ -1487,7 +1620,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PRIMITIVE)
{
if (children.size() < 2)
- log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str());
+ log_file_error(filename, location.first_line, "Insufficient number of arguments for primitive `%s'!\n", str.c_str());
std::vector<AstNode*> children_list;
for (auto child : children) {
@@ -1502,7 +1635,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
{
if (children_list.size() != 3)
- log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str());
+ log_file_error(filename, location.first_line, "Invalid number of arguments for primitive `%s'!\n", str.c_str());
std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
@@ -1589,7 +1722,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
+ log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
}
did_something = true;
@@ -1611,7 +1744,7 @@ skip_dynamic_range_lvalue_expansion:;
if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && current_block != NULL)
{
std::stringstream sstr;
- sstr << "$formal$" << filename << ":" << linenum << "$" << (autoidx++);
+ sstr << "$formal$" << filename << ":" << location.first_line << "$" << (autoidx++);
std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
AstNode *wire_check = new AstNode(AST_WIRE);
@@ -1719,7 +1852,7 @@ skip_dynamic_range_lvalue_expansion:;
newNode = new AstNode(AST_BLOCK);
AstNode *wire_tmp = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true)));
- wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", filename.c_str(), linenum, autoidx++);
+ 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);
@@ -1757,7 +1890,7 @@ skip_dynamic_range_lvalue_expansion:;
(children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE)
{
std::stringstream sstr;
- sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
+ sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
int mem_width, mem_size, addr_bits;
@@ -1868,7 +2001,7 @@ skip_dynamic_range_lvalue_expansion:;
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
+ log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
@@ -1964,11 +2097,11 @@ skip_dynamic_range_lvalue_expansion:;
int num_steps = 1;
if (GetSize(children) != 1 && GetSize(children) != 2)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
if (!current_always_clocked)
- log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
+ log_file_error(filename, location.first_line, "System function %s is only allowed in clocked blocks.\n",
RTLIL::unescape_id(str).c_str());
if (GetSize(children) == 2)
@@ -1976,7 +2109,7 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *buf = children[1]->clone();
while (buf->simplify(true, false, false, stage, -1, false, false)) { }
if (buf->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
num_steps = buf->asInt(true);
delete buf;
@@ -2003,7 +2136,7 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE,
mkconst_int(width_hint-1, true), mkconst_int(0, true)));
- reg->str = stringf("$past$%s:%d$%d$%d", filename.c_str(), linenum, myidx, i);
+ reg->str = stringf("$past$%s:%d$%d$%d", filename.c_str(), location.first_line, myidx, i);
reg->is_reg = true;
current_ast_mod->children.push_back(reg);
@@ -2038,11 +2171,11 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell" || str == "\\$changed")
{
if (GetSize(children) != 1)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
if (!current_always_clocked)
- log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
+ log_file_error(filename, location.first_line, "System function %s is only allowed in clocked blocks.\n",
RTLIL::unescape_id(str).c_str());
AstNode *present = children.at(0)->clone();
@@ -2080,13 +2213,13 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$clog2")
{
if (children.size() != 1)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
AstNode *buf = children[0]->clone();
while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (buf->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
RTLIL::Const arg_value = buf->bitsAsConst();
if (arg_value.as_bool())
@@ -2105,11 +2238,11 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$size" || str == "\\$bits")
{
if (str == "\\$bits" && children.size() != 1)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
if (str == "\\$size" && children.size() != 1 && children.size() != 2)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
int dim = 1;
@@ -2133,7 +2266,7 @@ skip_dynamic_range_lvalue_expansion:;
if (id_ast == NULL && current_scope.count(buf->str))
id_ast = current_scope.at(buf->str);
if (!id_ast)
- log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str());
+ log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str());
if (id_ast->type == AST_MEMORY) {
// We got here only if the argument is a memory
// Otherwise $size() and $bits() return the expression width
@@ -2141,15 +2274,15 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "\\$bits") {
if (mem_range->type == AST_RANGE) {
if (!mem_range->range_valid)
- log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
+ log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
mem_depth = mem_range->range_left - mem_range->range_right + 1;
} else
- log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
+ log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
} else {
// $size()
if (mem_range->type == AST_RANGE) {
if (!mem_range->range_valid)
- log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
+ log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
int dims;
if (id_ast->multirange_dimensions.empty())
dims = 1;
@@ -2160,9 +2293,9 @@ skip_dynamic_range_lvalue_expansion:;
else if (dim <= dims) {
width_hint = id_ast->multirange_dimensions[2*dim-1];
} else if ((dim > dims+1) || (dim < 0))
- log_file_error(filename, linenum, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1);
+ log_file_error(filename, location.first_line, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1);
} else
- log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
+ log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
}
}
}
@@ -2183,18 +2316,18 @@ skip_dynamic_range_lvalue_expansion:;
if (func_with_two_arguments) {
if (children.size() != 2)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 2.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
} else {
if (children.size() != 1)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
}
if (children.size() >= 1) {
while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (!children[0]->isConst())
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant argument.\n",
RTLIL::unescape_id(str).c_str());
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
@@ -2205,7 +2338,7 @@ skip_dynamic_range_lvalue_expansion:;
if (children.size() >= 2) {
while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (!children[1]->isConst())
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant argument.\n",
RTLIL::unescape_id(str).c_str());
int child_width_hint = width_hint;
bool child_sign_hint = sign_hint;
@@ -2244,6 +2377,17 @@ skip_dynamic_range_lvalue_expansion:;
goto apply_newNode;
}
+ if (str == "\\$sformatf") {
+ AstNode *node_string = children[0];
+ while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
+ if (node_string->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
+ std::string sformat = node_string->bitsAsConst().decode_string();
+ std::string sout = process_format_str(sformat, 1, stage, width_hint, sign_hint);
+ newNode = AstNode::mkconst_str(sout);
+ goto apply_newNode;
+ }
+
if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION)
{
AstNode *dpi_decl = current_scope[str];
@@ -2258,14 +2402,14 @@ skip_dynamic_range_lvalue_expansion:;
for (int i = 2; i < GetSize(dpi_decl->children); i++)
{
if (i-2 >= GetSize(children))
- log_file_error(filename, linenum, "Insufficient number of arguments in DPI function call.\n");
+ log_file_error(filename, location.first_line, "Insufficient number of arguments in DPI function call.\n");
argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str));
args.push_back(children.at(i-2)->clone());
while (args.back()->simplify(true, false, false, stage, -1, false, true)) { }
if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE)
- log_file_error(filename, linenum, "Failed to evaluate DPI function with non-constant argument.\n");
+ log_file_error(filename, location.first_line, "Failed to evaluate DPI function with non-constant argument.\n");
}
newNode = dpi_call(rtype, fname, argtypes, args);
@@ -2277,7 +2421,7 @@ skip_dynamic_range_lvalue_expansion:;
}
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
- log_file_error(filename, linenum, "Can't resolve function name `%s'.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Can't resolve function name `%s'.\n", str.c_str());
}
if (type == AST_TCALL)
@@ -2285,26 +2429,26 @@ skip_dynamic_range_lvalue_expansion:;
if (str == "$finish" || str == "$stop")
{
if (!current_always || current_always->type != AST_INITIAL)
- log_file_error(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
+ log_file_error(filename, location.first_line, "System task `%s' outside initial block is unsupported.\n", str.c_str());
- log_file_error(filename, linenum, "System task `%s' executed.\n", str.c_str());
+ log_file_error(filename, location.first_line, "System task `%s' executed.\n", str.c_str());
}
if (str == "\\$readmemh" || str == "\\$readmemb")
{
if (GetSize(children) < 2 || GetSize(children) > 4)
- log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n",
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 2-4.\n",
RTLIL::unescape_id(str).c_str(), int(children.size()));
AstNode *node_filename = children[0]->clone();
while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_filename->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
AstNode *node_memory = children[1]->clone();
while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY)
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str());
int start_addr = -1, finish_addr = -1;
@@ -2312,7 +2456,7 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *node_addr = children[2]->clone();
while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_addr->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str());
start_addr = int(node_addr->asInt(false));
}
@@ -2320,7 +2464,7 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *node_addr = children[3]->clone();
while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_addr->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str());
finish_addr = int(node_addr->asInt(false));
}
@@ -2348,13 +2492,13 @@ skip_dynamic_range_lvalue_expansion:;
}
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK)
- log_file_error(filename, linenum, "Can't resolve task name `%s'.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Can't resolve task name `%s'.\n", str.c_str());
}
AstNode *decl = current_scope[str];
std::stringstream sstr;
- sstr << "$func$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++) << "$";
+ sstr << "$func$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++) << "$";
std::string prefix = sstr.str();
bool recommend_const_eval = false;
@@ -2376,9 +2520,9 @@ skip_dynamic_range_lvalue_expansion:;
}
if (in_param)
- log_file_error(filename, linenum, "Non-constant function call in constant expression.\n");
+ log_file_error(filename, location.first_line, "Non-constant function call in constant expression.\n");
if (require_const_eval)
- log_file_error(filename, linenum, "Function %s can only be called with constant arguments.\n", str.c_str());
+ log_file_error(filename, location.first_line, "Function %s can only be called with constant arguments.\n", str.c_str());
}
size_t arg_count = 0;
@@ -2482,7 +2626,7 @@ skip_dynamic_range_lvalue_expansion:;
}
for (auto child : decl->children)
- if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
+ if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_ENUM_ITEM)
{
AstNode *wire = nullptr;
@@ -2500,7 +2644,7 @@ skip_dynamic_range_lvalue_expansion:;
goto tcall_incompatible_wires;
} else {
tcall_incompatible_wires:
- log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", child->str.c_str());
+ log_file_error(filename, location.first_line, "Incompatible re-declaration of wire %s.\n", child->str.c_str());
}
}
}
@@ -2513,6 +2657,9 @@ skip_dynamic_range_lvalue_expansion:;
wire->is_output = false;
wire->is_reg = true;
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ if (child->type == AST_ENUM_ITEM)
+ wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"];
+
wire_cache[child->str] = wire;
current_ast_mod->children.push_back(wire);
@@ -2588,7 +2735,7 @@ replace_fcall_later:;
switch (type)
{
case AST_IDENTIFIER:
- if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) {
+ if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM)) {
if (current_scope[str]->children[0]->type == AST_CONSTANT) {
if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
std::vector<RTLIL::State> data;
@@ -2851,7 +2998,7 @@ apply_newNode:
// newNode->dumpAst(stderr, "+ ");
log_assert(newNode != NULL);
newNode->filename = filename;
- newNode->linenum = linenum;
+ newNode->location = location;
newNode->cloneInto(this);
delete newNode;
did_something = true;
@@ -2887,10 +3034,20 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
std::ifstream f;
f.open(mem_filename.c_str());
- yosys_input_files.insert(mem_filename);
-
- if (f.fail())
- log_file_error(filename, linenum, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str());
+ if (f.fail()) {
+#ifdef _WIN32
+ char slash = '\\';
+#else
+ char slash = '/';
+#endif
+ std::string path = filename.substr(0, filename.find_last_of(slash)+1);
+ f.open(path + mem_filename.c_str());
+ yosys_input_files.insert(path + mem_filename);
+ } else {
+ yosys_input_files.insert(mem_filename);
+ }
+ if (f.fail() || GetSize(mem_filename) == 0)
+ log_file_error(filename, location.first_line, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str());
log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid);
int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right;
@@ -2936,7 +3093,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
char *endptr;
cursor = strtol(nptr, &endptr, 16);
if (!*nptr || *endptr)
- log_file_error(filename, linenum, "Can not parse address `%s` for %s.\n", nptr, str.c_str());
+ log_file_error(filename, location.first_line, "Can not parse address `%s` for %s.\n", nptr, str.c_str());
continue;
}
@@ -3006,14 +3163,6 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
current_ast_mod->children.push_back(p);
str = p->str;
id2ast = p;
-
- auto resolved = current_scope.at(index_var);
- if (resolved->range_valid) {
- p->range_left = resolved->range_left;
- p->range_right = resolved->range_right;
- p->range_swapped = resolved->range_swapped;
- p->range_valid = resolved->range_valid;
- }
}
}
@@ -3025,7 +3174,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
for (size_t i = 0; i < children.size(); i++) {
AstNode *child = children[i];
if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
- child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) {
+ child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF || child->type == AST_ENUM_ITEM) {
if (backup_name_map.size() == 0)
backup_name_map = name_map;
std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
@@ -3044,6 +3193,27 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
child->str = new_name;
current_scope[new_name] = child;
}
+ if (child->type == AST_ENUM){
+ current_scope[child->str] = child;
+ for (auto enode : child->children){
+ log_assert(enode->type == AST_ENUM_ITEM);
+ if (backup_name_map.size() == 0)
+ backup_name_map = name_map;
+ std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
+ size_t pos = enode->str.rfind('.');
+ if (pos == std::string::npos)
+ pos = enode->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
+ else
+ pos = pos + 1;
+ new_name = enode->str.substr(0, pos) + new_name + enode->str.substr(pos);
+ if (new_name[0] != '$' && new_name[0] != '\\')
+ new_name = prefix[0] + new_name;
+ name_map[enode->str] = new_name;
+
+ enode->str = new_name;
+ current_scope[new_name] = enode;
+ }
+ }
}
for (size_t i = 0; i < children.size(); i++) {
@@ -3098,7 +3268,7 @@ static void mark_memories_assign_lhs_complex(dict<AstNode*, pool<std::string>> &
if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) {
AstNode *mem = that->id2ast;
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS))
- mem2reg_places[mem].insert(stringf("%s:%d", that->filename.c_str(), that->linenum));
+ mem2reg_places[mem].insert(stringf("%s:%d", that->filename.c_str(), that->location.first_line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS;
}
}
@@ -3126,14 +3296,14 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
// activate mem2reg if this is assigned in an async proc
if (flags & AstNode::MEM2REG_FL_ASYNC) {
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
- mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
+ mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
}
// remember if this is assigned blocking (=)
if (type == AST_ASSIGN_EQ) {
if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
- mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
+ mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
}
@@ -3150,11 +3320,11 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
// remember where this is
if (flags & MEM2REG_FL_INIT) {
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
- mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
+ mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
} else {
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
- mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
+ mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
}
}
@@ -3168,7 +3338,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
// flag if used after blocking assignment (in same proc)
if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
- mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
+ mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
}
}
@@ -3237,7 +3407,7 @@ bool AstNode::mem2reg_check(pool<AstNode*> &mem2reg_set)
return false;
if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1)
- log_file_error(filename, linenum, "Invalid array access.\n");
+ log_file_error(filename, location.first_line, "Invalid array access.\n");
return true;
}
@@ -3329,7 +3499,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
children[0]->children[0]->children[0]->type != AST_CONSTANT)
{
std::stringstream sstr;
- sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
+ sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
int mem_width, mem_size, addr_bits;
@@ -3408,7 +3578,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
else
{
std::stringstream sstr;
- sstr << "$mem2reg_rd$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
+ sstr << "$mem2reg_rd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
int mem_width, mem_size, addr_bits;
@@ -3552,13 +3722,13 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
int offset = variables.at(str).offset, width = variables.at(str).val.bits.size();
if (!children.empty()) {
if (children.size() != 1 || children.at(0)->type != AST_RANGE)
- log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(filename, location.first_line, "Memory access in constant function is not supported\n%s:%d.%d-%d.%d: ...called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
children.at(0)->replace_variables(variables, fcall);
while (simplify(true, false, false, 1, -1, false, true)) { }
if (!children.at(0)->range_valid)
- log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(filename, location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
offset = min(children.at(0)->range_left, children.at(0)->range_right);
width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
}
@@ -3589,8 +3759,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
{
while (child->simplify(true, false, false, 1, -1, false, true)) { }
if (!child->range_valid)
- log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n",
- child->str.c_str(), fcall->filename.c_str(), fcall->linenum);
+ log_file_error(child->filename, child->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
+ child->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
variables[child->str].offset = min(child->range_left, child->range_right);
variables[child->str].is_signed = child->is_signed;
@@ -3629,24 +3799,24 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
if (stmt->children.at(1)->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here. X\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
if (stmt->children.at(0)->type != AST_IDENTIFIER)
- log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->location.first_line, "Unsupported composite left hand side in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
if (!variables.count(stmt->children.at(0)->str))
- log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->location.first_line, "Assignment to non-local variable in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
if (stmt->children.at(0)->children.empty()) {
variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
} else {
AstNode *range = stmt->children.at(0)->children.at(0);
if (!range->range_valid)
- log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(range->filename, range->location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
int offset = min(range->range_left, range->range_right);
int width = std::abs(range->range_left - range->range_right) + 1;
varinfo_t &v = variables[stmt->children.at(0)->str];
@@ -3677,8 +3847,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
if (cond->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
if (cond->asBool()) {
block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
@@ -3698,8 +3868,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (num->simplify(true, false, false, 1, -1, false, true)) { }
if (num->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
block->children.erase(block->children.begin());
for (int i = 0; i < num->bitsAsConst().as_int(); i++)
@@ -3736,8 +3906,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
if (cond->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
found_match = cond->asBool();
delete cond;
@@ -3766,8 +3936,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
}
- log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->linenum);
+ log_file_error(stmt->filename, stmt->location.first_line, "Unsupported language construct in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
+ fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
log_abort();
}
@@ -3782,4 +3952,32 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
}
+void AstNode::allocateDefaultEnumValues()
+{
+ log_assert(type==AST_ENUM);
+ int last_enum_int = -1;
+ for (auto node : children) {
+ log_assert(node->type==AST_ENUM_ITEM);
+ node->attributes["\\enum_base_type"] = mkconst_str(str);
+ for (size_t i = 0; i < node->children.size(); i++) {
+ switch (node->children[i]->type) {
+ case AST_NONE:
+ // replace with auto-incremented constant
+ delete node->children[i];
+ node->children[i] = AstNode::mkconst_int(++last_enum_int, true);
+ break;
+ case AST_CONSTANT:
+ // explicit constant (or folded expression)
+ // TODO: can't extend 'x or 'z item
+ last_enum_int = node->children[i]->integer;
+ break;
+ default:
+ // ignore ranges
+ break;
+ }
+ // TODO: range check
+ }
+ }
+}
+
YOSYS_NAMESPACE_END