diff options
Diffstat (limited to 'frontends/ast/genrtlil.cc')
-rw-r--r-- | frontends/ast/genrtlil.cc | 134 |
1 files changed, 76 insertions, 58 deletions
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index f87a68f67..8ed8c673a 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -73,7 +73,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed) { if (width <= sig.size()) { - sig.extend(width, is_signed); + sig.extend_u0(width, is_signed); return; } @@ -254,7 +254,7 @@ struct AST_INTERNAL::ProcessGenerator // create initial assignments for the temporary signals if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) { - subst_rvalue_map = subst_lvalue_from.to_sigbit_map(RTLIL::SigSpec(RTLIL::State::Sx, SIZE(subst_lvalue_from))); + subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from))); } else { addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from); } @@ -289,8 +289,8 @@ struct AST_INTERNAL::ProcessGenerator { RTLIL::SigSpec new_lhs, new_rhs; - log_assert(SIZE(lhs) == SIZE(rhs)); - for (int i = 0; i < SIZE(lhs); i++) { + log_assert(GetSize(lhs) == GetSize(rhs)); + for (int i = 0; i < GetSize(lhs); i++) { if (lhs[i].wire == nullptr) continue; new_lhs.append(lhs[i]); @@ -306,7 +306,7 @@ struct AST_INTERNAL::ProcessGenerator { std::vector<RTLIL::SigChunk> chunks = sig.chunks(); - for (int i = 0; i < SIZE(chunks); i++) + for (int i = 0; i < GetSize(chunks); i++) { RTLIL::SigChunk &chunk = chunks[i]; if (chunk.wire == NULL) @@ -430,7 +430,7 @@ struct AST_INTERNAL::ProcessGenerator lvalue.replace(subst_lvalue_map.stdmap()); if (ast->type == AST_ASSIGN_EQ) { - for (int i = 0; i < SIZE(unmapped_lvalue); i++) + for (int i = 0; i < GetSize(unmapped_lvalue); i++) subst_rvalue_map.set(unmapped_lvalue[i], rvalue[i]); } @@ -472,7 +472,7 @@ struct AST_INTERNAL::ProcessGenerator subst_lvalue_map.save(); subst_rvalue_map.save(); - for (int i = 0; i < SIZE(this_case_eq_lvalue); i++) + for (int i = 0; i < GetSize(this_case_eq_lvalue); i++) subst_lvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]); RTLIL::CaseRule *backup_case = current_case; @@ -507,7 +507,7 @@ struct AST_INTERNAL::ProcessGenerator sw->cases.push_back(default_case); } - for (int i = 0; i < SIZE(this_case_eq_lvalue); i++) + for (int i = 0; i < GetSize(this_case_eq_lvalue); i++) subst_rvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]); this_case_eq_lvalue.replace(subst_lvalue_map.stdmap()); @@ -567,9 +567,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) { this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1; } else - if (id_ast->children[0]->type == AST_CONSTANT) { + if (id_ast->children[0]->type != AST_CONSTANT) + while (id_ast->simplify(true, false, false, 1, -1, false, true)) { } + if (id_ast->children[0]->type == AST_CONSTANT) this_width = id_ast->children[0]->bits.size(); - } else + else log_error("Failed to detect width for parameter %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum); if (children.size() != 0) range = children[0]; @@ -839,14 +841,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); memory->name = str; memory->width = children[0]->range_left - children[0]->range_right + 1; - memory->start_offset = children[0]->range_right; - memory->size = children[1]->range_left - children[1]->range_right; + if (children[1]->range_right < children[1]->range_left) { + memory->start_offset = children[1]->range_right; + memory->size = children[1]->range_left - children[1]->range_right + 1; + } else { + memory->start_offset = children[1]->range_left; + memory->size = children[1]->range_right - children[1]->range_left + 1; + } current_module->memories[memory->name] = memory; - if (memory->size < 0) - memory->size *= -1; - memory->size += std::min(children[1]->range_left, children[1]->range_right) + 1; - for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) log_error("Attribute `%s' with non-constant value at %s:%d!\n", @@ -869,7 +872,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_REALVALUE: { RTLIL::SigSpec sig = realAsConst(width_hint); - log("Warning: converting real value %e to binary %s at %s:%d.\n", + log_warning("converting real value %e to binary %s at %s:%d.\n", realvalue, log_signal(sig), filename.c_str(), linenum); return sig; } @@ -890,7 +893,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); wire->name = str; if (flag_autowire) - log("Warning: Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum); else log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum); } @@ -941,7 +944,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed); fake_ast->children[1]->is_signed = true; } - if (SIZE(shift_val) >= 32) + if (GetSize(shift_val) >= 32) fake_ast->children[1]->is_signed = true; RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val); delete left_at_zero_ast; @@ -955,10 +958,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width); if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) { if (chunk.width == 1) - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n", str.c_str(), filename.c_str(), linenum); else - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n", str.c_str(), filename.c_str(), linenum, chunk.width); chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width); } else { @@ -972,10 +975,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset += add_undef_bits_lsb; } if (add_undef_bits_lsb) - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n", str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb); if (add_undef_bits_msb) - log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n", + log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n", str.c_str(), filename.c_str(), linenum, add_undef_bits_msb); } } @@ -1213,9 +1216,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width); wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); - int addr_bits = 1; - while ((1 << addr_bits) < current_module->memories[str]->size) - addr_bits++; + int mem_width, mem_size, addr_bits; + id2ast->meminfo(mem_width, mem_size, addr_bits); cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1)); cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits)); @@ -1234,28 +1236,30 @@ 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++; + int mem_width, mem_size, addr_bits; + id2ast->meminfo(mem_width, mem_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); } @@ -1263,19 +1267,22 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // generate $assert cells case AST_ASSERT: + case AST_ASSUME: { log_assert(children.size() == 2); RTLIL::SigSpec check = children[0]->genRTLIL(); - log_assert(check.size() == 1); + if (GetSize(check) != 1) + check = current_module->ReduceBool(NEW_ID, check); RTLIL::SigSpec en = children[1]->genRTLIL(); - log_assert(en.size() == 1); + if (GetSize(en) != 1) + en = current_module->ReduceBool(NEW_ID, en); std::stringstream sstr; - sstr << "$assert$" << filename << ":" << linenum << "$" << (autoidx++); + sstr << (type == AST_ASSERT ? "$assert$" : "$assume$") << filename << ":" << linenum << "$" << (autoidx++); - RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$assert"); + RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_ASSERT ? "$assert" : "$assume"); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); for (auto &attr : attributes) { @@ -1293,15 +1300,23 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // add entries to current_module->connections for assignments (outside of always blocks) case AST_ASSIGN: { - if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_AUTOWIRE) { - RTLIL::SigSpec right = children[1]->genRTLIL(); - RTLIL::SigSpec left = children[0]->genWidthRTLIL(right.size()); - current_module->connect(RTLIL::SigSig(left, right)); - } else { - RTLIL::SigSpec left = children[0]->genRTLIL(); - RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size()); - current_module->connect(RTLIL::SigSig(left, right)); + RTLIL::SigSpec left = children[0]->genRTLIL(); + RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size()); + if (left.has_const()) { + RTLIL::SigSpec new_left, new_right; + for (int i = 0; i < GetSize(left); i++) + if (left[i].wire) { + new_left.append(left[i]); + new_right.append(right[i]); + } + log_warning("Ignoring assignment to constant bits at %s:%d:\n" + " old assignment: %s = %s\n new assignment: %s = %s.\n", + filename.c_str(), linenum, log_signal(left), log_signal(right), + log_signal(new_left), log_signal(new_right)); + left = new_left; + right = new_right; } + current_module->connect(RTLIL::SigSig(left, right)); } break; @@ -1326,16 +1341,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) continue; } if (child->type == AST_PARASET) { - if (child->children[0]->type != AST_CONSTANT) - log_error("Parameter `%s' with non-constant value at %s:%d!\n", - child->str.c_str(), filename.c_str(), linenum); - if (child->str.size() == 0) { - char buf[100]; - snprintf(buf, 100, "$%d", ++para_counter); - cell->parameters[buf] = child->children[0]->asParaConst(); - } else { - cell->parameters[child->str] = child->children[0]->asParaConst(); + IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; + if (child->children[0]->type == AST_REALVALUE) { + log_warning("Replacing floating point parameter %s.%s = %f with string at %s:%d.\n", + log_id(cell), log_id(paraname), child->children[0]->realvalue, + filename.c_str(), linenum); + auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue)); + strnode->cloneInto(child->children[0]); + delete strnode; } + if (child->children[0]->type != AST_CONSTANT) + log_error("Parameter %s.%s with non-constant value at %s:%d!\n", + log_id(cell), log_id(paraname), filename.c_str(), linenum); + cell->parameters[paraname] = child->children[0]->asParaConst(); continue; } if (child->type == AST_ARGUMENT) { @@ -1391,9 +1409,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // this is a wrapper for AstNode::genRTLIL() when a specific signal width is requested and/or // signals must be substituted before beeing used as input values (used by ProcessGenerator) // note that this is using some global variables to communicate this special settings to AstNode::genRTLIL(). -RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const std::map<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr) +RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr) { - const std::map<RTLIL::SigBit, RTLIL::SigBit> *backup_subst_ptr = genRTLIL_subst_ptr; + const dict<RTLIL::SigBit, RTLIL::SigBit> *backup_subst_ptr = genRTLIL_subst_ptr; if (new_subst_ptr) genRTLIL_subst_ptr = new_subst_ptr; |