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 {
|
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);
|
int vpi_get(int code);
|
||||||
char* vpi_get_str(int code);
|
char* vpi_get_str(int code);
|
||||||
void vpi_get_value(p_vpi_value val);
|
void vpi_get_value(p_vpi_value val);
|
||||||
|
vpiHandle vpi_handle(int code);
|
||||||
|
|
||||||
struct __vpiArray*array;
|
struct __vpiArray*array;
|
||||||
unsigned word_sel;
|
unsigned word_sel;
|
||||||
|
|
@ -495,13 +496,10 @@ int __vpiArrayVthrAPV::vpi_get(int code)
|
||||||
return part_wid;
|
return part_wid;
|
||||||
|
|
||||||
case vpiLeftRange:
|
case vpiLeftRange:
|
||||||
return array->msb.get_value();
|
return part_bit + part_wid - 1;
|
||||||
|
|
||||||
case vpiRightRange:
|
case vpiRightRange:
|
||||||
return array->lsb.get_value();
|
return part_bit;
|
||||||
|
|
||||||
case vpiIndex:
|
|
||||||
return (int)word_sel;
|
|
||||||
|
|
||||||
case vpiAutomatic:
|
case vpiAutomatic:
|
||||||
return array->get_scope()->is_automatic() ? 1 : 0;
|
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)
|
void __vpiArray::set_word(unsigned address, unsigned part_off, const vvp_vector4_t&val)
|
||||||
{
|
{
|
||||||
if (address >= get_size())
|
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
|
// Special case: the target object is a vpiPartSelect
|
||||||
if (data->obj->get_type_code() == vpiPartSelect)
|
if (data->obj->get_type_code() == vpiPartSelect) {
|
||||||
return make_value_change_part(data);
|
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)
|
if (data->obj->get_type_code() == vpiMemoryWord)
|
||||||
return vpip_array_word_change(data);
|
return vpip_array_word_change(data);
|
||||||
|
|
|
||||||
|
|
@ -915,15 +915,18 @@ void vpi_call_delete(vpiHandle item)
|
||||||
case _vpi_at_A:
|
case _vpi_at_A:
|
||||||
A_delete(obj->args[arg]);
|
A_delete(obj->args[arg]);
|
||||||
break;
|
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:
|
case _vpi_at_APV:
|
||||||
APV_delete(obj->args[arg]);
|
APV_delete(obj->args[arg]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case vpiPartSelect:
|
|
||||||
assert(vpi_get(_vpiFromThr, obj->args[arg]) == _vpi_at_PV);
|
|
||||||
PV_delete(obj->args[arg]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(obj->args);
|
free(obj->args);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue