Add means for &A<> to index using a calculated index.
This is not a solution to all the problems, but is a better catch-all then what is currently there. Allow the index field to be a T<> that accesses the thread to get the address index. Note that the lexor.lex currently returns the T<> as a T_SYMBOL, and the users of T_SYMBOL objects need to interpret the meaning. This is probably not the best idea, in light of all the other *<> formats that now exist.
This commit is contained in:
parent
6a1235ac28
commit
a2dc1e0a29
|
|
@ -285,10 +285,17 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
word_ex = 0;
|
||||
}
|
||||
}
|
||||
if (word_ex)
|
||||
break;
|
||||
|
||||
snprintf(buffer, sizeof buffer, "&A<v%p, %u>", sig, use_word);
|
||||
if (word_ex) {
|
||||
struct vector_info av;
|
||||
av = draw_eval_expr(word_ex, STUFF_OK_XZ);
|
||||
snprintf(buffer, sizeof buffer,
|
||||
"&A<v%p, T<%u,%u,u>>", sig, av.base, av.wid);
|
||||
args[idx].vec = av;
|
||||
args[idx].vec_flag = 1;
|
||||
} else {
|
||||
snprintf(buffer, sizeof buffer,
|
||||
"&A<v%p, %u>", sig, use_word);
|
||||
}
|
||||
args[idx].text = strdup(buffer);
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -754,6 +754,47 @@ by the fork atomically joins that scope. Once the transient thread
|
|||
joins the scope, it stays there until it ends. Threads never change
|
||||
scopes, not even transient threads.
|
||||
|
||||
VPI TASK/FUNCTION CALLS
|
||||
|
||||
Threads call vpi tasks with the %vpi_call or %vpi_func
|
||||
instructions. The formats are:
|
||||
|
||||
%vpi_call <file-index> <lineno> <name>, <args>... ;
|
||||
%vpi_func <file-index> <lineno> <name>, <args>... ;
|
||||
%vpi_func/r <file-index> <lineno> <name>, <args>... ;
|
||||
|
||||
The <file-index> is an index into the string table. The indexed string
|
||||
is the source code file name where this call appears. The <lineno> is
|
||||
the line number from the source code where this task/function appears.
|
||||
|
||||
The <name> is a string that is the name of the system
|
||||
task/function. For example, "$display", $strobe", etc. This name is
|
||||
looked up and compared with the registered system tasks/functions.
|
||||
|
||||
The <args>... is a comma (",") separated list of arguments. These are
|
||||
made available to the VPI code as vpi handles.
|
||||
|
||||
* The &A<> argument
|
||||
|
||||
The &A<> argument is a reference to the word of a variable array. The
|
||||
syntax is:
|
||||
|
||||
&A '<' <symbol> , <number> '>'
|
||||
|
||||
The <symbol> is the label for a variable array, and the <number> is
|
||||
the cannonical word index as an unsigned integer.
|
||||
|
||||
* The T<> argument
|
||||
|
||||
This is the catch-all for arguments that are not otherwise
|
||||
handled. This references the bits directly in the thread. The format
|
||||
is:
|
||||
|
||||
T '<' <base>, <wid>, <su> '>'
|
||||
|
||||
The <base> and <wid> are the base of a vector value in the thread and
|
||||
the width of the vector. The <su> is 's' or 'u' for signed or unsigned.
|
||||
|
||||
TRUTH TABLES
|
||||
|
||||
The logic that a functor represents is expressed as a truth table. The
|
||||
|
|
|
|||
66
vvp/array.cc
66
vvp/array.cc
|
|
@ -83,7 +83,25 @@ struct __vpiArrayIndex {
|
|||
struct __vpiArrayVthrA {
|
||||
struct __vpiHandle base;
|
||||
struct __vpiArray*array;
|
||||
// If wid==0, then address is the address into the array.
|
||||
unsigned address;
|
||||
// If wid >0, then the address is the base and wid the vector
|
||||
// width of the index to pull from the thread.
|
||||
unsigned wid;
|
||||
|
||||
unsigned get_address() const
|
||||
{
|
||||
if (wid == 0)
|
||||
return address;
|
||||
vvp_vector4_t tmp (wid);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread, address+idx);
|
||||
tmp.set_bit(idx, bit);
|
||||
}
|
||||
unsigned long val;
|
||||
vector4_to_value(tmp, val);
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -516,7 +534,6 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref)
|
|||
return 0; // Not implemented for now!
|
||||
|
||||
case vpiSize:
|
||||
assert(parent->vals);
|
||||
return parent->vals_width;
|
||||
|
||||
case vpiLeftRange:
|
||||
|
|
@ -546,7 +563,7 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref)
|
|||
}
|
||||
|
||||
char sidx [64];
|
||||
snprintf(sidx, 63, "%d", (int)obj->address + parent->first_addr.value);
|
||||
snprintf(sidx, 63, "%d", (int)obj->get_address() + parent->first_addr.value);
|
||||
return generic_get_str(code, &parent->scope->base, parent->name, sidx);
|
||||
}
|
||||
|
||||
|
|
@ -557,18 +574,10 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value)
|
|||
struct __vpiArray*parent = obj->array;
|
||||
|
||||
assert(parent);
|
||||
assert(parent->vals);
|
||||
assert(obj->address < parent->array_count);
|
||||
|
||||
unsigned index = obj->address;
|
||||
unsigned width = parent->vals_width;
|
||||
|
||||
/* If we don't have a value yet just return X. */
|
||||
if (parent->vals[index].size() == 0) {
|
||||
vpip_vec4_get_value(vvp_vector4_t(width), width, false, value);
|
||||
} else {
|
||||
vpip_vec4_get_value(parent->vals[index], width, false, value);
|
||||
}
|
||||
unsigned index = obj->get_address();
|
||||
vvp_vector4_t tmp = array_get_word(parent, index);
|
||||
vpip_vec4_get_value(tmp, parent->vals_width, false, value);
|
||||
}
|
||||
|
||||
static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int)
|
||||
|
|
@ -577,10 +586,10 @@ static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
assert(obj);
|
||||
struct __vpiArray*parent = obj->array;
|
||||
|
||||
unsigned index = obj->address;
|
||||
unsigned index = obj->get_address();
|
||||
|
||||
assert(parent);
|
||||
assert(obj->address < parent->array_count);
|
||||
assert(index < parent->array_count);
|
||||
|
||||
vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width);
|
||||
array_set_word(parent, index, 0, val);
|
||||
|
|
@ -1053,13 +1062,40 @@ vpiHandle vpip_make_vthr_A(char*label, unsigned addr)
|
|||
|
||||
obj->array = array_find(label);
|
||||
assert(obj->array);
|
||||
free(label);
|
||||
|
||||
obj->address = addr;
|
||||
obj->wid = 0;
|
||||
assert(addr < obj->array->array_count);
|
||||
|
||||
return &(obj->base);
|
||||
}
|
||||
|
||||
vpiHandle vpip_make_vthr_A(char*label, char*symbol)
|
||||
{
|
||||
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
||||
malloc(sizeof (struct __vpiArrayVthrA));
|
||||
|
||||
obj->base.vpi_type = &vpip_array_vthr_A_rt;
|
||||
|
||||
obj->array = array_find(label);
|
||||
assert(obj->array);
|
||||
free(label);
|
||||
|
||||
unsigned base;
|
||||
unsigned wid;
|
||||
char sflag;
|
||||
int rc = sscanf(symbol, "T<%u,%u,%c>", &base, &wid, &sflag);
|
||||
assert(rc == 3);
|
||||
free(symbol);
|
||||
|
||||
obj->address = base;
|
||||
obj->wid = wid;
|
||||
assert(sflag == 'u');
|
||||
|
||||
return &(obj->base);
|
||||
}
|
||||
|
||||
void compile_array_cleanup(void)
|
||||
{
|
||||
if (array_table) {
|
||||
|
|
|
|||
|
|
@ -817,6 +817,8 @@ argument
|
|||
}
|
||||
| K_A '<' T_SYMBOL ',' T_NUMBER '>'
|
||||
{ $$ = vpip_make_vthr_A($3, $5); }
|
||||
| K_A '<' T_SYMBOL ',' T_SYMBOL '>'
|
||||
{ $$ = 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 '>'
|
||||
|
|
|
|||
|
|
@ -446,6 +446,7 @@ vpiHandle vpip_make_vthr_vector(unsigned base, unsigned wid, bool signed_flag);
|
|||
vpiHandle vpip_make_vthr_word(unsigned base, const char*type);
|
||||
|
||||
vpiHandle vpip_make_vthr_A(char*symbol, unsigned index);
|
||||
vpiHandle vpip_make_vthr_A(char*symbol, char*symbol);
|
||||
|
||||
/*
|
||||
* This function is called before any compilation to load VPI
|
||||
|
|
|
|||
Loading…
Reference in New Issue