Add user function synth and clean up expression code.
This patch adds synthesize() for user functions. It also cleans up a number of inconsistencies and missing checks in the expression code.
This commit is contained in:
parent
11a33a0907
commit
fac1cc5a1c
81
dup_expr.cc
81
dup_expr.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
|
|
@ -16,9 +16,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dup_expr.cc,v 1.21 2006/11/04 06:10:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
|
|
@ -112,7 +109,7 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
|||
tmp_parms[idx] = parms_[idx]->dup_expr();
|
||||
}
|
||||
|
||||
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
|
||||
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms);
|
||||
|
||||
assert(tmp);
|
||||
return tmp;
|
||||
|
|
@ -131,77 +128,3 @@ NetEUReduce* NetEUReduce::dup_expr() const
|
|||
assert(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.21 2006/11/04 06:10:13 steve
|
||||
* Handle dup of pad as well as normal select.
|
||||
*
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.19 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.18 2004/06/17 16:06:18 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
* Revision 1.17 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.16 2003/10/31 02:47:11 steve
|
||||
* NetEUReduce has its own dup_expr method.
|
||||
*
|
||||
* Revision 1.15 2003/05/30 02:55:32 steve
|
||||
* Support parameters in real expressions and
|
||||
* as real expressions, and fix multiply and
|
||||
* divide with real results.
|
||||
*
|
||||
* Revision 1.14 2003/04/22 04:48:29 steve
|
||||
* Support event names as expressions elements.
|
||||
*
|
||||
* Revision 1.13 2003/03/15 18:08:43 steve
|
||||
* Comparison operators do have defined width.
|
||||
*
|
||||
* Revision 1.12 2003/03/15 04:46:28 steve
|
||||
* Better organize the NetESFunc return type guesses.
|
||||
*
|
||||
* Revision 1.11 2003/03/10 23:40:53 steve
|
||||
* Keep parameter constants for the ivl_target API.
|
||||
*
|
||||
* Revision 1.10 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.9 2002/11/09 00:25:27 steve
|
||||
* Add dup_expr for user defined function calls.
|
||||
*
|
||||
* Revision 1.8 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.7 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.6 2001/11/19 01:54:14 steve
|
||||
* Port close cropping behavior from mcrgb
|
||||
* Move window array reset to libmc.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.4 2000/05/07 18:20:07 steve
|
||||
* Import MCD support from Stephen Tell, and add
|
||||
* system function parameter support to the IVL core.
|
||||
*
|
||||
* Revision 1.3 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*/
|
||||
|
||||
|
|
|
|||
18
elab_expr.cc
18
elab_expr.cc
|
|
@ -197,9 +197,10 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
|||
baseline Verilog. But we allow it in our extended
|
||||
form of Verilog. */
|
||||
if (generation_flag < GN_VER2001X) {
|
||||
if (lp->expr_type()==IVL_VT_REAL || rp->expr_type()==IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: Modulus operator may not "
|
||||
"have REAL operands." << endl;
|
||||
if (lp->expr_type()==IVL_VT_REAL ||
|
||||
rp->expr_type()==IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: Modulus operator "
|
||||
"may not have REAL operands." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -237,10 +238,11 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
|||
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL
|
||||
|| rp->expr_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: Case equality may not "
|
||||
<< "have real operands." << endl;
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< "may not have real operands." << endl;
|
||||
return 0;
|
||||
}
|
||||
/* Fall through... */
|
||||
|
|
@ -628,7 +630,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
if (NetNet*res = dscope->find_signal(dscope->basename())) {
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms);
|
||||
func->set_line(*this);
|
||||
func->cast_signed(res->get_signed());
|
||||
return func;
|
||||
|
|
|
|||
217
elab_net.cc
217
elab_net.cc
|
|
@ -29,26 +29,6 @@
|
|||
# include <iostream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* Human readable version of op_ used in NetEBinary and NetEUnary.
|
||||
* XXX This isn't a complete list, but it's enough to cover the
|
||||
* restricted cases it is used for.
|
||||
*/
|
||||
static const char *human_readable_op(const char op_)
|
||||
{
|
||||
const char *type;
|
||||
switch (op_) {
|
||||
case '^': type = "^"; break; // XOR
|
||||
case 'X': type = "~^"; break; // XNOR
|
||||
case '&': type = "&"; break; // AND
|
||||
case 'A': type = "~&"; break; // NAND (~&)
|
||||
case '|': type = "|"; break; // Bitwise OR
|
||||
case 'O': type = "~|"; break; // Bitwise NOR
|
||||
default: assert(0);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a state flag that determines whether an elaborate_net must
|
||||
* report an error when it encounters an unsized number. Normally, it
|
||||
|
|
@ -158,18 +138,8 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
|
|||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (lsig == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
left_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
if (rsig == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
right_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
NetNet*osig;
|
||||
|
||||
|
|
@ -278,18 +248,8 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
|
|||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
|
||||
if (lsig == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
left_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
if (rsig == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
right_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
if (lsig->vector_width() < rsig->vector_width())
|
||||
lsig = pad_to_width(des, lsig, rsig->vector_width());
|
||||
|
|
@ -494,21 +454,10 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
(so that the eval_tree method can reduce constant
|
||||
expressions, including parameters) then turn those results
|
||||
into synthesized nets. */
|
||||
NetExpr*lexp = elab_and_eval(des, scope, left_, lwidth);
|
||||
if (lexp == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
left_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*lexp = elab_and_eval(des, scope, left_, lwidth),
|
||||
*rexp = elab_and_eval(des, scope, right_, lwidth);
|
||||
|
||||
NetExpr*rexp = elab_and_eval(des, scope, right_, lwidth);
|
||||
if (rexp == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
right_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
if (lexp == 0 || rexp == 0) return 0;
|
||||
|
||||
unsigned operand_width;
|
||||
bool real_arg = false;
|
||||
|
|
@ -539,12 +488,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) {
|
||||
|
||||
lsig = lexp->synthesize(des);
|
||||
if (lsig == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"Cannot elaborate net for " << *lexp << endl;
|
||||
return 0;
|
||||
}
|
||||
assert(lsig);
|
||||
if (lsig == 0) return 0;
|
||||
delete lexp;
|
||||
lexp = 0;
|
||||
|
||||
|
|
@ -553,6 +497,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
NetECReal rlval(vrl);
|
||||
rsig = rlval.synthesize(des);
|
||||
delete rexp;
|
||||
rexp = 0;
|
||||
} else {
|
||||
NetNet*osig = compare_eq_constant(des, scope,
|
||||
lsig, tmp, op_,
|
||||
|
|
@ -567,14 +512,16 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) {
|
||||
|
||||
rsig = rexp->synthesize(des);
|
||||
assert(rsig);
|
||||
if (rsig == 0) return 0;
|
||||
delete rexp;
|
||||
rexp = 0;
|
||||
|
||||
if (real_arg) {
|
||||
verireal vrl(tmp->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
lsig = rlval.synthesize(des);
|
||||
delete lexp;
|
||||
lexp = 0;
|
||||
} else {
|
||||
NetNet*osig = compare_eq_constant(des, scope,
|
||||
rsig, tmp, op_,
|
||||
|
|
@ -588,13 +535,13 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
|
||||
if (lsig == 0) {
|
||||
lsig = lexp->synthesize(des);
|
||||
assert(lsig);
|
||||
if (lsig == 0) return 0;
|
||||
delete lexp;
|
||||
}
|
||||
|
||||
if (rsig == 0) {
|
||||
rsig = rexp->synthesize(des);
|
||||
assert(rsig);
|
||||
if (rsig == 0) return 0;
|
||||
delete rexp;
|
||||
}
|
||||
|
||||
|
|
@ -614,6 +561,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
lsig->data_type() != IVL_VT_REAL)) {
|
||||
cerr << get_fileline() << ": sorry: comparing bit based signals "
|
||||
"and real values is not supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -661,6 +609,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
if (real_arg) {
|
||||
cerr << get_fileline() << ": error: Case equality may not "
|
||||
"have real operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, true);
|
||||
|
|
@ -673,6 +622,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
if (real_arg) {
|
||||
cerr << get_fileline() << ": error: Case inequality may not "
|
||||
"have real operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, false);
|
||||
|
|
@ -757,11 +707,10 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
|
|||
const NetExpr* fall,
|
||||
const NetExpr* decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (lsig == 0) return 0;
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
// Check the l-value width. If it is unspecified, then use the
|
||||
// largest operand width as the l-value width. Restrict the
|
||||
|
|
@ -841,10 +790,10 @@ NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
|
|||
const NetExpr* fall,
|
||||
const NetExpr* decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
if (lsig == 0) return 0;
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
/* The arguments of a modulus must have the same type. */
|
||||
if (lsig->data_type() != rsig->data_type()) {
|
||||
|
|
@ -911,35 +860,16 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
|||
const NetExpr* fall,
|
||||
const NetExpr* decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
if (lsig == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
left_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
if (rsig == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot elaborate ";
|
||||
right_->dump(cerr);
|
||||
cerr << endl;
|
||||
return 0;
|
||||
}
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
if (rsig->data_type() == IVL_VT_REAL ||
|
||||
lsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": sorry: ";
|
||||
switch (op_) {
|
||||
case 'a':
|
||||
cerr << "&&";
|
||||
break;
|
||||
case 'o':
|
||||
cerr << "||";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
cerr << " is currently unsupported for real values." << endl;
|
||||
cerr << get_fileline() << ": sorry: " << human_readable_op(op_)
|
||||
<< " is currently unsupported for real values." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1057,10 +987,10 @@ NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (lsig == 0) return 0;
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
/* The arguments of a multiply must have the same type. */
|
||||
if (lsig->data_type() != rsig->data_type()) {
|
||||
|
|
@ -1107,7 +1037,7 @@ NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
|
|||
connect(mult->pin_DataA(), lsig->pin(0));
|
||||
connect(mult->pin_DataB(), rsig->pin(0));
|
||||
|
||||
// Make a signal to carry the output from the multiply.
|
||||
/* Make a signal to carry the output from the multiply. */
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, rwidth);
|
||||
osig->data_type( lsig->data_type() );
|
||||
|
|
@ -1123,10 +1053,10 @@ NetNet* PEBinary::elaborate_net_pow_(Design*des, NetScope*scope,
|
|||
const NetExpr* fall,
|
||||
const NetExpr* decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (lsig == 0) return 0;
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
|
||||
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
/* The arguments of a power must have the same type. */
|
||||
if (lsig->data_type() != rsig->data_type()) {
|
||||
|
|
@ -1139,7 +1069,7 @@ NetNet* PEBinary::elaborate_net_pow_(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
// The power is signed if either its operands are signed.
|
||||
/* The power is signed if either of its operands are signed. */
|
||||
bool arith_is_signed = lsig->get_signed() || rsig->get_signed();
|
||||
|
||||
unsigned rwidth = lwidth;
|
||||
|
|
@ -1174,7 +1104,7 @@ NetNet* PEBinary::elaborate_net_pow_(Design*des, NetScope*scope,
|
|||
connect(powr->pin_DataA(), lsig->pin(0));
|
||||
connect(powr->pin_DataB(), rsig->pin(0));
|
||||
|
||||
// Make a signal to carry the output from the power.
|
||||
/* Make a signal to carry the output from the power. */
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, rwidth);
|
||||
osig->data_type( lsig->data_type() );
|
||||
|
|
@ -1191,12 +1121,14 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
|||
const NetExpr* decay) const
|
||||
{
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
|
||||
if (lsig == 0) return 0;
|
||||
|
||||
/* Cannot shift a real value. */
|
||||
if (lsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: shift operators "
|
||||
"cannot shift a real value." << endl;
|
||||
cerr << get_fileline() << ": error: shift operators ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") cannot shift a real value." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1358,6 +1290,7 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
|||
dwid += 1;
|
||||
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, dwid, 0, 0, 0);
|
||||
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
/* You cannot shift a value by a real amount. */
|
||||
|
|
@ -1441,7 +1374,6 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(def);
|
||||
|
||||
NetScope*dscope = def->scope();
|
||||
assert(dscope);
|
||||
|
|
@ -1470,6 +1402,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
|||
<< "port " << idx << " of call to " << path_ <<
|
||||
"." << endl;
|
||||
errors += 1;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1477,8 +1410,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
|||
eparms[idx] = tmp;
|
||||
}
|
||||
|
||||
if (errors > 0)
|
||||
return 0;
|
||||
if (errors > 0) return 0;
|
||||
|
||||
NetUserFunc*net = new NetUserFunc(scope,
|
||||
scope->local_symbol(),
|
||||
|
|
@ -1591,6 +1523,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
|
|||
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
unsigned errors = 0;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->elaborate_net(des, scope, 0,
|
||||
0, 0, 0,
|
||||
|
|
@ -1599,11 +1532,16 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
|
|||
cerr << get_fileline() << ": error: Unable to elaborate "
|
||||
<< "port " << idx << " of call to " << path_ <<
|
||||
"." << endl;
|
||||
errors += 1;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(net->pin(1+idx), tmp->pin(0));
|
||||
}
|
||||
|
||||
if (errors > 0) return 0;
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
|
|
@ -1702,7 +1640,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
|||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
des->errors += errors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2305,7 +2243,7 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
des->errors += errors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2997,13 +2935,11 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
|||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
NetNet* expr_sig = expr_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
NetNet* tru_sig = tru_->elaborate_net(des, scope, width, 0, 0, 0);
|
||||
NetNet* fal_sig = fal_->elaborate_net(des, scope, width, 0, 0, 0);
|
||||
if (expr_sig == 0 || tru_sig == 0 || fal_sig == 0) {
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetNet*expr_sig = expr_->elaborate_net(des, scope, 0, 0, 0, 0),
|
||||
*tru_sig = tru_->elaborate_net(des, scope, width, 0, 0, 0),
|
||||
*fal_sig = fal_->elaborate_net(des, scope, width, 0, 0, 0);
|
||||
|
||||
if (expr_sig == 0 || tru_sig == 0 || fal_sig == 0) return 0;
|
||||
|
||||
/* The type of the true and false expressions must
|
||||
match. These become the type of the resulting
|
||||
|
|
@ -3020,11 +2956,13 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
des->errors += 1;
|
||||
expr_type = IVL_VT_NO_TYPE;
|
||||
return 0;
|
||||
|
||||
} else if (expr_type == IVL_VT_NO_TYPE) {
|
||||
cerr << get_fileline() << ": internal error: True and false "
|
||||
<< "clauses of ternary both have NO TYPE." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The natural width of the expression is the width of the
|
||||
|
|
@ -3200,11 +3138,8 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetNet* sub_sig = expr->synthesize(des);
|
||||
if (sub_sig == 0) {
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(sub_sig);
|
||||
|
||||
if (sub_sig == 0) return 0;
|
||||
|
||||
delete expr;
|
||||
expr = 0;
|
||||
|
|
@ -3442,12 +3377,9 @@ NetNet* PEUnary::elab_net_unary_real_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetNet* sub_sig = expr->synthesize(des);
|
||||
|
||||
if (sub_sig == 0) return 0;
|
||||
delete expr;
|
||||
if (sub_sig == 0) {
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, sub_sig);
|
||||
|
||||
NetNet*sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
|
|
@ -3463,14 +3395,21 @@ NetNet* PEUnary::elab_net_unary_real_(Design*des, NetScope*scope,
|
|||
<< op_ << " expression with real values." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
case '~':
|
||||
cerr << get_fileline() << ": error: bit-wise negation ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
case '&':
|
||||
case 'A':
|
||||
case '|':
|
||||
case 'N':
|
||||
case '^':
|
||||
case 'X':
|
||||
cerr << get_fileline() << ": error: " << human_readable_op(op_)
|
||||
<< " reduction operator may not have a REAL operand." << endl;
|
||||
cerr << get_fileline() << ": error: reduction operator ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
case '!':
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
|
|||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return false;
|
||||
verinum tmp = lc->value();
|
||||
lval = verireal(tmp.as_long());
|
||||
lval = verireal(tmp.as_double());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
|
|||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
verinum tmp = rc->value();
|
||||
rval = verireal(tmp.as_long());
|
||||
rval = verireal(tmp.as_double());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
291
expr_synth.cc
291
expr_synth.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
|
|
@ -25,6 +26,57 @@
|
|||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
|
||||
{
|
||||
NetNet* sig;
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
verireal vrl(tmp->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
sig = rlval.synthesize(des);
|
||||
} else {
|
||||
cerr << obj->get_fileline() << ": sorry: Cannot convert "
|
||||
"bit based value (" << *expr << ") to real." << endl;
|
||||
des->errors += 1;
|
||||
sig = 0;
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Note that lsig, rsig and real_args are references. */
|
||||
bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
|
||||
NetNet*&lsig, NetNet*&rsig, bool&real_args,
|
||||
NetExpr*obj)
|
||||
{
|
||||
if (left->expr_type() == IVL_VT_REAL ||
|
||||
right->expr_type() == IVL_VT_REAL) {
|
||||
real_args = true;
|
||||
|
||||
/* Currently we will have a runtime assert if both expressions
|
||||
are not real, though we can convert constants. */
|
||||
if (left->expr_type() == IVL_VT_REAL) {
|
||||
lsig = left->synthesize(des);
|
||||
} else {
|
||||
lsig = convert_to_real_const(des, left, obj);
|
||||
}
|
||||
|
||||
if (right->expr_type() == IVL_VT_REAL) {
|
||||
rsig = right->synthesize(des);
|
||||
} else {
|
||||
rsig = convert_to_real_const(des, right, obj);
|
||||
}
|
||||
} else {
|
||||
real_args = false;
|
||||
lsig = left->synthesize(des);
|
||||
rsig = right->synthesize(des);
|
||||
|
||||
}
|
||||
|
||||
if (lsig == 0 || rsig == 0) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
|
||||
|
|
@ -40,8 +92,12 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
|||
{
|
||||
assert((op()=='+') || (op()=='-'));
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(expr_width() >= lsig->vector_width());
|
||||
assert(expr_width() >= rsig->vector_width());
|
||||
|
|
@ -87,6 +143,17 @@ NetNet* NetEBBits::synthesize(Design*des)
|
|||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
/* You cannot do bitwise operations on real values. */
|
||||
if (lsig->data_type() == IVL_VT_REAL ||
|
||||
rsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: " << human_readable_op(op_)
|
||||
<< " operator may not have REAL operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
|
|
@ -98,6 +165,7 @@ NetNet* NetEBBits::synthesize(Design*des)
|
|||
<< lsig->vector_width() << ": " << *left_ << endl;
|
||||
cerr << get_fileline() << ": : width="
|
||||
<< rsig->vector_width() << ": " << *right_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +183,9 @@ NetNet* NetEBBits::synthesize(Design*des)
|
|||
case '&':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND, wid);
|
||||
break;
|
||||
case 'A':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NAND, wid);
|
||||
break;
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR, wid);
|
||||
break;
|
||||
|
|
@ -144,19 +215,27 @@ NetNet* NetEBBits::synthesize(Design*des)
|
|||
NetNet* NetEBComp::synthesize(Design*des)
|
||||
{
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (real_args) {
|
||||
width = 1;
|
||||
} else {
|
||||
width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width) width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width)
|
||||
width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->set_line(*this);
|
||||
|
|
@ -165,7 +244,7 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
|
||||
/* Handle the special case of a single bit equality
|
||||
operation. Make an XNOR gate instead of a comparator. */
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E')) && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR, 1);
|
||||
gate->set_line(*this);
|
||||
|
|
@ -179,7 +258,7 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
/* Handle the special case of a single bit inequality
|
||||
operation. This is similar to single bit equality, but uses
|
||||
an XOR instead of an XNOR gate. */
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N')) && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR, 1);
|
||||
gate->set_line(*this);
|
||||
|
|
@ -206,8 +285,14 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
case '>':
|
||||
connect(dev->pin_AGB(), osig->pin(0));
|
||||
break;
|
||||
case 'e': // ==
|
||||
case 'E': // === ?
|
||||
if (real_args) {
|
||||
cerr << get_fileline() << ": error: Case equality may "
|
||||
"not have real operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
case 'e': // ==
|
||||
connect(dev->pin_AEB(), osig->pin(0));
|
||||
break;
|
||||
case 'G': // >=
|
||||
|
|
@ -216,8 +301,14 @@ NetNet* NetEBComp::synthesize(Design*des)
|
|||
case 'L': // <=
|
||||
connect(dev->pin_ALEB(), osig->pin(0));
|
||||
break;
|
||||
case 'n': // !=
|
||||
case 'N': // !==
|
||||
if (real_args) {
|
||||
cerr << get_fileline() << ": error: Case inequality may "
|
||||
"not have real operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
case 'n': // !=
|
||||
connect(dev->pin_ANEB(), osig->pin(0));
|
||||
break;
|
||||
|
||||
|
|
@ -241,20 +332,22 @@ NetNet* NetEBPow::synthesize(Design*des)
|
|||
|
||||
NetNet* NetEBMult::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0)
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rsig == 0)
|
||||
return 0;
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetMult*mult = new NetMult(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
des->add_node(mult);
|
||||
|
|
@ -266,7 +359,7 @@ NetNet* NetEBMult::synthesize(Design*des)
|
|||
connect(mult->pin_DataB(), rsig->pin(0));
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->set_line(*this);
|
||||
osig->data_type(expr_type());
|
||||
|
|
@ -279,13 +372,21 @@ NetNet* NetEBMult::synthesize(Design*des)
|
|||
|
||||
NetNet* NetEBDiv::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->local_flag(true);
|
||||
|
|
@ -294,7 +395,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
|||
|
||||
case '/': {
|
||||
NetDivide*div = new NetDivide(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
|
|
@ -307,8 +408,16 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
|||
}
|
||||
|
||||
case '%': {
|
||||
/* Baseline Verilog does not support the % operator with
|
||||
real arguments, but we allow it in our extended form. */
|
||||
if (real_args && generation_flag < GN_VER2001X) {
|
||||
cerr << get_fileline() << ": error: Modulus operator "
|
||||
"may not have REAL operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetModulo*div = new NetModulo(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
|
|
@ -339,11 +448,16 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
|||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0)
|
||||
return 0;
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
if (rsig == 0)
|
||||
/* You cannot currently do logical operations on real values. */
|
||||
if (lsig->data_type() == IVL_VT_REAL ||
|
||||
rsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": sorry: " << human_readable_op(op_)
|
||||
<< " is currently unsupported for real values." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
|
@ -420,8 +534,17 @@ NetNet* NetEBShift::synthesize(Design*des)
|
|||
}
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
if (lsig == 0)
|
||||
|
||||
if (lsig == 0) return 0;
|
||||
|
||||
/* Cannot shift a real values. */
|
||||
if (lsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: shift operator ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") cannot shift a real values." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool right_flag = op_ == 'r' || op_ == 'R';
|
||||
bool signed_flag = op_ == 'R';
|
||||
|
|
@ -508,8 +631,8 @@ NetNet* NetEBShift::synthesize(Design*des)
|
|||
}
|
||||
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
if (rsig == 0)
|
||||
return 0;
|
||||
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
|
|
@ -627,6 +750,16 @@ NetNet* NetEUBits::synthesize(Design*des)
|
|||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
if (isig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: bit-wise negation ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
|
|
@ -659,6 +792,16 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
|||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
if (isig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: reduction operator ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
|
|
@ -710,8 +853,8 @@ NetNet* NetESelect::synthesize(Design *des)
|
|||
{
|
||||
|
||||
NetNet*sub = expr_->synthesize(des);
|
||||
if (sub == 0)
|
||||
return 0;
|
||||
|
||||
if (sub == 0) return 0;
|
||||
|
||||
NetScope*scope = sub->scope();
|
||||
|
||||
|
|
@ -803,9 +946,27 @@ NetNet* NetESelect::synthesize(Design *des)
|
|||
*/
|
||||
NetNet* NetETernary::synthesize(Design *des)
|
||||
{
|
||||
NetNet*csig = cond_->synthesize(des);
|
||||
NetNet*tsig = true_val_->synthesize(des);
|
||||
NetNet*fsig = false_val_->synthesize(des);
|
||||
NetNet*csig = cond_->synthesize(des),
|
||||
*tsig = true_val_->synthesize(des),
|
||||
*fsig = false_val_->synthesize(des);
|
||||
|
||||
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
|
||||
|
||||
if (tsig->data_type() != fsig->data_type()) {
|
||||
cerr << get_fileline() << ": error: True and False clauses of "
|
||||
"ternary expression have different types." << endl;
|
||||
cerr << get_fileline() << ": : True clause is: "
|
||||
<< tsig->data_type() << endl;
|
||||
cerr << get_fileline() << ": : False clause is: "
|
||||
<< fsig->data_type() << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
|
||||
cerr << get_fileline() << ": internal error: True and False "
|
||||
"clauses of ternary both have NO TYPE." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
perm_string path = csig->scope()->local_symbol();
|
||||
|
||||
|
|
@ -876,3 +1037,53 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* NetESFunc::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
|
||||
<< *this << " in this context" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* NetEUFunc::synthesize(Design*des)
|
||||
{
|
||||
svector<NetNet*> eparms (parms_.count());
|
||||
|
||||
/* Synthesize the arguments. */
|
||||
bool errors = false;
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->synthesize(des);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to synthesize "
|
||||
"port " << idx << " of call to "
|
||||
<< func_->basename() << "." << endl;
|
||||
errors = true;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
if (errors) return 0;
|
||||
|
||||
NetUserFunc*net = new NetUserFunc(scope_, scope_->local_symbol(), func_);
|
||||
net->set_line(*this);
|
||||
des->add_node(net);
|
||||
|
||||
/* Create an output signal and connect it to the function. */
|
||||
NetNet*osig = new NetNet(scope_, scope_->local_symbol(), NetNet::WIRE,
|
||||
result_sig_->vector_width());
|
||||
osig->local_flag(true);
|
||||
osig->data_type(result_sig_->expr_type());
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
/* Connect the pins to the arguments. */
|
||||
NetFuncDef*def = func_->func_def();
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = pad_to_width(des, eparms[idx],
|
||||
def->port(idx)->vector_width());
|
||||
connect(net->pin(idx+1), tmp->pin(0));
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1918,8 +1918,9 @@ const NetExpr* NetSTask::parm(unsigned idx) const
|
|||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetEUFunc::NetEUFunc(NetScope*def, NetESignal*res, svector<NetExpr*>&p)
|
||||
: func_(def), result_sig_(res), parms_(p)
|
||||
NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
|
||||
svector<NetExpr*>&p)
|
||||
: scope_(scope), func_(def), result_sig_(res), parms_(p)
|
||||
{
|
||||
expr_width(result_sig_->expr_width());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2492,7 +2492,7 @@ class NetTaskDef {
|
|||
class NetEUFunc : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEUFunc(NetScope*, NetESignal*, svector<NetExpr*>&);
|
||||
NetEUFunc(NetScope*, NetScope*, NetESignal*, svector<NetExpr*>&);
|
||||
~NetEUFunc();
|
||||
|
||||
const NetESignal*result_sig() const;
|
||||
|
|
@ -2509,8 +2509,10 @@ class NetEUFunc : public NetExpr {
|
|||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEUFunc*dup_expr() const;
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual NetNet* synthesize(Design*des);
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
NetScope*func_;
|
||||
NetESignal*result_sig_;
|
||||
svector<NetExpr*> parms_;
|
||||
|
|
@ -3067,6 +3069,7 @@ class NetESFunc : public NetExpr {
|
|||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetESFunc*dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
|
||||
private:
|
||||
const char* name_;
|
||||
|
|
|
|||
32
netmisc.cc
32
netmisc.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2008 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
|
||||
|
|
@ -191,3 +191,33 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
|||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Human readable version of op. Used in elaboration error messages.
|
||||
*/
|
||||
const char *human_readable_op(const char op)
|
||||
{
|
||||
const char *type;
|
||||
switch (op) {
|
||||
case '~': type = "~"; break; // Negation
|
||||
|
||||
case '^': type = "^"; break; // XOR
|
||||
case 'X': type = "~^"; break; // XNOR
|
||||
case '&': type = "&"; break; // Bitwise AND
|
||||
case 'A': type = "~&"; break; // NAND (~&)
|
||||
case '|': type = "|"; break; // Bitwise OR
|
||||
case 'O': type = "~|"; break; // NOR
|
||||
|
||||
case 'a': type = "&&"; break; // Logical AND
|
||||
case 'o': type = "||"; break; // Logical OR
|
||||
|
||||
case 'E': type = "==="; break; // Case equality
|
||||
case 'N': type = "!=="; break; // Case inequality
|
||||
|
||||
case 'l': type = "<<(<)"; break; // Left shifts
|
||||
case 'r': type = ">>"; break; // Logical right shift
|
||||
case 'R': type = ">>>"; break; // Arithmetic right shift
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
|
|
|||
10
netmisc.h
10
netmisc.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __netmisc_H
|
||||
#define __netmisc_H
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
|
|
@ -18,9 +18,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.h,v 1.31 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
|
|
@ -133,4 +130,9 @@ bool eval_as_long(long&value, NetExpr*expr);
|
|||
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path);
|
||||
|
||||
/*
|
||||
* Return a human readable version of the operator.
|
||||
*/
|
||||
const char *human_readable_op(const char op);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue