l-value part select for procedural assignments.

This commit is contained in:
steve 1999-06-13 23:51:16 +00:00
parent 0d210c90e5
commit 740c63291a
7 changed files with 210 additions and 148 deletions

View File

@ -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: Statement.cc,v 1.7 1999/06/06 20:45:38 steve Exp $" #ident "$Id: Statement.cc,v 1.8 1999/06/13 23:51:16 steve Exp $"
#endif #endif
# include "Statement.h" # include "Statement.h"
@ -27,16 +27,33 @@ Statement::~Statement()
{ {
} }
PAssign::~PAssign() PAssign_::PAssign_(PExpr*lval, PExpr*ex)
: lval_(lval), rval_(ex)
{
}
PAssign_::~PAssign_()
{ {
delete lval_; delete lval_;
delete expr_; delete rval_;
}
PAssign::PAssign(PExpr*lval, PExpr*ex)
: PAssign_(lval, ex)
{
}
PAssign::~PAssign()
{
}
PAssignNB::PAssignNB(PExpr*lval, PExpr*ex)
: PAssign_(lval, ex)
{
} }
PAssignNB::~PAssignNB() PAssignNB::~PAssignNB()
{ {
delete lval_;
delete rval_;
} }
PBlock::PBlock(BL_TYPE t, const list<Statement*>&st) PBlock::PBlock(BL_TYPE t, const list<Statement*>&st)
@ -100,6 +117,9 @@ PWhile::~PWhile()
/* /*
* $Log: Statement.cc,v $ * $Log: Statement.cc,v $
* Revision 1.8 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.7 1999/06/06 20:45:38 steve * Revision 1.7 1999/06/06 20:45:38 steve
* Add parse and elaboration of non-blocking assignments, * Add parse and elaboration of non-blocking assignments,
* Replace list<PCase::Item*> with an svector version, * Replace list<PCase::Item*> with an svector version,

View File

@ -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: Statement.h,v 1.9 1999/06/06 20:45:38 steve Exp $" #ident "$Id: Statement.h,v 1.10 1999/06/13 23:51:16 steve Exp $"
#endif #endif
# include <string> # include <string>
@ -76,46 +76,50 @@ class Statement : public LineInfo {
* type. The rvalue is an expression. The lvalue needs to be figured * type. The rvalue is an expression. The lvalue needs to be figured
* out by the parser as much as possible. * out by the parser as much as possible.
*/ */
class PAssign : public Statement { class PAssign_ : public Statement {
public: public:
explicit PAssign(PExpr*lval, PExpr*ex) explicit PAssign_(PExpr*lval, PExpr*ex);
: lval_(lval), expr_(ex) { } virtual ~PAssign_() =0;
~PAssign();
const PExpr* lval() const { return lval_; }
const PExpr* get_expr() const { return expr_; }
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
PExpr* lval_;
PExpr* expr_;
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
Design*des, const string&path) const;
};
class PAssignNB : public Statement {
public:
explicit PAssignNB(PExpr*lval, PExpr*ex)
: lval_(lval), rval_(ex) { }
~PAssignNB();
const PExpr* lval() const { return lval_; } const PExpr* lval() const { return lval_; }
const PExpr* rval() const { return rval_; } const PExpr* rval() const { return rval_; }
virtual void dump(ostream&out, unsigned ind) const; protected:
virtual NetProc* elaborate(Design*des, const string&path) const; NetNet*elaborate_lval(Design*, const string&path,
unsigned&lsb, unsigned&msb,
NetExpr*&mux) const;
private: private:
PExpr* lval_; PExpr* lval_;
PExpr* rval_; PExpr* rval_;
}; };
class PAssign : public PAssign_ {
public:
explicit PAssign(PExpr*lval, PExpr*ex);
~PAssign();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
Design*des, const string&path) const;
};
class PAssignNB : public PAssign_ {
public:
explicit PAssignNB(PExpr*lval, PExpr*ex);
~PAssignNB();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
};
/* /*
* A block statement is an ordered list of statements that make up the * A block statement is an ordered list of statements that make up the
* block. The block can be sequential or parallel, which only affects * block. The block can be sequential or parallel, which only affects
@ -297,6 +301,9 @@ class PWhile : public Statement {
/* /*
* $Log: Statement.h,v $ * $Log: Statement.h,v $
* Revision 1.10 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.9 1999/06/06 20:45:38 steve * Revision 1.9 1999/06/06 20:45:38 steve
* Add parse and elaboration of non-blocking assignments, * Add parse and elaboration of non-blocking assignments,
* Replace list<PCase::Item*> with an svector version, * Replace list<PCase::Item*> with an svector version,

View File

@ -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: elaborate.cc,v 1.42 1999/06/13 16:30:06 steve Exp $" #ident "$Id: elaborate.cc,v 1.43 1999/06/13 23:51:16 steve Exp $"
#endif #endif
/* /*
@ -996,88 +996,28 @@ NetProc* Statement::elaborate(Design*des, const string&path) const
NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix, NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix,
Design*des, const string&path) const Design*des, const string&path) const
{ {
NetExpr*rval = expr_->elaborate_expr(des, path); NetExpr*rv = rval()->elaborate_expr(des, path);
if (rval == 0) { if (rv == 0) {
cerr << get_line() << ": " << "failed to elaborate expression." cerr << get_line() << ": " << "failed to elaborate expression."
<< endl; << endl;
return 0; return 0;
} }
assert(rval); assert(rv);
NetExpr*idx = ix->elaborate_expr(des, path); NetExpr*idx = ix->elaborate_expr(des, path);
assert(idx); assert(idx);
NetAssignMem*am = new NetAssignMem(mem, idx, rval); NetAssignMem*am = new NetAssignMem(mem, idx, rv);
am->set_line(*this); am->set_line(*this);
return am; return am;
} }
NetProc* PAssign::elaborate(Design*des, const string&path) const NetNet* PAssign_::elaborate_lval(Design*des, const string&path,
{ unsigned&msb, unsigned&lsb,
const PEIdent*id = dynamic_cast<const PEIdent*>(lval_); NetExpr*&mux) const
assert(id);
/* Catch the case where the lvalue is a reference to a memory
item. These are handled differently. */
if (NetMemory*mem = des->find_memory(path+"."+id->name()))
return assign_to_memory_(mem, id->msb_, des, path);
if (id->lsb_ || id->msb_) {
cerr << get_line() << ": Sorry, cannot elaborate part/bit"
" selects in l-value." << endl;
des->errors += 1;
return 0;
}
NetNet*reg = des->find_signal(path+"."+id->name());
if (reg == 0) {
cerr << get_line() << ": Could not match signal: " <<
id->name() << endl;
des->errors += 1;
return 0;
}
assert(reg);
if (reg->type() != NetNet::REG) {
cerr << get_line() << ": " << *lval() << " is not a register."
<< endl;
return 0;
}
assert(reg->type() == NetNet::REG);
assert(expr_);
NetExpr*rval = expr_->elaborate_expr(des, path);
if (rval == 0) {
cerr << get_line() << ": failed to elaborate expression."
<< endl;
return 0;
}
assert(rval);
NetAssign*cur = new NetAssign("@assign", des, reg, rval);
for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1)
connect(cur->pin(idx), reg->pin(idx));
cur->set_line(*this);
des->add_node(cur);
return cur;
}
/*
* The l-value of a procedural assignment is a very much constrained
* expression. To wit, only identifiers, bit selects and part selects
* are allowed. I therefore can elaborate the l-value by hand, without
* the help of recursive elaboration.
*
* (For now, this does not yet support concatenation in the l-value.)
*/
NetProc* PAssignNB::elaborate(Design*des, const string&path) const
{ {
/* Get the l-value, and assume that it is an identifier. */ /* Get the l-value, and assume that it is an identifier. */
const PEIdent*id = dynamic_cast<const PEIdent*>(lval_); const PEIdent*id = dynamic_cast<const PEIdent*>(lval());
assert(id); assert(id);
/* Get the signal referenced by the identifier, and make sure /* Get the signal referenced by the identifier, and make sure
@ -1097,22 +1037,7 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const
return 0; return 0;
} }
assert(reg->type() == NetNet::REG); assert(reg->type() == NetNet::REG);
assert(rval_);
/* Elaborate the r-value expression. This generates a
procedural expression that I attach to the assignment. */
NetExpr*rval = rval_->elaborate_expr(des, path);
if (rval == 0) {
cerr << get_line() << ": " << "failed to elaborate expression."
<< endl;
return 0;
}
assert(rval);
/* Notice and handle bit selects of the signal. This is done
by making a mux expression to attach to the assignment
node. */
NetAssignNB*cur;
if (id->msb_ && id->lsb_) { if (id->msb_ && id->lsb_) {
verinum*vl = id->lsb_->eval_const(des, path); verinum*vl = id->lsb_->eval_const(des, path);
if (vl == 0) { if (vl == 0) {
@ -1129,11 +1054,9 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const
return 0; return 0;
} }
unsigned wid = vm->as_ulong()-vl->as_ulong()+1; msb = vm->as_ulong();
cur = new NetAssignNB(des->local_symbol(path), des, wid, rval); lsb = vl->as_ulong();
for (unsigned idx = 0 ; idx < wid ; idx += 1) mux = 0;
connect(cur->pin(idx), reg->pin(idx+vl->as_ulong()));
} else if (id->msb_) { } else if (id->msb_) {
assert(id->lsb_ == 0); assert(id->lsb_ == 0);
@ -1141,24 +1064,121 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const
if (v == 0) { if (v == 0) {
NetExpr*m = id->msb_->elaborate_expr(des, path); NetExpr*m = id->msb_->elaborate_expr(des, path);
assert(m); assert(m);
cur = new NetAssignNB(des->local_symbol(path), des, msb = 0;
reg->pin_count(), m, rval); lsb = 0;
mux = m;
for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1)
connect(cur->pin(idx), reg->pin(idx));
} else { } else {
cur = new NetAssignNB(des->local_symbol(path), des, 1, rval); msb = v->as_ulong();
connect(cur->pin(0), reg->pin(v->as_ulong())); lsb = v->as_ulong();
mux = 0;
} }
} else { } else {
cur = new NetAssignNB(des->local_symbol(path), des, assert(id->msb_ == 0);
reg->pin_count(), rval); assert(id->lsb_ == 0);
msb = reg->pin_count() - 1;
lsb = 0;
mux = 0;
}
for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1) return reg;
connect(cur->pin(idx), reg->pin(idx)); }
NetProc* PAssign::elaborate(Design*des, const string&path) const
{
/* Catch the case where the lvalue is a reference to a memory
item. These are handled differently. */
do {
const PEIdent*id = dynamic_cast<const PEIdent*>(lval());
if (id == 0) break;
if (NetMemory*mem = des->find_memory(path+"."+id->name()))
return assign_to_memory_(mem, id->msb_, des, path);
} while(0);
unsigned lsb, msb;
NetExpr*mux;
NetNet*reg = elaborate_lval(des, path, msb, lsb, mux);
if (reg == 0) return 0;
assert(rval());
NetExpr*rv = rval()->elaborate_expr(des, path);
if (rv == 0) {
cerr << get_line() << ": failed to elaborate expression."
<< endl;
return 0;
}
assert(rv);
NetAssign*cur;
if (mux == 0) {
unsigned wid = msb - lsb + 1;
cur = new NetAssign(des->local_symbol(path), des, wid, rv);
for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(cur->pin(idx), reg->pin(idx+lsb));
} else {
assert(reg->pin_count() == 1);
cerr << get_line() << ": Sorry, l-value bit select expression"
" must be constant." << endl;
delete reg;
delete rv;
return 0;
#if 0
cur = new NetAssign(des->local_symbol(path), des, 1, mux, rv);
connect(cur->pin(0), reg->pin(0));
#endif
}
cur->set_line(*this);
des->add_node(cur);
return cur;
}
/*
* The l-value of a procedural assignment is a very much constrained
* expression. To wit, only identifiers, bit selects and part selects
* are allowed. I therefore can elaborate the l-value by hand, without
* the help of recursive elaboration.
*
* (For now, this does not yet support concatenation in the l-value.)
*/
NetProc* PAssignNB::elaborate(Design*des, const string&path) const
{
unsigned lsb, msb;
NetExpr*mux;
NetNet*reg = elaborate_lval(des, path, msb, lsb, mux);
if (reg == 0) return 0;
assert(rval());
/* Elaborate the r-value expression. This generates a
procedural expression that I attach to the assignment. */
NetExpr*rv = rval()->elaborate_expr(des, path);
if (rv == 0) {
cerr << get_line() << ": " << "failed to elaborate expression."
<< endl;
return 0;
}
assert(rv);
NetAssignNB*cur;
if (mux == 0) {
unsigned wid = msb - lsb + 1;
cur = new NetAssignNB(des->local_symbol(path), des, wid, rv);
for (unsigned idx = 0 ; idx < wid ; idx += 1)
connect(cur->pin(idx), reg->pin(idx+lsb));
} else {
assert(reg->pin_count() == 1);
cur = new NetAssignNB(des->local_symbol(path), des, 1, mux, rv);
connect(cur->pin(0), reg->pin(0));
} }
@ -1372,7 +1392,7 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
return 0; return 0;
} }
assert(sig); assert(sig);
NetAssign*init = new NetAssign("@for-assign", des, sig, NetAssign*init = new NetAssign("@for-assign", des, sig->pin_count(),
expr1_->elaborate_expr(des, path)); expr1_->elaborate_expr(des, path));
for (unsigned idx = 0 ; idx < init->pin_count() ; idx += 1) for (unsigned idx = 0 ; idx < init->pin_count() ; idx += 1)
connect(init->pin(idx), sig->pin(idx)); connect(init->pin(idx), sig->pin(idx));
@ -1385,7 +1405,7 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
sig = des->find_signal(path+"."+id2->name()); sig = des->find_signal(path+"."+id2->name());
assert(sig); assert(sig);
NetAssign*step = new NetAssign("@for-assign", des, sig, NetAssign*step = new NetAssign("@for-assign", des, sig->pin_count(),
expr2_->elaborate_expr(des, path)); expr2_->elaborate_expr(des, path));
for (unsigned idx = 0 ; idx < step->pin_count() ; idx += 1) for (unsigned idx = 0 ; idx < step->pin_count() ; idx += 1)
connect(step->pin(idx), sig->pin(idx)); connect(step->pin(idx), sig->pin(idx));
@ -1507,6 +1527,9 @@ Design* elaborate(const map<string,Module*>&modules,
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.43 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.42 1999/06/13 16:30:06 steve * Revision 1.42 1999/06/13 16:30:06 steve
* Unify the NetAssign constructors a bit. * Unify the NetAssign constructors a bit.
* *

View File

@ -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: netlist.cc,v 1.36 1999/06/13 16:30:06 steve Exp $" #ident "$Id: netlist.cc,v 1.37 1999/06/13 23:51:16 steve Exp $"
#endif #endif
# include <cassert> # include <cassert>
@ -285,10 +285,10 @@ NetAssign_::~NetAssign_()
{ {
} }
NetAssign::NetAssign(const string&n, Design*des, NetNet*lv, NetExpr*rv) NetAssign::NetAssign(const string&n, Design*des, unsigned w, NetExpr*rv)
: NetAssign_(n, lv->pin_count()), rval_(rv) : NetAssign_(n, w), rval_(rv)
{ {
bool flag = rval_->set_width(lv->pin_count()); bool flag = rval_->set_width(w);
if (flag == false) { if (flag == false) {
cerr << rv->get_line() << ": Expression bit width" << cerr << rv->get_line() << ": Expression bit width" <<
" conflicts with l-value bit width." << endl; " conflicts with l-value bit width." << endl;
@ -1202,6 +1202,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.37 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.36 1999/06/13 16:30:06 steve * Revision 1.36 1999/06/13 16:30:06 steve
* Unify the NetAssign constructors a bit. * Unify the NetAssign constructors a bit.
* *

View File

@ -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.39 1999/06/13 17:30:23 steve Exp $" #ident "$Id: netlist.h,v 1.40 1999/06/13 23:51:16 steve Exp $"
#endif #endif
/* /*
@ -576,7 +576,7 @@ class NetAssign_ : public NetProc, public NetNode, public LineInfo {
class NetAssign : public NetAssign_ { class NetAssign : public NetAssign_ {
public: public:
explicit NetAssign(const string&, Design*des, NetNet*lv, NetExpr*rv); explicit NetAssign(const string&, Design*des, unsigned w, NetExpr*rv);
~NetAssign(); ~NetAssign();
const NetExpr*rval() const { return rval_; } const NetExpr*rval() const { return rval_; }
@ -1252,6 +1252,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.40 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.39 1999/06/13 17:30:23 steve * Revision 1.39 1999/06/13 17:30:23 steve
* More unary operators. * More unary operators.
* *

View File

@ -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: pform.cc,v 1.25 1999/06/12 20:35:27 steve Exp $" #ident "$Id: pform.cc,v 1.26 1999/06/13 23:51:16 steve Exp $"
#endif #endif
# include "compiler.h" # include "compiler.h"
@ -192,7 +192,7 @@ void pform_make_udp(string*name, list<string>*parms,
// XXXX // XXXX
assert(id->name() == pins[0]->name); assert(id->name() == pins[0]->name);
const PENumber*np = dynamic_cast<const PENumber*>(pa->get_expr()); const PENumber*np = dynamic_cast<const PENumber*>(pa->rval());
assert(np); assert(np);
init = np->value()[0]; init = np->value()[0];
@ -590,6 +590,9 @@ int pform_parse(const char*path, map<string,Module*>&modules,
/* /*
* $Log: pform.cc,v $ * $Log: pform.cc,v $
* Revision 1.26 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.25 1999/06/12 20:35:27 steve * Revision 1.25 1999/06/12 20:35:27 steve
* parse more verilog. * parse more verilog.
* *

View File

@ -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: pform_dump.cc,v 1.19 1999/06/10 04:03:53 steve Exp $" #ident "$Id: pform_dump.cc,v 1.20 1999/06/13 23:51:16 steve Exp $"
#endif #endif
/* /*
@ -262,14 +262,14 @@ void Statement::dump(ostream&out, unsigned ind) const
void PAssign::dump(ostream&out, unsigned ind) const void PAssign::dump(ostream&out, unsigned ind) const
{ {
out << setw(ind) << ""; out << setw(ind) << "";
out << *lval_ << " = " << *expr_ << ";"; out << *lval() << " = " << *rval() << ";";
out << " /* " << get_line() << " */" << endl; out << " /* " << get_line() << " */" << endl;
} }
void PAssignNB::dump(ostream&out, unsigned ind) const void PAssignNB::dump(ostream&out, unsigned ind) const
{ {
out << setw(ind) << ""; out << setw(ind) << "";
out << *lval_ << " <= " << *rval_ << ";"; out << *lval() << " <= " << *rval() << ";";
out << " /* " << get_line() << " */" << endl; out << " /* " << get_line() << " */" << endl;
} }
@ -480,6 +480,9 @@ void PUdp::dump(ostream&out) const
/* /*
* $Log: pform_dump.cc,v $ * $Log: pform_dump.cc,v $
* Revision 1.20 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.19 1999/06/10 04:03:53 steve * Revision 1.19 1999/06/10 04:03:53 steve
* Add support for the Ternary operator, * Add support for the Ternary operator,
* Add support for repeat concatenation, * Add support for repeat concatenation,