Merge branch 'implicit-sig'
This commit is contained in:
commit
a2ea980a7a
2
PExpr.cc
2
PExpr.cc
|
|
@ -43,7 +43,7 @@ bool PExpr::is_constant(Module*) const
|
||||||
return false;
|
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: "
|
cerr << get_fileline() << ": error: expression not valid in assign l-value: "
|
||||||
<< *this << endl;
|
<< *this << endl;
|
||||||
|
|
|
||||||
18
PExpr.h
18
PExpr.h
|
|
@ -74,6 +74,10 @@ class PExpr : public LineInfo {
|
||||||
unsigned min, unsigned lval,
|
unsigned min, unsigned lval,
|
||||||
bool&unsized_flag) const;
|
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
|
// Procedural elaboration of the expression. The expr_width is
|
||||||
// the width of the context of the expression (i.e. the
|
// the width of the context of the expression (i.e. the
|
||||||
// l-value width of an assignment),
|
// l-value width of an assignment),
|
||||||
|
|
@ -107,8 +111,7 @@ class PExpr : public LineInfo {
|
||||||
|
|
||||||
// This method elaborates the expression as gates, but
|
// This method elaborates the expression as gates, but
|
||||||
// restricted for use as l-values of continuous assignments.
|
// restricted for use as l-values of continuous assignments.
|
||||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||||
bool implicit_net_ok =false) const;
|
|
||||||
|
|
||||||
// This is similar to elaborate_lnet, except that the
|
// This is similar to elaborate_lnet, except that the
|
||||||
// expression is evaluated to be bi-directional. This is
|
// 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 verinum* eval_const(Design*des, NetScope*sc) const;
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||||
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;
|
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||||
unsigned width,
|
unsigned width,
|
||||||
|
|
@ -177,7 +180,6 @@ class PEConcat : public PExpr {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
bool implicit_net_ok,
|
|
||||||
bool bidirectional_flag) const;
|
bool bidirectional_flag) const;
|
||||||
private:
|
private:
|
||||||
svector<PExpr*>parms_;
|
svector<PExpr*>parms_;
|
||||||
|
|
@ -264,9 +266,10 @@ class PEIdent : public PExpr {
|
||||||
unsigned min, unsigned lval,
|
unsigned min, unsigned lval,
|
||||||
bool&unsized_flag) const;
|
bool&unsized_flag) const;
|
||||||
|
|
||||||
|
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||||
bool implicit_net_ok =false) const;
|
|
||||||
|
|
||||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
|
|
@ -379,7 +382,6 @@ class PEIdent : public PExpr {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
bool implicit_net_ok,
|
|
||||||
bool bidirectional_flag) const;
|
bool bidirectional_flag) const;
|
||||||
|
|
||||||
NetNet*make_implicit_net_(Design*des, NetScope*scope) 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;
|
void dump(ostream&out, unsigned ind =4) const;
|
||||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||||
|
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
@ -166,6 +167,7 @@ class PGBuiltin : public PGate {
|
||||||
|
|
||||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||||
virtual void elaborate(Design*, NetScope*scope) const;
|
virtual void elaborate(Design*, NetScope*scope) const;
|
||||||
|
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
|
|
|
||||||
63
elab_net.cc
63
elab_net.cc
|
|
@ -2188,7 +2188,6 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope,
|
||||||
* make the l-value connections.
|
* make the l-value connections.
|
||||||
*/
|
*/
|
||||||
NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
bool implicit_net_ok,
|
|
||||||
bool bidirectional_flag) const
|
bool bidirectional_flag) const
|
||||||
{
|
{
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
|
@ -2222,8 +2221,7 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
if (bidirectional_flag) {
|
if (bidirectional_flag) {
|
||||||
nets[idx] = parms_[idx]->elaborate_bi_net(des, scope);
|
nets[idx] = parms_[idx]->elaborate_bi_net(des, scope);
|
||||||
} else {
|
} else {
|
||||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
|
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
|
||||||
implicit_net_ok);
|
|
||||||
}
|
}
|
||||||
if (nets[idx] == 0)
|
if (nets[idx] == 0)
|
||||||
errors += 1;
|
errors += 1;
|
||||||
|
|
@ -2284,15 +2282,14 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
return osig;
|
return osig;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
|
||||||
bool implicit_net_ok) 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
|
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* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
NetNet::Type nettype = scope->default_nettype();
|
NetNet::Type nettype = scope->default_nettype();
|
||||||
NetNet*sig = 0;
|
assert(nettype != NetNet::NONE);
|
||||||
|
|
||||||
if (!error_implicit && nettype!=NetNet::NONE) {
|
NetNet*sig = new NetNet(scope, peek_tail_name(path_),
|
||||||
sig = new NetNet(scope, peek_tail_name(path_),
|
NetNet::IMPLICIT, 1);
|
||||||
NetNet::IMPLICIT, 1);
|
sig->set_line(*this);
|
||||||
/* Implicit nets are always scalar logic. */
|
/* Implicit nets are always scalar logic. */
|
||||||
sig->data_type(IVL_VT_LOGIC);
|
sig->data_type(IVL_VT_LOGIC);
|
||||||
|
|
||||||
if (warn_implicit) {
|
if (warn_implicit) {
|
||||||
cerr << get_fileline() << ": warning: implicit "
|
cerr << get_fileline() << ": warning: implicit "
|
||||||
"definition of wire logic " << scope_path(scope)
|
"definition of wire logic " << scope_path(scope)
|
||||||
<< "." << peek_tail_name(path_) << "." << endl;
|
<< "." << peek_tail_name(path_) << "." << endl;
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
cerr << get_fileline() << ": error: Net " << path_
|
|
||||||
<< " is not defined in this context." << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sig;
|
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.
|
* so most of the work for both is done here.
|
||||||
*/
|
*/
|
||||||
NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
bool implicit_net_ok,
|
|
||||||
bool bidirectional_flag) const
|
bool bidirectional_flag) const
|
||||||
{
|
{
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
|
@ -2526,19 +2515,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sig == 0) {
|
if (sig == 0) {
|
||||||
|
cerr << get_fileline() << ": error: Net " << path_
|
||||||
if (implicit_net_ok) {
|
<< " is not defined in this context." << endl;
|
||||||
|
des->errors += 1;
|
||||||
sig = make_implicit_net_(des, scope);
|
return 0;
|
||||||
if (sig == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
cerr << get_fileline() << ": error: Net " << path_
|
|
||||||
<< " is not defined in this context." << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sig);
|
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
|
* Identifiers in continuous assignment l-values are limited to wires
|
||||||
* and that ilk. Detect registers and memories here and report errors.
|
* and that ilk. Detect registers and memories here and report errors.
|
||||||
*/
|
*/
|
||||||
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
|
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||||
bool implicit_net_ok) 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
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
88
elab_sig.cc
88
elab_sig.cc
|
|
@ -230,11 +230,94 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
return flag;
|
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,
|
bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||||
Module*rmod) const
|
Module*rmod) const
|
||||||
{
|
{
|
||||||
bool flag = true;
|
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()];
|
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
|
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);
|
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,
|
* Elaborate a source wire. The "wire" is the declaration of wires,
|
||||||
* registers, ports and memories. The parser has already merged the
|
* 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(0));
|
||||||
assert(pin(1));
|
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. */
|
/* 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) {
|
if (lval == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -410,7 +402,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope, true);
|
NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope);
|
||||||
assert(lval_sig);
|
assert(lval_sig);
|
||||||
|
|
||||||
/* Detect the special case that the l-value width exactly
|
/* 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
|
assignment, as the port will continuous assign
|
||||||
into the port. */
|
into the port. */
|
||||||
|
|
||||||
sig = pins[idx]->elaborate_lnet(des, scope, true);
|
sig = pins[idx]->elaborate_lnet(des, scope);
|
||||||
if (sig == 0) {
|
if (sig == 0) {
|
||||||
cerr << pins[idx]->get_fileline() << ": error: "
|
cerr << pins[idx]->get_fileline() << ": error: "
|
||||||
<< "Output port expression must support "
|
<< "Output port expression must support "
|
||||||
|
|
@ -1475,7 +1467,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
NetNet*sig = pins[0]->elaborate_lnet(des, scope, true);
|
NetNet*sig = pins[0]->elaborate_lnet(des, scope);
|
||||||
if (sig == 0) {
|
if (sig == 0) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
<< "Output port expression is not valid." << endl;
|
<< "Output port expression is not valid." << endl;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue