diff options
Diffstat (limited to 'frontends/ast/genrtlil.cc')
-rw-r--r-- | frontends/ast/genrtlil.cc | 27 |
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; |