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.
This commit is contained in:
Stephen Williams 2012-06-17 18:22:50 -07:00
parent ea420d94ac
commit d48362b861
30 changed files with 603 additions and 13 deletions

View File

@ -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 File

@ -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 File

@ -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 File

@ -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

37
pform_string_type.cc Normal file
View File

@ -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 File

@ -23,3 +23,7 @@
data_type_t::~data_type_t()
{
}
string_type_t::~string_type_t()
{
}

View File

@ -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 File

@ -48,6 +48,7 @@ EXTERN_C_START
#define vpiIntVar 612
#define vpiByteVar 614
#define vpiLogicVar vpiReg
#define vpiStringVar 616
#define vpiBitVar 620
/********* TYPESPECS *************/

View File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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

68
vvp/vpi_string.cc Normal file
View File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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.