diff --git a/tgt-vvp/draw_mux.c b/tgt-vvp/draw_mux.c index 78ef3c741..299b916fb 100644 --- a/tgt-vvp/draw_mux.c +++ b/tgt-vvp/draw_mux.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2010 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 @@ -47,6 +47,10 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz) dly = ""; if (d_rise != 0) { + unsigned dly_width = width; + if (data_type_of_nexus(ivl_lpm_q(net)) == IVL_VT_REAL) + dly_width = 0; + dly = "/d"; if (number_is_immediate(d_rise, 64, 0) && number_is_immediate(d_fall, 64, 0) && @@ -67,8 +71,9 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz) exit(1); } - fprintf(vvp_out, "L_%p .delay (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n", - net, get_number_immediate64(d_rise), + fprintf(vvp_out, "L_%p .delay %u (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n", + net, dly_width, + get_number_immediate64(d_rise), get_number_immediate64(d_fall), get_number_immediate64(d_decay), net); } else { @@ -80,7 +85,8 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz) assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL); assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL); - fprintf(vvp_out, "L_%p .delay L_%p/d", net, net); + fprintf(vvp_out, "L_%p .delay %u L_%p/d", + net, dly_width, net); sig = ivl_expr_signal(d_rise); assert(ivl_signal_dimensions(sig) == 0); diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index cdffbd909..8adb8cf81 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 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 @@ -355,6 +355,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) if (cptr) { char *result = 0; ivl_expr_t d_rise, d_fall, d_decay; + unsigned dly_width = 0; /* Constants should have exactly 1 pin, with a literal value. */ assert(nptr_pin == 0); @@ -372,10 +373,12 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) ivl_nexus_ptr_drive0(nptr), ivl_nexus_ptr_drive1(nptr)); } + dly_width = ivl_const_width(cptr); break; case IVL_VT_REAL: result = draw_Cr_to_string(ivl_const_real(cptr)); + dly_width = 0; break; default: @@ -403,9 +406,10 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) assert(! number_is_unknown(d_fall)); assert(! number_is_unknown(d_decay)); - fprintf(vvp_out, "L_%p .delay " + fprintf(vvp_out, "L_%p .delay %u " "(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n", - cptr, get_number_immediate64(d_rise), + cptr, dly_width, + get_number_immediate64(d_rise), get_number_immediate64(d_fall), get_number_immediate64(d_decay), cptr); @@ -418,7 +422,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL); assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL); - fprintf(vvp_out, "L_%p .delay L_%p/d", cptr, cptr); + fprintf(vvp_out, "L_%p .delay %u L_%p/d", + cptr, dly_width, cptr); sig = ivl_expr_signal(d_rise); assert(ivl_signal_dimensions(sig) == 0); diff --git a/tgt-vvp/modpath.c b/tgt-vvp/modpath.c index 097412d8d..c26087e5e 100644 --- a/tgt-vvp/modpath.c +++ b/tgt-vvp/modpath.c @@ -66,6 +66,8 @@ static void draw_modpath_record(const char*label, const char*driver, ccharp*src_drivers; ccharp*con_drivers; + unsigned width = ivl_signal_width(path_sig); + src_drivers = calloc(ivl_signal_npath(path_sig), sizeof(ccharp)); con_drivers = calloc(ivl_signal_npath(path_sig), sizeof(ccharp)); for (idx = 0 ; idx < ivl_signal_npath(path_sig) ; idx += 1) { @@ -81,7 +83,7 @@ static void draw_modpath_record(const char*label, const char*driver, } fprintf(vvp_out, " .scope S_%p;\n", ivl_path_scope(ivl_signal_path(path_sig,0))); - fprintf(vvp_out, "%s .modpath %s v%p_0", label, driver, path_sig); + fprintf(vvp_out, "%s .modpath %u %s v%p_0", label, width, driver, path_sig); for (idx = 0 ; idx < ivl_signal_npath(path_sig); idx += 1) { ivl_delaypath_t path = ivl_signal_path(path_sig, idx); diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 1c6334215..698c16e3a 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -878,6 +878,10 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) ivl_expr_t fall_exp = ivl_logic_delay(lptr, 1); ivl_expr_t decay_exp = ivl_logic_delay(lptr, 2); + unsigned dly_width = vector_width; + if (data_type_of_nexus(ivl_logic_pin(lptr,0)) == IVL_VT_REAL) + dly_width = 0; + if (number_is_immediate(rise_exp, 64, 0) && number_is_immediate(fall_exp, 64, 0) && number_is_immediate(decay_exp, 64, 0)) { @@ -897,8 +901,9 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) assert(0); } - fprintf(vvp_out, "L_%p .delay (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n", - lptr, get_number_immediate64(rise_exp), + fprintf(vvp_out, "L_%p .delay %u (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n", + lptr, dly_width, + get_number_immediate64(rise_exp), get_number_immediate64(fall_exp), get_number_immediate64(decay_exp), lptr); } else { @@ -910,7 +915,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL); assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL); - fprintf(vvp_out, "L_%p .delay L_%p/d", lptr, lptr); + fprintf(vvp_out, "L_%p .delay %u L_%p/d", lptr, dly_width, lptr); sig = ivl_expr_signal(rise_exp); assert(ivl_signal_dimensions(sig) == 0); @@ -1091,11 +1096,15 @@ static void draw_lpm_data_inputs(ivl_lpm_t net, unsigned base, * "" string if the node was not needed. The caller uses that string * to modify labels that are generated. */ -static const char* draw_lpm_output_delay(ivl_lpm_t net) +static const char* draw_lpm_output_delay(ivl_lpm_t net, ivl_variable_type_t dt) { ivl_expr_t d_rise = ivl_lpm_delay(net, 0); ivl_expr_t d_fall = ivl_lpm_delay(net, 1); ivl_expr_t d_decay = ivl_lpm_delay(net, 2); + unsigned width = ivl_lpm_width(net); + + if (dt == IVL_VT_REAL) + width = 0; const char*dly = ""; if (d_rise != 0) { @@ -1119,8 +1128,9 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net) } dly = "/d"; - fprintf(vvp_out, "L_%p .delay (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ")" - " L_%p/d;\n", net, get_number_immediate64(d_rise), + fprintf(vvp_out, "L_%p .delay %u (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ")" + " L_%p/d;\n", net, width, + get_number_immediate64(d_rise), get_number_immediate64(d_fall), get_number_immediate64(d_decay), net); } @@ -1131,11 +1141,12 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net) static void draw_lpm_abs(ivl_lpm_t net) { const char*src_table[1]; + ivl_variable_type_t dt = data_type_of_nexus(ivl_lpm_data(net,0)); const char*dly; draw_lpm_data_inputs(net, 0, 1, src_table); - dly = draw_lpm_output_delay(net); + dly = draw_lpm_output_delay(net, dt); fprintf(vvp_out, "L_%p%s .abs %s;\n", net, dly, src_table[0]); @@ -1148,7 +1159,7 @@ static void draw_lpm_cast_int(ivl_lpm_t net) draw_lpm_data_inputs(net, 0, 1, src_table); - dly = draw_lpm_output_delay(net); + dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); fprintf(vvp_out, "L_%p%s .cast/int %u, %s;\n", net, dly, ivl_lpm_width(net), src_table[0]); @@ -1162,7 +1173,7 @@ static void draw_lpm_cast_real(ivl_lpm_t net) draw_lpm_data_inputs(net, 0, 1, src_table); - dly = draw_lpm_output_delay(net); + dly = draw_lpm_output_delay(net, IVL_VT_REAL); if (ivl_lpm_signed(net)) is_signed = ".s"; @@ -1234,7 +1245,7 @@ static void draw_lpm_add(ivl_lpm_t net) draw_lpm_data_inputs(net, 0, 2, src_table); - dly = draw_lpm_output_delay(net); + dly = draw_lpm_output_delay(net, dto); fprintf(vvp_out, "L_%p%s .arith/%s %u, %s, %s;\n", net, dly, type, width, src_table[0], src_table[1]); @@ -1317,7 +1328,7 @@ static void draw_lpm_cmp(ivl_lpm_t net) draw_lpm_data_inputs(net, 0, 2, src_table); - dly = draw_lpm_output_delay(net); + dly = draw_lpm_output_delay(net, dtc); fprintf(vvp_out, "L_%p%s .cmp/%s%s %u, %s, %s;\n", net, dly, type, signed_string, width, @@ -1375,7 +1386,7 @@ static void draw_lpm_concat(ivl_lpm_t net) { const char*src_table[4]; unsigned icnt = ivl_lpm_size(net); - const char*dly = draw_lpm_output_delay(net); + const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); if (icnt <= 4) { /* This is the easiest case. There are 4 or fewer input @@ -1545,7 +1556,7 @@ static void draw_lpm_shiftl(ivl_lpm_t net) { unsigned width = ivl_lpm_width(net); const char* signed_flag = ivl_lpm_signed(net)? "s" : ""; - const char*dly = draw_lpm_output_delay(net); + const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); if (ivl_lpm_type(net) == IVL_LPM_SHIFTR) fprintf(vvp_out, "L_%p%s .shift/r%s %u", net, dly, signed_flag, @@ -1580,7 +1591,8 @@ static void draw_lpm_sfunc(ivl_lpm_t net) { unsigned idx; - const char*dly = draw_lpm_output_delay(net); + ivl_variable_type_t dt = data_type_of_nexus(ivl_lpm_q(net)); + const char*dly = draw_lpm_output_delay(net, dt); if (ivl_lpm_trigger(net)) fprintf(vvp_out, "L_%p%s .sfunc/e %u %u \"%s\", E_%p", net, dly, @@ -1616,7 +1628,8 @@ static void draw_lpm_ufunc(ivl_lpm_t net) const char**input_strings; ivl_scope_t def = ivl_lpm_define(net); - const char*dly = draw_lpm_output_delay(net); + ivl_variable_type_t dt = data_type_of_nexus(ivl_lpm_q(net)); + const char*dly = draw_lpm_output_delay(net, dt); /* Get all the input labels that I will use for net signals that connect to the inputs of the function. */ @@ -1681,7 +1694,7 @@ static void draw_lpm_part(ivl_lpm_t net) unsigned width, base; ivl_nexus_t sel; - const char*dly = draw_lpm_output_delay(net); + const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); width = ivl_lpm_width(net); base = ivl_lpm_base(net); @@ -1722,7 +1735,7 @@ static void draw_lpm_part_pv(ivl_lpm_t net) */ static void draw_lpm_re(ivl_lpm_t net, const char*type) { - const char*dly = draw_lpm_output_delay(net); + const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); fprintf(vvp_out, "L_%p%s .reduce/%s %s;\n", net, dly, type, draw_net_input(ivl_lpm_data(net,0))); @@ -1730,7 +1743,7 @@ static void draw_lpm_re(ivl_lpm_t net, const char*type) static void draw_lpm_repeat(ivl_lpm_t net) { - const char*dly = draw_lpm_output_delay(net); + const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); fprintf(vvp_out, "L_%p%s .repeat %u, %u, %s;\n", net, dly, ivl_lpm_width(net), ivl_lpm_size(net), @@ -1739,7 +1752,7 @@ static void draw_lpm_repeat(ivl_lpm_t net) static void draw_lpm_sign_ext(ivl_lpm_t net) { - const char*dly = draw_lpm_output_delay(net); + const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); fprintf(vvp_out, "L_%p%s .extend/s %u, %s;\n", net, dly, ivl_lpm_width(net), diff --git a/vvp/README.txt b/vvp/README.txt index 7deb3b04c..46c04c621 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) * */ @@ -375,13 +375,14 @@ delayed. The delay amount is given on the node line. Variable delay nodes have three extra inputs to receive the rise, fall and decay times that are used for delay. - .delay ( , , ) ; - .delay , , , ; + .delay ( , , ) ; + .delay , , , ; The first form above takes three constant (64bit) numbers as the initial delay, and takes a single input. The second form takes 4 net inputs, with the first being the value to delay, and the remaining to -be the delay values to use. +be the delay values to use. specifies the bit width of the +input net, with a width of 0 used to identify a real valued net. MODULE PATH DELAY STATEMENTS: @@ -389,7 +390,9 @@ A module path delay takes data from its input, then a list of module path delays. The for each possible delay set is a trigger that activates the delay. - .modpath , [ ( [? ]) ] ; + .modpath , [ ( [? ]) ] ; + + specifies the bit width of the input net. ARRAY INDEX STATEMENTS: diff --git a/vvp/compile.cc b/vvp/compile.cc index 41dd826dd..c320d9ced 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 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 @@ -1244,10 +1244,11 @@ void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv) } -void compile_delay(char*label, vvp_delay_t*delay, struct symb_s arg) +void compile_delay(char*label, unsigned width, + vvp_delay_t*delay, struct symb_s arg) { vvp_net_t*net = new vvp_net_t; - vvp_fun_delay*obj = new vvp_fun_delay(net, BIT4_X, *delay); + vvp_fun_delay*obj = new vvp_fun_delay(net, width, *delay); net->fun = obj; delete delay; @@ -1258,11 +1259,12 @@ void compile_delay(char*label, vvp_delay_t*delay, struct symb_s arg) free(label); } -void compile_delay(char*label, unsigned argc, struct symb_s*argv) +void compile_delay(char*label, unsigned width, + unsigned argc, struct symb_s*argv) { vvp_delay_t stub (0, 0, 0); vvp_net_t*net = new vvp_net_t; - vvp_fun_delay*obj = new vvp_fun_delay(net, BIT4_X, stub); + vvp_fun_delay*obj = new vvp_fun_delay(net, width, stub); net->fun = obj; inputs_connect(net, argc, argv); @@ -1289,11 +1291,11 @@ void compile_extend_signed(char*label, long wid, struct symb_s arg) input_connect(ptr, 0, arg.text); } -struct __vpiModPath* compile_modpath(char*label, struct symb_s drv, - struct symb_s dest) +struct __vpiModPath* compile_modpath(char*label, unsigned width, + struct symb_s drv, struct symb_s dest) { vvp_net_t*net = new vvp_net_t; - vvp_fun_modpath*obj = new vvp_fun_modpath(net); + vvp_fun_modpath*obj = new vvp_fun_modpath(net, width); net->fun = obj; input_connect(net, 0, drv.text); diff --git a/vvp/compile.h b/vvp/compile.h index f4dfd8ebd..482a96482 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -1,7 +1,7 @@ #ifndef __compile_H #define __compile_H /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 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 @@ -128,8 +128,10 @@ extern void compile_compiletf(struct __vpiSysTaskCall*); /* * Compile delay nodes of various form. */ -extern void compile_delay(char*label, vvp_delay_t*del, struct symb_s input); -extern void compile_delay(char*label, unsigned argc, struct symb_s*argv); +extern void compile_delay(char*label, unsigned width, + vvp_delay_t*del, struct symb_s input); +extern void compile_delay(char*label, unsigned width, + unsigned argc, struct symb_s*argv); /* * This is called by the parser to create a part select node. @@ -198,6 +200,7 @@ extern void compile_dff(char*label, class __vpiModPath; extern __vpiModPath* compile_modpath(char*label, + unsigned width, struct symb_s drv, struct symb_s dest); extern void compile_modpath_src(__vpiModPath*dst, diff --git a/vvp/delay.cc b/vvp/delay.cc index bf387751d..f57391dbe 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2009 Stephen Williams + * Copyright (c) 2005-2010 Stephen Williams * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -133,12 +133,17 @@ void vvp_delay_t::set_decay(vvp_time64_t val) calculate_min_delay_(); } -vvp_fun_delay::vvp_fun_delay(vvp_net_t*n, vvp_bit4_t init, const vvp_delay_t&d) -: net_(n), delay_(d), cur_vec4_(1) +vvp_fun_delay::vvp_fun_delay(vvp_net_t*n, unsigned width, const vvp_delay_t&d) +: net_(n), delay_(d) { - cur_vec4_.set_bit(0, init); - cur_vec8_ = vvp_vector8_t(cur_vec4_, 6, 6); cur_real_ = 0.0; + if (width > 0) { + cur_vec4_ = vvp_vector4_t(width, BIT4_X); + cur_vec8_ = vvp_vector8_t(cur_vec4_, 6, 6); + schedule_init_propagate(net_, cur_vec4_); + } else { + schedule_init_propagate(net_, cur_real_); + } list_ = 0; type_ = UNKNOWN_DELAY; initial_ = true; @@ -468,9 +473,11 @@ void vvp_fun_delay::run_run_real_(struct vvp_fun_delay::event_*cur) net_->send_real(cur_real_, 0); } -vvp_fun_modpath::vvp_fun_modpath(vvp_net_t*net) +vvp_fun_modpath::vvp_fun_modpath(vvp_net_t*net, unsigned width) : net_(net), src_list_(0), ifnone_list_(0) { + cur_vec4_ = vvp_vector4_t(width, BIT4_X); + schedule_init_propagate(net_, cur_vec4_); } vvp_fun_modpath::~vvp_fun_modpath() diff --git a/vvp/delay.h b/vvp/delay.h index 12c64e4dd..9b6eb75e7 100644 --- a/vvp/delay.h +++ b/vvp/delay.h @@ -1,7 +1,7 @@ #ifndef __delay_H #define __delay_H /* - * Copyright 2005-2008 Stephen Williams + * Copyright 2005-2008,2010 Stephen Williams * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -83,7 +83,7 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s { }; public: - vvp_fun_delay(vvp_net_t*net, vvp_bit4_t init, const vvp_delay_t&d); + vvp_fun_delay(vvp_net_t*net, unsigned width, const vvp_delay_t&d); ~vvp_fun_delay(); void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, @@ -156,7 +156,7 @@ class vvp_fun_modpath_src; class vvp_fun_modpath : public vvp_net_fun_t, private vvp_gen_event_s { public: - vvp_fun_modpath(vvp_net_t*net); + vvp_fun_modpath(vvp_net_t*net, unsigned width); ~vvp_fun_modpath(); void add_modpath_src(vvp_fun_modpath_src*that, bool ifnone); diff --git a/vvp/parse.y b/vvp/parse.y index 233bf18de..c834cda37 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -426,15 +426,15 @@ statement node takes two form, one with an array of constants and a single input, and another with an array of inputs. */ - | T_LABEL K_DELAY delay symbol ';' - { compile_delay($1, $3, $4); } - | T_LABEL K_DELAY symbols ';' - { struct symbv_s obj = $3; - compile_delay($1, obj.cnt, obj.vect); + | T_LABEL K_DELAY T_NUMBER delay symbol ';' + { compile_delay($1, $3, $4, $5); } + | T_LABEL K_DELAY T_NUMBER symbols ';' + { struct symbv_s obj = $4; + compile_delay($1, $3, obj.cnt, obj.vect); } - | T_LABEL K_MODPATH symbol symbol ',' - { modpath_dst = compile_modpath($1, $3, $4); } + | T_LABEL K_MODPATH T_NUMBER symbol symbol ',' + { modpath_dst = compile_modpath($1, $3, $4, $5); } modpath_src_list ';' { modpath_dst = 0; } diff --git a/vvp/udp.cc b/vvp/udp.cc index ae65c5cc0..4b38b349d 100644 --- a/vvp/udp.cc +++ b/vvp/udp.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2005-2010 Stephen Williams (steve@icarus.com) * * (This is a rewrite of code that was ... * Copyright (c) 2001 Stephan Boettcher ) @@ -985,7 +985,7 @@ void compile_udp_functor(char*label, char*type, if (delay != 0) { vvp_net_t*net_drv = new vvp_net_t; - vvp_fun_delay*obj_drv = new vvp_fun_delay(net_drv, BIT4_X, *delay); + vvp_fun_delay*obj_drv = new vvp_fun_delay(net_drv, 1, *delay); delete delay; net_drv->fun = obj_drv;