Merge branch 'master' into verilog-ams
This commit is contained in:
commit
1be1f65f33
|
|
@ -188,7 +188,13 @@ iverilog-vpi.pdf: iverilog-vpi.ps
|
|||
.PHONY: version.h
|
||||
version.h:
|
||||
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
|
||||
@if test -d $(srcdir)/.git; then \
|
||||
echo "Using git-describe for VERSION_TAG"; \
|
||||
|
|
|
|||
|
|
@ -716,6 +716,15 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
|||
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()) {
|
||||
cerr << get_fileline() << ": error: Concatenation repeat "
|
||||
<< "may not be negative (" << rep->value().as_long()
|
||||
|
|
|
|||
|
|
@ -1578,6 +1578,14 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
|||
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()) {
|
||||
cerr << get_fileline() << ": error: Concatenation repeat "
|
||||
<< "may not be negative (" << erep->value().as_long()
|
||||
|
|
|
|||
2
ivl.def
2
ivl.def
|
|
@ -226,8 +226,6 @@ ivl_switch_file
|
|||
ivl_switch_lineno
|
||||
ivl_switch_scope
|
||||
ivl_switch_type
|
||||
ivl_switch_attr_cnt
|
||||
ivl_switch_attr_val
|
||||
|
||||
ivl_udp_init
|
||||
ivl_udp_name
|
||||
|
|
|
|||
|
|
@ -1854,9 +1854,6 @@ extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
|
|||
* ivl_switch_basename
|
||||
* 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_b
|
||||
* 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 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_b(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 ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
|
||||
|
||||
extern const char* ivl_switch_file(ivl_switch_t net);
|
||||
extern unsigned ivl_switch_lineno(ivl_switch_t net);
|
||||
|
||||
*** */
|
||||
#if defined(__MINGW32__) || defined (__CYGWIN32__)
|
||||
# define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -29,6 +29,82 @@
|
|||
#define snprintf _snprintf
|
||||
#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[] = {
|
||||
"$time",
|
||||
"$stime",
|
||||
|
|
@ -217,6 +293,39 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
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
|
||||
passed as a constant to the vpi task. */
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -92,7 +92,8 @@ unsigned long get_number_immediate(ivl_expr_t ex)
|
|||
case '0':
|
||||
break;
|
||||
case '1':
|
||||
imm |= 1 << idx;
|
||||
assert(idx < 8*sizeof(imm));
|
||||
imm |= 1UL << idx;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -909,12 +910,43 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
|
|||
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,
|
||||
unsigned wid)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(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 rv;
|
||||
|
||||
|
|
@ -1166,23 +1198,50 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
|
|||
|
||||
imm = get_number_immediate(re);
|
||||
|
||||
/* Now generate enough %addi instructions to add the entire
|
||||
immediate value to the destination. The adds are done 16
|
||||
bits at a time, but 17 bits are done to push the carry into
|
||||
the higher bits if needed. */
|
||||
{ unsigned base;
|
||||
for (base = 0 ; base < lv.wid ; base += 16) {
|
||||
unsigned long tmp = imm & 0xffffUL;
|
||||
unsigned add_wid = lv.wid - base;
|
||||
|
||||
imm >>= 16;
|
||||
|
||||
fprintf(vvp_out, " %%addi %u, %lu, %u;\n",
|
||||
lv.base+base, tmp, add_wid);
|
||||
|
||||
/* This shouldn't generally happen, because the elaborator
|
||||
should take care of simple constant propagation like this,
|
||||
but it doesn't have to and it is easy to catch here. */
|
||||
if (imm == 0)
|
||||
break;
|
||||
return lv;
|
||||
|
||||
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;
|
||||
|
||||
case 1: /* Left expression is 1...1 (i.e. -1) */
|
||||
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;
|
||||
|
||||
case 2: /* Left expression is X or Z */
|
||||
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;
|
||||
|
|
@ -1203,7 +1262,8 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
|
|||
assert(lv.wid == wid);
|
||||
|
||||
imm = get_number_immediate(re);
|
||||
assert( (imm & ~0xffff) == 0 );
|
||||
if (imm == 0)
|
||||
return lv;
|
||||
|
||||
switch (lv.base) {
|
||||
case 0:
|
||||
|
|
@ -1220,18 +1280,18 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
|
|||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp, lv.base, wid);
|
||||
lv.base = tmp;
|
||||
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
|
||||
return lv;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
lv.base = 2;
|
||||
return lv;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
|
|
@ -1246,6 +1306,8 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
|
|||
assert(lv.wid == wid);
|
||||
|
||||
imm = get_number_immediate(re);
|
||||
if (imm == 0)
|
||||
return lv;
|
||||
|
||||
fprintf(vvp_out, " %%muli %u, %lu, %u;\n", lv.base, imm, lv.wid);
|
||||
|
||||
|
|
@ -1299,13 +1361,13 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
|
|||
if ((ivl_expr_opcode(exp) == '-')
|
||||
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
|
||||
&& (! number_is_unknown(re))
|
||||
&& number_is_immediate(re, 16))
|
||||
&& number_is_immediate(re, IMM_WID))
|
||||
return draw_sub_immediate(le, re, wid);
|
||||
|
||||
if ((ivl_expr_opcode(exp) == '*')
|
||||
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
|
||||
&& (! number_is_unknown(re))
|
||||
&& number_is_immediate(re, 16))
|
||||
&& number_is_immediate(re, IMM_WID))
|
||||
return draw_mul_immediate(le, re, wid);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ((!number_is_unknown(exp)) && number_is_immediate(exp, 16)) {
|
||||
int val = get_number_immediate(exp);
|
||||
fprintf(vvp_out, " %%movi %u, %d, %u;\n", res.base, val, wid);
|
||||
if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID)) {
|
||||
unsigned long val = get_number_immediate(exp);
|
||||
fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1836,8 +1898,8 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
|
|||
idx = 0;
|
||||
while (idx < nwid) {
|
||||
unsigned bits;
|
||||
unsigned trans = 16;
|
||||
if (nwid-idx < 16)
|
||||
unsigned trans = IMM_WID;
|
||||
if (nwid-idx < trans)
|
||||
trans = nwid-idx;
|
||||
|
||||
bits = *p;
|
||||
|
|
@ -1845,6 +1907,14 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
|
|||
if (trans > 8) {
|
||||
bits |= *p << 8;
|
||||
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);
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, res.wid-swid);
|
||||
unsigned base = res.base+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) {
|
||||
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,
|
||||
ivl_expr_width(sube), wid);
|
||||
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",
|
||||
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);
|
||||
clr_vector(res);
|
||||
res = tmp;
|
||||
|
|
@ -2460,7 +2536,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
|||
assert(res.base);
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
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);
|
||||
clr_vector(res);
|
||||
res = tmp;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ struct vector_info {
|
|||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -827,6 +827,7 @@ static void do_display(unsigned int mcd, struct strobe_cb_info*info)
|
|||
case vpiReg:
|
||||
case vpiIntegerVar:
|
||||
case vpiMemoryWord:
|
||||
case vpiPartSelect:
|
||||
do_display_numeric(mcd, info, item);
|
||||
break;
|
||||
|
||||
|
|
@ -1836,6 +1837,7 @@ static char *get_display(unsigned int *rtnsz, struct strobe_cb_info *info)
|
|||
case vpiReg:
|
||||
case vpiIntegerVar:
|
||||
case vpiMemoryWord:
|
||||
case vpiPartSelect:
|
||||
width = get_numeric(&result, info, item);
|
||||
rtn = realloc(rtn, (size+width)*sizeof(char));
|
||||
memcpy(rtn+size-1, result, width);
|
||||
|
|
|
|||
|
|
@ -279,6 +279,7 @@ typedef struct t_vpi_delay {
|
|||
#define vpiNamedFork 35
|
||||
#define vpiNet 36
|
||||
#define vpiParameter 41
|
||||
#define vpiPartSelect 42
|
||||
#define vpiPathTerm 43
|
||||
#define vpiRealVar 47
|
||||
#define vpiReg 48
|
||||
|
|
@ -297,6 +298,7 @@ typedef struct t_vpi_delay {
|
|||
#define vpiModPathIn 95
|
||||
#define vpiModPathOut 96
|
||||
#define vpiVariables 100
|
||||
#define vpiExpr 102
|
||||
|
||||
#define vpiCallback 1000
|
||||
|
||||
|
|
@ -346,8 +348,8 @@ typedef struct t_vpi_delay {
|
|||
# define vpiSysFuncReal vpiRealFunc
|
||||
# define vpiSysFuncTime vpiTimeFunc
|
||||
# define vpiSysFuncSized vpiSizedFunc
|
||||
#define vpiConstantSelect 53
|
||||
#define vpiSigned 65
|
||||
#define vpiExpr 102
|
||||
/* IVL private properties */
|
||||
#define _vpiNexusId 0x1000000
|
||||
|
||||
|
|
|
|||
|
|
@ -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_ADDI(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_ASSIGN_AV(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 {
|
||||
unsigned bit_idx[2];
|
||||
uint32_t bit_idx[2];
|
||||
vvp_net_t *net2;
|
||||
vvp_code_t cptr2;
|
||||
struct ufunc_core*ufunc_core_ptr;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%addi", of_ADDI, 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} },
|
||||
{ "%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/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} },
|
||||
|
|
|
|||
|
|
@ -173,22 +173,24 @@
|
|||
"%disable" { return K_disable; }
|
||||
"%fork" { return K_fork; }
|
||||
|
||||
/* Handle the specialized variable access functions. */
|
||||
|
||||
"&A" { return K_A; }
|
||||
"&PV" { return K_PV; }
|
||||
|
||||
"%"[.$_/a-zA-Z0-9]+ {
|
||||
yylval.text = strdup(yytext);
|
||||
assert(yylval.text);
|
||||
return T_INSTR; }
|
||||
|
||||
[0-9][0-9]* {
|
||||
yylval.numb = strtol(yytext, 0, 0);
|
||||
yylval.numb = strtoul(yytext, 0, 0);
|
||||
return T_NUMBER; }
|
||||
|
||||
"0x"[0-9a-fA-F]+ {
|
||||
yylval.numb = strtol(yytext, 0, 0);
|
||||
yylval.numb = strtoul(yytext, 0, 0);
|
||||
return T_NUMBER; }
|
||||
|
||||
|
||||
"&A" { return K_A; }
|
||||
|
||||
/* Handle some specialized constant/literals as symbols. */
|
||||
|
||||
"C4<"[01xz]*">" {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
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>
|
||||
|
||||
|
|
|
|||
11
vvp/parse.y
11
vvp/parse.y
|
|
@ -47,7 +47,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%union {
|
||||
char*text;
|
||||
char **table;
|
||||
long numb;
|
||||
unsigned long numb;
|
||||
bool flag;
|
||||
|
||||
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_NET8 K_NET8_S
|
||||
%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_RESOLV K_SCOPE K_SFUNC K_SHIFTL K_SHIFTR K_SHIFTRS
|
||||
%token K_THREAD K_TIMESCALE K_UFUNC
|
||||
|
|
@ -790,9 +790,14 @@ argument
|
|||
}
|
||||
| K_A '<' T_SYMBOL ',' T_NUMBER '>'
|
||||
{ $$ = 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. */
|
||||
symbols
|
||||
: symbol
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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
|
||||
* __vpiSignal. Return a nil if the type is not appropriate.
|
||||
|
|
@ -368,6 +382,7 @@ struct __vpiSysTaskCall {
|
|||
class vvp_net_t*fnet;
|
||||
unsigned file_idx;
|
||||
unsigned lineno;
|
||||
bool put_value;
|
||||
};
|
||||
|
||||
extern struct __vpiSysTaskCall*vpip_cur_task;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
* draw_tt.c program.
|
||||
*/
|
||||
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
|
||||
|
|
@ -109,6 +109,385 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind
|
|||
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)
|
||||
{
|
||||
if ((ref->vpi_type->type_code != vpiNet)
|
||||
|
|
@ -245,65 +624,6 @@ static vpiHandle signal_iterate(int code, vpiHandle ref)
|
|||
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)
|
||||
{
|
||||
unsigned wid = (rfp->msb >= rfp->lsb)
|
||||
|
|
@ -313,97 +633,6 @@ static unsigned signal_width(const struct __vpiSignal*rfp)
|
|||
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 vector to the caller. This causes no side-effect, and reads the
|
||||
|
|
@ -421,145 +650,47 @@ 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);
|
||||
assert(vsig);
|
||||
|
||||
char *rbuf = 0;
|
||||
|
||||
switch (vp->format) {
|
||||
|
||||
case vpiIntVal:
|
||||
signal_get_IntVal(rfp, vp);
|
||||
format_vpiIntVal(vsig, 0, wid, vp);
|
||||
break;
|
||||
|
||||
case vpiScalarVal:
|
||||
signal_get_ScalarVal(rfp, vp);
|
||||
format_vpiScalarVal(vsig, 0, vp);
|
||||
break;
|
||||
|
||||
case vpiStrengthVal:
|
||||
signal_get_StrengthVal(rfp, vp);
|
||||
format_vpiStrengthVal(vsig, 0, wid, vp);
|
||||
break;
|
||||
|
||||
case vpiBinStrVal:
|
||||
rbuf = need_result_buf(wid+1, RBUF_VAL);
|
||||
|
||||
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;
|
||||
format_vpiBinStrVal(vsig, 0, wid, vp);
|
||||
break;
|
||||
|
||||
case vpiHexStrVal: {
|
||||
unsigned hwid = (wid + 3) / 4;
|
||||
|
||||
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;
|
||||
format_vpiHexStrVal(vsig, 0, wid, vp);
|
||||
break;
|
||||
}
|
||||
|
||||
case vpiOctStrVal: {
|
||||
unsigned hval, hwid;
|
||||
hwid = (wid + 2) / 3;
|
||||
|
||||
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;
|
||||
case vpiOctStrVal:
|
||||
format_vpiOctStrVal(vsig, 0, wid, vp);
|
||||
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:
|
||||
vp->value.str = signal_vpiDecStrVal(rfp, vp);
|
||||
format_vpiDecStrVal(vsig, 0, wid, rfp->signed_flag, vp);
|
||||
break;
|
||||
|
||||
case vpiStringVal:
|
||||
vp->value.str = signal_vpiStringVal(rfp, vp);
|
||||
format_vpiStringVal(vsig, 0, wid, vp);
|
||||
break;
|
||||
|
||||
case vpiVectorVal: {
|
||||
unsigned int obit = 0;
|
||||
unsigned hwid = (wid - 1)/32 + 1;
|
||||
|
||||
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);
|
||||
case vpiVectorVal:
|
||||
format_vpiVectorVal(vsig, 0, wid, vp);
|
||||
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: {
|
||||
bool flag = rfp->signed_flag;
|
||||
vp->value.real = 0.0;
|
||||
vector4_to_value(vsig->vec4_value(), vp->value.real, flag);
|
||||
format_vpiRealVal(vsig, 0, wid, rfp->signed_flag, vp);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -812,3 +943,218 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,6 +167,8 @@ static vpiHandle sysfunc_put_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
|
||||
rfp->put_value = true;
|
||||
|
||||
assert(rfp->vbit >= 4);
|
||||
|
||||
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;
|
||||
|
||||
rfp->put_value = true;
|
||||
|
||||
/* Make sure this is a real valued function. */
|
||||
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;
|
||||
|
||||
rfp->put_value = true;
|
||||
|
||||
unsigned vwid = (unsigned) rfp->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);
|
||||
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
double val;
|
||||
|
||||
rfp->put_value = true;
|
||||
|
||||
double val;
|
||||
switch (vp->format) {
|
||||
|
||||
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->lineno = (unsigned) lineno;
|
||||
obj->userdata = 0;
|
||||
obj->put_value = false;
|
||||
|
||||
compile_compiletf(obj);
|
||||
|
||||
|
|
@ -590,8 +599,23 @@ void vpip_execute_vpi_call(vthread_t thr, vpiHandle ref)
|
|||
if (vpip_cur_task->defn->info.calltf) {
|
||||
assert(vpi_mode_flag == VPI_MODE_NONE);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 oct_digits[256];
|
||||
extern const char oct_digits[64];
|
||||
|
||||
/*
|
||||
* vpi_get
|
||||
|
|
|
|||
954
vvp/vthread.cc
954
vvp/vthread.cc
File diff suppressed because it is too large
Load Diff
|
|
@ -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)
|
||||
{
|
||||
if (bit4_is_xz(a))
|
||||
|
|
|
|||
|
|
@ -87,8 +87,21 @@ inline vvp_bit4_t bit4_z2x(vvp_bit4_t a)
|
|||
inline vvp_bit4_t operator ~ (vvp_bit4_t a)
|
||||
{ return bit4_z2x((vvp_bit4_t) (((int)a) ^ 1)); }
|
||||
|
||||
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);
|
||||
inline 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 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_);
|
||||
|
||||
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;
|
||||
amask <<= off;
|
||||
bmask <<= off;
|
||||
|
||||
if (size_ > BITS_PER_WORD) {
|
||||
unsigned wdx = idx / BITS_PER_WORD;
|
||||
switch (val) {
|
||||
case BIT4_0:
|
||||
abits_ptr_[wdx] &= ~mask;
|
||||
abits_ptr_[wdx] |= amask;
|
||||
bbits_ptr_[wdx] &= ~mask;
|
||||
bbits_ptr_[wdx] |= bmask;
|
||||
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 {
|
||||
switch (val) {
|
||||
case BIT4_0:
|
||||
abits_val_ &= ~mask;
|
||||
abits_val_ |= amask;
|
||||
bbits_val_ &= ~mask;
|
||||
bbits_val_ |= bmask;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue