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:
parent
5e8a1bd8cc
commit
f049426f25
22
elab_net.cc
22
elab_net.cc
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
17
vvp/arith.cc
17
vvp/arith.cc
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
12
vvp/parse.y
12
vvp/parse.y
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue