aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast/simplify.cc
diff options
context:
space:
mode:
authorUdi Finkelstein <github@udifink.com>2018-03-09 10:35:33 +0200
committerUdi Finkelstein <github@udifink.com>2018-03-11 23:09:34 +0200
commit2b9c75f8e372f6886e073743d1df11bcd1c58281 (patch)
tree756704366060541ff047db59878e059971503ec6 /frontends/ast/simplify.cc
parentefaef82f75d8e477baf958eac39f538e6eed5b03 (diff)
downloadyosys-2b9c75f8e372f6886e073743d1df11bcd1c58281.tar.gz
yosys-2b9c75f8e372f6886e073743d1df11bcd1c58281.tar.bz2
yosys-2b9c75f8e372f6886e073743d1df11bcd1c58281.zip
This PR should be the base for discussion, do not merge it yet!
It correctly detects reg/wire mix and incorrect use on blocking,nonblocking assignments within blocks and assign statements. What it DOES'T do: Detect registers connected to output ports of instances. Where it FAILS: memorty nonblocking assignments causes spurious (I assume??) errors on yosys-generated "_ADDR", "_DATA", "EN" signals. You can test it with tests/simple/reg_wire_error.v (look inside for the comments to enable/disable specific lines)
Diffstat (limited to 'frontends/ast/simplify.cc')
-rw-r--r--frontends/ast/simplify.cc10
1 files changed, 10 insertions, 0 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index a16fdfeeb..c9c5e5263 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -327,6 +327,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (node->type == AST_WIRE) {
if (this_wire_scope.count(node->str) > 0) {
AstNode *first_node = this_wire_scope[node->str];
+ if (first_node->is_input && node->is_reg)
+ goto wires_are_incompatible;
if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0)
goto wires_are_compatible;
if (first_node->children.size() == 0 && node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
@@ -361,6 +363,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
first_node->is_output = true;
if (node->is_reg)
first_node->is_reg = true;
+ if (node->is_logic)
+ first_node->is_logic = true;
if (node->is_signed)
first_node->is_signed = true;
for (auto &it : node->attributes) {
@@ -440,6 +444,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
children[1]->detectSignWidth(width_hint, sign_hint);
width_hint = max(width_hint, backup_width_hint);
child_0_is_self_determined = true;
+ 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);
+ if (type == AST_ASSIGN && children[0]->id2ast->is_reg)
+ log_error("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
break;
case AST_PARAMETER: