diff options
author | Udi Finkelstein <github@udifink.com> | 2018-03-09 10:35:33 +0200 |
---|---|---|
committer | Udi Finkelstein <github@udifink.com> | 2018-03-11 23:09:34 +0200 |
commit | 2b9c75f8e372f6886e073743d1df11bcd1c58281 (patch) | |
tree | 756704366060541ff047db59878e059971503ec6 /frontends/ast/simplify.cc | |
parent | efaef82f75d8e477baf958eac39f538e6eed5b03 (diff) | |
download | yosys-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.cc | 10 |
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: |