From d48362b861b76f13de5548227dc5f7a2719e68b0 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 17 Jun 2012 18:22:50 -0700 Subject: [PATCH] First pass at getting strings to work. In vvp, create the .var/str variable for representing strings, and handle strings in the $display system task. Add to vvp threads the concept of a stack of strings. This is going to be how complex objects are to me handled in the future: forth-like operation stacks. Also add the first two instructions to minimally get strings to work. In the parser, handle the variable declaration and make it available to the ivl_target.h code generator. The vvp code generator can use this information to generate the code for new vvp support. --- Makefile.in | 4 +- parse.y | 5 +- pform.cc | 5 ++ pform.h | 2 + pform_string_type.cc | 37 +++++++++++ pform_types.cc | 4 ++ pform_types.h | 5 ++ sv_vpi_user.h | 1 + tgt-stub/stub.c | 4 ++ tgt-vvp/stmt_assign.c | 32 ++++++++++ tgt-vvp/vvp_scope.c | 5 ++ vpi/sys_display.c | 11 ++++ vvp/Makefile.in | 2 +- vvp/README.txt | 1 + vvp/codes.h | 2 + vvp/compile.cc | 7 ++ vvp/compile.h | 4 +- vvp/lexor.lex | 1 + vvp/opcodes.txt | 8 +++ vvp/parse.y | 7 +- vvp/vpi_callback.cc | 16 +++++ vvp/vpi_priv.cc | 5 ++ vvp/vpi_priv.h | 18 ++++++ vvp/vpi_string.cc | 68 ++++++++++++++++++++ vvp/vthread.cc | 58 +++++++++++++++++ vvp/vvp_net.cc | 9 ++- vvp/vvp_net.h | 24 ++++++- vvp/vvp_net_sig.cc | 144 ++++++++++++++++++++++++++++++++++++++++++ vvp/vvp_net_sig.h | 88 ++++++++++++++++++++++++++ vvp/words.cc | 39 +++++++++++- 30 files changed, 603 insertions(+), 13 deletions(-) create mode 100644 pform_string_type.cc create mode 100644 vvp/vpi_string.cc diff --git a/Makefile.in b/Makefile.in index 26f2f13ef..ee1254316 100644 --- a/Makefile.in +++ b/Makefile.in @@ -113,8 +113,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ net_link.o net_modulo.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \ - pform_disciplines.o pform_dump.o pform_pclass.o pform_struct_type.o \ - pform_types.o \ + pform_disciplines.o pform_dump.o pform_pclass.o pform_string_type.o \ + pform_struct_type.o pform_types.o \ symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \ Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \ PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \ diff --git a/parse.y b/parse.y index 0a0a1b744..39d97c5c5 100644 --- a/parse.y +++ b/parse.y @@ -898,8 +898,9 @@ data_type /* IEEE1800-2005: A.2.2.1 */ else $$ = $1; } | K_string - { yyerror(@1, "sorry: String data type not supported."); - $$ = 0; + { string_type_t*tmp = new string_type_t; + FILE_NAME(tmp, @1); + $$ = tmp; } ; diff --git a/pform.cc b/pform.cc index ee878a868..9223fe0eb 100644 --- a/pform.cc +++ b/pform.cc @@ -2829,6 +2829,11 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { + pform_set_string_type(string_type, names, attr); + return; + } + assert(0); } diff --git a/pform.h b/pform.h index 23d45c558..12101259a 100644 --- a/pform.h +++ b/pform.h @@ -310,6 +310,8 @@ extern void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list< extern void pform_set_struct_type(struct_type_t*struct_type, std::list*names, std::list*attr); +extern void pform_set_string_type(string_type_t*string_type, std::list*names, std::list*attr); + /* pform_set_attrib and pform_set_type_attrib exist to support the $attribute syntax, which can only set string values to attributes. The functions keep the value strings that are diff --git a/pform_string_type.cc b/pform_string_type.cc new file mode 100644 index 000000000..c7f626d63 --- /dev/null +++ b/pform_string_type.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012 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 + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "pform.h" +# include "parse_misc.h" +# include "ivl_assert.h" + +static void pform_set_string_type(string_type_t*string_type, perm_string name, list*attr) +{ + PWire*net = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_STRING); + pform_bind_attributes(net->attributes, attr, true); +} + +void pform_set_string_type(string_type_t*string_type, list*names, list*attr) +{ + for (list::iterator cur = names->begin() + ; cur != names->end() ; ++ cur) { + pform_set_string_type(string_type, *cur, attr); + } +} + diff --git a/pform_types.cc b/pform_types.cc index 9a85b5b7e..7650ec36e 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -23,3 +23,7 @@ data_type_t::~data_type_t() { } + +string_type_t::~string_type_t() +{ +} diff --git a/pform_types.h b/pform_types.h index cfd56e5c3..b55d31013 100644 --- a/pform_types.h +++ b/pform_types.h @@ -156,6 +156,11 @@ struct real_type_t : public data_type_t { type_t type_code; }; +struct string_type_t : public data_type_t { + inline explicit string_type_t() { } + ~string_type_t(); +}; + struct class_type_t : public data_type_t { inline explicit class_type_t(perm_string n) : name(n) { } diff --git a/sv_vpi_user.h b/sv_vpi_user.h index 606f7f73f..0bc5ca22f 100644 --- a/sv_vpi_user.h +++ b/sv_vpi_user.h @@ -48,6 +48,7 @@ EXTERN_C_START #define vpiIntVar 612 #define vpiByteVar 614 #define vpiLogicVar vpiReg +#define vpiStringVar 616 #define vpiBitVar 620 /********* TYPESPECS *************/ diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 3cddd2ab6..4180a977e 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1274,6 +1274,10 @@ static void show_signal(ivl_signal_t net) data_type = "real"; break; + case IVL_VT_STRING: + data_type = "string"; + break; + default: data_type = "?data?"; break; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 13f2e2391..242fef33d 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -731,6 +731,34 @@ static int show_stmt_assign_sig_real(ivl_statement_t net) return 0; } +static int show_stmt_assign_sig_string(ivl_statement_t net) +{ + struct vector_info res; + ivl_lval_t lval = ivl_stmt_lval(net, 0); + ivl_expr_t rval = ivl_stmt_rval(net); + ivl_signal_t var; + assert(ivl_stmt_lvals(net) == 1); + assert(ivl_stmt_opcode(net) == 0); + + var = ivl_lval_sig(lval); + + switch (ivl_expr_value(rval)) { + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + res = draw_eval_expr(rval, 0); + fprintf(vvp_out, " %%pushv/str %u, %u;\n", + res.base, res.wid); + fprintf(vvp_out, " %%store/str v%p_0;\n", var); + if (res.base > 0) + clr_vector(res); + break; + default: + assert(0); + break; + } + + return 0; +} int show_stmt_assign(ivl_statement_t net) { @@ -746,5 +774,9 @@ int show_stmt_assign(ivl_statement_t net) return show_stmt_assign_sig_real(net); } + if (sig && (ivl_signal_data_type(sig) == IVL_VT_STRING)) { + return show_stmt_assign_sig_string(net); + } + return show_stmt_assign_vector(net); } diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index c927ed932..554403436 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -502,6 +502,11 @@ static void draw_reg_in_scope(ivl_signal_t sig) vvp_mangle_name(ivl_signal_basename(sig)), swapped ? first: last, swapped ? last : first, msb, lsb); + } 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)), + ivl_signal_local(sig)? " Local signal" : ""); + } else { fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n", diff --git a/vpi/sys_display.c b/vpi/sys_display.c index d5fdb4234..1dfe1b19e 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -964,6 +964,16 @@ static char *get_display(unsigned int *rtnsz, const struct strobe_cb_info *info) memcpy(rtn+size-1, buf, width); break; + /* Process string variables like string constants: interpret + the contained strings like format strings. */ + case vpiStringVar: + value.format = vpiStringVal; + vpi_get_value(item, &value); + width = strlen(value.value.str); + rtn = realloc(rtn, (size+width)*sizeof(char)); + memcpy(rtn+size-1, value.value.str, width); + break; + case vpiSysFuncCall: func_name = vpi_get_str(vpiName, item); if (strcmp(func_name, "$time") == 0) { @@ -1071,6 +1081,7 @@ static int sys_check_args(vpiHandle callh, vpiHandle argv, const PLI_BYTE8*name, case vpiLongIntVar: case vpiTimeVar: case vpiRealVar: + case vpiStringVar: case vpiSysFuncCall: break; diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 4f3a59a80..0aed0f35b 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -67,7 +67,7 @@ dllib=@DLLIB@ MDIR1 = -DMODULE_DIR1='"$(libdir)/ivl$(suffix)"' V = vpi_modules.o vpi_callback.o vpi_const.o vpi_event.o vpi_iter.o vpi_mcd.o \ - vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_tasks.o vpi_time.o \ + vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_string.o vpi_tasks.o vpi_time.o \ vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \ vpip_to_dec.o vpip_format.o vvp_vpi.o diff --git a/vvp/README.txt b/vvp/README.txt index a45854ded..329902f6a 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -284,6 +284,7 @@ general syntax of a variable is: