diff options
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/ast/ast.cc | 4 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 46 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 224 | ||||
-rw-r--r-- | frontends/blif/blifparse.cc | 2 | ||||
-rw-r--r-- | frontends/ilang/ilang_parser.y | 24 | ||||
-rw-r--r-- | frontends/verific/Makefile.inc | 5 | ||||
-rw-r--r-- | frontends/verific/verific.cc | 49 | ||||
-rw-r--r-- | frontends/verilog/const2ast.cc | 78 | ||||
-rw-r--r-- | frontends/verilog/preproc.cc | 3 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.cc | 23 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 4 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 8 |
12 files changed, 342 insertions, 128 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index a45859157..3e163bae7 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -699,7 +699,7 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe for (size_t i = 0; i < 32; i++) { if (i < node->bits.size()) node->integer |= (node->bits[i] == RTLIL::S1) << i; - else if (is_signed) + else if (is_signed && !node->bits.empty()) node->integer |= (node->bits.back() == RTLIL::S1) << i; } node->range_valid = true; @@ -831,7 +831,7 @@ double AstNode::asReal(bool is_signed) { RTLIL::Const val(bits); - bool is_negative = is_signed && val.bits.back() == RTLIL::State::S1; + bool is_negative = is_signed && !val.bits.empty() && val.bits.back() == RTLIL::State::S1; if (is_negative) val = const_neg(val, val, false, false, val.bits.size()); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index a2655e9a5..87e8379e9 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -520,6 +520,11 @@ struct AST_INTERNAL::ProcessGenerator log_error("Found wire declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum); break; + case AST_PARAMETER: + case AST_LOCALPARAM: + log_error("Found parameter declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum); + break; + case AST_TCALL: case AST_FOR: break; @@ -547,14 +552,14 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun switch (type) { case AST_CONSTANT: - width_hint = std::max(width_hint, int(bits.size())); + width_hint = max(width_hint, int(bits.size())); if (!is_signed) sign_hint = false; break; case AST_REALVALUE: *found_real = true; - width_hint = std::max(width_hint, 32); + width_hint = max(width_hint, 32); break; case AST_IDENTIFIER: @@ -617,7 +622,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun this_width = range->range_left - range->range_right + 1; sign_hint = false; } - width_hint = std::max(width_hint, this_width); + width_hint = max(width_hint, this_width); if (!id_ast->is_signed) sign_hint = false; break; @@ -627,7 +632,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (children[0]->type != AST_CONSTANT) log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum); children[1]->detectSignWidthWorker(sub_width_hint, sign_hint); - width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int()); + width_hint = max(width_hint, children[0]->bitsAsConst().as_int()); break; case AST_TO_SIGNED: @@ -646,7 +651,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun child->detectSignWidthWorker(sub_width_hint, sub_sign_hint); this_width += sub_width_hint; } - width_hint = std::max(width_hint, this_width); + width_hint = max(width_hint, this_width); sign_hint = false; break; @@ -655,7 +660,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (children[0]->type != AST_CONSTANT) log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum); children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint); - width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint); + width_hint = max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint); sign_hint = false; break; @@ -678,7 +683,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_REDUCE_XOR: case AST_REDUCE_XNOR: case AST_REDUCE_BOOL: - width_hint = std::max(width_hint, 1); + width_hint = max(width_hint, 1); sign_hint = false; break; @@ -698,7 +703,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_NEX: case AST_GE: case AST_GT: - width_hint = std::max(width_hint, 1); + width_hint = max(width_hint, 1); sign_hint = false; break; @@ -714,7 +719,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_LOGIC_AND: case AST_LOGIC_OR: case AST_LOGIC_NOT: - width_hint = std::max(width_hint, 1); + width_hint = max(width_hint, 1); sign_hint = false; break; @@ -729,7 +734,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (!id2ast->children[0]->range_valid) log_error("Failed to detect with of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum); this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1; - width_hint = std::max(width_hint, this_width); + width_hint = max(width_hint, this_width); break; // everything should have been handled above -> print error if not. @@ -1054,7 +1059,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) detectSignWidth(width_hint, sign_hint); RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint); RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint); - int width = std::max(left.size(), right.size()); + int width = max(left.size(), right.size()); if (width_hint > 0) width = width_hint; is_signed = children[0]->is_signed && children[1]->is_signed; @@ -1068,7 +1073,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (0) { case AST_REDUCE_XNOR: type_name = "$reduce_xnor"; } { RTLIL::SigSpec arg = children[0]->genRTLIL(); - RTLIL::SigSpec sig = uniop2rtlil(this, type_name, std::max(width_hint, 1), arg); + RTLIL::SigSpec sig = uniop2rtlil(this, type_name, max(width_hint, 1), arg); return sig; } @@ -1077,7 +1082,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (0) { case AST_REDUCE_BOOL: type_name = "$reduce_bool"; } { RTLIL::SigSpec arg = children[0]->genRTLIL(); - RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, std::max(width_hint, 1), arg) : arg; + RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, max(width_hint, 1), arg) : arg; return sig; } @@ -1123,7 +1128,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (0) { case AST_GE: type_name = "$ge"; } if (0) { case AST_GT: type_name = "$gt"; } { - int width = std::max(width_hint, 1); + int width = max(width_hint, 1); width_hint = -1, sign_hint = true; children[0]->detectSignWidthWorker(width_hint, sign_hint); children[1]->detectSignWidthWorker(width_hint, sign_hint); @@ -1145,7 +1150,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint); RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint); #if 0 - int width = std::max(left.size(), right.size()); + int width = max(left.size(), right.size()); if (width > width_hint && width_hint > 0) width = width_hint; if (width < width_hint) { @@ -1154,10 +1159,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed)) width = width_hint; if (type == AST_MUL) - width = std::min(left.size() + right.size(), width_hint); + width = min(left.size() + right.size(), width_hint); } #else - int width = std::max(std::max(left.size(), right.size()), width_hint); + int width = max(max(left.size(), right.size()), width_hint); #endif is_signed = children[0]->is_signed && children[1]->is_signed; return binop2rtlil(this, type_name, width, left, right); @@ -1169,14 +1174,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) { RTLIL::SigSpec left = children[0]->genRTLIL(); RTLIL::SigSpec right = children[1]->genRTLIL(); - return binop2rtlil(this, type_name, std::max(width_hint, 1), left, right); + return binop2rtlil(this, type_name, max(width_hint, 1), left, right); } // generate cells for unary operations: $logic_not case AST_LOGIC_NOT: { RTLIL::SigSpec arg = children[0]->genRTLIL(); - return uniop2rtlil(this, "$logic_not", std::max(width_hint, 1), arg); + return uniop2rtlil(this, "$logic_not", max(width_hint, 1), arg); } // generate multiplexer for ternary operator (aka ?:-operator) @@ -1192,7 +1197,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (cond.size() > 1) cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false); - int width = std::max(val1.size(), val2.size()); + int width = max(val1.size(), val2.size()); is_signed = children[1]->is_signed && children[2]->is_signed; widthExtend(this, val1, width, is_signed); widthExtend(this, val2, width, is_signed); @@ -1220,6 +1225,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) id2ast->meminfo(mem_width, mem_size, addr_bits); cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1)); + cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1)); cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits)); cell->setPort("\\DATA", RTLIL::SigSpec(wire)); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 5eb173c9a..2264d896a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -174,13 +174,113 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // deactivate all calls to non-synthesis system tasks - if ((type == AST_FCALL || type == AST_TCALL) && (str == "$display" || str == "$strobe" || str == "$monitor" || str == "$time" || str == "$stop" || str == "$finish" || + // note that $display and $finish are used for synthesis-time DRC so they're not in this list + if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" || str == "$stop" || str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) { log_warning("Ignoring call to system %s %s at %s:%d.\n", type == AST_FCALL ? "function" : "task", str.c_str(), filename.c_str(), linenum); delete_children(); str = std::string(); } + if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) { + log_warning("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + delete_children(); + str = std::string(); + } + + // print messages if this a call to $display() or $write() + // This code implements only a small subset of Verilog-2005 $display() format specifiers, + // but should be good enough for most uses + if ((type == AST_TCALL) && ((str == "$display") || (str == "$write"))) + { + size_t nargs = GetSize(children); + if(nargs < 1) + log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n", + str.c_str(), int(children.size()), filename.c_str(), linenum); + + // First argument is the format string + AstNode *node_string = children[0]->clone(); + while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + if (node_string->type != AST_CONSTANT) + log_error("Failed to evaluate system task `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + std::string sformat = node_string->bitsAsConst().decode_string(); + + // Other arguments are placeholders. Process the string as we go through it + std::string sout; + size_t next_arg = 1; + for(size_t i=0; i<sformat.length(); i++) + { + // format specifier + if(sformat[i] == '%') + { + // If there's no next character, that's a problem + if(i+1 >= sformat.length()) + log_error("System task `%s' called with `%%' at end of string at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + + char cformat = sformat[++i]; + + // %% is special, does not need a matching argument + if(cformat == '%') + { + sout += '%'; + continue; + } + + // If we're out of arguments, that's a problem! + if(next_arg >= nargs) + log_error("System task `%s' called with more format specifiers than arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + + // Simplify the argument + AstNode *node_arg = children[next_arg ++]->clone(); + while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + if (node_arg->type != AST_CONSTANT) + log_error("Failed to evaluate system task `%s' with non-constant argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + + // Everything from here on depends on the format specifier + switch(cformat) + { + case 's': + case 'S': + sout += node_arg->bitsAsConst().decode_string(); + break; + + case 'd': + case 'D': + { + char tmp[128]; + snprintf(tmp, sizeof(tmp), "%d", node_arg->bitsAsConst().as_int()); + sout += tmp; + } + break; + + case 'x': + case 'X': + { + char tmp[128]; + snprintf(tmp, sizeof(tmp), "%x", node_arg->bitsAsConst().as_int()); + sout += tmp; + } + break; + + default: + log_error("System task `%s' called with invalid format specifier at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + break; + } + } + + // not a format specifier + else + sout += sformat[i]; + } + + // Finally, print the message (only include a \n for $display, not for $write) + log("%s", sout.c_str()); + if(str == "$display") + log("\n"); + delete_children(); + str = std::string(); + } + // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.) if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) const_fold = true; @@ -298,7 +398,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, did_something = true; children[0]->detectSignWidth(backup_width_hint, backup_sign_hint); children[1]->detectSignWidth(width_hint, sign_hint); - width_hint = std::max(width_hint, backup_width_hint); + width_hint = max(width_hint, backup_width_hint); child_0_is_self_determined = true; break; @@ -312,7 +412,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, did_something = true; if (!children[1]->range_valid) log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum); - width_hint = std::max(width_hint, children[1]->range_left - children[1]->range_right + 1); + width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1); } break; @@ -552,6 +652,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // dumpAst(NULL, "> "); log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum); } + if (children[1]->type == AST_PREFIX) + children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param); log_assert(children[1]->type == AST_IDENTIFIER); newNode = children[1]->clone(); const char *second_part = children[1]->str.c_str(); @@ -631,8 +733,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, for (auto range : children[1]->children) { if (!range->range_valid) log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum); - multirange_dimensions.push_back(std::min(range->range_left, range->range_right)); - multirange_dimensions.push_back(std::max(range->range_left, range->range_right) - std::min(range->range_left, range->range_right) + 1); + multirange_dimensions.push_back(min(range->range_left, range->range_right)); + multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1); total_size *= multirange_dimensions.back(); } delete children[1]; @@ -658,10 +760,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (i == 0) index_expr = new_index_expr; else - index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i-1], true)), new_index_expr); + index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i+1], true)), new_index_expr); } - for (int i = GetSize(id2ast->multirange_dimensions)/1; i < GetSize(children[0]->children); i++) + for (int i = GetSize(id2ast->multirange_dimensions)/2; i < GetSize(children[0]->children); i++) children.push_back(children[0]->children[i]->clone()); delete children[0]; @@ -911,7 +1013,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, std::vector<AstNode*> new_children; for (size_t i = 0; i < children.size(); i++) - if (children[i]->type == AST_WIRE) { + if (children[i]->type == AST_WIRE || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) { children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(children[i]); current_scope[children[i]->str] = children[i]; @@ -1067,7 +1169,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum); newNode = new AstNode(AST_GENBLOCK); - int num = std::max(children.at(0)->range_left, children.at(0)->range_right) - std::min(children.at(0)->range_left, children.at(0)->range_right) + 1; + int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1; for (int i = 0; i < num; i++) { int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i; @@ -1274,7 +1376,7 @@ skip_dynamic_range_lvalue_expansion:; // found right-hand side identifier for memory -> replace with memory read port if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue && - children[0]->type == AST_RANGE && children[0]->children.size() == 1) { + children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) { newNode = new AstNode(AST_MEMRD, children[0]->children[0]->clone()); newNode->str = str; newNode->id2ast = id2ast; @@ -1569,7 +1671,17 @@ skip_dynamic_range_lvalue_expansion:; if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION) log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum); } - if (type == AST_TCALL) { + + if (type == AST_TCALL) + { + if (str == "$finish") + { + if (!current_always || current_always->type != AST_INITIAL) + log_error("System task `$finish' outside initial block is unsupported at %s:%d.\n", filename.c_str(), linenum); + + log_error("System task `$finish' executed at %s:%d.\n", filename.c_str(), linenum); + } + if (str == "\\$readmemh" || str == "\\$readmemb") { if (GetSize(children) < 2 || GetSize(children) > 4) @@ -1606,12 +1718,19 @@ skip_dynamic_range_lvalue_expansion:; bool unconditional_init = false; if (current_always->type == AST_INITIAL) { + pool<AstNode*> queue; log_assert(current_always->children[0]->type == AST_BLOCK); - for (auto n : current_always->children[0]->children) - if (n == this) { - unconditional_init = true; - break; + queue.insert(current_always->children[0]); + while (!unconditional_init && !queue.empty()) { + pool<AstNode*> next_queue; + for (auto n : queue) + for (auto c : n->children) { + if (c == this) + unconditional_init = true; + next_queue.insert(c); } + next_queue.swap(queue); + } } newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init); @@ -1654,6 +1773,8 @@ skip_dynamic_range_lvalue_expansion:; size_t arg_count = 0; std::map<std::string, std::string> replace_rules; + vector<AstNode*> added_mod_children; + dict<std::string, AstNode*> wire_cache; if (current_block == NULL) { @@ -1746,17 +1867,39 @@ skip_dynamic_range_lvalue_expansion:; } for (auto child : decl->children) - if (child->type == AST_WIRE) + if (child->type == AST_WIRE || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) { - AstNode *wire = child->clone(); - wire->str = prefix + wire->str; - wire->port_id = 0; - wire->is_input = false; - wire->is_output = false; - current_ast_mod->children.push_back(wire); - while (wire->simplify(true, false, false, 1, -1, false, false)) { } + AstNode *wire = nullptr; + + if (wire_cache.count(child->str)) + { + wire = wire_cache.at(child->str); + if (wire->children.empty()) { + for (auto c : child->children) + wire->children.push_back(c->clone()); + } else { + if (!child->children.empty()) + log_error("Incompatible re-declaration of wire %s at %s:%d.\n", child->str.c_str(), filename.c_str(), linenum); + } + } + else + { + wire = child->clone(); + wire->str = prefix + wire->str; + wire->port_id = 0; + wire->is_input = false; + wire->is_output = false; + wire_cache[child->str] = wire; + + current_ast_mod->children.push_back(wire); + added_mod_children.push_back(wire); + } + + if (child->type == AST_WIRE) + while (wire->simplify(true, false, false, 1, -1, false, false)) { } replace_rules[child->str] = wire->str; + current_scope[wire->str] = wire; if ((child->is_input || child->is_output) && arg_count < children.size()) { @@ -1776,8 +1919,13 @@ skip_dynamic_range_lvalue_expansion:; } } + for (auto child : added_mod_children) { + child->replace_ids(prefix, replace_rules); + while (child->simplify(true, false, false, 1, -1, false, false)) { } + } + for (auto child : decl->children) - if (child->type != AST_WIRE) + if (child->type != AST_WIRE && child->type != AST_PARAMETER && child->type != AST_LOCALPARAM) { AstNode *stmt = child->clone(); stmt->replace_ids(prefix, replace_rules); @@ -1924,7 +2072,7 @@ skip_dynamic_range_lvalue_expansion:; if (0) { case AST_GE: const_func = RTLIL::const_ge; } if (0) { case AST_GT: const_func = RTLIL::const_gt; } if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) { - int cmp_width = std::max(children[0]->bits.size(), children[1]->bits.size()); + int cmp_width = max(children[0]->bits.size(), children[1]->bits.size()); bool cmp_signed = children[0]->is_signed && children[1]->is_signed; RTLIL::Const y = const_func(children[0]->bitsAsConst(cmp_width, cmp_signed), children[1]->bitsAsConst(cmp_width, cmp_signed), cmp_signed, cmp_signed, 1); @@ -2099,6 +2247,9 @@ static void replace_result_wire_name_in_function(AstNode *node, std::string &fro // replace a readmem[bh] TCALL ast node with a block of memory assignments AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init) { + int mem_width, mem_size, addr_bits; + memory->meminfo(mem_width, mem_size, addr_bits); + AstNode *block = new AstNode(AST_BLOCK); AstNode *meminit = nullptr; @@ -2114,13 +2265,13 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid); int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right; - int range_min = std::min(range_left, range_right), range_max = std::max(range_left, range_right); + int range_min = min(range_left, range_right), range_max = max(range_left, range_right); if (start_addr < 0) start_addr = range_min; if (finish_addr < 0) - finish_addr = range_max; + finish_addr = range_max + 1; bool in_comment = false; int increment = start_addr <= finish_addr ? +1 : -1; @@ -2160,7 +2311,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m continue; } - AstNode *value = VERILOG_FRONTEND::const2ast((is_readmemh ? "'h" : "'b") + token); + AstNode *value = VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token); if (unconditional_init) { @@ -2196,12 +2347,12 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m block->children.back()->children[0]->id2ast = memory; } - if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min)) + if ((cursor == finish_addr) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min)) break; cursor += increment; } - if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min)) + if ((cursor == finish_addr) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min)) break; } @@ -2598,7 +2749,7 @@ void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits) if (mem_size < 0) mem_size *= -1; - mem_size += std::min(children[1]->range_left, children[1]->range_right) + 1; + mem_size += min(children[1]->range_left, children[1]->range_right) + 1; addr_bits = 1; while ((1 << addr_bits) < mem_size) @@ -2634,8 +2785,8 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia if (!children.at(0)->range_valid) log_error("Non-constant range in %s:%d (called from %s:%d).\n", filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum); - offset = std::min(children.at(0)->range_left, children.at(0)->range_right); - width = std::min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); + offset = min(children.at(0)->range_left, children.at(0)->range_right); + width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); } offset -= variables.at(str).offset; std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits; @@ -2675,7 +2826,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n", child->str.c_str(), child->filename.c_str(), child->linenum, fcall->filename.c_str(), fcall->linenum); variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1); - variables[child->str].offset = std::min(child->range_left, child->range_right); + variables[child->str].offset = min(child->range_left, child->range_right); variables[child->str].is_signed = child->is_signed; if (child->is_input && argidx < fcall->children.size()) variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size()); @@ -2706,6 +2857,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (stmt->type == AST_ASSIGN_EQ) { + if (stmt->children.at(0)->type == AST_IDENTIFIER && stmt->children.at(0)->children.size() != 0 && + stmt->children.at(0)->children.at(0)->type == AST_RANGE) + stmt->children.at(0)->children.at(0)->replace_variables(variables, fcall); stmt->children.at(1)->replace_variables(variables, fcall); while (stmt->simplify(true, false, false, 1, -1, false, true)) { } @@ -2731,7 +2885,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (!range->range_valid) log_error("Non-constant range in %s:%d (called from %s:%d).\n", range->filename.c_str(), range->linenum, fcall->filename.c_str(), fcall->linenum); - int offset = std::min(range->range_left, range->range_right); + int offset = min(range->range_left, range->range_right); int width = std::abs(range->range_left - range->range_right) + 1; varinfo_t &v = variables[stmt->children.at(0)->str]; RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size()); diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 4bf050741..9f2e08df0 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -133,7 +133,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name) if (v[0] == '"') { std::string str(v+1); if (str.back() == '"') - str.pop_back(); + str.resize(str.size()-1); const_v = Const(str); } else { int n = strlen(v); diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 6090fabe5..cc31c8642 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -50,6 +50,7 @@ USING_YOSYS_NAMESPACE int integer; YOSYS_NAMESPACE_PREFIX RTLIL::Const *data; YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec *sigspec; + std::vector<YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec> *rsigspec; } %token <string> TOK_ID TOK_VALUE TOK_STRING @@ -60,6 +61,7 @@ USING_YOSYS_NAMESPACE %token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET %token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_UPTO +%type <rsigspec> sigspec_list_reversed %type <sigspec> sigspec sigspec_list %type <integer> sync_type %type <data> constant @@ -121,7 +123,7 @@ attr_stmt: autoidx_stmt: TOK_AUTOIDX TOK_INT EOL { - autoidx = std::max(autoidx, $2); + autoidx = max(autoidx, $2); }; wire_stmt: @@ -274,8 +276,8 @@ compare_list: /* empty */; case_body: - switch_stmt case_body | - assign_stmt case_body | + case_body switch_stmt | + case_body assign_stmt | /* empty */; assign_stmt: @@ -389,16 +391,20 @@ sigspec: $$ = $2; }; -sigspec_list: - sigspec_list sigspec { - $$ = new RTLIL::SigSpec; - $$->append(*$2); - $$->append(*$1); - delete $1; +sigspec_list_reversed: + sigspec_list_reversed sigspec { + $$->push_back(*$2); delete $2; } | /* empty */ { + $$ = new std::vector<RTLIL::SigSpec>; + }; + +sigspec_list: sigspec_list_reversed { $$ = new RTLIL::SigSpec; + for (auto it = $1->rbegin(); it != $1->rend(); it++) + $$->append(*it); + delete $1; }; conn_stmt: diff --git a/frontends/verific/Makefile.inc b/frontends/verific/Makefile.inc index 13f242c4b..68ef9aed1 100644 --- a/frontends/verific/Makefile.inc +++ b/frontends/verific/Makefile.inc @@ -8,8 +8,9 @@ EXTRA_TARGETS += share/verific share/verific: $(P) rm -rf share/verific.new $(Q) mkdir -p share/verific.new - $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs share/verific.new/vhdl_vdbs_1993 - $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_2008 share/verific.new/vhdl_vdbs_2008 + $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1987/. share/verific.new/vhdl_vdbs_1987 + $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1993/. share/verific.new/vhdl_vdbs_1993 + $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_2008/. share/verific.new/vhdl_vdbs_2008 $(Q) mv share/verific.new share/verific endif diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 897a7f328..45cd4f3fc 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -314,6 +314,16 @@ static bool import_netlist_instance_cells(RTLIL::Module *module, std::map<Net*, return true; } + if (inst->Type() == PRIM_DLATCHRS) + { + if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd()) + module->addDlatch(RTLIL::escape_id(inst->Name()), net_map.at(inst->GetControl()), net_map.at(inst->GetInput()), net_map.at(inst->GetOutput())); + else + module->addDlatchsr(RTLIL::escape_id(inst->Name()), net_map.at(inst->GetControl()), net_map.at(inst->GetSet()), net_map.at(inst->GetReset()), + net_map.at(inst->GetInput()), net_map.at(inst->GetOutput())); + return true; + } + #define IN operatorInput(inst, net_map) #define IN1 operatorInput1(inst, net_map) #define IN2 operatorInput2(inst, net_map) @@ -541,7 +551,7 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist* // log(" importing portbus %s.\n", portbus->Name()); RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(portbus->Name()), portbus->Size()); - wire->start_offset = std::min(portbus->LeftIndex(), portbus->RightIndex()); + wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex()); import_attributes(wire->attributes, portbus); if (portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN) @@ -580,11 +590,11 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist* int bits_in_word = number_of_bits; FOREACH_PORTREF_OF_NET(net, si, pr) { if (pr->GetInst()->Type() == OPER_READ_PORT) { - bits_in_word = std::min<int>(bits_in_word, pr->GetInst()->OutputSize()); + bits_in_word = min<int>(bits_in_word, pr->GetInst()->OutputSize()); continue; } if (pr->GetInst()->Type() == OPER_WRITE_PORT || pr->GetInst()->Type() == OPER_CLOCKED_WRITE_PORT) { - bits_in_word = std::min<int>(bits_in_word, pr->GetInst()->Input2Size()); + bits_in_word = min<int>(bits_in_word, pr->GetInst()->Input2Size()); continue; } log_error("Verific RamNet %s is connected to unsupported instance type %s (%s).\n", @@ -630,7 +640,7 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist* RTLIL::IdString wire_name = module->uniquify(RTLIL::escape_id(netbus->Name())); RTLIL::Wire *wire = module->addWire(wire_name, netbus->Size()); - wire->start_offset = std::min(netbus->LeftIndex(), netbus->RightIndex()); + wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex()); import_attributes(wire->attributes, netbus); for (int i = netbus->LeftIndex();; i += netbus->IsUp() ? +1 : -1) { @@ -692,7 +702,8 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist* cell->parameters["\\TRANSPARENT"] = false; cell->parameters["\\ABITS"] = GetSize(addr); cell->parameters["\\WIDTH"] = GetSize(data); - cell->setPort("\\CLK", RTLIL::State::S0); + cell->setPort("\\CLK", RTLIL::State::Sx); + cell->setPort("\\EN", RTLIL::State::Sx); cell->setPort("\\ADDR", addr); cell->setPort("\\DATA", data); continue; @@ -744,6 +755,8 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist* RTLIL::Cell *cell = module->addCell(RTLIL::escape_id(inst->Name()), inst->IsOperator() ? std::string("$verific$") + inst->View()->Owner()->Name() : RTLIL::escape_id(inst->View()->Owner()->Name())); + dict<IdString, vector<SigBit>> cell_port_conns; + FOREACH_PORTREF_OF_INST(inst, mi2, pr) { // log(" .%s(%s)\n", pr->GetPort()->Name(), pr->GetNet()->Name()); const char *port_name = pr->GetPort()->Name(); @@ -751,18 +764,18 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist* if (pr->GetPort()->Bus()) { port_name = pr->GetPort()->Bus()->Name(); port_offset = pr->GetPort()->Bus()->IndexOf(pr->GetPort()) - - std::min(pr->GetPort()->Bus()->LeftIndex(), pr->GetPort()->Bus()->RightIndex()); - } - RTLIL::SigSpec conn; - if (cell->hasPort(RTLIL::escape_id(port_name))) - conn = cell->getPort(RTLIL::escape_id(port_name)); - while (GetSize(conn) <= port_offset) { - if (pr->GetPort()->GetDir() != DIR_IN) - conn.append(module->addWire(NEW_ID, port_offset - GetSize(conn))); - conn.append(RTLIL::State::Sz); + min(pr->GetPort()->Bus()->LeftIndex(), pr->GetPort()->Bus()->RightIndex()); } - conn.replace(port_offset, net_map.at(pr->GetNet())); - cell->setPort(RTLIL::escape_id(port_name), conn); + IdString port_name_id = RTLIL::escape_id(port_name); + auto &sigvec = cell_port_conns[port_name_id]; + if (GetSize(sigvec) <= port_offset) + sigvec.resize(port_offset+1, State::Sz); + sigvec[port_offset] = net_map.at(pr->GetNet()); + } + + for (auto &it : cell_port_conns) { + // log(" .%s(%s)\n", log_id(it.first), log_signal(it.second)); + cell->setPort(it.first, it.second); } } } @@ -840,7 +853,7 @@ struct VerificPass : public Pass { } if (args.size() > 1 && args[1] == "-vhdl87") { - vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1993").c_str()); + vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1987").c_str()); for (size_t argidx = 2; argidx < args.size(); argidx++) if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_87)) log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", args[argidx].c_str()); @@ -917,10 +930,12 @@ struct VerificPass : public Pass { for (; argidx < args.size(); argidx++) { if (veri_file::GetModule(args[argidx].c_str())) { + log("Running veri_file::Elaborate(\"%s\").\n", args[argidx].c_str()); if (!veri_file::Elaborate(args[argidx].c_str())) log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); nl_todo.insert(Netlist::PresentDesign()); } else { + log("Running vhdl_file::Elaborate(\"%s\").\n", args[argidx].c_str()); if (!vhdl_file::Elaborate(args[argidx].c_str())) log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); nl_todo.insert(Netlist::PresentDesign()); diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index ebecb92f2..4a58357bf 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -96,44 +96,54 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le if (base == 10 && GetSize(digits) == 1 && digits.front() >= 0xf0) base = 2; + data.clear(); + if (base == 10) { - data.clear(); - if (len_in_bits < 0) { - while (!digits.empty()) - data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0); - while (data.size() < 32) - data.push_back(RTLIL::S0); - } else { - for (int i = 0; i < len_in_bits; i++) - data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0); + while (!digits.empty()) + data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0); + } else { + int bits_per_digit = my_ilog2(base-1); + for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) { + if (*it > (base-1) && *it < 0xf0) + log_error("Digit larger than %d used in in base-%d constant at %s:%d.\n", + base-1, base, current_filename.c_str(), get_line_num()); + for (int i = 0; i < bits_per_digit; i++) { + int bitmask = 1 << i; + if (*it == 0xf0) + data.push_back(case_type == 'x' ? RTLIL::Sa : RTLIL::Sx); + else if (*it == 0xf1) + data.push_back(case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz); + else if (*it == 0xf2) + data.push_back(RTLIL::Sa); + else + data.push_back((*it & bitmask) ? RTLIL::S1 : RTLIL::S0); + } } - return; } - int bits_per_digit = my_ilog2(base-1); - if (len_in_bits < 0) - len_in_bits = std::max<int>(digits.size() * bits_per_digit, 32); + int len = GetSize(data); + RTLIL::State msb = data.empty() ? RTLIL::S0 : data.back(); - data.clear(); - data.resize(len_in_bits); - - for (int i = 0; i < len_in_bits; i++) { - int bitmask = 1 << (i % bits_per_digit); - int digitidx = digits.size() - (i / bits_per_digit) - 1; - if (digitidx < 0) { - if (i > 0 && (data[i-1] == RTLIL::Sz || data[i-1] == RTLIL::Sx || data[i-1] == RTLIL::Sa)) - data[i] = data[i-1]; - else - data[i] = RTLIL::S0; - } else if (digits[digitidx] == 0xf0) - data[i] = case_type == 'x' ? RTLIL::Sa : RTLIL::Sx; - else if (digits[digitidx] == 0xf1) - data[i] = case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz; - else if (digits[digitidx] == 0xf2) - data[i] = RTLIL::Sa; - else - data[i] = (digits[digitidx] & bitmask) ? RTLIL::S1 : RTLIL::S0; + if (len_in_bits < 0) { + if (len < 32) + data.resize(32, msb == RTLIL::S0 || msb == RTLIL::S1 ? RTLIL::S0 : msb); + return; + } + + for (len = len - 1; len >= 0; len--) + if (data[len] == RTLIL::S1) + break; + if (msb == RTLIL::S0 || msb == RTLIL::S1) { + len += 1; + data.resize(len_in_bits, RTLIL::S0); + } else { + len += 2; + data.resize(len_in_bits, msb); } + + if (len > len_in_bits) + log_warning("Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n", + len_in_bits, len, current_filename.c_str(), get_line_num()); } // convert the Verilog code for a constant to an AST node @@ -142,7 +152,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn if (warn_z) { AstNode *ret = const2ast(code, case_type); if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) - log_warning("Yosys does not support tri-state logic at the moment. (%s:%d)\n", + log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n", current_filename.c_str(), get_line_num()); return ret; } @@ -220,8 +230,6 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn if (len_in_bits < 0) { if (is_signed && data.back() == RTLIL::S1) data.push_back(RTLIL::S0); - while (data.size() < 32) - data.push_back(RTLIL::S0); } return AstNode::mkconst_bits(data, is_signed); } diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index fb8a7b95f..997920b89 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -39,6 +39,7 @@ #include <string.h> YOSYS_NAMESPACE_BEGIN +using namespace VERILOG_FRONTEND; static std::list<std::string> output_code; static std::list<std::string> input_buffer; @@ -222,7 +223,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons input_file(f, filename); defines_map["YOSYS"] = "1"; - defines_map["SYNTHESIS"] = "1"; + defines_map[formal_mode ? "FORMAL" : "SYNTHESIS"] = "1"; while (!input_buffer.empty()) { diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 727ee3d1c..cd8b586c4 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -39,6 +39,14 @@ using namespace VERILOG_FRONTEND; static std::vector<std::string> verilog_defaults; static std::list<std::vector<std::string>> verilog_defaults_stack; +static void error_on_dpi_function(AST::AstNode *node) +{ + if (node->type == AST::AST_DPI_FUNCTION) + log_error("Found DPI function %s at %s:%d.\n", node->str.c_str(), node->filename.c_str(), node->linenum); + for (auto child : node->children) + error_on_dpi_function(child); +} + struct VerilogFrontend : public Frontend { VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } virtual void help() @@ -55,8 +63,8 @@ struct VerilogFrontend : public Frontend { log(" of SystemVerilog is supported)\n"); log("\n"); log(" -formal\n"); - log(" enable support for assert() and assume() statements\n"); - log(" (assert support is also enabled with -sv)\n"); + log(" enable support for assert() and assume() from SystemVerilog\n"); + log(" replace the implicit -D SYNTHESIS with -D FORMAL\n"); log("\n"); log(" -dump_ast1\n"); log(" dump abstract syntax tree (before simplification)\n"); @@ -107,6 +115,9 @@ struct VerilogFrontend : public Frontend { log(" -nopp\n"); log(" do not run the pre-processor\n"); log("\n"); + log(" -nodpi\n"); + log(" disable DPI-C support\n"); + log("\n"); log(" -lib\n"); log(" only create empty blackbox modules. This implies -DBLACKBOX.\n"); log("\n"); @@ -160,6 +171,7 @@ struct VerilogFrontend : public Frontend { bool flag_mem2reg = false; bool flag_ppdump = false; bool flag_nopp = false; + bool flag_nodpi = false; bool flag_lib = false; bool flag_noopt = false; bool flag_icells = false; @@ -229,6 +241,10 @@ struct VerilogFrontend : public Frontend { flag_nopp = true; continue; } + if (arg == "-nodpi") { + flag_nodpi = true; + continue; + } if (arg == "-lib") { flag_lib = true; defines_map["BLACKBOX"] = string(); @@ -320,6 +336,9 @@ struct VerilogFrontend : public Frontend { child->attributes[attr] = AST::AstNode::mkconst_int(1, false); } + if (flag_nodpi) + error_on_dpi_function(current_ast); + AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire); if (!flag_nopp) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index a72593583..69a8ddaad 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -170,7 +170,7 @@ YOSYS_NAMESPACE_END "always_latch" { SV_KEYWORD(TOK_ALWAYS); } "assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } -"assume" { if (formal_mode) return TOK_ASSUME; return TOK_ID; } +"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "logic" { SV_KEYWORD(TOK_REG); } "bit" { SV_KEYWORD(TOK_REG); } @@ -248,7 +248,7 @@ and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { supply0 { return TOK_SUPPLY0; } supply1 { return TOK_SUPPLY1; } -"$"(display|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { +"$"(display|write|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { frontend_verilog_yylval.string = new std::string(yytext); return TOK_ID; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 708ac7627..863fee599 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -153,6 +153,8 @@ design: module design | defattr design | task_func_decl design | + param_decl design | + localparam_decl design | /* empty */; attr: @@ -708,6 +710,8 @@ wire_name_and_opt_assign: wire_name: TOK_ID range_or_multirange { + if (astbuf1 == nullptr) + frontend_verilog_yyerror("Syntax error."); AstNode *node = astbuf1->clone(); node->str = *$1; append_attr_clone(node, albuf); @@ -755,7 +759,7 @@ assign_expr_list: assign_expr | assign_expr_list ',' assign_expr; assign_expr: - expr '=' expr { + lvalue '=' expr { ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); }; @@ -959,7 +963,7 @@ simple_behavioral_stmt: // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: - defattr | assert | wire_decl | + defattr | assert | wire_decl | param_decl | localparam_decl | non_opt_delay behavioral_stmt | simple_behavioral_stmt ';' | ';' | hierarchical_id attr { |