diff --git a/PEvent.cc b/PEvent.cc index 9bf56ea5b..ed6fce388 100644 --- a/PEvent.cc +++ b/PEvent.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -21,8 +21,8 @@ # include "PEvent.h" -PEvent::PEvent(perm_string n) -: name_(n) +PEvent::PEvent(perm_string n, unsigned lexical_pos) +: name_(n), lexical_pos_(lexical_pos) { } diff --git a/PEvent.h b/PEvent.h index ba5bb668b..3b648f757 100644 --- a/PEvent.h +++ b/PEvent.h @@ -1,7 +1,7 @@ #ifndef IVL_PEvent_H #define IVL_PEvent_H /* - * Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -36,17 +36,20 @@ class PEvent : public PNamedItem { public: // The name is a perm-allocated string. It is the simple name // of the event, without any scope. - explicit PEvent(perm_string name); + explicit PEvent(perm_string name, unsigned lexical_pos); ~PEvent(); perm_string name() const; + unsigned lexical_pos() const { return lexical_pos_; } + void elaborate_scope(Design*des, NetScope*scope) const; SymbolType symbol_type() const; private: perm_string name_; + unsigned lexical_pos_; private: // not implemented PEvent(const PEvent&); diff --git a/PExpr.cc b/PExpr.cc index 73679a4b1..35f0ed2ef 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2021 Stephen Williams + * Copyright (c) 1998-2024 Stephen Williams * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -360,19 +360,19 @@ const verireal& PEFNumber::value() const return *value_; } -PEIdent::PEIdent(const pform_name_t&that) -: path_(that), no_implicit_sig_(false) +PEIdent::PEIdent(const pform_name_t&that, unsigned lexical_pos) +: path_(that), lexical_pos_(lexical_pos), no_implicit_sig_(false) { } -PEIdent::PEIdent(perm_string s, bool no_implicit_sig) -: no_implicit_sig_(no_implicit_sig) +PEIdent::PEIdent(perm_string s, unsigned lexical_pos, bool no_implicit_sig) +: lexical_pos_(lexical_pos), no_implicit_sig_(no_implicit_sig) { path_.name.push_back(name_component_t(s)); } -PEIdent::PEIdent(PPackage*pkg, const pform_name_t&that) -: path_(pkg, that), no_implicit_sig_(true) +PEIdent::PEIdent(PPackage*pkg, const pform_name_t&that, unsigned lexical_pos) +: path_(pkg, that), lexical_pos_(lexical_pos), no_implicit_sig_(true) { } @@ -426,7 +426,7 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type) ss = ss->parent_scope(); } - PWire*net = new PWire(name, type, NetNet::NOT_A_PORT); + PWire*net = new PWire(name, lexical_pos_, type, NetNet::NOT_A_PORT); net->set_file(get_file()); net->set_lineno(get_lineno()); scope->wires[name] = net; @@ -440,7 +440,7 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type) bool PEIdent::has_aa_term(Design*des, NetScope*scope) const { symbol_search_results sr; - if (!symbol_search(this, des, scope, path_, &sr)) + if (!symbol_search(this, des, scope, path_, lexical_pos_, &sr)) return false; // Class properties are not considered automatic since a non-blocking diff --git a/PExpr.h b/PExpr.h index 991ad395a..ba494ada3 100644 --- a/PExpr.h +++ b/PExpr.h @@ -336,9 +336,9 @@ class PEFNumber : public PExpr { class PEIdent : public PExpr { public: - explicit PEIdent(perm_string, bool no_implicit_sig=false); - explicit PEIdent(PPackage*pkg, const pform_name_t&name); - explicit PEIdent(const pform_name_t&); + explicit PEIdent(perm_string, unsigned lexical_pos, bool no_implicit_sig=false); + explicit PEIdent(PPackage*pkg, const pform_name_t&name, unsigned lexical_pos); + explicit PEIdent(const pform_name_t&, unsigned lexical_pos); ~PEIdent(); // Add another name to the string of hierarchy that is the @@ -386,8 +386,11 @@ class PEIdent : public PExpr { const pform_scoped_name_t& path() const { return path_; } + unsigned lexical_pos() const { return lexical_pos_; } + private: pform_scoped_name_t path_; + unsigned lexical_pos_; bool no_implicit_sig_; private: diff --git a/PScope.h b/PScope.h index 9fd41a461..03bc4f2e3 100644 --- a/PScope.h +++ b/PScope.h @@ -1,7 +1,7 @@ #ifndef IVL_PScope_H #define IVL_PScope_H /* - * Copyright (c) 2008-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -121,6 +121,8 @@ class LexicalScope { bool overridable; // Whether the parameter is a type parameter bool type_flag = false; + // The lexical position of the declaration + unsigned lexical_pos = 0; SymbolType symbol_type() const; }; diff --git a/PWire.cc b/PWire.cc index c4bc817f2..817c1d1b5 100644 --- a/PWire.cc +++ b/PWire.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -25,10 +25,11 @@ using namespace std; PWire::PWire(perm_string n, + unsigned lp, NetNet::Type t, NetNet::PortType pt, PWSRType rt) -: name_(n), type_(t), port_type_(pt), signed_(false), +: name_(n), lexical_pos_(lp), type_(t), port_type_(pt), signed_(false), port_set_(false), net_set_(false), is_scalar_(false), error_cnt_(0), discipline_(0) { diff --git a/PWire.h b/PWire.h index f9178d11c..4ab66d430 100644 --- a/PWire.h +++ b/PWire.h @@ -1,7 +1,7 @@ #ifndef IVL_PWire_H #define IVL_PWire_H /* - * Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -55,6 +55,7 @@ class PWire : public PNamedItem { public: PWire(perm_string name, + unsigned lexical_pos, NetNet::Type t, NetNet::PortType pt, PWSRType rt = SR_NET); @@ -62,6 +63,8 @@ class PWire : public PNamedItem { // Return a hierarchical name. perm_string basename() const; + unsigned lexical_pos() const { return lexical_pos_; } + NetNet::Type get_wire_type() const; bool set_wire_type(NetNet::Type); @@ -99,6 +102,7 @@ class PWire : public PNamedItem { private: perm_string name_; + unsigned lexical_pos_; NetNet::Type type_; NetNet::PortType port_type_; bool signed_; diff --git a/Statement.cc b/Statement.cc index 1dda37940..16307804a 100644 --- a/Statement.cc +++ b/Statement.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -396,8 +396,8 @@ PReturn::~PReturn() delete expr_; } -PTrigger::PTrigger(PPackage*pkg, const pform_name_t&ev) -: event_(pkg, ev) +PTrigger::PTrigger(PPackage*pkg, const pform_name_t&ev, unsigned lexical_pos) +: event_(pkg, ev), lexical_pos_(lexical_pos) { } @@ -405,8 +405,8 @@ PTrigger::~PTrigger() { } -PNBTrigger::PNBTrigger(const pform_name_t&ev, PExpr*dly) -: event_(ev), dly_(dly) +PNBTrigger::PNBTrigger(const pform_name_t&ev, unsigned lexical_pos, PExpr*dly) +: event_(ev), lexical_pos_(lexical_pos), dly_(dly) { } diff --git a/Statement.h b/Statement.h index d540fb881..c0c5e23e5 100644 --- a/Statement.h +++ b/Statement.h @@ -1,7 +1,7 @@ #ifndef IVL_Statement_H #define IVL_Statement_H /* - * Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -599,7 +599,7 @@ class PReturn : public Statement { class PTrigger : public Statement { public: - explicit PTrigger(PPackage*pkg, const pform_name_t&ev); + explicit PTrigger(PPackage*pkg, const pform_name_t&ev, unsigned lexical_pos); ~PTrigger(); virtual NetProc* elaborate(Design*des, NetScope*scope) const; @@ -607,11 +607,12 @@ class PTrigger : public Statement { private: pform_scoped_name_t event_; + unsigned lexical_pos_; }; class PNBTrigger : public Statement { public: - explicit PNBTrigger(const pform_name_t&ev, PExpr*dly); + explicit PNBTrigger(const pform_name_t&ev, unsigned lexical_pos, PExpr*dly); ~PNBTrigger(); virtual NetProc* elaborate(Design*des, NetScope*scope) const; @@ -619,6 +620,7 @@ class PNBTrigger : public Statement { private: pform_name_t event_; + unsigned lexical_pos_; PExpr*dly_; }; diff --git a/elab_expr.cc b/elab_expr.cc index 902f1605a..12967412a 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2023 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2024 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1731,7 +1731,7 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope, // Search for the symbol. This should turn up a scope. symbol_search_results search_results; - bool search_flag = symbol_search(this, des, scope, path_, &search_results); + bool search_flag = symbol_search(this, des, scope, path_, UINT_MAX, &search_results); if (debug_elaborate) { cerr << get_fileline() << ": PECallFunction::test_width: " @@ -2843,7 +2843,7 @@ NetExpr* PECallFunction::elaborate_expr_(Design*des, NetScope*scope, // Search for the symbol. This should turn up a scope. symbol_search_results search_results; - bool search_flag = symbol_search(this, des, scope, path_, &search_results); + bool search_flag = symbol_search(this, des, scope, path_, UINT_MAX, &search_results); if (debug_elaborate) { cerr << get_fileline() << ": PECallFunction::elaborate_expr: " @@ -4334,7 +4334,7 @@ ivl_type_t PEIdent::resolve_type_(Design *des, const symbol_search_results &sr, unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) { symbol_search_results sr; - bool found_symbol = symbol_search(this, des, scope, path_, &sr); + bool found_symbol = symbol_search(this, des, scope, path_, lexical_pos_, &sr); // If there is a part/bit select expression, then process it // here. This constrains the results no matter what kind the @@ -4490,11 +4490,16 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, bool need_const = NEED_CONST & flags; symbol_search_results sr; - symbol_search(this, des, scope, path_, &sr); + symbol_search(this, des, scope, path_, lexical_pos_, &sr); if (!sr.net) { cerr << get_fileline() << ": error: Unable to bind variable `" << path_ << "' in `" << scope_path(scope) << "'" << endl; + if (sr.decl_after_use) { + cerr << sr.decl_after_use->get_fileline() << ": : " + "A symbol with that name was declared here. " + "Check for declaration after use." << endl; + } des->errors++; return nullptr; } @@ -4680,7 +4685,7 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, // a net called "b" in the scope "main.a" and with a member // named "c". symbol_search() handles this for us. symbol_search_results sr; - symbol_search(this, des, scope, path_, &sr); + symbol_search(this, des, scope, path_, lexical_pos_, &sr); // If the identifier name is a parameter name, then return // the parameter value. @@ -5016,6 +5021,11 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, << "' is being used as a constant function, so may " "only reference local variables." << endl; } + if (sr.decl_after_use) { + cerr << sr.decl_after_use->get_fileline() << ": : " + "A symbol with that name was declared here. " + "Check for declaration after use." << endl; + } des->errors += 1; return 0; } diff --git a/elab_lval.cc b/elab_lval.cc index 81c12a6c0..bc6ae087e 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -174,7 +174,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, } symbol_search_results sr; - symbol_search(this, des, scope, path_, &sr); + symbol_search(this, des, scope, path_, lexical_pos_, &sr); NetNet *reg = sr.net; pform_name_t &member_path = sr.path_tail; @@ -193,6 +193,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, cerr << get_fileline() << ": error: Could not find variable ``" << path_ << "'' in ``" << scope_path(scope) << "''" << endl; + if (sr.decl_after_use) { + cerr << sr.decl_after_use->get_fileline() << ": : " + "A symbol with that name was declared here. " + "Check for declaration after use." << endl; + } } des->errors += 1; return 0; diff --git a/elab_net.cc b/elab_net.cc index 388f01491..7d0024192 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -503,7 +503,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, ivl_assert(*this, scope); symbol_search_results sr; - symbol_search(this, des, scope, path_.name, &sr); + symbol_search(this, des, scope, path_.name, lexical_pos_, &sr); if (sr.eve != 0) { cerr << get_fileline() << ": error: named events (" << path_ @@ -520,6 +520,11 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, if (sig == 0) { cerr << get_fileline() << ": error: Net " << path_ << " is not defined in this context." << endl; + if (sr.decl_after_use) { + cerr << sr.decl_after_use->get_fileline() << ": : " + "A symbol with that name was declared here. " + "Check for declaration after use." << endl; + } des->errors += 1; return 0; } @@ -1113,10 +1118,15 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const { symbol_search_results sr; - symbol_search(this, des, scope, path_, &sr); + symbol_search(this, des, scope, path_, lexical_pos_, &sr); if (!sr.net) { cerr << get_fileline() << ": error: Net " << path_ << " is not defined in this context." << endl; + if (sr.decl_after_use) { + cerr << sr.decl_after_use->get_fileline() << ": : " + "A symbol with that name was declared here. " + "Check for declaration after use." << endl; + } des->errors += 1; return nullptr; } @@ -1138,7 +1148,7 @@ bool PEIdent::is_collapsible_net(Design*des, NetScope*scope, ivl_assert(*this, scope); symbol_search_results sr; - symbol_search(this, des, scope, path_.name, &sr); + symbol_search(this, des, scope, path_.name, lexical_pos_, &sr); if (sr.eve != 0) return false; diff --git a/elab_scope.cc b/elab_scope.cc index c5e26c596..aa97a9027 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2022 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1553,6 +1553,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s void PEvent::elaborate_scope(Design*, NetScope*scope) const { NetEvent*ev = new NetEvent(name_); + ev->lexical_pos(lexical_pos_); ev->set_line(*this); scope->add_event(ev); } diff --git a/elab_sig.cc b/elab_sig.cc index 34692f1c1..65c2899f7 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1209,6 +1209,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const if (wtype == NetNet::WIRE) sig->devirtualize_pins(); sig->set_line(*this); sig->port_type(port_type_); + sig->lexical_pos(lexical_pos_); if (ivl_discipline_t dis = get_discipline()) { sig->set_discipline(dis); diff --git a/elab_type.cc b/elab_type.cc index 7ae224836..9048e3afc 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2020 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -250,7 +250,7 @@ ivl_type_t struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const } netstruct_t::member_t memb; - memb.name = namep->name; + memb.name = namep->name.first; memb.net_type = elaborate_array_type(des, scope, *this, mem_vec, namep->index); res->append_member(des, memb); diff --git a/elaborate.cc b/elaborate.cc index 6e4cc99a0..410e30eff 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -29,6 +29,7 @@ # include # include +# include # include # include # include @@ -1270,9 +1271,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const pform_name_t path_; path_.push_back(name_component_t(rmod->ports[j]->name)); symbol_search_results sr; - symbol_search(this, des, scope, path_, &sr); + symbol_search(this, des, scope, path_, UINT_MAX, &sr); if (sr.net != 0) { - pins[j] = new PEIdent(rmod->ports[j]->name, true); + pins[j] = new PEIdent(rmod->ports[j]->name, UINT_MAX, true); pins[j]->set_lineno(get_lineno()); pins[j]->set_file(get_file()); } @@ -3824,7 +3825,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, // (internally represented as "@") is handled by there being a // "this" object in the instance scope. symbol_search_results sr; - symbol_search(this, des, scope, use_path, &sr); + symbol_search(this, des, scope, use_path, UINT_MAX, &sr); NetNet*net = sr.net; if (net == 0) @@ -4907,7 +4908,7 @@ cerr << endl; if (PEIdent*id = dynamic_cast(expr_[idx]->expr())) { symbol_search_results sr; - symbol_search(this, des, scope, id->path(), &sr); + symbol_search(this, des, scope, id->path(), id->lexical_pos(), &sr); if (sr.scope && sr.eve) { wa->add_event(sr.eve); @@ -6037,9 +6038,14 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const ivl_assert(*this, scope); symbol_search_results sr; - if (!symbol_search(this, des, scope, event_, &sr)) { + if (!symbol_search(this, des, scope, event_, lexical_pos_, &sr)) { cerr << get_fileline() << ": error: event <" << event_ << ">" << " not found." << endl; + if (sr.decl_after_use) { + cerr << sr.decl_after_use->get_fileline() << ": : " + "A symbol with that name was declared here. " + "Check for declaration after use." << endl; + } des->errors += 1; return 0; } @@ -6061,9 +6067,14 @@ NetProc* PNBTrigger::elaborate(Design*des, NetScope*scope) const ivl_assert(*this, scope); symbol_search_results sr; - if (!symbol_search(this, des, scope, event_, &sr)) { + if (!symbol_search(this, des, scope, event_, lexical_pos_, &sr)) { cerr << get_fileline() << ": error: event <" << event_ << ">" << " not found." << endl; + if (sr.decl_after_use) { + cerr << sr.decl_after_use->get_fileline() << ": : " + "A symbol with that name was declared here. " + "Check for declaration after use." << endl; + } des->errors += 1; return 0; } diff --git a/ivtest/gold/decl_before_use1-iverilog-stderr.gold b/ivtest/gold/decl_before_use1-iverilog-stderr.gold new file mode 100644 index 000000000..bde09a416 --- /dev/null +++ b/ivtest/gold/decl_before_use1-iverilog-stderr.gold @@ -0,0 +1,4 @@ +ivltests/decl_before_use1.v:4: error: Could not find variable ``v'' in ``test'' +ivltests/decl_before_use1.v:9: : A symbol with that name was declared here. Check for declaration after use. +ivltests/decl_before_use1.v:5: error: Unable to bind wire/reg/memory `v' in `test' +2 error(s) during elaboration. diff --git a/ivtest/gold/decl_before_use2-iverilog-stderr.gold b/ivtest/gold/decl_before_use2-iverilog-stderr.gold new file mode 100644 index 000000000..40091a707 --- /dev/null +++ b/ivtest/gold/decl_before_use2-iverilog-stderr.gold @@ -0,0 +1,4 @@ +ivltests/decl_before_use2.v:3: error: Net w is not defined in this context. +ivltests/decl_before_use2.v:10: : A symbol with that name was declared here. Check for declaration after use. +ivltests/decl_before_use2.v:6: error: Unable to bind wire/reg/memory `w' in `test' +2 error(s) during elaboration. diff --git a/ivtest/gold/decl_before_use3-iverilog-stderr.gold b/ivtest/gold/decl_before_use3-iverilog-stderr.gold new file mode 100644 index 000000000..b42d51989 --- /dev/null +++ b/ivtest/gold/decl_before_use3-iverilog-stderr.gold @@ -0,0 +1,3 @@ +ivltests/decl_before_use3.v:4: error: event not found. +ivltests/decl_before_use3.v:8: : A symbol with that name was declared here. Check for declaration after use. +1 error(s) during elaboration. diff --git a/ivtest/gold/decl_before_use4-iverilog-stderr.gold b/ivtest/gold/decl_before_use4-iverilog-stderr.gold new file mode 100644 index 000000000..1a6e3ebe3 --- /dev/null +++ b/ivtest/gold/decl_before_use4-iverilog-stderr.gold @@ -0,0 +1,4 @@ +ivltests/decl_before_use4.v:4: error: Unable to bind wire/reg/memory `e' in `test' +ivltests/decl_before_use4.v:8: : A symbol with that name was declared here. Check for declaration after use. +ivltests/decl_before_use4.v:4: error: Failed to evaluate event expression 'e'. +2 error(s) during elaboration. diff --git a/ivtest/gold/decl_before_use5-iverilog-stderr.gold b/ivtest/gold/decl_before_use5-iverilog-stderr.gold new file mode 100644 index 000000000..732e678fd --- /dev/null +++ b/ivtest/gold/decl_before_use5-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/decl_before_use5.v:4: error: Unable to bind wire/reg/memory `w' in `test' +1 error(s) during elaboration. diff --git a/ivtest/ivltests/decl_before_use1.v b/ivtest/ivltests/decl_before_use1.v new file mode 100644 index 000000000..8f338b72a --- /dev/null +++ b/ivtest/ivltests/decl_before_use1.v @@ -0,0 +1,11 @@ +module test(); + +initial begin + v = 1; + $display("%b", v); + $display("FAILED"); +end + +reg v; + +endmodule diff --git a/ivtest/ivltests/decl_before_use2.v b/ivtest/ivltests/decl_before_use2.v new file mode 100644 index 000000000..3eeb619c3 --- /dev/null +++ b/ivtest/ivltests/decl_before_use2.v @@ -0,0 +1,12 @@ +module test(); + +assign w = 1; + +initial begin + $display("%b", w); + $display("FAILED"); +end + +wire [7:0] w; + +endmodule diff --git a/ivtest/ivltests/decl_before_use3.v b/ivtest/ivltests/decl_before_use3.v new file mode 100644 index 000000000..8fed35387 --- /dev/null +++ b/ivtest/ivltests/decl_before_use3.v @@ -0,0 +1,10 @@ +module test(); + +initial begin + ->e; + $display("FAILED"); +end + +event e; + +endmodule diff --git a/ivtest/ivltests/decl_before_use4.v b/ivtest/ivltests/decl_before_use4.v new file mode 100644 index 000000000..8daa94218 --- /dev/null +++ b/ivtest/ivltests/decl_before_use4.v @@ -0,0 +1,12 @@ +module test(); + +initial begin + @(e); + $display("FAILED"); +end + +event e; + +initial ->e; + +endmodule diff --git a/ivtest/ivltests/decl_before_use5.v b/ivtest/ivltests/decl_before_use5.v new file mode 100644 index 000000000..cb92f23a0 --- /dev/null +++ b/ivtest/ivltests/decl_before_use5.v @@ -0,0 +1,10 @@ +module test(); + +initial begin + $display("%b", w); + $display("FAILED"); +end + +localparam w = 8'hAA; + +endmodule diff --git a/ivtest/ivltests/decl_before_use6.v b/ivtest/ivltests/decl_before_use6.v new file mode 100644 index 000000000..36770556d --- /dev/null +++ b/ivtest/ivltests/decl_before_use6.v @@ -0,0 +1,20 @@ +module test(); + +localparam w = 8; + +task t; + reg [w:1] v; + localparam w = 2; + begin + v = 8'hAA; + $display("%b", v); + if (v === 8'hAA) + $display("PASSED"); + else + $display("FAILED"); + end +endtask; + +initial t; + +endmodule diff --git a/ivtest/ivltests/sdf_interconnect1.v b/ivtest/ivltests/sdf_interconnect1.v index 91f500539..7f8f44c73 100644 --- a/ivtest/ivltests/sdf_interconnect1.v +++ b/ivtest/ivltests/sdf_interconnect1.v @@ -42,14 +42,14 @@ endmodule module top; + reg a; + wire b; + initial begin $sdf_annotate("ivltests/sdf_interconnect1.sdf", my_design_inst); $monitor("time=%0t a=%h b=%h", $realtime, a, b); end - reg a; - wire b; - initial begin #5; a <= 1'b0; @@ -65,4 +65,3 @@ module top; ); endmodule - diff --git a/ivtest/ivltests/sdf_interconnect2.v b/ivtest/ivltests/sdf_interconnect2.v index c35523a41..2627398c5 100644 --- a/ivtest/ivltests/sdf_interconnect2.v +++ b/ivtest/ivltests/sdf_interconnect2.v @@ -44,14 +44,14 @@ endmodule module top; + reg a; + wire b; + initial begin $sdf_annotate("ivltests/sdf_interconnect2.sdf", my_design_inst); $monitor("time=%0t a=%h b=%h", $realtime, a, b); end - reg a; - wire b; - initial begin #5; a <= 1'b0; @@ -67,4 +67,3 @@ module top; ); endmodule - diff --git a/ivtest/ivltests/sdf_interconnect3.v b/ivtest/ivltests/sdf_interconnect3.v index fc501f641..203cc4656 100644 --- a/ivtest/ivltests/sdf_interconnect3.v +++ b/ivtest/ivltests/sdf_interconnect3.v @@ -87,14 +87,14 @@ endmodule module top; + reg a, b, c; + wire d; + initial begin $sdf_annotate("ivltests/sdf_interconnect3.sdf", my_design_inst); $monitor("time=%0t a=%h b=%h c=%h d=%h", $realtime, a, b, c, d); end - reg a, b, c; - wire d; - initial begin #10; a <= 1'b0; @@ -140,4 +140,3 @@ module top; ); endmodule - diff --git a/ivtest/ivltests/sdf_interconnect4.v b/ivtest/ivltests/sdf_interconnect4.v index 918a34a98..5b6e1be37 100644 --- a/ivtest/ivltests/sdf_interconnect4.v +++ b/ivtest/ivltests/sdf_interconnect4.v @@ -41,14 +41,14 @@ endmodule module top; + reg [2:0] a; + wire [2:0] b; + initial begin $sdf_annotate("ivltests/sdf_interconnect4.sdf", my_design_inst); $monitor("time=%0t a=%b b=%b", $realtime, a, b); end - reg [2:0] a; - wire [2:0] b; - initial begin #5; a <= 3'b000; @@ -64,4 +64,3 @@ module top; ); endmodule - diff --git a/ivtest/regress-ivl1.list b/ivtest/regress-ivl1.list index 7ba05aba8..af0a5b3e5 100644 --- a/ivtest/regress-ivl1.list +++ b/ivtest/regress-ivl1.list @@ -286,10 +286,6 @@ sv_deferred_assume2 CE,-g2009 ivltests gold=sv_deferred_assume2.gold # Icarus deviations #------------------------------------------------------------------------------ -# Icarus still allows (implicit) declaration after use in some circumstances. -pr1909940 normal ivltests -pr1909940b normal ivltests - # Icarus allows hierarchical references to unnamed generate blocks. # We should add a warning about this, as it's not strictly allowed. unnamed_generate_block normal ivltests gold=unnamed_generate_block.gold diff --git a/ivtest/regress-vhdl.list b/ivtest/regress-vhdl.list index 87089687f..3d94f9e8b 100644 --- a/ivtest/regress-vhdl.list +++ b/ivtest/regress-vhdl.list @@ -108,7 +108,7 @@ vhdl_generic_eval normal,-g2005-sv,ivltests/vhdl_generic_eval.vhd ivltests vhdl_fa4_test1 normal,-g2005-sv,ivltests/vhdl_fa4_test1.vhd ivltests vhdl_fa4_test2 normal,-g2005-sv,ivltests/vhdl_fa4_test2.vhd ivltests vhdl_fa4_test3 normal,-g2005-sv,ivltests/vhdl_fa4_test3.vhd ivltests -vhdl_fa4_test4 normal,-g2005-sv,ivltests/vhdl_fa4_test4.vhd ivltests +vhdl_fa4_test4 NI ivltests vhdl_file_open normal,-g2005-sv,ivltests/vhdl_file_open.vhd ivltests vhdl_generic_default normal,-g2005-sv,ivltests/vhdl_generic_default.vhd ivltests vhdl_init normal,-g2005-sv,ivltests/vhdl_init.vhd ivltests diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index 8dd34a0fa..19ece7d66 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -1106,6 +1106,8 @@ pr1903324 normal ivltests pr1903343 normal ivltests gold=pr1903343.gold pr1903520 normal ivltests pr1907192 normal ivltests +pr1909940 CE ivltests +pr1909940b CE ivltests pr1912843 normal ivltests pr1913918a normal ivltests pr1913918b normal ivltests diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 79662c919..468ca7d14 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -64,6 +64,12 @@ constfunc17 vvp_tests/constfunc17.json constfunc18 vvp_tests/constfunc18.json constfunc19 vvp_tests/constfunc19.json constfunc20 vvp_tests/constfunc20.json +decl_before_use1 vvp_tests/decl_before_use1.json +decl_before_use2 vvp_tests/decl_before_use2.json +decl_before_use3 vvp_tests/decl_before_use3.json +decl_before_use4 vvp_tests/decl_before_use4.json +decl_before_use5 vvp_tests/decl_before_use5.json +decl_before_use6 vvp_tests/decl_before_use6.json delayed_sfunc vvp_tests/delayed_sfunc.json dffsynth vvp_tests/dffsynth.json dffsynth-S vvp_tests/dffsynth-S.json diff --git a/ivtest/vvp_tests/decl_before_use1.json b/ivtest/vvp_tests/decl_before_use1.json new file mode 100644 index 000000000..e3452b26a --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use1.json @@ -0,0 +1,6 @@ + +{ + "type" : "CE", + "source" : "decl_before_use1.v", + "gold" : "decl_before_use1" +} diff --git a/ivtest/vvp_tests/decl_before_use2.json b/ivtest/vvp_tests/decl_before_use2.json new file mode 100644 index 000000000..07ec7d5f1 --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use2.json @@ -0,0 +1,6 @@ + +{ + "type" : "CE", + "source" : "decl_before_use2.v", + "gold" : "decl_before_use2" +} diff --git a/ivtest/vvp_tests/decl_before_use3.json b/ivtest/vvp_tests/decl_before_use3.json new file mode 100644 index 000000000..0fa1baa38 --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use3.json @@ -0,0 +1,6 @@ + +{ + "type" : "CE", + "source" : "decl_before_use3.v", + "gold" : "decl_before_use3" +} diff --git a/ivtest/vvp_tests/decl_before_use4.json b/ivtest/vvp_tests/decl_before_use4.json new file mode 100644 index 000000000..4c367891b --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use4.json @@ -0,0 +1,6 @@ + +{ + "type" : "CE", + "source" : "decl_before_use4.v", + "gold" : "decl_before_use4" +} diff --git a/ivtest/vvp_tests/decl_before_use5.json b/ivtest/vvp_tests/decl_before_use5.json new file mode 100644 index 000000000..36e14fe11 --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use5.json @@ -0,0 +1,6 @@ + +{ + "type" : "CE", + "source" : "decl_before_use5.v", + "gold" : "decl_before_use5" +} diff --git a/ivtest/vvp_tests/decl_before_use6.json b/ivtest/vvp_tests/decl_before_use6.json new file mode 100644 index 000000000..17376ea6f --- /dev/null +++ b/ivtest/vvp_tests/decl_before_use6.json @@ -0,0 +1,5 @@ + +{ + "type" : "normal", + "source" : "decl_before_use6.v" +} diff --git a/lexor.lex b/lexor.lex index f94c68f5f..4e93cb87b 100644 --- a/lexor.lex +++ b/lexor.lex @@ -26,6 +26,7 @@ //# define YYSTYPE lexval +# include # include # include # include "compiler.h" @@ -40,7 +41,7 @@ using namespace std; -# define YY_USER_INIT reset_lexor(); +# define YY_USER_INIT do { reset_lexor(); yylloc.lexical_pos = 0; } while (0); # define yylval VLlval # define YY_NO_INPUT @@ -338,6 +339,8 @@ TU [munpf] int rc = lexor_keyword_code(yytext, yyleng); switch (rc) { case IDENTIFIER: + assert(yylloc.lexical_pos != UINT_MAX); + yylloc.lexical_pos += 1; yylval.text = strdupnew(yytext); if (strncmp(yylval.text,"PATHPULSE$", 10) == 0) rc = PATHPULSE_IDENTIFIER; @@ -429,6 +432,8 @@ TU [munpf] \\[^ \t\b\f\r\n]+ { + assert(yylloc.lexical_pos != UINT_MAX); + yylloc.lexical_pos += 1; yylval.text = strdupnew(yytext+1); if (gn_system_verilog()) { if (PPackage*pkg = pform_test_package_identifier(yylval.text)) { diff --git a/net_scope.cc b/net_scope.cc index 9fac014e8..76d29c601 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * * This source code is free software; you can redistribute it @@ -280,6 +280,7 @@ void NetScope::set_parameter(perm_string key, bool is_annotatable, ref.local_flag = param.local_flag; ref.overridable = param.overridable; ref.type_flag = param.type_flag; + ref.lexical_pos = param.lexical_pos; ivl_assert(param, !ref.range); ref.range = range_list; ref.val = 0; @@ -449,6 +450,17 @@ LineInfo NetScope::get_parameter_line_info(perm_string key) const return LineInfo(); } +unsigned NetScope::get_parameter_lexical_pos(perm_string key) const +{ + map::const_iterator idx; + + idx = parameters.find(key); + if (idx != parameters.end()) return idx->second.lexical_pos; + + // If we get here, assume an enumeration value. + return 0; +} + void NetScope::print_type(ostream&stream) const { switch (type_) { @@ -879,4 +891,3 @@ void NetScope::add_tie_lo(Design*des) connect(sig->pin(0), tie_lo_->pin(0)); } } - diff --git a/netlist.cc b/netlist.cc index 0ad54660f..80a2fd096 100644 --- a/netlist.cc +++ b/netlist.cc @@ -557,7 +557,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, const netranges_t&unpacked, ivl_type_t use_net_type) : NetObj(s, n, calculate_count(unpacked)), type_(t), port_type_(NOT_A_PORT), coerced_to_uwire_(false), - local_flag_(false), net_type_(use_net_type), + local_flag_(false), lexical_pos_(0), net_type_(use_net_type), discipline_(0), unpacked_dims_(unpacked), eref_count_(0), lref_count_(0) { @@ -580,7 +580,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, NetNet::NetNet(NetScope*s, perm_string n, Type t, ivl_type_t type) : NetObj(s, n, 1), type_(t), port_type_(NOT_A_PORT), coerced_to_uwire_(false), - local_flag_(false), net_type_(type), + local_flag_(false), lexical_pos_(0), net_type_(type), discipline_(0), eref_count_(0), lref_count_(0) { diff --git a/netlist.h b/netlist.h index 68a408899..d2a039e44 100644 --- a/netlist.h +++ b/netlist.h @@ -695,6 +695,9 @@ class NetNet : public NetObj, public PortType { PortType port_type() const; void port_type(PortType t); + unsigned lexical_pos() const { return lexical_pos_; } + void lexical_pos(unsigned lp) { lexical_pos_ = lp; } + // If this net net is a port (i.e. a *sub*port net of a module port) // its port index is number of the module it connects through int get_module_port_index() const; // -1 Not connected to port... @@ -819,6 +822,7 @@ class NetNet : public NetObj, public PortType { PortType port_type_ : 3; bool coerced_to_uwire_: 1; bool local_flag_: 1; + unsigned lexical_pos_; ivl_type_t net_type_; netuarray_t *array_type_ = nullptr; ivl_discipline_t discipline_; @@ -1239,6 +1243,8 @@ class NetScope : public Definitions, public Attrib { bool overridable = false; // Is it a type parameter bool type_flag = false; + // The lexical position of the declaration + unsigned lexical_pos = 0; // range constraints struct range_t*range; @@ -1257,6 +1263,8 @@ class NetScope : public Definitions, public Attrib { LineInfo get_parameter_line_info(perm_string name) const; + unsigned get_parameter_lexical_pos(perm_string name) const; + /* Module instance arrays are collected here for access during the multiple elaboration passes. */ typedef std::vector scope_vec_t; @@ -3421,6 +3429,9 @@ class NetEvent : public LineInfo { perm_string name() const; + unsigned lexical_pos() const { return lexical_pos_; } + void lexical_pos(unsigned lp) { lexical_pos_ = lp; } + bool local_flag() const { return local_flag_; } void local_flag(bool f) { local_flag_ = f; } @@ -3455,6 +3466,7 @@ class NetEvent : public LineInfo { private: perm_string name_; + unsigned lexical_pos_; bool local_flag_; // The NetScope class uses these to list the events. diff --git a/netmisc.h b/netmisc.h index d9da5af76..5ae10d6f9 100644 --- a/netmisc.h +++ b/netmisc.h @@ -49,6 +49,7 @@ struct symbol_search_results { par_val = 0; type = 0; eve = 0; + decl_after_use = 0; } inline bool is_scope() const { @@ -78,6 +79,11 @@ struct symbol_search_results { ivl_type_t type; // If this is a named event, ... NetEvent*eve; + // If a symbol was located but skipped because its lexical position + // is after the lexical position of the name being searched, it is + // stored here. If more than one such symbol is found, the first + // one is retained. + const LineInfo*decl_after_use; // Store bread crumbs of the search here. The path_tail is the parts // of the original path that were not found, or are after an object @@ -106,11 +112,12 @@ static inline bool test_function_return_value(const symbol_search_results&search } extern bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, - pform_name_t path, struct symbol_search_results*res, + pform_name_t path, unsigned lexical_pos, + struct symbol_search_results*res, NetScope*start_scope = nullptr, bool prefix_scope = false); extern bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, - const pform_scoped_name_t &path, + const pform_scoped_name_t &path, unsigned lexical_pos, struct symbol_search_results*res); /* diff --git a/parse.y b/parse.y index 61ea8aa81..f7bf42aef 100644 --- a/parse.y +++ b/parse.y @@ -22,6 +22,7 @@ # include "config.h" +# include # include # include "parse_misc.h" # include "compiler.h" @@ -115,12 +116,14 @@ static std::list*attributes_in_context = 0; (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + (Current).lexical_pos = YYRHSLOC (Rhs, 1).lexical_pos; \ (Current).text = YYRHSLOC (Rhs, 1).text; \ } else { \ (Current).first_line = YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = YYRHSLOC (Rhs, 0).last_column; \ (Current).last_line = YYRHSLOC (Rhs, 0).last_line; \ (Current).last_column = YYRHSLOC (Rhs, 0).last_column; \ + (Current).lexical_pos = YYRHSLOC (Rhs, 0).lexical_pos; \ (Current).text = YYRHSLOC (Rhs, 0).text; \ } \ } while (0) @@ -132,32 +135,39 @@ static std::list*attributes_in_context = 0; static const struct str_pair_t pull_strength = { IVL_DR_PULL, IVL_DR_PULL }; static const struct str_pair_t str_strength = { IVL_DR_STRONG, IVL_DR_STRONG }; -static std::list* make_port_list(char*id, std::list*udims, PExpr*expr) +static std::list* make_port_list(char*id, unsigned idn, + std::list*udims, + PExpr*expr) { std::list*tmp = new std::list; - tmp->push_back(pform_port_t(lex_strings.make(id), udims, expr)); + pform_ident_t tmp_name = { lex_strings.make(id), idn }; + tmp->push_back(pform_port_t(tmp_name, udims, expr)); delete[]id; return tmp; } static std::list* make_port_list(list*tmp, - char*id, std::list*udims, PExpr*expr) + char*id, unsigned idn, + std::list*udims, + PExpr*expr) { - tmp->push_back(pform_port_t(lex_strings.make(id), udims, expr)); + pform_ident_t tmp_name = { lex_strings.make(id), idn }; + tmp->push_back(pform_port_t(tmp_name, udims, expr)); delete[]id; return tmp; } -static std::list* list_from_identifier(char*id) +static std::list* list_from_identifier(char*id, unsigned idn) { - std::list*tmp = new std::list; - tmp->push_back(lex_strings.make(id)); + std::list*tmp = new std::list; + tmp->push_back({ lex_strings.make(id), idn }); delete[]id; return tmp; } -static std::list* list_from_identifier(list*tmp, char*id) +static std::list* list_from_identifier(list*tmp, + char*id, unsigned idn) { - tmp->push_back(lex_strings.make(id)); + tmp->push_back({ lex_strings.make(id), idn }); delete[]id; return tmp; } @@ -373,10 +383,10 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, PExpr *default_value, std::list *attributes) { - perm_string name = lex_strings.make(id); + pform_ident_t name = { lex_strings.make(id), loc.lexical_pos }; delete[] id; - Module::port_t *port = pform_module_port_reference(loc, name); + Module::port_t *port = pform_module_port_reference(loc, name.first); switch (port_type) { case NetNet::PINOUT: @@ -439,6 +449,8 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, char*text; std::list*perm_strings; + std::list*identifiers; + std::list*port_list; std::vector* tf_ports; @@ -652,10 +664,10 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type drive_strength drive_strength_opt dr_strength0 dr_strength1 %type udp_input_sym udp_output_sym %type udp_input_list udp_sequ_entry udp_comb_entry -%type udp_input_declaration_list +%type udp_input_declaration_list %type udp_entry_list udp_comb_entry_list udp_sequ_entry_list %type udp_body -%type udp_port_list +%type udp_port_list %type udp_port_decl udp_port_decls %type udp_initial udp_init_opt @@ -665,8 +677,9 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type event_variable label_opt class_declaration_endlabel_opt %type block_identifier_opt %type identifier_name -%type event_variable_list -%type list_of_identifiers loop_variables +%type event_variable_list +%type list_of_identifiers +%type loop_variables %type list_of_port_identifiers list_of_variable_port_identifiers %type net_decl_assigns @@ -1082,7 +1095,7 @@ class_new /* IEEE1800-2005 A.2.4 */ $$ = new_expr; } | K_new hierarchy_identifier - { PEIdent*tmpi = new PEIdent(*$2); + { PEIdent*tmpi = new PEIdent(*$2, @2.lexical_pos); FILE_NAME(tmpi, @2); PENewCopy*tmp = new PENewCopy(tmpi); FILE_NAME(tmp, @1); @@ -1770,7 +1783,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */ listassign_list; decl_assignment_t*tmp_assign = new decl_assignment_t; - tmp_assign->name = lex_strings.make($5); + tmp_assign->name = { lex_strings.make($5), @5.lexical_pos }; assign_list.push_back(tmp_assign); pform_make_var(@5, &assign_list, $4); } @@ -1913,7 +1926,7 @@ variable_decl_assignment /* IEEE1800-2005 A.2.3 */ } decl_assignment_t*tmp = new decl_assignment_t; - tmp->name = lex_strings.make($1); + tmp->name = { lex_strings.make($1), @1.lexical_pos }; if ($2) { tmp->index = *$2; delete $2; @@ -2497,7 +2510,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ NetNet::PortType use_port_type = $1; if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($3 == 0))) use_port_type = port_declaration_context.port_type; - list* port_list = make_port_list($4, $5, 0); + list* port_list = make_port_list($4, @4.lexical_pos, $5, 0); if (use_port_type == NetNet::PIMPLICIT) { yyerror(@1, "error: Missing task/function port direction."); @@ -3165,7 +3178,7 @@ delay_value_simple } } | IDENTIFIER - { PEIdent*tmp = new PEIdent(lex_strings.make($1)); + { PEIdent*tmp = new PEIdent(lex_strings.make($1), @1.lexical_pos); FILE_NAME(tmp, @1); $$ = tmp; delete[]$1; @@ -3961,13 +3974,13 @@ expr_primary $$ = tmp; } | K_this - { PEIdent*tmp = new PEIdent(perm_string::literal(THIS_TOKEN)); + { PEIdent*tmp = new PEIdent(perm_string::literal(THIS_TOKEN), UINT_MAX); FILE_NAME(tmp,@1); $$ = tmp; } | class_hierarchy_identifier - { PEIdent*tmp = new PEIdent(*$1); + { PEIdent*tmp = new PEIdent(*$1, @1.lexical_pos); FILE_NAME(tmp, @1); delete $1; $$ = tmp; @@ -4483,23 +4496,23 @@ hierarchy_identifier non-hierarchical names separated by ',' characters. */ list_of_identifiers : IDENTIFIER - { $$ = list_from_identifier($1); } + { $$ = list_from_identifier($1, @1.lexical_pos); } | list_of_identifiers ',' IDENTIFIER - { $$ = list_from_identifier($1, $3); } + { $$ = list_from_identifier($1, $3, @3.lexical_pos); } ; list_of_port_identifiers : IDENTIFIER dimensions_opt - { $$ = make_port_list($1, $2, 0); } + { $$ = make_port_list($1, @1.lexical_pos, $2, 0); } | list_of_port_identifiers ',' IDENTIFIER dimensions_opt - { $$ = make_port_list($1, $3, $4, 0); } + { $$ = make_port_list($1, $3, @3.lexical_pos, $4, 0); } ; list_of_variable_port_identifiers : IDENTIFIER dimensions_opt initializer_opt - { $$ = make_port_list($1, $2, $3); } + { $$ = make_port_list($1, @1.lexical_pos, $2, $3); } | list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt initializer_opt - { $$ = make_port_list($1, $3, $4, $5); } + { $$ = make_port_list($1, $3, @3.lexical_pos, $4, $5); } ; @@ -4631,7 +4644,7 @@ lpvalue } | class_hierarchy_identifier - { PEIdent*tmp = new PEIdent(*$1); + { PEIdent*tmp = new PEIdent(*$1, @1.lexical_pos); FILE_NAME(tmp, @1); $$ = tmp; delete $1; @@ -5418,7 +5431,7 @@ generate_block net_decl_assign : IDENTIFIER '=' expression { decl_assignment_t*tmp = new decl_assignment_t; - tmp->name = lex_strings.make($1); + tmp->name = { lex_strings.make($1), @1.lexical_pos }; tmp->expr.reset($3); delete[]$1; $$ = tmp; @@ -5727,7 +5740,7 @@ port_name named_pexpr_t*tmp = new named_pexpr_t; FILE_NAME(tmp, @$); tmp->name = lex_strings.make($3); - tmp->parm = new PEIdent(lex_strings.make($3), true); + tmp->parm = new PEIdent(lex_strings.make($3), @3.lexical_pos, true); FILE_NAME(tmp->parm, @3); delete[]$3; delete $1; @@ -5812,7 +5825,7 @@ port_reference pform_name_t pname; pname.push_back(ntmp); - PEIdent*wtmp = new PEIdent(pname); + PEIdent*wtmp = new PEIdent(pname, @1.lexical_pos); FILE_NAME(wtmp, @1); Module::port_t*ptmp = new Module::port_t; @@ -5835,7 +5848,7 @@ port_reference pform_name_t pname; pname.push_back(ntmp); - PEIdent*tmp = new PEIdent(pname); + PEIdent*tmp = new PEIdent(pname, @1.lexical_pos); FILE_NAME(tmp, @1); Module::port_t*ptmp = new Module::port_t; @@ -5848,7 +5861,7 @@ port_reference | IDENTIFIER '[' error ']' { yyerror(@1, "error: Invalid port bit select"); Module::port_t*ptmp = new Module::port_t; - PEIdent*wtmp = new PEIdent(lex_strings.make($1)); + PEIdent*wtmp = new PEIdent(lex_strings.make($1), @1.lexical_pos); FILE_NAME(wtmp, @1); ptmp->name = lex_strings.make($1); ptmp->expr.push_back(wtmp); @@ -5891,7 +5904,7 @@ dimensions net_variable : IDENTIFIER dimensions_opt - { perm_string name = lex_strings.make($1); + { pform_ident_t name = { lex_strings.make($1), @1.lexical_pos }; $$ = pform_makewire(@1, name, NetNet::IMPLICIT, $2); delete [] $1; } @@ -5921,9 +5934,9 @@ event_variable event_variable_list : event_variable - { $$ = list_from_identifier($1); } + { $$ = list_from_identifier($1, @1.lexical_pos); } | event_variable_list ',' event_variable - { $$ = list_from_identifier($1, $3); } + { $$ = list_from_identifier($1, $3, @3.lexical_pos); } ; specify_item @@ -6753,35 +6766,35 @@ statement_item /* This is roughly statement_item in the LRM */ $$ = tmp; } | K_TRIGGER hierarchy_identifier ';' - { PTrigger*tmp = pform_new_trigger(@2, 0, *$2); + { PTrigger*tmp = pform_new_trigger(@2, 0, *$2, @2.lexical_pos); delete $2; $$ = tmp; } | K_TRIGGER package_scope hierarchy_identifier { lex_in_package_scope(0); - PTrigger*tmp = pform_new_trigger(@3, $2, *$3); + PTrigger*tmp = pform_new_trigger(@3, $2, *$3, @3.lexical_pos); delete $3; $$ = tmp; } /* FIXME: Does this need support for package resolution like above? */ | K_NB_TRIGGER hierarchy_identifier ';' - { PNBTrigger*tmp = pform_new_nb_trigger(@2, 0, *$2); + { PNBTrigger*tmp = pform_new_nb_trigger(@2, 0, *$2, @2.lexical_pos); delete $2; $$ = tmp; } | K_NB_TRIGGER delay1 hierarchy_identifier ';' - { PNBTrigger*tmp = pform_new_nb_trigger(@3, $2, *$3); + { PNBTrigger*tmp = pform_new_nb_trigger(@3, $2, *$3, @3.lexical_pos); delete $3; $$ = tmp; } | K_NB_TRIGGER event_control hierarchy_identifier ';' - { PNBTrigger*tmp = pform_new_nb_trigger(@3, 0, *$3); + { PNBTrigger*tmp = pform_new_nb_trigger(@3, 0, *$3, @3.lexical_pos); delete $3; $$ = tmp; yywarn(@1, "sorry: ->> with event control is not currently supported."); } | K_NB_TRIGGER K_repeat '(' expression ')' event_control hierarchy_identifier ';' - { PNBTrigger*tmp = pform_new_nb_trigger(@7, 0, *$7); + { PNBTrigger*tmp = pform_new_nb_trigger(@7, 0, *$7, @7.lexical_pos); delete $7; $$ = tmp; yywarn(@1, "sorry: ->> with repeat event control is not currently supported."); @@ -7166,7 +7179,7 @@ udp_sequ_entry udp_initial : K_initial IDENTIFIER '=' number ';' { PExpr*etmp = new PENumber($4); - PEIdent*itmp = new PEIdent(lex_strings.make($2)); + PEIdent*itmp = new PEIdent(lex_strings.make($2), @2.lexical_pos); PAssign*atmp = new PAssign(itmp, etmp); FILE_NAME(atmp, @2); delete[]$2; @@ -7246,7 +7259,7 @@ udp_port_decl { $$ = pform_make_udp_input_ports($2); } | K_output IDENTIFIER ';' { perm_string pname = lex_strings.make($2); - PWire*pp = new PWire(pname, NetNet::IMPLICIT, NetNet::POUTPUT); + PWire*pp = new PWire(pname, @2.lexical_pos, NetNet::IMPLICIT, NetNet::POUTPUT); vector*tmp = new std::vector(1); (*tmp)[0] = pp; $$ = tmp; @@ -7254,7 +7267,7 @@ udp_port_decl } | K_reg IDENTIFIER ';' { perm_string pname = lex_strings.make($2); - PWire*pp = new PWire(pname, NetNet::REG, NetNet::PIMPLICIT); + PWire*pp = new PWire(pname, @2.lexical_pos, NetNet::REG, NetNet::PIMPLICIT); vector*tmp = new std::vector(1); (*tmp)[0] = pp; $$ = tmp; @@ -7262,7 +7275,7 @@ udp_port_decl } | K_output K_reg IDENTIFIER ';' { perm_string pname = lex_strings.make($3); - PWire*pp = new PWire(pname, NetNet::REG, NetNet::POUTPUT); + PWire*pp = new PWire(pname, @3.lexical_pos, NetNet::REG, NetNet::POUTPUT); vector*tmp = new std::vector(1); (*tmp)[0] = pp; $$ = tmp; @@ -7286,17 +7299,9 @@ udp_port_decls udp_port_list : IDENTIFIER - { std::list*tmp = new std::list; - tmp->push_back(lex_strings.make($1)); - delete[]$1; - $$ = tmp; - } + { $$ = list_from_identifier($1, @1.lexical_pos); } | udp_port_list ',' IDENTIFIER - { std::list*tmp = $1; - tmp->push_back(lex_strings.make($3)); - delete[]$3; - $$ = tmp; - } + { $$ = list_from_identifier($1, $3, @3.lexical_pos); } ; udp_reg_opt @@ -7305,17 +7310,9 @@ udp_reg_opt udp_input_declaration_list : K_input IDENTIFIER - { std::list*tmp = new std::list; - tmp->push_back(lex_strings.make($2)); - $$ = tmp; - delete[]$2; - } + { $$ = list_from_identifier($2, @2.lexical_pos); } | udp_input_declaration_list ',' K_input IDENTIFIER - { std::list*tmp = $1; - tmp->push_back(lex_strings.make($4)); - $$ = tmp; - delete[]$4; - } + { $$ = list_from_identifier($1, $4, @4.lexical_pos); } ; udp_primitive @@ -7343,7 +7340,7 @@ udp_primitive udp_body K_endprimitive label_opt { perm_string tmp2 = lex_strings.make($2); - perm_string tmp6 = lex_strings.make($6); + pform_ident_t tmp6 = { lex_strings.make($6) , @6.lexical_pos }; pform_make_udp(@2, tmp2, $5, tmp6, $7, $9, $12); check_end_label(@14, "primitive", $2, $14); delete[]$2; diff --git a/parse_misc.h b/parse_misc.h index 86e86314b..23547e85c 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -1,7 +1,7 @@ #ifndef IVL_parse_misc_H #define IVL_parse_misc_H /* - * Copyright (c) 1998-2022 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -34,6 +34,7 @@ struct vlltype { int first_column; int last_line; int last_column; + unsigned lexical_pos; const char*text; std::string get_fileline() const; }; diff --git a/pform.cc b/pform.cc index fb8b73534..99714f3af 100644 --- a/pform.cc +++ b/pform.cc @@ -708,23 +708,24 @@ PEIdent* pform_new_ident(const struct vlltype&loc, const pform_name_t&name) if (gn_system_verilog()) check_potential_imports(loc, name.front().name, false); - return new PEIdent(name); + return new PEIdent(name, loc.lexical_pos); } PTrigger* pform_new_trigger(const struct vlltype&loc, PPackage*pkg, - const pform_name_t&name) + const pform_name_t&name, unsigned lexical_pos) { if (gn_system_verilog()) check_potential_imports(loc, name.front().name, false); - PTrigger*tmp = new PTrigger(pkg, name); + PTrigger*tmp = new PTrigger(pkg, name, lexical_pos); FILE_NAME(tmp, loc); return tmp; } PNBTrigger* pform_new_nb_trigger(const struct vlltype&loc, const list*dly, - const pform_name_t&name) + const pform_name_t&name, + unsigned lexical_pos) { if (gn_system_verilog()) check_potential_imports(loc, name.front().name, false); @@ -735,7 +736,7 @@ PNBTrigger* pform_new_nb_trigger(const struct vlltype&loc, tmp_dly = dly->front(); } - PNBTrigger*tmp = new PNBTrigger(name, tmp_dly); + PNBTrigger*tmp = new PNBTrigger(name, lexical_pos, tmp_dly); FILE_NAME(tmp, loc); return tmp; } @@ -969,7 +970,7 @@ void pform_make_foreach_declarations(const struct vlltype&loc, if (cur->nil()) continue; decl_assignment_t*tmp_assign = new decl_assignment_t; - tmp_assign->name = lex_strings.make(*cur); + tmp_assign->name = { lex_strings.make(*cur), 0 }; assign_list.push_back(tmp_assign); } @@ -1376,7 +1377,7 @@ Module::port_t* pform_module_port_reference(const struct vlltype&loc, perm_string name) { Module::port_t*ptmp = new Module::port_t; - PEIdent*tmp = new PEIdent(name); + PEIdent*tmp = new PEIdent(name, loc.lexical_pos); FILE_NAME(tmp, loc); ptmp->name = name; ptmp->expr.push_back(tmp); @@ -1478,19 +1479,19 @@ void pform_endmodule(const char*name, bool inside_celldefine, pform_pop_scope(); } -void pform_genvars(const struct vlltype&li, list*names) +void pform_genvars(const struct vlltype&li, list*names) { - list::const_iterator cur; + list::const_iterator cur; for (cur = names->begin(); cur != names->end() ; *cur++) { PGenvar*genvar = new PGenvar(); FILE_NAME(genvar, li); if (pform_cur_generate) { - add_local_symbol(pform_cur_generate, *cur, genvar); - pform_cur_generate->genvars[*cur] = genvar; + add_local_symbol(pform_cur_generate, cur->first, genvar); + pform_cur_generate->genvars[cur->first] = genvar; } else { - add_local_symbol(pform_cur_module.front(), *cur, genvar); - pform_cur_module.front()->genvars[*cur] = genvar; + add_local_symbol(pform_cur_module.front(), cur->first, genvar); + pform_cur_module.front()->genvars[cur->first] = genvar; } } @@ -1855,7 +1856,7 @@ static void process_udp_table(PUdp*udp, list*table, } void pform_make_udp(const struct vlltype&loc, perm_string name, - list*parms, vector*decl, + list*parms, vector*decl, list*table, Statement*init_expr) { unsigned local_errors = 0; @@ -1896,13 +1897,13 @@ void pform_make_udp(const struct vlltype&loc, perm_string name, PWire* created by an input or output declaration. */ std::vector pins(parms->size()); std::vector pin_names(parms->size()); - { list::iterator cur; + { list::iterator cur; unsigned idx; for (cur = parms->begin(), idx = 0 ; cur != parms->end() ; ++ idx, ++ cur) { - pins[idx] = defs[*cur]; - pin_names[idx] = *cur; + pins[idx] = defs[cur->first]; + pin_names[idx] = cur->first; } } @@ -2048,27 +2049,27 @@ void pform_make_udp(const struct vlltype&loc, perm_string name, } void pform_make_udp(const struct vlltype&loc, perm_string name, - bool synchronous_flag, perm_string out_name, - PExpr*init_expr, list*parms, + bool synchronous_flag, const pform_ident_t&out_name, + PExpr*init_expr, list*parms, list*table) { std::vector pins(parms->size() + 1); /* Make the PWire for the output port. */ - pins[0] = new PWire(out_name, + pins[0] = new PWire(out_name.first, out_name.second, synchronous_flag? NetNet::REG : NetNet::WIRE, NetNet::POUTPUT); FILE_NAME(pins[0], loc); /* Make the PWire objects for the input ports. */ - { list::iterator cur; + { list::iterator cur; unsigned idx; for (cur = parms->begin(), idx = 1 ; cur != parms->end() ; idx += 1, ++ cur) { ivl_assert(loc, idx < pins.size()); - pins[idx] = new PWire(*cur, NetNet::WIRE, + pins[idx] = new PWire(cur->first, cur->second, NetNet::WIRE, NetNet::PINPUT); FILE_NAME(pins[idx], loc); } @@ -2151,21 +2152,19 @@ static void pform_set_net_range(PWire *wire, * This is invoked to make a named event. This is the declaration of * the event, and not necessarily the use of it. */ -static void pform_make_event(const struct vlltype&loc, perm_string name) +static void pform_make_event(const struct vlltype&loc, const pform_ident_t&name) { - PEvent*event = new PEvent(name); + PEvent*event = new PEvent(name.first, name.second); FILE_NAME(event, loc); - add_local_symbol(lexical_scope, name, event); - lexical_scope->events[name] = event; + add_local_symbol(lexical_scope, name.first, event); + lexical_scope->events[name.first] = event; } -void pform_make_events(const struct vlltype&loc, list*names) +void pform_make_events(const struct vlltype&loc, const list*names) { - list::iterator cur; - for (cur = names->begin() ; cur != names->end() ; ++ cur ) { - perm_string txt = *cur; - pform_make_event(loc, txt); + for (auto cur = names->begin() ; cur != names->end() ; ++ cur ) { + pform_make_event(loc, *cur); } delete names; @@ -2476,8 +2475,8 @@ void pform_make_pgassign_list(const struct vlltype&loc, * This syntax is not part of the IEEE1364-1995 standard, but is * approved by OVI as enhancement BTF-B14. */ -void pform_make_var_init(const struct vlltype&li, - perm_string name, PExpr*expr) +void pform_make_var_init(const struct vlltype&li, const pform_ident_t&name, + PExpr*expr) { if (! pform_at_module_level() && !gn_system_verilog()) { VLerror(li, "error: Variable declaration assignments are only " @@ -2486,7 +2485,7 @@ void pform_make_var_init(const struct vlltype&li, return; } - PEIdent*lval = new PEIdent(name); + PEIdent*lval = new PEIdent(name.first, name.second); FILE_NAME(lval, li); PAssign*ass = new PAssign(lval, expr, !gn_system_verilog(), true); FILE_NAME(ass, li); @@ -2514,8 +2513,10 @@ void pform_make_var_init(const struct vlltype&li, */ -static PWire* pform_get_or_make_wire(const struct vlltype&li, perm_string name, - NetNet::Type type, NetNet::PortType ptype, +static PWire* pform_get_or_make_wire(const struct vlltype&li, + const pform_ident_t&name, + NetNet::Type type, + NetNet::PortType ptype, PWSRType rt) { PWire *cur = 0; @@ -2523,7 +2524,7 @@ static PWire* pform_get_or_make_wire(const struct vlltype&li, perm_string name, // If this is not a full declaration check if there is already a signal // with the same name that can be extended. if (rt != SR_BOTH) - cur = pform_get_wire_in_scope(name); + cur = pform_get_wire_in_scope(name.first); // If the wire already exists but isn't yet fully defined, // carry on adding details. @@ -2547,10 +2548,10 @@ static PWire* pform_get_or_make_wire(const struct vlltype&li, perm_string name, // to the scope. Do not delete the old wire - it will // remain in the local symbol map. - cur = new PWire(name, type, ptype, rt); + cur = new PWire(name.first, name.second, type, ptype, rt); FILE_NAME(cur, li); - pform_put_wire_in_scope(name, cur); + pform_put_wire_in_scope(name.first, cur); return cur; } @@ -2567,7 +2568,7 @@ static PWire* pform_get_or_make_wire(const struct vlltype&li, perm_string name, * as is done for the old method. */ void pform_module_define_port(const struct vlltype&li, - perm_string name, + const pform_ident_t&name, NetNet::PortType port_kind, NetNet::Type type, data_type_t*vtype, @@ -2621,11 +2622,10 @@ void pform_module_define_port(const struct vlltype&li, * the variable/net. Other forms of pform_makewire ultimately call * this one to create the wire and stash it. */ -PWire *pform_makewire(const vlltype&li, perm_string name, NetNet::Type type, - std::list *indices) +PWire *pform_makewire(const vlltype&li, const pform_ident_t&name, + NetNet::Type type, std::list *indices) { - PWire*cur = pform_get_or_make_wire(li, name, type, NetNet::NOT_A_PORT, - SR_NET); + PWire*cur = pform_get_or_make_wire(li, name, type, NetNet::NOT_A_PORT, SR_NET); ivl_assert(li, cur); if (indices && !indices->empty()) @@ -2666,7 +2666,8 @@ void pform_makewire(const struct vlltype&li, if (type == NetNet::REG || type == NetNet::IMPLICIT_REG) { pform_make_var_init(li, first->name, expr); } else { - PEIdent*lval = new PEIdent(first->name); + PEIdent*lval = new PEIdent(first->name.first, + first->name.second); FILE_NAME(lval, li); PGAssign*ass = pform_make_pgassign(lval, expr, delay, str); FILE_NAME(ass, li); @@ -2735,10 +2736,8 @@ vector*pform_make_task_ports(const struct vlltype&loc, for (list::iterator cur = ports->begin(); cur != ports->end(); ++cur) { - const perm_string &name = cur->name; - - PWire*curw = pform_get_or_make_wire(loc, name, NetNet::IMPLICIT_REG, - pt, rt); + PWire*curw = pform_get_or_make_wire(loc, cur->name, + NetNet::IMPLICIT_REG, pt, rt); if (rt == SR_BOTH) curw->set_data_type(vtype); @@ -2797,7 +2796,7 @@ PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_ { pform_requires_sv(loc, "Increment/decrement operator"); - PExpr*lval = new PEIdent(lex_strings.make(name)); + PExpr*lval = new PEIdent(lex_strings.make(name), loc.lexical_pos); PExpr*rval = new PENumber(new verinum(1)); FILE_NAME(lval, loc); FILE_NAME(rval, loc); @@ -2813,7 +2812,7 @@ PExpr* pform_genvar_compressed(const struct vlltype &loc, const char *name, { pform_requires_sv(loc, "Compressed assignment operator"); - PExpr *lval = new PEIdent(lex_strings.make(name)); + PExpr *lval = new PEIdent(lex_strings.make(name), loc.lexical_pos); FILE_NAME(lval, loc); PExpr *expr; @@ -2954,6 +2953,7 @@ void pform_set_parameter(const struct vlltype&loc, parm->local_flag = is_local; parm->overridable = overridable; parm->type_flag = is_type; + parm->lexical_pos = loc.lexical_pos; scope->parameters[name] = parm; @@ -3170,8 +3170,7 @@ void pform_set_port_type(const struct vlltype&li, ; cur != ports->end() ; ++ cur ) { PWire *wire = pform_get_or_make_wire(li, cur->name, - NetNet::IMPLICIT, pt, - SR_PORT); + NetNet::IMPLICIT, pt, SR_PORT); pform_set_net_range(wire, vt, SR_PORT, attr); if (cur->udims) { @@ -3235,15 +3234,14 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, delete wires; } -vector* pform_make_udp_input_ports(list*names) +vector* pform_make_udp_input_ports(list*names) { vector*out = new vector(names->size()); unsigned idx = 0; - for (list::iterator cur = names->begin() + for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur ) { - perm_string txt = *cur; - PWire*pp = new PWire(txt, + PWire*pp = new PWire(cur->first, cur->second, NetNet::IMPLICIT, NetNet::PINPUT); (*out)[idx] = pp; diff --git a/pform.h b/pform.h index bb3dabfef..127f503f1 100644 --- a/pform.h +++ b/pform.h @@ -151,7 +151,7 @@ extern void pform_set_scope_timescale(const struct vlltype&loc); in an ansi style or non-ansi style declaration. In this case, we have everything needed to define the port, all in one place. */ extern void pform_module_define_port(const struct vlltype&li, - perm_string name, + const pform_ident_t&name, NetNet::PortType, NetNet::Type type, data_type_t*vtype, @@ -186,14 +186,14 @@ extern void pform_end_class_declaration(const struct vlltype&loc); extern bool pform_in_class(); extern void pform_make_udp(const struct vlltype&loc, perm_string name, - std::list*parms, + std::list*parms, std::vector*decl, std::list*table, Statement*init); extern void pform_make_udp(const struct vlltype&loc, perm_string name, - bool sync_flag, perm_string out_name, + bool sync_flag, const pform_ident_t&out_name, PExpr*sync_init, - std::list*parms, + std::list*parms, std::list*table); /* * Package related functions. @@ -230,10 +230,11 @@ extern void pform_add_modport_port(const struct vlltype&loc, extern PEIdent* pform_new_ident(const struct vlltype&loc, const pform_name_t&name); extern PTrigger* pform_new_trigger(const struct vlltype&loc, PPackage*pkg, - const pform_name_t&name); + const pform_name_t&name, unsigned lexical_pos); extern PNBTrigger* pform_new_nb_trigger(const struct vlltype&loc, const std::list*dly, - const pform_name_t&name); + const pform_name_t&name, + unsigned lexical_pos); /* * Enter/exit name scopes. The push_scope function pushes the scope @@ -272,7 +273,7 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val, * This function takes the list of names as new genvars to declare in * the current module or generate scope. */ -extern void pform_genvars(const struct vlltype&li, std::list*names); +extern void pform_genvars(const struct vlltype&li, std::list*names); /* * This flag is set by the parser to indicate the current generate block @@ -338,7 +339,8 @@ extern PForeach* pform_make_foreach(const struct vlltype&loc, * The makewire functions announce to the pform code new wires. These * go into a module that is currently opened. */ -extern PWire *pform_makewire(const struct vlltype&li, perm_string name, +extern PWire *pform_makewire(const struct vlltype&li, + const pform_ident_t&name, NetNet::Type type, std::list *indices); @@ -360,7 +362,8 @@ extern void pform_make_var(const struct vlltype&loc, bool is_const = false); extern void pform_make_var_init(const struct vlltype&li, - perm_string name, PExpr*expr); + const pform_ident_t&name, + PExpr*expr); /* This function is used when we have an incomplete port definition in a non-ansi style declaration. Look up the names of the wires, and set @@ -460,10 +463,10 @@ extern PProcess* pform_make_behavior(ivl_process_type_t, Statement*, std::list*attr); extern void pform_mc_translate_on(bool flag); -extern std::vector* pform_make_udp_input_ports(std::list*); +extern std::vector* pform_make_udp_input_ports(std::list*); extern void pform_make_events(const struct vlltype&loc, - std::list*names); + const std::list*names); /* * The makegate function creates a new gate (which need not have a * name) and connects it to the specified wires. @@ -537,7 +540,7 @@ extern void pform_discipline_potential(const struct vlltype&loc, const char*name extern void pform_discipline_flow(const struct vlltype&loc, const char*name); extern void pform_attach_discipline(const struct vlltype&loc, - ivl_discipline_t discipline, std::list*names); + ivl_discipline_t discipline, std::list*names); extern void pform_dump(std::ostream&out, const ivl_nature_s*); extern void pform_dump(std::ostream&out, const ivl_discipline_s*); diff --git a/pform_analog.cc b/pform_analog.cc index eb96cce61..b5058d655 100644 --- a/pform_analog.cc +++ b/pform_analog.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -47,10 +47,10 @@ PExpr* pform_make_branch_probe_expression(const struct vlltype&loc, char*name, char*n1, char*n2) { vector parms (2); - parms[0].parm = new PEIdent(lex_strings.make(n1)); + parms[0].parm = new PEIdent(lex_strings.make(n1), loc.lexical_pos); FILE_NAME(parms[0].parm, loc); - parms[1].parm = new PEIdent(lex_strings.make(n2)); + parms[1].parm = new PEIdent(lex_strings.make(n2), loc.lexical_pos); FILE_NAME(parms[1].parm, loc); PECallFunction*res = new PECallFunction(lex_strings.make(name), parms); @@ -62,7 +62,7 @@ PExpr* pform_make_branch_probe_expression(const struct vlltype&loc, char*name, char*branch_name) { vector parms (1); - parms[0].parm = new PEIdent(lex_strings.make(branch_name)); + parms[0].parm = new PEIdent(lex_strings.make(branch_name), loc.lexical_pos); FILE_NAME(parms[0].parm, loc); PECallFunction*res = new PECallFunction(lex_strings.make(name), parms); diff --git a/pform_disciplines.cc b/pform_disciplines.cc index 830222ab4..19cef6aa3 100644 --- a/pform_disciplines.cc +++ b/pform_disciplines.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -189,12 +189,12 @@ void pform_end_discipline(const struct vlltype&loc) * in the current lexical scope. */ void pform_attach_discipline(const struct vlltype&loc, - ivl_discipline_t discipline, list*names) + ivl_discipline_t discipline, list*names) { - for (list::iterator cur = names->begin() + for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur ) { - PWire* cur_net = pform_get_wire_in_scope(*cur); + PWire* cur_net = pform_get_wire_in_scope(cur->first); if (cur_net == 0) { /* Not declared yet, declare it now. */ cur_net = pform_makewire(loc, *cur, NetNet::WIRE, 0); diff --git a/pform_dump.cc b/pform_dump.cc index 1a43caaa5..9d714c3b6 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2023 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -374,7 +374,7 @@ void struct_member_t::pform_dump(ostream&out, unsigned indent) const for (list::iterator cur = names->begin() ; cur != names->end() ; ++cur) { decl_assignment_t*curp = *cur; - out << " " << curp->name; + out << " " << curp->name.first; } out << ";" << endl; } diff --git a/pform_package.cc b/pform_package.cc index 002bb359f..ea602c5cc 100644 --- a/pform_package.cc +++ b/pform_package.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2024 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -232,7 +232,7 @@ PExpr* pform_package_ident(const struct vlltype&loc, PPackage*pkg, pform_name_t*ident_name) { ivl_assert(loc, ident_name); - PEIdent*tmp = new PEIdent(pkg, *ident_name); + PEIdent*tmp = new PEIdent(pkg, *ident_name, loc.lexical_pos); FILE_NAME(tmp, loc); return tmp; } diff --git a/pform_pclass.cc b/pform_pclass.cc index b438f4cde..e9276a49a 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -86,12 +86,12 @@ void pform_class_property(const struct vlltype&loc, FILE_NAME(use_type, loc); } - pform_cur_class->type->properties[curp->name] + pform_cur_class->type->properties[curp->name.first] = class_type_t::prop_info_t(property_qual,use_type); - FILE_NAME(&pform_cur_class->type->properties[curp->name], loc); + FILE_NAME(&pform_cur_class->type->properties[curp->name.first], loc); if (PExpr*rval = curp->expr.release()) { - PExpr*lval = new PEIdent(curp->name); + PExpr*lval = new PEIdent(curp->name.first, curp->name.second); FILE_NAME(lval, loc); PAssign*tmp = new PAssign(lval, rval); FILE_NAME(tmp, loc); @@ -110,7 +110,7 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net) return; list*this_name = new list; - this_name->push_back(pform_port_t(perm_string::literal(THIS_TOKEN), 0, 0)); + this_name->push_back(pform_port_t({ perm_string::literal(THIS_TOKEN), 0 }, 0, 0)); vector*this_port = pform_make_task_ports(loc, NetNet::PINPUT, pform_cur_class->type, diff --git a/pform_types.h b/pform_types.h index fb7a03f8a..c35926662 100644 --- a/pform_types.h +++ b/pform_types.h @@ -49,6 +49,12 @@ class netclass_t; class netenum_t; typedef named named_pexpr_t; +/* + * The pform_ident_t holds the identifier name and its lexical position + * (the lexical_pos supplied by the scanner). + */ +typedef std::pair pform_ident_t; + /* * The pform_range_t holds variable dimensions for type * declarations. The two expressions are interpreted as the first and @@ -89,11 +95,11 @@ struct lgate : public LineInfo { * declarations. */ struct pform_port_t { - pform_port_t(perm_string n, std::list*ud, PExpr*e) + pform_port_t(pform_ident_t n, std::list*ud, PExpr*e) : name(n), udims(ud), expr(e) { } ~pform_port_t() { } - perm_string name; + pform_ident_t name; std::list*udims; PExpr*expr; }; @@ -130,7 +136,7 @@ struct name_component_t { }; struct decl_assignment_t { - perm_string name; + pform_ident_t name; std::listindex; std::unique_ptr expr; }; diff --git a/symbol_search.cc b/symbol_search.cc index d96f2a5f0..8479ff268 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2024 Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -38,7 +38,8 @@ using namespace std; */ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, - pform_name_t path, struct symbol_search_results*res, + pform_name_t path, unsigned lexical_pos, + struct symbol_search_results*res, NetScope*start_scope, bool prefix_scope) { assert(scope); @@ -68,8 +69,8 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, // recursively. Ideally, the result is a scope that we search // for the tail key, but there are other special cases as well. if (! path.empty()) { - bool flag = symbol_search(li, des, scope, path, res, start_scope, - prefix_scope); + bool flag = symbol_search(li, des, scope, path, lexical_pos, + res, start_scope, prefix_scope); if (! flag) return false; @@ -162,28 +163,40 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } if (NetNet*net = scope->find_signal(path_tail.name)) { - path.push_back(path_tail); - res->scope = scope; - res->net = net; - res->type = net->net_type(); - res->path_head = path; - return true; + if (prefix_scope || (net->lexical_pos() <= lexical_pos)) { + path.push_back(path_tail); + res->scope = scope; + res->net = net; + res->type = net->net_type(); + res->path_head = path; + return true; + } else if (!res->decl_after_use) { + res->decl_after_use = net; + } } if (NetEvent*eve = scope->find_event(path_tail.name)) { - path.push_back(path_tail); - res->scope = scope; - res->eve = eve; - res->path_head = path; - return true; + if (prefix_scope || (eve->lexical_pos() <= lexical_pos)) { + path.push_back(path_tail); + res->scope = scope; + res->eve = eve; + res->path_head = path; + return true; + } else if (!res->decl_after_use) { + res->decl_after_use = eve; + } } if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->type)) { - path.push_back(path_tail); - res->scope = scope; - res->par_val = par; - res->path_head = path; - return true; + if (prefix_scope || (scope->get_parameter_lexical_pos(path_tail.name) <= lexical_pos)) { + path.push_back(path_tail); + res->scope = scope; + res->par_val = par; + res->path_head = path; + return true; + } else if (!res->decl_after_use) { + res->decl_after_use = par; + } } // Static items are just normal signals and are found above. @@ -310,7 +323,7 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, - const pform_scoped_name_t &path, + const pform_scoped_name_t &path, unsigned lexical_pos, struct symbol_search_results *res) { NetScope *search_scope = scope; @@ -323,6 +336,6 @@ bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, prefix_scope = true; } - return symbol_search(li, des, search_scope, path.name, res, search_scope, - prefix_scope); + return symbol_search(li, des, search_scope, path.name, lexical_pos, + res, search_scope, prefix_scope); }