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
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
# include <typeinfo>
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
||||||
void connect(NetObj::Link&l, NetObj::Link&r)
|
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) {
|
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||||
connect(pin(idx), lv->pin(idx));
|
connect(pin(idx), lv->pin(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rval_->set_width(lval_->pin_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
NetAssign::~NetAssign()
|
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()
|
NetEBinary::~NetEBinary()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEConst::~NetEConst()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
|
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
|
||||||
: op_(op), left_(l), right_(r)
|
: op_(op), left_(l), right_(r)
|
||||||
{
|
{
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case 'e':
|
case 'e':
|
||||||
natural_width(1);
|
expr_width(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
natural_width(left_->natural_width() > right_->natural_width()
|
expr_width(left_->expr_width() > right_->expr_width()
|
||||||
? left_->natural_width() : right_->natural_width());
|
? left_->expr_width() : right_->expr_width());
|
||||||
break;
|
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)
|
void Design::add_signal(NetNet*net)
|
||||||
{
|
{
|
||||||
assert(net->design_ == 0);
|
assert(net->design_ == 0);
|
||||||
|
|
@ -253,6 +317,9 @@ void Design::add_process(NetProcTop*pro)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.cc,v $
|
* $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
|
* Revision 1.2 1998/11/07 17:05:05 steve
|
||||||
* Handle procedural conditional, and some
|
* Handle procedural conditional, and some
|
||||||
* of the conditional expressions.
|
* 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
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -475,6 +475,13 @@ class NetProcTop {
|
||||||
/* =========
|
/* =========
|
||||||
* There are cases where expressions need to be represented. The
|
* There are cases where expressions need to be represented. The
|
||||||
* NetExpr class is the root of a heirarchy that serves that purpose.
|
* 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 {
|
class NetExpr {
|
||||||
public:
|
public:
|
||||||
|
|
@ -484,10 +491,11 @@ class NetExpr {
|
||||||
virtual void expr_scan(struct expr_scan_t*) const =0;
|
virtual void expr_scan(struct expr_scan_t*) const =0;
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
unsigned natural_width() const { return width_; }
|
unsigned expr_width() const { return width_; }
|
||||||
|
virtual void set_width(unsigned);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void natural_width(unsigned w) { width_ = w; }
|
void expr_width(unsigned w) { width_ = w; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned width_;
|
unsigned width_;
|
||||||
|
|
@ -508,6 +516,8 @@ class NetEBinary : public NetExpr {
|
||||||
|
|
||||||
char op() const { return op_; }
|
char op() const { return op_; }
|
||||||
|
|
||||||
|
void set_width(unsigned w);
|
||||||
|
|
||||||
virtual void expr_scan(struct expr_scan_t*) const;
|
virtual void expr_scan(struct expr_scan_t*) const;
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
|
@ -526,6 +536,7 @@ class NetEConst : public NetExpr {
|
||||||
|
|
||||||
const verinum&value() const { return value_; }
|
const verinum&value() const { return value_; }
|
||||||
|
|
||||||
|
virtual void set_width(unsigned w);
|
||||||
virtual void expr_scan(struct expr_scan_t*) const;
|
virtual void expr_scan(struct expr_scan_t*) const;
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
|
@ -537,11 +548,14 @@ class NetEUnary : public NetExpr {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NetEUnary(char op, NetExpr*ex)
|
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_; }
|
char op() const { return op_; }
|
||||||
const NetExpr* expr() const { return expr_; }
|
const NetExpr* expr() const { return expr_; }
|
||||||
|
|
||||||
|
void set_width(unsigned w);
|
||||||
|
|
||||||
virtual void expr_scan(struct expr_scan_t*) const;
|
virtual void expr_scan(struct expr_scan_t*) const;
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
|
@ -574,9 +588,12 @@ class NetESignal : public NetExpr {
|
||||||
public:
|
public:
|
||||||
NetESignal(NetNet*n)
|
NetESignal(NetNet*n)
|
||||||
: NetExpr(n->pin_count()), sig_(n) { }
|
: NetExpr(n->pin_count()), sig_(n) { }
|
||||||
|
~NetESignal();
|
||||||
|
|
||||||
const string& name() const { return sig_->name(); }
|
const string& name() const { return sig_->name(); }
|
||||||
|
|
||||||
|
virtual void set_width(unsigned);
|
||||||
|
|
||||||
virtual void expr_scan(struct expr_scan_t*) const;
|
virtual void expr_scan(struct expr_scan_t*) const;
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
|
@ -653,6 +670,9 @@ inline ostream& operator << (ostream&o, const NetExpr&exp)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.h,v $
|
* $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
|
* Revision 1.2 1998/11/07 17:05:05 steve
|
||||||
* Handle procedural conditional, and some
|
* Handle procedural conditional, and some
|
||||||
* of the conditional expressions.
|
* 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
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
@ -69,14 +69,13 @@ class target_vvm : public target_t {
|
||||||
class vvm_proc_rval : public expr_scan_t {
|
class vvm_proc_rval : public expr_scan_t {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit vvm_proc_rval(ostream&os, unsigned width)
|
explicit vvm_proc_rval(ostream&os)
|
||||||
: result(""), os_(os), width_(width) { }
|
: result(""), os_(os) { }
|
||||||
|
|
||||||
string result;
|
string result;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ostream&os_;
|
ostream&os_;
|
||||||
unsigned width_;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void expr_const(const NetEConst*);
|
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)
|
void vvm_proc_rval::expr_const(const NetEConst*expr)
|
||||||
{
|
{
|
||||||
string tname = make_temp();
|
string tname = make_temp();
|
||||||
os_ << " vvm_bitset_t<" << width_ << "> " << tname << ";" << endl;
|
os_ << " vvm_bitset_t<" << expr->expr_width() << "> "
|
||||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
<< tname << ";" << endl;
|
||||||
|
for (unsigned idx = 0 ; idx < expr->expr_width() ; idx += 1) {
|
||||||
os_ << " " << tname << "[" << idx << "] = ";
|
os_ << " " << tname << "[" << idx << "] = ";
|
||||||
switch (expr->value().get(idx)) {
|
switch (expr->value().get(idx)) {
|
||||||
case verinum::V0:
|
case verinum::V0:
|
||||||
|
|
@ -127,7 +127,8 @@ void vvm_proc_rval::expr_unary(const NetEUnary*expr)
|
||||||
expr->expr()->expr_scan(this);
|
expr->expr()->expr_scan(this);
|
||||||
string tname = make_temp();
|
string tname = make_temp();
|
||||||
|
|
||||||
os_ << " vvm_bitset_t<" << width_ << "> " << tname << " = ";
|
os_ << " vvm_bitset_t<" << expr->expr_width() << "> "
|
||||||
|
<< tname << " = ";
|
||||||
switch (expr->op()) {
|
switch (expr->op()) {
|
||||||
case '~':
|
case '~':
|
||||||
os_ << "vvm_unop_not(" << result << ");"
|
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)
|
void vvm_proc_rval::expr_binary(const NetEBinary*expr)
|
||||||
{
|
{
|
||||||
if (width_ == 0) {
|
|
||||||
width_ = expr->left()->natural_width();
|
|
||||||
}
|
|
||||||
|
|
||||||
expr->left()->expr_scan(this);
|
expr->left()->expr_scan(this);
|
||||||
string lres = result;
|
string lres = result;
|
||||||
|
|
||||||
expr->right()->expr_scan(this);
|
expr->right()->expr_scan(this);
|
||||||
string rres = result;
|
string rres = result;
|
||||||
|
|
||||||
|
result = make_temp();
|
||||||
|
os_ << " vvm_bitset_t<" << expr->expr_width() << ">" <<
|
||||||
|
result << ";" << endl;
|
||||||
switch (expr->op()) {
|
switch (expr->op()) {
|
||||||
case 'e':
|
case 'e':
|
||||||
result = string("vvm_binop_eq(") + lres + "," + rres + ")";
|
os_ << " " << result << " = vvm_binop_eq(" << lres
|
||||||
|
<< "," << rres << ");" << endl;
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
result = string("vvm_binop_plus(") + lres + "," + rres + ")";
|
os_ << " " << result << " = vvm_binop_plus(" << lres
|
||||||
|
<< "," << rres << ");" << endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cerr << "vvm: Unhandled binary op `" << expr->op() << "': "
|
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);
|
expr->expr_scan(&scan);
|
||||||
return scan.result;
|
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)
|
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() << " = ";
|
os << " // " << net->lval()->name() << " = ";
|
||||||
net->rval()->dump(os);
|
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) {
|
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||||
const NetObj*cur;
|
const NetObj*cur;
|
||||||
unsigned pin;
|
unsigned pin;
|
||||||
for (net->lval()->pin(0).next_link(cur, pin)
|
for (net->lval()->pin(idx).next_link(cur, pin)
|
||||||
; cur != net->lval()
|
; cur != net->lval()
|
||||||
; cur->pin(pin).next_link(cur, pin)) {
|
; 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)
|
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;
|
os << " if (" << expr << "[0] == V1) {" << endl;
|
||||||
net->emit_recurse_if(os, this);
|
net->emit_recurse_if(os, this);
|
||||||
os << " } else {" << endl;
|
os << " } else {" << endl;
|
||||||
|
|
@ -543,6 +545,9 @@ extern const struct target tgt_vvm = {
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* $Log: t-vvm.cc,v $
|
* $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
|
* Revision 1.2 1998/11/07 17:05:06 steve
|
||||||
* Handle procedural conditional, and some
|
* Handle procedural conditional, and some
|
||||||
* of the conditional expressions.
|
* of the conditional expressions.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue