diff --git a/elab_net.cc b/elab_net.cc index ce8519bd2..0f5b1f12e 100644 --- a/elab_net.cc +++ b/elab_net.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 @@ -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; diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index ae6cf3ed6..f3287b23f 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -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; diff --git a/verinum.cc b/verinum.cc index 7b26a3322..98ecae9d6 100644 --- a/verinum.cc +++ b/verinum.cc @@ -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 # include +# include // 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) - */ - diff --git a/verinum.h b/verinum.h index 047f110cd..4670e45c9 100644 --- a/verinum.h +++ b/verinum.h @@ -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 @@ -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 diff --git a/vvp/arith.cc b/vvp/arith.cc index 8c7b74b37..d3f0f379e 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -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); +} + diff --git a/vvp/arith.h b/vvp/arith.h index ad16d7b10..5a6419676 100644 --- a/vvp/arith.h +++ b/vvp/arith.h @@ -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 diff --git a/vvp/compile.cc b/vvp/compile.cc index 6c6320598..c4eb70030 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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) { diff --git a/vvp/compile.h b/vvp/compile.h index 4991e33ba..cc12fe633 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -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, diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 95a437017..69e04e6d2 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -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; } diff --git a/vvp/parse.y b/vvp/parse.y index 72ddc1949..666031bb5 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -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);