Merge branch 'master' of steve-icarus@icarus.com:git/verilog

This commit is contained in:
Stephen Williams 2008-04-15 19:19:38 -07:00
commit 54cf66d8b4
13 changed files with 317 additions and 158 deletions

View File

@ -1784,17 +1784,6 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
assert(pc);
verinum pvalue = pc->value();
/* If the desired lwidth is more than the width of the
constant value, extend the value to fit the desired
output. */
if (lwidth > pvalue.len()) {
verinum tmp ((uint64_t)0, lwidth);
for (unsigned idx = 0 ; idx < pvalue.len() ; idx += 1)
tmp.set(idx, pvalue.get(idx));
pvalue = tmp;
}
/* If the parameter has declared dimensions, then apply
those to the dimensions of the net that we create. */
long msb = pvalue.len()-1;
@ -1810,10 +1799,23 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
lsb = tmp->value().as_long();
}
/* If the constant is smaller than its defined width extend
the value. If needed this will be padded later to fit
the real signal width. */
unsigned pwidth = msb > lsb ? msb - lsb : lsb - msb;
if (pwidth > pvalue.len()) {
verinum tmp ((uint64_t)0, pwidth);
for (unsigned idx = 0 ; idx < pvalue.len() ; idx += 1)
tmp.set(idx, pvalue.get(idx));
pvalue = tmp;
}
sig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, msb, lsb);
sig->set_line(*this);
sig->data_type(IVL_VT_LOGIC);
sig->local_flag(true);
NetConst*cp = new NetConst(scope, scope->local_symbol(),
pvalue);
cp->set_line(*this);

View File

@ -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 <acc_user.h>
# include <vpi_user.h>
@ -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 "<acc_fetch_value>";
}
/*
* $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.
*
*/

View File

@ -350,8 +350,8 @@ void pform_endmodule(const char*name)
msg << "Module " << name << " was already declared here: "
<< (*test).second->get_fileline() << endl;
VLerror(msg.str().c_str());
pform_cur_module = 0;
return;
} else {
pform_modules[mod_name] = pform_cur_module;
}
// The current lexical scope should be this module by now, and
@ -360,7 +360,6 @@ void pform_endmodule(const char*name)
lexical_scope = pform_cur_module->pscope_parent();
ivl_assert(*pform_cur_module, lexical_scope == 0);
pform_modules[mod_name] = pform_cur_module;
pform_cur_module = 0;
}

View File

@ -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;

View File

@ -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,17 @@ 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);
if (bit > 0) my_mcd_printf(mcd, "_");
}
}
static void format_error_msg(const char*msg, int leading_zero,
@ -695,7 +698,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 +1325,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 +1393,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 +1423,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 +1458,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 +1492,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 +1503,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 +1538,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 +1576,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 +1588,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 +1616,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 +1653,38 @@ 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]);
/* 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);
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 +1704,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. */

View File

@ -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

View File

@ -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);

View File

@ -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} },

View File

@ -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 <label>, <bit>, <wid>
Perform continuous assign of a constant value to part of the target
variable. This is similar to %set/x instruction, but it uses the
cassign port (port-1) of the signal functor instead of the normal
assign port (port-0), so the signal responds differently. See
"VARIABLE STATEMENTS" and "NET STATEMENTS" in the README.txt file.
* %cmp/u <bit-l>, <bit-r>, <wid>
* %cmp/s <bit-l>, <bit-r>, <wid>
@ -239,11 +246,15 @@ The %cvt/vr opcode converts a real word <bit-r> to a thread vector
starting at <bit-l> and with the width <wid>. Non-integer precision is
lost in the conversion.
* %deassign <var-label>
* %deassign <var-label>, <base>, <width>
Deactivate and disconnect a procedural continuous assignment to a
variable. The <var-label> identifies the affected variable.
The <base> and <width> are used to determine what part of the signal
will be deactivated. For a full deactivation the <base> is 0 and
<width> is the entire signal width.
* %delay <delay>
This opcode pauses the thread, and causes it to be rescheduled for a
@ -291,8 +302,8 @@ in the README.txt file.
* %force/x0 <label>, <bit>, <wid>
Force a constant value to part target variable. This is similar to
%set/x instruction, but it uses the force port (port-2) of the signal
Force a constant value to part of the target variable. This is similar
to %set/x instruction, but it uses the force port (port-2) of the signal
functor instead of the normal assign port (port-0), so the signal
responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS"
in the README.txt file.

View File

@ -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 <vpi_user.h>
# include <assert.h>
@ -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);
}
}

View File

@ -845,6 +845,40 @@ bool of_CASSIGN_V(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
unsigned base = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
// Implicitly, we get the base into the target vector from the
// X0 register.
long index = thr->words[0].w_int;
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*> (net->fun);
if (index < 0 && (wid <= (unsigned)-index))
return true;
if (index >= (long)sig->size())
return true;
if (index < 0) {
wid -= (unsigned) -index;
index = 0;
}
if (index+wid > sig->size())
wid = sig->size() - index;
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
vvp_net_ptr_t ptr (net, 1);
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size());
return true;
}
bool of_CMPS(vthread_t thr, vvp_code_t cp)
{
vvp_bit4_t eq = BIT4_1;
@ -1185,9 +1219,24 @@ bool of_CVT_VR(vthread_t thr, vvp_code_t cp)
bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
unsigned base = cp->bit_idx[0];
unsigned width = cp->bit_idx[1];
vvp_fun_signal_vec*sig = reinterpret_cast<vvp_fun_signal_vec*>(net->fun);
assert(sig);
if (base >= sig->size()) return true;
if (base+width > sig->size()) width = sig->size() - base;
bool full_sig = base == 0 && width == sig->size();
/* Do we release all or part of the net? */
vvp_net_ptr_t ptr (net, 3);
vvp_send_long(ptr, 1);
if (full_sig) {
vvp_send_long(ptr, 1);
} else {
vvp_send_long_pv(ptr, 1, base, width);
}
return true;
}
@ -1777,7 +1826,7 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
/* Collect the thread bits into a vector4 item. */
vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid);
/* set the value into port 1 of the destination. */
/* Set the value into port 2 of the destination. */
vvp_net_ptr_t ptr (net, 2);
vvp_send_vec4(ptr, value);
@ -1787,7 +1836,7 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
{
vvp_net_t*net = cp->net;
unsigned bit = cp->bit_idx[0];
unsigned base = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
// Implicitly, we get the base into the target vector from the
@ -1810,19 +1859,14 @@ bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
if (index+wid > sig->size())
wid = sig->size() - index;
vvp_vector4_t bit_vec(wid);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_bit4_t bit_val = thr_get_bit(thr, bit);
bit_vec.set_bit(idx, bit_val);
if (bit >= 4)
bit += 1;
}
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
vvp_net_ptr_t ptr (net, 2);
vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->size());
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size());
return true;
}
/*
* The %fork instruction causes a new child to be created and pushed
* in front of any existing child. This causes the new child to be the

View File

@ -1133,6 +1133,18 @@ bool vvp_vector2_t::is_NaN() const
return wid_ == 0;
}
bool vvp_vector2_t::is_zero() const
{
const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
for (unsigned idx = 0; idx < words; idx += 1) {
if (vec_[idx] == 0) continue;
return false;
}
return true;
}
/*
* Basic idea from "Introduction to Programming using SML" by
* Michael R. Hansen and Hans Rischel page 261 and "Seminumerical
@ -1659,6 +1671,18 @@ vvp_fun_signal_base::vvp_fun_signal_base()
void vvp_fun_signal_base::deassign()
{
continuous_assign_active_ = false;
assign_mask_ = vvp_vector2_t();
}
void vvp_fun_signal_base::deassign_pv(unsigned base, unsigned wid)
{
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
assign_mask_.set_bit(base+idx, 0);
}
if (assign_mask_.is_zero()) {
assign_mask_ = vvp_vector2_t();
}
}
/*
@ -1700,9 +1724,7 @@ void vvp_fun_signal_base::recv_long_pv(vvp_net_ptr_t ptr, long bit,
case 3: // Command port
switch (bit) {
case 1: // deassign command
fprintf(stderr, "Sorry: cannot deassign a partial signal\n");
assert(0);
deassign();
deassign_pv(base, wid);
break;
case 2: // release/net
release_pv(ptr, true, base, wid);
@ -1745,22 +1767,34 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{
switch (ptr.port()) {
case 0: // Normal input (feed from net, or set from process)
/* If continuous assign is active, then this is a var
and the continuous assigned values overrides any
normal input. So process input only if continuous
assignment is not active. */
if (!continuous_assign_active_) {
/* If we don't have a continuous assign mask then just
copy the bits, otherwise we need to see if there are
any holes in the mask so we can set those bits. */
if (assign_mask_.size() == 0) {
if (needs_init_ || !bits4_.eeq(bit)) {
bits4_ = bit;
needs_init_ = false;
calculate_output_(ptr);
}
} else {
bool changed = false;
assert(bits4_.size() == assign_mask_.size());
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1) {
if (idx >= bits4_.size()) break;
if (assign_mask_.value(idx)) continue;
bits4_.set_bit(idx, bit.value(idx));
changed = true;
}
if (changed) {
needs_init_ = false;
calculate_output_(ptr);
}
}
break;
case 1: // Continuous assign value
continuous_assign_active_ = true;
bits4_ = bit;
assign_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size());
calculate_output_(ptr);
break;
@ -1792,17 +1826,41 @@ void vvp_fun_signal::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
switch (ptr.port()) {
case 0: // Normal input
if (! continuous_assign_active_) {
if (assign_mask_.size() == 0) {
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits4_.size())
break;
if (base+idx >= bits4_.size()) break;
bits4_.set_bit(base+idx, bit.value(idx));
}
needs_init_ = false;
calculate_output_(ptr);
} else {
bool changed = false;
assert(bits4_.size() == assign_mask_.size());
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits4_.size()) break;
if (assign_mask_.value(base+idx)) continue;
bits4_.set_bit(base+idx, bit.value(idx));
changed = true;
}
if (changed) {
needs_init_ = false;
calculate_output_(ptr);
}
}
break;
case 1: // Continuous assign value
if (assign_mask_.size() == 0)
assign_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits4_.size())
break;
bits4_.set_bit(base+idx, bit.value(idx));
assign_mask_.set_bit(base+idx, 1);
}
calculate_output_(ptr);
break;
case 2: // Force value
if (force_mask_.size() == 0)
@ -1870,6 +1928,7 @@ void vvp_fun_signal::release_pv(vvp_net_ptr_t ptr, bool net,
force_mask_.set_bit(base+idx, 0);
if (!net) bits4_.set_bit(base+idx, force_.value(base+idx));
}
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t();
if (net) calculate_output_(ptr);
}
@ -1929,19 +1988,18 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
{
switch (ptr.port()) {
case 0: // Normal input (feed from net, or set from process)
if (!continuous_assign_active_) {
if (needs_init_ || !bits8_.eeq(bit)) {
bits8_ = bit;
needs_init_ = false;
calculate_output_(ptr);
}
if (needs_init_ || !bits8_.eeq(bit)) {
bits8_ = bit;
needs_init_ = false;
calculate_output_(ptr);
}
break;
case 1: // Continuous assign value
continuous_assign_active_ = true;
bits8_ = bit;
calculate_output_(ptr);
/* This is a procedural continuous assign and it can
* only be used on a register and a register is never
* strength aware. */
assert(0);
break;
case 2: // Force value
@ -1964,6 +2022,57 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
}
}
void vvp_fun_signal8::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid)
{
recv_vec8_pv(ptr, bit, base, wid, vwid);
}
void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, vvp_vector8_t bit,
unsigned base, unsigned wid, unsigned vwid)
{
assert(bit.size() == wid);
assert(bits8_.size() == vwid);
switch (ptr.port()) {
case 0: // Normal input
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (base+idx >= bits8_.size()) break;
bits8_.set_bit(base+idx, bit.value(idx));
}
needs_init_ = false;
calculate_output_(ptr);
break;
case 1: // Continuous assign value
/* This is a procedural continuous assign and it can
* only be used on a register and a register is never
* strength aware. */
assert(0);
break;
case 2: // Force value
if (force_mask_.size() == 0)
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
if (force_.size() == 0)
force_ = vvp_vector8_t(vvp_vector4_t(vwid, BIT4_Z));
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
force_mask_.set_bit(base+idx, 1);
force_.set_bit(base+idx, bit.value(idx));
}
calculate_output_(ptr);
break;
default:
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
assert(0);
break;
}
}
void vvp_fun_signal8::calculate_output_(vvp_net_ptr_t ptr)
{
if (force_mask_.size()) {
@ -2003,6 +2112,7 @@ void vvp_fun_signal8::release_pv(vvp_net_ptr_t ptr, bool net,
force_mask_.set_bit(base+idx, 0);
if (!net) bits8_.set_bit(base+idx, force_.value(base+idx));
}
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t();
if (net) calculate_output_(ptr);
}
@ -2025,9 +2135,14 @@ vvp_bit4_t vvp_fun_signal8::value(unsigned idx) const
vvp_vector4_t vvp_fun_signal8::vec4_value() const
{
if (force_mask_.size())
return reduce4(force_);
else
if (force_mask_.size()) {
vvp_vector8_t bits (bits8_);
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
return reduce4(bits);
} else
return reduce4(bits8_);
}

View File

@ -306,6 +306,7 @@ class vvp_vector2_t {
vvp_vector2_t&operator = (const vvp_vector2_t&);
bool is_NaN() const;
bool is_zero() const;
unsigned size() const;
int value(unsigned idx) const;
void set_bit(unsigned idx, int bit);
@ -834,8 +835,10 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback {
bool needs_init_;
bool continuous_assign_active_;
vvp_vector2_t force_mask_;
vvp_vector2_t assign_mask_;
void deassign();
void deassign_pv(unsigned base, unsigned wid);
virtual void release(vvp_net_ptr_t ptr, bool net) =0;
virtual void release_pv(vvp_net_ptr_t ptr, bool net,
unsigned base, unsigned wid) =0;
@ -896,8 +899,10 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec {
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
// 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_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, vvp_vector8_t bit,
unsigned base, unsigned wid, unsigned vwid);
// Get information about the vector value.
unsigned size() const;