From d891285326813332ea3878e85f2403e676416b44 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 4 Aug 2014 20:11:21 -0700 Subject: [PATCH] vvp code generation for push_back/push_front for queue objects. --- tgt-vvp/vvp_process.c | 54 ++++++++++++++++++++ vvp/codes.h | 6 +++ vvp/compile.cc | 6 +++ vvp/opcodes.txt | 15 ++++++ vvp/vthread.cc | 112 ++++++++++++++++++++++++++++++++++++++++++ vvp/vvp_darray.cc | 57 +++++++++++++++++++++ vvp/vvp_darray.h | 44 +++++++++++++++++ 7 files changed, 294 insertions(+) diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 53db270b2..02ede0190 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1820,6 +1820,54 @@ static int show_delete_method(ivl_statement_t net) return 0; } +static int show_push_frontback_method(ivl_statement_t net) +{ + const char*stmt_name = ivl_stmt_name(net); + + show_stmt_file_line(net, "queue: push_back"); + + const char*type_code = "?"; + if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0) + type_code = "qf"; + else if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0) + type_code = "qb"; + else + type_code = "??"; + + unsigned parm_count = ivl_stmt_parm_count(net); + if (parm_count != 2) + return 1; + + ivl_expr_t parm0 = ivl_stmt_parm(net,0); + assert(ivl_expr_type(parm0) == IVL_EX_SIGNAL); + ivl_signal_t var = ivl_expr_signal(parm0); + ivl_type_t var_type = ivl_signal_net_type(var); + assert(ivl_type_base(var_type)== IVL_VT_QUEUE); + + ivl_type_t element_type = ivl_type_element(var_type); + + ivl_expr_t parm1 = ivl_stmt_parm(net,1); + struct vector_info vec; + switch (ivl_type_base(element_type)) { + case IVL_VT_REAL: + draw_eval_real(parm1); + fprintf(vvp_out, " %%store/%s/r v%p_0;\n", type_code, var); + break; + case IVL_VT_STRING: + draw_eval_string(parm1); + fprintf(vvp_out, " %%store/%s/str v%p_0;\n", type_code, var); + break; + default: + vec = draw_eval_expr(parm1, STUFF_OK_RO); + fprintf(vvp_out, " %%set/%s v%p_0, %u, %u;\n", + type_code, var, vec.base, vec.wid); + if (vec.base >= 4) clr_vector(vec); + break; + } + + return 0; +} + static int show_system_task_call(ivl_statement_t net) { const char*stmt_name = ivl_stmt_name(net); @@ -1827,6 +1875,12 @@ static int show_system_task_call(ivl_statement_t net) if (strcmp(stmt_name,"$ivl_darray_method$delete") == 0) return show_delete_method(net); + if (strcmp(stmt_name,"$ivl_queue_method$push_front") == 0) + return show_push_frontback_method(net); + + if (strcmp(stmt_name,"$ivl_queue_method$push_back") == 0) + return show_push_frontback_method(net); + show_stmt_file_line(net, "System task call."); draw_vpi_task_call(net); diff --git a/vvp/codes.h b/vvp/codes.h index 1c2b5209a..16b6952b8 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -181,6 +181,8 @@ extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code); extern bool of_SCOPY(vthread_t thr, vvp_code_t code); extern bool of_SET_AV(vthread_t thr, vvp_code_t code); extern bool of_SET_DAR(vthread_t thr, vvp_code_t code); +extern bool of_SET_QB(vthread_t thr, vvp_code_t code); +extern bool of_SET_QF(vthread_t thr, vvp_code_t code); extern bool of_SET_DAR_OBJ(vthread_t thr, vvp_code_t code); extern bool of_SET_DAR_OBJ_REAL(vthread_t thr, vvp_code_t code); extern bool of_SET_DAR_OBJ_STR(vthread_t thr, vvp_code_t code); @@ -192,6 +194,10 @@ extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code); extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code); extern bool of_STORE_DAR_R(vthread_t thr, vvp_code_t code); extern bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t code); +extern bool of_STORE_QB_R(vthread_t thr, vvp_code_t code); +extern bool of_STORE_QB_STR(vthread_t thr, vvp_code_t code); +extern bool of_STORE_QF_R(vthread_t thr, vvp_code_t code); +extern bool of_STORE_QF_STR(vthread_t thr, vvp_code_t code); extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code); extern bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t code); extern bool of_STORE_PROP_R(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 04b459177..430d68869 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -232,6 +232,8 @@ static const struct opcode_table_s opcode_table[] = { { "%set/dar/obj", of_SET_DAR_OBJ, 3,{OA_NUMBER,OA_BIT1,OA_BIT2} }, { "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} }, { "%set/dar/obj/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} }, + { "%set/qb", of_SET_QB, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, + { "%set/qf", of_SET_QF, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, @@ -239,6 +241,10 @@ static const struct opcode_table_s opcode_table[] = { { "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} }, { "%store/dar/r", of_STORE_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%store/dar/str",of_STORE_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%store/qb/r", of_STORE_QB_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%store/qb/str", of_STORE_QB_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%store/qf/r", of_STORE_QF_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%store/qf/str", of_STORE_QF_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%store/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%store/prop/obj",of_STORE_PROP_OBJ,1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index b89f41291..6924f7f65 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -997,6 +997,12 @@ width is implied from the that is the argument. This is the part The address (in canonical form) is precalculated and loaded into index register 3. This is the address of the word within the array. +* %set/qb , , +* %set/qf , , + +This sets the vector value into the back (qb) or front (qf) of a queue +variable. + * %set/x0 , , This sets the part of a signal vector, the address calculated by @@ -1068,6 +1074,10 @@ index in the index register * %store/stra , * %store/dar/r * %store/dar/str +* %store/qf/r +* %store/qf/str +* %store/qb/r +* %store/qb/str The %store/str instruction pops the top of the string stack and writes it to the string variable. @@ -1077,6 +1087,11 @@ The %store/stra targets an array. The %store/dar/str is similar, but the target is a dynamic array of string string. The index is taken from signed index register 3. +The %store/qf/* and %store/qb/* instructions are queue manipulations, +which implement the push_back (qb) and push_front (qf) +functions. These only apply to queue object, and are distinct from the +dar versions because the begin/front don't exist, by definition. + * %sub , , This instruction arithmetically subtracts the right vector out of the diff --git a/vvp/vthread.cc b/vvp/vthread.cc index ca1d4da6b..a47c1db52 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -5012,6 +5012,64 @@ bool of_SET_DAR_OBJ_STR(vthread_t thr, vvp_code_t cp) return true; } +/* + * %set/qb , + */ +bool of_SET_QB(vthread_t thr, vvp_code_t cp) +{ + unsigned bit = cp->bit_idx[0]; + unsigned wid = cp->bit_idx[1]; + + /* Make a vector of the desired width. */ + vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); + + vvp_net_t*net = cp->net; + vvp_fun_signal_object*obj = dynamic_cast (net->fun); + assert(obj); + + vvp_queue*dqueue = obj->get_object().peek(); + if (dqueue == 0) { + assert(obj->get_object().test_nil()); + dqueue = new vvp_queue_vec4; + vvp_object_t val (dqueue); + vvp_net_ptr_t ptr (cp->net, 0); + vvp_send_object(ptr, val, thr->wt_context); + } + + assert(dqueue); + dqueue->push_back(value); + return true; +} + +/* + * %set/qf , + */ +bool of_SET_QF(vthread_t thr, vvp_code_t cp) +{ + unsigned bit = cp->bit_idx[0]; + unsigned wid = cp->bit_idx[1]; + + /* Make a vector of the desired width. */ + vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); + + vvp_net_t*net = cp->net; + vvp_fun_signal_object*obj = dynamic_cast (net->fun); + assert(obj); + + vvp_queue*dqueue = obj->get_object().peek(); + if (dqueue == 0) { + assert(obj->get_object().test_nil()); + dqueue = new vvp_queue_vec4; + vvp_object_t val (dqueue); + vvp_net_ptr_t ptr (cp->net, 0); + vvp_send_object(ptr, val, thr->wt_context); + } + + assert(dqueue); + dqueue->push_front(value); + return true; +} + /* * This implements the "%set/v