summaryrefslogtreecommitdiff
path: root/frontends
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-09-06 17:58:27 +0200
committerClifford Wolf <clifford@clifford.at>2014-09-06 17:58:27 +0200
commitdeff416ea7d60b490b0e4f8d70abdb1ad8d4d0f3 (patch)
tree747548292b58883d881a444eb9ce7efe3a453fe7 /frontends
parentb847ec8a0bfb3b729278f1132ae2819676498ee7 (diff)
Fixed assignment of out-of bounds array element
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/genrtlil.cc28
1 files changed, 26 insertions, 2 deletions
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 0c7be1f5..f87a68f6 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;