Creating $meminit cells in verilog front-end
authorClifford Wolf <clifford@clifford.at>
Sat, 14 Feb 2015 09:49:30 +0000 (10:49 +0100)
committerClifford Wolf <clifford@clifford.at>
Sat, 14 Feb 2015 09:49:30 +0000 (10:49 +0100)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc

index 68b3327f9b0408d35635827106a997f72aee487b..589b08e1dcd33b52d66df00a6b7e6b7ca5605fe9 100644 (file)
@@ -58,7 +58,7 @@ namespace AST_INTERNAL {
        std::map<std::string, AstNode*> current_scope;
        const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
        RTLIL::SigSpec ignoreThisSignalsInInitial;
-       AstNode *current_top_block, *current_block, *current_block_child;
+       AstNode *current_always, *current_top_block, *current_block, *current_block_child;
        AstModule *current_module;
 }
 
@@ -132,6 +132,7 @@ std::string AST::type2str(AstNodeType type)
        X(AST_TERNARY)
        X(AST_MEMRD)
        X(AST_MEMWR)
+       X(AST_MEMINIT)
        X(AST_TCALL)
        X(AST_ASSIGN)
        X(AST_CELL)
index 18064626715e6a795aa02aa33ef6d4e1359e1a52..3523d075448266c3153412297f02bf5cc6e55e84 100644 (file)
@@ -107,6 +107,7 @@ namespace AST
                AST_TERNARY,
                AST_MEMRD,
                AST_MEMWR,
+               AST_MEMINIT,
 
                AST_TCALL,
                AST_ASSIGN,
@@ -299,7 +300,7 @@ namespace AST_INTERNAL
        extern std::map<std::string, AST::AstNode*> current_scope;
        extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr;
        extern RTLIL::SigSpec ignoreThisSignalsInInitial;
-       extern AST::AstNode *current_top_block, *current_block, *current_block_child;
+       extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child;
        extern AST::AstModule *current_module;
        struct ProcessGenerator;
 }
index 71248663ede0e1087b3773ea8df896a4f2a9c6a4..7a78743b9ccaa77278f69bf497243875b8d1a81b 100644 (file)
@@ -1235,28 +1235,31 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 
        // generate $memwr cells for memory write ports
        case AST_MEMWR:
+       case AST_MEMINIT:
                {
                        std::stringstream sstr;
-                       sstr << "$memwr$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
+                       sstr << (type == AST_MEMWR ? "$memwr$" : "$meminit$") << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
 
-                       RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$memwr");
+                       RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? "$memwr" : "$meminit");
                        cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
 
                        int addr_bits = 1;
                        while ((1 << addr_bits) < current_module->memories[str]->size)
                                addr_bits++;
 
-                       cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
                        cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
                        cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width));
-                       cell->setPort("\\EN", children[2]->genRTLIL());
 
                        cell->parameters["\\MEMID"] = RTLIL::Const(str);
                        cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits);
                        cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width);
 
-                       cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
-                       cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
+                       if (type == AST_MEMWR) {
+                               cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
+                               cell->setPort("\\EN", children[2]->genRTLIL());
+                               cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
+                               cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
+                       }
 
                        cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1);
                }
index 27b278be9826c818ece6117ac57a5cc7ab0ebd24..6e56920116c842a915098db79209fa726b3453a0 100644 (file)
@@ -262,6 +262,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
        auto backup_current_block = current_block;
        auto backup_current_block_child = current_block_child;
        auto backup_current_top_block = current_top_block;
+       auto backup_current_always = current_always;
+
+       if (type == AST_ALWAYS || type == AST_INITIAL)
+               current_always = this;
 
        int backup_width_hint = width_hint;
        bool backup_sign_hint = sign_hint;
@@ -501,6 +505,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
        current_block = backup_current_block;
        current_block_child = backup_current_block_child;
        current_top_block = backup_current_top_block;
+       current_always = backup_current_always;
 
        for (auto it = backup_scope.begin(); it != backup_scope.end(); it++) {
                if (it->second == NULL)
@@ -1300,11 +1305,14 @@ skip_dynamic_range_lvalue_expansion:;
                current_scope[wire_data->str] = wire_data;
                while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
 
-               AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
-               wire_en->str = id_en;
-               current_ast_mod->children.push_back(wire_en);
-               current_scope[wire_en->str] = wire_en;
-               while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
+               AstNode *wire_en = nullptr;
+               if (current_always->type != AST_INITIAL) {
+                       wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
+                       wire_en->str = id_en;
+                       current_ast_mod->children.push_back(wire_en);
+                       current_scope[wire_en->str] = wire_en;
+                       while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
+               }
 
                std::vector<RTLIL::State> x_bits_addr, x_bits_data, set_bits_en;
                for (int i = 0; i < addr_bits; i++)
@@ -1320,13 +1328,17 @@ skip_dynamic_range_lvalue_expansion:;
                AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
                assign_data->children[0]->str = id_data;
 
-               AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
-               assign_en->children[0]->str = id_en;
+               AstNode *assign_en = nullptr;
+               if (current_always->type != AST_INITIAL) {
+                       assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
+                       assign_en->children[0]->str = id_en;
+               }
 
                AstNode *default_signals = new AstNode(AST_BLOCK);
                default_signals->children.push_back(assign_addr);
                default_signals->children.push_back(assign_data);
-               default_signals->children.push_back(assign_en);
+               if (current_always->type != AST_INITIAL)
+                       default_signals->children.push_back(assign_en);
                current_top_block->children.insert(current_top_block->children.begin(), default_signals);
 
                assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
@@ -1341,15 +1353,16 @@ skip_dynamic_range_lvalue_expansion:;
 
                                std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx);
 
-                               for (int i = 0; i < mem_width; i++)
-                                       set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
-
                                assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
                                                new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone()));
                                assign_data->children[0]->str = id_data;
 
-                               assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
-                               assign_en->children[0]->str = id_en;
+                               if (current_always->type != AST_INITIAL) {
+                                       for (int i = 0; i < mem_width; i++)
+                                               set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
+                                       assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
+                                       assign_en->children[0]->str = id_en;
+                               }
                        }
                        else
                        {
@@ -1364,16 +1377,17 @@ skip_dynamic_range_lvalue_expansion:;
                                        log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
                                int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
 
-                               for (int i = 0; i < mem_width; i++)
-                                       set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
-
                                assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
                                                new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));
                                assign_data->children[0]->str = id_data;
 
-                               assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
-                                               new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
-                               assign_en->children[0]->str = id_en;
+                               if (current_always->type != AST_INITIAL) {
+                                       for (int i = 0; i < mem_width; i++)
+                                               set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
+                                       assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
+                                                       new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
+                                       assign_en->children[0]->str = id_en;
+                               }
 
                                delete left_at_zero_ast;
                                delete right_at_zero_ast;
@@ -1385,23 +1399,28 @@ skip_dynamic_range_lvalue_expansion:;
                        assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
                        assign_data->children[0]->str = id_data;
 
-                       assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
-                       assign_en->children[0]->str = id_en;
+                       if (current_always->type != AST_INITIAL) {
+                               assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
+                               assign_en->children[0]->str = id_en;
+                       }
                }
 
                newNode = new AstNode(AST_BLOCK);
                newNode->children.push_back(assign_addr);
                newNode->children.push_back(assign_data);
-               newNode->children.push_back(assign_en);
+               if (current_always->type != AST_INITIAL)
+                       newNode->children.push_back(assign_en);
 
-               AstNode *wrnode = new AstNode(AST_MEMWR);
-               wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
+               AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR);
                wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
                wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
+               if (current_always->type != AST_INITIAL)
+                       wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
                wrnode->str = children[0]->str;
                wrnode->children[0]->str = id_addr;
                wrnode->children[1]->str = id_data;
-               wrnode->children[2]->str = id_en;
+               if (current_always->type != AST_INITIAL)
+                       wrnode->children[2]->str = id_en;
                current_ast_mod->children.push_back(wrnode);
 
                goto apply_newNode;