Calculate expression widths at elaboration time.

This commit is contained in:
steve 1998-11-07 19:17:10 +00:00
parent b118634189
commit 47a444fb92
3 changed files with 121 additions and 29 deletions

View File

@ -17,10 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.cc,v 1.2 1998/11/07 17:05:05 steve Exp $"
#ident "$Id: netlist.cc,v 1.3 1998/11/07 19:17:10 steve Exp $"
#endif
# include <cassert>
# include <typeinfo>
# include "netlist.h"
void connect(NetObj::Link&l, NetObj::Link&r)
@ -98,6 +99,8 @@ NetAssign::NetAssign(NetNet*lv, NetExpr*rv)
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
connect(pin(idx), lv->pin(idx));
}
rval_->set_width(lval_->pin_count());
}
NetAssign::~NetAssign()
@ -129,28 +132,89 @@ NetExpr::~NetExpr()
{
}
void NetExpr::set_width(unsigned w)
{
cerr << typeid(*this).name() << ": set_width(unsigned) "
"not implemented." << endl;
expr_width(w);
}
NetEBinary::~NetEBinary()
{
}
NetEConst::~NetEConst()
{
}
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
: op_(op), left_(l), right_(r)
{
switch (op_) {
case 'e':
natural_width(1);
expr_width(1);
break;
default:
natural_width(left_->natural_width() > right_->natural_width()
? left_->natural_width() : right_->natural_width());
expr_width(left_->expr_width() > right_->expr_width()
? left_->expr_width() : right_->expr_width());
break;
}
}
void NetEBinary::set_width(unsigned w)
{
switch (op_) {
/* Comparison operators allow the subexpressions to have
their own natural width. Do not recurse the
set_width(). */
case 'e':
assert(w == 1);
expr_width(w);
break;;
/* The default rule is that the operands of the binary
operator might as well use the same width as the
output from the binary operation. */
default:
cerr << "NetEBinary::set_width(): Using default for " <<
op_ << "." << endl;
case '+':
left_->set_width(w);
right_->set_width(w);
expr_width(w);
break;
}
}
NetEConst::~NetEConst()
{
}
void NetEConst::set_width(unsigned w)
{
assert(w <= value_.len());
expr_width(w);
}
NetESignal::~NetESignal()
{
}
void NetESignal::set_width(unsigned w)
{
assert(w == sig_->pin_count());
expr_width(w);
}
NetEUnary::~NetEUnary()
{
}
void NetEUnary::set_width(unsigned w)
{
expr_->set_width(w);
expr_width(w);
}
void Design::add_signal(NetNet*net)
{
assert(net->design_ == 0);
@ -253,6 +317,9 @@ void Design::add_process(NetProcTop*pro)
/*
* $Log: netlist.cc,v $
* Revision 1.3 1998/11/07 19:17:10 steve
* Calculate expression widths at elaboration time.
*
* Revision 1.2 1998/11/07 17:05:05 steve
* Handle procedural conditional, and some
* of the conditional expressions.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.h,v 1.2 1998/11/07 17:05:05 steve Exp $"
#ident "$Id: netlist.h,v 1.3 1998/11/07 19:17:10 steve Exp $"
#endif
/*
@ -475,6 +475,13 @@ class NetProcTop {
/* =========
* There are cases where expressions need to be represented. The
* NetExpr class is the root of a heirarchy that serves that purpose.
*
* The expr_width() is the width of the expression, that accounts
* for the widths of the sub-expressions I might have. It is up to the
* derived classes to properly set the expr width, if need be. The
* set_width() method is used to compel an expression to have a
* certain width, and is used particulary when the expression is an
* rvalue in an assignment statement.
*/
class NetExpr {
public:
@ -484,10 +491,11 @@ class NetExpr {
virtual void expr_scan(struct expr_scan_t*) const =0;
virtual void dump(ostream&) const;
unsigned natural_width() const { return width_; }
unsigned expr_width() const { return width_; }
virtual void set_width(unsigned);
protected:
void natural_width(unsigned w) { width_ = w; }
void expr_width(unsigned w) { width_ = w; }
private:
unsigned width_;
@ -508,6 +516,8 @@ class NetEBinary : public NetExpr {
char op() const { return op_; }
void set_width(unsigned w);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -526,6 +536,7 @@ class NetEConst : public NetExpr {
const verinum&value() const { return value_; }
virtual void set_width(unsigned w);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -537,11 +548,14 @@ class NetEUnary : public NetExpr {
public:
NetEUnary(char op, NetExpr*ex)
: NetExpr(ex->natural_width()), op_(op), expr_(ex) { }
: NetExpr(ex->expr_width()), op_(op), expr_(ex) { }
~NetEUnary();
char op() const { return op_; }
const NetExpr* expr() const { return expr_; }
void set_width(unsigned w);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -574,9 +588,12 @@ class NetESignal : public NetExpr {
public:
NetESignal(NetNet*n)
: NetExpr(n->pin_count()), sig_(n) { }
~NetESignal();
const string& name() const { return sig_->name(); }
virtual void set_width(unsigned);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -653,6 +670,9 @@ inline ostream& operator << (ostream&o, const NetExpr&exp)
/*
* $Log: netlist.h,v $
* Revision 1.3 1998/11/07 19:17:10 steve
* Calculate expression widths at elaboration time.
*
* Revision 1.2 1998/11/07 17:05:05 steve
* Handle procedural conditional, and some
* of the conditional expressions.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-vvm.cc,v 1.2 1998/11/07 17:05:06 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.3 1998/11/07 19:17:10 steve Exp $"
#endif
# include <iostream>
@ -69,14 +69,13 @@ class target_vvm : public target_t {
class vvm_proc_rval : public expr_scan_t {
public:
explicit vvm_proc_rval(ostream&os, unsigned width)
: result(""), os_(os), width_(width) { }
explicit vvm_proc_rval(ostream&os)
: result(""), os_(os) { }
string result;
private:
ostream&os_;
unsigned width_;
private:
virtual void expr_const(const NetEConst*);
@ -89,8 +88,9 @@ class vvm_proc_rval : public expr_scan_t {
void vvm_proc_rval::expr_const(const NetEConst*expr)
{
string tname = make_temp();
os_ << " vvm_bitset_t<" << width_ << "> " << tname << ";" << endl;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
os_ << " vvm_bitset_t<" << expr->expr_width() << "> "
<< tname << ";" << endl;
for (unsigned idx = 0 ; idx < expr->expr_width() ; idx += 1) {
os_ << " " << tname << "[" << idx << "] = ";
switch (expr->value().get(idx)) {
case verinum::V0:
@ -127,7 +127,8 @@ void vvm_proc_rval::expr_unary(const NetEUnary*expr)
expr->expr()->expr_scan(this);
string tname = make_temp();
os_ << " vvm_bitset_t<" << width_ << "> " << tname << " = ";
os_ << " vvm_bitset_t<" << expr->expr_width() << "> "
<< tname << " = ";
switch (expr->op()) {
case '~':
os_ << "vvm_unop_not(" << result << ");"
@ -145,22 +146,23 @@ void vvm_proc_rval::expr_unary(const NetEUnary*expr)
void vvm_proc_rval::expr_binary(const NetEBinary*expr)
{
if (width_ == 0) {
width_ = expr->left()->natural_width();
}
expr->left()->expr_scan(this);
string lres = result;
expr->right()->expr_scan(this);
string rres = result;
result = make_temp();
os_ << " vvm_bitset_t<" << expr->expr_width() << ">" <<
result << ";" << endl;
switch (expr->op()) {
case 'e':
result = string("vvm_binop_eq(") + lres + "," + rres + ")";
os_ << " " << result << " = vvm_binop_eq(" << lres
<< "," << rres << ");" << endl;
break;
case '+':
result = string("vvm_binop_plus(") + lres + "," + rres + ")";
os_ << " " << result << " = vvm_binop_plus(" << lres
<< "," << rres << ");" << endl;
break;
default:
cerr << "vvm: Unhandled binary op `" << expr->op() << "': "
@ -171,9 +173,9 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr)
}
}
static string emit_proc_rval(ostream&os, unsigned width, const NetExpr*expr)
static string emit_proc_rval(ostream&os, const NetExpr*expr)
{
vvm_proc_rval scan (os, width);
vvm_proc_rval scan (os);
expr->expr_scan(&scan);
return scan.result;
}
@ -400,7 +402,7 @@ void target_vvm::start_process(ostream&os, const NetProcTop*proc)
*/
void target_vvm::proc_assign(ostream&os, const NetAssign*net)
{
string rval = emit_proc_rval(os, net->lval()->pin_count(), net->rval());
string rval = emit_proc_rval(os, net->rval());
os << " // " << net->lval()->name() << " = ";
net->rval()->dump(os);
@ -419,7 +421,7 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
const NetObj*cur;
unsigned pin;
for (net->lval()->pin(0).next_link(cur, pin)
for (net->lval()->pin(idx).next_link(cur, pin)
; cur != net->lval()
; cur->pin(pin).next_link(cur, pin)) {
@ -450,7 +452,7 @@ void target_vvm::proc_block(ostream&os, const NetBlock*net)
void target_vvm::proc_condit(ostream&os, const NetCondit*net)
{
string expr = emit_proc_rval(os, 0, net->expr());
string expr = emit_proc_rval(os, net->expr());
os << " if (" << expr << "[0] == V1) {" << endl;
net->emit_recurse_if(os, this);
os << " } else {" << endl;
@ -543,6 +545,9 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.3 1998/11/07 19:17:10 steve
* Calculate expression widths at elaboration time.
*
* Revision 1.2 1998/11/07 17:05:06 steve
* Handle procedural conditional, and some
* of the conditional expressions.