diff options
author | Clifford Wolf <clifford@clifford.at> | 2014-09-06 17:58:27 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2014-09-06 17:58:27 +0200 |
commit | deff416ea7d60b490b0e4f8d70abdb1ad8d4d0f3 (patch) | |
tree | 747548292b58883d881a444eb9ce7efe3a453fe7 /frontends/ast | |
parent | b847ec8a0bfb3b729278f1132ae2819676498ee7 (diff) | |
download | yosys-deff416ea7d60b490b0e4f8d70abdb1ad8d4d0f3.tar.gz yosys-deff416ea7d60b490b0e4f8d70abdb1ad8d4d0f3.tar.bz2 yosys-deff416ea7d60b490b0e4f8d70abdb1ad8d4d0f3.zip |
Fixed assignment of out-of bounds array element
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/genrtlil.cc | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 0c7be1f54..f87a68f67 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -276,6 +276,7 @@ struct AST_INTERNAL::ProcessGenerator for (auto &init_lvalue_c : init_lvalue.chunks()) { RTLIL::SigSpec lhs = init_lvalue_c; RTLIL::SigSpec rhs = init_rvalue.extract(offset, init_lvalue_c.width); + remove_unwanted_lvalue_bits(lhs, rhs); sync->actions.push_back(RTLIL::SigSig(lhs, rhs)); offset += lhs.size(); } @@ -284,6 +285,22 @@ struct AST_INTERNAL::ProcessGenerator outputSignals = RTLIL::SigSpec(subst_lvalue_from); } + void remove_unwanted_lvalue_bits(RTLIL::SigSpec &lhs, RTLIL::SigSpec &rhs) + { + RTLIL::SigSpec new_lhs, new_rhs; + + log_assert(SIZE(lhs) == SIZE(rhs)); + for (int i = 0; i < SIZE(lhs); i++) { + if (lhs[i].wire == nullptr) + continue; + new_lhs.append(lhs[i]); + new_rhs.append(rhs[i]); + } + + lhs = new_lhs; + rhs = new_rhs; + } + // create new temporary signals RTLIL::SigSpec new_temp_signal(RTLIL::SigSpec sig) { @@ -349,8 +366,13 @@ struct AST_INTERNAL::ProcessGenerator log_abort(); } - if (run_sort_and_unify) - reg.sort_and_unify(); + if (run_sort_and_unify) { + std::set<RTLIL::SigBit> sorted_reg; + for (auto bit : reg) + if (bit.wire) + sorted_reg.insert(bit); + reg = RTLIL::SigSpec(sorted_reg); + } } // remove all assignments to the given signal pattern in a case and all its children. @@ -384,6 +406,7 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue_c.width); if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute("\\nosync")) rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.size()); + remove_unwanted_lvalue_bits(lhs, rhs); actions.push_back(RTLIL::SigSig(lhs, rhs)); offset += lhs.size(); } @@ -412,6 +435,7 @@ struct AST_INTERNAL::ProcessGenerator } removeSignalFromCaseTree(lvalue.to_sigbit_set(), current_case); + remove_unwanted_lvalue_bits(lvalue, rvalue); current_case->actions.push_back(RTLIL::SigSig(lvalue, rvalue)); } break; |