From ef3aacfe36d70f87e9b774a106651a621a25d66e Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 9 Apr 2008 18:16:21 -0700 Subject: [PATCH 1/5] Make %v print all the bits of a vector. This patch reworks the %v code to print the strength information for all the bits of a vector. The code previously only printed the LSB information. --- libveriuser/a_fetch_value.c | 35 ++--------------- vpi/sys_display.c | 75 +++++++++++++++++++++++-------------- vpi_user.h | 4 +- vvp/vpip_format.c | 44 ++++++++++------------ 4 files changed, 71 insertions(+), 87 deletions(-) diff --git a/libveriuser/a_fetch_value.c b/libveriuser/a_fetch_value.c index dc65ee007..c7525f02f 100644 --- a/libveriuser/a_fetch_value.c +++ b/libveriuser/a_fetch_value.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2008 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 @@ -16,9 +16,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: a_fetch_value.c,v 1.5 2003/06/17 16:55:07 steve Exp $" -#endif # include # include @@ -104,7 +101,8 @@ static char* fetch_strength_value(handle obj) val.format = vpiStrengthVal; vpi_get_value(obj, &val); - vpip_format_strength(str, &val); + /* Should this iterate over the bits? It now matches the old code. */ + vpip_format_strength(str, &val, 0); if (pli_trace) { fprintf(pli_trace, "acc_fetch_value(<%s>, \"%%v\") --> %s\n", @@ -125,30 +123,3 @@ char* acc_fetch_value(handle obj, const char*fmt, s_acc_value*value) vpi_printf("XXXX acc_fetch_value(..., \"%s\", ...)\n", fmt); return ""; } - - -/* - * $Log: a_fetch_value.c,v $ - * Revision 1.5 2003/06/17 16:55:07 steve - * 1) setlinebuf() for vpi_trace - * 2) Addes error checks for trace file opens - * 3) removes now extraneous flushes - * 4) fixes acc_next() bug - * - * Revision 1.4 2003/05/18 00:16:35 steve - * Add PLI_TRACE tracing of PLI1 modules. - * - * Add tf_isetdelay and friends, and add - * callback return values for acc_vcl support. - * - * Revision 1.3 2003/04/24 02:02:37 steve - * Clean up some simple warnings. - * - * Revision 1.2 2003/04/20 02:49:07 steve - * acc_fetch_value support for %v format. - * - * Revision 1.1 2003/04/12 18:57:14 steve - * More acc_ function stubs. - * - */ - diff --git a/vpi/sys_display.c b/vpi/sys_display.c index e6bbf8ca2..69a248fcc 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2008 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 @@ -16,9 +16,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: sys_display.c,v 1.79 2007/04/18 02:40:20 steve Exp $" -#endif # include "vpi_config.h" @@ -320,11 +317,16 @@ static void format_time_real(unsigned mcd, int fsize, } -static void format_strength(unsigned int mcd, s_vpi_value*value) +static void format_strength(unsigned int mcd, s_vpi_value*value, + unsigned size) { char str[4]; - vpip_format_strength(str, value); - my_mcd_printf(mcd, "%s", str); + int bit; + + for (bit = size-1; bit >= 0; bit -= 1) { + vpip_format_strength(str, value, (unsigned) bit); + my_mcd_printf(mcd, "%s", str); + } } static void format_error_msg(const char*msg, int leading_zero, @@ -695,7 +697,7 @@ static int format_str_char(vpiHandle scope, unsigned int mcd, return 1; } - format_strength(mcd, &value); + format_strength(mcd, &value, vpi_get(vpiSize, argv[idx])); use_count = 1; break; @@ -1322,12 +1324,16 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, s_vpi_value value; char *result, *fmtb; unsigned int size; - unsigned int max_size = 256; /* The initial size of the buffer. */ + unsigned int ini_size = 256; /* The initial size of the buffer. */ + + /* Make sure the width fits in the initial buffer. */ + if (width+1 > ini_size) ini_size = width + 1; /* The default return value is the full format. */ - result = malloc(max_size*sizeof(char)); + result = malloc(ini_size*sizeof(char)); fmtb = format_as_string(ljust, plus, ld_zero, width, prec, fmt); strcpy(result, fmtb); + size = strlen(result) + 1; /* fallback value if errors */ switch (fmt) { case '%': @@ -1386,13 +1392,13 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, } /* If the default buffer is too small, make it big enough. */ size = strlen(cp) + 1; - if (size > max_size) result = realloc(result, size*sizeof(char)); + if (size > ini_size) result = realloc(result, size*sizeof(char)); if (ljust == 0) sprintf(result, "%*s", width, cp); else sprintf(result, "%-*s", width, cp); + size = strlen(result) + 1; } } - size = strlen(result) + 1; break; case 'c': @@ -1416,9 +1422,9 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, value.value.str[strlen(value.value.str)-1]); else sprintf(result, "%-*c", width, value.value.str[strlen(value.value.str)-1]); + size = strlen(result) + 1; } } - size = strlen(result) + 1; break; case 'd': @@ -1451,13 +1457,13 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, strcpy(&tbuf[1], value.value.str); } else strcpy(&tbuf[0], value.value.str); /* If the default buffer is too small make it big enough. */ - if (size > max_size) result = realloc(result, size*sizeof(char)); + if (size > ini_size) result = realloc(result, size*sizeof(char)); if (ljust == 0) sprintf(result, "%*s", width, tbuf); else sprintf(result, "%-*s", width, tbuf); free(tbuf); + size = strlen(result) + 1; } } - size = strlen(result) + 1; break; case 'e': @@ -1485,9 +1491,9 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, while (*cp != '>') cp++; *cp = '\0'; sprintf(result, fmtb+1, value.value.real); + size = strlen(result) + 1; } } - size = strlen(result) + 1; break; /* This Verilog format specifier is not currently supported! @@ -1496,7 +1502,6 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, case 'L': vpi_printf("WARNING: %%%c currently unsupported %s%s.\n", fmt, info->name, fmtb); - size = strlen(result) + 1; break; case 'm': @@ -1532,12 +1537,12 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, if (width == -1) width = 0; /* If the default buffer is too small make it big enough. */ size = strlen(value.value.str) + 1; - if (size > max_size) result = realloc(result, size*sizeof(char)); + if (size > ini_size) result = realloc(result, size*sizeof(char)); if (ljust == 0) sprintf(result, "%*s", width, value.value.str); else sprintf(result, "%-*s", width, value.value.str); + size = strlen(result) + 1; } } - size = strlen(result) + 1; break; case 't': @@ -1570,6 +1575,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, get_time_real(tbuf, value.value.real, prec, time_units); if (ljust == 0) sprintf(result, "%*s", width, tbuf); else sprintf(result, "%-*s", width, tbuf); + size = strlen(result) + 1; } } else { value.format = vpiDecStrVal; @@ -1581,16 +1587,15 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, get_time(tbuf, value.value.str, prec, time_units); if (ljust == 0) sprintf(result, "%*s", width, tbuf); else sprintf(result, "%-*s", width, tbuf); + size = strlen(result) + 1; } } } - size = strlen(result) + 1; break; case 'u': case 'U': *idx += 1; - size = 0; /* fallback value if errors */ if (ljust != 0 || plus != 0 || ld_zero != 0 || width != -1 || prec != -1) { vpi_printf("WARNING: invalid format %s%s.\n", info->name, fmtb); @@ -1610,7 +1615,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, veclen = (vpi_get(vpiSize, info->items[*idx])+31)/32; size = veclen * 4 + 1; /* If the default buffer is too small, make it big enough. */ - if (size > max_size) result = realloc(result, size*sizeof(char)); + if (size > ini_size) result = realloc(result, size*sizeof(char)); cp = result; for (word = 0; word < veclen; word += 1) { bits = value.value.vector[word].aval & @@ -1647,22 +1652,34 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, vpi_printf("WARNING: incompatible value for %s%s.\n", info->name, fmtb); } else { - char tbuf[4]; + char tbuf[4], *rbuf; + PLI_INT32 nbits; + unsigned rsize; + int bit; /* If a width was not given use a width of zero. */ if (width == -1) width = 0; - vpip_format_strength(tbuf, &value); - if (ljust == 0) sprintf(result, "%*s", width, tbuf); - else sprintf(result, "%-*s", width, tbuf); + nbits = vpi_get(vpiSize, info->items[*idx]); + rsize = nbits*3 + 1; + rbuf = malloc(rsize*sizeof(char)); + if (rsize > ini_size) result = realloc(result, rsize*sizeof(char)); + strcpy(rbuf, ""); + for (bit = nbits-1; bit >= 0; bit -= 1) { + vpip_format_strength(tbuf, &value, bit); + strcat(rbuf, tbuf); + } + if (ljust == 0) sprintf(result, "%*s", width, rbuf); + else sprintf(result, "%-*s", width, rbuf); + free(rbuf); + size = strlen(result) + 1; } } - size = strlen(result) + 1; break; case 'z': case 'Z': *idx += 1; - size = 0; /* fallback value if errors */ + size = strlen(result) + 1; /* fallback value if errors */ if (ljust != 0 || plus != 0 || ld_zero != 0 || width != -1 || prec != -1) { vpi_printf("WARNING: invalid format %s%s.\n", info->name, fmtb); @@ -1682,7 +1699,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, veclen = (vpi_get(vpiSize, info->items[*idx])+31)/32; size = 2 * veclen * 4 + 1; /* If the default buffer is too small, make it big enough. */ - if (size > max_size) result = realloc(result, size*sizeof(char)); + if (size > ini_size) result = realloc(result, size*sizeof(char)); cp = result; for (word = 0; word < veclen; word += 1) { /* Write the aval followed by the bval in endian order. */ diff --git a/vpi_user.h b/vpi_user.h index 561ba5164..f0c739ac4 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -1,7 +1,7 @@ #ifndef __vpi_user_H #define __vpi_user_H /* - * Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2008 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 @@ -560,7 +560,7 @@ extern DLLEXPORT void (*vlog_startup_routines[])(); /* Format a scalar a la %v. The str points to a 4byte character buffer. The value must be a vpiStrengthVal. */ -extern void vpip_format_strength(char*str, s_vpi_value*value); +extern void vpip_format_strength(char*str, s_vpi_value*value, unsigned bit); EXTERN_C_END diff --git a/vvp/vpip_format.c b/vvp/vpip_format.c index cc00375cc..e6f227793 100644 --- a/vvp/vpip_format.c +++ b/vvp/vpip_format.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2008 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 @@ -16,9 +16,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: vpip_format.c,v 1.1 2003/04/20 02:49:07 steve Exp $" -#endif # include # include @@ -44,7 +41,7 @@ static const char str_char2_table[256] = { "50102010" "30102010" /* E0 EF */ "40102010" "30102010" /* F0 FF */ }; -void vpip_format_strength(char*str, s_vpi_value*value) +void vpip_format_strength(char*str, s_vpi_value*value, unsigned bit) { str[0] = '.'; str[1] = '.'; @@ -53,42 +50,42 @@ void vpip_format_strength(char*str, s_vpi_value*value) assert(value->format == vpiStrengthVal); - switch (value->value.strength[0].logic) { + switch (value->value.strength[bit].logic) { case vpi0: - str[0] = str_char1_table[value->value.strength[0].s0]; - str[1] = str_char2_table[value->value.strength[0].s0]; + str[0] = str_char1_table[value->value.strength[bit].s0]; + str[1] = str_char2_table[value->value.strength[bit].s0]; str[2] = '0'; break; case vpi1: - str[0] = str_char1_table[value->value.strength[0].s1]; - str[1] = str_char2_table[value->value.strength[0].s1]; + str[0] = str_char1_table[value->value.strength[bit].s1]; + str[1] = str_char2_table[value->value.strength[bit].s1]; str[2] = '1'; break; case vpiX: - if (value->value.strength[0].s0 == 1) { - str[0] = str_char1_table[value->value.strength[0].s1]; - str[1] = str_char2_table[value->value.strength[0].s1]; + if (value->value.strength[bit].s0 == 1) { + str[0] = str_char1_table[value->value.strength[bit].s1]; + str[1] = str_char2_table[value->value.strength[bit].s1]; str[2] = 'H'; - } else if (value->value.strength[0].s1 == 1) { - str[0] = str_char1_table[value->value.strength[0].s0]; - str[1] = str_char2_table[value->value.strength[0].s0]; + } else if (value->value.strength[bit].s1 == 1) { + str[0] = str_char1_table[value->value.strength[bit].s0]; + str[1] = str_char2_table[value->value.strength[bit].s0]; str[2] = 'L'; - } else if (value->value.strength[0].s1 == - value->value.strength[0].s0) { - str[0] = str_char1_table[value->value.strength[0].s0]; - str[1] = str_char2_table[value->value.strength[0].s0]; + } else if (value->value.strength[bit].s1 == + value->value.strength[bit].s0) { + str[0] = str_char1_table[value->value.strength[bit].s0]; + str[1] = str_char2_table[value->value.strength[bit].s0]; str[2] = 'X'; } else { int ss; str[0] = '0'; - ss = value->value.strength[0].s0; + ss = value->value.strength[bit].s0; while (ss > 1) { str[0] += 1; ss >>= 1; } str[1] = '0'; - ss = value->value.strength[0].s1; + ss = value->value.strength[bit].s1; while (ss > 1) { str[1] += 1; ss >>= 1; @@ -103,8 +100,7 @@ void vpip_format_strength(char*str, s_vpi_value*value) break; default: fprintf(stderr, "Unsupported type %d.\n", - value->value.strength[0].logic); + value->value.strength[bit].logic); assert(0); } } - From 321114e4dbf2b9279bf64ff863b68f986efc1a83 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 14 Apr 2008 15:41:39 -0700 Subject: [PATCH 2/5] Add an underscore between multiple strength values. When printing the strength information for a multi bit net this patch adds an underscore between the individual bit strength values. This makes it easier to see the individual bit values. --- vpi/sys_display.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 69a248fcc..e92ca15b6 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -326,6 +326,7 @@ static void format_strength(unsigned int mcd, s_vpi_value*value, for (bit = size-1; bit >= 0; bit -= 1) { vpip_format_strength(str, value, (unsigned) bit); my_mcd_printf(mcd, "%s", str); + if (bit > 0) my_mcd_printf(mcd, "_"); } } @@ -1660,13 +1661,17 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, /* If a width was not given use a width of zero. */ if (width == -1) width = 0; nbits = vpi_get(vpiSize, info->items[*idx]); - rsize = nbits*3 + 1; + /* This is 4 chars for all but the last bit (strenght + "_") + * which only needs three chars (strength), but then you need + * space for the EOS '\0', so it is just number of bits * 4. */ + rsize = nbits*4; rbuf = malloc(rsize*sizeof(char)); if (rsize > ini_size) result = realloc(result, rsize*sizeof(char)); strcpy(rbuf, ""); for (bit = nbits-1; bit >= 0; bit -= 1) { vpip_format_strength(tbuf, &value, bit); strcat(rbuf, tbuf); + if (bit > 0) strcat(rbuf, "_"); } if (ljust == 0) sprintf(result, "%*s", width, rbuf); else sprintf(result, "%-*s", width, rbuf); From 9bb8e8146f55905791232bbf20d797374afb6af6 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 9 Apr 2008 18:56:42 -0700 Subject: [PATCH 3/5] Add assign/deassign to bit/part selects and other fixes This patch adds the ability to assign/deassign a bit or part select. It also cleans up the code and fixes some problem in the forcing of strength aware nets. --- tgt-vvp/vvp_process.c | 24 +++---- vvp/codes.h | 1 + vvp/compile.cc | 3 +- vvp/opcodes.txt | 17 ++++- vvp/vthread.cc | 66 ++++++++++++++--- vvp/vvp_net.cc | 163 +++++++++++++++++++++++++++++++++++------- vvp/vvp_net.h | 9 ++- 7 files changed, 226 insertions(+), 57 deletions(-) diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index cac098fd3..8fa8830dc 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -802,7 +802,7 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec) switch (ivl_statement_type(net)) { case IVL_ST_CASSIGN: command_name = "%cassign/v"; - command_name_x0 = "ERROR"; + command_name_x0 = "%cassign/x0"; break; case IVL_ST_FORCE: command_name = "%force/v"; @@ -842,12 +842,6 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec) if (part_off != 0 || use_wid != ivl_signal_width(lsig)) { - if (ivl_statement_type(net) == IVL_ST_CASSIGN) { - fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot assign " - "signal to a bit/part select.\n", - ivl_stmt_file(net), ivl_stmt_lineno(net)); - exit(1); - } command_name = command_name_x0; fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off); @@ -967,15 +961,12 @@ static int show_stmt_deassign(ivl_statement_t net) assert(lsig != 0); assert(ivl_lval_mux(lval) == 0); - /* We do not currently support deassigning a bit or - * part select. */ + unsigned use_wid = ivl_lval_width(lval); ivl_expr_t part_off_ex = ivl_lval_part_off(lval); - if (ivl_signal_width(lsig) > ivl_lval_width(lval) || - (part_off_ex && get_number_immediate(part_off_ex) != 0)) { - fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot deassign " - "a bit/part select.\n", ivl_stmt_file(net), - ivl_stmt_lineno(net)); - exit(1); + unsigned part_off = 0; + if (part_off_ex != 0) { + assert(number_is_immediate(part_off_ex, 64)); + part_off = get_number_immediate(part_off_ex); } if (word_idx != 0) { @@ -984,7 +975,8 @@ static int show_stmt_deassign(ivl_statement_t net) } - fprintf(vvp_out, " %%deassign v%p_%lu;\n", lsig, use_word); + fprintf(vvp_out, " %%deassign v%p_%lu, %u, %u;\n", + lsig, use_word, part_off, use_wid); } return 0; diff --git a/vvp/codes.h b/vvp/codes.h index 0b0f7dad7..6cb5c3852 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -52,6 +52,7 @@ extern bool of_BLEND_WR(vthread_t thr, vvp_code_t code); extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code); extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code); extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code); +extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code); extern bool of_CMPIS(vthread_t thr, vvp_code_t code); extern bool of_CMPIU(vthread_t thr, vvp_code_t code); extern bool of_CMPS(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index ff073ab2f..608232b95 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -101,6 +101,7 @@ const static struct opcode_table_s opcode_table[] = { { "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%cassign/link",of_CASSIGN_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} }, { "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, + { "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, @@ -113,7 +114,7 @@ const static struct opcode_table_s opcode_table[] = { { "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%deassign",of_DEASSIGN,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 05156a6ae..6d7c6afa7 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -168,6 +168,13 @@ variable. This is similar to %set, but it uses the cassign port signal responds differently. See "VARIABLE STATEMENTS" in the README.txt file. +* %cassign/x0