Browse files

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.
  • Loading branch information...
1 parent ea420d9 commit d48362b861b76f13de5548227dc5f7a2719e68b0 @steveicarus committed Jun 17, 2012
View
4 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 \
View
5 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;
}
;
View
5 pform.cc
@@ -2829,6 +2829,11 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
return;
}
+ if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
+ pform_set_string_type(string_type, names, attr);
+ return;
+ }
+
assert(0);
}
View
2 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<perm_string>*names, std::list<named_pexpr_t>*attr);
+extern void pform_set_string_type(string_type_t*string_type, std::list<perm_string>*names, std::list<named_pexpr_t>*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
View
37 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<named_pexpr_t>*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<perm_string>*names, list<named_pexpr_t>*attr)
+{
+ for (list<perm_string>::iterator cur = names->begin()
+ ; cur != names->end() ; ++ cur) {
+ pform_set_string_type(string_type, *cur, attr);
+ }
+}
+
View
4 pform_types.cc
@@ -23,3 +23,7 @@
data_type_t::~data_type_t()
{
}
+
+string_type_t::~string_type_t()
+{
+}
View
5 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) { }
View
1 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 *************/
View
4 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;
View
32 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);
}
View
5 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",
View
11 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;
View
2 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
View
1 vvp/README.txt
@@ -284,6 +284,7 @@ general syntax of a variable is:
<label> .var/2s "name", <msb> <lsb>; Signed bool/bit variable
<label> .var/real "name", <msb>, <lsb>; real variable
<label> .var/i "name", <msb>, <lsb>; vpiIntegerVar variable
+ <label> .var/str "name"; vpiStringVar variable
The "name" is the declared base name of the original variable, for the
sake of VPI code that might access it. The variable is placed in the
View
2 vvp/codes.h
@@ -148,6 +148,7 @@ extern bool of_PAD(vthread_t thr, vvp_code_t code);
extern bool of_POW(vthread_t thr, vvp_code_t code);
extern bool of_POW_S(vthread_t thr, vvp_code_t code);
extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
+extern bool of_PUSHV_STR(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
@@ -160,6 +161,7 @@ extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
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_STR(vthread_t thr, vvp_code_t code);
extern bool of_SUB(vthread_t thr, vvp_code_t code);
extern bool of_SUB_WR(vthread_t thr, vvp_code_t code);
extern bool of_SUBI(vthread_t thr, vvp_code_t code);
View
7 vvp/compile.cc
@@ -194,6 +194,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pow/s", of_POW_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pow/wr", of_POW_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
+ { "%pushv/str", of_PUSHV_STR, 2, {OA_BIT1,OA_BIT2, OA_NONE} },
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
@@ -205,6 +206,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
+ { "%store/str",of_STORE_STR,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%sub/wr", of_SUB_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@@ -310,6 +312,11 @@ vvp_net_t* vvp_net_lookup(const char*label)
return sig->net;
}
+ case vpiStringVar: {
+ __vpiStringVar*sig = dynamic_cast<__vpiStringVar*>(vpi);
+ return sig->get_net();
+ }
+
case vpiNamedEvent: {
__vpiNamedEvent*tmp = dynamic_cast<__vpiNamedEvent*>(vpi);
return tmp->funct;
View
4 vvp/compile.h
@@ -455,8 +455,8 @@ extern void compile_variable(char*label, char*name,
int msb, int lsb, int vpi_type_code,
bool signed_flag, bool local_flag);
-extern void compile_var_real(char*label, char*name,
- int msb, int lsb);
+extern void compile_var_real(char*label, char*name);
+extern void compile_var_string(char*label, char*name);
/*
* This function is used to create a scope port
View
1 vvp/lexor.lex
@@ -197,6 +197,7 @@ static char* strdupnew(char const *str)
".var" { return K_VAR; }
".var/real" { return K_VAR_R; }
".var/s" { return K_VAR_S; }
+".var/str" { return K_VAR_STR; }
".var/i" { return K_VAR_I; /* integer */ }
".var/2s" { return K_VAR_2S; /* byte/shortint/int/longint signed */ }
".var/2u" { return K_VAR_2U; /* byte/shortint/int/longint unsigned */ }
View
8 vvp/opcodes.txt
@@ -750,6 +750,9 @@ replaces the left operand.
This opcode raises <bit-l> (real) to the power of <bit-r> (real). The
result replaces the left operand.
+* %pushv/str <src>, <wid>
+
+Convert a vector to a string and push the string to the string stack.
* %release/net <functor-label>, <base>, <width>
* %release/reg <functor-label>, <base>, <width>
@@ -849,6 +852,11 @@ top bits. %shiftr/s/i0 is a signed shift, so the value is sign-extended.
For a negative shift %shiftr/i0 will pad the value with 'bx.
+* %store/str <var-label>
+
+This pops the top of the string stack and writes it to the string
+varible.
+
* %sub <bit-l>, <bit-r>, <wid>
This instruction arithmetically subtracts the right vector out of the
View
7 vvp/parse.y
@@ -91,7 +91,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
%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_S K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
+%token K_VAR 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
%token K_disable K_fork
@@ -697,7 +697,10 @@ statement
{ compile_variable($1, $4, $6, $7, vpiIntVar, false, $3); }
| T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';'
- { compile_var_real($1, $3, $5, $6); }
+ { compile_var_real($1, $3); }
+
+ | T_LABEL K_VAR_STR T_STRING ';'
+ { compile_var_string($1, $3); }
/* Net statements are similar to .var statements, except that they
declare nets, and they have an input list. */
View
16 vvp/vpi_callback.cc
@@ -794,6 +794,16 @@ void vvp_wire_real::get_signal_value(struct t_vpi_value*vp)
real_signal_value(vp, real_value());
}
+void vvp_fun_signal_string_aa::get_signal_value(struct t_vpi_value*vp)
+{
+ assert(0);
+}
+#if 0
+void vvp_wire_string::get_signal_value(struct t_vpi_value*vp)
+{
+ assert(0);
+}
+#endif
void vvp_wire_vec4::get_value(struct t_vpi_value*val)
{
get_signal_value(val);
@@ -808,3 +818,9 @@ void vvp_wire_real::get_value(struct t_vpi_value*val)
{
get_signal_value(val);
}
+#if 0
+void vvp_wire_string::get_value(struct t_vpi_value*val)
+{
+ assert(0);
+}
+#endif
View
5 vvp/vpi_priv.cc
@@ -902,6 +902,11 @@ void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
assert(expr);
assert(vp);
+ // Never bother with suppressed values. All the derived
+ // classes can ignore this type.
+ if (vp->format == vpiSuppressVal)
+ return;
+
expr->vpi_get_value(vp);
if (vpi_trace) switch (vp->format) {
View
18 vvp/vpi_priv.h
@@ -24,6 +24,7 @@
# include "config.h"
# include <set>
+# include <string>
/*
* Added to use some "vvp_fun_modpath_src"
@@ -477,6 +478,23 @@ struct __vpiRealVar : public __vpiHandle {
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
+class __vpiStringVar : public __vpiHandle {
+
+ public:
+ __vpiStringVar(__vpiScope*scope, const char*name, vvp_net_t*net);
+
+ int get_type_code(void) const;
+ void vpi_get_value(p_vpi_value val);
+
+ inline vvp_net_t* get_net() const { return net_; }
+
+ private:
+ struct __vpiScope* scope_;
+ const char*name_;
+ vvp_net_t*net_;
+};
+
+extern vpiHandle vpip_make_string_var(const char*name, vvp_net_t*net);
/*
* When a loaded VPI module announces a system task/function, one
View
68 vvp/vpi_string.cc
@@ -0,0 +1,68 @@
+/*
+ * 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 "compile.h"
+# include "vpi_priv.h"
+# include "vvp_net_sig.h"
+# include "schedule.h"
+#ifdef CHECK_WITH_VALGRIND
+# include "vvp_cleanup.h"
+#endif
+# include <cstdio>
+# include <cstdlib>
+# include <cstring>
+# include <cassert>
+# include "ivl_alloc.h"
+
+using namespace std;
+
+__vpiStringVar::__vpiStringVar(__vpiScope*sc, const char*na, vvp_net_t*ne)
+: scope_(sc), name_(na), net_(ne)
+{
+}
+
+int __vpiStringVar::get_type_code(void) const
+{ return vpiStringVar; }
+
+void __vpiStringVar::vpi_get_value(p_vpi_value val)
+{
+ vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (net_->fun);
+ assert(fun);
+ string str = fun->get_string();
+
+ if (val->format == vpiStringVal || val->format == vpiObjTypeVal) {
+ char*rbuf = need_result_buf(str.size()+1, RBUF_VAL);
+ strcpy(rbuf, str.c_str());
+ val->format = vpiStringVal;
+ val->value.str = rbuf;
+ return;
+ }
+
+ val->format = vpiSuppressVal;
+}
+
+vpiHandle vpip_make_string_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;
+
+ struct __vpiStringVar*obj = new __vpiStringVar(scope, use_name, net);
+
+ return obj;
+}
View
58 vvp/vthread.cc
@@ -99,6 +99,13 @@ struct vthread_s {
double w_real;
} words[16];
+ /* Strings are operated on using a forth-like operator
+ set. Items at the top of the stack (back()) are the objects
+ operated on except for special cases. New objects are
+ pushed onto the top (back()) and pulled from the top
+ (back()) only. */
+ vector<string> stack_str;
+
/* My parent sets this when it wants me to wake it up. */
unsigned i_am_joining :1;
unsigned i_have_ended :1;
@@ -4141,6 +4148,41 @@ bool of_POW_WR(vthread_t thr, vvp_code_t cp)
return true;
}
+bool of_PUSHV_STR(vthread_t thr, vvp_code_t cp)
+{
+ unsigned src = cp->bit_idx[0];
+ unsigned wid = cp->bit_idx[1];
+
+ vvp_vector4_t vec = vthread_bits_to_vector(thr, src, wid);
+ size_t slen = (vec.size() + 7)/8;
+ vector<char>buf;
+ buf.reserve(slen);
+
+ for (size_t idx = 0 ; idx < vec.size() ; idx += 8) {
+ char tmp = 0;
+ size_t trans = 8;
+ if (idx+trans > vec.size())
+ trans = vec.size() - idx;
+
+ for (size_t bdx = 0 ; bdx < trans ; bdx += 1) {
+ if (vec.value(idx+bdx) == BIT4_1)
+ tmp |= 1 << bdx;
+ }
+
+ if (tmp != 0)
+ buf.push_back(tmp);
+ }
+
+ string val;
+ for (vector<char>::reverse_iterator cur = buf.rbegin()
+ ; cur != buf.rend() ; ++cur) {
+ val.push_back(*cur);
+ }
+
+ thr->stack_str.push_back(val);
+ return true;
+}
+
/*
* These implement the %release/net and %release/reg instructions. The
* %release/net instruction applies to a net kind of functor by
@@ -4478,6 +4520,22 @@ bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
return true;
}
+bool of_STORE_STR(vthread_t thr, vvp_code_t cp)
+{
+ /* set the value into port 0 of the destination. */
+ vvp_net_ptr_t ptr (cp->net, 0);
+
+ assert(!thr->stack_str.empty());
+
+ string val= thr->stack_str.back();
+ thr->stack_str.pop_back();
+
+ vvp_send_string(ptr, val, thr->wt_context);
+
+ return true;
+}
+
+
bool of_SUB(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
View
9 vvp/vvp_net.cc
@@ -1432,7 +1432,7 @@ void vvp_vector4_t::set_to_x()
}
}
-char* vvp_vector4_t::as_string(char*buf, size_t buf_len)
+char* vvp_vector4_t::as_string(char*buf, size_t buf_len) const
{
char*res = buf;
*buf++ = 'C';
@@ -2956,6 +2956,13 @@ void vvp_net_fun_t::recv_long_pv(vvp_net_ptr_t, long, unsigned, unsigned)
assert(0);
}
+void vvp_net_fun_t::recv_string(vvp_net_ptr_t, const std::string&bit, vvp_context_t)
+{
+ fprintf(stderr, "internal error: %s: recv_string(%s) not implemented\n",
+ typeid(*this).name(), bit.c_str());
+ assert(0);
+}
+
void vvp_net_fun_t::force_flag(void)
{
}
View
24 vvp/vvp_net.h
@@ -261,7 +261,7 @@ class vvp_vector4_t {
void set_to_x();
// Display the value into the buf as a string.
- char*as_string(char*buf, size_t buf_len);
+ char*as_string(char*buf, size_t buf_len) const;
void invert();
vvp_vector4_t& operator &= (const vvp_vector4_t&that);
@@ -1082,6 +1082,7 @@ class vvp_net_t {
void send_vec8(const vvp_vector8_t&val);
void send_real(double val, vvp_context_t context);
void send_long(long val);
+ void send_string(const std::string&val, vvp_context_t context);
void send_vec4_pv(const vvp_vector4_t&val,
unsigned base, unsigned wid, unsigned vwid,
@@ -1156,6 +1157,8 @@ class vvp_net_fun_t {
virtual void recv_real(vvp_net_ptr_t port, double bit,
vvp_context_t context);
virtual void recv_long(vvp_net_ptr_t port, long bit);
+ virtual void recv_string(vvp_net_ptr_t port, const std::string&bit,
+ vvp_context_t context);
// Part select variants of above
virtual void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
@@ -1514,6 +1517,18 @@ extern void vvp_send_long(vvp_net_ptr_t ptr, long val);
extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
unsigned base, unsigned width);
+inline void vvp_send_string(vvp_net_ptr_t ptr, const std::string&val, vvp_context_t context)
+{
+ while (vvp_net_t*cur = ptr.ptr()) {
+ vvp_net_ptr_t next = cur->port[ptr.port()];
+
+ if (cur->fun)
+ cur->fun->recv_string(ptr, val, context);
+
+ ptr = next;
+ }
+}
+
/*
* Part-vector versions of above functions. This function uses the
* corresponding recv_vec4_pv method in the vvp_net_fun_t functor to
@@ -1654,6 +1669,13 @@ inline void vvp_net_t::send_real(double val, vvp_context_t context)
}
+inline void vvp_net_t::send_string(const std::string&val, vvp_context_t context)
+{
+ assert(!fil);
+ vvp_send_string(out_, val, context);
+}
+
+
inline bool vvp_net_fil_t::test_force_mask(unsigned bit) const
{
if (bit >= force_mask_.size())
View
144 vvp/vvp_net_sig.cc
@@ -22,6 +22,7 @@
# include "vvp_net_sig.h"
# include "statistics.h"
# include "vpi_priv.h"
+# include <vector>
# include <cassert>
#ifdef CHECK_WITH_VALGRIND
# include <valgrind/memcheck.h>
@@ -30,6 +31,8 @@
# include <iostream>
+using namespace std;
+
/*
* The filter_mask_ method takes as an input the value to propagate,
* the mask of what is being forced, and returns a propagation
@@ -585,6 +588,83 @@ void vvp_fun_signal_real_aa::operator delete(void*)
assert(0);
}
+
+vvp_fun_signal_string_sa::vvp_fun_signal_string_sa()
+{
+}
+
+void vvp_fun_signal_string_sa::recv_string(vvp_net_ptr_t ptr, const std::string&bit,
+ vvp_context_t)
+{
+ assert(ptr.port() == 0);
+
+ if (needs_init_ || value_ != bit) {
+ value_ = bit;
+ needs_init_ = false;
+
+ ptr.ptr()->send_string(bit, 0);
+ }
+}
+
+vvp_fun_signal_string_aa::vvp_fun_signal_string_aa()
+{
+ context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
+}
+
+vvp_fun_signal_string_aa::~vvp_fun_signal_string_aa()
+{
+ assert(0);
+}
+
+void vvp_fun_signal_string_aa::alloc_instance(vvp_context_t)
+{
+ assert(0);
+}
+
+void vvp_fun_signal_string_aa::reset_instance(vvp_context_t)
+{
+ assert(0);
+}
+
+unsigned vvp_fun_signal_string_aa::value_size() const
+{
+ assert(0);
+ return 1;
+}
+
+vvp_bit4_t vvp_fun_signal_string_aa::value(unsigned) const
+{
+ assert(0);
+ return BIT4_X;
+}
+
+vvp_scalar_t vvp_fun_signal_string_aa::scalar_value(unsigned) const
+{
+ assert(0);
+ return vvp_scalar_t();
+}
+
+void vvp_fun_signal_string_aa::vec4_value(vvp_vector4_t&) const
+{
+ assert(0);
+}
+
+double vvp_fun_signal_string_aa::real_value() const
+{
+ assert(0);
+ return 0.0;
+}
+
+void* vvp_fun_signal_string_aa::operator new(std::size_t size)
+{
+ return vvp_net_fun_t::heap_.alloc(size);
+}
+
+void vvp_fun_signal_string_aa::operator delete(void*)
+{
+ assert(0);
+}
+
vvp_fun_force::vvp_fun_force()
{
}
@@ -1058,3 +1138,67 @@ double vvp_wire_real::real_value() const
else
return bit_;
}
+
+#if 0
+vvp_wire_string::vvp_wire_string()
+{
+}
+
+unsigned vvp_wire_string::filter_size() const
+{
+ assert(0);
+ return 0;
+}
+
+void vvp_wire_string::force_fil_vec4(const vvp_vector4_t&, vvp_vector2_t)
+{
+ assert(0);
+}
+void vvp_wire_string::force_fil_vec8(const vvp_vector8_t&, vvp_vector2_t)
+{
+ assert(0);
+}
+void vvp_wire_string::force_fil_real(double, vvp_vector2_t)
+{
+ assert(0);
+}
+
+void vvp_wire_string::release(vvp_net_ptr_t ptr, bool net_flag)
+{
+ assert(0);
+}
+
+void vvp_wire_string::release_pv(vvp_net_ptr_t, unsigned, unsigned, bool)
+{
+ assert(0);
+}
+
+unsigned vvp_wire_string::value_size() const
+{
+ assert(0);
+ return 1;
+}
+
+vvp_bit4_t vvp_wire_string::value(unsigned) const
+{
+ assert(0);
+ return BIT4_X;
+}
+
+vvp_scalar_t vvp_wire_string::scalar_value(unsigned) const
+{
+ assert(0);
+ return vvp_scalar_t();
+}
+
+void vvp_wire_string::vec4_value(vvp_vector4_t&) const
+{
+ assert(0);
+}
+
+double vvp_wire_string::real_value() const
+{
+ assert(0);
+ return 0.0;
+}
+#endif
View
88 vvp/vvp_net_sig.h
@@ -22,6 +22,7 @@
# include "config.h"
# include "vpi_user.h"
# include "vvp_net.h"
+# include <string>
# include <cstddef>
# include <cstdlib>
# include <cstring>
@@ -261,6 +262,63 @@ class vvp_fun_signal_real_aa : public vvp_fun_signal_real, public automatic_sign
};
+class vvp_fun_signal_string : public vvp_fun_signal_base {
+
+ public:
+ explicit vvp_fun_signal_string() {};
+
+ unsigned size() const { return 1; }
+
+ inline const std::string& get_string() const { return value_; }
+
+ protected:
+ std::string value_;
+};
+
+/*
+ * Statically allocated vvp_fun_signal_string.
+ */
+class vvp_fun_signal_string_sa : public vvp_fun_signal_string {
+
+ public:
+ explicit vvp_fun_signal_string_sa();
+
+ void recv_string(vvp_net_ptr_t port, const std::string&bit,
+ vvp_context_t context);
+};
+
+/*
+ * Automatically allocated vvp_fun_signal_real.
+ */
+class vvp_fun_signal_string_aa : public vvp_fun_signal_string, public automatic_signal_base, public automatic_hooks_s {
+
+ public:
+ explicit vvp_fun_signal_string_aa();
+ ~vvp_fun_signal_string_aa();
+
+ void alloc_instance(vvp_context_t context);
+ void reset_instance(vvp_context_t context);
+#ifdef CHECK_WITH_VALGRIND
+ void free_instance(vvp_context_t context);
+#endif
+
+ // Get information about the vector value.
+ unsigned value_size() const;
+ vvp_bit4_t value(unsigned idx) const;
+ vvp_scalar_t scalar_value(unsigned idx) const;
+ void vec4_value(vvp_vector4_t&) const;
+ double real_value() const;
+ void get_signal_value(struct t_vpi_value*vp);
+
+ public: // These objects are only permallocated.
+ static void* operator new(std::size_t size);
+ static void operator delete(void*obj);
+
+ private:
+ unsigned context_idx_;
+};
+
+
/* vvp_wire
* The vvp_wire is different from vvp_variable objects in that it
* exists only as a filter. The vvp_wire class tree is for
@@ -388,4 +446,34 @@ class vvp_wire_real : public vvp_wire_base {
double force_;
};
+#if 0
+class vvp_wire_string : public vvp_wire_base {
+
+ public:
+ explicit vvp_wire_string(void);
+
+ // Abstract methods from vvp_vpi_callback
+ void get_value(struct t_vpi_value*value);
+ // Abstract methods from vvp_net_fil_t
+ unsigned filter_size() const;
+ void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
+ void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
+ void force_fil_real(double val, vvp_vector2_t mask);
+ void release(vvp_net_ptr_t ptr, bool net_flag);
+ void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag);
+
+ // Implementation of vvp_signal_value methods
+ unsigned value_size() const;
+ vvp_bit4_t value(unsigned idx) const;
+ vvp_scalar_t scalar_value(unsigned idx) const;
+ void vec4_value(vvp_vector4_t&) const;
+ double real_value() const;
+
+ void get_signal_value(struct t_vpi_value*vp);
+
+ private:
+ std::string value_;
+};
+#endif
+
#endif
View
39 vvp/words.cc
@@ -65,9 +65,8 @@ static void __compile_var_real(char*label, char*name,
delete[] name;
}
-void compile_var_real(char*label, char*name, int msb, int lsb)
+void compile_var_real(char*label, char*name)
{
- assert(msb == 0 && lsb == 0);
__compile_var_real(label, name, 0, 0);
}
@@ -79,6 +78,42 @@ void compile_varw_real(char*label, vvp_array_t array,
__compile_var_real(label, 0, array, addr);
}
+static void __compile_var_string(char*label, char*name,
+ vvp_array_t array, unsigned long array_addr)
+{
+ vvp_net_t*net = new vvp_net_t;
+
+ if (vpip_peek_current_scope()->is_automatic) {
+ vvp_fun_signal_string_aa*tmp = new vvp_fun_signal_string_aa;
+ net->fil = tmp;
+ net->fun = tmp;
+ } else {
+ net->fil = 0;
+ net->fun = new vvp_fun_signal_string_sa;
+ }
+
+ define_functor_symbol(label, net);
+
+ vpiHandle obj = vpip_make_string_var(name, net);
+ compile_vpi_symbol(label, obj);
+
+ if (name) {
+ assert(!array);
+ vpip_attach_to_current_scope(obj);
+ }
+ if (array) {
+ assert(!name);
+ array_attach_word(array, array_addr, obj);
+ }
+ delete[]label;
+ delete[] name;
+}
+
+void compile_var_string(char*label, char*name)
+{
+ __compile_var_string(label, name, 0, 0);
+}
+
/*
* A variable is a special functor, so we allocate that functor and
* write the label into the symbol table.

0 comments on commit d48362b

Please sign in to comment.