separate assign lval elaboration for error checking.

This commit is contained in:
steve 1999-09-15 04:17:52 +00:00
parent b04148b754
commit 31bdb87c8f
3 changed files with 211 additions and 20 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PExpr.cc,v 1.7 1999/07/22 02:05:20 steve Exp $"
#ident "$Id: PExpr.cc,v 1.8 1999/09/15 04:17:52 steve Exp $"
#endif
# include "PExpr.h"
@ -38,6 +38,23 @@ bool PExpr::is_constant(Module*) const
return false;
}
NetNet* PExpr::elaborate_net(Design*des, const string&path,
unsigned long,
unsigned long,
unsigned long) const
{
cerr << "Don't know how to elaborate `" << *this
<< "' as gates." << endl;
return 0;
}
NetNet* PExpr::elaborate_lnet(Design*des, const string&path) const
{
cerr << get_line() << ": expression not valid in assign l-value: "
<< *this << endl;
return 0;
}
bool PEBinary::is_constant(Module*mod) const
{
return left_->is_constant(mod) && right_->is_constant(mod);
@ -102,6 +119,9 @@ bool PETernary::is_constant(Module*) const
/*
* $Log: PExpr.cc,v $
* Revision 1.8 1999/09/15 04:17:52 steve
* separate assign lval elaboration for error checking.
*
* Revision 1.7 1999/07/22 02:05:20 steve
* is_constant method for PEConcat.
*

24
PExpr.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PExpr.h,v 1.18 1999/08/31 22:38:29 steve Exp $"
#ident "$Id: PExpr.h,v 1.19 1999/09/15 04:17:52 steve Exp $"
#endif
# include <string>
@ -47,11 +47,20 @@ class PExpr : public LineInfo {
virtual ~PExpr();
virtual void dump(ostream&) const;
// Procedural elaboration of the expression.
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
// This method elaborate the expression as gates, for use in a
// continuous assign or other wholy structural context.
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned long rise =0,
unsigned long fall =0,
unsigned long decay =0) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
// This attempts to evaluate a constant expression, and return
// a verinum as a result. If the expression cannot be
@ -80,6 +89,7 @@ class PEConcat : public PExpr {
~PEConcat();
virtual void dump(ostream&) const;
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned long rise =0,
unsigned long fall =0,
@ -116,11 +126,18 @@ class PEIdent : public PExpr {
: text_(s), msb_(0), lsb_(0), idx_(0) { }
virtual void dump(ostream&) const;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
// Structural r-values are OK.
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned long rise =0,
unsigned long fall =0,
unsigned long decay =0) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
virtual bool is_constant(Module*) const;
verinum* eval_const(const Design*des, const string&path) const;
@ -263,6 +280,9 @@ class PECallFunction : public PExpr {
/*
* $Log: PExpr.h,v $
* Revision 1.19 1999/09/15 04:17:52 steve
* separate assign lval elaboration for error checking.
*
* Revision 1.18 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: elaborate.cc,v 1.85 1999/09/15 01:55:06 steve Exp $"
#ident "$Id: elaborate.cc,v 1.86 1999/09/15 04:17:52 steve Exp $"
#endif
/*
@ -204,8 +204,10 @@ void PGate::elaborate(Design*des, const string&path) const
cerr << "what kind of gate? " << typeid(*this).name() << endl;
}
/* Elaborate the continuous assign. (This is *not* the procedural
assign.) Elaborate the lvalue and rvalue, and do the assignment. */
/*
* Elaborate the continuous assign. (This is *not* the procedural
* assign.) Elaborate the lvalue and rvalue, and do the assignment.
*/
void PGAssign::elaborate(Design*des, const string&path) const
{
unsigned long rise_time, fall_time, decay_time;
@ -213,17 +215,20 @@ void PGAssign::elaborate(Design*des, const string&path) const
assert(pin(0));
assert(pin(1));
NetNet*lval = pin(0)->elaborate_net(des, path);
NetNet*rval = pin(1)->elaborate_net(des, path, rise_time,
fall_time, decay_time);
/* Elaborate the l-value. */
NetNet*lval = pin(0)->elaborate_lnet(des, path);
if (lval == 0) {
cerr << get_line() << ": Unable to elaborate l-value: " <<
*pin(0) << endl;
des->errors += 1;
return;
}
/* Elaborate the r-value. Account for the initial decays,
which are going to be attached to the last gate before the
generated NetNet. */
NetNet*rval = pin(1)->elaborate_net(des, path, rise_time,
fall_time, decay_time);
if (rval == 0) {
cerr << get_line() << ": Unable to elaborate r-value: " <<
*pin(1) << endl;
@ -617,15 +622,6 @@ void PGModule::elaborate(Design*des, const string&path) const
cerr << get_line() << ": Unknown module: " << type_ << endl;
}
NetNet* PExpr::elaborate_net(Design*des, const string&path,
unsigned long,
unsigned long,
unsigned long) const
{
cerr << "Don't know how to elaborate `" << *this << "' as gates." << endl;
return 0;
}
/*
* Elaborating binary operations generally involves elaborating the
* left and right expressions, then making an output wire and
@ -891,6 +887,61 @@ NetNet* PEConcat::elaborate_net(Design*des, const string&path,
return osig;
}
/*
* The concatenation is also OK an an l-value. This method elaborates
* it as a structural l-value.
*/
NetNet* PEConcat::elaborate_lnet(Design*des, const string&path) const
{
svector<NetNet*>nets (parms_.count());
unsigned pins = 0;
unsigned errors = 0;
if (repeat_) {
cerr << get_line() << ": Sorry, I do not know how to"
" elaborate repeat concatenation nets." << endl;
return 0;
}
/* Elaborate the operands of the concatenation. */
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
nets[idx] = parms_[idx]->elaborate_lnet(des, path);
if (nets[idx] == 0)
errors += 1;
else
pins += nets[idx]->pin_count();
}
/* If any of the sub expressions failed to elaborate, then
delete all those that did and abort myself. */
if (errors) {
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (nets[idx]) delete nets[idx];
}
des->errors += 1;
return 0;
}
/* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant,
which is opposite from how they are given in the list. */
NetNet*osig = new NetNet(des->local_symbol(path),
NetNet::IMPLICIT, pins);
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
}
}
osig->local_flag(true);
des->add_signal(osig);
return osig;
}
NetNet* PEIdent::elaborate_net(Design*des, const string&path,
unsigned long rise,
unsigned long fall,
@ -952,6 +1003,103 @@ NetNet* PEIdent::elaborate_net(Design*des, const string&path,
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetTmp*tmp = new NetTmp(1);
connect(tmp->pin(0), sig->pin(idx));
sig = tmp;
}
return sig;
}
/*
* 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, const string&path) const
{
NetNet*sig = des->find_signal(path, text_);
if (sig == 0) {
/* Don't allow memories here. Is it a memory? */
if (des->find_memory(path+"."+text_)) {
cerr << get_line() << ": memories (" << text_
<< ") cannot be l-values in continuous "
<< "assignments." << endl;
return 0;
}
/* Fine, create an implicit wire as an l-value. */
sig = new NetNet(path+"."+text_, NetNet::IMPLICIT, 1);
des->add_signal(sig);
cerr << get_line() << ": warning: Implicitly defining "
"wire " << path << "." << text_ << "." << endl;
}
assert(sig);
/* Don't allow registers as assign l-values. */
if (sig->type() == NetNet::REG) {
cerr << get_line() << ": registers (" << sig->name()
<< ") cannot be l-values in continuous"
<< " assignments." << endl;
return 0;
}
if (msb_ && lsb_) {
/* Detect a part select. Evaluate the bits and elaborate
the l-value by creating a sub-net that links to just
the right pins. */
verinum*mval = msb_->eval_const(des, path);
assert(mval);
verinum*lval = lsb_->eval_const(des, path);
assert(lval);
unsigned midx = sig->sb_to_idx(mval->as_long());
unsigned lidx = sig->sb_to_idx(lval->as_long());
if (midx >= lidx) {
NetTmp*tmp = new NetTmp(midx-lidx+1);
if (tmp->pin_count() > sig->pin_count()) {
cerr << get_line() << ": bit select out of "
<< "range for " << sig->name() << endl;
return sig;
}
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
connect(tmp->pin(idx-lidx), sig->pin(idx));
sig = tmp;
} else {
NetTmp*tmp = new NetTmp(lidx-midx+1);
assert(tmp->pin_count() <= sig->pin_count());
for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
connect(tmp->pin(idx-midx), sig->pin(idx));
sig = tmp;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, path);
if (mval == 0) {
cerr << get_line() << ": index of " << text_ <<
" needs to be constant in this context." <<
endl;
des->errors += 1;
return 0;
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetTmp*tmp = new NetTmp(1);
connect(tmp->pin(0), sig->pin(idx));
sig = tmp;
@ -2432,6 +2580,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.86 1999/09/15 04:17:52 steve
* separate assign lval elaboration for error checking.
*
* Revision 1.85 1999/09/15 01:55:06 steve
* Elaborate non-blocking assignment to memories.
*