Fix VPI interface to APV objects.
- type is vpiPartSelect, not vpiMemoryWord - left/right range is for part, not full word - index is not valid for a part select The user will now get a sensible error message if they pass part of an array word to $dumpvars (GitHub issue #230).
This commit is contained in:
parent
0cb1ebddf1
commit
8402696676
32
vvp/array.cc
32
vvp/array.cc
|
|
@ -95,10 +95,11 @@ struct __vpiArrayVthrA : public __vpiHandle {
|
|||
|
||||
|
||||
struct __vpiArrayVthrAPV : public __vpiHandle {
|
||||
int get_type_code(void) const { return vpiMemoryWord; }
|
||||
int get_type_code(void) const { return vpiPartSelect; }
|
||||
int vpi_get(int code);
|
||||
char* vpi_get_str(int code);
|
||||
void vpi_get_value(p_vpi_value val);
|
||||
vpiHandle vpi_handle(int code);
|
||||
|
||||
struct __vpiArray*array;
|
||||
unsigned word_sel;
|
||||
|
|
@ -495,13 +496,10 @@ int __vpiArrayVthrAPV::vpi_get(int code)
|
|||
return part_wid;
|
||||
|
||||
case vpiLeftRange:
|
||||
return array->msb.get_value();
|
||||
return part_bit + part_wid - 1;
|
||||
|
||||
case vpiRightRange:
|
||||
return array->lsb.get_value();
|
||||
|
||||
case vpiIndex:
|
||||
return (int)word_sel;
|
||||
return part_bit;
|
||||
|
||||
case vpiAutomatic:
|
||||
return array->get_scope()->is_automatic() ? 1 : 0;
|
||||
|
|
@ -545,6 +543,28 @@ void __vpiArrayVthrAPV::vpi_get_value(p_vpi_value vp)
|
|||
}
|
||||
}
|
||||
|
||||
vpiHandle __vpiArrayVthrAPV::vpi_handle(int code)
|
||||
{
|
||||
switch (code) {
|
||||
// Not currently implemented. We would need to create a VPI
|
||||
// object for the memory word.
|
||||
case vpiParent:
|
||||
return 0;
|
||||
|
||||
// Not part of the Verilog standard. We use this internally.
|
||||
case vpiArray:
|
||||
return array;
|
||||
|
||||
case vpiScope:
|
||||
return array->get_scope();
|
||||
|
||||
case vpiModule:
|
||||
return vpip_module(array->get_scope());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __vpiArray::set_word(unsigned address, unsigned part_off, const vvp_vector4_t&val)
|
||||
{
|
||||
if (address >= get_size())
|
||||
|
|
|
|||
|
|
@ -209,8 +209,12 @@ static value_callback* make_value_change(p_cb_data data)
|
|||
}
|
||||
|
||||
// Special case: the target object is a vpiPartSelect
|
||||
if (data->obj->get_type_code() == vpiPartSelect)
|
||||
return make_value_change_part(data);
|
||||
if (data->obj->get_type_code() == vpiPartSelect) {
|
||||
if (data->obj->vpi_handle(vpiArray))
|
||||
return vpip_array_word_change(data);
|
||||
else
|
||||
return make_value_change_part(data);
|
||||
}
|
||||
|
||||
if (data->obj->get_type_code() == vpiMemoryWord)
|
||||
return vpip_array_word_change(data);
|
||||
|
|
|
|||
|
|
@ -915,15 +915,18 @@ void vpi_call_delete(vpiHandle item)
|
|||
case _vpi_at_A:
|
||||
A_delete(obj->args[arg]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case vpiPartSelect:
|
||||
switch (vpi_get(_vpiFromThr, obj->args[arg])) {
|
||||
case _vpi_at_PV:
|
||||
PV_delete(obj->args[arg]);
|
||||
break;
|
||||
case _vpi_at_APV:
|
||||
APV_delete(obj->args[arg]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case vpiPartSelect:
|
||||
assert(vpi_get(_vpiFromThr, obj->args[arg]) == _vpi_at_PV);
|
||||
PV_delete(obj->args[arg]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(obj->args);
|
||||
|
|
|
|||
Loading…
Reference in New Issue