From f9c67e21b289717df4dfe5dcf6569d76c87e6830 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 7 Jul 2008 11:03:06 -0700 Subject: [PATCH 1/8] Some variable part select arguments must be drawn before the part select. Some variable part selects need to draw the select argument before the variable part select is printed e.g.(.array/port). --- tgt-vvp/vvp_scope.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index c55bcb590..1731a3a4d 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1602,9 +1602,10 @@ static void draw_lpm_part(ivl_lpm_t net) net, dly, draw_net_input(ivl_lpm_data(net, 0))); fprintf(vvp_out, ", %u, %u;\n", base, width); } else { + const char*sel_symbol = draw_net_input(sel); fprintf(vvp_out, "L_%p%s .part/v %s", net, dly, draw_net_input(ivl_lpm_data(net,0))); - fprintf(vvp_out, ", %s", draw_net_input(sel)); + fprintf(vvp_out, ", %s", sel_symbol); fprintf(vvp_out, ", %u;\n", width); } } From 2ceb0539afd73949da8b73388c460a804ed3de2e Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 16 Jul 2008 13:58:16 -0700 Subject: [PATCH 2/8] IVL_VT_LOGIC is default localparam type not IVL_VT_NO_TYPE This patch fixes a bug where a local parameter with only a range was incorrectly setting the default parameter type to IVL_VT_NO_TYPE. This would create a compile time assert for any untyped parameter/localparam immediately following it. --- parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.y b/parse.y index f63ee1d9b..c97dae85b 100644 --- a/parse.y +++ b/parse.y @@ -2519,7 +2519,7 @@ localparam_assign_decl localparam_assign_list { param_active_range = 0; param_active_signed = false; - param_active_type = IVL_VT_NO_TYPE; + param_active_type = IVL_VT_LOGIC; } | K_signed range { param_active_range = $2; From 5207be0778be4c42e507cf09259d8276fab2bde6 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 16 Jul 2008 15:49:33 -0700 Subject: [PATCH 3/8] Use ivl_signal_dimensions to find arrays not ivl_signal_array_count ivl_signal_dimensions() is the correct call to use to determine if a signal is part of an array. If it is greater than zero the signal is an array. --- tgt-vvp/draw_net_input.c | 2 +- tgt-vvp/draw_ufunc.c | 8 ++++---- tgt-vvp/eval_real.c | 2 +- tgt-vvp/vvp_process.c | 10 +++++----- tgt-vvp/vvp_scope.c | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 87c13733d..1f9846d9b 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -315,7 +315,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) because it may be an array of reg vectors. */ snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin); - if (ivl_signal_array_count(sptr) > 1) { + if (ivl_signal_dimensions(sptr) > 0) { fprintf(vvp_out, "v%p_%u .array/port v%p, %u;\n", sptr, nptr_pin, sptr, nptr_pin); } diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c index 6860b8531..6ea3b3637 100644 --- a/tgt-vvp/draw_ufunc.c +++ b/tgt-vvp/draw_ufunc.c @@ -30,7 +30,7 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp) struct vector_info res; /* ports cannot be arrays. */ - assert(ivl_signal_array_count(port) == 1); + assert(ivl_signal_dimensions(port) == 0); res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0); /* We could have extra bits so only select the ones we need. */ @@ -46,7 +46,7 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t exp) int res = draw_eval_real(exp); /* ports cannot be arrays. */ - assert(ivl_signal_array_count(port) == 1); + assert(ivl_signal_dimensions(port) == 0); fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", port, res); clr_word(res); @@ -126,7 +126,7 @@ struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid) if (load_wid > ivl_signal_width(retval)) load_wid = ivl_signal_width(retval); - assert(ivl_signal_array_count(retval) == 1); + assert(ivl_signal_dimensions(retval) == 0); fprintf(vvp_out, " %%load/v %u, v%p_0, %u;\n", res.base, retval, load_wid); @@ -157,7 +157,7 @@ int draw_ufunc_real(ivl_expr_t exp) fprintf(vvp_out, " %%join;\n"); /* Return value signal cannot be an array. */ - assert(ivl_signal_array_count(retval) == 1); + assert(ivl_signal_dimensions(retval) == 0); /* Load the result into a word. */ res = allocate_word(); diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index 27e803d8d..8a7dda0f2 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -326,7 +326,7 @@ static int draw_signal_real_real(ivl_expr_t exp) int res = allocate_word(); unsigned long word = 0; - if (ivl_signal_array_count(sig) > 1) { + if (ivl_signal_dimensions(sig) > 0) { ivl_expr_t ix = ivl_expr_oper1(exp); if (!number_is_immediate(ix, 8*sizeof(word), 0)) { /* XXXX Need to generate a %load/ar instruction. */ diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index fa550cdde..41220c832 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -235,7 +235,7 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, if (dexp == 0) { /* Constant delay... */ if (number_is_immediate(word_ix, 64, 0)) { - fprintf(vvp_out, " %%ix/load 3, %lu; address\n", + fprintf(vvp_out, " %%ix/load 3, %lu; address\n", get_number_immediate(word_ix)); } else { /* Calculate array word index into index register 3 */ @@ -298,7 +298,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit, ivl_expr_t word_ix = ivl_lval_idx(lval); const unsigned long use_word = 0; - if (ivl_signal_array_count(sig) > 1) { + if (ivl_signal_dimensions(sig) > 0) { assert(word_ix); assign_to_array_word(sig, word_ix, bit, delay, dexp, part_off_ex, width); return; @@ -480,7 +480,7 @@ static int show_stmt_assign_sig_real(ivl_statement_t net) var = ivl_lval_sig(lval); assert(var != 0); - assert(ivl_signal_array_count(var) == 1); + assert(ivl_signal_dimensions(var) == 0); fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res); @@ -540,7 +540,7 @@ static int show_stmt_assign_nb_real(ivl_statement_t net) sig = ivl_lval_sig(lval); assert(sig); - if (ivl_signal_array_count(sig) > 1) { + if (ivl_signal_dimensions(sig) > 0) { word_ix = ivl_lval_idx(lval); assert(word_ix); assert(number_is_immediate(word_ix, 8*sizeof(use_word), 0)); @@ -1013,7 +1013,7 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval) use_rword = get_number_immediate(rword_idx); } - assert(ivl_signal_array_count(rsig) == 1); + assert(ivl_signal_dimensions(rsig) == 0); use_rword = 0; fprintf(vvp_out, " %s/link", command_name); diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 1731a3a4d..3be138c7e 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -879,15 +879,15 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) fprintf(vvp_out, "L_%p .delay L_%p/d", lptr, lptr); sig = ivl_expr_signal(rise_exp); - assert(ivl_signal_array_count(sig) == 1); + assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0", sig); sig = ivl_expr_signal(fall_exp); - assert(ivl_signal_array_count(sig) == 1); + assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0", sig); sig = ivl_expr_signal(decay_exp); - assert(ivl_signal_array_count(sig) == 1); + assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0;\n", sig); } } @@ -1564,7 +1564,7 @@ static void draw_lpm_ufunc(ivl_lpm_t net) else fprintf(vvp_out, ", "); - assert(ivl_signal_array_count(psig) == 1); + assert(ivl_signal_dimensions(psig) == 0); fprintf(vvp_out, "v%p_0", psig); } @@ -1574,7 +1574,7 @@ static void draw_lpm_ufunc(ivl_lpm_t net) result is collected. */ { ivl_signal_t psig = ivl_scope_port(def, 0); assert(ivl_lpm_width(net) == ivl_signal_width(psig)); - assert(ivl_signal_array_count(psig) == 1); + assert(ivl_signal_dimensions(psig) == 0); fprintf(vvp_out, " v%p_0", psig); } From 7a4f85d3828fd2ddcffe50384a450ba2b928fbca Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 16 Jul 2008 17:58:34 -0700 Subject: [PATCH 4/8] Make .part/pv strength aware and resolv vec8_pv aware. This patch makes .part/pv strength aware, resolv vec8_pv aware. vvp_net_fun_t adds vec8_pv as a virtual function with an appropriate error default. vvp_fun_signal should full support vec8_pv (not tested and may not be needed). --- vvp/part.cc | 15 +++++++++++++++ vvp/part.h | 1 + vvp/resolv.cc | 18 ++++++++++++++++++ vvp/resolv.h | 2 ++ vvp/vvp_net.cc | 17 ++++++++++++++++- vvp/vvp_net.h | 17 +++++++++++++++++ 6 files changed, 69 insertions(+), 1 deletion(-) diff --git a/vvp/part.cc b/vvp/part.cc index 5b11485ce..3b7f6e500 100644 --- a/vvp/part.cc +++ b/vvp/part.cc @@ -109,6 +109,21 @@ void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) vvp_send_vec4_pv(port.ptr()->out, bit, base_, wid_, vwid_); } +void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit) +{ + assert(port.port() == 0); + + if (bit.size() != wid_) { + cerr << "internal error: part_pv (strength-aware) data mismatch. " + << "base_=" << base_ << ", wid_=" << wid_ + << ", vwid_=" << vwid_ << ", bit=" << bit + << endl; + } + assert(bit.size() == wid_); + + vvp_send_vec8_pv(port.ptr()->out, bit, base_, wid_, vwid_); +} + vvp_fun_part_var::vvp_fun_part_var(unsigned w) : base_(0), wid_(w) { diff --git a/vvp/part.h b/vvp/part.h index 8fa861b1a..3fdffd886 100644 --- a/vvp/part.h +++ b/vvp/part.h @@ -62,6 +62,7 @@ class vvp_fun_part_pv : public vvp_net_fun_t { public: void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit); + void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit); private: unsigned base_; diff --git a/vvp/resolv.cc b/vvp/resolv.cc index 4448b15c8..d0db6ec3c 100644 --- a/vvp/resolv.cc +++ b/vvp/resolv.cc @@ -97,6 +97,24 @@ void resolv_functor::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit) vvp_send_vec8(ptr->out, out); } +void resolv_functor::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit, + unsigned base, unsigned wid, unsigned vwid) +{ + assert(bit.size() == wid); + vvp_vector8_t res (vwid); + + for (unsigned idx = 0 ; idx < base ; idx += 1) + res.set_bit(idx, vvp_scalar_t()); + + for (unsigned idx = 0 ; idx < wid ; idx += 1) + res.set_bit(idx+base, bit.value(idx)); + + for (unsigned idx = base+wid ; idx < vwid ; idx += 1) + res.set_bit(idx, vvp_scalar_t()); + + recv_vec8(port, res); +} + resolv_wired_logic::resolv_wired_logic() { } diff --git a/vvp/resolv.h b/vvp/resolv.h index d7aa6fe94..4f0e683c6 100644 --- a/vvp/resolv.h +++ b/vvp/resolv.h @@ -45,6 +45,8 @@ class resolv_functor : public vvp_net_fun_t { void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit, unsigned base, unsigned wid, unsigned vwid); + void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit, + unsigned base, unsigned wid, unsigned vwid); private: vvp_vector8_t val_[4]; diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index eb5f154b4..f038777a2 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -2123,7 +2123,16 @@ void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bits, unsigned base, unsigned wid, unsigned vwid) { cerr << "internal error: " << typeid(*this).name() << ": " - << "recv_vect_pv(" << bits << ", " << base + << "recv_vec4_pv(" << bits << ", " << base + << ", " << wid << ", " << vwid << ") not implemented" << endl; + assert(0); +} + +void vvp_net_fun_t::recv_vec8_pv(vvp_net_ptr_t, const vvp_vector8_t&bits, + unsigned base, unsigned wid, unsigned vwid) +{ + cerr << "internal error: " << typeid(*this).name() << ": " + << "recv_vec8_pv(" << bits << ", " << base << ", " << wid << ", " << vwid << ") not implemented" << endl; assert(0); } @@ -2402,6 +2411,12 @@ void vvp_fun_signal::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, } } +void vvp_fun_signal::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit, + unsigned base, unsigned wid, unsigned vwid) +{ + recv_vec4_pv(ptr, reduce4(bit), base, wid, vwid); +} + void vvp_fun_signal::calculate_output_(vvp_net_ptr_t ptr) { if (force_mask_.size()) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 2d352c4e3..6e6497179 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -870,6 +870,8 @@ class vvp_net_fun_t { // Part select variants of above virtual void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit, unsigned base, unsigned wid, unsigned vwid); + virtual void recv_vec8_pv(vvp_net_ptr_t p, const vvp_vector8_t&bit, + unsigned base, unsigned wid, unsigned vwid); virtual void recv_long_pv(vvp_net_ptr_t port, long bit, unsigned base, unsigned wid); @@ -1114,6 +1116,8 @@ class vvp_fun_signal : public vvp_fun_signal_vec { // Part select variants of above void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit, unsigned base, unsigned wid, unsigned vwid); + void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit, + unsigned base, unsigned wid, unsigned vwid); // Get information about the vector value. unsigned size() const; @@ -1320,4 +1324,17 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val, } } +inline void vvp_send_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&val, + unsigned base, unsigned wid, unsigned vwid) +{ + while (struct vvp_net_t*cur = ptr.ptr()) { + vvp_net_ptr_t next = cur->port[ptr.port()]; + + if (cur->fun) + cur->fun->recv_vec8_pv(ptr, val, base, wid, vwid); + + ptr = next; + } +} + #endif From 6cb3d86d15f6daff4ffb05dea0c83797011a35ce Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 22 Jul 2008 10:42:13 -0700 Subject: [PATCH 5/8] Update %cvt/vr to use new double to vector conversion (constructor). This patch updates the %cvt/vr command to use the new double to vector constructor. This allows the resulting bit pattern to be larger than a long. The old method was producing incorrect results without a warning for large bit values. --- vvp/vthread.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index f8a6d5b49..31d1c8602 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1371,14 +1371,12 @@ bool of_CVT_RI(vthread_t thr, vvp_code_t cp) bool of_CVT_VR(vthread_t thr, vvp_code_t cp) { double r = thr->words[cp->bit_idx[1]].w_real; - long rl = lround(r); unsigned base = cp->bit_idx[0]; unsigned wid = cp->number; - - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - thr_put_bit(thr, base+idx, (rl&1)? BIT4_1 : BIT4_0); - rl >>= 1; - } + vvp_vector4_t tmp(wid, r); + /* Make sure there is enough space for the new vector. */ + thr_check_addr(thr, base+wid-1); + thr->bits4.set_vec(base, tmp); return true; } From 6d4dd5ae3b12c429921039ce2a5b354e7ef3e532 Mon Sep 17 00:00:00 2001 From: nog Date: Wed, 23 Jul 2008 14:45:30 +0200 Subject: [PATCH 6/8] Fix macro argument replacements When searching for macro arguments to replace, make sure that the argument is not the begining of another identifier. --- ivlpp/lexor.lex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 7e4796047..58b1d069b 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -858,6 +858,7 @@ static int define_continue_flag = 0; static char *find_arg(char*ptr, char*head, char*arg) { char *cp = ptr; + size_t len = strlen(arg); while (1) { /* Look for a candidate match, just return if none is found. */ @@ -868,7 +869,8 @@ static char *find_arg(char*ptr, char*head, char*arg) * match is not in the middle of another identifier. */ if (cp != head && - (isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$')) { + (isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$' || + isalnum(*(cp+len)) || *(cp+len) == '_' || *(cp+len) == '$')) { cp++; continue; } From 1a41ac31453d0be9c63e36864105aa3ce5f9850d Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 23 Jul 2008 09:36:25 -0700 Subject: [PATCH 7/8] Update real to int conversion: -inf is 'b0 not 'b1 like +inf. The new real to int conversion was incorrectly setting the bits for minus infinity to all ones. This is incorrect in a two's complement encoding where the largest negative number would be a leading 1 followed by an infinite number of zeros. --- vvp/vvp_net.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index f038777a2..f77850c3e 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -373,9 +373,10 @@ vvp_vector4_t::vvp_vector4_t(unsigned size, double val) return; } - /* We return 'b1 for + or - infinity. */ + /* We return 'b1 for + infinity or 'b0 for - infinity. */ if (val && (val == 0.5*val)) { - allocate_words_(size, WORD_1_ABITS, WORD_1_BBITS); + if (val > 0) allocate_words_(size, WORD_1_ABITS, WORD_1_BBITS); + else allocate_words_(size, WORD_0_ABITS, WORD_0_BBITS); return; } From 3191b3efcb2cae02a9c301fe977b4380364dda9d Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 28 Jul 2008 20:55:47 -0700 Subject: [PATCH 8/8] An included file should start at line 1. The preprocessor was incorrectly setting the line when starting an include file to the line it was called from instead of 1. This would give incorrect line numbers for errors/warnings in the included file. --- ivlpp/lexor.lex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 58b1d069b..1624f172a 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1472,7 +1472,7 @@ static void do_include() fprintf(depend_file, "%s\n", standby->path); if (line_direct_flag) - fprintf(yyout, "\n`line %u \"%s\" 1\n", istack->lineno+1, standby->path); + fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path); standby->next = istack; standby->stringify_flag = 0;