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:
Martin Whitaker 2019-07-25 08:58:00 +01:00
parent 0cb1ebddf1
commit 8402696676
3 changed files with 39 additions and 12 deletions

View File

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

View File

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

View File

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