diff --git a/Makefile.in b/Makefile.in index dd9448b03..986427846 100644 --- a/Makefile.in +++ b/Makefile.in @@ -175,7 +175,8 @@ endif rm -rf autom4te.cache cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ -UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \ -UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ diff --git a/Statement.cc b/Statement.cc index 696ef44bd..1e587758a 100644 --- a/Statement.cc +++ b/Statement.cc @@ -299,20 +299,20 @@ PDoWhile::~PDoWhile() } PEventStatement::PEventStatement(const svector&ee) -: expr_(ee), statement_(0), search_funcs_(false) +: expr_(ee), statement_(0), always_sens_(false) { assert(expr_.count() > 0); } PEventStatement::PEventStatement(PEEvent*ee) -: expr_(1), statement_(0), search_funcs_(false) +: expr_(1), statement_(0), always_sens_(false) { expr_[0] = ee; } -PEventStatement::PEventStatement(bool search_funcs) -: statement_(0), search_funcs_(search_funcs) +PEventStatement::PEventStatement(bool always_sens) +: statement_(0), always_sens_(always_sens) { } diff --git a/Statement.h b/Statement.h index 91ed3828d..95d453195 100644 --- a/Statement.h +++ b/Statement.h @@ -405,8 +405,8 @@ class PEventStatement : public Statement { explicit PEventStatement(const svector&ee); explicit PEventStatement(PEEvent*ee); // Make an @* statement or make a special @* version with the items - // from functions added and ouputs removed for always_comb/latch. - explicit PEventStatement(bool search_funcs = false); + // from functions added and outputs removed for always_comb/latch. + explicit PEventStatement(bool always_sens = false); ~PEventStatement(); @@ -432,7 +432,7 @@ class PEventStatement : public Statement { private: svectorexpr_; Statement*statement_; - bool search_funcs_; + bool always_sens_; }; ostream& operator << (ostream&o, const PEventStatement&obj); diff --git a/cadpli/Makefile.in b/cadpli/Makefile.in index ba347b72c..8d9af5a51 100644 --- a/cadpli/Makefile.in +++ b/cadpli/Makefile.in @@ -59,7 +59,7 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f $(INCLUDE_PATH) $^ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status cd ..; ./config.status --file=cadpli/$@ diff --git a/driver-vpi/Makefile.in b/driver-vpi/Makefile.in index 579780a0a..d93d5a207 100644 --- a/driver-vpi/Makefile.in +++ b/driver-vpi/Makefile.in @@ -66,7 +66,7 @@ distclean: clean rm -f Makefile config.log cppcheck: main.c - cppcheck --enable=all -f $(INCLUDE_PATH) $^ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status cd ..; ./config.status --file=driver-vpi/$@ diff --git a/driver/Makefile.in b/driver/Makefile.in index b2ad7150c..7ec46f529 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -67,7 +67,7 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ -UYY_USER_INIT \ -UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \ -UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \ diff --git a/elab_expr.cc b/elab_expr.cc index 8517109b2..5edcf1a3b 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -2017,7 +2017,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li, // If the member type is a netvector_t, then it is a // vector of atom or scaler objects. For example, if the - // l-value expression is "foo.member[1][2]", + // l-value expression is "foo.member[1][2]", // then the member should be something like: // ... logic [h:l][m:n] member; // There should be index expressions index the vector diff --git a/elab_lval.cc b/elab_lval.cc index a37abd901..a24bfb39e 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com) * Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1265,7 +1265,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, if (const netvector_t*mem_vec = dynamic_cast(member->net_type)) { // If the member type is a netvector_t, then it is a // vector of atom or scaler objects. For example, if the - // l-value expression is "foo.member[1][2]", + // l-value expression is "foo.member[1][2]", // then the member should be something like: // ... logic [h:l][m:n] member; // There should be index expressions index the vector diff --git a/elab_scope.cc b/elab_scope.cc index b69bdc9f2..830d40003 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -453,7 +453,9 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) if (debug_scopes) { cerr << pclass->get_fileline() <<": elaborate_scope_class: " - << "Elaborate scope class " << pclass->pscope_name() << endl; + << "Elaborate scope class " << pclass->pscope_name() + << " within scope " << scope_path(scope) + << endl; } class_type_t*base_class = dynamic_cast (use_type->base_type); @@ -491,12 +493,24 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) use_class->set_definition_scope(scope); set_scope_timescale(des, class_scope, pclass); + // Elaborate enum types declared in the class. We need these + // now because enumeration constants can be used during scope + // elaboration. + if (debug_scopes) { + cerr << pclass->get_fileline() << ": elaborate_scope_class: " + << "Elaborate " << pclass->enum_sets.size() << " enumerations" + << " in class " << scope_path(class_scope) + << ", scope=" << scope_path(scope) << "." + << endl; + } + elaborate_scope_enumerations(des, class_scope, pclass->enum_sets); + // Collect the properties, elaborate them, and add them to the // elaborated class definition. for (map::iterator cur = use_type->properties.begin() ; cur != use_type->properties.end() ; ++ cur) { - ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope); + ivl_type_s*tmp = cur->second.type->elaborate_type(des, class_scope); ivl_assert(*pclass, tmp); if (debug_scopes) { cerr << pclass->get_fileline() << ": elaborate_scope_class: " @@ -699,7 +713,15 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope) collect_scope_parameters_(des, scope, parameters); collect_scope_localparams_(des, scope, localparams); + + if (debug_scopes) { + cerr << get_fileline() << ": PPackage::elaborate_scope: " + << "Elaborate " << enum_sets.size() << " enumerations" + << " in package scope " << scope_path(scope) << "." + << endl; + } elaborate_scope_enumerations(des, scope, enum_sets); + elaborate_scope_classes(des, scope, classes_lexical); elaborate_scope_funcs(des, scope, funcs); elaborate_scope_tasks(des, scope, tasks); @@ -736,6 +758,12 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, replace_scope_parameters_(scope, *this, replacements); + if (debug_scopes) { + cerr << get_fileline() << ": Module::elaborate_scope: " + << "Elaborate " << enum_sets.size() << " enumerations" + << " in scope " << scope_path(scope) << "." + << endl; + } elaborate_scope_enumerations(des, scope, enum_sets); assert(classes.size() == classes_lexical.size()); diff --git a/elaborate.cc b/elaborate.cc index 61ea115f4..bd950ba2f 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -29,6 +29,7 @@ # include # include +# include # include # include # include "pform.h" @@ -4221,13 +4222,13 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, * a value to change. */ extern bool synthesis; /* Synthesis flag from main.cc */ bool rem_out = false; - if (synthesis || search_funcs_) { + if (synthesis || always_sens_) { rem_out = true; } // If this is an always_comb/latch then we need an implicit T0 // trigger of the event expression. - if (search_funcs_) wa->set_t0_trigger(); - NexusSet*nset = enet->nex_input(rem_out, search_funcs_); + if (always_sens_) wa->set_t0_trigger(); + NexusSet*nset = enet->nex_input(rem_out, always_sens_); if (nset == 0) { cerr << get_fileline() << ": error: Unable to elaborate:" << endl; @@ -4237,6 +4238,8 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, } if (nset->size() == 0) { + if (always_sens_) return wa; + cerr << get_fileline() << ": warning: @* found no " "sensitivities so it will never trigger." << endl; @@ -4256,8 +4259,38 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(), ev, NetEvProbe::ANYEDGE, nset->size()); - for (unsigned idx = 0 ; idx < nset->size() ; idx += 1) - connect(nset->at(idx).lnk, pr->pin(idx)); + for (unsigned idx = 0 ; idx < nset->size() ; idx += 1) { + unsigned wid = nset->at(idx).wid; + unsigned vwid = nset->at(idx).lnk.nexus()->vector_width(); + // Is this a part select? + if (always_sens_ && (wid != vwid)) { + cerr << get_fileline() << ": sorry: constant " + "selects in always_* processes are not " + "currently supported (all bits will be " + "included)." << endl; +# if 0 + unsigned base = nset->at(idx).base; +// FIXME: Is this needed since you can select past the vector? + assert((base + wid) <= vwid); +cerr << get_fileline() << ": base = " << base << ", width = " << wid + << ", expr width = " << vwid << endl; +nset->at(idx).lnk.dump_link(cerr, 4); +cerr << endl; +// FIXME: Convert the link to the appropriate NetNet + netvector_t*tmp_vec = new netvector_t(IVL_VT_BOOL, vwid, 0); + NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::IMPLICIT, tmp_vec); + NetPartSelect*tmp = new NetPartSelect(sig, base, wid, NetPartSelect::VP); + des->add_node(tmp); + tmp->set_line(*this); +// FIXME: create a part select to get the correct bits to connect. + connect(tmp->pin(1), nset->at(idx).lnk); + connect(tmp->pin(0), pr->pin(idx)); +# endif + connect(nset->at(idx).lnk, pr->pin(idx)); + } else { + connect(nset->at(idx).lnk, pr->pin(idx)); + } + } delete nset; des->add_node(pr); @@ -6136,6 +6169,31 @@ class later_defparams : public elaborator_work_item_t { } }; +static ostream& operator<< (ostream&o, ivl_process_type_t t) +{ + switch (t) { + case IVL_PR_ALWAYS: + o << "always"; + break; + case IVL_PR_ALWAYS_COMB: + o << "always_comb"; + break; + case IVL_PR_ALWAYS_FF: + o << "always_ff"; + break; + case IVL_PR_ALWAYS_LATCH: + o << "always_latch"; + break; + case IVL_PR_INITIAL: + o << "initial"; + break; + case IVL_PR_FINAL: + o << "final"; + break; + } + return o; +} + bool Design::check_proc_delay() const { bool result = false; @@ -6145,55 +6203,66 @@ bool Design::check_proc_delay() const * a runtime infinite loop will happen. If we possibly have some * delay then print a warning that an infinite loop is possible. */ - if ((pr->type() == IVL_PR_ALWAYS) || - (pr->type() == IVL_PR_ALWAYS_COMB) || - (pr->type() == IVL_PR_ALWAYS_FF) || - (pr->type() == IVL_PR_ALWAYS_LATCH)) { + if (pr->type() == IVL_PR_ALWAYS) { DelayType dly_type = pr->statement()->delay_type(); if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) { - cerr << pr->get_fileline() << ": error: always" - << " statement does not have any delay." << endl; - cerr << pr->get_fileline() << ": : A runtime" - << " infinite loop will occur." << endl; + cerr << pr->get_fileline() << ": error: always " + "process does not have any delay." << endl; + cerr << pr->get_fileline() << ": : A runtime " + "infinite loop will occur." << endl; result = true; } else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) { - cerr << pr->get_fileline() << ": warning: always" - << " statement may not have any delay." << endl; - cerr << pr->get_fileline() << ": : A runtime" - << " infinite loop may be possible." << endl; + cerr << pr->get_fileline() << ": warning: always " + "process may not have any delay." << endl; + cerr << pr->get_fileline() << ": : A runtime " + << "infinite loop may be possible." << endl; + } + } + + // The always_comb/ff/latch processes have special delay rules + // that need to be checked. + if ((pr->type() == IVL_PR_ALWAYS_COMB) || + (pr->type() == IVL_PR_ALWAYS_FF) || + (pr->type() == IVL_PR_ALWAYS_LATCH)) { + const NetEvWait *wait = dynamic_cast (pr->statement()); + if (! wait) { + // The always_comb/latch processes have an event + // control added automatically by the compiler. + assert(pr->type() == IVL_PR_ALWAYS_FF); + cerr << pr->get_fileline() << ": error: the first " + "statement of an always_ff process must be " + "an event control statement." << endl; + result = true; + } else if (wait->statement()->delay_type(true) != NO_DELAY) { + cerr << pr->get_fileline() << ": error: there must "; + + if (pr->type() == IVL_PR_ALWAYS_FF) { + cerr << "only be a single event control and " + "no blocking delays in an always_ff " + "process."; + } else { + cerr << "be no event controls or blocking " + "delays in an " << pr->type() + << " process."; + } + cerr << endl; + result = true; } - // The always_comb/ff/latch processes also have special - // delay rules that need to be checked. - if ((pr->type() == IVL_PR_ALWAYS_COMB) || - (pr->type() == IVL_PR_ALWAYS_FF) || - (pr->type() == IVL_PR_ALWAYS_LATCH)) { - const NetEvWait *wait = dynamic_cast (pr->statement()); - if (! wait) { - // The always_comb/latch processes have an event - // control added automatically by the compiler. - assert(pr->type() == IVL_PR_ALWAYS_FF); - cerr << pr->get_fileline() << ": error: the " - << "first statement of an always_ff must " - << "be an event control." << endl; - result = true; - } else if (wait->statement()->delay_type(true) != NO_DELAY) { - cerr << pr->get_fileline() << ": error: there " - << "must "; - - if (pr->type() == IVL_PR_ALWAYS_FF) { - cerr << "only be a single event control " - << "and no blocking delays in an " - << "always_ff process."; - } else { - cerr << "be no event controls or blocking " - << "delays in an always_comb/latch " - << "process."; - } - cerr << endl; + if ((pr->type() != IVL_PR_ALWAYS_FF) && + (wait->nevents() == 0)) { + if (pr->type() == IVL_PR_ALWAYS_LATCH) { + cerr << pr->get_fileline() << ": error: " + "always_latch process has no event " + "control." << endl; result = true; + } else { + assert(pr->type() == IVL_PR_ALWAYS_COMB); + cerr << pr->get_fileline() << ": warning: " + "always_comb process has no " + "sensitivities." << endl; } } } diff --git a/ivlpp/Makefile.in b/ivlpp/Makefile.in index 07053c298..2d8de7919 100644 --- a/ivlpp/Makefile.in +++ b/ivlpp/Makefile.in @@ -60,7 +60,7 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f $(INCLUDE_PATH) $^ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status cd ..; ./config.status --file=ivlpp/$@ diff --git a/libveriuser/Makefile.in b/libveriuser/Makefile.in index 989d7c980..461b4a526 100644 --- a/libveriuser/Makefile.in +++ b/libveriuser/Makefile.in @@ -76,8 +76,9 @@ distclean: clean rm -f config.h stamp-config-h cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ - --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ + --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in cd ..; ./config.status --file=libveriuser/$@ diff --git a/net_nex_input.cc b/net_nex_input.cc index 38e7e148a..9786193d1 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2019 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 @@ -19,8 +19,8 @@ # include "config.h" -# include - +# include +# include # include # include # include "compiler.h" @@ -43,13 +43,13 @@ NexusSet* NetProc::nex_input(bool, bool) const return new NexusSet; } -NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { if (items_[idx]==0) continue; - NexusSet*tmp = items_[idx]->nex_input(rem_out, search_funcs); + NexusSet*tmp = items_[idx]->nex_input(rem_out, always_sens); if (tmp == 0) continue; result->add(*tmp); @@ -58,25 +58,25 @@ NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetEBinary::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetEBinary::nex_input(bool rem_out, bool always_sens) const { - NexusSet*result = left_->nex_input(rem_out, search_funcs); - NexusSet*tmp = right_->nex_input(rem_out, search_funcs); + NexusSet*result = left_->nex_input(rem_out, always_sens); + NexusSet*tmp = right_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEConcat::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetEConcat::nex_input(bool rem_out, bool always_sens) const { if (parms_[0] == NULL) return new NexusSet; - NexusSet*result = parms_[0]->nex_input(rem_out, search_funcs); + NexusSet*result = parms_[0]->nex_input(rem_out, always_sens); for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { if (parms_[idx] == NULL) { delete result; return new NexusSet; } - NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -136,14 +136,27 @@ NexusSet* NetEScope::nex_input(bool, bool) const return new NexusSet; } -NexusSet* NetESelect::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetESelect::nex_input(bool rem_out, bool always_sens) const { - NexusSet*result = base_? base_->nex_input(rem_out, search_funcs) : new NexusSet(); - NexusSet*tmp = expr_->nex_input(rem_out, search_funcs); + NexusSet*result = base_? base_->nex_input(rem_out, always_sens) : new NexusSet(); + NexusSet*tmp = expr_->nex_input(rem_out, always_sens); + bool const_select = result->size() == 0; + if (always_sens && const_select) { + if (NetEConst *val = dynamic_cast (base_)) { + assert(select_type() == IVL_SEL_OTHER); + if (NetESignal *sig = dynamic_cast (expr_)) { + delete tmp; + tmp = sig->nex_input_base(rem_out, always_sens, val->value().as_unsigned(), expr_width()); + } else { + cerr << get_fileline() << ": Sorry, cannot determine the sensitivity " + << "for the select of " << *expr_ << ", using all bits." << endl; + } + } + } result->add(*tmp); delete tmp; /* See the comment for NetESignal below. */ - if (base_ && warn_sens_entire_vec) { + if (base_ && ! always_sens && warn_sens_entire_vec) { cerr << get_fileline() << ": warning: @* is sensitive to all " "bits in '" << *expr_ << "'." << endl; } @@ -153,7 +166,7 @@ NexusSet* NetESelect::nex_input(bool rem_out, bool search_funcs) const /* * The $fread, etc. system functions can have NULL arguments. */ -NexusSet* NetESFunc::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetESFunc::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; @@ -161,7 +174,7 @@ NexusSet* NetESFunc::nex_input(bool rem_out, bool search_funcs) const for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { if (parms_[idx]) { - NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -175,7 +188,12 @@ NexusSet* NetEShallowCopy::nex_input(bool, bool) const return new NexusSet; } -NexusSet* NetESignal::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetESignal::nex_input(bool rem_out, bool always_sens) const +{ + return nex_input_base(rem_out, always_sens, 0, 0); +} + +NexusSet* NetESignal::nex_input_base(bool rem_out, bool always_sens, unsigned base, unsigned width) const { /* * This is not what I would expect for the various selects (bit, @@ -183,55 +201,76 @@ NexusSet* NetESignal::nex_input(bool rem_out, bool search_funcs) const * instead of building the appropriate select and then using it * as the trigger. Other simulators also add everything. */ + bool const_select = false; + unsigned const_word = 0; NexusSet*result = new NexusSet; /* Local signals are not added to the sensitivity list. */ if (net_->local_flag()) return result; /* If we have an array index add it to the sensitivity list. */ if (word_) { NexusSet*tmp; - tmp = word_->nex_input(rem_out, search_funcs); + tmp = word_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; - if (warn_sens_entire_arr) { + if (!always_sens && warn_sens_entire_arr) { cerr << get_fileline() << ": warning: @* is sensitive to all " << net_->unpacked_count() << " words in array '" << name() << "'." << endl; } + if (always_sens) if (NetEConst *val = dynamic_cast (word_)) { + const_select = true; + const_word = val->value().as_unsigned(); + } + } + + if ((base == 0) && (width == 0)) width = net_->vector_width(); + + if (const_select) { + result->add(net_->pin(const_word).nexus(), base, width); + } else { + for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1) + result->add(net_->pin(idx).nexus(), base, width); } - for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1) - result->add(net_->pin(idx).nexus(), 0, net_->vector_width()); return result; } -NexusSet* NetETernary::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetETernary::nex_input(bool rem_out, bool always_sens) const { NexusSet*tmp; - NexusSet*result = cond_->nex_input(rem_out, search_funcs); + NexusSet*result = cond_->nex_input(rem_out, always_sens); - tmp = true_val_->nex_input(rem_out, search_funcs); + tmp = true_val_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; - tmp = false_val_->nex_input(rem_out, search_funcs); + tmp = false_val_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEUFunc::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetEUFunc::nex_input(bool rem_out, bool always_sens) const { + static set func_set; NexusSet*result = new NexusSet; + string func_name; + + // Avoid recursive function calls. + func_name = scope_->fullname().peek_name(); + if (! scope_->parent()) func_set.clear(); + if (! func_set.insert(func_name).second) return result; + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { - NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } - if (search_funcs) { + if (always_sens) { NetFuncDef*func = func_->func_def(); - NexusSet*tmp = func->proc()->nex_input(rem_out, search_funcs); + NexusSet*tmp = func->proc()->nex_input(rem_out, always_sens); // Remove the function inputs NexusSet*in = new NexusSet; for (unsigned idx = 0 ; idx < func->port_count() ; idx += 1) { @@ -249,9 +288,9 @@ NexusSet* NetEUFunc::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetEUnary::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetEUnary::nex_input(bool rem_out, bool always_sens) const { - return expr_->nex_input(rem_out, search_funcs); + return expr_->nex_input(rem_out, always_sens); } NexusSet* NetAlloc::nex_input(bool, bool) const @@ -259,18 +298,18 @@ NexusSet* NetAlloc::nex_input(bool, bool) const return new NexusSet; } -NexusSet* NetAssign_::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetAssign_::nex_input(bool rem_out, bool always_sens) const { assert(! nest_); NexusSet*result = new NexusSet; if (word_) { - NexusSet*tmp = word_->nex_input(rem_out, search_funcs); + NexusSet*tmp = word_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } if (base_) { - NexusSet*tmp = base_->nex_input(rem_out, search_funcs); + NexusSet*tmp = base_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -278,12 +317,12 @@ NexusSet* NetAssign_::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetAssignBase::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetAssignBase::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; // For the deassign and release statements there is no R-value. if (rval_) { - NexusSet*tmp = rval_->nex_input(rem_out, search_funcs); + NexusSet*tmp = rval_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -292,7 +331,7 @@ NexusSet* NetAssignBase::nex_input(bool rem_out, bool search_funcs) const particular, index expressions are statement inputs as well, so should be addressed here. */ for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) { - NexusSet*tmp = cur->nex_input(rem_out, search_funcs); + NexusSet*tmp = cur->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -317,11 +356,11 @@ NexusSet* NetAssignBase::nex_input(bool rem_out, bool search_funcs) const * In this example, "t" should not be in the input set because it is * used by the sequence as a temporary value. */ -NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetBlock::nex_input(bool rem_out, bool always_sens) const { if (last_ == 0) return new NexusSet; - if (! search_funcs && (type_ != SEQU)) { + if (! always_sens && (type_ != SEQU)) { cerr << get_fileline() << ": internal error: Sorry, " << "I don't know how to synthesize fork/join blocks." << endl; @@ -336,7 +375,7 @@ NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const do { /* Get the inputs for the current statement. */ - NexusSet*tmp = cur->nex_input(rem_out, search_funcs); + NexusSet*tmp = cur->nex_input(rem_out, always_sens); /* Add the current input set to the accumulated input set. */ result->add(*tmp); @@ -363,9 +402,9 @@ NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const * the inputs to all the guards, and the inputs to all the guarded * statements. */ -NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetCase::nex_input(bool rem_out, bool always_sens) const { - NexusSet*result = expr_->nex_input(rem_out, search_funcs); + NexusSet*result = expr_->nex_input(rem_out, always_sens); for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { @@ -373,7 +412,7 @@ NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const if (items_[idx].statement == 0) continue; - NexusSet*tmp = items_[idx].statement->nex_input(rem_out, search_funcs); + NexusSet*tmp = items_[idx].statement->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; @@ -381,7 +420,7 @@ NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const case is special and is identified by a null guard. The default guard obviously has no input. */ if (items_[idx].guard) { - tmp = items_[idx].guard->nex_input(rem_out, search_funcs); + tmp = items_[idx].guard->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -390,18 +429,18 @@ NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetCondit::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetCondit::nex_input(bool rem_out, bool always_sens) const { - NexusSet*result = expr_->nex_input(rem_out, search_funcs); + NexusSet*result = expr_->nex_input(rem_out, always_sens); if (if_ != 0) { - NexusSet*tmp = if_->nex_input(rem_out, search_funcs); + NexusSet*tmp = if_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } if (else_ != 0) { - NexusSet*tmp = else_->nex_input(rem_out, search_funcs); + NexusSet*tmp = else_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -414,12 +453,12 @@ NexusSet* NetDisable::nex_input(bool, bool) const return new NexusSet; } -NexusSet* NetDoWhile::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetDoWhile::nex_input(bool rem_out, bool always_sens) const { - NexusSet*result = cond_->nex_input(rem_out, search_funcs); + NexusSet*result = cond_->nex_input(rem_out, always_sens); if (proc_) { - NexusSet*tmp = proc_->nex_input(rem_out, search_funcs); + NexusSet*tmp = proc_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -432,12 +471,12 @@ NexusSet* NetEvTrig::nex_input(bool, bool) const return new NexusSet; } -NexusSet* NetEvWait::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetEvWait::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; if (statement_) { - NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + NexusSet*tmp = statement_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -445,12 +484,12 @@ NexusSet* NetEvWait::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetForever::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetForever::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; if (statement_) { - NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + NexusSet*tmp = statement_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -458,30 +497,30 @@ NexusSet* NetForever::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetForLoop::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetForLoop::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; if (init_expr_) { - NexusSet*tmp = init_expr_->nex_input(rem_out, search_funcs); + NexusSet*tmp = init_expr_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } if (condition_) { - NexusSet*tmp = condition_->nex_input(rem_out, search_funcs); + NexusSet*tmp = condition_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } if (step_statement_) { - NexusSet*tmp = step_statement_->nex_input(rem_out, search_funcs); + NexusSet*tmp = step_statement_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } if (statement_) { - NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + NexusSet*tmp = statement_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -512,12 +551,12 @@ NexusSet* NetFree::nex_input(bool, bool) const * include the input set of the because it does not affect the * result. The statement can be omitted. */ -NexusSet* NetPDelay::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetPDelay::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; if (statement_) { - NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + NexusSet*tmp = statement_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -525,12 +564,12 @@ NexusSet* NetPDelay::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetRepeat::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetRepeat::nex_input(bool rem_out, bool always_sens) const { - NexusSet*result = expr_->nex_input(rem_out, search_funcs); + NexusSet*result = expr_->nex_input(rem_out, always_sens); if (statement_) { - NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + NexusSet*tmp = statement_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -541,7 +580,7 @@ NexusSet* NetRepeat::nex_input(bool rem_out, bool search_funcs) const /* * The $display, etc. system tasks can have NULL arguments. */ -NexusSet* NetSTask::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetSTask::nex_input(bool rem_out, bool always_sens) const { NexusSet*result = new NexusSet; @@ -549,7 +588,7 @@ NexusSet* NetSTask::nex_input(bool rem_out, bool search_funcs) const for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { if (parms_[idx]) { - NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } @@ -568,12 +607,12 @@ NexusSet* NetUTask::nex_input(bool, bool) const return new NexusSet; } -NexusSet* NetWhile::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetWhile::nex_input(bool rem_out, bool always_sens) const { - NexusSet*result = cond_->nex_input(rem_out, search_funcs); + NexusSet*result = cond_->nex_input(rem_out, always_sens); if (proc_) { - NexusSet*tmp = proc_->nex_input(rem_out, search_funcs); + NexusSet*tmp = proc_->nex_input(rem_out, always_sens); result->add(*tmp); delete tmp; } diff --git a/netlist.h b/netlist.h index 17602388e..6b85a5a2a 100644 --- a/netlist.h +++ b/netlist.h @@ -2054,7 +2054,7 @@ class NetExpr : public LineInfo { // Get the Nexus that are the input to this // expression. Normally this descends down to the reference to // a signal that reads from its input. - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const =0; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const =0; // Return a version of myself that is structural. This is used // for converting expressions to gates. The arguments are: @@ -2097,7 +2097,7 @@ class NetEArrayPattern : public NetExpr { void dump(ostream&) const; NetEArrayPattern* dup_expr() const; - NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; private: std::vector items_; @@ -2130,7 +2130,7 @@ class NetEConst : public NetExpr { virtual NetEConst* dup_expr() const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*); - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; @@ -2202,7 +2202,7 @@ class NetECReal : public NetExpr { virtual NetECReal* dup_expr() const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*); - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; @@ -2646,7 +2646,7 @@ class NetProc : public virtual LineInfo { // Find the nexa that are input by the statement. This is used // for example by @* to find the inputs to the process for the // sensitivity list. - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; // Find the nexa that are set by the statement. Add the output // values to the set passed as a parameter. @@ -2754,7 +2754,7 @@ class NetAlloc : public NetProc { const NetScope* scope() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2863,7 +2863,7 @@ class NetAssign_ { // being outputs. For example foo[idx] = ... is the l-value // (NetAssign_ object) with a foo l-value and the input // expression idx. - NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; // Figuring out nex_output to process ultimately comes down to // this method. @@ -2911,7 +2911,7 @@ class NetAssignBase : public NetProc { void set_delay(NetExpr*); const NetExpr* get_delay() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&o); @@ -3029,7 +3029,7 @@ class NetBlock : public NetProc { // for sequential blocks. void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); @@ -3073,7 +3073,7 @@ class NetCase : public NetProc { inline const NetExpr*expr(unsigned idx) const { return items_[idx].guard;} inline const NetProc*stat(unsigned idx) const { return items_[idx].statement; } - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&out); bool synth_async(Design*des, NetScope*scope, @@ -3153,7 +3153,7 @@ class NetCondit : public NetProc { bool emit_recurse_if(struct target_t*) const; bool emit_recurse_else(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&o); bool is_asynchronous(); @@ -3244,7 +3244,7 @@ class NetDisable : public NetProc { const NetScope*target() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3275,7 +3275,7 @@ class NetDoWhile : public NetProc { void emit_proc_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3409,7 +3409,7 @@ class NetEvTrig : public NetProc { const NetEvent*event() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3451,7 +3451,7 @@ class NetEvWait : public NetProc { // process? This method checks. virtual bool is_synchronous(); - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&out); virtual bool synth_async(Design*des, NetScope*scope, @@ -3537,7 +3537,7 @@ class NetForever : public NetProc { void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3561,7 +3561,7 @@ class NetForLoop : public NetProc { void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3599,7 +3599,7 @@ class NetFree : public NetProc { const NetScope* scope() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3664,7 +3664,7 @@ class NetPDelay : public NetProc { uint64_t delay() const; const NetExpr*expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; @@ -3692,7 +3692,7 @@ class NetRepeat : public NetProc { const NetExpr*expr() const; void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3746,7 +3746,7 @@ class NetSTask : public NetProc { const NetExpr* parm(unsigned idx) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3807,7 +3807,7 @@ class NetELast : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetELast*dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; private: NetNet*sig_; @@ -3836,7 +3836,7 @@ class NetEUFunc : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEUFunc*dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual NetExpr* eval_tree(); virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3872,7 +3872,7 @@ class NetEAccess : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEAccess*dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; private: NetBranch*branch_; @@ -3894,7 +3894,7 @@ class NetUTask : public NetProc { const NetScope* task() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3920,7 +3920,7 @@ class NetWhile : public NetProc { void emit_proc_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -4064,7 +4064,7 @@ class NetEBinary : public NetExpr { virtual NetExpr* eval_tree(); virtual NetExpr* evaluate_function(const LineInfo&loc, map&ctx) const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -4318,7 +4318,7 @@ class NetEConcat : public NetExpr { NetExpr* parm(unsigned idx) const { return parms_[idx]; } virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual bool has_width() const; virtual NetEConcat* dup_expr() const; virtual NetEConst* eval_tree(); @@ -4366,7 +4366,7 @@ class NetESelect : public NetExpr { // sub-expression. virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; virtual NetEConst* eval_tree(); @@ -4395,7 +4395,7 @@ class NetEEvent : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEEvent* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void dump(ostream&os) const; @@ -4418,7 +4418,7 @@ class NetENetenum : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetENetenum* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void dump(ostream&os) const; @@ -4442,7 +4442,7 @@ class NetENew : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetENew* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void dump(ostream&os) const; @@ -4464,7 +4464,7 @@ class NetENull : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetENull* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void dump(ostream&os) const; }; @@ -4490,7 +4490,7 @@ class NetEProperty : public NetExpr { ivl_variable_type_t expr_type() const; virtual void expr_scan(struct expr_scan_t*) const; virtual NetEProperty* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void dump(ostream&os) const; @@ -4515,7 +4515,7 @@ class NetEScope : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEScope* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void dump(ostream&os) const; @@ -4549,7 +4549,7 @@ class NetESFunc : public NetExpr { map&ctx) const; virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual const netenum_t* enumeration() const; virtual void dump(ostream&) const; @@ -4683,7 +4683,7 @@ class NetEShallowCopy : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEShallowCopy* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void dump(ostream&os) const; @@ -4715,7 +4715,7 @@ class NetETernary : public NetExpr { virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*root); @@ -4770,7 +4770,7 @@ class NetEUnary : public NetExpr { virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -4846,7 +4846,9 @@ class NetESignal : public NetExpr { virtual NetESignal* dup_expr() const; NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root); - NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + NexusSet* nex_input(bool rem_out = true, bool always_sens = false) const; + NexusSet* nex_input_base(bool rem_out, bool always_sens, + unsigned base, unsigned width) const; const netenum_t*enumeration() const; virtual NetExpr*evaluate_function(const LineInfo&loc, diff --git a/parse.y b/parse.y index 822f02e83..602981987 100644 --- a/parse.y +++ b/parse.y @@ -864,7 +864,7 @@ class_item /* IEEE1800-2005: A.1.8 */ current_function = 0; } - /* Class properties... */ + /* IEEE1800-2017: A.1.9 Class items: Class properties... */ | property_qualifier_opt data_type list_of_variable_decl_assignments ';' { pform_class_property(@2, $1, $2, $3); } @@ -872,7 +872,15 @@ class_item /* IEEE1800-2005: A.1.8 */ | K_const class_item_qualifier_opt data_type list_of_variable_decl_assignments ';' { pform_class_property(@1, $2 | property_qualifier_t::make_const(), $3, $4); } - /* Class methods... */ + /* IEEEE1800-2017: A.1.9 Class items: class_item ::= { property_qualifier} data_declaration */ + + | property_qualifier_opt K_typedef data_type IDENTIFIER dimensions_opt ';' + { perm_string name = lex_strings.make($4); + delete[]$4; + pform_set_typedef(name, $3, $5); + } + + /* IEEE1800-1017: A.1.9 Class items: Class methods... */ | method_qualifier_opt task_declaration { /* The task_declaration rule puts this into the class */ } diff --git a/pform_pclass.cc b/pform_pclass.cc index a3b7df4f0..c294f6000 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -67,6 +67,10 @@ void pform_class_property(const struct vlltype&loc, { assert(pform_cur_class); + if (enum_type_t*enum_set = dynamic_cast(data_type)) { + pform_cur_class->enum_sets .insert(enum_set); + } + // Add the non-static properties to the class type // object. Unwind the list of names to make a map of name to // type. diff --git a/tgt-blif/Makefile.in b/tgt-blif/Makefile.in index 850666ad0..51d204c78 100644 --- a/tgt-blif/Makefile.in +++ b/tgt-blif/Makefile.in @@ -58,7 +58,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.cc) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-fpga/Makefile.in b/tgt-fpga/Makefile.in index 72546b5a6..2a3310246 100644 --- a/tgt-fpga/Makefile.in +++ b/tgt-fpga/Makefile.in @@ -61,7 +61,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-null/Makefile.in b/tgt-null/Makefile.in index c414f2fbe..0bf2434d9 100644 --- a/tgt-null/Makefile.in +++ b/tgt-null/Makefile.in @@ -56,7 +56,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-pal/Makefile.in b/tgt-pal/Makefile.in index 291acac9d..f3b06cb81 100644 --- a/tgt-pal/Makefile.in +++ b/tgt-pal/Makefile.in @@ -55,7 +55,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-pcb/Makefile.in b/tgt-pcb/Makefile.in index 228ede553..79fb9531f 100644 --- a/tgt-pcb/Makefile.in +++ b/tgt-pcb/Makefile.in @@ -61,7 +61,8 @@ distclean: clean rm -f stamp-pcb_config-h pcb_config.h cppcheck: $(O:.o=.cc) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ -UYY_USER_INIT \ -UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \ -UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \ diff --git a/tgt-pcb/fp.y b/tgt-pcb/fp.y index 60be85032..111c5f7ba 100644 --- a/tgt-pcb/fp.y +++ b/tgt-pcb/fp.y @@ -1,5 +1,5 @@ -%pure-parser +%define api.pure %parse-param {const char*file_path} %{ diff --git a/tgt-sizer/Makefile.in b/tgt-sizer/Makefile.in index dad317786..370198ad9 100644 --- a/tgt-sizer/Makefile.in +++ b/tgt-sizer/Makefile.in @@ -56,7 +56,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.cc) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-stub/Makefile.in b/tgt-stub/Makefile.in index c136ca37c..f00597ae3 100644 --- a/tgt-stub/Makefile.in +++ b/tgt-stub/Makefile.in @@ -57,7 +57,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-verilog/Makefile.in b/tgt-verilog/Makefile.in index 40d6c27d9..b06b4f889 100644 --- a/tgt-verilog/Makefile.in +++ b/tgt-verilog/Makefile.in @@ -55,7 +55,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-vhdl/Makefile.in b/tgt-vhdl/Makefile.in index b86c11a98..3d21f057e 100644 --- a/tgt-vhdl/Makefile.in +++ b/tgt-vhdl/Makefile.in @@ -60,7 +60,8 @@ distclean: clean rm -f stamp-vhdl_config-h vhdl_config.h cppcheck: $(O:.o=.cc) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-vlog95/Makefile.in b/tgt-vlog95/Makefile.in index 2bf721115..609a0765f 100644 --- a/tgt-vlog95/Makefile.in +++ b/tgt-vlog95/Makefile.in @@ -56,7 +56,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-vlog95/event.c b/tgt-vlog95/event.c index 0a1c0b881..88a7428dc 100644 --- a/tgt-vlog95/event.c +++ b/tgt-vlog95/event.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2019 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -90,8 +90,10 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt) /* If this is an always_comb/latch then we need to add a trigger to * get the correct functionality. */ if (ivl_stmt_needs_t0_trigger(stmt)) { - assert(first == 0); - fprintf(vlog_out, " or IVL_top_priv_module.IVL_T0_trigger_event"); + if (! first) { + fprintf(vlog_out, " or "); + } + fprintf(vlog_out, "IVL_top_priv_module.IVL_T0_trigger_event"); need_ivl_top_module = 1; }; } diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index d09c9e709..a9b4fd0a6 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -68,7 +68,8 @@ distclean: clean rm -f stamp-vvp_config-h vvp_config.h cppcheck: $(O:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index a8d2f1dfa..407df5219 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1654,7 +1654,10 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope) show_stmt_file_line(net, "Event wait (@) statement."); - if (ivl_stmt_nevent(net) == 1) { + if (ivl_stmt_nevent(net) == 0) { + assert(ivl_stmt_needs_t0_trigger(net) == 1); + fprintf(vvp_out, " %%wait E_0x0;\n"); + } else if (ivl_stmt_nevent(net) == 1) { ivl_event_t ev = ivl_stmt_events(net, 0); if (ivl_stmt_needs_t0_trigger(net)) { fprintf(vvp_out, "Ewait_%u .event/or E_%p, E_0x0;\n", diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index 9bafaf100..348d790bf 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -85,7 +85,7 @@ distclean: clean rm -f stamp-vhdlpp_config-h vhdlpp_config.h cppcheck: $(O:.o=.cc) - cppcheck --enable=all -f \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ -UYY_USER_INIT \ -UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \ -UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \ diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 6b4c13e5d..ece7a0b70 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1,5 +1,5 @@ -%pure-parser +%define api.pure %lex-param { yyscan_t yyscanner } %parse-param {yyscan_t yyscanner } %parse-param {const char*file_path} diff --git a/vpi/Makefile.in b/vpi/Makefile.in index a2ee88145..70f045ce1 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -101,7 +101,8 @@ distclean: clean # The -U flag is used to skip checking paths that depend on that define having # an explicit value (i.e. the define is expected to be real code). cppcheck: $(O:.o=.c) $(OPP:.o=.cc) $(M:.o=.c) $(V:.o=.c) - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ -UYY_USER_INIT \ -UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \ -UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \ diff --git a/vpi/fstapi.c b/vpi/fstapi.c index b9f39de1d..2e96b9f22 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -42,6 +42,7 @@ #include "fstapi.h" #include "fastlz.h" #include "lz4.h" +#include #ifndef HAVE_LIBPTHREAD #undef FST_WRITER_PARALLEL @@ -952,6 +953,17 @@ fflush(xc->handle); /* * mmap functions */ +static void fstWriterMmapSanity(void *pnt, const char *file, int line, const char *usage) +{ +if(pnt == MAP_FAILED) + { + fprintf(stderr, "fstMmap() assigned to %s failed: errno: %d, file %s, line %d.\n", usage, errno, file, line); + perror("Why"); + pnt = NULL; + } +} + + static void fstWriterCreateMmaps(struct fstWriterContext *xc) { off_t curpos = ftello(xc->handle); @@ -974,12 +986,20 @@ fflush(xc->handle); if(!xc->valpos_mem) { fflush(xc->valpos_handle); - xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->valpos_handle), 0); + errno = 0; + if(xc->maxhandle) + { + fstWriterMmapSanity(xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->valpos_handle), 0), __FILE__, __LINE__, "xc->valpos_mem"); + } } if(!xc->curval_mem) { fflush(xc->curval_handle); - xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0); + errno = 0; + if(xc->maxvalpos) + { + fstWriterMmapSanity(xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0), __FILE__, __LINE__, "xc->curval_handle"); + } } } @@ -1682,7 +1702,8 @@ fflush(xc->tchn_handle); tlen = ftello(xc->tchn_handle); fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); -tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0); +errno = 0; +fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0), __FILE__, __LINE__, "tmem"); if(tmem) { unsigned long destlen = tlen; @@ -1874,7 +1895,7 @@ if(xc) if(xc && !xc->already_in_close && !xc->already_in_flush) { - unsigned char *tmem; + unsigned char *tmem = NULL; off_t fixup_offs, tlen, hlen; xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */ @@ -1912,7 +1933,12 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) /* write out geom section */ fflush(xc->geom_handle); tlen = ftello(xc->geom_handle); - tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0); + errno = 0; + if(tlen) + { + fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0), __FILE__, __LINE__, "tmem"); + } + if(tmem) { unsigned long destlen = tlen; @@ -2020,14 +2046,18 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) { int lz4_maxlen; unsigned char *mem; - unsigned char *hmem; + unsigned char *hmem = NULL; int packed_len; fflush(xc->handle); lz4_maxlen = LZ4_compressBound(xc->hier_file_len); mem = (unsigned char *)malloc(lz4_maxlen); - hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->hier_handle), 0); + errno = 0; + if(xc->hier_file_len) + { + fstWriterMmapSanity(hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->hier_handle), 0), __FILE__, __LINE__, "hmem"); + } packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len); fstMunmap(hmem, xc->hier_file_len); diff --git a/vpi/sys_readmem.c b/vpi/sys_readmem.c index 0922214cf..4d4f37b9a 100644 --- a/vpi/sys_readmem.c +++ b/vpi/sys_readmem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2019 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 @@ -332,9 +332,9 @@ static PLI_INT32 sys_readmem_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) /* Configure the readmem lexer */ if (strcmp(name,"$readmemb") == 0) - sys_readmem_start_file(file, 1, wwid, value.value.vector); + sys_readmem_start_file(callh, file, 1, wwid, value.value.vector); else - sys_readmem_start_file(file, 0, wwid, value.value.vector); + sys_readmem_start_file(callh, file, 0, wwid, value.value.vector); /*======================================== Read memory file */ diff --git a/vpi/sys_readmem_lex.h b/vpi/sys_readmem_lex.h index 6531b8f1c..35b0c8f8c 100644 --- a/vpi/sys_readmem_lex.h +++ b/vpi/sys_readmem_lex.h @@ -1,7 +1,7 @@ #ifndef IVL_sys_readmem_lex_H #define IVL_sys_readmem_lex_H /* - * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2014,2019 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 @@ -28,7 +28,7 @@ extern char *readmem_error_token; -extern void sys_readmem_start_file(FILE*in, int bin_flag, +extern void sys_readmem_start_file(vpiHandle callh, FILE*in, int bin_flag, unsigned width, struct t_vpi_vecval*val); extern int readmemlex(void); diff --git a/vpi/sys_readmem_lex.lex b/vpi/sys_readmem_lex.lex index c7f4c53ef..9640d0c7a 100644 --- a/vpi/sys_readmem_lex.lex +++ b/vpi/sys_readmem_lex.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017,2019 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 @@ -57,6 +57,12 @@ char *readmem_error_token = 0; . { readmem_error_token = yytext; return MEM_ERROR; } %% + /* The call_handle is the handle for the call to the $readmem() + system task. This is used for adding line numbers to warnings and + error messages. */ +static vpiHandle call_handle = 0; +static int too_many_digits_warning = 0; + static unsigned word_width = 0; static struct t_vpi_vecval*vecval = 0; @@ -134,6 +140,26 @@ static void make_hex_value(void) word_max -= 32; } } + + /* If there are more text digits then needed to fill the + memory word, count those digits and print a warning + message. Print that warning only once per call to + $readmemh() so that the user isn't flooded. */ + int count_extra_digits = 0; + while (end > beg) { + end -= 1; + if (*end == '_') continue; + count_extra_digits += 1; + } + + if (count_extra_digits && too_many_digits_warning==0) { + vpi_printf("WARNING: %s:%d: Excess hex digits (%d of '%s') while reading %d-bit words.\n", + vpi_get_str(vpiFile, call_handle), + vpi_get(vpiLineNo, call_handle), + count_extra_digits, beg, + word_width); + too_many_digits_warning += 1; + } } static void make_bin_value(void) @@ -181,11 +207,33 @@ static void make_bin_value(void) word_max -= 32; } } + + /* If there are more text digits then needed to fill the + memory word, count those digits and print a warning + message. Print that warning only once per call to + $readmem() so that the user isn't flooded. */ + int count_extra_digits = 0; + while (end > beg) { + end -= 1; + if (*end == '_') continue; + count_extra_digits += 1; + } + + if (count_extra_digits && too_many_digits_warning==0) { + vpi_printf("WARNING: %s:%d: Excess binary digits (%d of '%s') while reading %d-bit words.\n", + vpi_get_str(vpiFile, call_handle), + vpi_get(vpiLineNo, call_handle), + count_extra_digits, beg, + word_width); + too_many_digits_warning += 1; + } } -void sys_readmem_start_file(FILE*in, int bin_flag, +void sys_readmem_start_file(vpiHandle callh, FILE*in, int bin_flag, unsigned width, struct t_vpi_vecval *vv) { + call_handle = callh; + too_many_digits_warning = 0; yyrestart(in); BEGIN(bin_flag? BIN : HEX); word_width = width; diff --git a/vvp/Makefile.in b/vvp/Makefile.in index fc6b88a0e..897aa6e17 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -108,7 +108,8 @@ distclean: clean rm -f stamp-config-h config.h cppcheck: $(O:.o=.cc) libvpi.c draw_tt.c - cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ + --suppressions-list=$(srcdir)/cppcheck.sup \ -UMODULE_DIR1 -UMODULE_DIR2 -UYY_USER_INIT \ -UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \ -UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \ diff --git a/vvp/compile.cc b/vvp/compile.cc index bf4af8a2e..72c14fbdb 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -378,6 +378,8 @@ vpiHandle vvp_lookup_handle(const char*label) vvp_net_t* vvp_net_lookup(const char*label) { + static bool t0_trigger_generated = false; + /* First, look to see if the symbol is a vpi object of some sort. If it is, then get the vvp_ipoint_t pointer out of the vpiHandle. */ @@ -425,6 +427,23 @@ vvp_net_t* vvp_net_lookup(const char*label) /* Failing that, look for a general functor. */ vvp_net_t*tmp = lookup_functor_symbol(label); + // This is a special label used to create a T0 trigger for the + // always_comb/latch processes. + if (! t0_trigger_generated && (strcmp(label, "E_0x0") == 0)) { + // This should never happen, but if it does then the E_0x0 + // event generation may need to be explicitly generated in + // the compiler output instead of implicitly in this code. + assert(! vpip_peek_current_scope()->is_automatic()); + t0_trigger_generated = true; + // Create a local event with no name for the T0 trigger + compile_named_event(strdup(label), strcpy(new char [1],""), true); + tmp = vvp_net_lookup(label); + assert(tmp); + // Create a trigger for the T0 event. + vvp_net_ptr_t ptr (tmp, 0); + schedule_t0_trigger(ptr); + } + return tmp; } @@ -481,7 +500,6 @@ struct vvp_net_resolv_list_s: public resolv_list_s { bool vvp_net_resolv_list_s::resolve(bool mes) { - static bool t0_trigger_generated = false; vvp_net_t*tmp = vvp_net_lookup(label()); if (tmp) { @@ -490,25 +508,6 @@ bool vvp_net_resolv_list_s::resolve(bool mes) return true; } - // This is a special label used to create a T0 trigger for the - // always_comb/latch processes. - if (! t0_trigger_generated && (strcmp(label(), "E_0x0") == 0)) { - // This should never happen, but if it does then the E_0x0 - // event generation may need to be explictly generated in - // the compiler output instead of implicitly in this code. - assert(! vpip_peek_current_scope()->is_automatic()); - t0_trigger_generated = true; - // Create a local event with no name for the T0 trigger - compile_named_event(strdup(label()), strcpy(new char [1],""), true); - tmp = vvp_net_lookup(label()); - assert(tmp); - tmp->link(port); - // Create a trigger for the T0 event. - vvp_net_ptr_t ptr (tmp, 0); - schedule_t0_trigger(ptr); - return true; - } - if (mes) fprintf(stderr, "unresolved vvp_net reference: %s\n", label());