aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast/genrtlil.cc
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/ast/genrtlil.cc')
-rw-r--r--frontends/ast/genrtlil.cc27
1 files changed, 20 insertions, 7 deletions
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 0654db2df..cb57bbab7 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -183,7 +183,9 @@ struct AST_INTERNAL::ProcessGenerator
{
// input and output structures
AstNode *always;
+ RTLIL::SigSpec skipSyncSignals;
RTLIL::Process *proc;
+ const RTLIL::SigSpec &outputSignals;
// This always points to the RTLIL::CaseRule beeing filled at the moment
RTLIL::CaseRule *current_case;
@@ -205,7 +207,7 @@ struct AST_INTERNAL::ProcessGenerator
// map helps generating nice numbered names for all this temporary signals.
std::map<RTLIL::Wire*, int> new_temp_count;
- ProcessGenerator(AstNode *always) : always(always)
+ ProcessGenerator(AstNode *always, RTLIL::SigSpec skipSyncSignalsArg = RTLIL::SigSpec()) : always(always), skipSyncSignals(skipSyncSignalsArg), outputSignals(subst_lvalue_from)
{
// generate process and simple root case
proc = new RTLIL::Process;
@@ -310,6 +312,7 @@ struct AST_INTERNAL::ProcessGenerator
case AST_COND:
case AST_ALWAYS:
+ case AST_INITIAL:
for (auto child : ast->children)
if (child->type == AST_BLOCK)
collect_lvalues(reg, child, type_eq, type_le, false);
@@ -334,9 +337,9 @@ struct AST_INTERNAL::ProcessGenerator
reg.sort_and_unify();
}
- // remove all assignments to the given signal pattern in a case and all its children
- // when the last statement in the code "a = 23; if (b) a = 42; a = 0;" is processed this
- // function is acalled to clean up the first two assignments as they are overwritten by
+ // remove all assignments to the given signal pattern in a case and all its children.
+ // e.g. when the last statement in the code "a = 23; if (b) a = 42; a = 0;" is processed this
+ // function is called to clean up the first two assignments as they are overwritten by
// the third assignment.
void removeSignalFromCaseTree(RTLIL::SigSpec pattern, RTLIL::CaseRule *cs)
{
@@ -350,8 +353,10 @@ struct AST_INTERNAL::ProcessGenerator
// add an assignment (aka "action") but split it up in chunks. this way huge assignments
// are avoided and the generated $mux cells have a more "natural" size.
- void addChunkActions(std::vector<RTLIL::SigSig> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool noSyncToUndef = false)
+ void addChunkActions(std::vector<RTLIL::SigSig> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool inSyncRule = false)
{
+ if (inSyncRule)
+ lvalue.remove2(skipSyncSignals, &rvalue);
assert(lvalue.width == rvalue.width);
lvalue.optimize();
rvalue.optimize();
@@ -360,7 +365,7 @@ struct AST_INTERNAL::ProcessGenerator
for (size_t i = 0; i < lvalue.chunks.size(); i++) {
RTLIL::SigSpec lhs = lvalue.chunks[i];
RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue.chunks[i].width);
- if (noSyncToUndef && lvalue.chunks[i].wire && lvalue.chunks[i].wire->attributes.count("\\nosync"))
+ if (inSyncRule && lvalue.chunks[i].wire && lvalue.chunks[i].wire->attributes.count("\\nosync"))
rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.width);
actions.push_back(RTLIL::SigSig(lhs, rhs));
offset += lhs.width;
@@ -456,7 +461,7 @@ struct AST_INTERNAL::ProcessGenerator
} else if (node->type == AST_BLOCK) {
processAst(node);
} else if (!generated_default_case)
- current_case->compare.push_back(node->genWidthRTLIL(sw->signal.width));
+ current_case->compare.push_back(node->genWidthRTLIL(sw->signal.width, &subst_rvalue_from, &subst_rvalue_to));
}
sw->cases.push_back(current_case);
current_case = backup_case;
@@ -528,6 +533,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint)
case AST_LOCALPARAM:
case AST_GENVAR:
case AST_GENFOR:
+ case AST_GENBLOCK:
case AST_GENIF:
break;
@@ -1015,6 +1021,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint)
case AST_ALWAYS: {
AstNode *always = this->clone();
ProcessGenerator generator(always);
+ ignoreThisSignalsInInitial.append(generator.outputSignals);
+ delete always;
+ } break;
+
+ case AST_INITIAL: {
+ AstNode *always = this->clone();
+ ProcessGenerator generator(always, ignoreThisSignalsInInitial);
delete always;
} break;