From 13f861a963df3acec3768df72018db985008721d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 31 Oct 2014 09:55:36 +0100 Subject: [PATCH 01/29] ivl: Added PECastType to handle type casting. --- PExpr.cc | 9 +++++++++ PExpr.h | 22 +++++++++++++++++++++ elab_expr.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ pform_dump.cc | 8 ++++++++ 4 files changed, 94 insertions(+) diff --git a/PExpr.cc b/PExpr.cc index 4c7f303f6..7e0e3693f 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -146,6 +146,15 @@ PECastSize::~PECastSize() { } +PECastType::PECastType(data_type_t*t, PExpr*b) +: target_(t), base_(b) +{ +} + +PECastType::~PECastType() +{ +} + PEBComp::PEBComp(char op, PExpr*l, PExpr*r) : PEBinary(op, l, r) { diff --git a/PExpr.h b/PExpr.h index 44c4008a5..004c619a7 100644 --- a/PExpr.h +++ b/PExpr.h @@ -986,6 +986,28 @@ class PECastSize : public PExpr { PExpr* base_; }; +/* + * Support the SystemVerilog cast to a different type. + */ +class PECastType : public PExpr { + + public: + explicit PECastType(data_type_t*target, PExpr*base); + ~PECastType(); + + void dump(ostream &out) const; + + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + unsigned expr_wid, unsigned flags) const; + + virtual unsigned test_width(Design*des, NetScope*scope, + width_mode_t&mode); + + private: + data_type_t* target_; + PExpr* base_; +}; + /* * This class is used for error recovery. All methods do nothing and return * null or default values. diff --git a/elab_expr.cc b/elab_expr.cc index c64582df4..e8507e904 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -36,6 +36,7 @@ # include "netmisc.h" # include "netdarray.h" # include "netstruct.h" +# include "netscalar.h" # include "util.h" # include "ivl_assert.h" @@ -2431,6 +2432,60 @@ NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope, return sel; } +unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) +{ + ivl_type_t t = target_->elaborate_type(des, scope); + base_->test_width(des, scope, wid); + + if(const netdarray_t*use_darray = dynamic_cast (t)) { + expr_type_ = use_darray->element_base_type(); + expr_width_ = use_darray->element_width(); + signed_flag_= false; + } + + else if(const netstring_t*use_string = dynamic_cast (t)) { + expr_type_ = use_string->base_type(); + expr_width_ = 1; + signed_flag_= false; + } + + else if(const netstruct_t*use_struct = dynamic_cast (t)) { + ivl_assert(*this, use_struct->packed()); + expr_type_ = use_struct->base_type(); + expr_width_ = use_struct->packed_width(); + signed_flag_= false; + } + + else if(const netvector_t*use_vector = dynamic_cast (t)) { + ivl_assert(*this, use_vector->packed()); + expr_type_ = use_vector->base_type(); + expr_width_ = use_vector->packed_width(); + signed_flag_= false; + } + + else { + expr_width_ = t->packed_width(); + } + + min_width_ = expr_width_; + return expr_width_; +} + +NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, + unsigned, unsigned) const +{ + if(dynamic_cast(target_)) + { + NetExpr*expr = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS); + return cast_to_real(expr); + } + + cerr << get_fileline() << "sorry: I don't know how to cast expression." << endl; + ivl_assert(*this, false); + + return expr; +} + unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&) { expr_width_ = 0; diff --git a/pform_dump.cc b/pform_dump.cc index 981fbecd2..4cbd994ec 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -323,6 +323,14 @@ void PECastSize::dump(ostream &out) const out << ")"; } +void PECastType::dump(ostream &out) const +{ + target_->pform_dump(out, 0); + out << "'("; + base_->dump(out); + out << ")"; +} + void PEEvent::dump(ostream&out) const { switch (type_) { From daa59a95ada1ddcb829acbd4affd349e54e6f3f1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 31 Oct 2014 09:47:02 +0100 Subject: [PATCH 02/29] ivl: Parsing rules for type casting. --- parse.y | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/parse.y b/parse.y index b2f1a815a..a69b43c1a 100644 --- a/parse.y +++ b/parse.y @@ -3543,6 +3543,18 @@ expr_primary } } + | data_type '\'' '(' expression ')' + { PExpr*base = $4; + if (gn_system_verilog()) { + PECastType*tmp = new PECastType($1, base); + FILE_NAME(tmp, @1); + $$ = tmp; + } else { + yyerror(@1, "error: Type cast requires SystemVerilog."); + $$ = base; + } + } + /* Aggregate literals are primaries. */ | assignment_pattern From 610ca95cbede2bc2ebe31ed01b79f4c6b583f496 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 31 Oct 2014 11:31:02 +0100 Subject: [PATCH 03/29] ivl: Allow to initialize variables with other variables (since Verilog-2001). --- pform.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pform.cc b/pform.cc index ecb81b721..48b136755 100644 --- a/pform.cc +++ b/pform.cc @@ -2239,7 +2239,7 @@ void pform_make_reginit(const struct vlltype&li, PEIdent*lval = new PEIdent(name); FILE_NAME(lval, li); - PAssign*ass = new PAssign(lval, expr, true); + PAssign*ass = new PAssign(lval, expr, generation_flag < GN_VER2001); FILE_NAME(ass, li); PProcess*top = new PProcess(IVL_PR_INITIAL, ass); FILE_NAME(top, li); From 43c6a0bacd03510fc6f1e7922fc155a14cd9f1eb Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 3 Nov 2014 10:49:05 +0100 Subject: [PATCH 04/29] ivl: Casting to int. --- elab_expr.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index e8507e904..84a0ab502 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2464,7 +2464,8 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) } else { - expr_width_ = t->packed_width(); + expr_width_ = t->packed_width(); + signed_flag_= false; } min_width_ = expr_width_; @@ -2474,12 +2475,18 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, unsigned, unsigned) const { + NetExpr*expr = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS); + if(dynamic_cast(target_)) { - NetExpr*expr = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS); return cast_to_real(expr); } + if(dynamic_cast(target_)) + { + return cast_to_int2(expr, expr_width_); + } + cerr << get_fileline() << "sorry: I don't know how to cast expression." << endl; ivl_assert(*this, false); From 89d1125979aa26e076923e00b445f21c12df8ac8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 3 Nov 2014 16:56:12 +0100 Subject: [PATCH 05/29] ivl: Bit selection using variables in strings. --- elab_expr.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/elab_expr.cc b/elab_expr.cc index 84a0ab502..78a45cb20 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -5004,6 +5004,18 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, return res; } + if (net->sig()->data_type() == IVL_VT_STRING) { + // Special case: This is a select of a string. + // This should be interpreted as a byte select. + if (debug_elaborate) { + cerr << get_fileline() << ": debug: " + << "Bit select of a string becomes NetESelect." << endl; + } + NetESelect*res = new NetESelect(net, mux, 8); + res->set_line(*net); + return res; + } + // Non-constant bit select? punt and make a subsignal // device to mux the bit in the net. This is a fairly // complicated task because we need to generate From 25c588252f5c7e9ca41edc7b104bfafcc16081df Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 5 Nov 2014 16:08:14 +0100 Subject: [PATCH 06/29] ivl: Added vpiSysFuncVoid to the system function types. --- sys_funcs.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys_funcs.cc b/sys_funcs.cc index 8e13ddede..3e2b26a51 100644 --- a/sys_funcs.cc +++ b/sys_funcs.cc @@ -193,6 +193,17 @@ int load_sys_func_table(const char*path) continue; } + if (strcmp(stype,"vpiSysFuncVoid") == 0) { + cell = new struct sfunc_return_type_cell; + cell->name = lex_strings.add(name); + cell->type = IVL_VT_VOID; + cell->wid = 0; + cell->signed_flag = false; + cell->next = sfunc_stack; + sfunc_stack = cell; + continue; + } + fprintf(stderr, "%s:%s: Unknown type: %s\n", path, name, stype); } From 21c8b8ca5a0d03dd5d0f9b84ace69ef62accaf82 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 5 Nov 2014 11:24:07 +0100 Subject: [PATCH 07/29] vpi: Added $ivl_string_method$to_vec for strings to vectors conversion. --- vpi/system.sft | 3 +- vpi/v2009_string.c | 125 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/vpi/system.sft b/vpi/system.sft index 2e65eade3..f3048198f 100644 --- a/vpi/system.sft +++ b/vpi/system.sft @@ -22,4 +22,5 @@ $simparam vpiSysFuncReal $simparam$str vpiSysFuncSized 1024 unsigned $table_model vpiSysFuncReal -$ivl_string_method$len vpiSysFuncInt +$ivl_string_method$len vpiSysFuncInt +$ivl_string_method$to_vec vpiSysFuncVoid diff --git a/vpi/v2009_string.c b/vpi/v2009_string.c index bb7bed623..e9b98cb79 100644 --- a/vpi/v2009_string.c +++ b/vpi/v2009_string.c @@ -19,6 +19,9 @@ # include "sys_priv.h" # include +# include +# include +# include static PLI_INT32 one_string_arg_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name) { @@ -75,6 +78,118 @@ static PLI_INT32 len_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) return 0; } + +static PLI_INT32 to_vec_compiletf(ICARUS_VPI_CONST PLI_BYTE8*user_data) +{ + (void) user_data; /* Parameter is not used. */ + + vpiHandle systf_handle, arg_iterator, arg_handle; + PLI_INT32 arg_type[2]; + + /* obtain a handle to the system task instance */ + systf_handle = vpi_handle(vpiSysTfCall, NULL); + if (systf_handle == NULL) { + vpi_printf("ERROR: $ivl_string_method$to_vec failed to obtain systf handle\n"); + vpi_control(vpiFinish,0); /* abort simulation */ + return 0; + } + + /* obtain handles to system task arguments */ + arg_iterator = vpi_iterate(vpiArgument, systf_handle); + if (arg_iterator == NULL) { + vpi_printf("ERROR: $ivl_string_method$to_vec requires 2 arguments\n"); + vpi_control(vpiFinish, 0); + return 0; + } + + /* check the type of object in system task arguments */ + arg_handle = vpi_scan(arg_iterator); + for(int i = 0; i < 2; ++i) { + arg_type[i] = vpi_get(vpiType, arg_handle); + arg_handle = vpi_scan(arg_iterator); + } + + if (arg_handle != NULL) { /* are there more arguments? */ + vpi_printf("ERROR: $ivl_string_method$to_vec can only have 2 arguments\n"); + vpi_free_object(arg_iterator); + vpi_control(vpiFinish, 0); + return 0; + } + + if ((arg_type[0] != vpiStringVar) || + (arg_type[1] != vpiNet && arg_type[1] != vpiReg)) { + vpi_printf("ERROR: $ivl_string_method$to_vec value arguments must be a string and a net or reg\n"); + vpi_free_object(arg_iterator); + vpi_control(vpiFinish, 0); + return 0; + } + + return 0; +} + +static PLI_INT32 to_vec_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) +{ + (void)name; /* Parameter is not used. */ + + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv, str, vec; + s_vpi_value str_val; + s_vpi_vecval*vec_val; + + /* Fetch arguments */ + argv = vpi_iterate(vpiArgument, callh); + assert(argv); + str = vpi_scan(argv); + assert(str); + vec = vpi_scan(argv); + assert(vec); + vpi_free_object(argv); + + int str_size = vpi_get(vpiSize, str); + int vec_size = vpi_get(vpiSize, vec); + if(str_size <= 0) { + vpi_printf("ERROR: Cannot cast empty string"); + assert(0); + } + + if(vec_size != str_size * 8) { + vpi_printf("ERROR: String and vector size do not match"); + assert(0); + } + + str_val.format = vpiStringVal; + vpi_get_value(str, &str_val); + assert(str_val.value.str); + + /* Conversion part */ + int vec_number = ceil((double)str_size / sizeof(PLI_INT32)); + vec_val = calloc(vec_number, sizeof(s_vpi_vecval)); + PLI_BYTE8*str_ptr = &str_val.value.str[str_size - 1]; + + /* We have to reverse the order of string, no memcpy here */ + for(int i = 0; i < vec_number; ++i) { + int copy_size = str_size > (int)sizeof(PLI_INT32) ? + (int)sizeof(PLI_INT32) : str_size; + + /* Clear the part responsible for X & Z values */ + memset(&vec_val[i].bval, 0x00, sizeof(PLI_INT32)); + PLI_BYTE8*dest = (PLI_BYTE8*)&vec_val[i].aval; + + for(int j = 0; j < copy_size; ++j) + *dest++ = *str_ptr--; + + str_size -= copy_size; + } + + str_val.format = vpiVectorVal; + str_val.value.vector = vec_val; + vpi_put_value(vec, &str_val, 0, vpiNoDelay); + + free(vec_val); + + return 0; +} + void v2009_string_register(void) { s_vpi_systf_data tf_data; @@ -89,4 +204,14 @@ void v2009_string_register(void) tf_data.user_data = "$ivl_string_method$len"; res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); + + tf_data.type = vpiSysTask; + tf_data.sysfunctype = 0; + tf_data.tfname = "$ivl_string_method$to_vec"; + tf_data.calltf = to_vec_calltf; + tf_data.compiletf = to_vec_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$ivl_string_method$to_vec"; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); } From 103828577b9178aa9bc5b636438811ecedd5ffd0 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 5 Nov 2014 16:46:55 +0100 Subject: [PATCH 08/29] ivl: Fixed indentations. --- elab_expr.cc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 78a45cb20..847061fbb 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2475,22 +2475,22 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, unsigned, unsigned) const { - NetExpr*expr = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS); + NetExpr*expr = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS); - if(dynamic_cast(target_)) - { - return cast_to_real(expr); - } + if(dynamic_cast(target_)) + { + return cast_to_real(expr); + } - if(dynamic_cast(target_)) - { - return cast_to_int2(expr, expr_width_); - } + if(dynamic_cast(target_)) + { + return cast_to_int2(expr, expr_width_); + } - cerr << get_fileline() << "sorry: I don't know how to cast expression." << endl; - ivl_assert(*this, false); + cerr << get_fileline() << "sorry: I don't know how to cast expression." << endl; + ivl_assert(*this, false); - return expr; + return expr; } unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&) From b12e00d87542eca4115585d82f0f4a218833c37a Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 6 Nov 2014 10:04:21 +0100 Subject: [PATCH 09/29] ivl: String to vector casting. --- elab_expr.cc | 16 +++++++++++++++- tgt-vvp/stmt_assign.c | 8 ++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/elab_expr.cc b/elab_expr.cc index 847061fbb..a17a6bd2b 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2445,7 +2445,7 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) else if(const netstring_t*use_string = dynamic_cast (t)) { expr_type_ = use_string->base_type(); - expr_width_ = 1; + expr_width_ = 8; signed_flag_= false; } @@ -2487,6 +2487,20 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, return cast_to_int2(expr, expr_width_); } + if(const vector_type_t*vec = dynamic_cast(target_)) + { + switch(vec->base_type) { + case IVL_VT_BOOL: + return cast_to_int2(expr, expr_width_); + + case IVL_VT_LOGIC: + return cast_to_int4(expr, expr_width_); + + default: + break; /* Suppress warnings */ + } + } + cerr << get_fileline() << "sorry: I don't know how to cast expression." << endl; ivl_assert(*this, false); diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 761d967a1..c7607920a 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -593,6 +593,14 @@ static int show_stmt_assign_vector(ivl_statement_t net) fprintf(vvp_out, " %%cvt/vr %u, %u;\n", res.base, res.wid); + } else if (ivl_expr_value(rval) == IVL_VT_STRING) { + /* Special case: vector to string casting */ + ivl_lval_t lval = ivl_stmt_lval(net, 0); + fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0};\n", + ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net), + ivl_expr_signal(rval), ivl_lval_sig(lval)); + return 0; + } else { res = draw_eval_expr(rval, 0); } From 675dd91403eb220f82d8400eb6e4a7501ff1e42b Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 6 Nov 2014 16:21:24 +0100 Subject: [PATCH 10/29] ivl: Added sign checking & casting between integers of different size. --- elab_expr.cc | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index a17a6bd2b..685e404f2 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2440,34 +2440,19 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid) if(const netdarray_t*use_darray = dynamic_cast (t)) { expr_type_ = use_darray->element_base_type(); expr_width_ = use_darray->element_width(); - signed_flag_= false; } else if(const netstring_t*use_string = dynamic_cast (t)) { expr_type_ = use_string->base_type(); expr_width_ = 8; - signed_flag_= false; - } - - else if(const netstruct_t*use_struct = dynamic_cast (t)) { - ivl_assert(*this, use_struct->packed()); - expr_type_ = use_struct->base_type(); - expr_width_ = use_struct->packed_width(); - signed_flag_= false; - } - - else if(const netvector_t*use_vector = dynamic_cast (t)) { - ivl_assert(*this, use_vector->packed()); - expr_type_ = use_vector->base_type(); - expr_width_ = use_vector->packed_width(); - signed_flag_= false; } else { + expr_type_ = t->base_type(); expr_width_ = t->packed_width(); - signed_flag_= false; } + signed_flag_= t->get_signed(); min_width_ = expr_width_; return expr_width_; } @@ -2482,9 +2467,12 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, return cast_to_real(expr); } - if(dynamic_cast(target_)) + if(const atom2_type_t*atom = dynamic_cast(target_)) { - return cast_to_int2(expr, expr_width_); + // That is how you both resize & cast to integers + ivl_assert(*this, base_->expr_width() <= expr_width_); + ivl_assert(*this, base_->has_sign() == atom->signed_flag); // no sign casting here + return new NetECast('2', expr, expr_width_, expr->has_sign()); } if(const vector_type_t*vec = dynamic_cast(target_)) From b2deae7ba998002825c540f1d6c90cbc5fedaace Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 7 Nov 2014 10:02:12 +0100 Subject: [PATCH 11/29] ivl: More meaningful errors messages. Minor code formatting. --- elab_expr.cc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 685e404f2..b2f812830 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2462,21 +2462,26 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, { NetExpr*expr = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS); - if(dynamic_cast(target_)) - { + if(dynamic_cast(target_)) { return cast_to_real(expr); } - if(const atom2_type_t*atom = dynamic_cast(target_)) - { + if(const atom2_type_t*atom = dynamic_cast(target_)) { + if(base_->expr_width() > expr_width_) { + cerr << get_fileline() << ": cast type is not wide enough to store the result." << endl; + ivl_assert(*this, 0); + } + + if(base_->has_sign() != atom->signed_flag) { + cerr << get_fileline() << ": cast type and subject differ in signedness." << endl; + ivl_assert(*this, 0); + } + // That is how you both resize & cast to integers - ivl_assert(*this, base_->expr_width() <= expr_width_); - ivl_assert(*this, base_->has_sign() == atom->signed_flag); // no sign casting here return new NetECast('2', expr, expr_width_, expr->has_sign()); } - if(const vector_type_t*vec = dynamic_cast(target_)) - { + if(const vector_type_t*vec = dynamic_cast(target_)) { switch(vec->base_type) { case IVL_VT_BOOL: return cast_to_int2(expr, expr_width_); @@ -2489,7 +2494,7 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, } } - cerr << get_fileline() << "sorry: I don't know how to cast expression." << endl; + cerr << get_fileline() << ": sorry: I don't know how to cast expression." << endl; ivl_assert(*this, false); return expr; From c3a318f14e14b1c217f7fbe145e83889ced985ea Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 7 Nov 2014 15:31:56 +0100 Subject: [PATCH 12/29] ivl: Casting vectors to strings. --- elab_expr.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/elab_expr.cc b/elab_expr.cc index b2f812830..fb07e07da 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2494,6 +2494,19 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, } } + else if(dynamic_cast(target_)) { + if(base_->expr_type() == IVL_VT_STRING) + return expr; // no conversion + + if((base_->expr_type() != IVL_VT_BOOL) && + (base_->expr_type() != IVL_VT_LOGIC)) { + cerr << get_fileline() << ": cannot be casted to string." << endl; + ivl_assert(*this, false); + } + + return expr; + } + cerr << get_fileline() << ": sorry: I don't know how to cast expression." << endl; ivl_assert(*this, false); From 1166cd932aacd9a59ccf2cd3332c8faa5af7161d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 11 Nov 2014 10:39:01 +0100 Subject: [PATCH 13/29] vpi: Handle new formats in vpi_get_value() for unpacked arrays. It is possible to use vpiIntVal, vpiVectorVal, vpiRealVal, vpiStringVal and vpiObjTypeVal to retrieve data from unpacked array cells. --- vvp/array.cc | 122 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 39 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 396b7effe..c664fd647 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -644,6 +644,42 @@ static char*vpi_array_var_word_get_str(int code, vpiHandle ref) return generic_get_str(code, parent->scope, parent->name, sidx); } +// This function return true if the underlying array words are real. +static bool vpi_array_is_real(vvp_array_t arr) +{ + // Check to see if this is a variable/register array. + if (arr->vals4 != 0) // A bit based variable/register array. + return false; + + if (dynamic_cast (arr->vals)) + return true; + + if (arr->vals != 0) + return false; + + // This must be a net array so look at element 0 to find the type. + assert(arr->nets != 0); + assert(arr->array_count > 0); + struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]); + if (rsig) { + return true; + } + + return false; +} + +static bool vpi_array_is_string(vvp_array_t arr) +{ + // Check to see if this is a variable/register array. + if (arr->vals4 != 0) // A bit based variable/register array. + return false; + + if (dynamic_cast (arr->vals)) + return true; + + return false; +} + static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value vp) { struct __vpiArrayWord*obj = array_var_word_from_handle(ref); @@ -651,10 +687,54 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value vp) assert(obj); unsigned index = decode_array_word_pointer(obj, parent); - unsigned width = parent->vals4->width(); - vpip_vec4_get_value(parent->vals4->get_word(index), width, - parent->signed_flag, vp); + // Determine the appropriate format (The Verilog PLI Handbook 5.2.10) + if(vp->format == vpiObjTypeVal) { + if(vpi_array_is_real(parent)) + vp->format = vpiRealVal; + else if(vpi_array_is_string(parent)) + vp->format = vpiStringVal; + else + vp->format = vpiIntVal; + } + + if(parent->vals4) { + vpip_vec4_get_value(parent->vals4->get_word(index), + parent->vals4->width(), parent->signed_flag, vp); + } else if(parent->vals) { + switch(vp->format) { + case vpiIntVal: + case vpiVectorVal: + { + vvp_vector4_t v; + parent->vals->get_word(index, v); + vpip_vec2_get_value(v, parent->vals_width, parent->signed_flag, vp); + } + break; + + case vpiRealVal: + { + double d; + parent->vals->get_word(index, d); + vpip_real_get_value(d, vp); + } + break; + + case vpiStringVal: + { + string s; + parent->vals->get_word(index, s); + vpip_string_get_value(s, vp); + } + break; + + // TODO *StrVal variants + + default: + fprintf(stderr, "vpi sorry: format is not implemented"); + assert(false); + } + } } static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int) @@ -800,42 +880,6 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref) return generic_get_str(code, parent->scope, parent->name, sidx); } -// This function return true if the underlying array words are real. -static bool vpi_array_is_real(vvp_array_t arr) -{ - // Check to see if this is a variable/register array. - if (arr->vals4 != 0) // A bit based variable/register array. - return false; - - if (dynamic_cast (arr->vals)) - return true; - - if (arr->vals != 0) - return false; - - // This must be a net array so look at element 0 to find the type. - assert(arr->nets != 0); - assert(arr->array_count > 0); - struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]); - if (rsig) { - return true; - } - - return false; -} - -static bool vpi_array_is_string(vvp_array_t arr) -{ - // Check to see if this is a variable/register array. - if (arr->vals4 != 0) // A bit based variable/register array. - return false; - - if (dynamic_cast (arr->vals)) - return true; - - return false; -} - static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) { struct __vpiArrayVthrA*obj = dynamic_cast<__vpiArrayVthrA*>(ref); From c1164dcc333c366f3ebf92784be8b84c8f8431ac Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 14 Nov 2014 18:25:49 +0100 Subject: [PATCH 14/29] vvp: Initial work on support for dynamic arrays in VPI. Added array_common.[ch] to store shared code. --- vvp/Makefile.in | 2 +- vvp/array.cc | 612 +++++++++++++------------------------------- vvp/array_common.cc | 157 ++++++++++++ vvp/array_common.h | 100 ++++++++ vvp/vpi_darray.cc | 57 ++++- vvp/vpi_priv.h | 33 ++- vvp/vpi_signal.cc | 2 +- 7 files changed, 515 insertions(+), 448 deletions(-) create mode 100644 vvp/array_common.cc create mode 100644 vvp/array_common.h diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 16a0ecbc2..35750f69d 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -71,7 +71,7 @@ V = vpi_modules.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \ vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \ vpip_to_dec.o vpip_format.o vvp_vpi.o -O = main.o parse.o parse_misc.o lexor.o arith.o array.o bufif.o compile.o \ +O = main.o parse.o parse_misc.o lexor.o arith.o array_common.o array.o bufif.o compile.o \ concat.o dff.o class_type.o enum_type.o extend.o file_line.o npmos.o part.o \ permaheap.o reduce.o resolv.o \ sfunc.o stop.o \ diff --git a/vvp/array.cc b/vvp/array.cc index c664fd647..6908c7a18 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +# include "array_common.h" # include "array.h" # include "symbols.h" # include "schedule.h" @@ -81,18 +82,20 @@ vvp_array_t array_find(const char*label) * array of double variables. This is very much like the way the * vector4 array works. */ -struct __vpiArray : public __vpiHandle { - __vpiArray(); - int get_type_code(void) const; +struct __vpiArray : public __vpiArrayBase, public __vpiHandle { + int get_type_code(void) const { return vpiMemory; } + unsigned get_size() const { return array_count; } + int get_word_size() const; + int get_left_range() const { assert(nets == 0); return msb.get_value(); } + int get_right_range() const { assert(nets == 0); return lsb.get_value(); } + struct __vpiScope*get_scope() const { return scope; } + int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); - vpiHandle vpi_iterate(int code); vpiHandle vpi_index(int idx); - struct __vpiScope*scope; const char*name; /* Permanently allocated string */ - unsigned array_count; __vpiDecConst first_addr; __vpiDecConst last_addr; __vpiDecConst msb; @@ -103,33 +106,20 @@ struct __vpiArray : public __vpiHandle { // If this is a var array, then these are used instead of nets. vvp_vector4array_t*vals4; vvp_darray *vals; - struct __vpiArrayWord*vals_words; vvp_fun_arrayport*ports_; struct __vpiCallback *vpi_callbacks; bool signed_flag; bool swap_addr; -}; -struct __vpiArrayIterator : public __vpiHandle { - __vpiArrayIterator(); - int get_type_code(void) const; - vpiHandle vpi_index(int idx); - free_object_fun_t free_object_fun(void); +private: + unsigned array_count; + struct __vpiScope*scope; - struct __vpiArray*array; - unsigned next; -}; - -struct __vpiArrayIndex : public __vpiHandle { - __vpiArrayIndex(); - int get_type_code(void) const; - vpiHandle vpi_iterate(int code); - vpiHandle vpi_index(int idx); - free_object_fun_t free_object_fun(void); - - __vpiDecConst *index; - unsigned done; +friend vpiHandle vpip_make_array(char*label, const char*name, + int first_addr, int last_addr, + bool signed_flag); +friend void compile_array_alias(char*label, char*name, char*src); }; struct __vpiArrayVthrA : public __vpiHandle { @@ -225,7 +215,7 @@ unsigned get_array_word_size(vvp_array_t array) { unsigned width; - assert(array->array_count > 0); + assert(array->get_size() > 0); /* For a net array we need to get the width from the first element. */ if (array->nets) { assert(array->vals4 == 0 && array->vals == 0); @@ -250,65 +240,6 @@ bool is_net_array(vpiHandle obj) return false; } -/* - * The vpiArrayWord is magic. It is used as the handle to return when - * vpi code tries to index or scan an array of variable words. The - * array word handle contains no actual data. It is just a hook for - * the vpi methods and to point to the parent. - * - * How the point to the parent works is tricky. The vpiArrayWord - * objects for an array are themselves allocated as an array. All the - * ArrayWord objects in the array have a word0 that points to the base - * of the array. Thus, the position into the array (and the index into - * the memory) is calculated by subtracting word0 from the ArrayWord - * pointer. - * - * To then get to the parent, use word0[-1].parent. - * - * The vpiArrayWord is also used as a handle for the index (vpiIndex) - * for the word. To make that work, return the pointer to the as_index - * member instead of the as_word member. The result is a different set - * of vpi functions is bound to the same structure. All the details - * for the word also apply when treating this as an index. - */ - - -struct __vpiArrayWord { - struct as_word_t : public __vpiHandle { - as_word_t(); - int get_type_code(void) const; - int vpi_get(int code); - char*vpi_get_str(int code); - void vpi_get_value(p_vpi_value val); - vpiHandle vpi_put_value(p_vpi_value val, int flags); - vpiHandle vpi_handle(int code); - } as_word; - - struct as_index_t : public __vpiHandle { - as_index_t(); - int get_type_code(void) const; - void vpi_get_value(p_vpi_value val); - } as_index; - - union { - struct __vpiArray*parent; - struct __vpiArrayWord*word0; - }; -}; - -static void array_make_vals_words(struct __vpiArray*parent); - -static vpiHandle array_index_scan(vpiHandle ref, int); - -static int vpi_array_var_word_get(int code, vpiHandle); -static char*vpi_array_var_word_get_str(int code, vpiHandle); -static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value vp); -static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, - int); -static vpiHandle vpi_array_var_word_get_handle(int code, vpiHandle ref); - -static void vpi_array_var_index_get_value(vpiHandle ref, p_vpi_value vp); - static int vpi_array_vthr_A_get(int code, vpiHandle); static char*vpi_array_vthr_A_get_str(int code, vpiHandle); static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp); @@ -319,11 +250,58 @@ static int vpi_array_vthr_APV_get(int code, vpiHandle); static char*vpi_array_vthr_APV_get_str(int code, vpiHandle); static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp); -inline __vpiArray::__vpiArray() -{ } -int __vpiArray::get_type_code(void) const -{ return vpiMemory; } +// This function return true if the underlying array words are real. +static bool vpi_array_is_real(vvp_array_t arr) +{ + // Check to see if this is a variable/register array. + if (arr->vals4 != 0) // A bit based variable/register array. + return false; + + if (dynamic_cast (arr->vals)) + return true; + + if (arr->vals != 0) + return false; + + // This must be a net array so look at element 0 to find the type. + assert(arr->nets != 0); + assert(arr->get_size() > 0); + struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]); + if (rsig) { + return true; + } + + return false; +} + +static bool vpi_array_is_string(vvp_array_t arr) +{ + // Check to see if this is a variable/register array. + if (arr->vals4 != 0) // A bit based variable/register array. + return false; + + if (dynamic_cast (arr->vals)) + return true; + + return false; +} + +int __vpiArray::get_word_size() const +{ + assert(nets == 0); + + if (vals4) { + assert(vals == 0); + return (int) vals4->width(); + } else { + assert(vals4 == 0); + return 1; + } + + assert(false); + return 0; +} int __vpiArray::vpi_get(int code) { @@ -332,7 +310,7 @@ int __vpiArray::vpi_get(int code) return 0; // Not implemented for now! case vpiSize: - return (int) array_count; + return get_size(); case vpiAutomatic: return (int) scope->is_automatic; @@ -354,14 +332,13 @@ char* __vpiArray::vpi_get_str(int code) vpiHandle __vpiArray::vpi_handle(int code) { switch (code) { + case vpiLeftRange: + if (swap_addr) return &last_addr; + else return &first_addr; - case vpiLeftRange: - if (swap_addr) return &last_addr; - else return &first_addr; - - case vpiRightRange: - if (swap_addr) return &first_addr; - else return &last_addr; + case vpiRightRange: + if (swap_addr) return &first_addr; + else return &last_addr; case vpiScope: return scope; @@ -373,23 +350,6 @@ vpiHandle __vpiArray::vpi_handle(int code) return 0; } -vpiHandle __vpiArray::vpi_iterate(int code) -{ - switch (code) { - - case vpiMemoryWord: { - struct __vpiArrayIterator*res; - res = new __vpiArrayIterator; - res->array = this; - res->next = 0; - return res; - } - - } - - return 0; -} - /* * VPI code passes indices that are not yet converted to canonical * form, so this index function does it here. @@ -397,7 +357,7 @@ vpiHandle __vpiArray::vpi_iterate(int code) vpiHandle __vpiArray::vpi_index(int index) { index -= first_addr.get_value(); - if (index >= (long)array_count) + if (index >= (long) get_size()) return 0; if (index < 0) return 0; @@ -407,215 +367,32 @@ vpiHandle __vpiArray::vpi_index(int index) } if (vals_words == 0) - array_make_vals_words(this); + make_vals_words(); return &(vals_words[index].as_word); } - -inline __vpiArrayIterator::__vpiArrayIterator() -{ } - -int __vpiArrayIterator::get_type_code(void) const -{ return vpiIterator; } - -vpiHandle __vpiArrayIterator::vpi_index(int) -{ - if (next >= array->array_count) { - vpi_free_object(this); - return 0; - } - - unsigned use_index = next; - next += 1; - - if (array->nets) return array->nets[use_index]; - - assert(array->vals4 || array->vals); - - if (array->vals_words == 0) array_make_vals_words(array); - - return &(array->vals_words[use_index].as_word); -} - - -static int array_iterator_free_object(vpiHandle ref) -{ - struct __vpiArrayIterator*obj = dynamic_cast<__vpiArrayIterator*>(ref); - delete obj; - return 1; -} - -__vpiHandle::free_object_fun_t __vpiArrayIterator::free_object_fun(void) -{ return &array_iterator_free_object; } - -inline __vpiArrayIndex::__vpiArrayIndex() -{ } - -int __vpiArrayIndex::get_type_code(void) const -{ return vpiIterator; } - -vpiHandle __vpiArrayIndex::vpi_iterate(int code) -{ return array_index_iterate(code, this); } - -vpiHandle __vpiArrayIndex::vpi_index(int idx) -{ return array_index_scan(this, idx); } - -static int array_index_free_object(vpiHandle ref) -{ - struct __vpiArrayIndex*obj = dynamic_cast<__vpiArrayIndex*>(ref); - delete obj; - return 1; -} - -__vpiHandle::free_object_fun_t __vpiArrayIndex::free_object_fun(void) -{ return &array_index_free_object; } - -inline __vpiArrayWord::as_word_t::as_word_t() -{ } - -int __vpiArrayWord::as_word_t::get_type_code(void) const -{ return vpiMemoryWord; } - int __vpiArrayWord::as_word_t::vpi_get(int code) -{ return vpi_array_var_word_get(code, this); } - -char* __vpiArrayWord::as_word_t::vpi_get_str(int code) -{ return vpi_array_var_word_get_str(code, this); } - -void __vpiArrayWord::as_word_t::vpi_get_value(p_vpi_value val) -{ vpi_array_var_word_get_value(this, val); } - -vpiHandle __vpiArrayWord::as_word_t::vpi_put_value(p_vpi_value val, int flags) -{ return vpi_array_var_word_put_value(this, val, flags); } - -vpiHandle __vpiArrayWord::as_word_t::vpi_handle(int code) -{ return vpi_array_var_word_get_handle(code, this); } - -inline __vpiArrayWord::as_index_t::as_index_t() -{ } - -int __vpiArrayWord::as_index_t::get_type_code(void) const -{ return vpiIndex; } - -void __vpiArrayWord::as_index_t::vpi_get_value(p_vpi_value val) -{ vpi_array_var_index_get_value(this, val); } - -inline __vpiArrayVthrA::__vpiArrayVthrA() -{ } - -int __vpiArrayVthrA::get_type_code(void) const -{ return vpiMemoryWord; } - -int __vpiArrayVthrA::vpi_get(int code) -{ return vpi_array_vthr_A_get(code, this); } - -char* __vpiArrayVthrA::vpi_get_str(int code) -{ return vpi_array_vthr_A_get_str(code, this); } - -void __vpiArrayVthrA::vpi_get_value(p_vpi_value val) -{ vpi_array_vthr_A_get_value(this, val); } - -vpiHandle __vpiArrayVthrA::vpi_put_value(p_vpi_value val, int flags) -{ return vpi_array_vthr_A_put_value(this, val, flags); } - -vpiHandle __vpiArrayVthrA::vpi_handle(int code) -{ return vpi_array_vthr_A_get_handle(code, this); } - - -inline __vpiArrayVthrAPV::__vpiArrayVthrAPV() -{ } - -int __vpiArrayVthrAPV::get_type_code(void) const -{ return vpiMemoryWord; } - -int __vpiArrayVthrAPV::vpi_get(int code) -{ return vpi_array_vthr_APV_get(code, this); } - -char* __vpiArrayVthrAPV::vpi_get_str(int code) -{ return vpi_array_vthr_APV_get_str(code, this); } - -void __vpiArrayVthrAPV::vpi_get_value(p_vpi_value val) -{ vpi_array_vthr_APV_get_value(this, val); } - -static struct __vpiArrayWord* array_var_word_from_handle(vpiHandle ref) { - if (ref == 0) - return 0; - __vpiArrayWord::as_word_t*ptr = dynamic_cast<__vpiArrayWord::as_word_t*> (ref); - if (ptr == 0) - return 0; - - return (struct __vpiArrayWord*) ref; -} - -static struct __vpiArrayWord* array_var_index_from_handle(vpiHandle ref) -{ - if (ref == 0) - return 0; - __vpiArrayWord::as_index_t*ptr = dynamic_cast<__vpiArrayWord::as_index_t*> (ref); - if (ptr == 0) - return 0; - - assert(sizeof(__vpiHandle) == sizeof(__vpiArrayWord::as_index_t)); - assert(sizeof(__vpiHandle) == sizeof(__vpiArrayWord::as_word_t)); - return (struct __vpiArrayWord*) (ref-1); -} - -static void array_make_vals_words(struct __vpiArray*parent) -{ - assert(parent->vals_words == 0); - parent->vals_words = new struct __vpiArrayWord[parent->array_count + 1]; - - // Make word[-1] point to the parent. - parent->vals_words->parent = parent; - // Now point to word-0 - parent->vals_words += 1; - - struct __vpiArrayWord*words = parent->vals_words; - for (unsigned idx = 0 ; idx < parent->array_count ; idx += 1) { - words[idx].word0 = words; - } -} - -static unsigned decode_array_word_pointer(struct __vpiArrayWord*word, - struct __vpiArray*&parent) -{ - struct __vpiArrayWord*word0 = word->word0; - parent = (word0 - 1) -> parent; - return word - word0; -} - -static int vpi_array_var_word_get(int code, vpiHandle ref) -{ - struct __vpiArrayWord*obj = array_var_word_from_handle(ref); - struct __vpiArray*parent; - + struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - decode_array_word_pointer(obj, parent); - assert(parent->nets == 0); + struct __vpiArrayBase*parent = get_word_parent(obj); switch (code) { case vpiLineNo: return 0; // Not implemented for now! case vpiSize: - if (parent->vals4) { - assert(parent->vals == 0); - return (int) parent->vals4->width(); - } else { - assert(parent->vals4 == 0); - return 1; - } + return parent->get_word_size(); case vpiLeftRange: - return parent->msb.get_value(); + return parent->get_left_range(); case vpiRightRange: - return parent->lsb.get_value(); + return parent->get_right_range(); case vpiAutomatic: - return (int) parent->scope->is_automatic; + return (int) parent->get_scope()->is_automatic; #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX) case _vpiFromThr: @@ -627,13 +404,13 @@ static int vpi_array_var_word_get(int code, vpiHandle ref) } } -static char*vpi_array_var_word_get_str(int code, vpiHandle ref) +// TODO make generic version of the following methods and move them to array_common +char* __vpiArrayWord::as_word_t::vpi_get_str(int code) { - struct __vpiArrayWord*obj = array_var_word_from_handle(ref); - struct __vpiArray*parent; - + struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - unsigned index = decode_array_word_pointer(obj, parent); + struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); + unsigned index = get_word_index(obj); if (code == vpiFile) { // Not implemented for now! return simple_set_rbuf_str(file_names[0]); @@ -641,52 +418,15 @@ static char*vpi_array_var_word_get_str(int code, vpiHandle ref) char sidx [64]; snprintf(sidx, 63, "%d", (int)index + parent->first_addr.get_value()); - return generic_get_str(code, parent->scope, parent->name, sidx); + return generic_get_str(code, parent->get_scope(), parent->name, sidx); } -// This function return true if the underlying array words are real. -static bool vpi_array_is_real(vvp_array_t arr) +void __vpiArrayWord::as_word_t::vpi_get_value(p_vpi_value vp) { - // Check to see if this is a variable/register array. - if (arr->vals4 != 0) // A bit based variable/register array. - return false; - - if (dynamic_cast (arr->vals)) - return true; - - if (arr->vals != 0) - return false; - - // This must be a net array so look at element 0 to find the type. - assert(arr->nets != 0); - assert(arr->array_count > 0); - struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]); - if (rsig) { - return true; - } - - return false; -} - -static bool vpi_array_is_string(vvp_array_t arr) -{ - // Check to see if this is a variable/register array. - if (arr->vals4 != 0) // A bit based variable/register array. - return false; - - if (dynamic_cast (arr->vals)) - return true; - - return false; -} - -static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value vp) -{ - struct __vpiArrayWord*obj = array_var_word_from_handle(ref); - struct __vpiArray*parent; - + struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - unsigned index = decode_array_word_pointer(obj, parent); + struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); + unsigned index = get_word_index(obj); // Determine the appropriate format (The Verilog PLI Handbook 5.2.10) if(vp->format == vpiObjTypeVal) { @@ -737,26 +477,23 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value vp) } } -static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int) +vpiHandle __vpiArrayWord::as_word_t::vpi_put_value(p_vpi_value vp, int) { - struct __vpiArrayWord*obj = array_var_word_from_handle(ref); - struct __vpiArray*parent; - + struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - unsigned index = decode_array_word_pointer(obj, parent); + struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); + unsigned index = get_word_index(obj); vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); array_set_word(parent, index, 0, val); - return ref; + return this; } -static vpiHandle vpi_array_var_word_get_handle(int code, vpiHandle ref) +vpiHandle __vpiArrayWord::as_word_t::vpi_handle(int code) { - struct __vpiArrayWord*obj = array_var_word_from_handle(ref); - struct __vpiArray*parent; - + struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - decode_array_word_pointer(obj, parent); + struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); switch (code) { @@ -773,54 +510,62 @@ static vpiHandle vpi_array_var_word_get_handle(int code, vpiHandle ref) return parent; case vpiScope: - return parent->scope; + return parent->get_scope(); case vpiModule: - return vpip_module(parent->scope); + return vpip_module(parent->get_scope()); } return 0; } -static void vpi_array_var_index_get_value(vpiHandle ref, p_vpi_value vp) +void __vpiArrayWord::as_index_t::vpi_get_value(p_vpi_value vp) { - struct __vpiArrayWord*obj = array_var_index_from_handle(ref); - struct __vpiArray*parent; - + struct __vpiArrayWord*obj = array_var_index_from_handle(this); assert(obj); - unsigned index = decode_array_word_pointer(obj, parent); + unsigned index = get_word_index(obj); assert(vp->format == vpiIntVal); vp->value.integer = index; } -vpiHandle array_index_iterate(int code, vpiHandle ref) -{ - __vpiDecConst *obj = dynamic_cast<__vpiDecConst*>(ref); - assert(obj); - if (code == vpiIndex) { - struct __vpiArrayIndex*res; - res = new __vpiArrayIndex; - res->index = obj; - res->done = 0; - return res; - } - return 0; -} +inline __vpiArrayVthrA::__vpiArrayVthrA() +{ } -static vpiHandle array_index_scan(vpiHandle ref, int) -{ - struct __vpiArrayIndex*obj = dynamic_cast<__vpiArrayIndex*>(ref); +int __vpiArrayVthrA::get_type_code(void) const +{ return vpiMemoryWord; } - if (obj->done == 0) { - obj->done = 1; - return obj->index; - } +int __vpiArrayVthrA::vpi_get(int code) +{ return vpi_array_vthr_A_get(code, this); } - vpi_free_object(ref); - return 0; -} +char* __vpiArrayVthrA::vpi_get_str(int code) +{ return vpi_array_vthr_A_get_str(code, this); } + +void __vpiArrayVthrA::vpi_get_value(p_vpi_value val) +{ vpi_array_vthr_A_get_value(this, val); } + +vpiHandle __vpiArrayVthrA::vpi_put_value(p_vpi_value val, int flags) +{ return vpi_array_vthr_A_put_value(this, val, flags); } + +vpiHandle __vpiArrayVthrA::vpi_handle(int code) +{ return vpi_array_vthr_A_get_handle(code, this); } + + +inline __vpiArrayVthrAPV::__vpiArrayVthrAPV() +{ } + +int __vpiArrayVthrAPV::get_type_code(void) const +{ return vpiMemoryWord; } + +int __vpiArrayVthrAPV::vpi_get(int code) +{ return vpi_array_vthr_APV_get(code, this); } + +char* __vpiArrayVthrAPV::vpi_get_str(int code) +{ return vpi_array_vthr_APV_get_str(code, this); } + +void __vpiArrayVthrAPV::vpi_get_value(p_vpi_value val) +{ vpi_array_vthr_APV_get_value(this, val); } static int vpi_array_vthr_A_get(int code, vpiHandle ref) { @@ -845,7 +590,7 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref) return (int)obj->get_address() + parent->first_addr.get_value(); case vpiAutomatic: - return (int) parent->scope->is_automatic; + return (int) parent->get_scope()->is_automatic; #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX) case _vpiFromThr: @@ -877,7 +622,7 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref) char sidx [64]; snprintf(sidx, 63, "%d", (int)obj->get_address() + parent->first_addr.get_value()); - return generic_get_str(code, parent->scope, parent->name, sidx); + return generic_get_str(code, parent->get_scope(), parent->name, sidx); } static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) @@ -911,7 +656,7 @@ static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) unsigned index = obj->get_address(); assert(parent); - assert(index < parent->array_count); + assert(index < parent->get_size()); if (vpi_array_is_real(parent)) { double val = real_from_vpi_value(vp); @@ -946,10 +691,10 @@ static vpiHandle vpi_array_vthr_A_get_handle(int code, vpiHandle ref) return parent; case vpiScope: - return parent->scope; + return parent->get_scope(); case vpiModule: - return vpip_module(parent->scope); + return vpip_module(parent->get_scope()); } return 0; @@ -977,7 +722,7 @@ static int vpi_array_vthr_APV_get(int code, vpiHandle ref) return (int)obj->word_sel; case vpiAutomatic: - return (int) parent->scope->is_automatic; + return (int) parent->get_scope()->is_automatic; #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX) case _vpiFromThr: @@ -1004,7 +749,7 @@ static char*vpi_array_vthr_APV_get_str(int code, vpiHandle ref) char sidx [64]; snprintf(sidx, 63, "%u", obj->word_sel + parent->first_addr.get_value()); - return generic_get_str(code, parent->scope, parent->name, sidx); + return generic_get_str(code, parent->get_scope(), parent->name, sidx); } static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp) @@ -1031,7 +776,7 @@ void array_set_word(vvp_array_t arr, unsigned part_off, vvp_vector4_t val) { - if (address >= arr->array_count) + if (address >= arr->get_size()) return; if (arr->vals4) { @@ -1134,10 +879,10 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) assert(arr->vals == 0); assert(arr->nets != 0); - if (address >= arr->array_count) { + if (address >= arr->get_size()) { // Reading outside the array. Return X's but get the // width by looking at a word that we know is present. - assert(arr->array_count > 0); + assert(arr->get_size() > 0); vpiHandle word = arr->nets[0]; assert(word); struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(word); @@ -1228,7 +973,7 @@ string array_get_word_str(vvp_array_t arr, unsigned address) return ""; } -static vpiHandle vpip_make_array(char*label, const char*name, +vpiHandle vpip_make_array(char*label, const char*name, int first_addr, int last_addr, bool signed_flag) { @@ -1291,14 +1036,14 @@ void array_alias_word(vvp_array_t array, unsigned long addr, vpiHandle word, { assert(array->msb.get_value() == msb); assert(array->lsb.get_value() == lsb); - assert(addr < array->array_count); + assert(addr < array->get_size()); assert(array->nets); array->nets[addr] = word; } void array_attach_word(vvp_array_t array, unsigned addr, vpiHandle word) { - assert(addr < array->array_count); + assert(addr < array->get_size()); assert(array->nets); array->nets[addr] = word; @@ -1343,16 +1088,16 @@ void compile_var_array(char*label, char*name, int last, int first, arr->vals_width = labs(msb-lsb) + 1; if (vpip_peek_current_scope()->is_automatic) { arr->vals4 = new vvp_vector4array_aa(arr->vals_width, - arr->array_count); + arr->get_size()); } else { arr->vals4 = new vvp_vector4array_sa(arr->vals_width, - arr->array_count); + arr->get_size()); } arr->msb.set_value(msb); arr->lsb.set_value(lsb); count_var_arrays += 1; - count_var_array_words += arr->array_count; + count_var_array_words += arr->get_size(); free(label); delete[] name; @@ -1372,27 +1117,27 @@ void compile_var2_array(char*label, char*name, int last, int first, assert(! arr->nets); if (lsb == 0 && msb == 7 && signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else if (lsb == 0 && msb == 7 && !signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else if (lsb == 0 && msb == 15 && signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else if (lsb == 0 && msb == 15 && !signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else if (lsb == 0 && msb == 31 && signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else if (lsb == 0 && msb == 31 && !signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else if (lsb == 0 && msb == 63 && signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else if (lsb == 0 && msb == 63 && !signed_flag) { - arr->vals = new vvp_darray_atom(arr->array_count); + arr->vals = new vvp_darray_atom(arr->get_size()); } else { // For now, only support the atom sizes. assert(0); } count_var_arrays += 1; - count_var_array_words += arr->array_count; + count_var_array_words += arr->get_size(); free(label); delete[] name; @@ -1405,11 +1150,11 @@ void compile_real_array(char*label, char*name, int last, int first) struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); /* Make the words. */ - arr->vals = new vvp_darray_real(arr->array_count); + arr->vals = new vvp_darray_real(arr->get_size()); arr->vals_width = 1; count_real_arrays += 1; - count_real_array_words += arr->array_count; + count_real_array_words += arr->get_size(); free(label); delete[] name; @@ -1422,11 +1167,11 @@ void compile_string_array(char*label, char*name, int last, int first) struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); /* Make the words. */ - arr->vals = new vvp_darray_string(arr->array_count); + arr->vals = new vvp_darray_string(arr->get_size()); arr->vals_width = 1; count_real_arrays += 1; - count_real_array_words += arr->array_count; + count_real_array_words += arr->get_size(); free(label); delete[] name; @@ -1439,11 +1184,11 @@ void compile_object_array(char*label, char*name, int last, int first) struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); /* Make the words. */ - arr->vals = new vvp_darray_object(arr->array_count); + arr->vals = new vvp_darray_object(arr->get_size()); arr->vals_width = 1; count_real_arrays += 1; - count_real_array_words += arr->array_count; + count_real_array_words += arr->get_size(); free(label); delete[] name; @@ -1457,10 +1202,10 @@ void compile_net_array(char*label, char*name, int last, int first) vpiHandle obj = vpip_make_array(label, name, first, last, false); struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); - arr->nets = (vpiHandle*)calloc(arr->array_count, sizeof(vpiHandle)); + arr->nets = (vpiHandle*)calloc(arr->get_size(), sizeof(vpiHandle)); count_net_arrays += 1; - count_net_array_words += arr->array_count; + count_net_array_words += arr->get_size(); free(label); delete[] name; @@ -1540,7 +1285,7 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit case 0: // Address input addr_valid_flag = vector4_to_value(bit, addr_); if (! addr_valid_flag) - addr_ = arr_->array_count; + addr_ = arr_->get_size(); if (vpi_array_is_real(arr_)) port.ptr()->send_real(array_get_word_r(arr_, addr_), 0); else @@ -1646,7 +1391,7 @@ void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit case 0: // Address input addr_valid_flag = vector4_to_value(bit, *addr); - if (! addr_valid_flag) *addr = arr_->array_count; + if (! addr_valid_flag) *addr = arr_->get_size(); if (vpi_array_is_real(arr_)) { port.ptr()->send_real(array_get_word_r(arr_, *addr), context); @@ -1687,7 +1432,7 @@ void vvp_fun_arrayport_aa::check_word_change_(unsigned long addr, void vvp_fun_arrayport_aa::check_word_change(unsigned long addr) { - if (arr_->scope->is_automatic) { + if (arr_->get_scope()->is_automatic) { assert(vthread_get_wt_context()); check_word_change_(addr, vthread_get_wt_context()); } else { @@ -1704,7 +1449,7 @@ static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun) assert(fun->next_ == 0); fun->next_ = array->ports_; array->ports_ = fun; - if (!array->scope->is_automatic) { + if (!array->get_scope()->is_automatic) { /* propagate initial values for variable arrays */ if (array->vals4) { vvp_vector4_t tmp(array->vals_width, BIT4_X); @@ -1912,7 +1657,8 @@ value_callback*vpip_array_word_change(p_cb_data data) struct __vpiArray*parent = 0; array_word_value_callback*cbh = 0; if (struct __vpiArrayWord*word = array_var_word_from_handle(data->obj)) { - unsigned addr = decode_array_word_pointer(word, parent); + parent = (__vpiArray*) get_word_parent(word); + unsigned addr = get_word_index(word); cbh = new array_word_value_callback(data); cbh->word_addr = addr; @@ -2145,7 +1891,7 @@ void memory_delete(vpiHandle item) delete arr->vals; if (arr->nets) { - for (unsigned idx = 0; idx < arr->array_count; idx += 1) { + for (unsigned idx = 0; idx < arr->get_size(); idx += 1) { if (struct __vpiSignal*sig = dynamic_cast<__vpiSignal*>(arr->nets[idx])) { // Delete the individual words? diff --git a/vvp/array_common.cc b/vvp/array_common.cc new file mode 100644 index 000000000..cce82ecc5 --- /dev/null +++ b/vvp/array_common.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2014 CERN + * @author Maciej Suminski + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "array_common.h" + +vpiHandle __vpiArrayBase::vpi_iterate(int code) +{ + switch (code) { + case vpiMemoryWord: { + struct __vpiArrayIterator*res; + res = new __vpiArrayIterator; + res->array = this; + res->next = 0; + return res; + } + } + + return 0; +} + +// TODO template +void __vpiArrayBase::make_vals_words() +{ + assert(vals_words == 0); + vals_words = new struct __vpiArrayWord[get_size() + 1]; + + // Make word[-1] point to the parent. + vals_words->parent = this; + // Now point to word-0 + vals_words += 1; + + struct __vpiArrayWord*words = vals_words; + for (unsigned idx = 0 ; idx < get_size() ; idx += 1) { + words[idx].word0 = words; + } +} + +vpiHandle __vpiArrayIterator::vpi_index(int) +{ + if (next >= array->get_size()) { + vpi_free_object(this); + return 0; + } + + unsigned use_index = next; + next += 1; + +// TODO ArrayBase::iterate(int)? + //if (array->nets) return array->nets[use_index]; + + //assert(array->vals4 || array->vals); + + if (array->vals_words == 0) array->make_vals_words(); + + return &(array->vals_words[use_index].as_word); +} + +static int array_iterator_free_object(vpiHandle ref) +{ + struct __vpiArrayIterator*obj = dynamic_cast<__vpiArrayIterator*>(ref); + delete obj; + return 1; +} + +__vpiHandle::free_object_fun_t __vpiArrayIterator::free_object_fun(void) +{ return &array_iterator_free_object; } + +vpiHandle __vpiArrayIndex::vpi_iterate(int code) +{ + // TODO originally, __vpiArrayIndex is casted to __vpiDecConst and assigned + // to res->index - seems like a bug to me + + if (code == vpiIndex) { + struct __vpiArrayIndex*res; + res = new __vpiArrayIndex; + res->index = index; // TODO ? see above comment + res->done = 0; + return res; + } + return 0; +} + +vpiHandle __vpiArrayIndex::vpi_index(int) +{ + if (done == 0) { + done = 1; + return index; + } + + vpi_free_object(this); + return 0; +} + +static int array_index_free_object(vpiHandle ref) +{ + struct __vpiArrayIndex*obj = dynamic_cast<__vpiArrayIndex*>(ref); + delete obj; + return 1; +} + +__vpiHandle::free_object_fun_t __vpiArrayIndex::free_object_fun(void) +{ return &array_index_free_object; } + +// TODO orson it should be a method +unsigned get_word_index(struct __vpiArrayWord*word) +{ + return word - word->word0; +} + +// TODO orson it should be a method +struct __vpiArrayBase*get_word_parent(struct __vpiArrayWord*word) +{ + struct __vpiArrayWord*word0 = word->word0; + return (word0 - 1)->parent; +} + +struct __vpiArrayWord*array_var_word_from_handle(vpiHandle ref) +{ + if (ref == 0) + return 0; + __vpiArrayWord::as_word_t*ptr = dynamic_cast<__vpiArrayWord::as_word_t*> (ref); + if (ptr == 0) + return 0; + + return (struct __vpiArrayWord*) ref; +} + +struct __vpiArrayWord* array_var_index_from_handle(vpiHandle ref) +{ + if (ref == 0) + return 0; + __vpiArrayWord::as_index_t*ptr = dynamic_cast<__vpiArrayWord::as_index_t*> (ref); + if (ptr == 0) + return 0; + + assert(sizeof(__vpiHandle) == sizeof(__vpiArrayWord::as_index_t)); + assert(sizeof(__vpiHandle) == sizeof(__vpiArrayWord::as_word_t)); + return (struct __vpiArrayWord*) (ref-1); +} diff --git a/vvp/array_common.h b/vvp/array_common.h new file mode 100644 index 000000000..a38977849 --- /dev/null +++ b/vvp/array_common.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2014 CERN + * @author Maciej Suminski + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef ARRAY_COMMON_H +#define ARRAY_COMMON_H + +#include "vpi_priv.h" + +struct __vpiArrayIterator : public __vpiHandle { + int get_type_code(void) const + { return vpiIterator; } + + virtual vpiHandle vpi_index(int idx); + free_object_fun_t free_object_fun(void); + + struct __vpiArrayBase*array; + unsigned next; +}; + +struct __vpiArrayIndex : public __vpiHandle { + int get_type_code(void) const + { return vpiIterator; } + + vpiHandle vpi_iterate(int code); + vpiHandle vpi_index(int idx); + free_object_fun_t free_object_fun(void); + + __vpiDecConst *index; + unsigned done; +}; + +/* + * The vpiArrayWord is magic. It is used as the handle to return when + * vpi code tries to index or scan an array of variable words. The + * array word handle contains no actual data. It is just a hook for + * the vpi methods and to point to the parent. + * + * How the point to the parent works is tricky. The vpiArrayWord + * objects for an array are themselves allocated as an array. All the + * ArrayWord objects in the array have a word0 that points to the base + * of the array. Thus, the position into the array (and the index into + * the memory) is calculated by subtracting word0 from the ArrayWord + * pointer. + * + * To then get to the parent, use word0[-1].parent. + * + * The vpiArrayWord is also used as a handle for the index (vpiIndex) + * for the word. To make that work, return the pointer to the as_index + * member instead of the as_word member. The result is a different set + * of vpi functions is bound to the same structure. All the details + * for the word also apply when treating this as an index. + */ +struct __vpiArrayWord { + struct as_word_t : public __vpiHandle { + int get_type_code(void) const { return vpiMemoryWord; } + int vpi_get(int code); + char*vpi_get_str(int code); + void vpi_get_value(p_vpi_value vp); + vpiHandle vpi_put_value(p_vpi_value vp, int flags); + vpiHandle vpi_handle(int code); + } as_word; + + struct as_index_t : public __vpiHandle { + int get_type_code(void) const { return vpiIndex; } + void vpi_get_value(p_vpi_value val); + } as_index; + + union { + struct __vpiArrayBase*parent; + struct __vpiArrayWord*word0; + }; +}; + +unsigned get_word_index(struct __vpiArrayWord*word); +struct __vpiArrayBase*get_word_parent(struct __vpiArrayWord*word); + +struct __vpiArrayWord*array_var_word_from_handle(vpiHandle ref); +struct __vpiArrayWord*array_var_index_from_handle(vpiHandle ref); + +vpiHandle array_index_iterate(int code, vpiHandle ref); + +#endif /* ARRAY_COMMON_H */ diff --git a/vvp/vpi_darray.cc b/vvp/vpi_darray.cc index 95046ecee..3f3694e4c 100644 --- a/vvp/vpi_darray.cc +++ b/vvp/vpi_darray.cc @@ -22,6 +22,7 @@ # include "vpi_priv.h" # include "vvp_net_sig.h" # include "vvp_darray.h" +# include "array_common.h" # include "schedule.h" #ifdef CHECK_WITH_VALGRIND # include "vvp_cleanup.h" @@ -39,31 +40,67 @@ __vpiDarrayVar::__vpiDarrayVar(__vpiScope*sc, const char*na, vvp_net_t*ne) { } -int __vpiDarrayVar::get_type_code(void) const -{ return vpiArrayVar; } - - -int __vpiDarrayVar::vpi_get(int code) +unsigned __vpiDarrayVar::get_size() const { vvp_fun_signal_object*fun = dynamic_cast (get_net()->fun); - assert(fun); + if(!fun) + return 0; + vvp_object_t val = fun->get_object(); vvp_darray*aval = val.peek(); + if(!aval) + return 0; + + return aval->get_size(); +} + +int __vpiDarrayVar::vpi_get(int code) +{ switch (code) { case vpiArrayType: return vpiDynamicArray; case vpiSize: - if (aval == 0) - return 0; - else - return aval->get_size(); + return get_size(); default: return 0; } } +char* __vpiDarrayVar::vpi_get_str(int code) +{ + // TODO orson + return NULL; +} + +vpiHandle __vpiDarrayVar::vpi_handle(int code) +{ + // TODO orson + //switch (code) { + //case vpiScope: + //return scope_; + + //case vpiModule: + //return vpip_module(scope_); + //} + + return 0; +} + +vpiHandle __vpiDarrayVar::vpi_index(int index) +{ + if (index >= (long) get_size()) + return 0; + if (index < 0) + return 0; + + if (vals_words == 0) + make_vals_words(); + + return &(vals_words[index].as_word); +} + void __vpiDarrayVar::vpi_get_value(p_vpi_value val) { val->format = vpiSuppressVal; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 07ce78a71..3fb08a1a1 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -35,6 +35,7 @@ class class_type; +typedef struct __vpiArray* vvp_array_t; /* * This header file contains the internal definitions that the vvp @@ -514,8 +515,10 @@ class __vpiBaseVar : public __vpiHandle { inline vvp_net_t* get_net() const { return net_; } - private: + protected: struct __vpiScope* scope_; + + private: const char*name_; vvp_net_t*net_; }; @@ -532,13 +535,37 @@ class __vpiStringVar : public __vpiBaseVar { extern vpiHandle vpip_make_string_var(const char*name, vvp_net_t*net); -class __vpiDarrayVar : public __vpiBaseVar { +struct __vpiArrayBase { + __vpiArrayBase() : vals_words(NULL) {} + virtual unsigned get_size(void) const = 0; + virtual int get_word_size() const = 0; + virtual int get_left_range() const = 0; + virtual int get_right_range() const = 0; + virtual struct __vpiScope*get_scope() const = 0; + + virtual vpiHandle vpi_iterate(int code); + virtual void make_vals_words(); + + struct __vpiArrayWord*vals_words; +}; + +class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { public: __vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net); - int get_type_code(void) const; + int get_type_code() const { return vpiArrayVar; } + unsigned get_size() const; + int get_word_size() const { return 0; } // TODO + int get_left_range() const { return 0; } + int get_right_range() const { return 0; } + struct __vpiScope*get_scope() const { return scope_; } + int vpi_get(int code); + char* vpi_get_str(int code); + vpiHandle vpi_handle(int code); + vpiHandle vpi_index(int index); + void vpi_get_value(p_vpi_value val); }; diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index a71fdd262..5cb6de055 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -654,7 +654,7 @@ static vpiHandle signal_iterate(int code, vpiHandle ref) assert(rfp); if (code == vpiIndex) { - return rfp->is_netarray? array_index_iterate(code, rfp->id.index) : 0; + return rfp->is_netarray ? rfp->id.index->vpi_iterate(code) : 0; } return 0; From 48d3701c024d05498db56aed17cdb0a9bb0ee1e8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 19 Nov 2014 16:14:57 +0100 Subject: [PATCH 15/29] vvp: get_word_index() & get_word_parent() moved to __vpiArrayWord. --- vvp/array.cc | 22 +++++++++++----------- vvp/array_common.cc | 13 ------------- vvp/array_common.h | 6 +++--- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 6908c7a18..0d6a05bf1 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -376,7 +376,7 @@ int __vpiArrayWord::as_word_t::vpi_get(int code) { struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - struct __vpiArrayBase*parent = get_word_parent(obj); + struct __vpiArrayBase*parent = obj->get_parent(); switch (code) { case vpiLineNo: @@ -409,8 +409,8 @@ char* __vpiArrayWord::as_word_t::vpi_get_str(int code) { struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); - unsigned index = get_word_index(obj); + struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); + unsigned index = obj->get_index(); if (code == vpiFile) { // Not implemented for now! return simple_set_rbuf_str(file_names[0]); @@ -425,8 +425,8 @@ void __vpiArrayWord::as_word_t::vpi_get_value(p_vpi_value vp) { struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); - unsigned index = get_word_index(obj); + struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); + unsigned index = obj->get_index(); // Determine the appropriate format (The Verilog PLI Handbook 5.2.10) if(vp->format == vpiObjTypeVal) { @@ -481,8 +481,8 @@ vpiHandle __vpiArrayWord::as_word_t::vpi_put_value(p_vpi_value vp, int) { struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); - unsigned index = get_word_index(obj); + struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); + unsigned index = obj->get_index(); vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); array_set_word(parent, index, 0, val); @@ -493,7 +493,7 @@ vpiHandle __vpiArrayWord::as_word_t::vpi_handle(int code) { struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); - struct __vpiArray*parent = (__vpiArray*) get_word_parent(obj); + struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); switch (code) { @@ -523,7 +523,7 @@ void __vpiArrayWord::as_index_t::vpi_get_value(p_vpi_value vp) { struct __vpiArrayWord*obj = array_var_index_from_handle(this); assert(obj); - unsigned index = get_word_index(obj); + unsigned index = obj->get_index(); assert(vp->format == vpiIntVal); vp->value.integer = index; @@ -1657,8 +1657,8 @@ value_callback*vpip_array_word_change(p_cb_data data) struct __vpiArray*parent = 0; array_word_value_callback*cbh = 0; if (struct __vpiArrayWord*word = array_var_word_from_handle(data->obj)) { - parent = (__vpiArray*) get_word_parent(word); - unsigned addr = get_word_index(word); + parent = (__vpiArray*) word->get_parent(); + unsigned addr = word->get_index(); cbh = new array_word_value_callback(data); cbh->word_addr = addr; diff --git a/vvp/array_common.cc b/vvp/array_common.cc index cce82ecc5..df249a2c6 100644 --- a/vvp/array_common.cc +++ b/vvp/array_common.cc @@ -119,19 +119,6 @@ static int array_index_free_object(vpiHandle ref) __vpiHandle::free_object_fun_t __vpiArrayIndex::free_object_fun(void) { return &array_index_free_object; } -// TODO orson it should be a method -unsigned get_word_index(struct __vpiArrayWord*word) -{ - return word - word->word0; -} - -// TODO orson it should be a method -struct __vpiArrayBase*get_word_parent(struct __vpiArrayWord*word) -{ - struct __vpiArrayWord*word0 = word->word0; - return (word0 - 1)->parent; -} - struct __vpiArrayWord*array_var_word_from_handle(vpiHandle ref) { if (ref == 0) diff --git a/vvp/array_common.h b/vvp/array_common.h index a38977849..2cfcb0bbe 100644 --- a/vvp/array_common.h +++ b/vvp/array_common.h @@ -87,10 +87,10 @@ struct __vpiArrayWord { struct __vpiArrayBase*parent; struct __vpiArrayWord*word0; }; -}; -unsigned get_word_index(struct __vpiArrayWord*word); -struct __vpiArrayBase*get_word_parent(struct __vpiArrayWord*word); + inline unsigned get_index() const { return this - word0; } + inline struct __vpiArrayBase*get_parent() const { return (word0 - 1)->parent; } +}; struct __vpiArrayWord*array_var_word_from_handle(vpiHandle ref); struct __vpiArrayWord*array_var_index_from_handle(vpiHandle ref); From ea7fa24f9e82503f13b28f21054008f181a484d5 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 19 Nov 2014 18:32:23 +0100 Subject: [PATCH 16/29] vvp: Further extraction of common code pieces from ArrayBase. --- vvp/array.cc | 223 ++++++++++++++++++-------------------------- vvp/array_common.cc | 68 ++++++++++++++ vvp/vpi_priv.h | 21 +++-- 3 files changed, 174 insertions(+), 138 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 0d6a05bf1..7c68ce821 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -85,11 +85,15 @@ vvp_array_t array_find(const char*label) struct __vpiArray : public __vpiArrayBase, public __vpiHandle { int get_type_code(void) const { return vpiMemory; } unsigned get_size() const { return array_count; } - int get_word_size() const; - int get_left_range() const { assert(nets == 0); return msb.get_value(); } - int get_right_range() const { assert(nets == 0); return lsb.get_value(); } + vpiHandle get_left_range() { assert(nets == 0); return &msb; } + vpiHandle get_right_range() { assert(nets == 0); return &lsb; } struct __vpiScope*get_scope() const { return scope; } + int get_word_size() const; + char*get_word_str(struct __vpiArrayWord*word, int code); + void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); + void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); + int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); @@ -252,7 +256,7 @@ static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp); // This function return true if the underlying array words are real. -static bool vpi_array_is_real(vvp_array_t arr) +static bool vpi_array_is_real(const vvp_array_t arr) { // Check to see if this is a variable/register array. if (arr->vals4 != 0) // A bit based variable/register array. @@ -275,7 +279,7 @@ static bool vpi_array_is_real(vvp_array_t arr) return false; } -static bool vpi_array_is_string(vvp_array_t arr) +static bool vpi_array_is_string(const vvp_array_t arr) { // Check to see if this is a variable/register array. if (arr->vals4 != 0) // A bit based variable/register array. @@ -303,6 +307,79 @@ int __vpiArray::get_word_size() const return 0; } +char*__vpiArray::get_word_str(struct __vpiArrayWord*word, int code) +{ + unsigned index = word->get_index(); + + if (code == vpiFile) { // Not implemented for now! + return simple_set_rbuf_str(file_names[0]); + } + + char sidx [64]; + snprintf(sidx, 63, "%d", (int)index + first_addr.get_value()); + return generic_get_str(code, get_scope(), name, sidx); +} + +void __vpiArray::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) +{ + unsigned index = word->get_index(); + + // Determine the appropriate format (The Verilog PLI Handbook 5.2.10) + if(vp->format == vpiObjTypeVal) { + if(vpi_array_is_real(this)) + vp->format = vpiRealVal; + else if(vpi_array_is_string(this)) + vp->format = vpiStringVal; + else + vp->format = vpiIntVal; + } + + if(vals4) { + vpip_vec4_get_value(vals4->get_word(index), + vals4->width(), signed_flag, vp); + } else if(vals) { + switch(vp->format) { + case vpiIntVal: + case vpiVectorVal: + { + vvp_vector4_t v; + vals->get_word(index, v); + vpip_vec2_get_value(v, vals_width, signed_flag, vp); + } + break; + + case vpiRealVal: + { + double d; + vals->get_word(index, d); + vpip_real_get_value(d, vp); + } + break; + + case vpiStringVal: + { + string s; + vals->get_word(index, s); + vpip_string_get_value(s, vp); + } + break; + + // TODO *StrVal variants + + default: + fprintf(stderr, "vpi sorry: format is not implemented"); + assert(false); + } + } +} + +void __vpiArray::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int) +{ + unsigned index = word->get_index(); + vvp_vector4_t val = vec4_from_vpi_value(vp, vals_width); + array_set_word(this, index, 0, val); +} + int __vpiArray::vpi_get(int code) { switch (code) { @@ -377,6 +454,7 @@ int __vpiArrayWord::as_word_t::vpi_get(int code) struct __vpiArrayWord*obj = array_var_word_from_handle(this); assert(obj); struct __vpiArrayBase*parent = obj->get_parent(); + t_vpi_value val; switch (code) { case vpiLineNo: @@ -386,10 +464,16 @@ int __vpiArrayWord::as_word_t::vpi_get(int code) return parent->get_word_size(); case vpiLeftRange: - return parent->get_left_range(); + val.format = vpiIntVal; + parent->get_left_range()->vpi_get_value(&val); + assert(val.format == vpiIntVal); + return val.value.integer; case vpiRightRange: - return parent->get_right_range(); + val.format = vpiIntVal; + parent->get_right_range()->vpi_get_value(&val); + assert(val.format == vpiIntVal); + return val.value.integer; case vpiAutomatic: return (int) parent->get_scope()->is_automatic; @@ -404,131 +488,6 @@ int __vpiArrayWord::as_word_t::vpi_get(int code) } } -// TODO make generic version of the following methods and move them to array_common -char* __vpiArrayWord::as_word_t::vpi_get_str(int code) -{ - struct __vpiArrayWord*obj = array_var_word_from_handle(this); - assert(obj); - struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); - unsigned index = obj->get_index(); - - if (code == vpiFile) { // Not implemented for now! - return simple_set_rbuf_str(file_names[0]); - } - - char sidx [64]; - snprintf(sidx, 63, "%d", (int)index + parent->first_addr.get_value()); - return generic_get_str(code, parent->get_scope(), parent->name, sidx); -} - -void __vpiArrayWord::as_word_t::vpi_get_value(p_vpi_value vp) -{ - struct __vpiArrayWord*obj = array_var_word_from_handle(this); - assert(obj); - struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); - unsigned index = obj->get_index(); - - // Determine the appropriate format (The Verilog PLI Handbook 5.2.10) - if(vp->format == vpiObjTypeVal) { - if(vpi_array_is_real(parent)) - vp->format = vpiRealVal; - else if(vpi_array_is_string(parent)) - vp->format = vpiStringVal; - else - vp->format = vpiIntVal; - } - - if(parent->vals4) { - vpip_vec4_get_value(parent->vals4->get_word(index), - parent->vals4->width(), parent->signed_flag, vp); - } else if(parent->vals) { - switch(vp->format) { - case vpiIntVal: - case vpiVectorVal: - { - vvp_vector4_t v; - parent->vals->get_word(index, v); - vpip_vec2_get_value(v, parent->vals_width, parent->signed_flag, vp); - } - break; - - case vpiRealVal: - { - double d; - parent->vals->get_word(index, d); - vpip_real_get_value(d, vp); - } - break; - - case vpiStringVal: - { - string s; - parent->vals->get_word(index, s); - vpip_string_get_value(s, vp); - } - break; - - // TODO *StrVal variants - - default: - fprintf(stderr, "vpi sorry: format is not implemented"); - assert(false); - } - } -} - -vpiHandle __vpiArrayWord::as_word_t::vpi_put_value(p_vpi_value vp, int) -{ - struct __vpiArrayWord*obj = array_var_word_from_handle(this); - assert(obj); - struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); - unsigned index = obj->get_index(); - - vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); - array_set_word(parent, index, 0, val); - return this; -} - -vpiHandle __vpiArrayWord::as_word_t::vpi_handle(int code) -{ - struct __vpiArrayWord*obj = array_var_word_from_handle(this); - assert(obj); - struct __vpiArray*parent = (__vpiArray*) obj->get_parent(); - - switch (code) { - - case vpiIndex: - return &(obj->as_index); - - case vpiLeftRange: - return &parent->msb; - - case vpiRightRange: - return &parent->lsb; - - case vpiParent: - return parent; - - case vpiScope: - return parent->get_scope(); - - case vpiModule: - return vpip_module(parent->get_scope()); - } - - return 0; -} - -void __vpiArrayWord::as_index_t::vpi_get_value(p_vpi_value vp) -{ - struct __vpiArrayWord*obj = array_var_index_from_handle(this); - assert(obj); - unsigned index = obj->get_index(); - - assert(vp->format == vpiIntVal); - vp->value.integer = index; -} - inline __vpiArrayVthrA::__vpiArrayVthrA() { } diff --git a/vvp/array_common.cc b/vvp/array_common.cc index df249a2c6..08bb11ab9 100644 --- a/vvp/array_common.cc +++ b/vvp/array_common.cc @@ -119,6 +119,73 @@ static int array_index_free_object(vpiHandle ref) __vpiHandle::free_object_fun_t __vpiArrayIndex::free_object_fun(void) { return &array_index_free_object; } +char* __vpiArrayWord::as_word_t::vpi_get_str(int code) +{ + struct __vpiArrayWord*obj = array_var_word_from_handle(this); + assert(obj); + struct __vpiArrayBase*parent = obj->get_parent(); + return parent->get_word_str(obj, code); +} + +void __vpiArrayWord::as_word_t::vpi_get_value(p_vpi_value vp) +{ + struct __vpiArrayWord*obj = array_var_word_from_handle(this); + assert(obj); + struct __vpiArrayBase*parent = obj->get_parent(); + return parent->get_word_value(obj, vp); +} + +vpiHandle __vpiArrayWord::as_word_t::vpi_put_value(p_vpi_value vp, int flags) +{ + struct __vpiArrayWord*obj = array_var_word_from_handle(this); + assert(obj); + struct __vpiArrayBase*parent = obj->get_parent(); + parent->put_word_value(obj, vp, flags); + return this; +} + +vpiHandle __vpiArrayWord::as_word_t::vpi_handle(int code) +{ + struct __vpiArrayWord*obj = array_var_word_from_handle(this); + assert(obj); + struct __vpiArrayBase*parent = obj->get_parent(); + + switch (code) { + + case vpiIndex: + return &(obj->as_index); + + case vpiLeftRange: + return parent->get_left_range(); + + case vpiRightRange: + return parent->get_right_range(); + + case vpiParent: + return dynamic_cast(parent); + + case vpiScope: + return parent->get_scope(); + + case vpiModule: + return vpip_module(parent->get_scope()); + } + + return 0; +} + +void __vpiArrayWord::as_index_t::vpi_get_value(p_vpi_value vp) +{ + struct __vpiArrayWord*obj = array_var_index_from_handle(this); + assert(obj); + unsigned index = obj->get_index(); + + assert(vp->format == vpiIntVal); + vp->value.integer = index; +} + + + struct __vpiArrayWord*array_var_word_from_handle(vpiHandle ref) { if (ref == 0) @@ -142,3 +209,4 @@ struct __vpiArrayWord* array_var_index_from_handle(vpiHandle ref) assert(sizeof(__vpiHandle) == sizeof(__vpiArrayWord::as_word_t)); return (struct __vpiArrayWord*) (ref-1); } + diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 3fb08a1a1..15efe0db8 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -539,11 +539,16 @@ struct __vpiArrayBase { __vpiArrayBase() : vals_words(NULL) {} virtual unsigned get_size(void) const = 0; - virtual int get_word_size() const = 0; - virtual int get_left_range() const = 0; - virtual int get_right_range() const = 0; + virtual vpiHandle get_left_range() = 0; + virtual vpiHandle get_right_range() = 0; virtual struct __vpiScope*get_scope() const = 0; + virtual int get_word_size() const = 0; + virtual char*get_word_str(struct __vpiArrayWord*word, int code) = 0; + virtual void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) = 0; + virtual void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, + int flags) = 0; + virtual vpiHandle vpi_iterate(int code); virtual void make_vals_words(); @@ -556,11 +561,15 @@ class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { int get_type_code() const { return vpiArrayVar; } unsigned get_size() const; - int get_word_size() const { return 0; } // TODO - int get_left_range() const { return 0; } - int get_right_range() const { return 0; } + vpiHandle get_left_range() { return NULL; } + vpiHandle get_right_range() { return NULL; } struct __vpiScope*get_scope() const { return scope_; } + int get_word_size() const { return 0; } // TODO + char*get_word_str(struct __vpiArrayWord*word, int code) { return NULL; } + void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) {} + void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) {} + int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); From 9538501b5422bee8309d8277c2aaf9c1ba8ff9f0 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 20 Nov 2014 16:32:00 +0100 Subject: [PATCH 17/29] vvp: Moved __vpiArrayBase::vpi_iterate to __vpiArayBase::vpi_array_base_iterate. --- vvp/array.cc | 1 + vvp/array_common.cc | 2 +- vvp/vpi_priv.h | 6 ++++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 7c68ce821..2ce2728d0 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -97,6 +97,7 @@ struct __vpiArray : public __vpiArrayBase, public __vpiHandle { int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); + inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } vpiHandle vpi_index(int idx); const char*name; /* Permanently allocated string */ diff --git a/vvp/array_common.cc b/vvp/array_common.cc index 08bb11ab9..668a61542 100644 --- a/vvp/array_common.cc +++ b/vvp/array_common.cc @@ -21,7 +21,7 @@ #include "array_common.h" -vpiHandle __vpiArrayBase::vpi_iterate(int code) +vpiHandle __vpiArrayBase::vpi_array_base_iterate(int code) { switch (code) { case vpiMemoryWord: { diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 15efe0db8..ecf2f0c22 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -548,8 +548,10 @@ struct __vpiArrayBase { virtual void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) = 0; virtual void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) = 0; - - virtual vpiHandle vpi_iterate(int code); + // vpi_iterate is already defined by vpiHandle, so to avoid problems with + // classes inheriting from vpiHandle and vpiArrayBase just share the common + // code in the following function + vpiHandle vpi_array_base_iterate(int code); virtual void make_vals_words(); struct __vpiArrayWord*vals_words; From 6015aceda2d6b50fffe89b8dda9a75beede2452c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 19 Nov 2014 19:03:05 +0100 Subject: [PATCH 18/29] vvp: vpiArrayIterator::vpi_index core moved to vpiArrayBase::get_iter_index. --- vvp/array.cc | 13 +++++++++++++ vvp/array_common.cc | 12 +----------- vvp/array_common.h | 2 +- vvp/vpi_priv.h | 5 +++++ 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 2ce2728d0..40941c1c0 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -94,6 +94,8 @@ struct __vpiArray : public __vpiArrayBase, public __vpiHandle { void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); + vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); + int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); @@ -381,6 +383,17 @@ void __vpiArray::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int) array_set_word(this, index, 0, val); } +vpiHandle __vpiArray::get_iter_index(struct __vpiArrayIterator*iter, int idx) +{ + if (nets) return nets[idx]; + + assert(vals4 || vals); + + if (vals_words == 0) make_vals_words(); + + return &(vals_words[idx].as_word); +} + int __vpiArray::vpi_get(int code) { switch (code) { diff --git a/vvp/array_common.cc b/vvp/array_common.cc index 668a61542..e4c1c810a 100644 --- a/vvp/array_common.cc +++ b/vvp/array_common.cc @@ -36,7 +36,6 @@ vpiHandle __vpiArrayBase::vpi_array_base_iterate(int code) return 0; } -// TODO template void __vpiArrayBase::make_vals_words() { assert(vals_words == 0); @@ -63,14 +62,7 @@ vpiHandle __vpiArrayIterator::vpi_index(int) unsigned use_index = next; next += 1; -// TODO ArrayBase::iterate(int)? - //if (array->nets) return array->nets[use_index]; - - //assert(array->vals4 || array->vals); - - if (array->vals_words == 0) array->make_vals_words(); - - return &(array->vals_words[use_index].as_word); + return array->get_iter_index(this, use_index); } static int array_iterator_free_object(vpiHandle ref) @@ -184,8 +176,6 @@ void __vpiArrayWord::as_index_t::vpi_get_value(p_vpi_value vp) vp->value.integer = index; } - - struct __vpiArrayWord*array_var_word_from_handle(vpiHandle ref) { if (ref == 0) diff --git a/vvp/array_common.h b/vvp/array_common.h index 2cfcb0bbe..d4d6bce0c 100644 --- a/vvp/array_common.h +++ b/vvp/array_common.h @@ -28,7 +28,7 @@ struct __vpiArrayIterator : public __vpiHandle { int get_type_code(void) const { return vpiIterator; } - virtual vpiHandle vpi_index(int idx); + vpiHandle vpi_index(int idx); free_object_fun_t free_object_fun(void); struct __vpiArrayBase*array; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index ecf2f0c22..4987cca94 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -548,10 +548,13 @@ struct __vpiArrayBase { virtual void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) = 0; virtual void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) = 0; + virtual vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx) = 0; + // vpi_iterate is already defined by vpiHandle, so to avoid problems with // classes inheriting from vpiHandle and vpiArrayBase just share the common // code in the following function vpiHandle vpi_array_base_iterate(int code); + virtual void make_vals_words(); struct __vpiArrayWord*vals_words; @@ -572,6 +575,8 @@ class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) {} void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) {} + vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx) {}; + int vpi_get(int code); char* vpi_get_str(int code); vpiHandle vpi_handle(int code); From ca2ef5c95627532782d2a24121efa70aca0d93a5 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 20 Nov 2014 17:23:16 +0100 Subject: [PATCH 19/29] vvp: Cleaning. --- vvp/array.cc | 4 +-- vvp/array.h | 1 - vvp/array_common.h | 2 -- vvp/vpi_darray.cc | 85 ++++++++++++++++++++++++++++++++++++++++------ vvp/vpi_priv.h | 19 +++++++---- 5 files changed, 88 insertions(+), 23 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 40941c1c0..5e81beb8b 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -367,8 +367,6 @@ void __vpiArray::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) } break; - // TODO *StrVal variants - default: fprintf(stderr, "vpi sorry: format is not implemented"); assert(false); @@ -383,7 +381,7 @@ void __vpiArray::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int) array_set_word(this, index, 0, val); } -vpiHandle __vpiArray::get_iter_index(struct __vpiArrayIterator*iter, int idx) +vpiHandle __vpiArray::get_iter_index(struct __vpiArrayIterator*, int idx) { if (nets) return nets[idx]; diff --git a/vvp/array.h b/vvp/array.h index d1766ed15..b4aba35c1 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -31,7 +31,6 @@ class value_callback; */ extern vvp_array_t array_find(const char*label); extern unsigned get_array_word_size(vvp_array_t array); -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/array_common.h b/vvp/array_common.h index d4d6bce0c..8b4d8c334 100644 --- a/vvp/array_common.h +++ b/vvp/array_common.h @@ -95,6 +95,4 @@ struct __vpiArrayWord { struct __vpiArrayWord*array_var_word_from_handle(vpiHandle ref); struct __vpiArrayWord*array_var_index_from_handle(vpiHandle ref); -vpiHandle array_index_iterate(int code, vpiHandle ref); - #endif /* ARRAY_COMMON_H */ diff --git a/vvp/vpi_darray.cc b/vvp/vpi_darray.cc index 3f3694e4c..bb1fbd055 100644 --- a/vvp/vpi_darray.cc +++ b/vvp/vpi_darray.cc @@ -55,6 +55,72 @@ unsigned __vpiDarrayVar::get_size() const return aval->get_size(); } +vpiHandle __vpiDarrayVar::get_left_range() +{ + return NULL; +} + +vpiHandle __vpiDarrayVar::get_right_range() +{ + return NULL; +} + +int __vpiDarrayVar::get_word_size() const +{ + return get_vvp_darray()->get_size(); +} + +char*__vpiDarrayVar::get_word_str(struct __vpiArrayWord*word, int code) +{ + return NULL; +} + +void __vpiDarrayVar::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) +{ + unsigned index = word->get_index(); + vvp_darray*aobj = get_vvp_darray(); + + switch(vp->format) { + case vpiIntVal: + case vpiVectorVal: + { + vvp_vector4_t v; + aobj->get_word(index, v); + vpip_vec2_get_value(v, get_word_size(), true, vp); + } + break; + + case vpiRealVal: + { + double d; + aobj->get_word(index, d); + vpip_real_get_value(d, vp); + } + break; + + case vpiStringVal: + { + string s; + aobj->get_word(index, s); + vpip_string_get_value(s, vp); + } + break; + + default: + fprintf(stderr, "vpi sorry: format is not implemented"); + assert(false); + } +} + +void __vpiDarrayVar::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) +{ +} + +vpiHandle __vpiDarrayVar::get_iter_index(struct __vpiArrayIterator*iter, int idx) +{ + return NULL; +} + int __vpiDarrayVar::vpi_get(int code) { switch (code) { @@ -70,21 +136,11 @@ int __vpiDarrayVar::vpi_get(int code) char* __vpiDarrayVar::vpi_get_str(int code) { - // TODO orson return NULL; } vpiHandle __vpiDarrayVar::vpi_handle(int code) { - // TODO orson - //switch (code) { - //case vpiScope: - //return scope_; - - //case vpiModule: - //return vpip_module(scope_); - //} - return 0; } @@ -106,6 +162,15 @@ void __vpiDarrayVar::vpi_get_value(p_vpi_value val) val->format = vpiSuppressVal; } +vvp_darray*__vpiDarrayVar::get_vvp_darray() const +{ + vvp_fun_signal_object*fun = dynamic_cast (get_net()->fun); + assert(fun); + vvp_object_t obj = fun->get_object(); + + return obj.peek(); +} + vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net) { struct __vpiScope*scope = vpip_peek_current_scope(); diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 4987cca94..8d9feafcb 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -35,6 +35,8 @@ class class_type; +class vvp_darray; + typedef struct __vpiArray* vvp_array_t; /* @@ -566,16 +568,16 @@ class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { int get_type_code() const { return vpiArrayVar; } unsigned get_size() const; - vpiHandle get_left_range() { return NULL; } - vpiHandle get_right_range() { return NULL; } + vpiHandle get_left_range(); + vpiHandle get_right_range(); struct __vpiScope*get_scope() const { return scope_; } - int get_word_size() const { return 0; } // TODO - char*get_word_str(struct __vpiArrayWord*word, int code) { return NULL; } - void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) {} - void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) {} + int get_word_size() const; + char*get_word_str(struct __vpiArrayWord*word, int code); + void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); + void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); - vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx) {}; + vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); int vpi_get(int code); char* vpi_get_str(int code); @@ -583,6 +585,9 @@ class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { vpiHandle vpi_index(int index); void vpi_get_value(p_vpi_value val); + + protected: + vvp_darray*get_vvp_darray() const; }; extern vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net); From a8d43fa7435eb8da94ec8ebbfc2806d4d75348c4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 25 Nov 2014 18:22:37 +0100 Subject: [PATCH 20/29] vvp: Stop simulation in case of errors in $ivl_string_method$to_vec. --- vpi/v2009_string.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vpi/v2009_string.c b/vpi/v2009_string.c index e9b98cb79..29dd3691d 100644 --- a/vpi/v2009_string.c +++ b/vpi/v2009_string.c @@ -149,12 +149,14 @@ static PLI_INT32 to_vec_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) int vec_size = vpi_get(vpiSize, vec); if(str_size <= 0) { vpi_printf("ERROR: Cannot cast empty string"); - assert(0); + vpi_control(vpiFinish, 0); + return 0; } if(vec_size != str_size * 8) { vpi_printf("ERROR: String and vector size do not match"); - assert(0); + vpi_control(vpiFinish, 0); + return 0; } str_val.format = vpiStringVal; From b4ccaa1b0c51ea9afa912fa5146d4cbaca421168 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 25 Nov 2014 18:25:02 +0100 Subject: [PATCH 21/29] vvp: Fixed iterators for dynamic arrays. --- vvp/array_common.cc | 1 + vvp/vpi_priv.h | 1 + 2 files changed, 2 insertions(+) diff --git a/vvp/array_common.cc b/vvp/array_common.cc index e4c1c810a..adec91db4 100644 --- a/vvp/array_common.cc +++ b/vvp/array_common.cc @@ -24,6 +24,7 @@ vpiHandle __vpiArrayBase::vpi_array_base_iterate(int code) { switch (code) { + case vpiReg: case vpiMemoryWord: { struct __vpiArrayIterator*res; res = new __vpiArrayIterator; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 8d9feafcb..108b225f1 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -578,6 +578,7 @@ class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); + inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } int vpi_get(int code); char* vpi_get_str(int code); From 21a8cb71eef688527b4e3b77d54d48cf4eea3103 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 26 Nov 2014 11:14:51 +0100 Subject: [PATCH 22/29] vvp: Handles for dynamic array ranges. --- vvp/vpi_darray.cc | 19 ++++++++++++++++--- vvp/vpi_priv.h | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/vvp/vpi_darray.cc b/vvp/vpi_darray.cc index bb1fbd055..49a041335 100644 --- a/vvp/vpi_darray.cc +++ b/vvp/vpi_darray.cc @@ -57,12 +57,14 @@ unsigned __vpiDarrayVar::get_size() const vpiHandle __vpiDarrayVar::get_left_range() { - return NULL; + left_range_.set_value(0); + return &left_range_; } vpiHandle __vpiDarrayVar::get_right_range() { - return NULL; + right_range_.set_value(get_size() - 1); + return &right_range_; } int __vpiDarrayVar::get_word_size() const @@ -141,7 +143,18 @@ char* __vpiDarrayVar::vpi_get_str(int code) vpiHandle __vpiDarrayVar::vpi_handle(int code) { - return 0; + switch (code) { + case vpiLeftRange: + return get_left_range(); + + case vpiRightRange: + return get_right_range(); + + //case vpiModule: + //return vpip_module(scope_); + } + + return 0; } vpiHandle __vpiDarrayVar::vpi_index(int index) diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 108b225f1..d1d2aabf6 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -589,6 +589,7 @@ class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { protected: vvp_darray*get_vvp_darray() const; + __vpiDecConst left_range_, right_range_; }; extern vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net); From a236c274f3160884ffe48447401460c4c75dc153 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 26 Nov 2014 11:24:13 +0100 Subject: [PATCH 23/29] vvp: Minor changes. --- vvp/array.cc | 2 +- vvp/array_common.cc | 2 +- vvp/vpi_darray.cc | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 5e81beb8b..b4c53562d 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -368,7 +368,7 @@ void __vpiArray::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) break; default: - fprintf(stderr, "vpi sorry: format is not implemented"); + fprintf(stderr, "vpi sorry: format is not implemented\n"); assert(false); } } diff --git a/vvp/array_common.cc b/vvp/array_common.cc index adec91db4..59d928df9 100644 --- a/vvp/array_common.cc +++ b/vvp/array_common.cc @@ -84,7 +84,7 @@ vpiHandle __vpiArrayIndex::vpi_iterate(int code) if (code == vpiIndex) { struct __vpiArrayIndex*res; res = new __vpiArrayIndex; - res->index = index; // TODO ? see above comment + res->index = index; // see the comment above res->done = 0; return res; } diff --git a/vvp/vpi_darray.cc b/vvp/vpi_darray.cc index 49a041335..862665599 100644 --- a/vvp/vpi_darray.cc +++ b/vvp/vpi_darray.cc @@ -109,16 +109,16 @@ void __vpiDarrayVar::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) break; default: - fprintf(stderr, "vpi sorry: format is not implemented"); + fprintf(stderr, "vpi sorry: format is not implemented\n"); assert(false); } } -void __vpiDarrayVar::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags) +void __vpiDarrayVar::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int) { } -vpiHandle __vpiDarrayVar::get_iter_index(struct __vpiArrayIterator*iter, int idx) +vpiHandle __vpiDarrayVar::get_iter_index(struct __vpiArrayIterator*, int idx) { return NULL; } @@ -189,7 +189,7 @@ vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net) struct __vpiScope*scope = vpip_peek_current_scope(); const char*use_name = name ? vpip_name_string(name) : 0; - class __vpiDarrayVar*obj = new __vpiDarrayVar(scope, use_name, net); + __vpiDarrayVar*obj = new __vpiDarrayVar(scope, use_name, net); return obj; } From 4ddef326312ac2646aca4cc7c2d01fdc1227ee9b Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 26 Nov 2014 11:26:14 +0100 Subject: [PATCH 24/29] vvp: __vpiArray::get_word_value handles StrVal variants. --- vvp/array.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vvp/array.cc b/vvp/array.cc index b4c53562d..ebfca39dd 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -342,7 +342,19 @@ void __vpiArray::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) vals4->width(), signed_flag, vp); } else if(vals) { switch(vp->format) { + case vpiBinStrVal: + case vpiOctStrVal: + case vpiDecStrVal: + case vpiHexStrVal: + case vpiScalarVal: case vpiIntVal: + { + vvp_vector4_t v; + vals->get_word(index, v); + vpip_vec4_get_value(v, vals_width, signed_flag, vp); + } + break; + case vpiVectorVal: { vvp_vector4_t v; From 230c435ae76c11291a8599b1f5eb8cd14ed72bcd Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 27 Nov 2014 09:37:04 +0100 Subject: [PATCH 25/29] vvp: Added missing functions for __vpiDarray. --- vvp/vpi_darray.cc | 119 ++++++++++++++++++++++++++++++++++++++++++---- vvp/vpi_priv.h | 2 +- 2 files changed, 110 insertions(+), 11 deletions(-) diff --git a/vvp/vpi_darray.cc b/vvp/vpi_darray.cc index 862665599..2f6104f71 100644 --- a/vvp/vpi_darray.cc +++ b/vvp/vpi_darray.cc @@ -69,12 +69,23 @@ vpiHandle __vpiDarrayVar::get_right_range() int __vpiDarrayVar::get_word_size() const { - return get_vvp_darray()->get_size(); + vvp_vector4_t new_vec; + vvp_darray*aobj = get_vvp_darray(); + aobj->get_word(0, new_vec); + return new_vec.size(); } char*__vpiDarrayVar::get_word_str(struct __vpiArrayWord*word, int code) { - return NULL; + unsigned index = word->get_index(); + + if (code == vpiFile) { // Not implemented for now! + return simple_set_rbuf_str(file_names[0]); + } + + char sidx [64]; + snprintf(sidx, 63, "%d", (int)index); + return generic_get_str(code, scope_, name_, sidx); } void __vpiDarrayVar::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) @@ -82,13 +93,34 @@ void __vpiDarrayVar::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) unsigned index = word->get_index(); vvp_darray*aobj = get_vvp_darray(); + if(vp->format == vpiObjTypeVal) { + if(dynamic_cast(aobj)) + vp->format = vpiRealVal; + else if(dynamic_cast(aobj)) + vp->format = vpiStringVal; + else + vp->format = vpiVectorVal; + } + switch(vp->format) { + case vpiBinStrVal: + case vpiOctStrVal: + case vpiDecStrVal: + case vpiHexStrVal: + case vpiScalarVal: case vpiIntVal: - case vpiVectorVal: + { + vvp_vector4_t v; + aobj->get_word(index, v); // width == 1? + vpip_vec4_get_value(v, 1, false, vp); // TODO sign? + } + break; + + case vpiVectorVal: // TODO vpip_vec2_ or vpip_vec4_? { vvp_vector4_t v; aobj->get_word(index, v); - vpip_vec2_get_value(v, get_word_size(), true, vp); + vpip_vec2_get_value(v, v.size(), false, vp); // TODO sign? } break; @@ -116,11 +148,71 @@ void __vpiDarrayVar::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp) void __vpiDarrayVar::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int) { + unsigned index = word->get_index(); + vvp_darray*aobj = get_vvp_darray(); + + switch(vp->format) { + case vpiScalarVal: + { + vvp_vector4_t vec(1, vp->value.scalar); + aobj->set_word(index, vec); + } + break; + + case vpiIntVal: + { + vvp_vector4_t vec; + vec.setarray(0, 8 * sizeof(vp->value.integer), (unsigned long*)(&vp->value.integer)); + aobj->set_word(index, vec); + } + break; + + case vpiVectorVal: // 2 vs 4 state logic? + { + int new_bit; + int size = get_word_size(); + PLI_INT32 a = 0, b = 0; + vvp_vector4_t new_vec(size); + p_vpi_vecval vec = vp->value.vector; + vec--; // it will be increased in the first loop iteration + + for(int i = 0; i < size; ++i) { + if(i % (8 * sizeof(vec->aval)) == 0) { + ++vec; + a = vec->aval; + b = vec->bval; + } + + // convert to vvp_bit4_t + new_bit = ((b & 1) << 2) | (a & 1); + new_vec.set_bit(i, (vvp_bit4_t) new_bit); + + a >>= 1; + b >>= 1; + } + aobj->set_word(index, new_vec); + } + break; + + case vpiRealVal: + aobj->set_word(index, vp->value.real); + break; + + case vpiStringVal: + aobj->set_word(index, std::string(vp->value.str)); + break; + + default: + fprintf(stderr, "vpi sorry: format is not implemented"); + assert(false); + } } vpiHandle __vpiDarrayVar::get_iter_index(struct __vpiArrayIterator*, int idx) { - return NULL; + if (vals_words == 0) make_vals_words(); + + return &(vals_words[idx].as_word); } int __vpiDarrayVar::vpi_get(int code) @@ -138,7 +230,11 @@ int __vpiDarrayVar::vpi_get(int code) char* __vpiDarrayVar::vpi_get_str(int code) { - return NULL; + if (code == vpiFile) { // Not implemented for now! + return simple_set_rbuf_str(file_names[0]); + } + + return generic_get_str(code, scope_, name_, NULL); } vpiHandle __vpiDarrayVar::vpi_handle(int code) @@ -150,11 +246,14 @@ vpiHandle __vpiDarrayVar::vpi_handle(int code) case vpiRightRange: return get_right_range(); - //case vpiModule: - //return vpip_module(scope_); - } + case vpiScope: + return scope_; - return 0; + case vpiModule: + return vpip_module(scope_); + } + + return 0; } vpiHandle __vpiDarrayVar::vpi_index(int index) diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index d1d2aabf6..bd803492a 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -519,9 +519,9 @@ class __vpiBaseVar : public __vpiHandle { protected: struct __vpiScope* scope_; + const char*name_; private: - const char*name_; vvp_net_t*net_; }; From cc4c5f499816e79d5a007870d02c266cbc325a57 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 28 Nov 2014 10:27:55 +0100 Subject: [PATCH 26/29] vvp: Changed get_array_word_size(vvp_array_t) to __vpiArray::get_word_size(). --- vvp/array.cc | 123 +++++++------------------------------------------ vvp/array.h | 1 - vvp/vpi_priv.h | 73 +++++++++++++++++++++++++++++ vvp/vthread.cc | 6 +-- 4 files changed, 93 insertions(+), 110 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index ebfca39dd..67c68e8a5 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -57,78 +57,6 @@ vvp_array_t array_find(const char*label) return v; } -/* -* The vpiArray object holds an array of vpi objects that themselves -* represent the words of the array. The vpi_array_t is a pointer to -* a struct __vpiArray. -* -* The details of the implementation depends on what this is an array -* of. The easiest case is if this is an array of nets. -* -* - Array of Nets: -* If this represents an array of nets, then the nets member points to -* an array of vpiHandle objects. Each vpiHandle is a word. This is -* done because typically each word of a net array is simultaneously -* driven and accessed by other means, so there is no advantage to -* compacting the array in any other way. -* -* - Array of vector4 words. -* In this case, the nets pointer is nil, and the vals4 member points -* to a vvl_vector4array_t object that is a compact representation of -* an array of vvp_vector4_t vectors. -* -* - Array of real variables -* The vals member points to a dynamic array objects that has an -* array of double variables. This is very much like the way the -* vector4 array works. -*/ -struct __vpiArray : public __vpiArrayBase, public __vpiHandle { - int get_type_code(void) const { return vpiMemory; } - unsigned get_size() const { return array_count; } - vpiHandle get_left_range() { assert(nets == 0); return &msb; } - vpiHandle get_right_range() { assert(nets == 0); return &lsb; } - struct __vpiScope*get_scope() const { return scope; } - - int get_word_size() const; - char*get_word_str(struct __vpiArrayWord*word, int code); - void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); - void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); - - vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); - - int vpi_get(int code); - char* vpi_get_str(int code); - vpiHandle vpi_handle(int code); - inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } - vpiHandle vpi_index(int idx); - - const char*name; /* Permanently allocated string */ - __vpiDecConst first_addr; - __vpiDecConst last_addr; - __vpiDecConst msb; - __vpiDecConst lsb; - unsigned vals_width; - // If this is a net array, nets lists the handles. - vpiHandle*nets; - // If this is a var array, then these are used instead of nets. - vvp_vector4array_t*vals4; - vvp_darray *vals; - - vvp_fun_arrayport*ports_; - struct __vpiCallback *vpi_callbacks; - bool signed_flag; - bool swap_addr; - -private: - unsigned array_count; - struct __vpiScope*scope; - -friend vpiHandle vpip_make_array(char*label, const char*name, - int first_addr, int last_addr, - bool signed_flag); -friend void compile_array_alias(char*label, char*name, char*src); -}; - struct __vpiArrayVthrA : public __vpiHandle { __vpiArrayVthrA(); @@ -217,27 +145,6 @@ struct __vpiArrayVthrAPV : public __vpiHandle { unsigned part_wid; }; -/* Get the array word size. */ -unsigned get_array_word_size(vvp_array_t array) -{ - unsigned width; - - assert(array->get_size() > 0); - /* For a net array we need to get the width from the first element. */ - if (array->nets) { - assert(array->vals4 == 0 && array->vals == 0); - struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(array->nets[0]); - assert(vsig); - width = vpip_size(vsig); - /* For a variable array we can get the width from vals_width. */ - } else { - assert(array->vals4 || array->vals); - width = array->vals_width; - } - - return width; -} - bool is_net_array(vpiHandle obj) { struct __vpiArray*rfp = dynamic_cast<__vpiArray*> (obj); @@ -296,18 +203,22 @@ static bool vpi_array_is_string(const vvp_array_t arr) int __vpiArray::get_word_size() const { - assert(nets == 0); + unsigned width; - if (vals4) { - assert(vals == 0); - return (int) vals4->width(); - } else { - assert(vals4 == 0); - return 1; - } + assert(get_size() > 0); + /* For a net array we need to get the width from the first element. */ + if (nets) { + assert(vals4 == 0 && vals == 0); + struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(nets[0]); + assert(vsig); + width = vpip_size(vsig); + /* For a variable array we can get the width from vals_width. */ + } else { + assert(vals4 || vals); + width = vals_width; + } - assert(false); - return 0; + return width; } char*__vpiArray::get_word_str(struct __vpiArrayWord*word, int code) @@ -561,7 +472,7 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref) return 0; // Not implemented for now! case vpiSize: - return get_array_word_size(parent); + return parent->get_word_size(); case vpiLeftRange: return parent->msb.get_value(); @@ -625,7 +536,7 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) vpip_string_get_value(tmp, vp); } else { vvp_vector4_t tmp = array_get_word(parent, index); - unsigned width = get_array_word_size(parent); + unsigned width = parent->get_word_size(); vpip_vec4_get_value(tmp, width, parent->signed_flag, vp); } } @@ -645,7 +556,7 @@ static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) double val = real_from_vpi_value(vp); array_set_word(parent, index, val); } else { - unsigned width = get_array_word_size(parent); + unsigned width = parent->get_word_size(); vvp_vector4_t val = vec4_from_vpi_value(vp, width); array_set_word(parent, index, 0, val); } diff --git a/vvp/array.h b/vvp/array.h index b4aba35c1..1016580ff 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -30,7 +30,6 @@ class value_callback; * table of all the arrays in the design. */ extern vvp_array_t array_find(const char*label); -extern unsigned get_array_word_size(vvp_array_t array); 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 bd803492a..1bdb5d64e 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -36,6 +36,7 @@ class class_type; class vvp_darray; +class vvp_fun_arrayport; typedef struct __vpiArray* vvp_array_t; @@ -562,6 +563,78 @@ struct __vpiArrayBase { struct __vpiArrayWord*vals_words; }; +/* +* The vpiArray object holds an array of vpi objects that themselves +* represent the words of the array. The vpi_array_t is a pointer to +* a struct __vpiArray. +* +* The details of the implementation depends on what this is an array +* of. The easiest case is if this is an array of nets. +* +* - Array of Nets: +* If this represents an array of nets, then the nets member points to +* an array of vpiHandle objects. Each vpiHandle is a word. This is +* done because typically each word of a net array is simultaneously +* driven and accessed by other means, so there is no advantage to +* compacting the array in any other way. +* +* - Array of vector4 words. +* In this case, the nets pointer is nil, and the vals4 member points +* to a vvl_vector4array_t object that is a compact representation of +* an array of vvp_vector4_t vectors. +* +* - Array of real variables +* The vals member points to a dynamic array objects that has an +* array of double variables. This is very much like the way the +* vector4 array works. +*/ +struct __vpiArray : public __vpiArrayBase, public __vpiHandle { + int get_type_code(void) const { return vpiMemory; } + unsigned get_size() const { return array_count; } + vpiHandle get_left_range() { assert(nets == 0); return &msb; } + vpiHandle get_right_range() { assert(nets == 0); return &lsb; } + struct __vpiScope*get_scope() const { return scope; } + + int get_word_size() const; + char*get_word_str(struct __vpiArrayWord*word, int code); + void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); + void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); + + vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); + + int vpi_get(int code); + char* vpi_get_str(int code); + vpiHandle vpi_handle(int code); + inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } + vpiHandle vpi_index(int idx); + + const char*name; /* Permanently allocated string */ + __vpiDecConst first_addr; + __vpiDecConst last_addr; + __vpiDecConst msb; + __vpiDecConst lsb; + unsigned vals_width; + // If this is a net array, nets lists the handles. + vpiHandle*nets; + // If this is a var array, then these are used instead of nets. + vvp_vector4array_t*vals4; + vvp_darray *vals; + + vvp_fun_arrayport*ports_; + struct __vpiCallback *vpi_callbacks; + bool signed_flag; + bool swap_addr; + +private: + unsigned array_count; + struct __vpiScope*scope; + +friend vpiHandle vpip_make_array(char*label, const char*name, + int first_addr, int last_addr, + bool signed_flag); +friend void compile_array_alias(char*label, char*name, char*src); +}; + class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { public: __vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net); diff --git a/vvp/vthread.cc b/vvp/vthread.cc index db0111773..1ebe5afc0 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1020,7 +1020,7 @@ bool of_ASSIGN_AV(vthread_t thr, vvp_code_t cp) if (adr < 0) return true; - long vwidth = get_array_word_size(cp->array); + long vwidth = cp->array->get_word_size(); // We fell off the MSB end. if (off >= vwidth) return true; // Trim the bits after the MSB @@ -1059,7 +1059,7 @@ bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp) if (adr < 0) return true; - long vwidth = get_array_word_size(cp->array); + long vwidth = cp->array->get_word_size(); // We fell off the MSB end. if (off >= vwidth) return true; // Trim the bits after the MSB @@ -1091,7 +1091,7 @@ bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t cp) if (adr < 0) return true; - long vwidth = get_array_word_size(cp->array); + long vwidth = cp->array->get_word_size(); // We fell off the MSB end. if (off >= vwidth) return true; // Trim the bits after the MSB From 7c77097f71b467fba39222e1c73049c5ba5e0509 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 28 Nov 2014 10:57:03 +0100 Subject: [PATCH 27/29] vvp: array_[set/get]_word changed to __vpiArray::[set/get]_word. --- vvp/array.cc | 190 ++++++++++++++++++++++++------------------------ vvp/array.h | 14 ---- vvp/event.cc | 4 +- vvp/schedule.cc | 4 +- vvp/vpi_priv.h | 10 +++ vvp/vthread.cc | 24 +++--- 6 files changed, 119 insertions(+), 127 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 67c68e8a5..62b2766ef 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -301,7 +301,7 @@ void __vpiArray::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int) { unsigned index = word->get_index(); vvp_vector4_t val = vec4_from_vpi_value(vp, vals_width); - array_set_word(this, index, 0, val); + set_word(index, 0, val); } vpiHandle __vpiArray::get_iter_index(struct __vpiArrayIterator*, int idx) @@ -529,13 +529,13 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) unsigned index = obj->get_address(); if (vpi_array_is_real(parent)) { - double tmp = array_get_word_r(parent, index); + double tmp = parent->get_word_r(index); vpip_real_get_value(tmp, vp); } else if (vpi_array_is_string(parent)) { - string tmp = array_get_word_str(parent, index); + string tmp = parent->get_word_str(index); vpip_string_get_value(tmp, vp); } else { - vvp_vector4_t tmp = array_get_word(parent, index); + vvp_vector4_t tmp = parent->get_word(index); unsigned width = parent->get_word_size(); vpip_vec4_get_value(tmp, width, parent->signed_flag, vp); } @@ -554,11 +554,11 @@ static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) if (vpi_array_is_real(parent)) { double val = real_from_vpi_value(vp); - array_set_word(parent, index, val); + parent->set_word(index, val); } else { unsigned width = parent->get_word_size(); vvp_vector4_t val = vec4_from_vpi_value(vp, width); - array_set_word(parent, index, 0, val); + parent->set_word(index, 0, val); } return ref; @@ -656,128 +656,125 @@ static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp) unsigned index = obj->word_sel; if (vpi_array_is_real(parent)) { - double tmp = array_get_word_r(parent, index); + double tmp = parent->get_word_r(index); vpip_real_get_value(tmp, vp); } else { - vvp_vector4_t tmp = array_get_word(parent, index); + vvp_vector4_t tmp = parent->get_word(index); tmp = tmp.subvalue(obj->part_bit, obj->part_wid); vpip_vec4_get_value(tmp, obj->part_wid, parent->signed_flag, vp); } } -void array_set_word(vvp_array_t arr, - unsigned address, - unsigned part_off, - vvp_vector4_t val) +void __vpiArray::set_word(unsigned address, unsigned part_off, vvp_vector4_t val) { - if (address >= arr->get_size()) + if (address >= get_size()) return; - if (arr->vals4) { - assert(arr->nets == 0); - if (part_off != 0 || val.size() != arr->vals_width) { - vvp_vector4_t tmp = arr->vals4->get_word(address); + if (vals4) { + assert(nets == 0); + if (part_off != 0 || val.size() != vals_width) { + vvp_vector4_t tmp = vals4->get_word(address); if ((part_off + val.size()) > tmp.size()) { cerr << "part_off=" << part_off << " val.size()=" << val.size() - << " arr->vals[address].size()=" << tmp.size() - << " arr->vals_width=" << arr->vals_width << endl; + << " vals[address].size()=" << tmp.size() + << " vals_width=" << vals_width << endl; assert(0); } tmp.set_vec(part_off, val); - arr->vals4->set_word(address, tmp); + vals4->set_word(address, tmp); } else { - arr->vals4->set_word(address, val); + vals4->set_word(address, val); } - array_word_change(arr, address); + array_word_change(this, address); return; } - if (arr->vals) { - assert(arr->nets == 0); + if (vals) { + assert(nets == 0); // FIXME: For now, assume no part select of word? assert(part_off==0); - assert(val.size() == arr->vals_width); - arr->vals->set_word(address, val); - array_word_change(arr, address); + assert(val.size() == vals_width); + vals->set_word(address, val); + array_word_change(this, address); return; } - assert(arr->nets != 0); + assert(nets != 0); // Select the word of the array that we affect. - vpiHandle word = arr->nets[address]; + vpiHandle word = nets[address]; struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(word); assert(vsig); vsig->node->send_vec4_pv(val, part_off, val.size(), vpip_size(vsig), 0); - array_word_change(arr, address); + array_word_change(this, address); } -void array_set_word(vvp_array_t arr, unsigned address, double val) +void __vpiArray::set_word(unsigned address, double val) { - assert(arr->vals != 0); - assert(arr->nets == 0); + assert(vals != 0); + assert(nets == 0); - if (address >= arr->vals->get_size()) + if (address >= vals->get_size()) return; - arr->vals->set_word(address, val); - array_word_change(arr, address); + vals->set_word(address, val); + array_word_change(this, address); } -void array_set_word(vvp_array_t arr, unsigned address, const string&val) +void __vpiArray::set_word(unsigned address, const string&val) { - assert(arr->vals != 0); - assert(arr->nets == 0); + assert(vals != 0); + assert(nets == 0); - if (address >= arr->vals->get_size()) + if (address >= vals->get_size()) return; - arr->vals->set_word(address, val); - array_word_change(arr, address); + vals->set_word(address, val); + array_word_change(this, address); } -void array_set_word(vvp_array_t arr, unsigned address, const vvp_object_t&val) +void __vpiArray::set_word(unsigned address, const vvp_object_t&val) { - assert(arr->vals != 0); - assert(arr->nets == 0); + assert(vals != 0); + assert(nets == 0); - if (address >= arr->vals->get_size()) + if (address >= vals->get_size()) return; - arr->vals->set_word(address, val); - array_word_change(arr, address); + vals->set_word(address, val); + array_word_change(this, address); } -vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) +vvp_vector4_t __vpiArray::get_word(unsigned address) { - if (arr->vals4) { - assert(arr->nets == 0); - assert(arr->vals == 0); - return arr->vals4->get_word(address); + if (vals4) { + assert(nets == 0); + assert(vals == 0); + return vals4->get_word(address); } - if (arr->vals) { - assert(arr->nets == 0); - assert(arr->vals4== 0); - if (address >= arr->vals->get_size()) - return vvp_vector4_t(arr->vals_width, BIT4_X); + if (vals) { + assert(nets == 0); + assert(vals4== 0); + if (address >= vals->get_size()) + return vvp_vector4_t(vals_width, BIT4_X); vvp_vector4_t val; - arr->vals->get_word(address, val); + vals->get_word(address, val); return val; } - assert(arr->vals4 == 0); - assert(arr->vals == 0); - assert(arr->nets != 0); + assert(vals4 == 0); + assert(vals == 0); + assert(nets != 0); - if (address >= arr->get_size()) { + if (address >= get_size()) { // Reading outside the array. Return X's but get the // width by looking at a word that we know is present. - assert(arr->get_size() > 0); - vpiHandle word = arr->nets[0]; + assert(get_size() > 0); + vpiHandle word = nets[0]; assert(word); struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(word); assert(vsig); @@ -786,7 +783,7 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) return vvp_vector4_t(sig->value_size(), BIT4_X); } - vpiHandle word = arr->nets[address]; + vpiHandle word = nets[address]; struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(word); assert(vsig); vvp_signal_value*sig = dynamic_cast (vsig->node->fil); @@ -797,23 +794,23 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) return val; } -double array_get_word_r(vvp_array_t arr, unsigned address) +double __vpiArray::get_word_r(unsigned address) { - if (arr->vals) { - assert(arr->vals4 == 0); - assert(arr->nets == 0); + if (vals) { + assert(vals4 == 0); + assert(nets == 0); // In this context, address out of bounds returns 0.0 // instead of an error. - if (address >= arr->vals->get_size()) + if (address >= vals->get_size()) return 0.0; double val; - arr->vals->get_word(address, val); + vals->get_word(address, val); return val; } - assert(arr->nets); - vpiHandle word = arr->nets[address]; + assert(nets); + vpiHandle word = nets[address]; struct __vpiRealVar*vsig = dynamic_cast<__vpiRealVar*>(word); assert(vsig); vvp_signal_value*sig = dynamic_cast (vsig->net->fil); @@ -821,47 +818,46 @@ double array_get_word_r(vvp_array_t arr, unsigned address) double val = sig->real_value(); return val; - } -void array_get_word_obj(vvp_array_t arr, unsigned address, vvp_object_t&val) +void __vpiArray::get_word_obj(unsigned address, vvp_object_t&val) { - if (arr->vals) { - assert(arr->vals4 == 0); - assert(arr->nets == 0); + if (vals) { + assert(vals4 == 0); + assert(nets == 0); // In this context, address out of bounds returns 0.0 // instead of an error. - if (address >= arr->vals->get_size()) { + if (address >= vals->get_size()) { val = vvp_object_t(); return; } - arr->vals->get_word(address, val); + vals->get_word(address, val); return; } - assert(arr->nets); + assert(nets); // Arrays of string nets not implemented! assert(0); return; } -string array_get_word_str(vvp_array_t arr, unsigned address) +string __vpiArray::get_word_str(unsigned address) { - if (arr->vals) { - assert(arr->vals4 == 0); - assert(arr->nets == 0); + if (vals) { + assert(vals4 == 0); + assert(nets == 0); // In this context, address out of bounds returns 0.0 // instead of an error. - if (address >= arr->vals->get_size()) + if (address >= vals->get_size()) return ""; string val; - arr->vals->get_word(address, val); + vals->get_word(address, val); return val; } - assert(arr->nets); + assert(nets); // Arrays of string nets not implemented! assert(0); return ""; @@ -1181,9 +1177,9 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit if (! addr_valid_flag) addr_ = arr_->get_size(); if (vpi_array_is_real(arr_)) - port.ptr()->send_real(array_get_word_r(arr_, addr_), 0); + port.ptr()->send_real(arr_->get_word_r(addr_), 0); else - port.ptr()->send_vec4(array_get_word(arr_,addr_), 0); + port.ptr()->send_vec4(arr_->get_word(addr_), 0); break; @@ -1198,9 +1194,9 @@ void vvp_fun_arrayport_sa::check_word_change(unsigned long addr) if (addr != addr_) return; if (vpi_array_is_real(arr_)) { - net_->send_real(array_get_word_r(arr_, addr_), 0); + net_->send_real(arr_->get_word_r(addr_), 0); } else { - net_->send_vec4(array_get_word(arr_, addr_), 0); + net_->send_vec4(arr_->get_word(addr_), 0); } } @@ -1287,10 +1283,10 @@ void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit addr_valid_flag = vector4_to_value(bit, *addr); if (! addr_valid_flag) *addr = arr_->get_size(); if (vpi_array_is_real(arr_)) { - port.ptr()->send_real(array_get_word_r(arr_, *addr), + port.ptr()->send_real(arr_->get_word_r(*addr), context); } else { - port.ptr()->send_vec4(array_get_word(arr_, *addr), + port.ptr()->send_vec4(arr_->get_word(*addr), context); } break; @@ -1318,9 +1314,9 @@ void vvp_fun_arrayport_aa::check_word_change_(unsigned long addr, return; if (vpi_array_is_real(arr_)) { - net_->send_real(array_get_word_r(arr_, addr), context); + net_->send_real(arr_->get_word_r(addr), context); } else { - net_->send_vec4(array_get_word(arr_, addr), context); + net_->send_vec4(arr_->get_word(addr), context); } } diff --git a/vvp/array.h b/vvp/array.h index 1016580ff..6aa021225 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -37,20 +37,6 @@ extern void array_attach_word(vvp_array_t array, unsigned addr, vpiHandle word); extern void array_alias_word(vvp_array_t array, unsigned long addr, vpiHandle word, int msb, int lsb); -extern void array_set_word(vvp_array_t arr, unsigned idx, - unsigned off, vvp_vector4_t val); -extern void array_set_word(vvp_array_t arr, unsigned idx, - double val); -extern void array_set_word(vvp_array_t arr, unsigned idx, - const std::string&val); -extern void array_set_word(vvp_array_t arr, unsigned idx, - const vvp_object_t&val); - -extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address); -extern double array_get_word_r(vvp_array_t array, unsigned address); -extern void array_get_word_obj(vvp_array_t array, unsigned address, vvp_object_t&val); -extern std::string array_get_word_str(vvp_array_t array, unsigned address); - /* VPI hooks */ extern value_callback* vpip_array_word_change(p_cb_data data); diff --git a/vvp/event.cc b/vvp/event.cc index 47b3d143a..d95ce975c 100644 --- a/vvp/event.cc +++ b/vvp/event.cc @@ -137,7 +137,7 @@ evctl_array::evctl_array(vvp_array_t memory, unsigned index, void evctl_array::run_run() { - array_set_word(mem_, idx_, off_, value_); + mem_->set_word(idx_, off_, value_); } void schedule_evctl(vvp_array_t memory, unsigned index, @@ -163,7 +163,7 @@ evctl_array_r::evctl_array_r(vvp_array_t memory, unsigned index, void evctl_array_r::run_run() { - array_set_word(mem_, idx_, value_); + mem_->set_word(idx_, value_); } void schedule_evctl(vvp_array_t memory, unsigned index, diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 4a62bf4de..c6bb71030 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -306,7 +306,7 @@ struct assign_array_word_s : public event_s { void assign_array_word_s::run_run(void) { count_assign_events += 1; - array_set_word(mem, adr, off, val); + mem->set_word(adr, off, val); } static const size_t ARRAY_W_CHUNK_COUNT = 8192 / sizeof(struct assign_array_word_s); @@ -396,7 +396,7 @@ struct assign_array_r_word_s : public event_s { void assign_array_r_word_s::run_run(void) { count_assign_events += 1; - array_set_word(mem, adr, val); + mem->set_word(adr, val); } static const size_t ARRAY_R_W_CHUNK_COUNT = 8192 / sizeof(struct assign_array_r_word_s); static slab_t array_r_w_heap; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 1bdb5d64e..cc70185f5 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -608,6 +608,16 @@ struct __vpiArray : public __vpiArrayBase, public __vpiHandle { inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } vpiHandle vpi_index(int idx); + void set_word(unsigned idx, unsigned off, vvp_vector4_t val); + void set_word(unsigned idx, double val); + void set_word(unsigned idx, const std::string&val); + void set_word(unsigned idx, const vvp_object_t&val); + + vvp_vector4_t get_word(unsigned address); + double get_word_r(unsigned address); + void get_word_obj(unsigned address, vvp_object_t&val); + std::string get_word_str(unsigned address); + const char*name; /* Permanently allocated string */ __vpiDecConst first_addr; __vpiDecConst last_addr; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 1ebe5afc0..32a0d8a29 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -3262,7 +3262,7 @@ bool of_LOAD_AR(vthread_t thr, vvp_code_t cp) if (thr_get_bit(thr, 4) == BIT4_1) { word = 0.0; } else { - word = array_get_word_r(cp->array, adr); + word = cp->array->get_word_r(adr); } thr->push_real(word); @@ -3294,7 +3294,7 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp) return true; } - vvp_vector4_t word = array_get_word(cp->array, adr); + vvp_vector4_t word = cp->array->get_word(adr); if (word.size() > wid) word.resize(wid); @@ -3451,7 +3451,7 @@ bool of_LOAD_AVP0(vthread_t thr, vvp_code_t cp) /* We need a vector this wide to make the math work correctly. * Copy the base bits into the vector, but keep the width. */ vvp_vector4_t sig_value(wid, BIT4_0); - sig_value.copy_bits(array_get_word(cp->array, adr)); + sig_value.copy_bits(cp->array->get_word(adr)); load_vp0_common(thr, cp, sig_value); return true; @@ -3471,7 +3471,7 @@ bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t cp) return true; } - vvp_vector4_t tmp (array_get_word(cp->array, adr)); + vvp_vector4_t tmp (cp->array->get_word(adr)); /* We need a vector this wide to make the math work correctly. * Copy the base bits into the vector, but keep the width. */ @@ -3505,7 +3505,7 @@ bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t cp) long use_index = thr->words[index].w_int; - vvp_vector4_t word = array_get_word(cp->array, adr); + vvp_vector4_t word = cp->array->get_word(adr); if ((use_index >= (long)word.size()) || (use_index < 0)) { thr_put_bit(thr, bit, BIT4_X); @@ -3543,7 +3543,7 @@ bool of_LOAD_OBJA(vthread_t thr, vvp_code_t cp) if (thr_get_bit(thr, 4) == BIT4_1) { ; // Return nil } else { - array_get_word_obj(cp->array, adr, word); + cp->array->get_word_obj(adr, word); } thr->push_object(word); @@ -3591,7 +3591,7 @@ bool of_LOAD_STRA(vthread_t thr, vvp_code_t cp) if (thr_get_bit(thr, 4) == BIT4_1) { word = ""; } else { - word = array_get_word_str(cp->array, adr); + word = cp->array->get_word_str(adr); } thr->push_str(word); @@ -5051,7 +5051,7 @@ bool of_SET_AV(vthread_t thr, vvp_code_t cp) /* Make a vector of the desired width. */ vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); - array_set_word(cp->array, adr, off, value); + cp->array->set_word(adr, off, value); return true; } @@ -5482,7 +5482,7 @@ bool of_STORE_OBJA(vthread_t thr, vvp_code_t cp) vvp_object_t val; thr->pop_object(val); - array_set_word(cp->array, adr, val); + cp->array->set_word(adr, val); return true; } @@ -5653,7 +5653,7 @@ bool of_STORE_REALA(vthread_t thr, vvp_code_t cp) unsigned adr = thr->words[idx].w_int; double val = thr->pop_real(); - array_set_word(cp->array, adr, val); + cp->array->set_word(adr, val); return true; } @@ -5678,7 +5678,7 @@ bool of_STORE_STRA(vthread_t thr, vvp_code_t cp) unsigned adr = thr->words[idx].w_int; string val = thr->pop_str(); - array_set_word(cp->array, adr, val); + cp->array->set_word(adr, val); return true; } @@ -5861,7 +5861,7 @@ bool of_TEST_NUL_A(vthread_t thr, vvp_code_t cp) return true; } - array_get_word_obj(cp->array, adr, word); + cp->array->get_word_obj(adr, word); if (word.test_nil()) thr_put_bit(thr, 4, BIT4_1); else From 9bc463aac0e65c6e5f27b5d5feea474bab376e26 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 28 Nov 2014 11:14:42 +0100 Subject: [PATCH 28/29] vvp: Moved array_word_change(), array_attach_word(), array_alias_word() to __vpiArray. --- vvp/array.cc | 73 ++++++++++++++++++++++----------------------- vvp/array.h | 7 ----- vvp/vpi_callback.cc | 2 +- vvp/vpi_priv.h | 4 +++ vvp/words.cc | 8 ++--- 5 files changed, 45 insertions(+), 49 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 62b2766ef..26b1ea46c 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -686,7 +686,7 @@ void __vpiArray::set_word(unsigned address, unsigned part_off, vvp_vector4_t val } else { vals4->set_word(address, val); } - array_word_change(this, address); + word_change(address); return; } @@ -696,7 +696,7 @@ void __vpiArray::set_word(unsigned address, unsigned part_off, vvp_vector4_t val assert(part_off==0); assert(val.size() == vals_width); vals->set_word(address, val); - array_word_change(this, address); + word_change(address); return; } @@ -708,7 +708,7 @@ void __vpiArray::set_word(unsigned address, unsigned part_off, vvp_vector4_t val assert(vsig); vsig->node->send_vec4_pv(val, part_off, val.size(), vpip_size(vsig), 0); - array_word_change(this, address); + word_change(address); } void __vpiArray::set_word(unsigned address, double val) @@ -720,7 +720,7 @@ void __vpiArray::set_word(unsigned address, double val) return; vals->set_word(address, val); - array_word_change(this, address); + word_change(address); } void __vpiArray::set_word(unsigned address, const string&val) @@ -732,7 +732,7 @@ void __vpiArray::set_word(unsigned address, const string&val) return; vals->set_word(address, val); - array_word_change(this, address); + word_change(address); } void __vpiArray::set_word(unsigned address, const vvp_object_t&val) @@ -744,7 +744,7 @@ void __vpiArray::set_word(unsigned address, const vvp_object_t&val) return; vals->set_word(address, val); - array_word_change(this, address); + word_change(address); } vvp_vector4_t __vpiArray::get_word(unsigned address) @@ -921,33 +921,32 @@ vpiHandle vpip_make_array(char*label, const char*name, return obj; } -void array_alias_word(vvp_array_t array, unsigned long addr, vpiHandle word, - int msb, int lsb) +void __vpiArray::alias_word(unsigned long addr, vpiHandle word, int msb_, int lsb_) { - assert(array->msb.get_value() == msb); - assert(array->lsb.get_value() == lsb); - assert(addr < array->get_size()); - assert(array->nets); - array->nets[addr] = word; + assert(msb.get_value() == msb_); + assert(lsb.get_value() == lsb_); + assert(addr < get_size()); + assert(nets); + nets[addr] = word; } -void array_attach_word(vvp_array_t array, unsigned addr, vpiHandle word) +void __vpiArray::attach_word(unsigned addr, vpiHandle word) { - assert(addr < array->get_size()); - assert(array->nets); - array->nets[addr] = word; + assert(addr < get_size()); + assert(nets); + nets[addr] = word; if (struct __vpiSignal*sig = dynamic_cast<__vpiSignal*>(word)) { vvp_net_t*net = sig->node; assert(net); vvp_vpi_callback*fun = dynamic_cast(net->fil); assert(fun); - fun->attach_as_word(array, addr); + fun->attach_as_word(this, addr); sig->is_netarray = 1; - sig->within.parent = array; - sig->id.index = new __vpiDecConst(addr + array->first_addr.get_value()); + sig->within.parent = this; + sig->id.index = new __vpiDecConst(addr + first_addr.get_value()); // Now we know the data type, update the array signed_flag. - array->signed_flag = sig->signed_flag; + signed_flag = sig->signed_flag; return; } @@ -956,12 +955,12 @@ void array_attach_word(vvp_array_t array, unsigned addr, vpiHandle word) assert(net); vvp_vpi_callback*fun = dynamic_cast(net->fil); assert(fun); - fun->attach_as_word(array, addr); + fun->attach_as_word(this, addr); sig->is_netarray = 1; - sig->within.parent = array; - sig->id.index = new __vpiDecConst(addr + array->first_addr.get_value()); + sig->within.parent = this; + sig->id.index = new __vpiDecConst(addr + first_addr.get_value()); // Now we know the data type, update the array signed_flag. - array->signed_flag = true; + signed_flag = true; return; } } @@ -1116,7 +1115,7 @@ class vvp_fun_arrayport : public vvp_net_fun_t { unsigned long addr_; friend void array_attach_port(vvp_array_t, vvp_fun_arrayport*); - friend void array_word_change(vvp_array_t, unsigned long); + friend void __vpiArray::word_change(unsigned long); vvp_fun_arrayport*next_; }; @@ -1361,13 +1360,13 @@ class array_word_value_callback : public value_callback { long word_addr; }; -void array_word_change(vvp_array_t array, unsigned long addr) +void __vpiArray::word_change(unsigned long addr) { - for (vvp_fun_arrayport*cur = array->ports_; cur; cur = cur->next_) + for (vvp_fun_arrayport*cur = ports_; cur; cur = cur->next_) cur->check_word_change(addr); // Run callbacks attached to the array itself. - struct __vpiCallback *next = array->vpi_callbacks; + struct __vpiCallback *next = vpi_callbacks; struct __vpiCallback *prev = 0; while (next) { @@ -1383,21 +1382,21 @@ void array_word_change(vvp_array_t array, unsigned long addr) // For whole array callbacks we need to set the index. if (cur->word_addr == -1) { cur->cb_data.index = (PLI_INT32) ((int)addr + - array->first_addr.get_value()); + first_addr.get_value()); } if (cur->cb_data.cb_rtn != 0) { if (cur->test_value_callback_ready()) { if (cur->cb_data.value) { - if (vpi_array_is_real(array)) { + if (vpi_array_is_real(this)) { double val = 0.0; - if (addr < array->vals->get_size()) - array->vals->get_word(addr, val); + if (addr < vals->get_size()) + vals->get_word(addr, val); vpip_real_get_value(val, cur->cb_data.value); } else { - vpip_vec4_get_value(array->vals4->get_word(addr), - array->vals_width, - array->signed_flag, + vpip_vec4_get_value(vals4->get_word(addr), + vals_width, + signed_flag, cur->cb_data.value); } } @@ -1409,7 +1408,7 @@ void array_word_change(vvp_array_t array, unsigned long addr) } else if (prev == 0) { - array->vpi_callbacks = next; + vpi_callbacks = next; cur->next = 0; delete cur; diff --git a/vvp/array.h b/vvp/array.h index 6aa021225..7b62f7cc0 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -31,14 +31,7 @@ class value_callback; */ extern vvp_array_t array_find(const char*label); -extern void array_word_change(vvp_array_t array, unsigned long addr); - -extern void array_attach_word(vvp_array_t array, unsigned addr, vpiHandle word); -extern void array_alias_word(vvp_array_t array, unsigned long addr, - vpiHandle word, int msb, int lsb); - /* VPI hooks */ - extern value_callback* vpip_array_word_change(p_cb_data data); extern value_callback* vpip_array_change(p_cb_data data); diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index cf12f0850..2d2574564 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -688,7 +688,7 @@ void vvp_vpi_callback::clear_all_callbacks() */ void vvp_vpi_callback::run_vpi_callbacks() { - if (array_) array_word_change(array_, array_word_); + if (array_) array_->word_change(array_word_); value_callback *next = vpi_callbacks_; value_callback *prev = 0; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index cc70185f5..f83e09b30 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -618,6 +618,10 @@ struct __vpiArray : public __vpiArrayBase, public __vpiHandle { void get_word_obj(unsigned address, vvp_object_t&val); std::string get_word_str(unsigned address); + void alias_word(unsigned long addr, vpiHandle word, int msb, int lsb); + void attach_word(unsigned addr, vpiHandle word); + void word_change(unsigned long addr); + const char*name; /* Permanently allocated string */ __vpiDecConst first_addr; __vpiDecConst last_addr; diff --git a/vvp/words.cc b/vvp/words.cc index a09e880d1..e7480bd05 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -59,7 +59,7 @@ static void __compile_var_real(char*label, char*name, } if (array) { assert(!name); - array_attach_word(array, array_addr, obj); + array->attach_word(array_addr, obj); } free(label); delete[] name; @@ -365,7 +365,7 @@ static void do_compile_net(vvp_net_t*node, vvp_array_t array, define_functor_symbol(my_label, node); if (array) - array_attach_word(array, array_addr, obj); + array->attach_word(array_addr, obj); else if (obj) vpip_attach_to_scope(scope,obj); @@ -495,7 +495,7 @@ static void __compile_real_net2(vvp_net_t*node, vvp_array_t array, define_functor_symbol(my_label, node); if (array) - array_attach_word(array, array_addr, obj); + array->attach_word(array_addr, obj); else if (obj) vpip_attach_to_scope(scope, obj); @@ -583,7 +583,7 @@ void compile_aliasw(char*label, char*array_label, unsigned long array_addr, vpiHandle obj = vvp_lookup_handle(argv[0].text); assert(obj); - array_alias_word(array, array_addr, obj, msb, lsb); + array->alias_word(array_addr, obj, msb, lsb); free(label); free(array_label); From 1834d470cbcea8ade926324d57b246c511e5875e Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 28 Nov 2014 13:36:29 +0100 Subject: [PATCH 29/29] vvp: Refactored __vpiArrayVthrA & __vpiArrayVthrAPV. --- vvp/array.cc | 191 +++++++++++++++------------------------------------ 1 file changed, 55 insertions(+), 136 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 26b1ea46c..84dcce59d 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -58,9 +58,7 @@ vvp_array_t array_find(const char*label) } struct __vpiArrayVthrA : public __vpiHandle { - - __vpiArrayVthrA(); - int get_type_code(void) const; + int get_type_code(void) const { return vpiMemoryWord; } int vpi_get(int code); char* vpi_get_str(int code); void vpi_get_value(p_vpi_value val); @@ -133,8 +131,7 @@ struct __vpiArrayVthrA : public __vpiHandle { struct __vpiArrayVthrAPV : public __vpiHandle { - __vpiArrayVthrAPV(); - int get_type_code(void) const; + int get_type_code(void) const { return vpiMemoryWord; } int vpi_get(int code); char* vpi_get_str(int code); void vpi_get_value(p_vpi_value val); @@ -154,17 +151,6 @@ bool is_net_array(vpiHandle obj) return false; } -static int vpi_array_vthr_A_get(int code, vpiHandle); -static char*vpi_array_vthr_A_get_str(int code, vpiHandle); -static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp); -static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int); -static vpiHandle vpi_array_vthr_A_get_handle(int code, vpiHandle ref); - -static int vpi_array_vthr_APV_get(int code, vpiHandle); -static char*vpi_array_vthr_APV_get_str(int code, vpiHandle); -static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp); - - // This function return true if the underlying array words are real. static bool vpi_array_is_real(const vvp_array_t arr) { @@ -424,67 +410,26 @@ int __vpiArrayWord::as_word_t::vpi_get(int code) } -inline __vpiArrayVthrA::__vpiArrayVthrA() -{ } - -int __vpiArrayVthrA::get_type_code(void) const -{ return vpiMemoryWord; } - int __vpiArrayVthrA::vpi_get(int code) -{ return vpi_array_vthr_A_get(code, this); } - -char* __vpiArrayVthrA::vpi_get_str(int code) -{ return vpi_array_vthr_A_get_str(code, this); } - -void __vpiArrayVthrA::vpi_get_value(p_vpi_value val) -{ vpi_array_vthr_A_get_value(this, val); } - -vpiHandle __vpiArrayVthrA::vpi_put_value(p_vpi_value val, int flags) -{ return vpi_array_vthr_A_put_value(this, val, flags); } - -vpiHandle __vpiArrayVthrA::vpi_handle(int code) -{ return vpi_array_vthr_A_get_handle(code, this); } - - -inline __vpiArrayVthrAPV::__vpiArrayVthrAPV() -{ } - -int __vpiArrayVthrAPV::get_type_code(void) const -{ return vpiMemoryWord; } - -int __vpiArrayVthrAPV::vpi_get(int code) -{ return vpi_array_vthr_APV_get(code, this); } - -char* __vpiArrayVthrAPV::vpi_get_str(int code) -{ return vpi_array_vthr_APV_get_str(code, this); } - -void __vpiArrayVthrAPV::vpi_get_value(p_vpi_value val) -{ vpi_array_vthr_APV_get_value(this, val); } - -static int vpi_array_vthr_A_get(int code, vpiHandle ref) { - struct __vpiArrayVthrA*obj = dynamic_cast<__vpiArrayVthrA*>(ref); - assert(obj); - struct __vpiArray*parent = obj->array; - switch (code) { case vpiLineNo: return 0; // Not implemented for now! case vpiSize: - return parent->get_word_size(); + return array->get_word_size(); case vpiLeftRange: - return parent->msb.get_value(); + return array->msb.get_value(); case vpiRightRange: - return parent->lsb.get_value(); + return array->lsb.get_value(); case vpiIndex: - return (int)obj->get_address() + parent->first_addr.get_value(); + return (int)get_address() + array->first_addr.get_value(); case vpiAutomatic: - return (int) parent->get_scope()->is_automatic; + return (int) array->get_scope()->is_automatic; #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX) case _vpiFromThr: @@ -497,126 +442,108 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref) // This assumes that the compiler is squashing all the // constant expressions down to a single value. case vpiConstantSelect: - return obj->address_handle == 0 && obj->wid == 0; + return address_handle == 0 && wid == 0; default: return 0; } } -static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref) +char* __vpiArrayVthrA::vpi_get_str(int code) { - struct __vpiArrayVthrA*obj = dynamic_cast<__vpiArrayVthrA*>(ref); - assert(obj); - struct __vpiArray*parent = obj->array; - if (code == vpiFile) { // Not implemented for now! return simple_set_rbuf_str(file_names[0]); } char sidx [64]; - snprintf(sidx, 63, "%d", (int)obj->get_address() + parent->first_addr.get_value()); - return generic_get_str(code, parent->get_scope(), parent->name, sidx); + snprintf(sidx, 63, "%d", (int)get_address() + array->first_addr.get_value()); + return generic_get_str(code, array->get_scope(), array->name, sidx); } -static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) +void __vpiArrayVthrA::vpi_get_value(p_vpi_value vp) { - struct __vpiArrayVthrA*obj = dynamic_cast<__vpiArrayVthrA*>(ref); - assert(obj); - struct __vpiArray*parent = obj->array; + assert(array); - assert(parent); - - unsigned index = obj->get_address(); - if (vpi_array_is_real(parent)) { - double tmp = parent->get_word_r(index); + unsigned index = get_address(); + if (vpi_array_is_real(array)) { + double tmp = array->get_word_r(index); vpip_real_get_value(tmp, vp); - } else if (vpi_array_is_string(parent)) { - string tmp = parent->get_word_str(index); + } else if (vpi_array_is_string(array)) { + string tmp = array->get_word_str(index); vpip_string_get_value(tmp, vp); } else { - vvp_vector4_t tmp = parent->get_word(index); - unsigned width = parent->get_word_size(); - vpip_vec4_get_value(tmp, width, parent->signed_flag, vp); + vvp_vector4_t tmp = array->get_word(index); + unsigned width = array->get_word_size(); + vpip_vec4_get_value(tmp, width, array->signed_flag, vp); } } -static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) +vpiHandle __vpiArrayVthrA::vpi_put_value(p_vpi_value vp, int) { - struct __vpiArrayVthrA*obj = dynamic_cast<__vpiArrayVthrA*>(ref); - assert(obj); - struct __vpiArray*parent = obj->array; + unsigned index = get_address(); - unsigned index = obj->get_address(); + assert(array); + assert(index < array->get_size()); - assert(parent); - assert(index < parent->get_size()); - - if (vpi_array_is_real(parent)) { + if (vpi_array_is_real(array)) { double val = real_from_vpi_value(vp); - parent->set_word(index, val); + array->set_word(index, val); } else { - unsigned width = parent->get_word_size(); + unsigned width = array->get_word_size(); vvp_vector4_t val = vec4_from_vpi_value(vp, width); - parent->set_word(index, 0, val); + array->set_word(index, 0, val); } - return ref; + return this; } -static vpiHandle vpi_array_vthr_A_get_handle(int code, vpiHandle ref) +vpiHandle __vpiArrayVthrA::vpi_handle(int code) { - struct __vpiArrayVthrA*obj = dynamic_cast<__vpiArrayVthrA*>(ref); - assert(obj); - struct __vpiArray*parent = obj->array; - switch (code) { - case vpiIndex: break; // Not implemented! case vpiLeftRange: - return &parent->msb; + return &array->msb; case vpiRightRange: - return &parent->lsb; + return &array->lsb; case vpiParent: - return parent; + case vpiArray: + return array; case vpiScope: - return parent->get_scope(); + return array->get_scope(); case vpiModule: - return vpip_module(parent->get_scope()); + return vpip_module(array->get_scope()); } return 0; } -static int vpi_array_vthr_APV_get(int code, vpiHandle ref) -{ - struct __vpiArrayVthrAPV*obj = dynamic_cast<__vpiArrayVthrAPV*>(ref); - struct __vpiArray*parent = obj->array; +int __vpiArrayVthrAPV::vpi_get(int code) +{ switch (code) { case vpiLineNo: return 0; // Not implemented for now! case vpiSize: - return obj->part_wid; + return part_wid; case vpiLeftRange: - return parent->msb.get_value(); + return array->msb.get_value(); case vpiRightRange: - return parent->lsb.get_value(); + return array->lsb.get_value(); case vpiIndex: - return (int)obj->word_sel; + return (int)word_sel; case vpiAutomatic: - return (int) parent->get_scope()->is_automatic; + return (int) array->get_scope()->is_automatic; #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX) case _vpiFromThr: @@ -631,37 +558,29 @@ static int vpi_array_vthr_APV_get(int code, vpiHandle ref) } } -static char*vpi_array_vthr_APV_get_str(int code, vpiHandle ref) +char* __vpiArrayVthrAPV::vpi_get_str(int code) { - struct __vpiArrayVthrAPV*obj = dynamic_cast<__vpiArrayVthrAPV*>(ref); - assert(obj); - struct __vpiArray*parent = obj->array; - if (code == vpiFile) { // Not implemented for now! return simple_set_rbuf_str(file_names[0]); } char sidx [64]; - snprintf(sidx, 63, "%u", obj->word_sel + parent->first_addr.get_value()); - return generic_get_str(code, parent->get_scope(), parent->name, sidx); + snprintf(sidx, 63, "%u", word_sel + array->first_addr.get_value()); + return generic_get_str(code, array->get_scope(), array->name, sidx); } -static void vpi_array_vthr_APV_get_value(vpiHandle ref, p_vpi_value vp) +void __vpiArrayVthrAPV::vpi_get_value(p_vpi_value vp) { - struct __vpiArrayVthrAPV*obj = dynamic_cast<__vpiArrayVthrAPV*>(ref); - assert(obj); - struct __vpiArray*parent = obj->array; + assert(array); - assert(parent); - - unsigned index = obj->word_sel; - if (vpi_array_is_real(parent)) { - double tmp = parent->get_word_r(index); + unsigned index = word_sel; + if (vpi_array_is_real(array)) { + double tmp = array->get_word_r(index); vpip_real_get_value(tmp, vp); } else { - vvp_vector4_t tmp = parent->get_word(index); - tmp = tmp.subvalue(obj->part_bit, obj->part_wid); - vpip_vec4_get_value(tmp, obj->part_wid, parent->signed_flag, vp); + vvp_vector4_t tmp = array->get_word(index); + tmp = tmp.subvalue(part_bit, part_wid); + vpip_vec4_get_value(tmp, part_wid, array->signed_flag, vp); } }