Add support for real % in a continuous assignment.

This patch adds conditional support (2001X) for the real modulus
operator in a continuous assignment.
This commit is contained in:
Cary R 2008-01-30 18:32:27 -08:00 committed by Stephen Williams
parent 5e8a1bd8cc
commit f049426f25
8 changed files with 64 additions and 11 deletions

View File

@ -828,20 +828,28 @@ NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
des->errors += 1;
}
if (lsig->data_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: The modulus operator "
"is not supported for real values." << endl;
/* The % operator does not support real arguments in baseline
Verilog. But we allow it in our extended form of Verilog. */
if (generation_flag < GN_VER2001X && lsig->data_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: Modulus operator may not "
"have REAL operands." << endl;
des->errors += 1;
}
/* rwidth is result width. */
unsigned rwidth = lwidth;
if (rwidth == 0) {
rwidth = lsig->vector_width();
if (rsig->vector_width() > rwidth)
rwidth = rsig->vector_width();
/* Reals are always 1 wide and lsig/rsig types match here. */
if (lsig->data_type() == IVL_VT_REAL) {
lwidth = 1;
rwidth = 1;
} else {
rwidth = lsig->vector_width();
if (rsig->vector_width() > rwidth)
rwidth = rsig->vector_width();
lwidth = rwidth;
lwidth = rwidth;
}
}
NetModulo*mod = new NetModulo(scope, scope->local_symbol(), rwidth,

View File

@ -1701,7 +1701,7 @@ static void draw_lpm_add(ivl_lpm_t net)
break;
case IVL_LPM_MOD:
if (dto == IVL_VT_REAL)
assert(0); /* Not supported for reals, */
type = "mod.r";
else
type = "mod";
break;

View File

@ -805,6 +805,23 @@ void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit)
vvp_send_real(ptr.ptr()->out, val);
}
/* Real modulus. */
vvp_arith_mod_real::vvp_arith_mod_real()
{
}
vvp_arith_mod_real::~vvp_arith_mod_real()
{
}
void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit)
{
dispatch_operand_(ptr, bit);
double val = fmod(op_a_, op_b_);
vvp_send_real(ptr.ptr()->out, val);
}
/* Real summation. */
vvp_arith_sum_real::vvp_arith_sum_real()
{

View File

@ -231,6 +231,14 @@ class vvp_arith_div_real : public vvp_arith_real_ {
void recv_real(vvp_net_ptr_t ptr, double bit);
};
class vvp_arith_mod_real : public vvp_arith_real_ {
public:
explicit vvp_arith_mod_real();
~vvp_arith_mod_real();
void recv_real(vvp_net_ptr_t ptr, double bit);
};
class vvp_arith_mult_real : public vvp_arith_real_ {
public:

View File

@ -956,6 +956,18 @@ void compile_arith_mod(char*label, long wid,
make_arith(arith, label, argc, argv);
}
void compile_arith_mod_r(char*label, unsigned argc, struct symb_s*argv)
{
if (argc != 2) {
fprintf(stderr, "%s .arith/mod.r has wrong number of symbols\n", label);
compile_errors += 1;
return;
}
vvp_arith_real_ *arith = new vvp_arith_mod_real;
make_arith(arith, label, argc, argv);
}
void compile_arith_mult(char*label, long wid,
unsigned argc, struct symb_s*argv)
{

View File

@ -173,6 +173,7 @@ extern void compile_arith_mult_r(char*label, unsigned argc,
struct symb_s*argv);
extern void compile_arith_pow_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv);
extern void compile_arith_mod_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);

View File

@ -91,6 +91,7 @@
".arith/div.r" { return K_ARITH_DIV_R; }
".arith/div.s" { return K_ARITH_DIV_S; }
".arith/mod" { return K_ARITH_MOD; }
".arith/mod.r" { return K_ARITH_MOD_R; }
".arith/mult" { return K_ARITH_MULT; }
".arith/mult.r" { return K_ARITH_MULT_R; }
".arith/pow.r" { return K_ARITH_POW_R; }

View File

@ -66,9 +66,10 @@ static struct __vpiModPath*modpath_dst = 0;
};
%token K_ALIAS K_ALIAS_S K_ALIAS_R
%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_ARITH_POW_R K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
%token K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MOD_R
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW_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_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
@ -270,6 +271,11 @@ statement
compile_arith_mod($1, $3, obj.cnt, obj.vect);
}
| T_LABEL K_ARITH_MOD_R T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_mod_r($1, obj.cnt, obj.vect);
}
| T_LABEL K_ARITH_MULT T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_mult($1, $3, obj.cnt, obj.vect);