From a8e9d37c14427527c9a810d83e183309cc5ca503 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 14 Feb 2015 10:49:30 +0100 Subject: [PATCH] Creating $meminit cells in verilog front-end --- frontends/ast/ast.cc | 3 +- frontends/ast/ast.h | 3 +- frontends/ast/genrtlil.cc | 15 +++++---- frontends/ast/simplify.cc | 69 +++++++++++++++++++++++++-------------- 4 files changed, 57 insertions(+), 33 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 68b3327f9..589b08e1d 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -58,7 +58,7 @@ namespace AST_INTERNAL { std::map current_scope; const dict *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) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 180646267..3523d0754 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -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 current_scope; extern const dict *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; } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 71248663e..7a78743b9 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -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); } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 27b278be9..6e5692011 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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 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 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; -- 2.30.2