Handle expression bit widths with non-fatal errors.
This commit is contained in:
parent
c1dbb56b70
commit
5ef3970714
43
elaborate.cc
43
elaborate.cc
|
|
@ -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.27 1999/05/20 04:31:45 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.28 1999/05/27 04:13:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -732,8 +732,24 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path) const
|
|||
|
||||
NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
return new NetEBinary(op_, left_->elaborate_expr(des, path),
|
||||
right_->elaborate_expr(des, path));
|
||||
bool flag;
|
||||
NetEBinary*tmp = new NetEBinary(op_, left_->elaborate_expr(des, path),
|
||||
right_->elaborate_expr(des, path));
|
||||
tmp->set_line(*this);
|
||||
switch (op_) {
|
||||
case 'e':
|
||||
case 'n':
|
||||
flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_line() << ": expression bit width"
|
||||
" is ambiguous." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PENumber::elaborate_expr(Design*des, const string&path) const
|
||||
|
|
@ -746,7 +762,9 @@ NetExpr* PENumber::elaborate_expr(Design*des, const string&path) const
|
|||
|
||||
NetExpr* PEString::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
return new NetEConst(value());
|
||||
NetEConst*tmp = new NetEConst(value());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
|
|
@ -775,6 +793,7 @@ NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const
|
|||
if (msb_) {
|
||||
NetExpr*ex = msb_->elaborate_expr(des, path);
|
||||
NetESubSignal*ss = new NetESubSignal(node, ex);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
assert(msb_ == 0);
|
||||
|
|
@ -797,6 +816,7 @@ NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const
|
|||
}
|
||||
|
||||
NetEMemory*node = new NetEMemory(mem, i);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
@ -815,7 +835,9 @@ NetExpr* PExpr::elaborate_expr(Design*des, const string&path) const
|
|||
|
||||
NetExpr* PEUnary::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
return new NetEUnary(op_, expr_->elaborate_expr(des, path));
|
||||
NetEUnary*tmp = new NetEUnary(op_, expr_->elaborate_expr(des, path));
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetProc* Statement::elaborate(Design*des, const string&path) const
|
||||
|
|
@ -881,7 +903,7 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
|
|||
}
|
||||
assert(rval);
|
||||
|
||||
NetAssign*cur = new NetAssign(reg, rval);
|
||||
NetAssign*cur = new NetAssign(des, reg, rval);
|
||||
cur->set_line(*this);
|
||||
des->add_node(cur);
|
||||
|
||||
|
|
@ -1042,7 +1064,8 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
|
|||
NetBlock*top = new NetBlock(NetBlock::SEQU);
|
||||
NetNet*sig = des->find_signal(path+"."+id1->name());
|
||||
assert(sig);
|
||||
NetAssign*init = new NetAssign(sig, expr1_->elaborate_expr(des, path));
|
||||
NetAssign*init = new NetAssign(des, sig,
|
||||
expr1_->elaborate_expr(des, path));
|
||||
top->append(init);
|
||||
|
||||
NetBlock*body = new NetBlock(NetBlock::SEQU);
|
||||
|
|
@ -1051,7 +1074,8 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
|
|||
|
||||
sig = des->find_signal(path+"."+id2->name());
|
||||
assert(sig);
|
||||
NetAssign*step = new NetAssign(sig, expr2_->elaborate_expr(des, path));
|
||||
NetAssign*step = new NetAssign(des, sig,
|
||||
expr2_->elaborate_expr(des, path));
|
||||
body->append(step);
|
||||
|
||||
NetWhile*loop = new NetWhile(cond_->elaborate_expr(des, path), body);
|
||||
|
|
@ -1169,6 +1193,9 @@ Design* elaborate(const map<string,Module*>&modules,
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.28 1999/05/27 04:13:08 steve
|
||||
* Handle expression bit widths with non-fatal errors.
|
||||
*
|
||||
* Revision 1.27 1999/05/20 04:31:45 steve
|
||||
* Much expression parsing work,
|
||||
* mark continuous assigns with source line info,
|
||||
|
|
|
|||
82
netlist.cc
82
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: netlist.cc,v 1.27 1999/05/20 05:07:37 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.28 1999/05/27 04:13:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -270,14 +270,19 @@ NetProc::~NetProc()
|
|||
{
|
||||
}
|
||||
|
||||
NetAssign::NetAssign(NetNet*lv, NetExpr*rv)
|
||||
NetAssign::NetAssign(Design*des, NetNet*lv, NetExpr*rv)
|
||||
: NetNode("@assign", lv->pin_count()), rval_(rv)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
connect(pin(idx), lv->pin(idx));
|
||||
}
|
||||
|
||||
rval_->set_width(lv->pin_count());
|
||||
bool flag = rval_->set_width(lv->pin_count());
|
||||
if (flag == false) {
|
||||
cerr << rv->get_line() << ": Expression bit width" <<
|
||||
" conflicts with l-value bit width." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign::~NetAssign()
|
||||
|
|
@ -391,11 +396,12 @@ NetExpr::~NetExpr()
|
|||
{
|
||||
}
|
||||
|
||||
void NetExpr::set_width(unsigned w)
|
||||
bool NetExpr::set_width(unsigned w)
|
||||
{
|
||||
cerr << typeid(*this).name() << ": set_width(unsigned) "
|
||||
"not implemented." << endl;
|
||||
expr_width(w);
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetExpr::REF::clr()
|
||||
|
|
@ -454,32 +460,29 @@ NetEBinary::~NetEBinary()
|
|||
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
|
||||
: op_(op), left_(l), right_(r)
|
||||
{
|
||||
switch (op_) {
|
||||
// comparison operators return a 1-bin wide result.
|
||||
case 'e':
|
||||
case 'n':
|
||||
expr_width(1);
|
||||
right_->set_width(left_->expr_width());
|
||||
break;
|
||||
default:
|
||||
expr_width(left_->expr_width() > right_->expr_width()
|
||||
? left_->expr_width() : right_->expr_width());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NetEBinary::set_width(unsigned w)
|
||||
bool NetEBinary::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
switch (op_) {
|
||||
/* Comparison operators allow the subexpressions to have
|
||||
their own natural width. However, I do need to make
|
||||
sure that the subexpressions have the same width. */
|
||||
case 'e':
|
||||
case 'e': /* == */
|
||||
case 'n': /* != */
|
||||
assert(w == 1);
|
||||
expr_width(w);
|
||||
flag = right_->set_width(left_->expr_width());
|
||||
break;
|
||||
|
||||
case 'l': // left shift (<<)
|
||||
case 'r': // right shift (>>)
|
||||
flag = left_->set_width(w);
|
||||
expr_width(w);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'o': // logical or (||)
|
||||
assert(w == 1);
|
||||
expr_width(w);
|
||||
break;
|
||||
|
|
@ -488,33 +491,40 @@ void NetEBinary::set_width(unsigned w)
|
|||
operator might as well use the same width as the
|
||||
output from the binary operation. */
|
||||
default:
|
||||
expr_width(left_->expr_width() > right_->expr_width()
|
||||
? left_->expr_width() : right_->expr_width());
|
||||
cerr << "NetEBinary::set_width(): Using default for " <<
|
||||
op_ << "." << endl;
|
||||
flag = false;
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
case '^':
|
||||
left_->set_width(w);
|
||||
right_->set_width(w);
|
||||
case '&':
|
||||
case '|':
|
||||
flag = left_->set_width(w) && flag;
|
||||
flag = right_->set_width(w) && flag;
|
||||
expr_width(w);
|
||||
break;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
NetEConst::~NetEConst()
|
||||
{
|
||||
}
|
||||
|
||||
void NetEConst::set_width(unsigned w)
|
||||
bool NetEConst::set_width(unsigned w)
|
||||
{
|
||||
if (w > value_.len()) {
|
||||
cerr << get_line() << ": Cannot expand " << *this
|
||||
<< " to " << w << " bits." << endl;
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
assert(w <= value_.len());
|
||||
value_ = verinum(value_, w);
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
NetEMemory::NetEMemory(NetMemory*m, NetExpr*i)
|
||||
|
|
@ -532,10 +542,11 @@ void NetMemory::set_attributes(const map<string,string>&attr)
|
|||
attributes_ = attr;
|
||||
}
|
||||
|
||||
void NetEMemory::set_width(unsigned w)
|
||||
bool NetEMemory::set_width(unsigned w)
|
||||
{
|
||||
assert(w == mem_->width());
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
NetESignal::NetESignal(NetNet*n)
|
||||
|
|
@ -550,15 +561,16 @@ NetESignal::~NetESignal()
|
|||
{
|
||||
}
|
||||
|
||||
void NetESignal::set_width(unsigned w)
|
||||
bool NetESignal::set_width(unsigned w)
|
||||
{
|
||||
if (w != pin_count()) {
|
||||
cerr << get_line() << ": Width of " << w << " does not match "
|
||||
<< *this << endl;
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
assert(w == pin_count());
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
NetESubSignal::NetESubSignal(NetESignal*sig, NetExpr*ex)
|
||||
|
|
@ -576,18 +588,25 @@ NetEUnary::~NetEUnary()
|
|||
expr_.clr_and_delete();
|
||||
}
|
||||
|
||||
void NetEUnary::set_width(unsigned w)
|
||||
bool NetEUnary::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
switch (op_) {
|
||||
case '~':
|
||||
flag = expr_->set_width(w);
|
||||
break;
|
||||
case '&':
|
||||
assert(w == 1);
|
||||
case '!':
|
||||
if (w != 1) {
|
||||
flag = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case '~':
|
||||
expr_->set_width(w);
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
expr_width(w);
|
||||
return flag;
|
||||
}
|
||||
|
||||
NetLogic::NetLogic(const string&n, unsigned pins, TYPE t)
|
||||
|
|
@ -1059,6 +1078,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.28 1999/05/27 04:13:08 steve
|
||||
* Handle expression bit widths with non-fatal errors.
|
||||
*
|
||||
* Revision 1.27 1999/05/20 05:07:37 steve
|
||||
* Line number info with match error message.
|
||||
*
|
||||
|
|
|
|||
24
netlist.h
24
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.31 1999/05/16 05:08:42 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.32 1999/05/27 04:13:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
# include "sref.h"
|
||||
# include "LineInfo.h"
|
||||
|
||||
class Design;
|
||||
class NetNode;
|
||||
class NetProc;
|
||||
class NetProcTop;
|
||||
|
|
@ -335,8 +336,12 @@ class NetExpr : public LineInfo {
|
|||
virtual void expr_scan(struct expr_scan_t*) const =0;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// How wide am I?
|
||||
unsigned expr_width() const { return width_; }
|
||||
virtual void set_width(unsigned);
|
||||
|
||||
// Coerce the expression to have a specific width. If the
|
||||
// coersion works, then return true. Otherwise, return false.
|
||||
virtual bool set_width(unsigned);
|
||||
|
||||
public:
|
||||
class REF {
|
||||
|
|
@ -597,7 +602,7 @@ class NetProc {
|
|||
*/
|
||||
class NetAssign : public NetProc, public NetNode, public LineInfo {
|
||||
public:
|
||||
explicit NetAssign(NetNet*lv, NetExpr*rv);
|
||||
explicit NetAssign(Design*des, NetNet*lv, NetExpr*rv);
|
||||
~NetAssign();
|
||||
|
||||
const NetExpr*rval() const { return rval_.ref(); }
|
||||
|
|
@ -909,7 +914,7 @@ class NetEBinary : public NetExpr {
|
|||
|
||||
char op() const { return op_; }
|
||||
|
||||
void set_width(unsigned w);
|
||||
virtual bool set_width(unsigned w);
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
|
@ -929,7 +934,7 @@ class NetEConst : public NetExpr {
|
|||
|
||||
const verinum&value() const { return value_; }
|
||||
|
||||
virtual void set_width(unsigned w);
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -955,7 +960,7 @@ class NetEUnary : public NetExpr {
|
|||
char op() const { return op_; }
|
||||
const NetExpr* expr() const { return expr_.ref(); }
|
||||
|
||||
void set_width(unsigned w);
|
||||
virtual bool set_width(unsigned w);
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
|
@ -993,7 +998,7 @@ class NetEMemory : public NetExpr {
|
|||
const string& name () const { return mem_->name(); }
|
||||
const NetExpr* index() const { return idx_.ref(); }
|
||||
|
||||
virtual void set_width(unsigned);
|
||||
virtual bool set_width(unsigned);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -1018,7 +1023,7 @@ class NetESignal : public NetExpr, public NetNode {
|
|||
|
||||
const string& name() const { return NetNode::name(); }
|
||||
|
||||
virtual void set_width(unsigned);
|
||||
virtual bool set_width(unsigned);
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
|
|
@ -1185,6 +1190,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.32 1999/05/27 04:13:08 steve
|
||||
* Handle expression bit widths with non-fatal errors.
|
||||
*
|
||||
* Revision 1.31 1999/05/16 05:08:42 steve
|
||||
* Redo constant expression detection to happen
|
||||
* after parsing.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: netlist.txt,v 1.1 1999/05/27 04:13:08 steve Exp $"
|
||||
|
||||
|
||||
Note that the netlist.h header contains detailed descriptions of how
|
||||
things work. This is just an overview.
|
||||
|
||||
NETLIST FORMAT
|
||||
|
||||
The output from the parse and elaboration steps is a "netlist" rooted
|
||||
in a Design object. Parsing translates the design described in the
|
||||
initial source file into a temporary symbolic "pform". Elaboration
|
||||
then expands the design, resolving references and expanding
|
||||
hierarchies, to produce a flattened netlist. This is the form that
|
||||
optimizers and code generators use.
|
||||
|
||||
The design optimization processes all manipulate the netlist,
|
||||
translating it to a (hopefully) better netlist after each step. The
|
||||
complete netlist is then passed to the code generator, the emit
|
||||
function, where the final code (in the target format) is produced.
|
||||
|
||||
EXPRESSIONS
|
||||
|
||||
Expressions are represented as a tree of NetExpr nodes. The NetExpr
|
||||
base class contains the core methods that represent an expression
|
||||
node, including virtual methods to help with dealing with nested
|
||||
complexities of expressions.
|
||||
|
||||
Expressions (as expressed in the source and p-form) may also be
|
||||
elaborated structurally, where it makes sense. In this case, the
|
||||
expression is represented as the equivilent set of gates. For example,
|
||||
continuous assignment module items are elaborated as gates instead of
|
||||
as a procedural expression as it is really a structural
|
||||
description. Event expressions are also elaborated structurally as
|
||||
events are like devices that trigger behavioral statements.
|
||||
|
||||
EXPRESSION BIT WIDTH
|
||||
|
||||
The NetExpr class represents an expression. The expression has a bit
|
||||
width that it either explicitly specified, or implied by context or
|
||||
contents.
|
||||
|
||||
When each node of the expression is first constructed during
|
||||
elaboration, it is given, by type and parameters, an idea what its
|
||||
width should be. It certain cases, this is definitive, for example
|
||||
with signals. In others, it is ambiguous, as with unsized constants.
|
||||
|
||||
As the expression is built up by elaboration, operators that combine
|
||||
expressions impose bit widths of the environment or expose the bit
|
||||
widths of the sub expressions. For example, the bitwise AND (&)
|
||||
operator has a bit size implied by its operands, whereas the
|
||||
comparison (==) operator has a bit size of 1. The building up of the
|
||||
elaborated expression checks and adjusts the bit widths as the
|
||||
expression is built up, util finally the context of the expression
|
||||
takes the final bit width and makes any final adjustments.
|
||||
|
||||
The NetExpr::expr_width() method returns the calculated (or guessed)
|
||||
expression width. This method will return 0 until the width is set by
|
||||
calculation or context. If this method returns false, then it is up to
|
||||
the context that wants the width to set one. The elaboration phase
|
||||
will call the NetExpr::set_width method on an expression as soon as it
|
||||
gets to a point where it believes that it knows what the width should
|
||||
be.
|
||||
|
||||
The NetExpr::set_width(unsigned) virtual method is used by the context
|
||||
of an expression node to note to the expression that the width is
|
||||
determined and please adapt. If the expression cannot reasonably
|
||||
adapt, it will return false. Otherwise, it will adjust bit widths and
|
||||
return true.
|
||||
|
||||
XXXX I do not yet properly deal with cases where elaboration knows for
|
||||
XXXX certain that the bit width does not matter. In this case, I
|
||||
XXXX really should tell the expression node about it so that it can
|
||||
XXXX pick a practical (and optimal) width.
|
||||
|
||||
|
||||
$Log: netlist.txt,v $
|
||||
Revision 1.1 1999/05/27 04:13:08 steve
|
||||
Handle expression bit widths with non-fatal errors.
|
||||
|
||||
Loading…
Reference in New Issue