diff --git a/elab_net.cc b/elab_net.cc index d3c542b16..1f0abdfba 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -3491,6 +3491,18 @@ NetNet* PEUnary::elab_net_unary_real_(Design*des, NetScope*scope, des->errors += 1; break; + case 'm': // abs() + NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), 1); + tmp->set_line(*this); + tmp->rise_time(rise); + tmp->fall_time(fall); + tmp->decay_time(decay); + des->add_node(tmp); + + connect(tmp->pin(0), sig->pin(0)); + connect(tmp->pin(1), sub_sig->pin(0)); + break; + case '-': NetAddSub*sub = new NetAddSub(scope, scope->local_symbol(), 1); sub->attribute(perm_string::literal("LPM_Direction"), diff --git a/t-dll.cc b/t-dll.cc index 9dba1b907..91db2dac5 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1323,7 +1323,7 @@ void dll_target::lpm_abs(const NetAbs*net) obj->u_.arith.q = nex->t_cookie(); nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG); - nex = net->pin(0).nexus(); + nex = net->pin(1).nexus(); assert(nex->t_cookie()); /* pin(1) is the input data. */ diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 2f8e98f24..066da1b12 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -679,6 +679,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) if (lpm) switch (ivl_lpm_type(lpm)) { case IVL_LPM_FF: + case IVL_LPM_ABS: case IVL_LPM_ADD: case IVL_LPM_ARRAY: case IVL_LPM_CONCAT: @@ -1693,6 +1694,17 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net) return dly; } +static void draw_lpm_abs(ivl_lpm_t net) +{ + const char*src_table[1]; + draw_lpm_data_inputs(net, 0, 1, src_table); + + const char*dly = draw_lpm_output_delay(net); + + fprintf(vvp_out, "L_%p%s .abs %s;\n", + net, dly, src_table[0]); +} + static void draw_lpm_add(ivl_lpm_t net) { const char*src_table[2]; @@ -2338,6 +2350,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net) { switch (ivl_lpm_type(net)) { + case IVL_LPM_ABS: + draw_lpm_abs(net); + return; + case IVL_LPM_ADD: case IVL_LPM_SUB: case IVL_LPM_MULT: diff --git a/vvp/arith.cc b/vvp/arith.cc index 0fd3041e4..c7b827bbc 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -55,6 +55,41 @@ void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit) } +vvp_arith_abs::vvp_arith_abs() +{ +} + +vvp_arith_abs::~vvp_arith_abs() +{ +} + +void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit) +{ + vvp_vector4_t out (bit.size(), BIT4_0);; + + vvp_bit4_t cmp = compare_gtge_signed(bit, out, BIT4_1); + switch (cmp) { + case BIT4_1: // bit >= 0 + out = bit; + break; + case BIT4_0: // bit < 0 + out = ~bit; + out += 1; + break; + default: // There's an X. + out = vvp_vector4_t(bit.size(), BIT4_X); + break; + } + + vvp_send_vec4(ptr.ptr()->out, out); +} + +void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit) +{ + double out = fabs(bit); + vvp_send_real(ptr.ptr()->out, out); +} + // Division vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag) diff --git a/vvp/arith.h b/vvp/arith.h index acc85b263..41ccf5371 100644 --- a/vvp/arith.h +++ b/vvp/arith.h @@ -49,6 +49,17 @@ class vvp_arith_ : public vvp_net_fun_t { vvp_vector4_t x_val_; }; +class vvp_arith_abs : public vvp_net_fun_t { + public: + explicit vvp_arith_abs(); + ~vvp_arith_abs(); + + void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit); + void recv_real(vvp_net_ptr_t ptr, double bit); + + private: +}; + class vvp_arith_div : public vvp_arith_ { public: diff --git a/vvp/compile.cc b/vvp/compile.cc index a8f2dc033..0cb0a9426 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -941,6 +941,21 @@ template void make_arith(T_ *arith, char*label, free(argv); } +void compile_arith_abs(char*label, unsigned argc, struct symb_s*argv) +{ + vvp_arith_abs*arith = new vvp_arith_abs; + + vvp_net_t* ptr = new vvp_net_t; + ptr->fun = arith; + + define_functor_symbol(label, ptr); + free(label); + + assert(argc == 1); + inputs_connect(ptr, argc, argv); + free(argv); +} + void compile_arith_div(char*label, long wid, bool signed_flag, unsigned argc, struct symb_s*argv) { diff --git a/vvp/compile.h b/vvp/compile.h index b8e61a38b..21b863ee7 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -149,6 +149,8 @@ extern void compile_part_select_var(char*label, char*src, */ extern void compile_arith_pow(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); +extern void compile_arith_abs(char*label, + unsigned argc, struct symb_s*argv); extern void compile_arith_div(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_arith_mod(char*label, long width, diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 3c7222313..46032abc5 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -87,6 +87,7 @@ ".alias" { return K_ALIAS; } ".alias/real" { return K_ALIAS_R; } ".alias/s" { return K_ALIAS_S; } +".abs" { return K_ARITH_ABS; } ".arith/div" { return K_ARITH_DIV; } ".arith/div.r" { return K_ARITH_DIV_R; } ".arith/div.s" { return K_ARITH_DIV_S; } diff --git a/vvp/parse.y b/vvp/parse.y index c2521712d..5dd08a3ae 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -66,7 +66,8 @@ 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_MOD_R +%token K_ARITH_ABS K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD +%token 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 K_ARITH_POW_R K_ARITH_POW_S %token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT @@ -248,6 +249,14 @@ statement symbols ';' { compile_concat($1, $4, $5, $6, $7, $10.cnt, $10.vect); } + /* The ABS statement is a special arithmetic node that takes 1 + input. Re-use the symbols rule. */ + + | T_LABEL K_ARITH_ABS symbols ';' + { struct symbv_s obj = $3; + compile_arith_abs($1, obj.cnt, obj.vect); + } + /* Arithmetic statements generate functor arrays of a given width that take like size input vectors. */