Add real comparisons in continuous assignments.

This patch adds real comparisons in continuous assignments.
It also converts bit based constants to real values when needed
by the comparisons.
This commit is contained in:
Cary R 2008-01-15 10:54:04 -08:00 committed by Stephen Williams
parent 59ee700634
commit 1ff31db2cc
10 changed files with 301 additions and 251 deletions

View File

@ -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
@ -500,16 +500,24 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
return 0;
}
unsigned operand_width;
bool real_arg = false;
if (lexp->expr_type() == IVL_VT_REAL ||
rexp->expr_type() == IVL_VT_REAL) {
operand_width = 1;
real_arg = true;
} else {
/* Choose the operand width to be the width of the widest
self-determined operand. */
unsigned operand_width = lexp->expr_width();
if (rexp->expr_width() > operand_width)
operand_width = rexp->expr_width();
operand_width = lexp->expr_width();
if (rexp->expr_width() > operand_width)
operand_width = rexp->expr_width();
lexp->set_width(operand_width);
lexp = pad_to_width(lexp, operand_width);
rexp->set_width(operand_width);
rexp = pad_to_width(rexp, operand_width);
lexp->set_width(operand_width);
lexp = pad_to_width(lexp, operand_width);
rexp->set_width(operand_width);
rexp = pad_to_width(rexp, operand_width);
}
NetNet*lsig = 0;
NetNet*rsig = 0;
@ -530,12 +538,18 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
delete lexp;
lexp = 0;
NetNet*osig = compare_eq_constant(des, scope,
lsig, tmp, op_,
rise, fall, decay);
if (osig != 0) {
delete rexp;
return osig;
if (real_arg) {
verireal vrl(tmp->value().as_double());
NetECReal rlval(vrl);
rsig = rlval.synthesize(des);
} else {
NetNet*osig = compare_eq_constant(des, scope,
lsig, tmp, op_,
rise, fall, decay);
if (osig != 0) {
delete rexp;
return osig;
}
}
}
@ -545,12 +559,18 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
assert(rsig);
delete rexp;
NetNet*osig = compare_eq_constant(des, scope,
rsig, tmp, op_,
rise, fall, decay);
if (osig != 0) {
delete lexp;
return osig;
if (real_arg) {
verireal vrl(tmp->value().as_double());
NetECReal rlval(vrl);
lsig = rlval.synthesize(des);
} else {
NetNet*osig = compare_eq_constant(des, scope,
rsig, tmp, op_,
rise, fall, decay);
if (osig != 0) {
delete lexp;
return osig;
}
}
}
@ -572,11 +592,18 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
/* Operands of binary compare need to be padded to equal
size. Figure the pad bit needed to extend the narrowest
vector. */
if (lsig->vector_width() < dwidth)
if (!real_arg && lsig->vector_width() < dwidth)
lsig = pad_to_width(des, lsig, dwidth);
if (rsig->vector_width() < dwidth)
if (!real_arg && rsig->vector_width() < dwidth)
rsig = pad_to_width(des, rsig, dwidth);
/* For now the runtime cannot convert a vec4 to a real value. */
if (real_arg && (rsig->data_type() != IVL_VT_REAL ||
lsig->data_type() != IVL_VT_REAL)) {
cerr << get_fileline() << ": sorry: comparing bit based signals "
"and real values is not supported." << endl;
return 0;
}
NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
osig->data_type(IVL_VT_LOGIC);
@ -619,6 +646,11 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
}
case 'E': // Case equals (===)
if (real_arg) {
cerr << get_fileline() << ": error: Case equality may not "
"have real operands." << endl;
return 0;
}
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, true);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
@ -626,6 +658,11 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
break;
case 'N': // Case equals (!==)
if (real_arg) {
cerr << get_fileline() << ": error: Case inequality may not "
"have real operands." << endl;
return 0;
}
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, false);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
@ -636,7 +673,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
/* Handle the special case of single bit compare with a
single XNOR gate. This is easy and direct. */
if (dwidth == 1) {
if (dwidth == 1 && !real_arg){
gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR, 1);
connect(gate->pin(0), osig->pin(0));
@ -664,7 +701,8 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
/* Handle the special case of single bit compare with a
single XOR gate. This is easy and direct. */
if (dwidth == 1) {
if (dwidth == 1 && lsig->data_type() != IVL_VT_REAL &&
rsig->data_type() != IVL_VT_REAL) {
gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR, 1);
connect(gate->pin(0), osig->pin(0));
@ -1124,7 +1162,7 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
connect(cc->pin(0), osig->pin(0));
/* Make the part select of the left expression and
connect it to the lsb or msb of the concatenation,
connect it to the LSB or MSB of the concatenation,
depending on the direction of the shift. */
NetPartSelect*part;
@ -1439,7 +1477,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
delete etmp;
if (repeat == 0) {
cerr << get_fileline() << ": error: Concatenation epeat "
cerr << get_fileline() << ": error: Concatenation repeat "
"may not be 0."
<< endl;
des->errors += 1;
@ -1448,7 +1486,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
}
if (debug_elaborate) {
cerr << get_fileline() <<": debug: PEConcat concat repeat="
cerr << get_fileline() <<": debug: PEConcat concatenation repeat="
<< repeat << "." << endl;
}
@ -1861,7 +1899,7 @@ NetNet* PEIdent::elaborate_net_net_idx_up_(Design*des, NetScope*scope,
// convert from -: to +: form.
if (down_flag) lsv -= (wid-1);
// If the part select convers exactly the entire
// If the part select covers exactly the entire
// vector, then do not bother with it. Return the
// signal itself.
if (sig->sb_to_idx(lsv) == 0 && wid == sig->vector_width())
@ -2576,7 +2614,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
return 0;
/* This should not happen. A PWire can only become
PIMPLICIT if this is a udp reg port, and the make_udp
PIMPLICIT if this is a UDP reg port, and the make_udp
function should turn it into an output.... I think. */
case NetNet::PIMPLICIT:
@ -2795,7 +2833,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
if (tru_sig->data_type() != fal_sig->data_type()) {
cerr << get_fileline() << ": error: True and False clauses of"
<< " ternary expression have differnt types." << endl;
<< " ternary expression have different types." << endl;
cerr << get_fileline() << ": : True clause is "
<< tru_sig->data_type() << ", false clause is "
<< fal_sig->data_type() << "." << endl;

View File

@ -1606,7 +1606,7 @@ static void draw_lpm_add(ivl_lpm_t net)
ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
ivl_variable_type_t dto = IVL_VT_LOGIC;
if (dta == IVL_VT_REAL && dtb == IVL_VT_REAL)
if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
dto = IVL_VT_REAL;
width = ivl_lpm_width(net);
@ -1676,29 +1676,51 @@ static void draw_lpm_cmp(ivl_lpm_t net)
unsigned width;
const char*type = "";
const char*signed_string = ivl_lpm_signed(net)? ".s" : "";
ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0));
ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
ivl_variable_type_t dtc = IVL_VT_LOGIC;
if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
dtc = IVL_VT_REAL;
width = ivl_lpm_width(net);
switch (ivl_lpm_type(net)) {
case IVL_LPM_CMP_EEQ:
assert(dtc != IVL_VT_REAL); /* Should never get here! */
type = "eeq";
signed_string = "";
break;
case IVL_LPM_CMP_EQ:
type = "eq";
if (dtc == IVL_VT_REAL)
type = "eq.r";
else
type = "eq";
signed_string = "";
break;
case IVL_LPM_CMP_GE:
type = "ge";
if (dtc == IVL_VT_REAL) {
type = "ge.r";
signed_string = "";
} else
type = "ge";
break;
case IVL_LPM_CMP_GT:
type = "gt";
if (dtc == IVL_VT_REAL) {
type = "gt.r";
signed_string = "";
} else
type = "gt";
break;
case IVL_LPM_CMP_NE:
type = "ne";
if (dtc == IVL_VT_REAL)
type = "ne.r";
else
type = "ne";
signed_string = "";
break;
case IVL_LPM_CMP_NEE:
assert(dtc != IVL_VT_REAL); /* Should never get here! */
type = "nee";
signed_string = "";
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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,15 +16,15 @@
* 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: verinum.cc,v 1.52 2007/02/25 23:08:24 steve Exp $"
#endif
# include "config.h"
# include "verinum.h"
# include <iostream>
# include <cassert>
# include <math.h> // Needed to get pow for as_double().
static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c);
verinum::verinum()
: bits_(0), nbits_(0), has_len_(false), has_sign_(false), string_flag_(false)
@ -332,6 +332,35 @@ signed long verinum::as_long() const
return val;
}
double verinum::as_double() const
{
if (nbits_ == 0) return 0.0;
/* Do we have a signed value? */
bool signed_flag = false;
if (bits_[nbits_-1] == V1) {
signed_flag = true;
}
double val = 0.0;
if (signed_flag) {
V carry = V1;
for (unsigned idx = 0; idx < nbits_; idx += 1) {
V sum = add_with_carry(~bits_[idx], V0, carry);
if (sum == V1)
val += pow(2.0, (double)idx);
}
val *= -1.0;
// val = (double) as_long();
} else {
for (unsigned idx = 0; idx < nbits_; idx += 1) {
if (bits_[idx] == V1)
val += pow(2.0, (double)idx);
}
}
return val;
}
string verinum::as_string() const
{
assert( nbits_%8 == 0 );
@ -1158,98 +1187,3 @@ verinum::V operator ^ (verinum::V l, verinum::V r)
return verinum::Vx;
}
/*
* $Log: verinum.cc,v $
* Revision 1.52 2007/02/25 23:08:24 steve
* Process Verilog escape sequences much earlier.
*
* Revision 1.51 2007/01/27 05:36:11 steve
* Fix padding of x when literal is sized and unsigned.
*
* Revision 1.50 2007/01/19 05:42:04 steve
* Fix calculation of verinum pow operation.
*
* Revision 1.49 2006/12/08 19:56:09 steve
* Handle very wide signed divide.
*
* Revision 1.48 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.47 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.46 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.45 2006/06/01 03:54:51 steve
* Fix broken subtraction of small constants.
*
* Revision 1.44 2005/12/07 04:04:24 steve
* Allow constant concat expressions.
*
* Revision 1.43 2004/05/18 18:43:15 steve
* Handle null string as a single nul character.
*
* Revision 1.42 2004/02/17 06:52:55 steve
* Support unsigned divide of huge numbers.
*
* Revision 1.41 2003/10/26 04:54:56 steve
* Support constant evaluation of binary ^ operator.
*
* Revision 1.40 2003/05/25 03:01:19 steve
* Get length of trimed unsigned value right.
*
* Revision 1.39 2003/04/14 03:40:21 steve
* Make some effort to preserve bits while
* operating on constant values.
*
* Revision 1.38 2003/04/03 04:30:00 steve
* Prevent overrun comparing verinums to zero.
*
* Revision 1.37 2003/02/02 00:43:16 steve
* Fix conversion of signed numbes to long
*
* Revision 1.36 2003/01/30 16:23:08 steve
* Spelling fixes.
*
* Revision 1.35 2002/08/19 02:39:17 steve
* Support parameters with defined ranges.
*
* Revision 1.34 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.33 2002/04/27 23:26:24 steve
* Trim leading nulls from string forms.
*
* Revision 1.32 2002/04/27 04:48:43 steve
* Display string verinums as strings.
*
* Revision 1.31 2002/02/01 05:09:14 steve
* Propagate sign in unary minus.
*
* Revision 1.30 2001/12/31 00:02:33 steve
* Include s indicator in dump of signed numbers.
*
* Revision 1.29 2001/11/19 02:54:12 steve
* Handle division and modulus by zero while
* evaluating run-time constants.
*
* Revision 1.28 2001/11/06 06:11:55 steve
* Support more real arithmetic in delay constants.
*
* Revision 1.27 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.26 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.25 2001/02/08 05:38:18 steve
* trim the length of unsized numbers.
*
* Revision 1.24 2001/02/07 21:47:13 steve
* Fix expression widths for rvalues and parameters (PR#131,132)
*/

117
verinum.h
View File

@ -1,7 +1,7 @@
#ifndef __verinum_H
#define __verinum_H
/*
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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: verinum.h,v 1.33 2007/02/02 04:33:01 steve Exp $"
#endif
# include <string>
@ -93,6 +90,7 @@ class verinum {
uint64_t as_ulong64() const;
unsigned long as_ulong() const;
signed long as_long() const;
double as_double() const;
string as_string() const;
private:
@ -158,115 +156,4 @@ extern verinum concat(const verinum&left, const verinum&right);
/* Bitwise not returns the ones complement. */
extern verinum v_not(const verinum&left);
/*
* $Log: verinum.h,v $
* Revision 1.33 2007/02/02 04:33:01 steve
* Use inttypes.h instead of stdint.h for portability.
*
* Revision 1.32 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.31 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.30 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.29 2006/06/01 03:54:51 steve
* Fix broken subtraction of small constants.
*
* Revision 1.28 2005/12/07 04:04:24 steve
* Allow constant concat expressions.
*
* Revision 1.27 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
* Revision 1.26 2004/02/17 06:52:55 steve
* Support unsigned divide of huge numbers.
*
* Revision 1.25 2003/10/26 04:54:56 steve
* Support constant evaluation of binary ^ operator.
*
* Revision 1.24 2003/04/14 03:40:21 steve
* Make some effort to preserve bits while
* operating on constant values.
*
* Revision 1.23 2003/04/03 04:30:00 steve
* Prevent overrun comparing verinums to zero.
*
* Revision 1.22 2003/01/30 16:23:08 steve
* Spelling fixes.
*
* Revision 1.21 2003/01/30 04:23:25 steve
* include config.h to get iosfwd flags.
*
* Revision 1.20 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.19 2002/06/03 04:04:24 steve
* Add verinum != operator.
*
* Revision 1.18 2001/02/10 20:29:39 steve
* In the context of range declarations, use elab_and_eval instead
* of the less robust eval_const methods.
*
* Revision 1.17 2001/02/09 05:44:23 steve
* support evaluation of constant < in expressions.
*
* Revision 1.16 2001/02/07 02:46:31 steve
* Support constant evaluation of / and % (PR#124)
*
* Revision 1.15 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.14 2001/01/02 03:23:40 steve
* Evaluate constant &, | and unary ~.
*
* Revision 1.13 2000/12/10 22:01:36 steve
* Support decimal constants in behavioral delays.
*
* Revision 1.12 2000/09/27 18:28:37 steve
* multiply in parameter expressions.
*
* Revision 1.11 2000/02/23 04:43:43 steve
* Some compilers do not accept the not symbol.
*
* Revision 1.10 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.9 2000/01/07 03:45:49 steve
* Initial support for signed constants.
*
* Revision 1.8 1999/11/06 16:00:17 steve
* Put number constants into a static table.
*
* Revision 1.7 1999/10/22 23:57:53 steve
* do the <= in bits, not numbers.
*
* Revision 1.6 1999/10/10 23:29:37 steve
* Support evaluating + operator at compile time.
*
* Revision 1.5 1999/05/13 04:02:09 steve
* More precise handling of verinum bit lengths.
*
* Revision 1.4 1998/12/20 02:05:41 steve
* Function to calculate wire initial value.
*
* Revision 1.3 1998/11/11 00:01:51 steve
* Check net ranges in declarations.
*
* Revision 1.2 1998/11/09 18:55:35 steve
* Add procedural while loops,
* Parse procedural for loops,
* Add procedural wait statements,
* Add constant nodes,
* Add XNOR logic gate,
* Make vvm output look a bit prettier.
*
* Revision 1.1 1998/11/03 23:29:08 steve
* Introduce verilog to CVS.
*
*/
#endif

View File

@ -821,3 +821,67 @@ void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit)
vvp_send_real(ptr.ptr()->out, val);
}
/* Real compare equal. */
vvp_cmp_eq_real::vvp_cmp_eq_real()
{
}
void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t res (1);
if (op_a_ == op_b_) res.set_bit(0, BIT4_1);
else res.set_bit(0, BIT4_0);
vvp_send_vec4(ptr.ptr()->out, res);
}
/* Real compare not equal. */
vvp_cmp_ne_real::vvp_cmp_ne_real()
{
}
void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t res (1);
if (op_a_ != op_b_) res.set_bit(0, BIT4_1);
else res.set_bit(0, BIT4_0);
vvp_send_vec4(ptr.ptr()->out, res);
}
/* Real compare greater than or equal. */
vvp_cmp_ge_real::vvp_cmp_ge_real()
{
}
void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t res (1);
if (op_a_ >= op_b_) res.set_bit(0, BIT4_1);
else res.set_bit(0, BIT4_0);
vvp_send_vec4(ptr.ptr()->out, res);
}
/* Real compare greater than. */
vvp_cmp_gt_real::vvp_cmp_gt_real()
{
}
void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t res (1);
if (op_a_ > op_b_) res.set_bit(0, BIT4_1);
else res.set_bit(0, BIT4_0);
vvp_send_vec4(ptr.ptr()->out, res);
}

View File

@ -247,4 +247,32 @@ class vvp_arith_sub_real : public vvp_arith_real_ {
void recv_real(vvp_net_ptr_t ptr, double bit);
};
class vvp_cmp_eq_real : public vvp_arith_real_ {
public:
explicit vvp_cmp_eq_real();
void recv_real(vvp_net_ptr_t ptr, const double bit);
};
class vvp_cmp_ne_real : public vvp_arith_real_ {
public:
explicit vvp_cmp_ne_real();
void recv_real(vvp_net_ptr_t ptr, const double bit);
};
class vvp_cmp_ge_real : public vvp_arith_real_ {
public:
explicit vvp_cmp_ge_real();
void recv_real(vvp_net_ptr_t ptr, const double bit);
};
class vvp_cmp_gt_real : public vvp_arith_real_ {
public:
explicit vvp_cmp_gt_real();
void recv_real(vvp_net_ptr_t ptr, const double bit);
};
#endif

View File

@ -1052,6 +1052,18 @@ void compile_cmp_eq(char*label, long wid, unsigned argc, struct symb_s*argv)
make_arith(arith, label, argc, argv);
}
void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv)
{
if (argc != 2) {
fprintf(stderr, "%s .cmp/eq.r has wrong number of symbols\n",label);
compile_errors += 1;
return;
}
vvp_arith_real_ *arith = new vvp_cmp_eq_real;
make_arith(arith, label, argc, argv);
}
void compile_cmp_ne(char*label, long wid, unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
@ -1066,6 +1078,18 @@ void compile_cmp_ne(char*label, long wid, unsigned argc, struct symb_s*argv)
make_arith(arith, label, argc, argv);
}
void compile_cmp_ne_r(char*label, unsigned argc, struct symb_s*argv)
{
if (argc != 2) {
fprintf(stderr, "%s .cmp/ne.r has wrong number of symbols\n",label);
compile_errors += 1;
return;
}
vvp_arith_real_ *arith = new vvp_cmp_ne_real;
make_arith(arith, label, argc, argv);
}
void compile_cmp_ge(char*label, long wid, bool signed_flag,
unsigned argc, struct symb_s*argv)
{
@ -1082,6 +1106,18 @@ void compile_cmp_ge(char*label, long wid, bool signed_flag,
make_arith(arith, label, argc, argv);
}
void compile_cmp_ge_r(char*label, unsigned argc, struct symb_s*argv)
{
if (argc != 2) {
fprintf(stderr, "%s .cmp/ge.r has wrong number of symbols\n",label);
compile_errors += 1;
return;
}
vvp_arith_real_ *arith = new vvp_cmp_ge_real;
make_arith(arith, label, argc, argv);
}
void compile_cmp_gt(char*label, long wid, bool signed_flag,
unsigned argc, struct symb_s*argv)
{
@ -1098,6 +1134,18 @@ void compile_cmp_gt(char*label, long wid, bool signed_flag,
make_arith(arith, label, argc, argv);
}
void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv)
{
if (argc != 2) {
fprintf(stderr, "%s .cmp/gt.r has wrong number of symbols\n",label);
compile_errors += 1;
return;
}
vvp_arith_real_ *arith = new vvp_cmp_gt_real;
make_arith(arith, label, argc, argv);
}
void compile_delay(char*label, vvp_delay_t*delay, struct symb_s arg)
{

View File

@ -174,6 +174,10 @@ extern void compile_arith_mult_r(char*label, unsigned argc,
extern void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_arith_sum_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_arith_sub_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_cmp_ne_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_cmp_ge_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_dff(char*label,
struct symb_s arg_d,

View File

@ -104,11 +104,15 @@
".array/port" { return K_ARRAY_PORT; }
".cmp/eeq" { return K_CMP_EEQ; }
".cmp/eq" { return K_CMP_EQ; }
".cmp/eq.r" { return K_CMP_EQ_R; }
".cmp/nee" { return K_CMP_NEE; }
".cmp/ne" { return K_CMP_NE; }
".cmp/ne.r" { return K_CMP_NE_R; }
".cmp/ge" { return K_CMP_GE; }
".cmp/ge.r" { return K_CMP_GE_R; }
".cmp/ge.s" { return K_CMP_GE_S; }
".cmp/gt" { return K_CMP_GT; }
".cmp/gt.r" { return K_CMP_GT_R; }
".cmp/gt.s" { return K_CMP_GT_S; }
".concat" { return K_CONCAT; }
".delay" { return K_DELAY; }

View File

@ -69,8 +69,8 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
%token K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R K_ARITH_SUM K_ARITH_SUM_R
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
%token K_CMP_EEQ K_CMP_EQ K_CMP_NEE K_CMP_NE
%token K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
%token K_CONCAT K_DEBUG K_DELAY K_DFF
%token K_EVENT K_EVENT_OR K_EXTEND_S K_FUNCTOR K_MODPATH K_NET K_NET_S K_NET_R
%token K_NET8 K_NET8_S
@ -315,16 +315,31 @@ statement
compile_cmp_eq($1, $3, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_EQ_R T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_eq_r($1, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_NE T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_ne($1, $3, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_NE_R T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_ne_r($1, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_GE T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_ge($1, $3, false, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_GE_R T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_ge_r($1, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_GE_S T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_ge($1, $3, true, obj.cnt, obj.vect);
@ -334,6 +349,12 @@ statement
{ struct symbv_s obj = $5;
compile_cmp_gt($1, $3, false, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_GT_R T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_gt_r($1, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_GT_S T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_gt($1, $3, true, obj.cnt, obj.vect);