Now only use value from "initial" when no matching "always" block is found
authorClifford Wolf <clifford@clifford.at>
Sun, 31 Mar 2013 09:51:12 +0000 (11:51 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 31 Mar 2013 09:51:12 +0000 (11:51 +0200)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
tests/k68_vltor/changes.diff
tests/k68_vltor/run.sh

index 391e0a4442cf64a699bf7064e16891e604d3ebec..cb0311b6be8fbced64bcbc909428cf2a908bc71c 100644 (file)
@@ -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;
index 918f12c1ad6a28501b000e309c6df73e38d8a6f0..acf10f9ad91443ac91863b336729c87a4a8c742c 100644 (file)
@@ -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;
index 2f5370fe8d3bd5c982723dd20bee50489413fb56..36074be34830a334b1f451956a7e129c2175ec4a 100644 (file)
@@ -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;
 
index 80d5da9d6877e9d2b0bc0136cd5bb340ed8f8513..7b9034032e06cc69c6c5c7af43fe99169b5aed62 100644 (file)
@@ -10,16 +10,3 @@ index 47a50c4..de27fbb 100755
      }
  
      cout<<"Final sum = "<<hex<<top->sum<<"\n";
-diff --git a/rtl/k68_clkgen.v b/rtl/k68_clkgen.v
-index c201a97..55b9cad 100755
---- a/rtl/k68_clkgen.v
-+++ b/rtl/k68_clkgen.v
-@@ -57,7 +57,7 @@ module k68_clkgen (/*AUTOARG*/
-    assign    clk4_o = cnt[1];
-    assign    clk_o = ~clk_i;
-    
--   initial cnt = 0;   // Power up state doesn't matter, but can't be X
-+   // initial cnt = 0;        // Power up state doesn't matter, but can't be X
-    always @(posedge clk_i) begin
-       cnt <= cnt + 1'b1;
index de831d38f649d42a706a0ab8d58059922ed14644..97ccf238916b3624e89c932bdf06078400a49c7d 100644 (file)
@@ -7,7 +7,7 @@ if (
 
        cd rtl
        mkdir -p ../synth
-       yosys -o ../synth/k68_soc.v -p 'hierarchy -check -top k68_soc; proc; opt; memory; opt' \
+       ../../../../yosys -o ../synth/k68_soc.v -p 'hierarchy -check -top k68_soc; proc; opt; memory; opt' \
                        k68_soc.v k68_arb.v k68_cpu.v k68_load.v k68_clkgen.v k68_decode.v k68_execute.v \
                        k68_fetch.v k68_regbank.v k68_buni.v k68_b2d.v k68_ccc.v k68_d2b.v k68_rox.v \
                        k68_calc.v k68_dpmem.v k68_sasc.v sasc_brg.v sasc_top.v sasc_fifo4.v