summaryrefslogtreecommitdiff
path: root/frontends
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2013-03-31 11:51:12 +0200
committerClifford Wolf <clifford@clifford.at>2013-03-31 11:51:12 +0200
commitf1a2fd966f62df072d2c43573fb71a1369857523 (patch)
treea86a810fe0b12f862b3d4b721f5a3e198bd8247b /frontends
parent161565be104fd0c7b7c4224bd23e9502625e041a (diff)
Now only use value from "initial" when no matching "always" block is found
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/ast.cc16
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/genrtlil.cc20
3 files changed, 31 insertions, 7 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 391e0a44..cb0311b6 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -51,6 +51,7 @@ namespace AST_INTERNAL {
std::map<std::string, AstNode*> current_scope;
RTLIL::SigSpec *genRTLIL_subst_from = NULL;
RTLIL::SigSpec *genRTLIL_subst_to = NULL;
+ RTLIL::SigSpec ignoreThisSignalsInInitial;
AstNode *current_top_block, *current_block, *current_block_child;
AstModule *current_module;
}
@@ -704,6 +705,9 @@ static AstModule* process_module(AstNode *ast)
current_module->ast = NULL;
current_module->name = ast->str;
current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum);
+
+ ignoreThisSignalsInInitial = RTLIL::SigSpec();
+
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
log_error("Attribute `%s' with non-constant value at %s:%d!\n",
@@ -718,10 +722,20 @@ static AstModule* process_module(AstNode *ast)
}
for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i];
- if (node->type != AST_WIRE && node->type != AST_MEMORY)
+ if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL)
node->genRTLIL();
}
+ ignoreThisSignalsInInitial.sort_and_unify();
+
+ for (size_t i = 0; i < ast->children.size(); i++) {
+ AstNode *node = ast->children[i];
+ if (node->type == AST_INITIAL)
+ node->genRTLIL();
+ }
+
+ ignoreThisSignalsInInitial = RTLIL::SigSpec();
+
current_module->ast = ast_before_simplify;
current_module->nolatches = flag_nolatches;
current_module->nomem2reg = flag_nomem2reg;
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 918f12c1..acf10f9a 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -221,7 +221,7 @@ namespace AST_INTERNAL
extern bool flag_dump_ast, flag_dump_ast_diff, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib;
extern AST::AstNode *current_ast, *current_ast_mod;
extern std::map<std::string, AST::AstNode*> current_scope;
- extern RTLIL::SigSpec *genRTLIL_subst_from, *genRTLIL_subst_to;
+ extern RTLIL::SigSpec *genRTLIL_subst_from, *genRTLIL_subst_to, ignoreThisSignalsInInitial;
extern AST::AstNode *current_top_block, *current_block, *current_block_child;
extern AST::AstModule *current_module;
struct ProcessGenerator;
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 2f5370fe..36074be3 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;
@@ -351,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();
@@ -361,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;
@@ -1014,10 +1018,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint)
break;
// use ProcessGenerator for always blocks
- case AST_ALWAYS:
- case AST_INITIAL: {
+ 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;