Merge branch 'master' into verilog-ams

This commit is contained in:
Stephen Williams 2008-05-29 20:11:00 -07:00
commit 1be1f65f33
22 changed files with 1424 additions and 879 deletions

View File

@ -188,7 +188,13 @@ iverilog-vpi.pdf: iverilog-vpi.ps
.PHONY: version.h .PHONY: version.h
version.h: version.h:
ifeq ($(GIT),none) ifeq ($(GIT),none)
@echo '#define VERSION_TAG ""' > $@; @if test -r $(srcdir)/$@; then \
echo "Using $(srcdir)/$@ for VERSION_TAG"; \
diff $(srcdir)/$@ $@ > /dev/null 2>&1 || cp $(srcdir)/$@ $@; \
else \
echo "Using empty VERSION_TAG"; \
echo '#define VERSION_TAG ""' > $@; \
fi
else else
@if test -d $(srcdir)/.git; then \ @if test -d $(srcdir)/.git; then \
echo "Using git-describe for VERSION_TAG"; \ echo "Using git-describe for VERSION_TAG"; \

View File

@ -716,6 +716,15 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
des->errors += 1; des->errors += 1;
} }
if (!rep->value().is_defined()) {
cerr << get_fileline() << ": error: Concatenation repeat "
<< "may not be undefined (" << rep->value()
<< ")." << endl;
des->errors += 1;
concat_depth -= 1;
return 0;
}
if (rep->value().is_negative()) { if (rep->value().is_negative()) {
cerr << get_fileline() << ": error: Concatenation repeat " cerr << get_fileline() << ": error: Concatenation repeat "
<< "may not be negative (" << rep->value().as_long() << "may not be negative (" << rep->value().as_long()

View File

@ -1578,6 +1578,14 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
return 0; return 0;
} }
if (!erep->value().is_defined()) {
cerr << get_fileline() << ": error: Concatenation repeat "
<< "may not be undefined (" << erep->value()
<< ")." << endl;
des->errors += 1;
return 0;
}
if (erep->value().is_negative()) { if (erep->value().is_negative()) {
cerr << get_fileline() << ": error: Concatenation repeat " cerr << get_fileline() << ": error: Concatenation repeat "
<< "may not be negative (" << erep->value().as_long() << "may not be negative (" << erep->value().as_long()

View File

@ -226,8 +226,6 @@ ivl_switch_file
ivl_switch_lineno ivl_switch_lineno
ivl_switch_scope ivl_switch_scope
ivl_switch_type ivl_switch_type
ivl_switch_attr_cnt
ivl_switch_attr_val
ivl_udp_init ivl_udp_init
ivl_udp_name ivl_udp_name

View File

@ -1854,9 +1854,6 @@ extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
* ivl_switch_basename * ivl_switch_basename
* This is the name given to the device in the source code. * This is the name given to the device in the source code.
* *
* ivl_switch_scope
* The scope where the switch device appears.
*
* ivl_switch_a * ivl_switch_a
* ivl_switch_b * ivl_switch_b
* The a and b ports are the two ports of the switch. * The a and b ports are the two ports of the switch.
@ -1871,17 +1868,17 @@ extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
*/ */
extern ivl_switch_type_t ivl_switch_type(ivl_switch_t net); extern ivl_switch_type_t ivl_switch_type(ivl_switch_t net);
extern const char*ivl_switch_basename(ivl_switch_t net); extern const char*ivl_switch_basename(ivl_switch_t net);
extern ivl_scope_t ivl_switch_scope(ivl_switch_t net);
extern ivl_nexus_t ivl_switch_a(ivl_switch_t net); extern ivl_nexus_t ivl_switch_a(ivl_switch_t net);
extern ivl_nexus_t ivl_switch_b(ivl_switch_t net); extern ivl_nexus_t ivl_switch_b(ivl_switch_t net);
extern ivl_nexus_t ivl_switch_enable(ivl_switch_t net); extern ivl_nexus_t ivl_switch_enable(ivl_switch_t net);
/* Not implemented yet
extern unsigned ivl_switch_attr_cnt(ivl_switch_t net); extern unsigned ivl_switch_attr_cnt(ivl_switch_t net);
extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx); extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
extern const char* ivl_switch_file(ivl_switch_t net); extern const char* ivl_switch_file(ivl_switch_t net);
extern unsigned ivl_switch_lineno(ivl_switch_t net); extern unsigned ivl_switch_lineno(ivl_switch_t net);
*** */
#if defined(__MINGW32__) || defined (__CYGWIN32__) #if defined(__MINGW32__) || defined (__CYGWIN32__)
# define DLLEXPORT __declspec(dllexport) # define DLLEXPORT __declspec(dllexport)
#else #else

View File

@ -29,6 +29,82 @@
#define snprintf _snprintf #define snprintf _snprintf
#endif #endif
/*
* Check to see if the expression (number) can be correctly represented
* with a long variable.
*/
static int is_constant_number(ivl_expr_t ex)
{
/* Make sure this matches the return type of constant_number(). */
unsigned lim_wid = 8*sizeof(long);
const char*bits;
char pad_bit = '0';
unsigned idx;
unsigned nbits = ivl_expr_width(ex);
if (ivl_expr_type(ex) != IVL_EX_NUMBER
&& ivl_expr_type(ex) != IVL_EX_ULONG)
return 0;
bits = ivl_expr_bits(ex);
/* For unsigned values the effective MSB and on must be '0'. */
if (!ivl_expr_signed(ex)) lim_wid -= 1;
/* For negative values the pad bit is '1'. */
if (ivl_expr_signed(ex) && bits[nbits-1]=='1') {
pad_bit = '1';
}
/* For the number to fit in the variable all the upper bits must
* match the pad bits. */
for (idx = lim_wid ; idx < nbits ; idx += 1) {
if (bits[idx] != pad_bit) return 0;
}
return 1;
}
/*
* Convert the expression (number) to a long value.
*/
static long get_constant_number(ivl_expr_t ex)
{
long rtn = 0;
switch (ivl_expr_type(ex)) {
case IVL_EX_ULONG:
rtn = (signed)ivl_expr_value(ex);
break;
case IVL_EX_NUMBER: {
unsigned idx;
const char*bits = ivl_expr_bits(ex);
unsigned nbits = ivl_expr_width(ex);
char pad_bit = bits[nbits-1];
/* Define all the bits in the long (negative numbers). */
for (idx = 0 ; idx < 8*sizeof(long) ; idx += 1) {
char bit;
if (idx < nbits) bit = bits[idx];
else bit = pad_bit;
switch (bit) {
case '0':
break;
case '1':
rtn |= 1 << idx;
break;
default:
assert(0);
}
}
break;
}
default:
assert(0);
}
return rtn;
}
static const char* magic_sfuncs[] = { static const char* magic_sfuncs[] = {
"$time", "$time",
"$stime", "$stime",
@ -217,6 +293,39 @@ static void draw_vpi_taskfunc_args(const char*call_string,
continue; continue;
} }
case IVL_EX_SELECT: {
ivl_expr_t vexpr = ivl_expr_oper1(expr);
assert(vexpr);
/* This code is only for signals. */
if (ivl_expr_type(vexpr) != IVL_EX_SIGNAL) break;
/* The signal is part of an array. */
/* Add &APV<> code here when it is finished. */
if (ivl_expr_oper1(vexpr)) break;
ivl_expr_t bexpr = ivl_expr_oper2(expr);
assert(bexpr);
/* This is a constant bit/part select. */
if (is_constant_number(bexpr)) {
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
ivl_expr_signal(vexpr),
get_constant_number(bexpr),
ivl_expr_width(expr));
/* This is an indexed bit/part select. */
} else {
struct vector_info rv;
rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
ivl_expr_signal(vexpr),
rv.base, rv.wid,
ivl_expr_width(expr));
}
args[idx].text = strdup(buffer);
continue;
}
/* Everything else will need to be evaluated and /* Everything else will need to be evaluated and
passed as a constant to the vpi task. */ passed as a constant to the vpi task. */
default: default:

View File

@ -92,7 +92,8 @@ unsigned long get_number_immediate(ivl_expr_t ex)
case '0': case '0':
break; break;
case '1': case '1':
imm |= 1 << idx; assert(idx < 8*sizeof(imm));
imm |= 1UL << idx;
break; break;
default: default:
assert(0); assert(0);
@ -909,12 +910,43 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
return lv; return lv;
} }
static struct vector_info draw_logic_immediate(ivl_expr_t exp,
ivl_expr_t le,
ivl_expr_t re,
unsigned wid)
{
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
unsigned long imm = get_number_immediate(re);
assert(lv.base >= 4);
switch (ivl_expr_opcode(exp)) {
case '&':
fprintf(vvp_out, " %%andi %u, %lu, %u;\n", lv.base, imm, lv.wid);
break;
default:
assert(0);
break;
}
return lv;
}
static struct vector_info draw_binary_expr_logic(ivl_expr_t exp, static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
unsigned wid) unsigned wid)
{ {
ivl_expr_t le = ivl_expr_oper1(exp); ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp); ivl_expr_t re = ivl_expr_oper2(exp);
if (ivl_expr_opcode(exp) == '&') {
if (number_is_immediate(re, IMM_WID) && !number_is_unknown(re))
return draw_logic_immediate(exp, le, re, wid);
if (number_is_immediate(le, IMM_WID) && !number_is_unknown(le))
return draw_logic_immediate(exp, re, le, wid);
}
struct vector_info lv; struct vector_info lv;
struct vector_info rv; struct vector_info rv;
@ -1166,23 +1198,50 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
imm = get_number_immediate(re); imm = get_number_immediate(re);
/* Now generate enough %addi instructions to add the entire /* This shouldn't generally happen, because the elaborator
immediate value to the destination. The adds are done 16 should take care of simple constant propagation like this,
bits at a time, but 17 bits are done to push the carry into but it doesn't have to and it is easy to catch here. */
the higher bits if needed. */ if (imm == 0)
{ unsigned base; return lv;
for (base = 0 ; base < lv.wid ; base += 16) {
unsigned long tmp = imm & 0xffffUL;
unsigned add_wid = lv.wid - base;
imm >>= 16; switch (lv.base) {
case 0: /* Left expression is 0. */
lv.base = allocate_vector(wid);
if (lv.base == 0) {
fprintf(stderr, "%s:%u: vvp.tgt error: "
"Unable to allocate %u thread bits "
"for result of addition.\n",
ivl_expr_file(re), ivl_expr_lineno(re), wid);
vvp_errors += 1;
}
fprintf(vvp_out, " %%movi %u, %lu %u;\n", lv.base, imm, wid);
break;
fprintf(vvp_out, " %%addi %u, %lu, %u;\n", case 1: /* Left expression is 1...1 (i.e. -1) */
lv.base+base, tmp, add_wid); imm -= 1;
if (imm == 0) {
lv.base = 0;
} else {
lv.base = allocate_vector(wid);
if (lv.base == 0) {
fprintf(stderr, "%s:%u: vvp.tgt error: "
"Unable to allocate %u thread bits "
"for result of addition.\n",
ivl_expr_file(re), ivl_expr_lineno(re), wid);
vvp_errors += 1;
}
fprintf(vvp_out, " %%movi %u, %lu %u;\n", lv.base, imm, wid);
}
break;
if (imm == 0) case 2: /* Left expression is X or Z */
break; case 3:
} lv.base = 2;
break;
default: /* The regular case. */
fprintf(vvp_out, " %%addi %u, %lu, %u;\n", lv.base, imm, wid);
break;
} }
return lv; return lv;
@ -1203,7 +1262,8 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
assert(lv.wid == wid); assert(lv.wid == wid);
imm = get_number_immediate(re); imm = get_number_immediate(re);
assert( (imm & ~0xffff) == 0 ); if (imm == 0)
return lv;
switch (lv.base) { switch (lv.base) {
case 0: case 0:
@ -1217,21 +1277,21 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
vvp_errors += 1; vvp_errors += 1;
} }
fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp, lv.base, wid); fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp, lv.base, wid);
lv.base = tmp; lv.base = tmp;
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid); fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
return lv; break;
case 2: case 2:
case 3: case 3:
lv.base = 2; lv.base = 2;
return lv; break;
default: default:
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid); fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
break;
} }
return lv; return lv;
} }
@ -1246,8 +1306,10 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
assert(lv.wid == wid); assert(lv.wid == wid);
imm = get_number_immediate(re); imm = get_number_immediate(re);
if (imm == 0)
return lv;
fprintf(vvp_out, " %%muli %u, %lu, %u;\n", lv.base, imm, lv.wid); fprintf(vvp_out, " %%muli %u, %lu, %u;\n", lv.base, imm, lv.wid);
return lv; return lv;
} }
@ -1299,13 +1361,13 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
if ((ivl_expr_opcode(exp) == '-') if ((ivl_expr_opcode(exp) == '-')
&& (ivl_expr_type(re) == IVL_EX_NUMBER) && (ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re)) && (! number_is_unknown(re))
&& number_is_immediate(re, 16)) && number_is_immediate(re, IMM_WID))
return draw_sub_immediate(le, re, wid); return draw_sub_immediate(le, re, wid);
if ((ivl_expr_opcode(exp) == '*') if ((ivl_expr_opcode(exp) == '*')
&& (ivl_expr_type(re) == IVL_EX_NUMBER) && (ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re)) && (! number_is_unknown(re))
&& number_is_immediate(re, 16)) && number_is_immediate(re, IMM_WID))
return draw_mul_immediate(le, re, wid); return draw_mul_immediate(le, re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ); lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
@ -1612,9 +1674,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
vvp_errors += 1; vvp_errors += 1;
} }
if ((!number_is_unknown(exp)) && number_is_immediate(exp, 16)) { if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID)) {
int val = get_number_immediate(exp); unsigned long val = get_number_immediate(exp);
fprintf(vvp_out, " %%movi %u, %d, %u;\n", res.base, val, wid); fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
return res; return res;
} }
@ -1836,8 +1898,8 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
idx = 0; idx = 0;
while (idx < nwid) { while (idx < nwid) {
unsigned bits; unsigned bits;
unsigned trans = 16; unsigned trans = IMM_WID;
if (nwid-idx < 16) if (nwid-idx < trans)
trans = nwid-idx; trans = nwid-idx;
bits = *p; bits = *p;
@ -1845,6 +1907,14 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
if (trans > 8) { if (trans > 8) {
bits |= *p << 8; bits |= *p << 8;
p -= 1; p -= 1;
if (trans > 16) {
bits |= *p << 16;
p -= 1;
if (trans > 24) {
bits |= *p << 24;
p -= 1;
}
}
} }
fprintf(vvp_out, " %%movi %u, %u, %u;\n", res.base+idx,bits,trans); fprintf(vvp_out, " %%movi %u, %u, %u;\n", res.base+idx,bits,trans);
@ -1881,8 +1951,14 @@ void pad_expr_in_place(ivl_expr_t exp, struct vector_info res, unsigned swid)
res.base+idx, res.base+swid-1); res.base+idx, res.base+swid-1);
} else { } else {
fprintf(vvp_out, " %%mov %u, 0, %u;\n", unsigned base = res.base+swid;
res.base+swid, res.wid-swid); unsigned count = res.wid-swid;
/* The %movi is faster for larger widths, but for very
small counts, the %mov is faster. */
if (count > 4)
fprintf(vvp_out, " %%movi %u, 0, %u;\n", base, count);
else
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base, count);
} }
} }
@ -2086,7 +2162,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
for (idx = 0 ; idx < res.wid ; idx += 1) { for (idx = 0 ; idx < res.wid ; idx += 1) {
if (idx >= bit_wid) { if (idx >= bit_wid) {
fprintf(vvp_out, " %%mov %u, 0, %u; Pad from %u to %u\n", fprintf(vvp_out, " %%movi %u, 0, %u; Pad from %u to %u\n",
res.base+idx, res.wid-idx, res.base+idx, res.wid-idx,
ivl_expr_width(sube), wid); ivl_expr_width(sube), wid);
break; break;
@ -2410,7 +2486,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, " %%mov %u, %u, %u;\n", fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, res.base, res.wid); tmp.base, res.base, res.wid);
fprintf(vvp_out, " %%mov %u, 0, %u;\n", fprintf(vvp_out, " %%movi %u, 0, %u;\n",
tmp.base+res.wid, tmp.wid-res.wid); tmp.base+res.wid, tmp.wid-res.wid);
clr_vector(res); clr_vector(res);
res = tmp; res = tmp;
@ -2460,7 +2536,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
assert(res.base); assert(res.base);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, res.base, res.wid); tmp.base, res.base, res.wid);
fprintf(vvp_out, " %%mov %u, 0, %u;\n", fprintf(vvp_out, " %%movi %u, 0, %u;\n",
tmp.base+res.wid, tmp.wid-res.wid); tmp.base+res.wid, tmp.wid-res.wid);
clr_vector(res); clr_vector(res);
res = tmp; res = tmp;

View File

@ -39,6 +39,12 @@ struct vector_info {
unsigned wid; unsigned wid;
}; };
/*
* Convenient constants...
*/
/* Width limit for typical immediate arguments. */
# define IMM_WID 32
/* /*
* Mangle all non-symbol characters in an identifier, quotes in names * Mangle all non-symbol characters in an identifier, quotes in names
*/ */

View File

@ -827,6 +827,7 @@ static void do_display(unsigned int mcd, struct strobe_cb_info*info)
case vpiReg: case vpiReg:
case vpiIntegerVar: case vpiIntegerVar:
case vpiMemoryWord: case vpiMemoryWord:
case vpiPartSelect:
do_display_numeric(mcd, info, item); do_display_numeric(mcd, info, item);
break; break;
@ -1836,6 +1837,7 @@ static char *get_display(unsigned int *rtnsz, struct strobe_cb_info *info)
case vpiReg: case vpiReg:
case vpiIntegerVar: case vpiIntegerVar:
case vpiMemoryWord: case vpiMemoryWord:
case vpiPartSelect:
width = get_numeric(&result, info, item); width = get_numeric(&result, info, item);
rtn = realloc(rtn, (size+width)*sizeof(char)); rtn = realloc(rtn, (size+width)*sizeof(char));
memcpy(rtn+size-1, result, width); memcpy(rtn+size-1, result, width);

View File

@ -279,6 +279,7 @@ typedef struct t_vpi_delay {
#define vpiNamedFork 35 #define vpiNamedFork 35
#define vpiNet 36 #define vpiNet 36
#define vpiParameter 41 #define vpiParameter 41
#define vpiPartSelect 42
#define vpiPathTerm 43 #define vpiPathTerm 43
#define vpiRealVar 47 #define vpiRealVar 47
#define vpiReg 48 #define vpiReg 48
@ -297,6 +298,7 @@ typedef struct t_vpi_delay {
#define vpiModPathIn 95 #define vpiModPathIn 95
#define vpiModPathOut 96 #define vpiModPathOut 96
#define vpiVariables 100 #define vpiVariables 100
#define vpiExpr 102
#define vpiCallback 1000 #define vpiCallback 1000
@ -346,8 +348,8 @@ typedef struct t_vpi_delay {
# define vpiSysFuncReal vpiRealFunc # define vpiSysFuncReal vpiRealFunc
# define vpiSysFuncTime vpiTimeFunc # define vpiSysFuncTime vpiTimeFunc
# define vpiSysFuncSized vpiSizedFunc # define vpiSysFuncSized vpiSizedFunc
#define vpiSigned 65 #define vpiConstantSelect 53
#define vpiExpr 102 #define vpiSigned 65
/* IVL private properties */ /* IVL private properties */
#define _vpiNexusId 0x1000000 #define _vpiNexusId 0x1000000

View File

@ -37,6 +37,7 @@ extern bool of_ADD(vthread_t thr, vvp_code_t code);
extern bool of_ADD_WR(vthread_t thr, vvp_code_t code); extern bool of_ADD_WR(vthread_t thr, vvp_code_t code);
extern bool of_ADDI(vthread_t thr, vvp_code_t code); extern bool of_ADDI(vthread_t thr, vvp_code_t code);
extern bool of_AND(vthread_t thr, vvp_code_t code); extern bool of_AND(vthread_t thr, vvp_code_t code);
extern bool of_ANDI(vthread_t thr, vvp_code_t code);
extern bool of_ANDR(vthread_t thr, vvp_code_t code); extern bool of_ANDR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code); extern bool of_ASSIGN_AV(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code); extern bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t code);
@ -167,7 +168,7 @@ struct vvp_code_s {
}; };
union { union {
unsigned bit_idx[2]; uint32_t bit_idx[2];
vvp_net_t *net2; vvp_net_t *net2;
vvp_code_t cptr2; vvp_code_t cptr2;
struct ufunc_core*ufunc_core_ptr; struct ufunc_core*ufunc_core_ptr;

View File

@ -85,6 +85,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, { "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, { "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },

View File

@ -173,22 +173,24 @@
"%disable" { return K_disable; } "%disable" { return K_disable; }
"%fork" { return K_fork; } "%fork" { return K_fork; }
/* Handle the specialized variable access functions. */
"&A" { return K_A; }
"&PV" { return K_PV; }
"%"[.$_/a-zA-Z0-9]+ { "%"[.$_/a-zA-Z0-9]+ {
yylval.text = strdup(yytext); yylval.text = strdup(yytext);
assert(yylval.text); assert(yylval.text);
return T_INSTR; } return T_INSTR; }
[0-9][0-9]* { [0-9][0-9]* {
yylval.numb = strtol(yytext, 0, 0); yylval.numb = strtoul(yytext, 0, 0);
return T_NUMBER; } return T_NUMBER; }
"0x"[0-9a-fA-F]+ { "0x"[0-9a-fA-F]+ {
yylval.numb = strtol(yytext, 0, 0); yylval.numb = strtoul(yytext, 0, 0);
return T_NUMBER; } return T_NUMBER; }
"&A" { return K_A; }
/* Handle some specialized constant/literals as symbols. */ /* Handle some specialized constant/literals as symbols. */
"C4<"[01xz]*">" { "C4<"[01xz]*">" {

View File

@ -531,7 +531,8 @@ is one of the 4 constant bits, the effect is to replicate the value
into the destination vector. This is useful for filling a vector. into the destination vector. This is useful for filling a vector.
The %movi variant moves a binary value, LSB first, into the The %movi variant moves a binary value, LSB first, into the
destination vector. destination vector. The immediate value is up to 32bits, padded with
zeros to fillout the width.
* %mul <bit-l>, <bit-r>, <wid> * %mul <bit-l>, <bit-r>, <wid>

View File

@ -47,7 +47,7 @@ static struct __vpiModPath*modpath_dst = 0;
%union { %union {
char*text; char*text;
char **table; char **table;
long numb; unsigned long numb;
bool flag; bool flag;
comp_operands_t opa; comp_operands_t opa;
@ -77,7 +77,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_EVENT K_EVENT_OR K_EXTEND_S K_FUNCTOR K_MODPATH K_NET K_NET_S K_NET_R %token K_EVENT K_EVENT_OR K_EXTEND_S K_FUNCTOR K_MODPATH K_NET K_NET_S K_NET_R
%token K_NET8 K_NET8_S %token K_NET8 K_NET8_S
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV %token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
%token K_PART_V K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR %token K_PART_V K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
%token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT %token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
%token K_RESOLV K_SCOPE K_SFUNC K_SHIFTL K_SHIFTR K_SHIFTRS %token K_RESOLV K_SCOPE K_SFUNC K_SHIFTL K_SHIFTR K_SHIFTRS
%token K_THREAD K_TIMESCALE K_UFUNC %token K_THREAD K_TIMESCALE K_UFUNC
@ -790,9 +790,14 @@ argument
} }
| K_A '<' T_SYMBOL ',' T_NUMBER '>' | K_A '<' T_SYMBOL ',' T_NUMBER '>'
{ $$ = vpip_make_vthr_A($3, $5); } { $$ = vpip_make_vthr_A($3, $5); }
| K_PV '<' T_SYMBOL ',' T_NUMBER ',' T_NUMBER '>'
{ $$ = vpip_make_PV($3, $5, $7); }
| K_PV '<' T_SYMBOL ',' '-' T_NUMBER ',' T_NUMBER '>'
{ $$ = vpip_make_PV($3, -$6, $8); }
| K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER ',' T_NUMBER '>'
{ $$ = vpip_make_PV($3, $5, $6, $8); }
; ;
/* functor operands can only be a list of symbols. */ /* functor operands can only be a list of symbols. */
symbols symbols
: symbol : symbol

View File

@ -220,6 +220,20 @@ extern vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb, extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node); bool signed_flag, vvp_net_t*node);
/*
* This is used by system calls to represent a bit/part select of
* a simple variable or constant array word.
*/
struct __vpiPV {
struct __vpiHandle base;
vpiHandle parent;
vvp_net_t*net;
int tbase;
unsigned twid, width;
};
extern vpiHandle vpip_make_PV(char*name, int base, int width);
extern vpiHandle vpip_make_PV(char*name, int tbase, int twid, int width);
/* /*
* This function safely converts a vpiHandle back to a * This function safely converts a vpiHandle back to a
* __vpiSignal. Return a nil if the type is not appropriate. * __vpiSignal. Return a nil if the type is not appropriate.
@ -368,6 +382,7 @@ struct __vpiSysTaskCall {
class vvp_net_t*fnet; class vvp_net_t*fnet;
unsigned file_idx; unsigned file_idx;
unsigned lineno; unsigned lineno;
bool put_value;
}; };
extern struct __vpiSysTaskCall*vpip_cur_task; extern struct __vpiSysTaskCall*vpip_cur_task;

View File

@ -48,7 +48,7 @@
* draw_tt.c program. * draw_tt.c program.
*/ */
extern const char hex_digits[256]; extern const char hex_digits[256];
extern const char oct_digits[256]; extern const char oct_digits[64];
/* /*
* The string values need a result buf to hold the results. This * The string values need a result buf to hold the results. This
@ -109,6 +109,385 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind
return res; return res;
} }
/*
* The standard formating/conversion routines.
* They work with full or partial signals.
*/
static void format_vpiBinStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
s_vpi_value*vp)
{
char *rbuf = need_result_buf(wid+1, RBUF_VAL);
long offset = wid - 1 + base;
long end = base + (signed)wid;
long ssize = (signed)sig->size();
for (long idx = base ; idx < end ; idx += 1) {
if (idx < 0 || idx >= ssize) {
rbuf[offset-idx] = 'x';
} else {
rbuf[offset-idx] = vvp_bit4_to_ascii(sig->value(idx));
}
}
rbuf[wid] = 0;
vp->value.str = rbuf;
}
static void format_vpiOctStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
s_vpi_value*vp)
{
unsigned dwid = (wid + 2) / 3;
char *rbuf = need_result_buf(dwid+1, RBUF_VAL);
long end = base + (signed)wid;
long ssize = (signed)sig->size();
unsigned val = 0;
rbuf[dwid] = 0;
for (long idx = base ; idx < end ; idx += 1) {
unsigned bit = 0;
if (idx < 0 || idx >= ssize) {
bit = 2; // BIT4_X
} else {
switch (sig->value(idx)) {
case BIT4_0:
bit = 0;
break;
case BIT4_1:
bit = 1;
break;
case BIT4_X:
bit = 2;
break;
case BIT4_Z:
bit = 3;
break;
}
}
val |= bit << 2*((idx-base) % 3);
if ((idx-base) % 3 == 2) {
dwid -= 1;
rbuf[dwid] = oct_digits[val];
val = 0;
}
}
/* Fill in X or Z if they are the only thing in the value. */
switch (wid % 3) {
case 1:
if (val == 2) val = 42;
else if (val == 3) val = 63;
break;
case 2:
if (val == 10) val = 42;
else if (val == 15) val = 63;
break;
}
if (dwid > 0) rbuf[0] = oct_digits[val];
vp->value.str = rbuf;
}
static void format_vpiHexStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
s_vpi_value*vp)
{
unsigned dwid = (wid + 3) / 4;
char *rbuf = need_result_buf(dwid+1, RBUF_VAL);
long end = base + (signed)wid;
long ssize = (signed)sig->size();
unsigned val = 0;
rbuf[dwid] = 0;
for (long idx = base ; idx < end ; idx += 1) {
unsigned bit = 0;
if (idx < 0 || idx >= ssize) {
bit = 2; // BIT4_X
} else {
switch (sig->value(idx)) {
case BIT4_0:
bit = 0;
break;
case BIT4_1:
bit = 1;
break;
case BIT4_X:
bit = 2;
break;
case BIT4_Z:
bit = 3;
break;
}
}
val |= bit << 2*((idx-base) % 4);
if ((idx-base) % 4 == 3) {
dwid -= 1;
rbuf[dwid] = hex_digits[val];
val = 0;
}
}
/* Fill in X or Z if they are the only thing in the value. */
switch (wid % 4) {
case 1:
if (val == 2) val = 170;
else if (val == 3) val = 255;
break;
case 2:
if (val == 10) val = 170;
else if (val == 15) val = 255;
break;
case 3:
if (val == 42) val = 170;
else if (val == 63) val = 255;
break;
}
if (dwid > 0) rbuf[0] = hex_digits[val];
vp->value.str = rbuf;
}
static void format_vpiDecStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
int signed_flag, s_vpi_value*vp)
{
unsigned hwid = (sig->size()+2) / 3 + 1;
char *rbuf = need_result_buf(hwid, RBUF_VAL);
long ssize = (signed)sig->size();
long end = base + (signed)wid;
/* Do we have an end outside of the real signal vector. */
if (base < 0 || end > ssize) {
bool all_x = true;
if (end > ssize) end = ssize;
if (base < 0) base = 0;
for (long idx = base ; idx < end ; idx += 1) {
if (sig->value(idx) != BIT4_X) {
all_x = false;
break;
}
}
if (all_x) {
rbuf[0] = 'x';
} else {
rbuf[0] = 'X';
}
rbuf[1] = 0;
vp->value.str = rbuf;
return;
}
vvp_vector4_t vec4;
if (base == 0 && end == ssize) {
vec4 = sig->vec4_value();
} else {
vec4 = sig->vec4_value().subvalue(base, wid);
}
vpip_vec4_to_dec_str(vec4, rbuf, hwid, signed_flag);
vp->value.str = rbuf;
}
static void format_vpiIntVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
s_vpi_value*vp)
{
unsigned iwid = 8 * sizeof(vp->value.integer);
long ssize = (signed)sig->size();
if (wid > iwid) wid = iwid;
long end = base + (signed)wid;
if (end > ssize) end = ssize;
vp->value.integer = 0;
for (long idx = (base < 0) ? 0 : base ; idx < end ; idx += 1) {
if (sig->value(idx) == BIT4_1) {
vp->value.integer |= 1<<(idx-base);
}
}
}
static void format_vpiRealVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
int signed_flag, s_vpi_value*vp)
{
vvp_vector4_t vec4(wid);
long ssize = (signed)sig->size();
long end = base + (signed)wid;
if (end > ssize) end = ssize;
for (long idx = (base < 0) ? 0 : base ; idx < end ; idx += 1) {
vec4.set_bit(idx-base, sig->value(idx));
}
vp->value.real = 0.0;
vector4_to_value(vec4, vp->value.real, signed_flag);
}
static void format_vpiStringVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
s_vpi_value*vp)
{
/* The result will use a character for each 8 bits of the
vector. Add one extra character for the highest bits that
don't form an 8 bit group. */
char *rbuf = need_result_buf(wid/8 + ((wid&7)!=0) + 1, RBUF_VAL);
char *cp = rbuf;
char tmp = 0;
for (long idx = base+(signed)wid-1; idx >= base; idx -= 1) {
tmp <<= 1;
if (idx >=0 && idx < (signed)sig->size() &&
sig->value(idx) == BIT4_1) {
tmp |= 1;
}
if (((idx-base)&7)==0){
/* Skip leading nulls. */
if (tmp == 0 && cp == rbuf)
continue;
/* Nulls in the middle get turned into spaces. */
*cp++ = tmp ? tmp : ' ';
tmp = 0;
}
}
*cp++ = 0;
vp->value.str = rbuf;
}
static void format_vpiScalarVal(vvp_fun_signal_vec*sig, int base,
s_vpi_value*vp)
{
if (base >= 0 && base < (signed)sig->size()) {
switch (sig->value(base)) {
case BIT4_0:
vp->value.scalar = vpi0;
break;
case BIT4_1:
vp->value.scalar = vpi1;
break;
case BIT4_X: {
vvp_scalar_t strn = sig->scalar_value(base);
if (strn.strength0() == 1) vp->value.scalar = vpiH;
else if (strn.strength1() == 1) vp->value.scalar = vpiL;
else vp->value.scalar = vpiX;
break;
}
case BIT4_Z:
vp->value.scalar = vpiZ;
break;
}
} else {
vp->value.scalar = vpiX;
}
}
static void format_vpiStrengthVal(vvp_fun_signal_vec*sig, int base,
unsigned wid, s_vpi_value*vp)
{
long end = base + (signed)wid;
s_vpi_strengthval*op;
op = (s_vpi_strengthval*)
need_result_buf(wid * sizeof(s_vpi_strengthval), RBUF_VAL);
for (long idx = base ; idx < end ; idx += 1) {
if (idx >=0 && idx < (signed)sig->size()) {
vvp_scalar_t val = sig->scalar_value(idx);
/* vvp_scalar_t strengths are 0-7, but the vpi strength
is bit0-bit7. This gets the vpi form of the strengths
from the vvp_scalar_t strengths. */
unsigned s0 = 1 << val.strength0();
unsigned s1 = 1 << val.strength1();
switch (val.value()) {
case BIT4_0:
op[idx-base].logic = vpi0;
op[idx-base].s0 = s0|s1;
op[idx-base].s1 = 0;
break;
case BIT4_1:
op[idx-base].logic = vpi1;
op[idx-base].s0 = 0;
op[idx-base].s1 = s0|s1;
break;
case BIT4_X:
op[idx-base].logic = vpiX;
op[idx-base].s0 = s0;
op[idx-base].s1 = s1;
break;
case BIT4_Z:
op[idx-base].logic = vpiZ;
op[idx-base].s0 = vpiHiZ;
op[idx-base].s1 = vpiHiZ;
break;
}
} else {
op[idx-base].logic = vpiX;
op[idx-base].s0 = vpiStrongDrive;
op[idx-base].s1 = vpiStrongDrive;
}
}
vp->value.strength = op;
}
static void format_vpiVectorVal(vvp_fun_signal_vec*sig, int base, unsigned wid,
s_vpi_value*vp)
{
long end = base + (signed)wid;
unsigned int obit = 0;
unsigned hwid = (wid - 1)/32 + 1;
s_vpi_vecval *op = (p_vpi_vecval)
need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL);
vp->value.vector = op;
op->aval = op->bval = 0;
for (long idx = base ; idx < end ; idx += 1) {
if (base >= 0 && base < (signed)sig->size()) {
switch (sig->value(idx)) {
case BIT4_0:
op->aval &= ~(1 << obit);
op->bval &= ~(1 << obit);
break;
case BIT4_1:
op->aval |= (1 << obit);
op->bval &= ~(1 << obit);
break;
case BIT4_X:
op->aval |= (1 << obit);
op->bval |= (1 << obit);
break;
case BIT4_Z:
op->aval &= ~(1 << obit);
op->bval |= (1 << obit);
break;
}
} else { /* BIT4_X */
op->aval |= (1 << obit);
op->bval |= (1 << obit);
}
obit++;
if (!(obit % 32)) {
op += 1;
if ((op - vp->value.vector) < (ptrdiff_t)hwid)
op->aval = op->bval = 0;
obit = 0;
}
}
}
struct __vpiSignal* vpip_signal_from_handle(vpiHandle ref) struct __vpiSignal* vpip_signal_from_handle(vpiHandle ref)
{ {
if ((ref->vpi_type->type_code != vpiNet) if ((ref->vpi_type->type_code != vpiNet)
@ -245,65 +624,6 @@ static vpiHandle signal_iterate(int code, vpiHandle ref)
return 0; return 0;
} }
static char *signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{
vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun);
assert(vsig);
unsigned hwid = (vsig->size()+2) / 3 + 1;
char *rbuf = need_result_buf(hwid, RBUF_VAL);
vpip_vec4_to_dec_str(vsig->vec4_value(), rbuf, hwid, rfp->signed_flag);
return rbuf;
}
static char *signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{
unsigned wid = (rfp->msb >= rfp->lsb)
? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 1);
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
/* The result will use a character for each 8 bits of the
vector. Add one extra character for the highest bits that
don't form an 8 bit group. */
char *rbuf = need_result_buf(wid/8 + ((wid&7)!=0) + 1, RBUF_VAL);
char *cp = rbuf;
char tmp = 0;
int bitnr;
for(bitnr=wid-1; bitnr>=0; bitnr--){
tmp <<= 1;
switch (vsig->value(bitnr)) {
case BIT4_0:
break;
case BIT4_1:
tmp |= 1;
break;
default:
break;
}
if ((bitnr&7)==0){
/* Skip leading nulls. */
if (tmp == 0 && cp == rbuf)
continue;
/* Nulls in the middle get turned into spaces. */
*cp++ = tmp? tmp : ' ';
tmp = 0;
}
}
*cp++ = 0;
return rbuf;
}
static unsigned signal_width(const struct __vpiSignal*rfp) static unsigned signal_width(const struct __vpiSignal*rfp)
{ {
unsigned wid = (rfp->msb >= rfp->lsb) unsigned wid = (rfp->msb >= rfp->lsb)
@ -313,97 +633,6 @@ static unsigned signal_width(const struct __vpiSignal*rfp)
return wid; return wid;
} }
static void signal_get_IntVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{
unsigned wid = signal_width(rfp);
unsigned iwid = 8 * sizeof vp->value.integer;
vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun);
if (wid > iwid) {
wid = iwid;
}
vp->value.integer = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
switch (vsig->value(idx)) {
case BIT4_0:
break;
case BIT4_1:
vp->value.integer |= 1<<idx;
break;
default:
/* vpi_get_value of vpiIntVal treats x and z
values as 0. */
break;
}
}
}
static void signal_get_ScalarVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{
vvp_fun_signal*vsig = dynamic_cast<vvp_fun_signal*>(rfp->node->fun);
switch (vsig->value(0)) {
case BIT4_0:
vp->value.scalar = vpi0;
break;
case BIT4_1:
vp->value.scalar = vpi1;
break;
case BIT4_X:
vp->value.scalar = vpiX;
break;
case BIT4_Z:
vp->value.scalar = vpiZ;
break;
}
}
static void signal_get_StrengthVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{
vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun);
unsigned wid = signal_width(rfp);
s_vpi_strengthval*op;
op = (s_vpi_strengthval*)
need_result_buf(wid * sizeof(s_vpi_strengthval), RBUF_VAL);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_scalar_t val = vsig->scalar_value(idx);
/* vvp_scalar_t strengths are 0-7, but the vpi strength
is bit0-bit7. This gets the vpi form of the strengths
from the vvp_scalar_t strengths. */
unsigned s0 = 1 << val.strength0();
unsigned s1 = 1 << val.strength1();
switch (val.value()) {
case BIT4_0:
op[idx].logic = vpi0;
op[idx].s0 = s0|s1;
op[idx].s1 = 0;
break;
case BIT4_1:
op[idx].logic = vpi1;
op[idx].s0 = 0;
op[idx].s1 = s0|s1;
break;
case BIT4_X:
op[idx].logic = vpiX;
op[idx].s0 = s0;
op[idx].s1 = s1;
break;
case BIT4_Z:
op[idx].logic = vpiZ;
op[idx].s0 = vpiHiZ;
op[idx].s1 = vpiHiZ;
break;
}
}
vp->value.strength = op;
}
/* /*
* The get_value method reads the values of the functors and returns * The get_value method reads the values of the functors and returns
* the vector to the caller. This causes no side-effect, and reads the * the vector to the caller. This causes no side-effect, and reads the
@ -421,146 +650,48 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun); vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun);
assert(vsig); assert(vsig);
char *rbuf = 0;
switch (vp->format) { switch (vp->format) {
case vpiIntVal: case vpiIntVal:
signal_get_IntVal(rfp, vp); format_vpiIntVal(vsig, 0, wid, vp);
break; break;
case vpiScalarVal: case vpiScalarVal:
signal_get_ScalarVal(rfp, vp); format_vpiScalarVal(vsig, 0, vp);
break; break;
case vpiStrengthVal: case vpiStrengthVal:
signal_get_StrengthVal(rfp, vp); format_vpiStrengthVal(vsig, 0, wid, vp);
break; break;
case vpiBinStrVal: case vpiBinStrVal:
rbuf = need_result_buf(wid+1, RBUF_VAL); format_vpiBinStrVal(vsig, 0, wid, vp);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
rbuf[wid-idx-1] = vvp_bit4_to_ascii(vsig->value(idx));
}
rbuf[wid] = 0;
vp->value.str = rbuf;
break; break;
case vpiHexStrVal: { case vpiHexStrVal: {
unsigned hwid = (wid + 3) / 4; format_vpiHexStrVal(vsig, 0, wid, vp);
break;
rbuf = need_result_buf(hwid+1, RBUF_VAL);
rbuf[hwid] = 0;
vpip_vec4_to_hex_str(vsig->vec4_value(), rbuf, hwid+1, false);
vp->value.str = rbuf;
break;
} }
case vpiOctStrVal: { case vpiOctStrVal:
unsigned hval, hwid; format_vpiOctStrVal(vsig, 0, wid, vp);
hwid = (wid + 2) / 3; break;
rbuf = need_result_buf(hwid+1, RBUF_VAL);
rbuf[hwid] = 0;
hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
unsigned tmp = 0;
switch (vsig->value(idx)) {
case BIT4_0:
tmp = 0;
break;
case BIT4_1:
tmp = 1;
break;
case BIT4_Z:
tmp = 3;
break;
case BIT4_X:
tmp = 2;
break;
}
hval = hval | (tmp << 2*(idx % 3));
if (idx%3 == 2) {
hwid -= 1;
rbuf[hwid] = oct_digits[hval];
hval = 0;
}
}
if (hwid > 0) {
hwid -= 1;
rbuf[hwid] = oct_digits[hval];
unsigned padd = 0;
switch(rbuf[hwid]) {
case 'X': padd = 2; break;
case 'Z': padd = 3; break;
}
if (padd) {
for (unsigned idx = wid % 3; idx < 3; idx += 1) {
hval = hval | padd << 2*idx;
}
rbuf[hwid] = oct_digits[hval];
}
}
vp->value.str = rbuf;
break;
}
case vpiDecStrVal: case vpiDecStrVal:
vp->value.str = signal_vpiDecStrVal(rfp, vp); format_vpiDecStrVal(vsig, 0, wid, rfp->signed_flag, vp);
break; break;
case vpiStringVal: case vpiStringVal:
vp->value.str = signal_vpiStringVal(rfp, vp); format_vpiStringVal(vsig, 0, wid, vp);
break; break;
case vpiVectorVal: { case vpiVectorVal:
unsigned int obit = 0; format_vpiVectorVal(vsig, 0, wid, vp);
unsigned hwid = (wid - 1)/32 + 1; break;
rbuf = need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL);
s_vpi_vecval *op = (p_vpi_vecval)rbuf;
vp->value.vector = op;
op->aval = op->bval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
switch (vsig->value(idx)) {
case BIT4_0:
op->aval &= ~(1 << obit);
op->bval &= ~(1 << obit);
break;
case BIT4_1:
op->aval |= (1 << obit);
op->bval &= ~(1 << obit);
break;
case BIT4_X:
op->aval |= (1 << obit);
op->bval |= (1 << obit);
break;
case BIT4_Z:
op->aval &= ~(1 << obit);
op->bval |= (1 << obit);
break;
}
obit++;
if (!(obit % 32)) {
op += 1;
if ((op - vp->value.vector) < (ptrdiff_t)hwid)
op->aval = op->bval = 0;
obit = 0;
}
}
break;
}
case vpiRealVal: { case vpiRealVal: {
bool flag = rfp->signed_flag; format_vpiRealVal(vsig, 0, wid, rfp->signed_flag, vp);
vp->value.real = 0.0; break;
vector4_to_value(vsig->vec4_value(), vp->value.real, flag);
break;
} }
default: default:
@ -812,3 +943,218 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
return &obj->base; return &obj->base;
} }
static int PV_get_base(struct __vpiPV*rfp)
{
if (rfp->twid == 0) return rfp->tbase;
int tval = 0;
for (unsigned idx = 0 ; idx < rfp->twid ; idx += 1) {
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread,
rfp->tbase + idx);
if (bit == BIT4_1) {
tval |= 1<<idx;
}
}
return tval;
}
static int PV_get(int code, vpiHandle ref)
{
assert(ref->vpi_type->type_code == vpiPartSelect);
struct __vpiPV*rfp = (struct __vpiPV*)ref;
int rval = 0;
switch (code) {
case vpiLineNo:
return 0; // Not implemented for now!
case vpiSigned:
return 0; // A part/bit select is always unsigned!
case vpiSize:
return rfp->width;
case vpiConstantSelect:
return rfp->twid == 0;
case vpiLeftRange: rval += rfp->width;
case vpiRightRange:
rval += vpi_get(vpiRightRange, rfp->parent) + PV_get_base(rfp);
return rval;
default:
fprintf(stderr, "PV_get: property %d is unknown\n", code);
}
return 0;
}
static char* PV_get_str(int code, vpiHandle ref)
{
assert(ref->vpi_type->type_code == vpiPartSelect);
struct __vpiPV*rfp = (struct __vpiPV*)ref;
switch (code) {
case vpiFile: // Not implemented for now!
return simple_set_rbuf_str(file_names[0]);
case vpiName:
case vpiFullName: {
const char*nm = vpi_get_str(code, rfp->parent);
char full[1024+strlen(nm)];
sprintf(full, "%s[%d:%d]", nm, vpi_get(vpiLeftRange, ref),
vpi_get(vpiRightRange, ref));
return simple_set_rbuf_str(full);
}
default:
fprintf(stderr, "PV_get_str: property %d is unknown\n", code);
}
return 0;
}
static void PV_get_value(vpiHandle ref, p_vpi_value vp)
{
assert(ref->vpi_type->type_code == vpiPartSelect);
struct __vpiPV*rfp = (struct __vpiPV*)ref;
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(rfp->net->fun);
assert(sig);
switch (vp->format) {
case vpiIntVal:
format_vpiIntVal(sig, PV_get_base(rfp), rfp->width, vp);
break;
case vpiBinStrVal:
format_vpiBinStrVal(sig, PV_get_base(rfp), rfp->width, vp);
break;
case vpiOctStrVal:
format_vpiOctStrVal(sig, PV_get_base(rfp), rfp->width, vp);
break;
case vpiHexStrVal:
format_vpiHexStrVal(sig, PV_get_base(rfp), rfp->width, vp);
break;
case vpiDecStrVal:
format_vpiDecStrVal(sig, PV_get_base(rfp), rfp->width, 0, vp);
break;
case vpiStringVal:
format_vpiStringVal(sig, PV_get_base(rfp), rfp->width, vp);
break;
case vpiScalarVal:
format_vpiScalarVal(sig, PV_get_base(rfp), vp);
break;
case vpiStrengthVal:
format_vpiStrengthVal(sig, PV_get_base(rfp), rfp->width, vp);
break;
case vpiVectorVal:
format_vpiVectorVal(sig, PV_get_base(rfp), rfp->width, vp);
break;
case vpiRealVal:
format_vpiRealVal(sig, PV_get_base(rfp), rfp->width, 0, vp);
break;
default:
fprintf(stderr, "vvp internal error: PV_get_value: "
"value type %u not implemented. Signal is %s.\n",
vp->format, vpi_get_str(vpiFullName, rfp->parent));
assert(0);
}
}
static vpiHandle PV_put_value(vpiHandle ref, p_vpi_value vp, int)
{
assert(ref->vpi_type->type_code == vpiPartSelect);
struct __vpiPV*rfp = (struct __vpiPV*)ref;
vvp_fun_signal_vec*sig = reinterpret_cast<vvp_fun_signal_vec*>(rfp->net);
assert(sig);
unsigned width = rfp->width;
int base = PV_get_base(rfp);
if (base >= (signed) sig->size()) return 0;
if (base < 0) {
width += base;
base = 0;
}
if (base+width > sig->size()) width = sig->size() - base;
bool full_sig = base == 0 && width == sig->size();
vvp_net_ptr_t ptr (rfp->net, 0);
/* We only support integer values. */
assert(vp->format == vpiIntVal);
if (full_sig) {
vvp_send_long(ptr, vp->value.integer);
} else {
vvp_send_long_pv(ptr, vp->value.integer, base, width);
}
return 0;
}
static vpiHandle PV_get_handle(int code, vpiHandle ref)
{
assert(ref->vpi_type->type_code==vpiPartSelect);
struct __vpiPV*rfp = (struct __vpiPV*)ref;
switch (code) {
case vpiParent:
return rfp->parent;
break;
}
return 0;
}
static const struct __vpirt vpip_PV_rt = {
vpiPartSelect,
PV_get,
PV_get_str,
PV_get_value,
PV_put_value,
PV_get_handle,
0
};
vpiHandle vpip_make_PV(char*var, int base, int width)
{
struct __vpiPV*obj = (struct __vpiPV*) malloc(sizeof(struct __vpiPV));
obj->base.vpi_type = &vpip_PV_rt;
obj->parent = vvp_lookup_handle(var);
obj->tbase = base;
obj->twid = 0;
obj->width = (unsigned) width;
obj->net = (vvp_net_t*) malloc(sizeof(vvp_net_t));
functor_ref_lookup(&obj->net, var);
return &obj->base;
}
vpiHandle vpip_make_PV(char*var, int tbase, int twid, int width)
{
struct __vpiPV*obj = (struct __vpiPV*) malloc(sizeof(struct __vpiPV));
obj->base.vpi_type = &vpip_PV_rt;
obj->parent = vvp_lookup_handle(var);
obj->tbase = tbase;
obj->twid = (unsigned) twid;
obj->width = (unsigned) width;
obj->net = (vvp_net_t*) malloc(sizeof(vvp_net_t));
functor_ref_lookup(&obj->net, var);
return &obj->base;
}

View File

@ -167,6 +167,8 @@ static vpiHandle sysfunc_put_value(vpiHandle ref, p_vpi_value vp, int)
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref; struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
rfp->put_value = true;
assert(rfp->vbit >= 4); assert(rfp->vbit >= 4);
switch (vp->format) { switch (vp->format) {
@ -271,6 +273,8 @@ static vpiHandle sysfunc_put_real_value(vpiHandle ref, p_vpi_value vp, int)
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref; struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
rfp->put_value = true;
/* Make sure this is a real valued function. */ /* Make sure this is a real valued function. */
assert(rfp->vwid == -vpiRealConst); assert(rfp->vwid == -vpiRealConst);
@ -297,6 +301,8 @@ static vpiHandle sysfunc_put_4net_value(vpiHandle ref, p_vpi_value vp, int)
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref; struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
rfp->put_value = true;
unsigned vwid = (unsigned) rfp->vwid; unsigned vwid = (unsigned) rfp->vwid;
vvp_vector4_t val (vwid); vvp_vector4_t val (vwid);
@ -384,8 +390,10 @@ static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp, int)
assert(ref->vpi_type->type_code == vpiSysFuncCall); assert(ref->vpi_type->type_code == vpiSysFuncCall);
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref; struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
double val;
rfp->put_value = true;
double val;
switch (vp->format) { switch (vp->format) {
case vpiRealVal: case vpiRealVal:
@ -563,6 +571,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
obj->file_idx = (unsigned) file_idx; obj->file_idx = (unsigned) file_idx;
obj->lineno = (unsigned) lineno; obj->lineno = (unsigned) lineno;
obj->userdata = 0; obj->userdata = 0;
obj->put_value = false;
compile_compiletf(obj); compile_compiletf(obj);
@ -590,8 +599,23 @@ void vpip_execute_vpi_call(vthread_t thr, vpiHandle ref)
if (vpip_cur_task->defn->info.calltf) { if (vpip_cur_task->defn->info.calltf) {
assert(vpi_mode_flag == VPI_MODE_NONE); assert(vpi_mode_flag == VPI_MODE_NONE);
vpi_mode_flag = VPI_MODE_CALLTF; vpi_mode_flag = VPI_MODE_CALLTF;
vpip_cur_task->put_value = false;
vpip_cur_task->defn->info.calltf(vpip_cur_task->defn->info.user_data); vpip_cur_task->defn->info.calltf(vpip_cur_task->defn->info.user_data);
vpi_mode_flag = VPI_MODE_NONE; vpi_mode_flag = VPI_MODE_NONE;
/* If the function call did not set a value then put a
* default value (0). */
if (ref->vpi_type->type_code == vpiSysFuncCall &&
!vpip_cur_task->put_value) {
s_vpi_value val;
if (vpip_cur_task->vwid == -vpiRealConst) {
val.format = vpiRealVal;
val.value.real = 0.0;
} else {
val.format = vpiIntVal;
val.value.integer = 0;
}
vpi_put_value(ref, &val, 0, vpiNoDelay);
}
} }
} }

View File

@ -67,7 +67,7 @@ void set_bit(struct __vpiVThrVec *rfp, unsigned idx, vvp_bit4_t bit)
extern const char hex_digits[256]; extern const char hex_digits[256];
extern const char oct_digits[256]; extern const char oct_digits[64];
/* /*
* vpi_get * vpi_get

File diff suppressed because it is too large Load Diff

View File

@ -61,28 +61,6 @@ vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
} }
} }
vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b)
{
if (a == BIT4_0)
return BIT4_0;
if (b == BIT4_0)
return BIT4_0;
if (bit4_is_xz(a))
return BIT4_X;
if (bit4_is_xz(b))
return BIT4_X;
return BIT4_1;
}
vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b)
{
if (a == BIT4_1)
return BIT4_1;
if (b == BIT4_1)
return BIT4_1;
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
}
vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b) vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b)
{ {
if (bit4_is_xz(a)) if (bit4_is_xz(a))

View File

@ -87,8 +87,21 @@ inline vvp_bit4_t bit4_z2x(vvp_bit4_t a)
inline vvp_bit4_t operator ~ (vvp_bit4_t a) inline vvp_bit4_t operator ~ (vvp_bit4_t a)
{ return bit4_z2x((vvp_bit4_t) (((int)a) ^ 1)); } { return bit4_z2x((vvp_bit4_t) (((int)a) ^ 1)); }
extern vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b); inline vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b)
extern vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b); {
if (a==BIT4_1 || b==BIT4_1)
return BIT4_1;
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
}
inline vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b)
{
if (a==BIT4_0 || b==BIT4_0)
return BIT4_0;
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
}
extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b); extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b);
extern ostream& operator<< (ostream&o, vvp_bit4_t a); extern ostream& operator<< (ostream&o, vvp_bit4_t a);
@ -294,41 +307,47 @@ inline void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
assert(idx < size_); assert(idx < size_);
unsigned long off = idx % BITS_PER_WORD; unsigned long off = idx % BITS_PER_WORD;
unsigned long amask = 0, bmask = 0;
switch (val) {
case BIT4_0:
amask = 0;
bmask = 0;
break;
case BIT4_1:
amask = 1;
bmask = 0;
break;
case BIT4_X:
amask = 1;
bmask = 1;
break;
case BIT4_Z:
amask = 0;
bmask = 1;
break;
}
unsigned long mask = 1UL << off; unsigned long mask = 1UL << off;
amask <<= off;
bmask <<= off;
if (size_ > BITS_PER_WORD) { if (size_ > BITS_PER_WORD) {
unsigned wdx = idx / BITS_PER_WORD; unsigned wdx = idx / BITS_PER_WORD;
abits_ptr_[wdx] &= ~mask; switch (val) {
abits_ptr_[wdx] |= amask; case BIT4_0:
bbits_ptr_[wdx] &= ~mask; abits_ptr_[wdx] &= ~mask;
bbits_ptr_[wdx] |= bmask; bbits_ptr_[wdx] &= ~mask;
break;
case BIT4_1:
abits_ptr_[wdx] |= mask;
bbits_ptr_[wdx] &= ~mask;
break;
case BIT4_X:
abits_ptr_[wdx] |= mask;
bbits_ptr_[wdx] |= mask;
break;
case BIT4_Z:
abits_ptr_[wdx] &= ~mask;
bbits_ptr_[wdx] |= mask;
break;
}
} else { } else {
abits_val_ &= ~mask; switch (val) {
abits_val_ |= amask; case BIT4_0:
bbits_val_ &= ~mask; abits_val_ &= ~mask;
bbits_val_ |= bmask; bbits_val_ &= ~mask;
break;
case BIT4_1:
abits_val_ |= mask;
bbits_val_ &= ~mask;
break;
case BIT4_X:
abits_val_ |= mask;
bbits_val_ |= mask;
break;
case BIT4_Z:
abits_val_ &= ~mask;
bbits_val_ |= mask;
break;
}
} }
} }