diff --git a/Statement.h b/Statement.h index bc638bc2f..b36ef239d 100644 --- a/Statement.h +++ b/Statement.h @@ -229,7 +229,10 @@ class PCallTask : public Statement { NetProc*elaborate_build_call_(Design*des, NetScope*scope, NetScope*task, NetExpr*use_this) const; - + NetProc*elaborate_sys_task_method_(Design*des, NetScope*scope, + NetNet*net, + perm_string method_name, + const char*sys_task_name) const; bool test_task_calls_ok_(Design*des, NetScope*scope) const; PPackage*package_; diff --git a/design_dump.cc b/design_dump.cc index a280ffffb..5fa1209df 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -30,6 +30,7 @@ # include "discipline.h" # include "netclass.h" # include "netdarray.h" +# include "netqueue.h" # include "netvector.h" # include "ivl_assert.h" # include "PExpr.h" @@ -113,6 +114,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val) case IVL_VT_CLASS: o << "class"; break; + case IVL_VT_QUEUE: + o << "queue"; + break; } return o; } @@ -205,6 +209,12 @@ ostream& netdarray_t::debug_dump(ostream&o) const return o; } +ostream& netqueue_t::debug_dump(ostream&fd) const +{ + fd << "queue of " << *element_type(); + return fd; +} + ostream& netvector_t::debug_dump(ostream&o) const { o << type_ << (signed_? " signed" : " unsigned") << packed_dims_; diff --git a/elaborate.cc b/elaborate.cc index 43e97afea..4cb9c41ec 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3427,6 +3427,38 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const return elaborate_build_call_(des, scope, task, 0); } +/* + * This private method is called to elaborate built-in methods. The + * method_name is the detected name of the built-in method, and the + * sys_task_name is the internal system-task name to use. + */ +NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope, + NetNet*net, + perm_string method_name, + const char*sys_task_name) const +{ + NetESignal*sig = new NetESignal(net); + sig->set_line(*this); + + vectorargv (1 + parms_.size()); + argv[0] = sig; + + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { + PExpr*ex = parms_[idx]; + if (ex != 0) { + argv[idx+1] = elab_sys_task_arg(des, scope, + method_name, + idx, ex); + } else { + argv[idx+1] = 0; + } + } + + NetSTask*sys = new NetSTask(sys_task_name, IVL_SFUNC_AS_TASK_IGNORE, argv); + sys->set_line(*this); + return sys; +} + NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const { pform_name_t use_path = path_; @@ -3453,15 +3485,20 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const // Is this a delete method for dynamic arrays? if (net->darray_type() && method_name=="delete") { - NetESignal*sig = new NetESignal(net); + return elaborate_sys_task_method_(des, scope, net, + method_name, + "$ivl_darray_method$delete"); + } - vector argv (1); - argv[0] = sig; - - NetSTask*sys = new NetSTask("$ivl_darray_method$delete", - IVL_SFUNC_AS_TASK_IGNORE, argv); - sys->set_line(*this); - return sys; + if (net->queue_type()) { + if (method_name=="push_back") + return elaborate_sys_task_method_(des, scope, net, + method_name, + "$ivl_queue_method$push_back"); + if (method_name=="push_front") + return elaborate_sys_task_method_(des, scope, net, + method_name, + "$ivl_queue_method$push_front"); } if (const netclass_t*class_type = net->class_type()) { diff --git a/ivl_target.h b/ivl_target.h index 8541f729e..3fdb61801 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -440,6 +440,7 @@ typedef enum ivl_variable_type_e { IVL_VT_STRING = 5, IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */ IVL_VT_CLASS = 7, /* SystemVerilog class instances */ + IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */ IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */ } ivl_variable_type_t; diff --git a/netlist.cc b/netlist.cc index 5bd211bd7..44f142246 100644 --- a/netlist.cc +++ b/netlist.cc @@ -31,6 +31,7 @@ # include "netdarray.h" # include "netenum.h" # include "netparray.h" +# include "netqueue.h" # include "netstruct.h" # include "netvector.h" # include "ivl_assert.h" @@ -754,6 +755,11 @@ const netdarray_t* NetNet::darray_type(void) const return dynamic_cast (net_type_); } +const netqueue_t* NetNet::queue_type(void) const +{ + return dynamic_cast (net_type_); +} + const netclass_t* NetNet::class_type(void) const { return dynamic_cast (net_type_); diff --git a/netlist.h b/netlist.h index cd724aac7..f277f5840 100644 --- a/netlist.h +++ b/netlist.h @@ -80,6 +80,7 @@ struct enum_type_t; class netclass_t; class netdarray_t; class netparray_t; +class netqueue_t; class netenum_t; class netstruct_t; class netvector_t; @@ -695,6 +696,7 @@ class NetNet : public NetObj, public PortType { const netenum_t*enumeration(void) const; const netstruct_t*struct_type(void) const; const netdarray_t*darray_type(void) const; + const netqueue_t*queue_type(void) const; const netclass_t*class_type(void) const; /* Attach a discipline to the net. */ diff --git a/netqueue.cc b/netqueue.cc index ff68015a1..a850e3b46 100644 --- a/netqueue.cc +++ b/netqueue.cc @@ -31,6 +31,11 @@ netqueue_t::~netqueue_t() { } +ivl_variable_type_t netqueue_t::base_type() const +{ + return IVL_VT_QUEUE; +} + bool netqueue_t::test_compatibility(ivl_type_t that) const { const netqueue_t*that_q = dynamic_cast(that); diff --git a/netqueue.h b/netqueue.h index 7bc126a05..af2de0a1c 100644 --- a/netqueue.h +++ b/netqueue.h @@ -33,6 +33,13 @@ class netqueue_t : public netdarray_t { explicit netqueue_t(ivl_type_t vec); ~netqueue_t(); + // This is the "base_type()" virtual method of the + // nettype_base_t. The ivl_target api expects this to return + // IVL_VT_QUEUE for queues. + ivl_variable_type_t base_type() const; + + std::ostream& debug_dump(std::ostream&) const; + private: bool test_compatibility(ivl_type_t that) const; }; diff --git a/sv_vpi_user.h b/sv_vpi_user.h index 37267ca19..59aea7d55 100644 --- a/sv_vpi_user.h +++ b/sv_vpi_user.h @@ -44,6 +44,11 @@ EXTERN_C_START /********* OBJECT TYPES ***********/ #define vpiPackage 600 +#define vpiArrayType 606 +#define vpiStaticARray 1 +#define vpiDynamicArray 2 +#define vpiAssocArray 3 +#define vpiQueueArray 4 #define vpiLongIntVar 610 #define vpiShortIntVar 611 #define vpiIntVar 612 diff --git a/t-dll.h b/t-dll.h index 530ab46cc..b588d2a8b 100644 --- a/t-dll.h +++ b/t-dll.h @@ -482,7 +482,7 @@ struct ivl_lval_s { * structural context. */ struct ivl_net_const_s { - ivl_variable_type_t type : 3; + ivl_variable_type_t type : 4; unsigned width_ : 24; unsigned signed_ : 1; perm_string file; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 1bcec050e..353952718 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -175,6 +175,9 @@ const char*data_type_string(ivl_variable_type_t vtype) case IVL_VT_CLASS: vt = "class"; break; + case IVL_VT_QUEUE: + vt = "queue"; + break; } return vt; diff --git a/tgt-stub/types.c b/tgt-stub/types.c index 7323f6729..38a6b38c6 100644 --- a/tgt-stub/types.c +++ b/tgt-stub/types.c @@ -30,6 +30,15 @@ static void show_net_type_darray(ivl_type_t net_type) show_net_type(element_type); } +static void show_net_type_queue(ivl_type_t net_type) +{ + /* Dynamic arrays have a single element type. */ + ivl_type_t element_type = ivl_type_element(net_type); + + fprintf(out, "queue of "); + show_net_type(element_type); +} + void show_net_type(ivl_type_t net_type) { ivl_variable_type_t data_type = ivl_type_base(net_type); @@ -57,6 +66,9 @@ void show_net_type(ivl_type_t net_type) case IVL_VT_CLASS: fprintf(out, "class"); break; + case IVL_VT_QUEUE: + show_net_type_queue(net_type); + break; case IVL_VT_VOID: fprintf(out, "void"); break; @@ -112,6 +124,12 @@ void show_type_of_signal(ivl_signal_t net) fprintf(out, "ERROR-DARRAY"); stub_errors += 1; break; + case IVL_VT_QUEUE: + /* The QUEUE type MUST be described by an + ivl_signal_net_type object. */ + fprintf(out, "ERROR-QUEUE"); + stub_errors += 1; + break; case IVL_VT_VOID: fprintf(out, "void"); break; diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 7bfd4e782..a41db91b3 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -503,6 +503,11 @@ static void draw_reg_in_scope(ivl_signal_t sig) vvp_mangle_name(ivl_signal_basename(sig)), ivl_signal_local(sig)? " Local signal" : ""); + } else if (ivl_signal_data_type(sig) == IVL_VT_QUEUE) { + fprintf(vvp_out, "v%p_0 .var/queue \"%s\";%s\n", sig, + vvp_mangle_name(ivl_signal_basename(sig)), + ivl_signal_local(sig)? " Local signal" : ""); + } else if (ivl_signal_data_type(sig) == IVL_VT_STRING) { fprintf(vvp_out, "v%p_0 .var/str \"%s\";%s\n", sig, vvp_mangle_name(ivl_signal_basename(sig)), diff --git a/vvp/compile.h b/vvp/compile.h index 12f8462c4..c385e76f0 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -490,6 +490,7 @@ extern void compile_var_real(char*label, char*name); extern void compile_var_string(char*label, char*name); extern void compile_var_darray(char*label, char*name); extern void compile_var_cobject(char*label, char*name); +extern void compile_var_queue(char*label, char*name); /* * This function is used to create a scope port diff --git a/vvp/lexor.lex b/vvp/lexor.lex index bcfb4d5c4..e197928bf 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -209,6 +209,7 @@ static char* strdupnew(char const *str) ".var" { return K_VAR; } ".var/cobj" { return K_VAR_COBJECT; } ".var/darray" { return K_VAR_DARRAY; } +".var/queue" { return K_VAR_QUEUE; } ".var/real" { return K_VAR_R; } ".var/s" { return K_VAR_S; } ".var/str" { return K_VAR_STR; } diff --git a/vvp/parse.y b/vvp/parse.y index 8b72ff600..2a9753e00 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -96,6 +96,7 @@ static struct __vpiModPath*modpath_dst = 0; %token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP %token K_UFUNC K_UFUNC_E K_UDP K_UDP_C K_UDP_S %token K_VAR K_VAR_COBJECT K_VAR_DARRAY +%token K_VAR_QUEUE %token K_VAR_S K_VAR_STR K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U %token K_vpi_call K_vpi_call_w K_vpi_call_i %token K_vpi_func K_vpi_func_r @@ -748,6 +749,9 @@ statement | T_LABEL K_VAR_DARRAY T_STRING ';' { compile_var_darray($1, $3); } + | T_LABEL K_VAR_QUEUE T_STRING ';' + { compile_var_queue($1, $3); } + | T_LABEL K_VAR_COBJECT T_STRING ';' { compile_var_cobject($1, $3); } diff --git a/vvp/vpi_darray.cc b/vvp/vpi_darray.cc index f6fb39d4a..dc4e0dbd2 100644 --- a/vvp/vpi_darray.cc +++ b/vvp/vpi_darray.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -51,6 +51,8 @@ int __vpiDarrayVar::vpi_get(int code) vvp_darray*aval = val.peek(); switch (code) { + case vpiArrayType: + return vpiDynamicArray; case vpiSize: if (aval == 0) return 0; @@ -77,10 +79,62 @@ vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net) return obj; } +__vpiQueueVar::__vpiQueueVar(__vpiScope*sc, const char*na, vvp_net_t*ne) +: __vpiBaseVar(sc, na, ne) +{ +} + +int __vpiQueueVar::get_type_code(void) const +{ return vpiArrayVar; } + + +int __vpiQueueVar::vpi_get(int code) +{ + vvp_fun_signal_object*fun = dynamic_cast (get_net()->fun); + assert(fun); + vvp_object_t val = fun->get_object(); + vvp_darray*aval = val.peek(); + + switch (code) { + case vpiArrayType: + return vpiQueueArray; + case vpiSize: + if (aval == 0) + return 0; + else + return aval->get_size(); + + default: + return 0; + } +} + +void __vpiQueueVar::vpi_get_value(p_vpi_value val) +{ + val->format = vpiSuppressVal; +} + + +vpiHandle vpip_make_queue_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 __vpiQueueVar*obj = new __vpiQueueVar(scope, use_name, net); + + return obj; +} + #ifdef CHECK_WITH_VALGRIND void darray_delete(vpiHandle item) { class __vpiDarrayVar*obj = dynamic_cast<__vpiDarrayVar*>(item); delete obj; } + +void queue_delete(vpiHandle item) +{ + class __vpiQueueVar*obj = dynamic_cast<__vpiQueueVar*>(item); + delete obj; +} #endif diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 77a81b8b1..07ce78a71 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -544,6 +544,18 @@ class __vpiDarrayVar : public __vpiBaseVar { extern vpiHandle vpip_make_darray_var(const char*name, vvp_net_t*net); +class __vpiQueueVar : public __vpiBaseVar { + + public: + __vpiQueueVar(__vpiScope*scope, const char*name, vvp_net_t*net); + + int get_type_code(void) const; + int vpi_get(int code); + void vpi_get_value(p_vpi_value val); +}; + +extern vpiHandle vpip_make_queue_var(const char*name, vvp_net_t*net); + class __vpiCobjectVar : public __vpiBaseVar { public: diff --git a/vvp/vvp_cleanup.h b/vvp/vvp_cleanup.h index ad67e1f68..47cf6c479 100644 --- a/vvp/vvp_cleanup.h +++ b/vvp/vvp_cleanup.h @@ -49,6 +49,7 @@ extern void class_def_delete(class_type *item); extern void constant_delete(class __vpiHandle *item); extern void contexts_delete(struct __vpiScope *scope); extern void darray_delete(class __vpiHandle *item); +extern void queue_delete(class __vpiHandle *item); extern void enum_delete(class __vpiHandle *item); extern void memory_delete(class __vpiHandle *item); extern void named_event_delete(class __vpiHandle *item); diff --git a/vvp/words.cc b/vvp/words.cc index 9618cc5f4..a09e880d1 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -124,6 +124,29 @@ void compile_var_darray(char*label, char*name) delete[] name; } +void compile_var_queue(char*label, char*name) +{ + vvp_net_t*net = new vvp_net_t; + + if (vpip_peek_current_scope()->is_automatic) { + vvp_fun_signal_object_aa*tmp = new vvp_fun_signal_object_aa; + net->fil = tmp; + net->fun = tmp; + } else { + net->fil = 0; + net->fun = new vvp_fun_signal_object_sa; + } + + define_functor_symbol(label, net); + + vpiHandle obj = vpip_make_queue_var(name, net); + compile_vpi_symbol(label, obj); + + vpip_attach_to_current_scope(obj); + free(label); + delete[] name; +} + void compile_var_cobject(char*label, char*name) { vvp_net_t*net = new vvp_net_t;