Move implicit net creation from elaboration to elaborate_sig
If implicit nets are declared during elaboration, then the success of binding during elaboration will depend on the order of the code in the source file.
This commit is contained in:
parent
8e6c2652ab
commit
d26ae866f8
2
PExpr.cc
2
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;
|
||||
|
|
|
|||
18
PExpr.h
18
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:
|
||||
svector<PExpr*>parms_;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
2
PGate.h
2
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_;
|
||||
|
|
|
|||
36
elab_net.cc
36
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2506,7 +2503,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 +2522,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 +2658,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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
63
elab_sig.cc
63
elab_sig.cc
|
|
@ -230,6 +230,64 @@ 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;
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -598,11 +656,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
|
||||
|
|
|
|||
16
elaborate.cc
16
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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue