From 6ac9f79de6e558f9386d219eb03654f3f4f3ff08 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 18 Jun 2025 18:05:48 +0200 Subject: [PATCH] neater errors, lost in the sauce of source --- .../yosys_internals/flow/verilog_frontend.rst | 11 +-- frontends/ast/ast.cc | 50 +++++------ frontends/ast/ast.h | 24 ++--- frontends/ast/dpicall.cc | 12 +-- frontends/ast/genrtlil.cc | 50 +++++------ frontends/ast/simplify.cc | 80 +++++++++-------- frontends/verilog/Makefile.inc | 2 + frontends/verilog/const2ast.cc | 11 +-- frontends/verilog/verilog_frontend.cc | 69 +++++--------- frontends/verilog/verilog_frontend.h | 6 +- frontends/verilog/verilog_lexer.h | 18 ++-- frontends/verilog/verilog_lexer.l | 18 ++-- frontends/verilog/verilog_parser.y | 90 ++++++++----------- 13 files changed, 196 insertions(+), 245 deletions(-) diff --git a/docs/source/yosys_internals/flow/verilog_frontend.rst b/docs/source/yosys_internals/flow/verilog_frontend.rst index b6a7ba8a0..d6bdf6b6d 100644 --- a/docs/source/yosys_internals/flow/verilog_frontend.rst +++ b/docs/source/yosys_internals/flow/verilog_frontend.rst @@ -48,7 +48,7 @@ The lexer does little more than identifying all keywords and literals recognised by the Yosys Verilog frontend. The lexer keeps track of the current location in the Verilog source code using -some global variables. These variables are used by the constructor of AST nodes +some VerilogLexer member variables. These variables are used by the constructor of AST nodes to annotate each node with the source code location it originated from. Finally the lexer identifies and handles special comments such as "``// synopsys @@ -189,10 +189,11 @@ the bison code for parsing multiplications: .. code:: none :number-lines: - basic_expr '*' attr basic_expr { - $$ = new AstNode(AST_MUL, $1, $4); - append_attr($$, $3); - } | + basic_expr TOK_ASTER attr basic_expr { + $$ = std::make_unique(AST_MUL, std::move($1), std::move($4)); + SET_AST_NODE_LOC($$.get(), @1, @4); + append_attr($$.get(), $3); + } | The generated AST data structure is then passed directly to the AST frontend that performs the actual conversion to RTLIL. diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 2844f96b7..28a6fce99 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -38,8 +38,7 @@ using namespace AST_INTERNAL; // instantiate global variables (public API) namespace AST { - std::string current_filename; - bool sv_mode; + bool sv_mode_but_global_and_used_for_literally_one_condition; unsigned long long astnodes = 0; unsigned long long astnode_count() { return astnodes; } } @@ -200,7 +199,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) // create new node (AstNode constructor) // (the optional child arguments make it easier to create AST trees) -AstNode::AstNode(AstNodeType type, std::unique_ptr child1, std::unique_ptr child2, std::unique_ptr child3, std::unique_ptr child4) +AstNode::AstNode(AstSrcLocType loc, AstNodeType type, std::unique_ptr child1, std::unique_ptr child2, std::unique_ptr child3, std::unique_ptr child4) { static unsigned int hashidx_count = 123456789; hashidx_count = mkhash_xorshift(hashidx_count); @@ -208,7 +207,7 @@ AstNode::AstNode(AstNodeType type, std::unique_ptr child1, std::unique_ astnodes++; this->type = type; - filename = current_filename; + loc = loc; is_input = false; is_output = false; is_reg = false; @@ -252,7 +251,7 @@ AstNode::AstNode(AstNodeType type, std::unique_ptr child1, std::unique_ // create a (deep recursive) copy of a node std::unique_ptr AstNode::clone() const { - auto that = std::make_unique(this->type); + auto that = std::make_unique(this->location, this->type); cloneInto(*that.get()); return that; } @@ -287,7 +286,6 @@ void AstNode::cloneInto(AstNode &other) const other.id2ast = id2ast; other.basic_prep = basic_prep; other.lookahead = lookahead; - other.filename = filename; other.location = location; other.in_lvalue = in_lvalue; other.in_param = in_param; @@ -842,9 +840,9 @@ bool AstNode::contains(const AstNode *other) const } // create an AST node for a constant (using a 32 bit int as value) -std::unique_ptr AstNode::mkconst_int(uint32_t v, bool is_signed, int width) +std::unique_ptr AstNode::mkconst_int(AstSrcLocType loc, uint32_t v, bool is_signed, int width) { - auto node = std::make_unique(AST_CONSTANT); + auto node = std::make_unique(loc, AST_CONSTANT); node->integer = v; node->is_signed = is_signed; for (int i = 0; i < width; i++) { @@ -858,9 +856,9 @@ std::unique_ptr AstNode::mkconst_int(uint32_t v, bool is_signed, int wi } // create an AST node for a constant (using a bit vector as value) -std::unique_ptr AstNode::mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized) +std::unique_ptr AstNode::mkconst_bits(AstSrcLocType loc, const std::vector &v, bool is_signed, bool is_unsized) { - auto node = std::make_unique(AST_CONSTANT); + auto node = std::make_unique(loc, AST_CONSTANT); node->is_signed = is_signed; node->bits = v; for (size_t i = 0; i < 32; i++) { @@ -876,15 +874,15 @@ std::unique_ptr AstNode::mkconst_bits(const std::vector & return node; } -std::unique_ptr AstNode::mkconst_bits(const std::vector &v, bool is_signed) +std::unique_ptr AstNode::mkconst_bits(AstSrcLocType loc, const std::vector &v, bool is_signed) { - return mkconst_bits(v, is_signed, false); + return mkconst_bits(loc, v, is_signed, false); } // create an AST node for a constant (using a string in bit vector form as value) -std::unique_ptr AstNode::mkconst_str(const std::vector &v) +std::unique_ptr AstNode::mkconst_str(AstSrcLocType loc, const std::vector &v) { - auto node = mkconst_str(RTLIL::Const(v).decode_string()); + auto node = mkconst_str(loc, RTLIL::Const(v).decode_string()); while (GetSize(node->bits) < GetSize(v)) node->bits.push_back(RTLIL::State::S0); log_assert(node->bits == v); @@ -892,14 +890,14 @@ std::unique_ptr AstNode::mkconst_str(const std::vector &v } // create an AST node for a constant (using a string as value) -std::unique_ptr AstNode::mkconst_str(const std::string &str) +std::unique_ptr AstNode::mkconst_str(AstSrcLocType loc, const std::string &str) { std::unique_ptr node; // LRM 1364-2005 5.2.3.3 The empty string literal ("") shall be considered // equivalent to the ASCII NUL ("\0") if (str.empty()) { - node = AstNode::mkconst_int(0, false, 8); + node = AstNode::mkconst_int(loc, 0, false, 8); } else { std::vector data; data.reserve(str.size() * 8); @@ -910,7 +908,7 @@ std::unique_ptr AstNode::mkconst_str(const std::string &str) ch = ch >> 1; } } - node = AstNode::mkconst_bits(data, false); + node = AstNode::mkconst_bits(loc, data, false); } node->is_string = true; @@ -919,19 +917,19 @@ std::unique_ptr AstNode::mkconst_str(const std::string &str) } // create a temporary register -std::unique_ptr AstNode::mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed) +std::unique_ptr AstNode::mktemp_logic(AstSrcLocType loc, const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed) { - auto wire_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(range_left, true), mkconst_int(range_right, true))); + auto wire_owned = std::make_unique(loc, AST_WIRE, std::make_unique(loc, AST_RANGE, mkconst_int(loc, range_left, true), mkconst_int(loc, range_right, true))); auto* wire = wire_owned.get(); - wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); + wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(location.filename).c_str(), location.first_line, autoidx++); if (nosync) - wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); + wire->set_attribute(ID::nosync, AstNode::mkconst_int(loc, 1, false)); wire->is_signed = is_signed; wire->is_logic = true; mod->children.push_back(std::move(wire_owned)); while (wire->simplify(true, 1, -1, false)) { } - auto ident = std::make_unique(AST_IDENTIFIER); + auto ident = std::make_unique(loc, AST_IDENTIFIER); ident->str = wire->str; ident->id2ast = wire; @@ -985,7 +983,7 @@ RTLIL::Const AstNode::asParaConst() const { if (type == AST_REALVALUE) { - auto strnode = AstNode::mkconst_str(stringf("%f", realvalue)); + auto strnode = AstNode::mkconst_str(location, stringf("%f", realvalue)); RTLIL::Const val = strnode->asAttrConst(); val.flags |= RTLIL::CONST_FLAG_REAL; return val; @@ -1087,7 +1085,7 @@ RTLIL::Const AstNode::realAsConst(int width) std::string AstNode::loc_string() const { - return stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); + return stringf("%s:%d.%d-%d.%d", location.filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); } void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast) @@ -1445,7 +1443,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump if (design->has(child->str)) { RTLIL::Module *existing_mod = design->module(child->str); if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) { - log_file_error(child->filename, child->location.first_line, "Re-definition of module `%s'!\n", child->str.c_str()); + log_file_error(child->location.filename, child->location.first_line, "Re-definition of module `%s'!\n", child->str.c_str()); } else if (nooverwrite) { log("Ignoring re-definition of module `%s' at %s.\n", child->str.c_str(), child->loc_string().c_str()); @@ -1924,7 +1922,7 @@ void AstNode::input_error(const char *format, ...) const { va_list ap; va_start(ap, format); - logv_file_error(filename, location.first_line, format, ap); + logv_file_error(location.filename, location.first_line, format, ap); } YOSYS_NAMESPACE_END diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 4c75b6dfa..f881dfcb7 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -163,10 +163,11 @@ namespace AST }; struct AstSrcLocType { + std::string filename; unsigned int first_line, last_line; unsigned int first_column, last_column; - AstSrcLocType() : first_line(0), last_line(0), first_column(0), last_column(0) {} - AstSrcLocType(int _first_line, int _first_column, int _last_line, int _last_column) : first_line(_first_line), last_line(_last_line), first_column(_first_column), last_column(_last_column) {} + AstSrcLocType() : filename(""), first_line(0), last_line(0), first_column(0), last_column(0) {} + AstSrcLocType(std::string _filename, int _first_line, int _first_column, int _last_line, int _last_column) : filename(_filename), first_line(_first_line), last_line(_last_line), first_column(_first_column), last_column(_last_column) {} }; // convert an node type to a string (e.g. for debug output) @@ -223,7 +224,6 @@ namespace AST // this is the original sourcecode location that resulted in this AST node // it is automatically set by the constructor using AST::current_filename and // the AST::get_line_num() callback function. - std::string filename; AstSrcLocType location; // are we embedded in an lvalue, param? @@ -234,7 +234,7 @@ namespace AST bool in_param_from_above; // creating and deleting nodes - AstNode(AstNodeType type = AST_NONE, std::unique_ptr child1 = nullptr, std::unique_ptr child2 = nullptr, std::unique_ptr child3 = nullptr, std::unique_ptr child4 = nullptr); + AstNode(AstSrcLocType loc, AstNodeType type = AST_NONE, std::unique_ptr child1 = nullptr, std::unique_ptr child2 = nullptr, std::unique_ptr child3 = nullptr, std::unique_ptr child4 = nullptr); std::unique_ptr clone() const; void cloneInto(AstNode &other) const; void delete_children(); @@ -322,14 +322,14 @@ namespace AST AstNode operator=(AstNode) = delete; // helper functions for creating AST nodes for constants - static std::unique_ptr mkconst_int(uint32_t v, bool is_signed, int width = 32); - static std::unique_ptr mkconst_bits(const std::vector &v, bool is_signed, bool is_unsized); - static std::unique_ptr mkconst_bits(const std::vector &v, bool is_signed); - static std::unique_ptr mkconst_str(const std::vector &v); - static std::unique_ptr mkconst_str(const std::string &str); + static std::unique_ptr mkconst_int(AstSrcLocType loc, uint32_t v, bool is_signed, int width = 32); + static std::unique_ptr mkconst_bits(AstSrcLocType loc, const std::vector &v, bool is_signed, bool is_unsized); + static std::unique_ptr mkconst_bits(AstSrcLocType loc, const std::vector &v, bool is_signed); + static std::unique_ptr mkconst_str(AstSrcLocType loc, const std::vector &v); + static std::unique_ptr mkconst_str(AstSrcLocType loc, const std::string &str); // helper function to create an AST node for a temporary register - std::unique_ptr mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed); + std::unique_ptr mktemp_logic(AstSrcLocType loc, const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed); // helper function for creating sign-extended const objects RTLIL::Const bitsAsConst(int width, bool is_signed); @@ -409,7 +409,7 @@ namespace AST // to initialize the filename and linenum properties of new nodes extern std::string current_filename; // also set by the language frontend to control some AST processing - extern bool sv_mode; + extern bool sv_mode_but_global_and_used_for_literally_one_condition; // for stats unsigned long long astnode_count(); @@ -419,7 +419,7 @@ namespace AST void use_internal_line_num(); // call a DPI function - std::unique_ptr dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector> &args); + std::unique_ptr dpi_call(AstSrcLocType loc, const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector> &args); // Helper functions related to handling SystemVerilog interfaces std::pair split_modport_from_type(std::string name_type); diff --git a/frontends/ast/dpicall.cc b/frontends/ast/dpicall.cc index 4fa375df7..07314e3d7 100644 --- a/frontends/ast/dpicall.cc +++ b/frontends/ast/dpicall.cc @@ -64,7 +64,7 @@ static ffi_fptr resolve_fn (std::string symbol_name) log_error("unable to resolve '%s'.\n", symbol_name.c_str()); } -std::unique_ptr AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector> &args) +std::unique_ptr AST::dpi_call(AstSrcLocType loc, const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector> &args) { std::unique_ptr newNode = nullptr; union value { double f64; float f32; int32_t i32; void *ptr; }; @@ -125,11 +125,11 @@ std::unique_ptr AST::dpi_call(const std::string &rtype, const std: ffi_call(&cif, resolve_fn(fname.c_str()), values[args.size()], values.data()); if (rtype == "real") { - newNode = std::make_unique(AST_REALVALUE); + newNode = std::make_unique(loc, AST_REALVALUE); newNode->realvalue = value_store[args.size()].f64; log(" return realvalue: %g\n", newNode->asReal(true)); } else if (rtype == "shortreal") { - newNode = std::make_unique(AST_REALVALUE); + newNode = std::make_unique(loc, AST_REALVALUE); newNode->realvalue = value_store[args.size()].f32; log(" return realvalue: %g\n", newNode->asReal(true)); } else if (rtype == "chandle") { @@ -137,10 +137,10 @@ std::unique_ptr AST::dpi_call(const std::string &rtype, const std: std::vector bits(64); for (int i = 0; i < 64; i++) bits.at(i) = (rawval & (1ULL << i)) ? RTLIL::State::S1 : RTLIL::State::S0; - newNode = AstNode::mkconst_bits(bits, false); + newNode = AstNode::mkconst_bits(loc, bits, false); log(" return chandle: %llx\n", (unsigned long long)newNode->asInt(false)); } else { - newNode = AstNode::mkconst_int(value_store[args.size()].i32, false); + newNode = AstNode::mkconst_int(loc, value_store[args.size()].i32, false); log(" return integer: %lld\n", (long long)newNode->asInt(true)); } @@ -153,7 +153,7 @@ YOSYS_NAMESPACE_END YOSYS_NAMESPACE_BEGIN -AST::AstNode *AST::dpi_call(const std::string&, const std::string &fname, const std::vector&, const std::vector&) +AST::AstNode *AST::dpi_call(AstSrcLocType loc, const std::string&, const std::string &fname, const std::vector&, const std::vector&) { log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname.c_str()); } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 994c87da6..dadc4129f 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -45,7 +45,7 @@ using namespace AST_INTERNAL; // helper function for creating RTLIL code for unary operations static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true) { - IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++); + IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line, autoidx++); RTLIL::Cell *cell = current_module->addCell(name, type); set_src_attr(cell, that); @@ -77,7 +77,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s return; } - IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++); + IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line, autoidx++); RTLIL::Cell *cell = current_module->addCell(name, ID($pos)); set_src_attr(cell, that); @@ -104,7 +104,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s // helper function for creating RTLIL code for binary operations static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) { - IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++); + IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line, autoidx++); RTLIL::Cell *cell = current_module->addCell(name, type); set_src_attr(cell, that); @@ -138,7 +138,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const log_assert(cond.size() == 1); std::stringstream sstr; - sstr << "$ternary$" << RTLIL::encode_filename(that->filename) << ":" << that->location.first_line << "$" << (autoidx++); + sstr << "$ternary$" << RTLIL::encode_filename(that->location.filename) << ":" << that->location.first_line << "$" << (autoidx++); RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux)); set_src_attr(cell, that); @@ -347,7 +347,7 @@ struct AST_INTERNAL::ProcessGenerator LookaheadRewriter la_rewriter(always.get()); // generate process and simple root case - proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(always->filename).c_str(), always->location.first_line, autoidx++)); + proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(always->location.filename).c_str(), always->location.first_line, autoidx++)); set_src_attr(proc, always.get()); for (auto &attr : always->attributes) { if (attr.second->type != AST_CONSTANT) @@ -723,7 +723,7 @@ struct AST_INTERNAL::ProcessGenerator if (ast->str == "$display" || ast->str == "$displayb" || ast->str == "$displayh" || ast->str == "$displayo" || ast->str == "$write" || ast->str == "$writeb" || ast->str == "$writeh" || ast->str == "$writeo") { std::stringstream sstr; - sstr << ast->str << "$" << ast->filename << ":" << ast->location.first_line << "$" << (autoidx++); + sstr << ast->str << "$" << ast->location.filename << ":" << ast->location.first_line << "$" << (autoidx++); Wire *en = current_module->addWire(sstr.str() + "_EN", 1); set_src_attr(en, ast); @@ -766,7 +766,7 @@ struct AST_INTERNAL::ProcessGenerator node->detectSignWidth(width, is_signed, nullptr); VerilogFmtArg arg = {}; - arg.filename = node->filename; + arg.filename = node->location.filename; arg.first_line = node->location.first_line; if (node->type == AST_CONSTANT && node->is_string) { arg.type = VerilogFmtArg::STRING; @@ -793,7 +793,7 @@ struct AST_INTERNAL::ProcessGenerator fmt.append_literal("\n"); fmt.emit_rtlil(cell); } else if (!ast->str.empty()) { - log_file_error(ast->filename, ast->location.first_line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str()); + log_file_error(ast->location.filename, ast->location.first_line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str()); } break; @@ -813,7 +813,7 @@ struct AST_INTERNAL::ProcessGenerator IdString cellname; if (ast->str.empty()) - cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(ast->filename).c_str(), ast->location.first_line, autoidx++); + cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(ast->location.filename).c_str(), ast->location.first_line, autoidx++); else cellname = ast->str; check_unique_id(current_module, cellname, ast, "procedural assertion"); @@ -843,7 +843,7 @@ struct AST_INTERNAL::ProcessGenerator set_src_attr(cell, ast); for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(ast->location.filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } cell->setParam(ID::FLAVOR, flavor); @@ -1503,7 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } RTLIL::SigSpec sig = realAsConst(width_hint); - log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); + log_file_warning(location.filename, location.first_line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); return sig; } @@ -1535,7 +1535,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (dynamic_cast(current_module)) { /* nothing to do here */ } else if (flag_autowire) - log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str()); + log_file_warning(location.filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str()); else input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); } @@ -1640,10 +1640,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset = source_width - (chunk.offset + chunk.width); if (chunk.offset > chunk_left || chunk.offset + chunk.width < chunk_right) { if (chunk.width == 1) - log_file_warning(filename, location.first_line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", + log_file_warning(location.filename, location.first_line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", str.c_str()); else - log_file_warning(filename, location.first_line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", + log_file_warning(location.filename, location.first_line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width); chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width); } else { @@ -1657,10 +1657,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset += add_undef_bits_lsb; } if (add_undef_bits_lsb) - log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", + log_file_warning(location.filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) - log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", + log_file_warning(location.filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); } } @@ -1934,7 +1934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_MEMRD: { std::stringstream sstr; - sstr << "$memrd$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); + sstr << "$memrd$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++); RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd)); set_src_attr(cell, this); @@ -1972,7 +1972,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_MEMINIT: { std::stringstream sstr; - sstr << "$meminit$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); + sstr << "$meminit$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++); SigSpec en_sig = children[2]->genRTLIL(); @@ -2017,7 +2017,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) IdString cellname; if (str.empty()) - cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); + cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(location.filename).c_str(), location.first_line, autoidx++); else cellname = str; check_unique_id(current_module, cellname, this, "procedural assertion"); @@ -2060,7 +2060,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) new_left.append(left[i]); new_right.append(right[i]); } - log_file_warning(filename, location.first_line, "Ignoring assignment to constant bits:\n" + log_file_warning(location.filename, location.first_line, "Ignoring assignment to constant bits:\n" " old assignment: %s = %s\n new assignment: %s = %s.\n", log_signal(left), log_signal(right), log_signal(new_left), log_signal(new_right)); @@ -2095,7 +2095,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; const AstNode *value = child->children[0].get(); if (value->type == AST_REALVALUE) - log_file_warning(filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n", + log_file_warning(location.filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n", log_id(cell), log_id(paraname), value->realvalue); else if (value->type != AST_CONSTANT) input_error("Parameter %s.%s with non-constant value!\n", @@ -2192,14 +2192,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int sz = children.size(); if (str == "$info") { if (sz > 0) - log_file_info(filename, location.first_line, "%s.\n", children[0]->str.c_str()); + log_file_info(location.filename, location.first_line, "%s.\n", children[0]->str.c_str()); else - log_file_info(filename, location.first_line, "\n"); + log_file_info(location.filename, location.first_line, "\n"); } else if (str == "$warning") { if (sz > 0) - log_file_warning(filename, location.first_line, "%s.\n", children[0]->str.c_str()); + log_file_warning(location.filename, location.first_line, "%s.\n", children[0]->str.c_str()); else - log_file_warning(filename, location.first_line, "\n"); + log_file_warning(location.filename, location.first_line, "\n"); } else if (str == "$error") { if (sz > 0) input_error("%s.\n", children[0]->str.c_str()); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index f4c27caf4..402dcb1e0 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -155,7 +155,7 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_ while (node_arg->simplify(true, stage, -1, false)) { } VerilogFmtArg arg = {}; - arg.filename = filename; + arg.filename = location.filename; arg.first_line = location.first_line; if (node_arg->type == AST_CONSTANT && node_arg->is_string) { arg.type = VerilogFmtArg::STRING; @@ -173,10 +173,10 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_ arg.sig = node_arg->bitsAsConst(); arg.signed_ = node_arg->is_signed; } else if (may_fail) { - log_file_info(filename, location.first_line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); + log_file_info(location.filename, location.first_line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); return Fmt(); } else { - log_file_error(filename, location.first_line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); + log_file_error(location.filename, location.first_line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); } args.push_back(arg); } @@ -240,20 +240,20 @@ void AstNode::annotateTypedEnums(AstNode *template_node) RTLIL::Const val = enum_item->children[0]->bitsAsConst(width, is_signed); enum_item_str.append(val.as_string()); //set attribute for available val to enum item name mappings - set_attribute(enum_item_str.c_str(), mkconst_str(enum_item->str)); + set_attribute(enum_item_str.c_str(), mkconst_str(location, enum_item->str)); } } } -static std::unique_ptr make_range(int left, int right, bool is_signed = false) +static std::unique_ptr make_range(AstSrcLocType loc, int left, int right, bool is_signed = false) { // generate a pre-validated range node for a fixed signal range. - auto range = std::make_unique(AST_RANGE); + auto range = std::make_unique(loc, AST_RANGE); range->range_left = left; range->range_right = right; range->range_valid = true; - range->children.push_back(AstNode::mkconst_int(left, true)); - range->children.push_back(AstNode::mkconst_int(right, true)); + range->children.push_back(AstNode::mkconst_int(loc, left, true)); + range->children.push_back(AstNode::mkconst_int(loc, right, true)); range->is_signed = is_signed; return range; } @@ -388,30 +388,32 @@ static int size_packed_struct(AstNode *snode, int base_offset) return width; } -static std::unique_ptr node_int(int ival) +static std::unique_ptr node_int(AstSrcLocType loc, int ival) { - return AstNode::mkconst_int(ival, true); + return AstNode::mkconst_int(loc, ival, true); } static std::unique_ptr multiply_by_const(std::unique_ptr expr_node, int stride) { - return std::make_unique(AST_MUL, std::move(expr_node), node_int(stride)); + auto loc = expr_node->location; + return std::make_unique(loc, AST_MUL, std::move(expr_node), node_int(loc, stride)); } static std::unique_ptr normalize_index(AstNode *expr, AstNode *decl_node, int dimension) { auto new_expr = expr->clone(); + auto loc = expr->location; int offset = decl_node->dimensions[dimension].range_right; if (offset) { - new_expr = std::make_unique(AST_SUB, std::move(new_expr), node_int(offset)); + new_expr = std::make_unique(loc, AST_SUB, std::move(new_expr), node_int(loc, offset)); } // Packed dimensions are normally indexed by lsb, while unpacked dimensions are normally indexed by msb. if ((dimension < decl_node->unpacked_dimensions) ^ decl_node->dimensions[dimension].range_swapped) { // Swap the index if the dimension is declared the "wrong" way. int left = decl_node->dimensions[dimension].range_width - 1; - new_expr = std::make_unique(AST_SUB, node_int(left), std::move(new_expr)); + new_expr = std::make_unique(loc, AST_SUB, node_int(loc, left), std::move(new_expr)); } return new_expr; @@ -433,7 +435,7 @@ static std::unique_ptr index_msb_offset(std::unique_ptr lsb_of std::unique_ptr add_offset; if (rnode->children.size() == 1) { // Index, e.g. s.a[i] - add_offset = node_int(stride - 1); + add_offset = node_int(rnode->location, stride - 1); } else { // rnode->children.size() == 2 @@ -620,7 +622,7 @@ const RTLIL::Module* AstNode::lookup_cell_module() auto reprocess_after = [this] (const std::string &modname) { if (!attributes.count(ID::reprocess_after)) - set_attribute(ID::reprocess_after, AstNode::mkconst_str(modname)); + set_attribute(ID::reprocess_after, AstNode::mkconst_str(location, modname)); }; const AstNode *celltype = nullptr; @@ -929,7 +931,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin #if 0 log("-------------\n"); - log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), location.first_line, type2str(type).c_str(), this); + log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, location.filename.c_str(), location.first_line, type2str(type).c_str(), this); log("const_fold=%d, stage=%d, width_hint=%d, sign_hint=%d\n", int(const_fold), int(stage), int(width_hint), int(sign_hint)); // dumpAst(nullptr, "> "); @@ -1020,7 +1022,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin for (auto &it : node->attributes) if (it.first != ID::mem2reg) reg->set_attribute(it.first, it.second->clone()); - reg->filename = node->filename; + reg->location.filename = node->location.filename; reg->location = node->location; while (reg->simplify(true, 1, -1, false)) { } children.push_back(std::move(reg)); @@ -1049,7 +1051,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // note that $display, $finish, and $stop 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 == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) { - log_file_warning(filename, location.first_line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str()); + log_file_warning(location.filename, location.first_line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str()); delete_children(); str = std::string(); } @@ -1059,7 +1061,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin str == "$write" || str == "$writeb" || str == "$writeh" || str == "$writeo")) { if (!current_always) { - log_file_warning(filename, location.first_line, "System task `%s' outside initial or always block is unsupported.\n", str.c_str()); + log_file_warning(location.filename, location.first_line, "System task `%s' outside initial or always block is unsupported.\n", str.c_str()); delete_children(); str = std::string(); } else { @@ -1336,7 +1338,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // create the indirection wire std::stringstream sstr; - sstr << "$indirect$" << ref->name.c_str() << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); + sstr << "$indirect$" << ref->name.c_str() << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++); std::string tmp_str = sstr.str(); add_wire_for_ref(ref, tmp_str); @@ -2174,7 +2176,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin int width = std::abs(children[1]->range_left - children[1]->range_right) + 1; if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); - log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", + log_file_warning(location.filename, location.first_line, "converting real value %e to binary %s.\n", children[0]->realvalue, log_signal(constvalue)); children[0] = mkconst_bits(constvalue.to_bits(), sign_hint); fixup_hierarchy_flags(); @@ -2316,7 +2318,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin std::swap(data_range_left, data_range_right); std::stringstream sstr; - sstr << "$mem2bits$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); + sstr << "$mem2bits$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++); std::string wire_id = sstr.str(); auto wire_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true))); @@ -2536,7 +2538,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin for (size_t i = 0; i < children.size(); i++) if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) { - log_assert(!sv_mode); + log_assert(!sv_mode_but_global_and_used_for_literally_one_condition); children[i]->input_error("Local declaration in unnamed block is only supported in SystemVerilog mode!\n"); } } @@ -3072,7 +3074,7 @@ skip_dynamic_range_lvalue_expansion:; auto wire_tmp_owned = std::make_unique(AST_WIRE, std::make_unique(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true))); auto wire_tmp = wire_tmp_owned.get(); - wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); + wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line, autoidx++); current_scope[wire_tmp->str] = wire_tmp; current_ast_mod->children.push_back(std::move(wire_tmp_owned)); wire_tmp->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); @@ -3114,7 +3116,7 @@ skip_dynamic_range_lvalue_expansion:; input_error("Insufficient number of array indices for %s.\n", log_id(str)); std::stringstream sstr; - sstr << "$memwr$" << children[0]->str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); + sstr << "$memwr$" << children[0]->str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; int mem_width, mem_size, addr_bits; @@ -3385,7 +3387,7 @@ skip_dynamic_range_lvalue_expansion:; auto* reg = reg_owned.get(); current_ast_mod->children.push_back(std::move(reg_owned)); - reg->str = stringf("$past$%s:%d$%d$%d", RTLIL::encode_filename(filename).c_str(), location.first_line, myidx, i); + reg->str = stringf("$past$%s:%d$%d$%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line, myidx, i); reg->is_reg = true; reg->is_signed = sign_hint; @@ -3761,7 +3763,7 @@ skip_dynamic_range_lvalue_expansion:; input_error("Failed to evaluate DPI function with non-constant argument.\n"); } - newNode = dpi_call(rtype, fname, argtypes, args); + newNode = dpi_call(dpi_decl->location, rtype, fname, argtypes, args); goto apply_newNode; } @@ -3845,7 +3847,7 @@ skip_dynamic_range_lvalue_expansion:; std::stringstream sstr; - sstr << str << "$func$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++) << '.'; + sstr << str << "$func$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++) << '.'; std::string prefix = sstr.str(); auto* decl = current_scope[str]; @@ -4375,7 +4377,7 @@ apply_newNode: // newNode->dumpAst(stderr, "+ "); log_assert(newNode != nullptr); // newNode->null_check(); - newNode->filename = filename; + newNode->location.filename = location.filename; newNode->location = location; newNode->cloneInto(*this); fixup_hierarchy_flags(); @@ -4422,7 +4424,7 @@ std::unique_ptr AstNode::readmem(bool is_readmemh, std::string mem_file #else char slash = '/'; #endif - std::string path = filename.substr(0, filename.find_last_of(slash)+1); + std::string path = location.filename.substr(0, location.filename.find_last_of(slash)+1); f.open(path + mem_filename.c_str()); yosys_input_files.insert(path + mem_filename); } else { @@ -4479,7 +4481,7 @@ std::unique_ptr AstNode::readmem(bool is_readmemh, std::string mem_file continue; } - VERILOG_FRONTEND::ConstParser p{mem_filename, std::nullopt}; + VERILOG_FRONTEND::ConstParser p{memory->location}; auto value = p.const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token); if (unconditional_init) @@ -4701,7 +4703,7 @@ static void mark_memories_assign_lhs_complex(dict> & if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) { AstNode *mem = that->id2ast; if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS)) - mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(that->filename).c_str(), that->location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS; } } @@ -4729,14 +4731,14 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg // activate mem2reg if this is assigned in an async proc if (flags & AstNode::MEM2REG_FL_ASYNC) { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC)) - mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC; } // remember if this is assigned blocking (=) if (type == AST_ASSIGN_EQ) { if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1)) - mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line)); proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; } @@ -4753,11 +4755,11 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg // remember where this is if (flags & MEM2REG_FL_INIT) { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT)) - mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT; } else { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE)) - mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE; } } @@ -4774,7 +4776,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg // flag if used after blocking assignment (in same proc) if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) { - mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line)); + mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line)); mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2; } } @@ -4960,7 +4962,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, children[0]->children[0]->children[0]->type != AST_CONSTANT) { std::stringstream sstr; - sstr << "$mem2reg_wr$" << children[0]->str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); + sstr << "$mem2reg_wr$" << children[0]->str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA"; int mem_width, mem_size, addr_bits; @@ -5079,7 +5081,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, else { std::stringstream sstr; - sstr << "$mem2reg_rd$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++); + sstr << "$mem2reg_rd$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA"; int mem_width, mem_size, addr_bits; diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc index cc8baf6aa..338b13e4b 100644 --- a/frontends/verilog/Makefile.inc +++ b/frontends/verilog/Makefile.inc @@ -13,6 +13,7 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc frontends/verilog/verilog_frontend.h: frontends/verilog/verilog_parser.tab.hh +frontends/verilog/verilog_error.h: frontends/verilog/verilog_parser.tab.hh frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc $(Q) mkdir -p $(dir $@) @@ -24,5 +25,6 @@ OBJS += frontends/verilog/verilog_parser.tab.o OBJS += frontends/verilog/verilog_lexer.o OBJS += frontends/verilog/preproc.o OBJS += frontends/verilog/verilog_frontend.o +OBJS += frontends/verilog/verilog_error.o OBJS += frontends/verilog/const2ast.o diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 9c4a2e76c..cd8f05b9b 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -46,11 +46,8 @@ using namespace VERILOG_FRONTEND; std::string ConstParser::fmt_maybe_loc(std::string msg) { std::string s; - s += filename.value_or("INTERNAL"); - if (loc) - s += stringf("%d", loc->first_line); - s += ": "; + s += stringf("%s:%d:", loc.filename, loc.first_line); s += msg; return s; @@ -191,7 +188,7 @@ std::unique_ptr ConstParser::const2ast(std::string code, char case_type ch = ch >> 1; } } - auto ast = AstNode::mkconst_bits(data, false); + auto ast = AstNode::mkconst_bits(loc, data, false); ast->str = code; return ast; } @@ -210,7 +207,7 @@ std::unique_ptr ConstParser::const2ast(std::string code, char case_type my_strtobin(data, str, -1, 10, case_type, false); if (data.back() == State::S1) data.push_back(State::S0); - return AstNode::mkconst_bits(data, true); + return AstNode::mkconst_bits(loc, data, true); } // unsized constant @@ -258,7 +255,7 @@ std::unique_ptr ConstParser::const2ast(std::string code, char case_type if (is_signed && data.back() == State::S1) data.push_back(State::S0); } - return AstNode::mkconst_bits(data, is_signed, is_unsized); + return AstNode::mkconst_bits(loc, data, is_signed, is_unsized); } return NULL; diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 8cb9bb3ae..7a31b9363 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -32,10 +32,12 @@ #include "verilog_frontend.h" #include "verilog_lexer.h" +#include "verilog_error.h" #include "preproc.h" #include "kernel/yosys.h" #include "libs/sha1/sha1.h" #include +#include YOSYS_NAMESPACE_BEGIN using namespace VERILOG_FRONTEND; @@ -47,10 +49,10 @@ static std::list> verilog_defaults_stack; static void error_on_dpi_function(AST::AstNode *node) { - if (node->type == AST::AST_DPI_FUNCTION) - log_file_error(node->filename, node->location.first_line, "Found DPI function %s.\n", node->str.c_str()); - for (auto& child : node->children) - error_on_dpi_function(child.get()); + if (node->type == AST::AST_DPI_FUNCTION) + err_at_ast(node->location, "Found DPI function %s.\n", node->str.c_str()); + for (auto& child : node->children) + error_on_dpi_function(child.get()); } static void add_package_types(dict &user_types, std::vector> &package_list) @@ -69,15 +71,7 @@ static void add_package_types(dict &user_types, std } struct VerilogFrontend : public Frontend { - ParseMode parse_mode; - ParseState parse_state; - VerilogLexer lexer; - frontend_verilog_yy::parser parser; - VerilogFrontend() : Frontend("verilog", "read modules from Verilog file"), - parse_mode(), - parse_state(), - lexer(&parse_state, &parse_mode), - parser(&lexer, &parse_state, &parse_mode) { } + VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -259,6 +253,8 @@ struct VerilogFrontend : public Frontend { bool flag_dump_vlog1 = false; bool flag_dump_vlog2 = false; bool flag_dump_rtlil = false; + bool flag_debug_lexer = false; + bool flag_debug_parser = false; bool flag_nolatches = false; bool flag_nomeminit = false; bool flag_nomem2reg = false; @@ -281,8 +277,8 @@ struct VerilogFrontend : public Frontend { std::list include_dirs; std::list attributes; - lexer.set_debug(false); - parser.set_debug_level(0); + ParseMode parse_mode; + ParseState parse_state; parse_mode.sv = false; parse_mode.formal = false; parse_mode.noassert = false; @@ -340,8 +336,8 @@ struct VerilogFrontend : public Frontend { flag_dump_ast2 = true; flag_dump_vlog1 = true; flag_dump_vlog2 = true; - lexer.set_debug(true); - parser.set_debug_level(1); + flag_debug_lexer = true; + flag_debug_parser = true; continue; } if (arg == "-dump_ast1") { @@ -370,6 +366,8 @@ struct VerilogFrontend : public Frontend { } if (arg == "-yydebug") { flag_yydebug = true; + flag_debug_lexer = true; + flag_debug_parser = true; continue; } if (arg == "-nolatches") { @@ -481,6 +479,11 @@ struct VerilogFrontend : public Frontend { break; } + VerilogLexer lexer(&parse_state, &parse_mode, &filename); + frontend_verilog_yy::parser parser(&lexer, &parse_state, &parse_mode); + lexer.set_debug(flag_debug_lexer); + parser.set_debug_level(flag_debug_parser ? 1 : 0); + if (parse_mode.formal || !flag_nosynthesis) defines_map.add(parse_mode.formal ? "FORMAL" : "SYNTHESIS", "1"); @@ -491,10 +494,10 @@ struct VerilogFrontend : public Frontend { log("Parsing %s%s input from `%s' to AST representation.\n", parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str()); - AST::current_filename = filename; - AST::sv_mode = parse_mode.sv; + AST::sv_mode_but_global_and_used_for_literally_one_condition = parse_mode.sv; - parse_state.current_ast = new AST::AstNode(AST::AST_DESIGN); + AstSrcLocType top_loc = AstSrcLocType ( "read_verilog", 0, 0, 0, 0); + parse_state.current_ast = new AST::AstNode(top_loc, AST::AST_DESIGN); parse_state.lexin = f; std::string code_after_preproc; @@ -522,10 +525,6 @@ struct VerilogFrontend : public Frontend { // add a new empty type map to allow overriding existing global definitions parse_state.user_type_stack.push_back(UserTypeMap()); - parser.~parser(); - lexer.~VerilogLexer(); - new (&lexer) VerilogLexer(&parse_state, &parse_mode); - new (&parser) frontend_verilog_yy::parser(&lexer, &parse_state, &parse_mode); if (flag_yydebug) { lexer.set_debug(true); parser.set_debug_level(1); @@ -537,7 +536,7 @@ struct VerilogFrontend : public Frontend { if (child->type == AST::AST_MODULE) for (auto &attr : attributes) if (child->attributes.count(attr) == 0) - child->attributes[attr] = AST::AstNode::mkconst_int(1, false); + child->attributes[attr] = AST::AstNode::mkconst_int(top_loc, 1, false); } if (flag_nodpi) @@ -776,24 +775,4 @@ struct VerilogFileList : public Pass { #endif -[[noreturn]] -void VERILOG_FRONTEND::verr_at(std::string filename, int begin_line, char const *fmt, va_list ap) -{ - char buffer[1024]; - char *p = buffer; - p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); - p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); - YOSYS_NAMESPACE_PREFIX log_file_error(filename, begin_line, "%s", buffer); - exit(1); -} - -[[noreturn]] -void VERILOG_FRONTEND::err_at_ast(AstSrcLocType loc, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - verr_at(AST::current_filename, loc.first_line, fmt, args); - va_end(args); -} - YOSYS_NAMESPACE_END diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index 29c16c039..e97cee4fc 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -39,7 +39,6 @@ #include #include -#include YOSYS_NAMESPACE_BEGIN @@ -47,8 +46,7 @@ namespace VERILOG_FRONTEND { /* Ephemeral context class */ struct ConstParser { - std::optional filename; - std::optional loc; + AST::AstSrcLocType loc; private: std::string fmt_maybe_loc(std::string msg); void log_maybe_loc_error(std::string msg); @@ -64,8 +62,6 @@ namespace VERILOG_FRONTEND std::unique_ptr const2ast(std::string code, char case_type = 0, bool warn_z = false); }; - [[noreturn]] - extern void err_at_ast(AST::AstSrcLocType loc, char const *fmt, ...); }; YOSYS_NAMESPACE_END diff --git a/frontends/verilog/verilog_lexer.h b/frontends/verilog/verilog_lexer.h index 2c31160dd..a4f3d9bfb 100644 --- a/frontends/verilog/verilog_lexer.h +++ b/frontends/verilog/verilog_lexer.h @@ -4,18 +4,20 @@ #include "kernel/yosys.h" #include "frontends/ast/ast.h" #include "frontends/verilog/verilog_parser.tab.hh" +#include YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { - [[noreturn]] - extern void verr_at(std::string filename, int begin_line, char const *fmt, va_list ap); using parser = frontend_verilog_yy::parser; class VerilogLexer : public frontend_verilog_yyFlexLexer { ParseState* extra; ParseMode* mode; public: - VerilogLexer(ParseState* e, ParseMode* m) : frontend_verilog_yyFlexLexer(e->lexin), extra(e), mode(m) {} + parser::location_type out_loc; // TODO private? + VerilogLexer(ParseState* e, ParseMode* m, std::string* filename) : frontend_verilog_yyFlexLexer(e->lexin), extra(e), mode(m) { + out_loc.begin.filename = filename; + } ~VerilogLexer() override {} // autogenerated body due to YY_DECL parser::symbol_type nextToken(); @@ -24,19 +26,9 @@ namespace VERILOG_FRONTEND { parser::symbol_type terminate() { return parser::make_FRONTEND_VERILOG_YYEOF(out_loc); } - parser::location_type out_loc; - [[noreturn]] - void err(char const *fmt, ...) - { - va_list args; - va_start(args, fmt); - verr_at(AST::current_filename, yylineno, fmt, args); - } private: std::vector fn_stack; std::vector ln_stack; - parser::location_type real_loc; - parser::location_type old_loc; int LexerInput(char* buf, int max_size) override { return readsome(*extra->lexin, buf, max_size); } diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index d57912265..f9e9dc2df 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -85,17 +85,16 @@ YOSYS_NAMESPACE_END // result = readsome(*extra->lexin, buf, max_size) #define YY_USER_ACTION \ - real_loc.begin = real_loc.end; \ + out_loc.begin = out_loc.end; \ for(int i = 0; YYText()[i] != '\0'; ++i){ \ if(YYText()[i] == '\n') { \ - real_loc.end.line++; \ - real_loc.end.column = 1; \ + out_loc.end.line++; \ + out_loc.end.column = 1; \ } \ else { \ - real_loc.end.column++; \ + out_loc.end.column++; \ } \ - } \ - out_loc = real_loc; + } #define YY_BREAK \ break; @@ -183,7 +182,6 @@ TIME_SCALE_SUFFIX [munpf]?s current_filename = current_filename.substr(0, current_filename.size()-1); yylineno = (0); out_loc.begin.line = out_loc.end.line = 0; - real_loc.begin.line = real_loc.end.line = 0; } "`file_pop"[^\n]*\n { @@ -191,7 +189,6 @@ TIME_SCALE_SUFFIX [munpf]?s fn_stack.pop_back(); yylineno = (ln_stack.back()); out_loc.begin.line = out_loc.end.line = ln_stack.back(); - real_loc.begin.line = real_loc.end.line = ln_stack.back(); ln_stack.pop_back(); } @@ -200,7 +197,6 @@ TIME_SCALE_SUFFIX [munpf]?s while (*p == ' ' || *p == '\t') p++; yylineno = (atoi(p)); out_loc.begin.line = out_loc.end.line = atoi(p); - real_loc.begin.line = real_loc.end.line = atoi(p); while (*p && *p != ' ' && *p != '\t') p++; while (*p == ' ' || *p == '\t') p++; const char *q = *p ? p + 1 : p; @@ -226,14 +222,14 @@ TIME_SCALE_SUFFIX [munpf]?s else if (!strcmp(p, "wire")) extra->default_nettype_wire = true; else - err("Unsupported default nettype: %s", p); + err_at_loc(out_loc, "Unsupported default nettype: %s", p); } "`protect"[^\n]* /* ignore `protect*/ "`endprotect"[^\n]* /* ignore `endprotect*/ "`"[a-zA-Z_$][a-zA-Z0-9_$]* { - err("Unimplemented compiler directive or undefined macro %s.", YYText()); + err_at_loc(out_loc, "Unimplemented compiler directive or undefined macro %s.", YYText()); } "module" { return parser::make_TOK_MODULE(out_loc); } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 24a21a740..527d01247 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -45,7 +45,7 @@ %code requires { #include "kernel/yosys_common.h" - // #include "frontends/verilog/verilog_lexer.h" + #include "frontends/verilog/verilog_error.h" // start requires YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { @@ -157,8 +157,7 @@ static ConstParser make_ConstParser_here(parser::location_type flex_loc) { AstSrcLocType loc; SET_LOC(loc, flex_loc, flex_loc); - std::optional filename = flex_loc.begin.filename ? std::make_optional(*(flex_loc.begin.filename)) : std::nullopt; - ConstParser p{filename, loc}; + ConstParser p{loc}; return p; } static void append_attr(AstNode *ast, dict> *al) @@ -244,17 +243,6 @@ node->children.push_back(std::move(rangeNode)); } - [[noreturn]] - extern void verr_at(std::string filename, int begin_line, char const *fmt, va_list ap); - [[noreturn]] - static void err_at_loc(frontend_verilog_yy::parser::location_type loc, char const *fmt, ...) - { - va_list args; - va_start(args, fmt); - verr_at(AST::current_filename, loc.begin.line, fmt, args); - va_end(args); - } - static void checkLabelsMatch(const frontend_verilog_yy::parser::location_type& loc, const char *element, const std::string* before, const std::string *after) { if (!before && after) @@ -731,7 +719,7 @@ module: append_attr(mod, $1); } module_para_opt module_args_opt TOK_SEMICOL module_body TOK_ENDMODULE opt_label { if (extra->port_stubs.size() != 0) - lexer->err("Missing details for module port `%s'.", + err_at_loc(@7, "Missing details for module port `%s'.", extra->port_stubs.begin()->first.c_str()); SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @$); extra->ast_stack.pop_back(); @@ -785,7 +773,7 @@ module_arg_opt_assignment: extra->ast_stack.back()->children.push_back(std::make_unique(AST_ASSIGN, std::move(wire), std::move($2))); } } else - lexer->err("SystemVerilog interface in module port list cannot have a default value."); + err_at_loc(@2, "SystemVerilog interface in module port list cannot have a default value."); } | %empty; @@ -799,7 +787,7 @@ module_arg: extra->ast_stack.back()->children.push_back(std::move(node)); } else { if (extra->port_stubs.count(*$1) != 0) - lexer->err("Duplicate module port `%s'.", $1->c_str()); + err_at_loc(@1, "Duplicate module port `%s'.", $1->c_str()); extra->port_stubs[*$1] = ++extra->port_counter; } } module_arg_opt_assignment | @@ -809,7 +797,7 @@ module_arg: extra->astbuf1->children[0]->str = *$1; } TOK_ID { /* SV interfaces */ if (!mode->sv) - lexer->err("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str()); + err_at_loc(@3, "Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str()); extra->astbuf2 = extra->astbuf1->clone(); // really only needed if multiple instances of same type. extra->astbuf2->str = *$3; extra->astbuf2->port_id = ++extra->port_counter; @@ -824,9 +812,9 @@ module_arg: if (range != nullptr) node->children.push_back(std::move(range)); if (!node->is_input && !node->is_output) - lexer->err("Module port `%s' is neither input nor output.", $4->c_str()); + err_at_loc(@4, "Module port `%s' is neither input nor output.", $4->c_str()); if (node->is_reg && node->is_input && !node->is_output && !mode->sv) - lexer->err("Input port `%s' is declared as register.", $4->c_str()); + err_at_loc(@4, "Input port `%s' is declared as register.", $4->c_str()); append_attr(node.get(), $1); extra->ast_stack.back()->children.push_back(std::move(node)); } module_arg_opt_assignment | @@ -867,7 +855,7 @@ interface: intf->str = *$3; } module_para_opt module_args_opt TOK_SEMICOL interface_body TOK_ENDINTERFACE { if (extra->port_stubs.size() != 0) - lexer->err("Missing details for module port `%s'.", + err_at_loc(@6, "Missing details for module port `%s'.", extra->port_stubs.begin()->first.c_str()); extra->ast_stack.pop_back(); log_assert(extra->ast_stack.size() == 1); @@ -1284,7 +1272,7 @@ task_func_port: extra->astbuf2 = checkRange(extra->astbuf1.get(), std::move($3)); if (!extra->astbuf1->is_input && !extra->astbuf1->is_output) { if (!mode->sv) - lexer->err("task/function argument direction missing"); + err_at_loc(@2, "task/function argument direction missing"); extra->astbuf1->is_input = prev_was_input; extra->astbuf1->is_output = prev_was_output; } @@ -1292,7 +1280,7 @@ task_func_port: { if (!extra->astbuf1) { if (!mode->sv) - lexer->err("task/function argument direction missing"); + err_at_loc(@$, "task/function argument direction missing"); extra->albuf = new dict>; extra->astbuf1 = std::make_unique(AST_WIRE); extra->current_wire_rand = false; @@ -1325,7 +1313,7 @@ specify_item: specify_rise_fall_ptr_t timing = std::move($9); if (specify_edge != 0 && target->dat == nullptr) - lexer->err("Found specify edge but no data spec.\n"); + err_at_loc(@3, "Found specify edge but no data spec.\n"); auto cell_owned = std::make_unique(AST_CELL); auto cell = cell_owned.get(); @@ -1400,7 +1388,7 @@ specify_item: TOK_ID TOK_LPAREN specify_edge expr specify_condition TOK_COMMA specify_edge expr specify_condition TOK_COMMA specify_triple specify_opt_triple TOK_RPAREN TOK_SEMICOL { if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" && *$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange") - lexer->err("Unsupported specify rule type: %s\n", $1->c_str()); + err_at_loc(@1, "Unsupported specify rule type: %s\n", $1->c_str()); auto src_pen = AstNode::mkconst_int($3 != 0, false, 1); auto src_pol = AstNode::mkconst_int($3 == 'p', false, 1); @@ -1766,10 +1754,10 @@ single_param_decl: AstNode *decl = extra->ast_stack.back()->children.back().get(); if (decl->type != AST_PARAMETER) { log_assert(decl->type == AST_LOCALPARAM); - lexer->err("localparam initialization is missing!"); + err_at_loc(@1, "localparam initialization is missing!"); } if (!mode->sv) - lexer->err("Parameter defaults can only be omitted in SystemVerilog mode!"); + err_at_loc(@1, "Parameter defaults can only be omitted in SystemVerilog mode!"); decl->children.erase(decl->children.begin()); }; @@ -1778,7 +1766,7 @@ single_param_decl_ident: std::unique_ptr node_owned; if (extra->astbuf1 == nullptr) { if (!mode->sv) - lexer->err("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword"); + err_at_loc(@1, "In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword"); node_owned = std::make_unique(AST_PARAMETER); node_owned->children.push_back(AstNode::mkconst_int(0, true)); } else { @@ -1929,7 +1917,7 @@ struct_body: opt_packed TOK_LCURL struct_member_list TOK_RCURL opt_packed: TOK_PACKED opt_signed_struct | - %empty { lexer->err("Only PACKED supported at this time"); }; + %empty { err_at_loc(@$, "Only PACKED supported at this time"); }; opt_signed_struct: TOK_SIGNED { extra->astbuf2->is_signed = true; } @@ -2114,7 +2102,7 @@ wire_name_and_opt_assign: wire_name: TOK_ID range_or_multirange { if (extra->astbuf1 == nullptr) - lexer->err("Internal error - should not happen - no AST_WIRE node."); + err_at_loc(@1, "Internal error - should not happen - no AST_WIRE node."); auto node = extra->astbuf1->clone(); node->str = *$1; append_attr_clone(node.get(), extra->albuf); @@ -2122,7 +2110,7 @@ wire_name: node->children.push_back(extra->astbuf2->clone()); if ($2 != nullptr) { if (node->is_input || node->is_output) - lexer->err("input/output/inout ports cannot have unpacked dimensions."); + err_at_loc(@2, "input/output/inout ports cannot have unpacked dimensions."); if (!extra->astbuf2 && !node->is_custom_type) { addRange(node.get(), 0, 0, false); } @@ -2133,21 +2121,21 @@ wire_name: node->port_id = extra->current_function_or_task_port_id++; } else if (extra->ast_stack.back()->type == AST_GENBLOCK) { if (node->is_input || node->is_output) - lexer->err("Cannot declare module port `%s' within a generate block.", $1->c_str()); + err_at_loc(@1, "Cannot declare module port `%s' within a generate block.", $1->c_str()); } else { if (extra->do_not_require_port_stubs && (node->is_input || node->is_output) && extra->port_stubs.count(*$1) == 0) { extra->port_stubs[*$1] = ++extra->port_counter; } if (extra->port_stubs.count(*$1) != 0) { if (!node->is_input && !node->is_output) - lexer->err("Module port `%s' is neither input nor output.", $1->c_str()); + err_at_loc(@1, "Module port `%s' is neither input nor output.", $1->c_str()); if (node->is_reg && node->is_input && !node->is_output && !mode->sv) - lexer->err("Input port `%s' is declared as register.", $1->c_str()); + err_at_loc(@1, "Input port `%s' is declared as register.", $1->c_str()); node->port_id = extra->port_stubs[*$1]; extra->port_stubs.erase(*$1); } else { if (node->is_input || node->is_output) - lexer->err("Module port `%s' is not declared in module header.", $1->c_str()); + err_at_loc(@1, "Module port `%s' is not declared in module header.", $1->c_str()); } } //FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column... @@ -2169,7 +2157,7 @@ assign_expr: }; type_name: TOK_ID { $$ = std::move($1); } // first time seen - | TOK_USER_TYPE { if (extra->isInLocalScope($1.get())) lexer->err("Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); $$ = std::move($1); } + | TOK_USER_TYPE { if (extra->isInLocalScope($1.get())) err_at_loc(@1, "Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); $$ = std::move($1); } ; typedef_decl: @@ -2347,7 +2335,7 @@ cell_port_list: } if (has_positional_args && has_named_args) - lexer->err("Mix of positional and named cell ports."); + err_at_loc(@1, "Mix of positional and named cell ports."); }; cell_port_list_rules: @@ -2388,7 +2376,7 @@ cell_port: } | attr TOK_WILDCARD_CONNECT { if (!mode->sv) - lexer->err("Wildcard port connections are only supported in SystemVerilog mode."); + err_at_loc(@2, "Wildcard port connections are only supported in SystemVerilog mode."); extra->cell_hack->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false); free_attr($1); }; @@ -2727,11 +2715,11 @@ for_initialization: extra->ast_stack.back()->children.push_back(std::move(node)); } | non_io_wire_type range TOK_ID { - lexer->err("For loop variable declaration is missing initialization!"); + err_at_loc(@3, "For loop variable declaration is missing initialization!"); } | non_io_wire_type range TOK_ID TOK_EQ expr { if (!mode->sv) - lexer->err("For loop inline variable declaration is only supported in SystemVerilog mode!"); + err_at_loc(@4, "For loop inline variable declaration is only supported in SystemVerilog mode!"); // loop variable declaration auto wire = std::move($1); @@ -2915,21 +2903,21 @@ if_attr: attr TOK_UNIQUE0 { AstNode *context = extra->ast_stack.back(); if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) - lexer->err("unique0 keyword cannot be used for 'else if' branch."); + err_at_loc(@2, "unique0 keyword cannot be used for 'else if' branch."); (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false); $$ = $1; } | attr TOK_PRIORITY { AstNode *context = extra->ast_stack.back(); if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) - lexer->err("priority keyword cannot be used for 'else if' branch."); + err_at_loc(@2, "priority keyword cannot be used for 'else if' branch."); (*$1)[ID::full_case] = AstNode::mkconst_int(1, false); $$ = $1; } | attr TOK_UNIQUE { AstNode *context = extra->ast_stack.back(); if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) - lexer->err("unique keyword cannot be used for 'else if' branch."); + err_at_loc(@2, "unique keyword cannot be used for 'else if' branch."); (*$1)[ID::full_case] = AstNode::mkconst_int(1, false); (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false); $$ = $1; @@ -3127,11 +3115,11 @@ genvar_identifier: genvar_initialization: TOK_GENVAR genvar_identifier { - lexer->err("Generate for loop variable declaration is missing initialization!"); + err_at_loc(@2, "Generate for loop variable declaration is missing initialization!"); } | TOK_GENVAR genvar_identifier TOK_EQ expr { if (!mode->sv) - lexer->err("Generate for loop inline variable declaration is only supported in SystemVerilog mode!"); + err_at_loc(@3, "Generate for loop inline variable declaration is only supported in SystemVerilog mode!"); AstNode* node = extra->saveChild(std::make_unique(AST_GENVAR)); node->is_reg = true; node->is_signed = true; @@ -3233,7 +3221,7 @@ basic_expr: } | TOK_LPAREN expr TOK_RPAREN integral_number { if ($4->compare(0, 1, "'") != 0) - lexer->err("Cast operation must be applied on sized constants e.g. () , while %s is not a sized constant.", $4->c_str()); + err_at_loc(@4, "Cast operation must be applied on sized constants e.g. () , while %s is not a sized constant.", $4->c_str()); auto p = make_ConstParser_here(@4); auto val = p.const2ast(*$4, extra->case_type_stack.size() == 0 ? 0 : extra->case_type_stack.back(), !mode->lib); if (val == nullptr) @@ -3242,7 +3230,7 @@ basic_expr: } | hierarchical_id integral_number { if ($2->compare(0, 1, "'") != 0) - lexer->err("Cast operation must be applied on sized constants, e.g. \'d0, while %s is not a sized constant.", $2->c_str()); + err_at_loc(@2, "Cast operation must be applied on sized constants, e.g. \'d0, while %s is not a sized constant.", $2->c_str()); auto bits = std::make_unique(AST_IDENTIFIER); bits->str = *$1; SET_AST_NODE_LOC(bits.get(), @1, @1); @@ -3491,25 +3479,25 @@ basic_expr: } | TOK_SIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!mode->sv) - lexer->err("Static cast is only supported in SystemVerilog mode."); + err_at_loc(@2, "Static cast is only supported in SystemVerilog mode."); $$ = std::make_unique(AST_TO_SIGNED, std::move($4)); SET_AST_NODE_LOC($$.get(), @1, @4); } | TOK_UNSIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!mode->sv) - lexer->err("Static cast is only supported in SystemVerilog mode."); + err_at_loc(@2, "Static cast is only supported in SystemVerilog mode."); $$ = std::make_unique(AST_TO_UNSIGNED, std::move($4)); SET_AST_NODE_LOC($$.get(), @1, @4); } | basic_expr OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!mode->sv) - lexer->err("Static cast is only supported in SystemVerilog mode."); + err_at_loc(@2, "Static cast is only supported in SystemVerilog mode."); $$ = std::make_unique(AST_CAST_SIZE, std::move($1), std::move($4)); SET_AST_NODE_LOC($$.get(), @1, @4); } | typedef_base_type OP_CAST TOK_LPAREN expr TOK_RPAREN { if (!mode->sv) - lexer->err("Static cast is only supported in SystemVerilog mode."); + err_at_loc(@2, "Static cast is only supported in SystemVerilog mode."); $$ = std::make_unique(AST_CAST_SIZE, std::move($1), std::move($4)); SET_AST_NODE_LOC($$.get(), @1, @4); } |