Calculate expression widths at elaboration time.
This commit is contained in:
parent
b118634189
commit
47a444fb92
81
netlist.cc
81
netlist.cc
|
|
@ -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.
|
||||
|
|
|
|||
28
netlist.h
28
netlist.h
|
|
@ -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.
|
||||
|
|
|
|||
41
t-vvm.cc
41
t-vvm.cc
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue