aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/ast')
-rw-r--r--frontends/ast/ast.cc4
-rw-r--r--frontends/ast/genrtlil.cc46
-rw-r--r--frontends/ast/simplify.cc224
3 files changed, 217 insertions, 57 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index a45859157..3e163bae7 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -699,7 +699,7 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
for (size_t i = 0; i < 32; i++) {
if (i < node->bits.size())
node->integer |= (node->bits[i] == RTLIL::S1) << i;
- else if (is_signed)
+ else if (is_signed && !node->bits.empty())
node->integer |= (node->bits.back() == RTLIL::S1) << i;
}
node->range_valid = true;
@@ -831,7 +831,7 @@ double AstNode::asReal(bool is_signed)
{
RTLIL::Const val(bits);
- bool is_negative = is_signed && val.bits.back() == RTLIL::State::S1;
+ bool is_negative = is_signed && !val.bits.empty() && val.bits.back() == RTLIL::State::S1;
if (is_negative)
val = const_neg(val, val, false, false, val.bits.size());
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index a2655e9a5..87e8379e9 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -520,6 +520,11 @@ struct AST_INTERNAL::ProcessGenerator
log_error("Found wire declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
break;
+ case AST_PARAMETER:
+ case AST_LOCALPARAM:
+ log_error("Found parameter declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
+ break;
+
case AST_TCALL:
case AST_FOR:
break;
@@ -547,14 +552,14 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
switch (type)
{
case AST_CONSTANT:
- width_hint = std::max(width_hint, int(bits.size()));
+ width_hint = max(width_hint, int(bits.size()));
if (!is_signed)
sign_hint = false;
break;
case AST_REALVALUE:
*found_real = true;
- width_hint = std::max(width_hint, 32);
+ width_hint = max(width_hint, 32);
break;
case AST_IDENTIFIER:
@@ -617,7 +622,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
this_width = range->range_left - range->range_right + 1;
sign_hint = false;
}
- width_hint = std::max(width_hint, this_width);
+ width_hint = max(width_hint, this_width);
if (!id_ast->is_signed)
sign_hint = false;
break;
@@ -627,7 +632,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (children[0]->type != AST_CONSTANT)
log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
- width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int());
+ width_hint = max(width_hint, children[0]->bitsAsConst().as_int());
break;
case AST_TO_SIGNED:
@@ -646,7 +651,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
child->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
this_width += sub_width_hint;
}
- width_hint = std::max(width_hint, this_width);
+ width_hint = max(width_hint, this_width);
sign_hint = false;
break;
@@ -655,7 +660,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (children[0]->type != AST_CONSTANT)
log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
- width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint);
+ width_hint = max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint);
sign_hint = false;
break;
@@ -678,7 +683,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_REDUCE_XOR:
case AST_REDUCE_XNOR:
case AST_REDUCE_BOOL:
- width_hint = std::max(width_hint, 1);
+ width_hint = max(width_hint, 1);
sign_hint = false;
break;
@@ -698,7 +703,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_NEX:
case AST_GE:
case AST_GT:
- width_hint = std::max(width_hint, 1);
+ width_hint = max(width_hint, 1);
sign_hint = false;
break;
@@ -714,7 +719,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_LOGIC_AND:
case AST_LOGIC_OR:
case AST_LOGIC_NOT:
- width_hint = std::max(width_hint, 1);
+ width_hint = max(width_hint, 1);
sign_hint = false;
break;
@@ -729,7 +734,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (!id2ast->children[0]->range_valid)
log_error("Failed to detect with of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1;
- width_hint = std::max(width_hint, this_width);
+ width_hint = max(width_hint, this_width);
break;
// everything should have been handled above -> print error if not.
@@ -1054,7 +1059,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
detectSignWidth(width_hint, sign_hint);
RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
- int width = std::max(left.size(), right.size());
+ int width = max(left.size(), right.size());
if (width_hint > 0)
width = width_hint;
is_signed = children[0]->is_signed && children[1]->is_signed;
@@ -1068,7 +1073,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (0) { case AST_REDUCE_XNOR: type_name = "$reduce_xnor"; }
{
RTLIL::SigSpec arg = children[0]->genRTLIL();
- RTLIL::SigSpec sig = uniop2rtlil(this, type_name, std::max(width_hint, 1), arg);
+ RTLIL::SigSpec sig = uniop2rtlil(this, type_name, max(width_hint, 1), arg);
return sig;
}
@@ -1077,7 +1082,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (0) { case AST_REDUCE_BOOL: type_name = "$reduce_bool"; }
{
RTLIL::SigSpec arg = children[0]->genRTLIL();
- RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, std::max(width_hint, 1), arg) : arg;
+ RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, max(width_hint, 1), arg) : arg;
return sig;
}
@@ -1123,7 +1128,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (0) { case AST_GE: type_name = "$ge"; }
if (0) { case AST_GT: type_name = "$gt"; }
{
- int width = std::max(width_hint, 1);
+ int width = max(width_hint, 1);
width_hint = -1, sign_hint = true;
children[0]->detectSignWidthWorker(width_hint, sign_hint);
children[1]->detectSignWidthWorker(width_hint, sign_hint);
@@ -1145,7 +1150,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
#if 0
- int width = std::max(left.size(), right.size());
+ int width = max(left.size(), right.size());
if (width > width_hint && width_hint > 0)
width = width_hint;
if (width < width_hint) {
@@ -1154,10 +1159,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed))
width = width_hint;
if (type == AST_MUL)
- width = std::min(left.size() + right.size(), width_hint);
+ width = min(left.size() + right.size(), width_hint);
}
#else
- int width = std::max(std::max(left.size(), right.size()), width_hint);
+ int width = max(max(left.size(), right.size()), width_hint);
#endif
is_signed = children[0]->is_signed && children[1]->is_signed;
return binop2rtlil(this, type_name, width, left, right);
@@ -1169,14 +1174,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
{
RTLIL::SigSpec left = children[0]->genRTLIL();
RTLIL::SigSpec right = children[1]->genRTLIL();
- return binop2rtlil(this, type_name, std::max(width_hint, 1), left, right);
+ return binop2rtlil(this, type_name, max(width_hint, 1), left, right);
}
// generate cells for unary operations: $logic_not
case AST_LOGIC_NOT:
{
RTLIL::SigSpec arg = children[0]->genRTLIL();
- return uniop2rtlil(this, "$logic_not", std::max(width_hint, 1), arg);
+ return uniop2rtlil(this, "$logic_not", max(width_hint, 1), arg);
}
// generate multiplexer for ternary operator (aka ?:-operator)
@@ -1192,7 +1197,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (cond.size() > 1)
cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false);
- int width = std::max(val1.size(), val2.size());
+ int width = max(val1.size(), val2.size());
is_signed = children[1]->is_signed && children[2]->is_signed;
widthExtend(this, val1, width, is_signed);
widthExtend(this, val2, width, is_signed);
@@ -1220,6 +1225,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
id2ast->meminfo(mem_width, mem_size, addr_bits);
cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
+ cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1));
cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
cell->setPort("\\DATA", RTLIL::SigSpec(wire));
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 5eb173c9a..2264d896a 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -174,13 +174,113 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
// deactivate all calls to non-synthesis system tasks
- if ((type == AST_FCALL || type == AST_TCALL) && (str == "$display" || str == "$strobe" || str == "$monitor" || str == "$time" || str == "$stop" || str == "$finish" ||
+ // note that $display and $finish 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 == "$stop" ||
str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) {
log_warning("Ignoring call to system %s %s at %s:%d.\n", type == AST_FCALL ? "function" : "task", str.c_str(), filename.c_str(), linenum);
delete_children();
str = std::string();
}
+ if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) {
+ log_warning("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ delete_children();
+ str = std::string();
+ }
+
+ // print messages if this a call to $display() or $write()
+ // This code implements only a small subset of Verilog-2005 $display() format specifiers,
+ // but should be good enough for most uses
+ if ((type == AST_TCALL) && ((str == "$display") || (str == "$write")))
+ {
+ size_t nargs = GetSize(children);
+ if(nargs < 1)
+ log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n",
+ str.c_str(), int(children.size()), filename.c_str(), linenum);
+
+ // First argument is the format string
+ AstNode *node_string = children[0]->clone();
+ while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
+ if (node_string->type != AST_CONSTANT)
+ log_error("Failed to evaluate system task `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ std::string sformat = node_string->bitsAsConst().decode_string();
+
+ // Other arguments are placeholders. Process the string as we go through it
+ std::string sout;
+ size_t 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_error("System task `%s' called with `%%' at end of string at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+
+ char cformat = sformat[++i];
+
+ // %% is special, does not need a matching argument
+ if(cformat == '%')
+ {
+ sout += '%';
+ continue;
+ }
+
+ // If we're out of arguments, that's a problem!
+ if(next_arg >= nargs)
+ log_error("System task `%s' called with more format specifiers than arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+
+ // Simplify the argument
+ AstNode *node_arg = children[next_arg ++]->clone();
+ while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
+ if (node_arg->type != AST_CONSTANT)
+ log_error("Failed to evaluate system task `%s' with non-constant argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+
+ // Everything from here on depends on the format specifier
+ 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;
+
+ default:
+ log_error("System task `%s' called with invalid format specifier at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ break;
+ }
+ }
+
+ // not a format specifier
+ else
+ sout += sformat[i];
+ }
+
+ // Finally, print the message (only include a \n for $display, not for $write)
+ log("%s", sout.c_str());
+ if(str == "$display")
+ log("\n");
+ delete_children();
+ str = std::string();
+ }
+
// 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)
const_fold = true;
@@ -298,7 +398,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
did_something = true;
children[0]->detectSignWidth(backup_width_hint, backup_sign_hint);
children[1]->detectSignWidth(width_hint, sign_hint);
- width_hint = std::max(width_hint, backup_width_hint);
+ width_hint = max(width_hint, backup_width_hint);
child_0_is_self_determined = true;
break;
@@ -312,7 +412,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
did_something = true;
if (!children[1]->range_valid)
log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
- width_hint = std::max(width_hint, children[1]->range_left - children[1]->range_right + 1);
+ width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1);
}
break;
@@ -552,6 +652,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// dumpAst(NULL, "> ");
log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum);
}
+ if (children[1]->type == AST_PREFIX)
+ children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param);
log_assert(children[1]->type == AST_IDENTIFIER);
newNode = children[1]->clone();
const char *second_part = children[1]->str.c_str();
@@ -631,8 +733,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
for (auto range : children[1]->children) {
if (!range->range_valid)
log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
- multirange_dimensions.push_back(std::min(range->range_left, range->range_right));
- multirange_dimensions.push_back(std::max(range->range_left, range->range_right) - std::min(range->range_left, range->range_right) + 1);
+ 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();
}
delete children[1];
@@ -658,10 +760,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (i == 0)
index_expr = new_index_expr;
else
- index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i-1], true)), new_index_expr);
+ index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i+1], true)), new_index_expr);
}
- for (int i = GetSize(id2ast->multirange_dimensions)/1; i < GetSize(children[0]->children); i++)
+ for (int i = GetSize(id2ast->multirange_dimensions)/2; i < GetSize(children[0]->children); i++)
children.push_back(children[0]->children[i]->clone());
delete children[0];
@@ -911,7 +1013,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
std::vector<AstNode*> new_children;
for (size_t i = 0; i < children.size(); i++)
- if (children[i]->type == AST_WIRE) {
+ if (children[i]->type == AST_WIRE || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) {
children[i]->simplify(false, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(children[i]);
current_scope[children[i]->str] = children[i];
@@ -1067,7 +1169,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
log_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum);
newNode = new AstNode(AST_GENBLOCK);
- int num = std::max(children.at(0)->range_left, children.at(0)->range_right) - std::min(children.at(0)->range_left, children.at(0)->range_right) + 1;
+ 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;
for (int i = 0; i < num; i++) {
int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
@@ -1274,7 +1376,7 @@ skip_dynamic_range_lvalue_expansion:;
// found right-hand side identifier for memory -> replace with memory read port
if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
- children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
+ children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
newNode = new AstNode(AST_MEMRD, children[0]->children[0]->clone());
newNode->str = str;
newNode->id2ast = id2ast;
@@ -1569,7 +1671,17 @@ skip_dynamic_range_lvalue_expansion:;
if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
}
- if (type == AST_TCALL) {
+
+ if (type == AST_TCALL)
+ {
+ if (str == "$finish")
+ {
+ if (!current_always || current_always->type != AST_INITIAL)
+ log_error("System task `$finish' outside initial block is unsupported at %s:%d.\n", filename.c_str(), linenum);
+
+ log_error("System task `$finish' executed at %s:%d.\n", filename.c_str(), linenum);
+ }
+
if (str == "\\$readmemh" || str == "\\$readmemb")
{
if (GetSize(children) < 2 || GetSize(children) > 4)
@@ -1606,12 +1718,19 @@ skip_dynamic_range_lvalue_expansion:;
bool unconditional_init = false;
if (current_always->type == AST_INITIAL) {
+ pool<AstNode*> queue;
log_assert(current_always->children[0]->type == AST_BLOCK);
- for (auto n : current_always->children[0]->children)
- if (n == this) {
- unconditional_init = true;
- break;
+ queue.insert(current_always->children[0]);
+ while (!unconditional_init && !queue.empty()) {
+ pool<AstNode*> next_queue;
+ for (auto n : queue)
+ for (auto c : n->children) {
+ if (c == this)
+ unconditional_init = true;
+ next_queue.insert(c);
}
+ next_queue.swap(queue);
+ }
}
newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init);
@@ -1654,6 +1773,8 @@ skip_dynamic_range_lvalue_expansion:;
size_t arg_count = 0;
std::map<std::string, std::string> replace_rules;
+ vector<AstNode*> added_mod_children;
+ dict<std::string, AstNode*> wire_cache;
if (current_block == NULL)
{
@@ -1746,17 +1867,39 @@ skip_dynamic_range_lvalue_expansion:;
}
for (auto child : decl->children)
- if (child->type == AST_WIRE)
+ if (child->type == AST_WIRE || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
{
- AstNode *wire = child->clone();
- wire->str = prefix + wire->str;
- wire->port_id = 0;
- wire->is_input = false;
- wire->is_output = false;
- current_ast_mod->children.push_back(wire);
- while (wire->simplify(true, false, false, 1, -1, false, false)) { }
+ AstNode *wire = nullptr;
+
+ if (wire_cache.count(child->str))
+ {
+ wire = wire_cache.at(child->str);
+ if (wire->children.empty()) {
+ for (auto c : child->children)
+ wire->children.push_back(c->clone());
+ } else {
+ if (!child->children.empty())
+ log_error("Incompatible re-declaration of wire %s at %s:%d.\n", child->str.c_str(), filename.c_str(), linenum);
+ }
+ }
+ else
+ {
+ wire = child->clone();
+ wire->str = prefix + wire->str;
+ wire->port_id = 0;
+ wire->is_input = false;
+ wire->is_output = false;
+ wire_cache[child->str] = wire;
+
+ current_ast_mod->children.push_back(wire);
+ added_mod_children.push_back(wire);
+ }
+
+ if (child->type == AST_WIRE)
+ while (wire->simplify(true, false, false, 1, -1, false, false)) { }
replace_rules[child->str] = wire->str;
+ current_scope[wire->str] = wire;
if ((child->is_input || child->is_output) && arg_count < children.size())
{
@@ -1776,8 +1919,13 @@ skip_dynamic_range_lvalue_expansion:;
}
}
+ for (auto child : added_mod_children) {
+ child->replace_ids(prefix, replace_rules);
+ while (child->simplify(true, false, false, 1, -1, false, false)) { }
+ }
+
for (auto child : decl->children)
- if (child->type != AST_WIRE)
+ if (child->type != AST_WIRE && child->type != AST_PARAMETER && child->type != AST_LOCALPARAM)
{
AstNode *stmt = child->clone();
stmt->replace_ids(prefix, replace_rules);
@@ -1924,7 +2072,7 @@ skip_dynamic_range_lvalue_expansion:;
if (0) { case AST_GE: const_func = RTLIL::const_ge; }
if (0) { case AST_GT: const_func = RTLIL::const_gt; }
if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
- int cmp_width = std::max(children[0]->bits.size(), children[1]->bits.size());
+ int cmp_width = max(children[0]->bits.size(), children[1]->bits.size());
bool cmp_signed = children[0]->is_signed && children[1]->is_signed;
RTLIL::Const y = const_func(children[0]->bitsAsConst(cmp_width, cmp_signed),
children[1]->bitsAsConst(cmp_width, cmp_signed), cmp_signed, cmp_signed, 1);
@@ -2099,6 +2247,9 @@ static void replace_result_wire_name_in_function(AstNode *node, std::string &fro
// replace a readmem[bh] TCALL ast node with a block of memory assignments
AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init)
{
+ int mem_width, mem_size, addr_bits;
+ memory->meminfo(mem_width, mem_size, addr_bits);
+
AstNode *block = new AstNode(AST_BLOCK);
AstNode *meminit = nullptr;
@@ -2114,13 +2265,13 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
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;
- int range_min = std::min(range_left, range_right), range_max = std::max(range_left, range_right);
+ int range_min = min(range_left, range_right), range_max = max(range_left, range_right);
if (start_addr < 0)
start_addr = range_min;
if (finish_addr < 0)
- finish_addr = range_max;
+ finish_addr = range_max + 1;
bool in_comment = false;
int increment = start_addr <= finish_addr ? +1 : -1;
@@ -2160,7 +2311,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
continue;
}
- AstNode *value = VERILOG_FRONTEND::const2ast((is_readmemh ? "'h" : "'b") + token);
+ AstNode *value = VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token);
if (unconditional_init)
{
@@ -2196,12 +2347,12 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
block->children.back()->children[0]->id2ast = memory;
}
- if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
+ if ((cursor == finish_addr) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
break;
cursor += increment;
}
- if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
+ if ((cursor == finish_addr) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
break;
}
@@ -2598,7 +2749,7 @@ void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits)
if (mem_size < 0)
mem_size *= -1;
- mem_size += std::min(children[1]->range_left, children[1]->range_right) + 1;
+ mem_size += min(children[1]->range_left, children[1]->range_right) + 1;
addr_bits = 1;
while ((1 << addr_bits) < mem_size)
@@ -2634,8 +2785,8 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
if (!children.at(0)->range_valid)
log_error("Non-constant range in %s:%d (called from %s:%d).\n",
filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum);
- offset = std::min(children.at(0)->range_left, children.at(0)->range_right);
- width = std::min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
+ 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);
}
offset -= variables.at(str).offset;
std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
@@ -2675,7 +2826,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n",
child->str.c_str(), child->filename.c_str(), child->linenum, fcall->filename.c_str(), fcall->linenum);
variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
- variables[child->str].offset = std::min(child->range_left, child->range_right);
+ variables[child->str].offset = min(child->range_left, child->range_right);
variables[child->str].is_signed = child->is_signed;
if (child->is_input && argidx < fcall->children.size())
variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
@@ -2706,6 +2857,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (stmt->type == AST_ASSIGN_EQ)
{
+ if (stmt->children.at(0)->type == AST_IDENTIFIER && stmt->children.at(0)->children.size() != 0 &&
+ stmt->children.at(0)->children.at(0)->type == AST_RANGE)
+ stmt->children.at(0)->children.at(0)->replace_variables(variables, fcall);
stmt->children.at(1)->replace_variables(variables, fcall);
while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
@@ -2731,7 +2885,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (!range->range_valid)
log_error("Non-constant range in %s:%d (called from %s:%d).\n",
range->filename.c_str(), range->linenum, fcall->filename.c_str(), fcall->linenum);
- int offset = std::min(range->range_left, range->range_right);
+ 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];
RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());