diff options
Diffstat (limited to 'frontends/ast/simplify.cc')
-rw-r--r-- | frontends/ast/simplify.cc | 180 |
1 files changed, 100 insertions, 80 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 26c1cc7a9..b87af0f8c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -172,7 +172,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, deep_recursion_warning = true; while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { } - if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg")) + if (!flag_nomem2reg && !get_bool_attribute(ID::nomem2reg)) { dict<AstNode*, pool<std::string>> mem2reg_places; dict<AstNode*, uint32_t> mem2reg_candidates, dummy_proc_flags; @@ -187,10 +187,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, bool this_nomeminit = flag_nomeminit; log_assert((memflags & ~0x00ffff00) == 0); - if (mem->get_bool_attribute("\\nomem2reg")) + if (mem->get_bool_attribute(ID::nomem2reg)) continue; - if (mem->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit")) + if (mem->get_bool_attribute(ID::nomeminit) || get_bool_attribute(ID::nomeminit)) this_nomeminit = true; if (memflags & AstNode::MEM2REG_FL_FORCED) @@ -248,7 +248,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, reg->is_reg = true; reg->is_signed = node->is_signed; for (auto &it : node->attributes) - if (it.first != ID(mem2reg)) + if (it.first != ID::mem2reg) reg->attributes.emplace(it.first, it.second->clone()); reg->filename = node->filename; reg->location = node->location; @@ -345,9 +345,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { for (auto c : node->children[0]->children) { if (!c->is_simple_const_expr()) { - if (attributes.count("\\dynports")) - delete attributes.at("\\dynports"); - attributes["\\dynports"] = AstNode::mkconst_int(1, true); + if (attributes.count(ID::dynports)) + delete attributes.at(ID::dynports); + attributes[ID::dynports] = AstNode::mkconst_int(1, true); } } } @@ -432,7 +432,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM)) did_something = true; if (node->type == AST_ENUM) { - for (auto enode : node->children){ + for (auto enode YS_ATTRIBUTE(unused) : node->children){ log_assert(enode->type==AST_ENUM_ITEM); while (node->simplify(true, false, false, 1, -1, false, in_param)) did_something = true; @@ -1219,7 +1219,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true))); wire->str = wire_id; if (current_block) - wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); current_ast_mod->children.push_back(wire); while (wire->simplify(true, false, false, 1, -1, false, false)) { } @@ -1812,6 +1812,7 @@ skip_dynamic_range_lvalue_expansion:; newNode->children.push_back(assign_en); AstNode *assertnode = new AstNode(type); + assertnode->location = location; assertnode->str = str; assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); @@ -1856,7 +1857,7 @@ skip_dynamic_range_lvalue_expansion:; wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); current_ast_mod->children.push_back(wire_tmp); current_scope[wire_tmp->str] = wire_tmp; - wire_tmp->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_tmp->attributes[ID::nosync] = AstNode::mkconst_int(1, false); while (wire_tmp->simplify(true, false, false, 1, -1, false, false)) { } wire_tmp->is_logic = true; @@ -1898,6 +1899,9 @@ skip_dynamic_range_lvalue_expansion:; bool mem_signed = children[0]->id2ast->is_signed; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); + newNode = new AstNode(AST_BLOCK); + AstNode *defNode = new AstNode(AST_BLOCK); + int data_range_left = children[0]->id2ast->children[0]->range_left; int data_range_right = children[0]->id2ast->children[0]->range_right; int mem_data_range_offset = std::min(data_range_left, data_range_right); @@ -1907,31 +1911,6 @@ skip_dynamic_range_lvalue_expansion:; children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint); addr_bits = std::max(addr_bits, addr_width_hint); - AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); - wire_addr->str = id_addr; - wire_addr->was_checked = true; - current_ast_mod->children.push_back(wire_addr); - current_scope[wire_addr->str] = wire_addr; - while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } - - AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); - wire_data->str = id_data; - wire_data->was_checked = true; - wire_data->is_signed = mem_signed; - current_ast_mod->children.push_back(wire_data); - current_scope[wire_data->str] = wire_data; - while (wire_data->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; - wire_en->was_checked = true; - 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++) x_bits_addr.push_back(RTLIL::State::Sx); @@ -1940,32 +1919,79 @@ skip_dynamic_range_lvalue_expansion:; for (int i = 0; i < mem_width; i++) set_bits_en.push_back(RTLIL::State::S1); - AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); - assign_addr->children[0]->str = id_addr; - assign_addr->children[0]->was_checked = true; + AstNode *node_addr = nullptr; + if (children[0]->children[0]->children[0]->isConst()) { + node_addr = children[0]->children[0]->children[0]->clone(); + } else { + AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); + wire_addr->str = id_addr; + wire_addr->was_checked = true; + current_ast_mod->children.push_back(wire_addr); + current_scope[wire_addr->str] = wire_addr; + while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } - 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; - assign_data->children[0]->was_checked = true; + AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); + assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; + defNode->children.push_back(assign_addr); - 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_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); + assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; + newNode->children.push_back(assign_addr); + + node_addr = new AstNode(AST_IDENTIFIER); + node_addr->str = id_addr; + } + + AstNode *node_data = nullptr; + if (children[0]->children.size() == 1 && children[1]->isConst()) { + node_data = children[1]->clone(); + } else { + AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); + wire_data->str = id_data; + wire_data->was_checked = true; + wire_data->is_signed = mem_signed; + current_ast_mod->children.push_back(wire_data); + current_scope[wire_data->str] = wire_data; + while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } + + 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; + assign_data->children[0]->was_checked = true; + defNode->children.push_back(assign_data); + + node_data = new AstNode(AST_IDENTIFIER); + node_data->str = id_data; + } + + AstNode *node_en = nullptr; + if (current_always->type == AST_INITIAL) { + node_en = AstNode::mkconst_int(1, false); + } else { + 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; + wire_en->was_checked = true; + 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 *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width)); assign_en->children[0]->str = id_en; assign_en->children[0]->was_checked = true; - } + defNode->children.push_back(assign_en); - AstNode *default_signals = new AstNode(AST_BLOCK); - default_signals->children.push_back(assign_addr); - default_signals->children.push_back(assign_data); - 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); + node_en = new AstNode(AST_IDENTIFIER); + node_en->str = id_en; + } - assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); - assign_addr->children[0]->str = id_addr; - assign_addr->children[0]->was_checked = true; + if (!defNode->children.empty()) + current_top_block->children.insert(current_top_block->children.begin(), defNode); + else + delete defNode; + AstNode *assign_data = nullptr; + AstNode *assign_en = nullptr; if (children[0]->children.size() == 2) { if (children[0]->children[1]->range_valid) @@ -2026,9 +2052,11 @@ skip_dynamic_range_lvalue_expansion:; } else { - assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone()); - assign_data->children[0]->str = id_data; - assign_data->children[0]->was_checked = true; + if (!(children[0]->children.size() == 1 && children[1]->isConst())) { + assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone()); + assign_data->children[0]->str = id_data; + assign_data->children[0]->was_checked = true; + } if (current_always->type != AST_INITIAL) { assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); @@ -2036,28 +2064,20 @@ skip_dynamic_range_lvalue_expansion:; assign_en->children[0]->was_checked = true; } } - - newNode = new AstNode(AST_BLOCK); - newNode->children.push_back(assign_addr); - newNode->children.push_back(assign_data); - if (current_always->type != AST_INITIAL) + if (assign_data) + newNode->children.push_back(assign_data); + if (assign_en) newNode->children.push_back(assign_en); - 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)); - else - wrnode->children.push_back(AstNode::mkconst_int(1, false)); + AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR, node_addr, node_data, node_en); wrnode->str = children[0]->str; wrnode->id2ast = children[0]->id2ast; - wrnode->children[0]->str = id_addr; - wrnode->children[1]->str = id_data; - if (current_always->type != AST_INITIAL) - wrnode->children[2]->str = id_en; current_ast_mod->children.push_back(wrnode); + if (newNode->children.empty()) { + delete newNode; + newNode = new AstNode(); + } goto apply_newNode; } @@ -2657,7 +2677,7 @@ skip_dynamic_range_lvalue_expansion:; wire->is_input = false; wire->is_output = false; wire->is_reg = true; - wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); if (child->type == AST_ENUM_ITEM) wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"]; @@ -3345,10 +3365,10 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg } // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg' - if (type == AST_MEMORY && (get_bool_attribute("\\mem2reg") || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg)) + if (type == AST_MEMORY && (get_bool_attribute(ID::mem2reg) || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg)) mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED; - if (type == AST_MODULE && get_bool_attribute("\\mem2reg")) + if (type == AST_MODULE && get_bool_attribute(ID::mem2reg)) children_flags |= AstNode::MEM2REG_FL_ALL; dict<AstNode*, uint32_t> *proc_flags_p = NULL; @@ -3511,7 +3531,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, wire_addr->str = id_addr; wire_addr->is_reg = true; wire_addr->was_checked = true; - wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_addr); while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } @@ -3520,7 +3540,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, wire_data->is_reg = true; wire_data->was_checked = true; wire_data->is_signed = mem_signed; - wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_data); while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } @@ -3591,7 +3611,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, wire_addr->is_reg = true; wire_addr->was_checked = true; if (block) - wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_addr); while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } @@ -3601,7 +3621,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, wire_data->was_checked = true; wire_data->is_signed = mem_signed; if (block) - wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_data); while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } |