diff --git a/vpi_user.h b/vpi_user.h index 6df2bada6..b9bc65997 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -291,6 +291,7 @@ typedef struct t_vpi_delay { #define vpiTimeVar 63 #define vpiIndex 78 #define vpiLeftRange 79 +#define vpiParent 81 #define vpiRightRange 83 #define vpiScope 84 #define vpiSysTfCall 85 @@ -312,8 +313,9 @@ typedef struct t_vpi_delay { #define vpiDefName 9 #define vpiTimeUnit 11 #define vpiTimePrecision 12 -#define vpiNetType 22 +#define vpiNetType 22 # define vpiWire 1 +#define vpiArray 28 #define vpiConstType 40 # define vpiDecConst 1 # define vpiRealConst 2 diff --git a/vvp/array.cc b/vvp/array.cc index 6f8c8f74a..7e67ce9e0 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -69,6 +69,12 @@ struct __vpiArrayIterator { unsigned next; }; +struct __vpiArrayIndex { + struct __vpiHandle base; + struct __vpiDecConst *index; + unsigned done; +}; + const char *get_array_name(char*label) { vvp_array_t array = array_find(label); @@ -94,6 +100,9 @@ static vpiHandle vpi_array_index(vpiHandle ref, int index); static vpiHandle array_iterator_scan(vpiHandle ref, int); static int array_iterator_free_object(vpiHandle ref); +static vpiHandle array_index_scan(vpiHandle ref, int); +static int array_index_free_object(vpiHandle ref); + static const struct __vpirt vpip_arraymem_rt = { vpiMemory, vpi_array_get, @@ -117,6 +126,21 @@ static const struct __vpirt vpip_array_iterator_rt = { &array_iterator_free_object }; +/* This should look a bit odd since it provides a fake iteration on + * this object. This trickery is used to implement the two forms of + * index access, simple handle access and iteration access. */ +static const struct __vpirt vpip_array_index_rt = { + vpiIterator, + 0, + 0, + 0, + 0, + 0, + array_index_iterate, + array_index_scan, + array_index_free_object +}; + # define ARRAY_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemory), \ (struct __vpiArray*)ref) @@ -239,6 +263,45 @@ static int array_iterator_free_object(vpiHandle ref) return 1; } +# define ARRAY_INDEX(ref) (assert(ref->vpi_type->type_code==vpiIterator), \ + (struct __vpiArrayIndex*)ref) + +vpiHandle array_index_iterate(int code, vpiHandle ref) +{ + assert(ref->vpi_type->type_code == vpiConstant); + struct __vpiDecConst*obj = (struct __vpiDecConst*)ref; + + if (code == vpiIndex) { + struct __vpiArrayIndex*res; + res = (struct __vpiArrayIndex*) calloc(1, sizeof (*res)); + res->base.vpi_type = &vpip_array_index_rt; + res->index = obj; + res->done = 0; + return &res->base; + } + return 0; +} + +static vpiHandle array_index_scan(vpiHandle ref, int) +{ + struct __vpiArrayIndex*obj = ARRAY_INDEX(ref); + + if (obj->done == 0) { + obj->done = 1; + return &obj->index->base; + } + + vpi_free_object(ref); + return 0; +} + +static int array_index_free_object(vpiHandle ref) +{ + struct __vpiArrayIndex*obj = ARRAY_INDEX(ref); + free(obj); + return 1; +} + void array_set_word(vvp_array_t arr, unsigned address, unsigned part_off, @@ -328,6 +391,8 @@ void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word) vvp_fun_signal_base*fun = dynamic_cast(net->fun); assert(fun); fun->attach_as_word(array, addr); + sig->parent = &array->base; + sig->index = vpip_make_dec_const(addr + array->first_addr.value); } } diff --git a/vvp/array.h b/vvp/array.h index 02fb8b9c4..c6973858e 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -34,6 +34,7 @@ typedef struct __vpiArray* vvp_array_t; extern vvp_array_t array_find(char*label); extern const char *get_array_name(char*label); extern const int get_array_base(char*label); +extern vpiHandle array_index_iterate(int code, vpiHandle ref); extern void array_word_change(vvp_array_t array, unsigned long addr); diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 48a84d891..a7b4839ee 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -91,8 +91,8 @@ struct __vpirt { int (*vpi_free_object_)(vpiHandle); /* - This tow method are used to read/write delay - value from/into modpath record + These two methods are used to read/write delay + values from/into modpath records */ void (*vpi_get_delays_)(vpiHandle, p_vpi_delay); void (*vpi_put_delays_)(vpiHandle, p_vpi_delay); @@ -190,6 +190,8 @@ extern void vpip_make_root_iterator(struct __vpiHandle**&table, */ struct __vpiSignal { struct __vpiHandle base; + vpiHandle parent; + vpiHandle index; struct __vpiScope* scope; /* The name of this reg/net, or [] for array words. */ const char*name; @@ -319,6 +321,8 @@ extern void vpip_run_memory_value_change(vpiHandle ref, unsigned adr); */ struct __vpiRealVar { struct __vpiHandle base; + vpiHandle parent; + vpiHandle index; struct __vpiScope* scope; const char*name; vvp_net_t*net; diff --git a/vvp/vpi_real.cc b/vvp/vpi_real.cc index 565021e95..fe1ff75ac 100644 --- a/vvp/vpi_real.cc +++ b/vvp/vpi_real.cc @@ -30,6 +30,18 @@ #endif # include +static int real_var_get(int code, vpiHandle ref) +{ + assert(ref->vpi_type->type_code == vpiRealVar); + + struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref; + + if (code == vpiArray) { + return rfp->parent != 0; + } + + return 0; +} static char* real_var_get_str(int code, vpiHandle ref) { @@ -60,6 +72,37 @@ static char* real_var_get_str(int code, vpiHandle ref) return 0; } +static vpiHandle real_var_get_handle(int code, vpiHandle ref) +{ + assert(ref->vpi_type->type_code == vpiRealVar); + + struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref; + + switch (code) { + + case vpiParent: + return rfp->parent; + + case vpiIndex: + return rfp->index; + } + + return 0; +} + +static vpiHandle real_var_iterate(int code, vpiHandle ref) +{ + assert(ref->vpi_type->type_code == vpiRealVar); + + struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref; + + if (code == vpiIndex) { + return (rfp->index->vpi_type->iterate_)(code, rfp->index); + } + + return 0; +} + static void real_var_get_value(vpiHandle ref, s_vpi_value*vp) { assert(ref->vpi_type->type_code == vpiRealVar); @@ -104,13 +147,13 @@ static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp) static const struct __vpirt vpip_real_var_rt = { vpiRealVar, - 0, - &real_var_get_str, - &real_var_get_value, - &real_var_put_value, + real_var_get, + real_var_get_str, + real_var_get_value, + real_var_put_value, - 0, - 0, + real_var_get_handle, + real_var_iterate, 0, 0 @@ -133,6 +176,8 @@ vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net) malloc(sizeof(struct __vpiRealVar)); obj->base.vpi_type = &vpip_real_var_rt; + obj->parent = 0; + obj->index = 0; obj->name = vpip_name_string(name); obj->net = net; diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index e49262ac0..e9499a8f6 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -97,6 +97,9 @@ static int signal_get(int code, vpiHandle ref) case vpiSigned: return rfp->signed_flag != 0; + case vpiArray: + return rfp->parent != 0; + case vpiSize: if (rfp->msb >= rfp->lsb) return rfp->msb - rfp->lsb + 1; @@ -162,6 +165,12 @@ static vpiHandle signal_get_handle(int code, vpiHandle ref) switch (code) { + case vpiParent: + return rfp->parent; + + case vpiIndex: + return rfp->index; + case vpiScope: return &rfp->scope->base; @@ -178,6 +187,20 @@ static vpiHandle signal_get_handle(int code, vpiHandle ref) return 0; } +static vpiHandle signal_iterate(int code, vpiHandle ref) +{ + assert((ref->vpi_type->type_code==vpiNet) + || (ref->vpi_type->type_code==vpiReg)); + + struct __vpiSignal*rfp = (struct __vpiSignal*)ref; + + if (code == vpiIndex) { + return array_index_iterate(code, rfp->index); + } + + return 0; +} + static char *signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp) { @@ -642,6 +665,7 @@ static const struct __vpirt vpip_reg_rt = { signal_get_value, signal_put_value, signal_get_handle, + signal_iterate, 0 }; @@ -652,6 +676,7 @@ static const struct __vpirt vpip_net_rt = { signal_get_value, signal_put_value, signal_get_handle, + signal_iterate, 0 }; @@ -710,6 +735,8 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb, { struct __vpiSignal*obj = allocate_vpiSignal(); obj->base.vpi_type = &vpip_net_rt; + obj->parent = 0; + obj->index = 0; obj->name = name? vpip_name_string(name) : 0; obj->msb = msb; obj->lsb = lsb;