diff --git a/PExpr.cc b/PExpr.cc index ac6369973..aa1265856 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -43,7 +43,7 @@ bool PExpr::is_constant(Module*) const return false; } -NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const +NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const { cerr << get_fileline() << ": error: expression not valid in assign l-value: " << *this << endl; diff --git a/PExpr.h b/PExpr.h index ee34a20b0..3481351aa 100644 --- a/PExpr.h +++ b/PExpr.h @@ -74,6 +74,10 @@ class PExpr : public LineInfo { unsigned min, unsigned lval, bool&unsized_flag) const; + // During the elaborate_sig phase, we may need to scan + // expressions to find implicit net declarations. + virtual bool elaborate_sig(Design*des, NetScope*scope) const; + // Procedural elaboration of the expression. The expr_width is // the width of the context of the expression (i.e. the // l-value width of an assignment), @@ -107,8 +111,7 @@ class PExpr : public LineInfo { // This method elaborates the expression as gates, but // restricted for use as l-values of continuous assignments. - virtual NetNet* elaborate_lnet(Design*des, NetScope*scope, - bool implicit_net_ok =false) const; + virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const; // This is similar to elaborate_lnet, except that the // expression is evaluated to be bi-directional. This is @@ -157,8 +160,8 @@ class PEConcat : public PExpr { virtual verinum* eval_const(Design*des, NetScope*sc) const; virtual void dump(ostream&) const; - virtual NetNet* elaborate_lnet(Design*des, NetScope*scope, - bool implicit_net_ok =false) const; + virtual bool elaborate_sig(Design*des, NetScope*scope) const; + virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const; virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const; virtual NetNet* elaborate_net(Design*des, NetScope*scope, unsigned width, @@ -177,7 +180,6 @@ class PEConcat : public PExpr { private: NetNet* elaborate_lnet_common_(Design*des, NetScope*scope, - bool implicit_net_ok, bool bidirectional_flag) const; private: svectorparms_; @@ -264,9 +266,10 @@ class PEIdent : public PExpr { unsigned min, unsigned lval, bool&unsized_flag) const; + virtual bool elaborate_sig(Design*des, NetScope*scope) const; + // Identifiers are allowed (with restrictions) is assign l-values. - virtual NetNet* elaborate_lnet(Design*des, NetScope*scope, - bool implicit_net_ok =false) const; + virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const; virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const; @@ -379,7 +382,6 @@ class PEIdent : public PExpr { private: NetNet* elaborate_lnet_common_(Design*des, NetScope*scope, - bool implicit_net_ok, bool bidirectional_flag) const; NetNet*make_implicit_net_(Design*des, NetScope*scope) const; diff --git a/PGate.h b/PGate.h index 9f4f14469..0e9e2810c 100644 --- a/PGate.h +++ b/PGate.h @@ -129,6 +129,7 @@ class PGAssign : public PGate { void dump(ostream&out, unsigned ind =4) const; virtual void elaborate(Design*des, NetScope*scope) const; + virtual bool elaborate_sig(Design*des, NetScope*scope) const; private: }; @@ -166,6 +167,7 @@ class PGBuiltin : public PGate { virtual void dump(ostream&out, unsigned ind =4) const; virtual void elaborate(Design*, NetScope*scope) const; + virtual bool elaborate_sig(Design*des, NetScope*scope) const; private: Type type_; diff --git a/elab_net.cc b/elab_net.cc index bd3c0357a..9398a44e4 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -2188,7 +2188,6 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope, * make the l-value connections. */ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope, - bool implicit_net_ok, bool bidirectional_flag) const { assert(scope); @@ -2222,8 +2221,7 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope, if (bidirectional_flag) { nets[idx] = parms_[idx]->elaborate_bi_net(des, scope); } else { - nets[idx] = parms_[idx]->elaborate_lnet(des, scope, - implicit_net_ok); + nets[idx] = parms_[idx]->elaborate_lnet(des, scope); } if (nets[idx] == 0) errors += 1; @@ -2284,15 +2282,14 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope, return osig; } -NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope, - bool implicit_net_ok) const +NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const { - return elaborate_lnet_common_(des, scope, implicit_net_ok, false); + return elaborate_lnet_common_(des, scope, false); } NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope) const { - return elaborate_lnet_common_(des, scope, true, true); + return elaborate_lnet_common_(des, scope, true); } /* @@ -2337,25 +2334,18 @@ NetNet* PEFNumber::elaborate_net(Design*des, NetScope*scope, NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const { NetNet::Type nettype = scope->default_nettype(); - NetNet*sig = 0; + assert(nettype != NetNet::NONE); - if (!error_implicit && nettype!=NetNet::NONE) { - sig = new NetNet(scope, peek_tail_name(path_), - NetNet::IMPLICIT, 1); - /* Implicit nets are always scalar logic. */ - sig->data_type(IVL_VT_LOGIC); + NetNet*sig = new NetNet(scope, peek_tail_name(path_), + NetNet::IMPLICIT, 1); + sig->set_line(*this); + /* Implicit nets are always scalar logic. */ + sig->data_type(IVL_VT_LOGIC); - if (warn_implicit) { - cerr << get_fileline() << ": warning: implicit " - "definition of wire logic " << scope_path(scope) - << "." << peek_tail_name(path_) << "." << endl; - } - - } else { - cerr << get_fileline() << ": error: Net " << path_ - << " is not defined in this context." << endl; - des->errors += 1; - return 0; + if (warn_implicit) { + cerr << get_fileline() << ": warning: implicit " + "definition of wire logic " << scope_path(scope) + << "." << peek_tail_name(path_) << "." << endl; } return sig; @@ -2506,7 +2496,6 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig, * so most of the work for both is done here. */ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, - bool implicit_net_ok, bool bidirectional_flag) const { assert(scope); @@ -2526,19 +2515,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, } if (sig == 0) { - - if (implicit_net_ok) { - - sig = make_implicit_net_(des, scope); - if (sig == 0) - return 0; - - } else { - cerr << get_fileline() << ": error: Net " << path_ - << " is not defined in this context." << endl; - des->errors += 1; - return 0; - } + cerr << get_fileline() << ": error: Net " << path_ + << " is not defined in this context." << endl; + des->errors += 1; + return 0; } assert(sig); @@ -2671,15 +2651,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, * Identifiers in continuous assignment l-values are limited to wires * and that ilk. Detect registers and memories here and report errors. */ -NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope, - bool implicit_net_ok) const +NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const { - return elaborate_lnet_common_(des, scope, implicit_net_ok, false); + return elaborate_lnet_common_(des, scope, false); } NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const { - return elaborate_lnet_common_(des, scope, true, true); + return elaborate_lnet_common_(des, scope, true); } /* diff --git a/elab_sig.cc b/elab_sig.cc index 7be84919f..e84778224 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -230,11 +230,94 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const return flag; } +bool PExpr::elaborate_sig(Design*des, NetScope*scope) const +{ + return true; +} + +bool PEConcat::elaborate_sig(Design*des, NetScope*scope) const +{ + bool flag = true; + for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) + flag = parms_[idx]->elaborate_sig(des, scope) && flag; + + return flag; +} + +bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const +{ + NetNet* sig = 0; + const NetExpr*par = 0; + NetEvent* eve = 0; + + // If implicit net creation is turned off, then stop now. + if (scope->default_nettype() == NetNet::NONE) + return true; + if (error_implicit) + return true; + + symbol_search(des, scope, path_, sig, par, eve); + + if (eve != 0) + return false; + + if (sig == 0) + sig = make_implicit_net_(des, scope); + + return sig != 0; +} + +bool PGate::elaborate_sig(Design*des, NetScope*scope) const +{ + return true; +} + +bool PGBuiltin::elaborate_sig(Design*des, NetScope*scope) const +{ + bool flag = true; + + for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) + flag = pin(idx)->elaborate_sig(des, scope) && flag; + + return flag; +} + +bool PGAssign::elaborate_sig(Design*des, NetScope*scope) const +{ + /* Normally, l-values to continuous assignments are NOT allowed + to implicitly declare nets. However, so many tools do allow + it that Icarus Verilog will allow it, at least if extensions + are enabled. */ + if (generation_flag == GN_VER2001X) + return pin(0)->elaborate_sig(des, scope); + + return true; +} + bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope, Module*rmod) const { bool flag = true; + // First, elaborate the signals that may be created implicitly + // by ports to this module instantiation. Handle the case that + // the ports are passed by name (pins_ != 0) or position. + if (pins_) + for (unsigned idx = 0 ; idx < npins_ ; idx += 1) { + const PExpr*tmp = pins_[idx].parm; + if (tmp == 0) + continue; + flag = tmp->elaborate_sig(des, scope) && flag; + } + else + for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { + const PExpr*tmp = pin(idx); + if (tmp == 0) + continue; + flag = tmp->elaborate_sig(des, scope) && flag; + } + + NetScope::scope_vec_t instance = scope->instance_arrays[get_name()]; for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) { @@ -598,11 +681,6 @@ void PForStatement::elaborate_sig(Design*des, NetScope*scope) const statement_->elaborate_sig(des, scope); } -bool PGate::elaborate_sig(Design*des, NetScope*scope) const -{ - return true; -} - /* * Elaborate a source wire. The "wire" is the declaration of wires, * registers, ports and memories. The parser has already merged the diff --git a/elaborate.cc b/elaborate.cc index b4b0a4f68..d22b808d0 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -85,16 +85,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const assert(pin(0)); assert(pin(1)); - /* Normally, l-values to continuous assignments are NOT allowed - to implicitly declare nets. However, so many tools do allow - it that Icarus Verilog will allow it, at least if extensions - are enabled. */ - bool implicit_lval_ok = false; - if (generation_flag == GN_VER2001X) - implicit_lval_ok = true; - /* Elaborate the l-value. */ - NetNet*lval = pin(0)->elaborate_lnet(des, scope, implicit_lval_ok); + NetNet*lval = pin(0)->elaborate_lnet(des, scope); if (lval == 0) { return; } @@ -410,7 +402,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const des->errors += 1; return; } - NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope, true); + NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope); assert(lval_sig); /* Detect the special case that the l-value width exactly @@ -1140,7 +1132,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const assignment, as the port will continuous assign into the port. */ - sig = pins[idx]->elaborate_lnet(des, scope, true); + sig = pins[idx]->elaborate_lnet(des, scope); if (sig == 0) { cerr << pins[idx]->get_fileline() << ": error: " << "Output port expression must support " @@ -1475,7 +1467,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const << endl; } else { - NetNet*sig = pins[0]->elaborate_lnet(des, scope, true); + NetNet*sig = pins[0]->elaborate_lnet(des, scope); if (sig == 0) { cerr << get_fileline() << ": error: " << "Output port expression is not valid." << endl;