diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2019-10-18 19:56:51 +0000 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2019-10-18 19:56:51 +0000 |
commit | 1f6bb85359149a016811e7e7fef980c3d45211e7 (patch) | |
tree | 749672f9a104cbfb25bb02acad6cb731724b9d56 /frontends/ast | |
parent | ff5734b20220e6fb4a3913cf5279ed94bb5156ea (diff) |
New upstream version 0.9
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/ast.cc | 118 | ||||
-rw-r--r-- | frontends/ast/ast.h | 13 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 95 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 50 |
4 files changed, 257 insertions, 19 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index d4899616..3d066af5 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -46,7 +46,7 @@ namespace AST { // instantiate global variables (private API) namespace AST_INTERNAL { bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit; - bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; + bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map<std::string, AstNode*> current_scope; const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL; @@ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type) X(AST_GENIF) X(AST_GENCASE) X(AST_GENBLOCK) + X(AST_TECALL) X(AST_POSEDGE) X(AST_NEGEDGE) X(AST_EDGE) @@ -194,6 +195,9 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch is_logic = false; is_signed = false; is_string = false; + is_wand = false; + is_wor = false; + is_unsized = false; was_checked = false; range_valid = false; range_swapped = false; @@ -722,7 +726,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width) } // create an AST node for a constant (using a bit vector as value) -AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed) +AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized) { AstNode *node = new AstNode(AST_CONSTANT); node->is_signed = is_signed; @@ -736,9 +740,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe node->range_valid = true; node->range_left = node->bits.size()-1; node->range_right = 0; + node->is_unsized = is_unsized; return node; } +AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed) +{ + return mkconst_bits(v, is_signed, false); +} + // create an AST node for a constant (using a string in bit vector form as value) AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v) { @@ -775,6 +785,14 @@ bool AstNode::bits_only_01() const return true; } +RTLIL::Const AstNode::bitsAsUnsizedConst(int width) +{ + RTLIL::State extbit = bits.back(); + while (width > int(bits.size())) + bits.push_back(extbit); + return RTLIL::Const(bits); +} + RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed) { std::vector<RTLIL::State> bits = this->bits; @@ -942,6 +960,23 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast if (!defer) { + bool blackbox_module = flag_lib; + + if (!blackbox_module && !flag_noblackbox) { + blackbox_module = true; + for (auto child : ast->children) { + if (child->type == AST_WIRE && (child->is_input || child->is_output)) + continue; + if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) + continue; + if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE && + (child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) + continue; + blackbox_module = false; + break; + } + } + while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { } if (flag_dump_ast2) { @@ -956,7 +991,63 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast log("--- END OF AST DUMP ---\n"); } - if (flag_lib) { + if (flag_nowb && ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); + } + + if (ast->attributes.count("\\lib_whitebox")) { + if (!flag_lib || flag_nowb) { + delete ast->attributes.at("\\lib_whitebox"); + ast->attributes.erase("\\lib_whitebox"); + } else { + if (ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); + } + AstNode *n = ast->attributes.at("\\lib_whitebox"); + ast->attributes["\\whitebox"] = n; + ast->attributes.erase("\\lib_whitebox"); + } + } + + if (!blackbox_module && ast->attributes.count("\\blackbox")) { + AstNode *n = ast->attributes.at("\\blackbox"); + if (n->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Got blackbox attribute with non-constant value!\n"); + blackbox_module = n->asBool(); + } + + if (blackbox_module && ast->attributes.count("\\whitebox")) { + AstNode *n = ast->attributes.at("\\whitebox"); + if (n->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Got whitebox attribute with non-constant value!\n"); + blackbox_module = !n->asBool(); + } + + if (ast->attributes.count("\\noblackbox")) { + if (blackbox_module) { + AstNode *n = ast->attributes.at("\\noblackbox"); + if (n->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Got noblackbox attribute with non-constant value!\n"); + blackbox_module = !n->asBool(); + } + delete ast->attributes.at("\\noblackbox"); + ast->attributes.erase("\\noblackbox"); + } + + if (blackbox_module) + { + if (ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); + } + + if (ast->attributes.count("\\lib_whitebox")) { + delete ast->attributes.at("\\lib_whitebox"); + ast->attributes.erase("\\lib_whitebox"); + } + std::vector<AstNode*> new_children; for (auto child : ast->children) { if (child->type == AST_WIRE && (child->is_input || child->is_output)) { @@ -965,12 +1056,19 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast child->delete_children(); child->children.push_back(AstNode::mkconst_int(0, false, 0)); new_children.push_back(child); + } else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE && + (child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) { + new_children.push_back(child); } else { delete child; } } + ast->children.swap(new_children); - ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); + + if (ast->attributes.count("\\blackbox") == 0) { + ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); + } } ignoreThisSignalsInInitial = RTLIL::SigSpec(); @@ -1009,9 +1107,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast current_module->nomeminit = flag_nomeminit; current_module->nomem2reg = flag_nomem2reg; current_module->mem2reg = flag_mem2reg; + current_module->noblackbox = flag_noblackbox; current_module->lib = flag_lib; + current_module->nowb = flag_nowb; current_module->noopt = flag_noopt; current_module->icells = flag_icells; + current_module->pwires = flag_pwires; current_module->autowire = flag_autowire; current_module->fixup_ports(); @@ -1026,7 +1127,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast // create AstModule instances for all modules in the AST tree and add them to 'design' void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, - bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire) + bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire) { current_ast = ast; flag_dump_ast1 = dump_ast1; @@ -1039,9 +1140,12 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump flag_nomeminit = nomeminit; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; + flag_noblackbox = noblackbox; flag_lib = lib; + flag_nowb = nowb; flag_noopt = noopt; flag_icells = icells; + flag_pwires = pwires; flag_autowire = autowire; log_assert(current_ast->type == AST_DESIGN); @@ -1373,9 +1477,12 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString flag_nomeminit = nomeminit; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; + flag_noblackbox = noblackbox; flag_lib = lib; + flag_nowb = nowb; flag_noopt = noopt; flag_icells = icells; + flag_pwires = pwires; flag_autowire = autowire; use_internal_line_num(); @@ -1447,6 +1554,7 @@ RTLIL::Module *AstModule::clone() const new_mod->lib = lib; new_mod->noopt = noopt; new_mod->icells = icells; + new_mod->pwires = pwires; new_mod->autowire = autowire; return new_mod; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index ddd59d4b..54b2fb31 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -137,7 +137,8 @@ namespace AST AST_GENIF, AST_GENCASE, AST_GENBLOCK, - + AST_TECALL, + AST_POSEDGE, AST_NEGEDGE, AST_EDGE, @@ -173,7 +174,7 @@ namespace AST // node content - most of it is unused in most node types std::string str; std::vector<RTLIL::State> bits; - bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked; + bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized; int port_id, range_left, range_right; uint32_t integer; double realvalue; @@ -262,6 +263,7 @@ namespace AST // helper functions for creating AST nodes for constants static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32); + static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized); static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed); static AstNode *mkconst_str(const std::vector<RTLIL::State> &v); static AstNode *mkconst_str(const std::string &str); @@ -269,6 +271,7 @@ namespace AST // helper function for creating sign-extended const objects RTLIL::Const bitsAsConst(int width, bool is_signed); RTLIL::Const bitsAsConst(int width = -1); + RTLIL::Const bitsAsUnsizedConst(int width); RTLIL::Const asAttrConst(); RTLIL::Const asParaConst(); uint64_t asInt(bool is_signed); @@ -283,13 +286,13 @@ namespace AST // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit, - bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire); + bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire); // parametric modules are supported directly by the AST library // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions struct AstModule : RTLIL::Module { AstNode *ast; - bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; + bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE; @@ -322,7 +325,7 @@ namespace AST_INTERNAL { // internal state variables extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit; - extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; + extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_pwires, flag_autowire; extern AST::AstNode *current_ast, *current_ast_mod; extern std::map<std::string, AST::AstNode*> current_scope; extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index b3a2a84b..571ddd98 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -504,6 +504,7 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::CaseRule *backup_case = current_case; current_case = new RTLIL::CaseRule; + current_case->attributes["\\src"] = stringf("%s:%d", child->filename.c_str(), child->linenum); last_generated_case = current_case; addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); for (auto node : child->children) { @@ -645,6 +646,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (!id_ast->children[0]->range_valid) log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str()); this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1; + if (children.size() > 1) + range = children[1]; } else log_file_error(filename, linenum, "Failed to detect width for identifier %s!\n", str.c_str()); if (range) { @@ -851,7 +854,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_FUNCTION: case AST_DPI_FUNCTION: case AST_AUTOWIRE: - case AST_LOCALPARAM: case AST_DEFPARAM: case AST_GENVAR: case AST_GENFOR: @@ -893,6 +895,26 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // remember the parameter, needed for example in techmap case AST_PARAMETER: current_module->avail_parameters.insert(str); + /* fall through */ + case AST_LOCALPARAM: + if (flag_pwires) + { + if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT) + log_file_error(filename, linenum, "Parameter `%s' with non-constant value!\n", str.c_str()); + + RTLIL::Const val = children[0]->bitsAsConst(); + RTLIL::Wire *wire = current_module->addWire(str, GetSize(val)); + current_module->connect(wire, val); + + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1; + + for (auto &attr : attributes) { + if (attr.second->type != AST_CONSTANT) + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + wire->attributes[attr.first] = attr.second->asAttrConst(); + } + } break; // create an RTLIL::Wire for an AST_WIRE node @@ -902,7 +924,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (!range_valid) log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str()); - log_assert(range_left >= range_right || (range_left == -1 && range_right == 0)); + if (!(range_left >= range_right || (range_left == -1 && range_right == 0))) + log_file_error(filename, linenum, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1); RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1); wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -917,6 +940,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } + + if (is_wand) wire->set_bool_attribute("\\wand"); + if (is_wor) wire->set_bool_attribute("\\wor"); } break; @@ -961,8 +987,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) detectSignWidth(width_hint, sign_hint); is_signed = sign_hint; - if (type == AST_CONSTANT) - return RTLIL::SigSpec(bitsAsConst()); + if (type == AST_CONSTANT) { + if (is_unsized) { + return RTLIL::SigSpec(bitsAsUnsizedConst(width_hint)); + } else { + return RTLIL::SigSpec(bitsAsConst()); + } + } RTLIL::SigSpec sig = realAsConst(width_hint); log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); @@ -1490,10 +1521,12 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) continue; } if (child->type == AST_PARASET) { + int extra_const_flags = 0; IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; if (child->children[0]->type == AST_REALVALUE) { log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n", log_id(cell), log_id(paraname), child->children[0]->realvalue); + extra_const_flags = RTLIL::CONST_FLAG_REAL; auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue)); strnode->cloneInto(child->children[0]); delete strnode; @@ -1502,6 +1535,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n", log_id(cell), log_id(paraname)); cell->parameters[paraname] = child->children[0]->asParaConst(); + cell->parameters[paraname].flags |= extra_const_flags; continue; } if (child->type == AST_ARGUMENT) { @@ -1521,9 +1555,29 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value.\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } + if (cell->type.in("$specify2", "$specify3")) { + int src_width = GetSize(cell->getPort("\\SRC")); + int dst_width = GetSize(cell->getPort("\\DST")); + bool full = cell->getParam("\\FULL").as_bool(); + if (!full && src_width != dst_width) + log_file_error(filename, linenum, "Parallel specify SRC width does not match DST width.\n"); + if (cell->type == "$specify3") { + int dat_width = GetSize(cell->getPort("\\DAT")); + if (dat_width != dst_width) + log_file_error(filename, linenum, "Specify DAT width does not match DST width.\n"); + } + cell->setParam("\\SRC_WIDTH", Const(src_width)); + cell->setParam("\\DST_WIDTH", Const(dst_width)); + } + if (cell->type == "$specrule") { + int src_width = GetSize(cell->getPort("\\SRC")); + int dst_width = GetSize(cell->getPort("\\DST")); + cell->setParam("\\SRC_WIDTH", Const(src_width)); + cell->setParam("\\DST_WIDTH", Const(dst_width)); + } } break; @@ -1541,6 +1595,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) delete always; } break; + case AST_TECALL: { + int sz = children.size(); + if (str == "$info") { + if (sz > 0) + log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_info(filename, linenum, "\n"); + } else if (str == "$warning") { + if (sz > 0) + log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_warning(filename, linenum, "\n"); + } else if (str == "$error") { + if (sz > 0) + log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "\n"); + } else if (str == "$fatal") { + // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() + // if no parameter is given, default value is 1 + // dollar_finish(sz ? children[0] : 1); + // perhaps create & use log_file_fatal() + if (sz > 0) + log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "FATAL.\n"); + } else { + log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); + } + } break; + case AST_FCALL: { if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 63b71b80..e947125b 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1030,7 +1030,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n"); if (type == AST_REPEAT) - log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n"); + { + AstNode *count = children[0]; + AstNode *body = children[1]; + + // eval count expression + while (count->simplify(true, false, false, stage, 32, true, false)) { } + + if (count->type != AST_CONSTANT) + log_file_error(filename, linenum, "Repeat loops outside must have constant repeat counts!\n"); + + // convert to a block with the body repeated n times + type = AST_BLOCK; + children.clear(); + for (int i = 0; i < count->bitsAsConst().as_int(); i++) + children.insert(children.begin(), body->clone()); + + delete count; + delete body; + did_something = true; + } // unroll for loops and generate-for blocks if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0) @@ -1066,7 +1085,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // eval 1st expression AstNode *varbuf = init_ast->children[1]->clone(); - while (varbuf->simplify(true, false, false, stage, 32, true, false)) { } + { + int expr_width_hint = -1; + bool expr_sign_hint = true; + varbuf->detectSignWidth(expr_width_hint, expr_sign_hint); + while (varbuf->simplify(true, false, false, stage, 32, true, false)) { } + } if (varbuf->type != AST_CONSTANT) log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n"); @@ -1088,7 +1112,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { // eval 2nd expression AstNode *buf = while_ast->clone(); - while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + { + int expr_width_hint = -1; + bool expr_sign_hint = true; + buf->detectSignWidth(expr_width_hint, expr_sign_hint); + while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { } + } if (buf->type != AST_CONSTANT) log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n"); @@ -1129,7 +1158,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // eval 3rd expression buf = next_ast->children[1]->clone(); - while (buf->simplify(true, false, false, stage, 32, true, false)) { } + { + int expr_width_hint = -1; + bool expr_sign_hint = true; + buf->detectSignWidth(expr_width_hint, expr_sign_hint); + while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { } + } if (buf->type != AST_CONSTANT) log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n"); @@ -1138,6 +1172,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, varbuf->children[0] = buf; } + if (type == AST_FOR) { + AstNode *buf = next_ast->clone(); + delete buf->children[1]; + buf->children[1] = varbuf->children[0]->clone(); + current_block->children.insert(current_block->children.begin() + current_block_idx++, buf); + } + current_scope[varbuf->str] = backup_scope_varbuf; delete varbuf; delete_children(); @@ -1564,6 +1605,7 @@ skip_dynamic_range_lvalue_expansion:; current_scope[wire_tmp->str] = wire_tmp; wire_tmp->attributes["\\nosync"] = AstNode::mkconst_int(1, false); while (wire_tmp->simplify(true, false, false, 1, -1, false, false)) { } + wire_tmp->is_logic = true; AstNode *wire_tmp_id = new AstNode(AST_IDENTIFIER); wire_tmp_id->str = wire_tmp->str; |