Add smart part select for system functions &PV<>.

This patch adds a smart part select that allows system functions
to have full access to the real bits of the part select.
This commit is contained in:
Cary R 2008-05-27 14:29:08 -07:00 committed by Stephen Williams
parent f04fb0fc45
commit 2fab3159dd
8 changed files with 753 additions and 273 deletions

View File

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

View File

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

View File

@ -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 vpiSigned 65
#define vpiExpr 102
#define vpiConstantSelect 53
#define vpiSigned 65
/* IVL private properties */
#define _vpiNexusId 0x1000000

View File

@ -173,6 +173,11 @@
"%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);
@ -186,9 +191,6 @@
yylval.numb = strtol(yytext, 0, 0);
return T_NUMBER; }
"&A" { return K_A; }
/* Handle some specialized constant/literals as symbols. */
"C4<"[01xz]*">" {

View File

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

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,
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.

View File

@ -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,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);
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;
break;
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;
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 vpiOctStrVal:
format_vpiOctStrVal(vsig, 0, wid, vp);
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);
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 vpiVectorVal:
format_vpiVectorVal(vsig, 0, wid, vp);
break;
case vpiRealVal: {
bool flag = rfp->signed_flag;
vp->value.real = 0.0;
vector4_to_value(vsig->vec4_value(), vp->value.real, flag);
break;
format_vpiRealVal(vsig, 0, wid, rfp->signed_flag, vp);
break;
}
default:
@ -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;
}

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 oct_digits[256];
extern const char oct_digits[64];
/*
* vpi_get