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:
parent
ea420d94ac
commit
d48362b861
|
|
@ -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_link.o net_modulo.o \
|
||||||
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.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 \
|
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_disciplines.o pform_dump.o pform_pclass.o pform_string_type.o \
|
||||||
pform_types.o \
|
pform_struct_type.o pform_types.o \
|
||||||
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.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 \
|
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 \
|
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
||||||
|
|
|
||||||
5
parse.y
5
parse.y
|
|
@ -898,8 +898,9 @@ data_type /* IEEE1800-2005: A.2.2.1 */
|
||||||
else $$ = $1;
|
else $$ = $1;
|
||||||
}
|
}
|
||||||
| K_string
|
| K_string
|
||||||
{ yyerror(@1, "sorry: String data type not supported.");
|
{ string_type_t*tmp = new string_type_t;
|
||||||
$$ = 0;
|
FILE_NAME(tmp, @1);
|
||||||
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
5
pform.cc
5
pform.cc
|
|
@ -2829,6 +2829,11 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
|
||||||
return;
|
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);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2
pform.h
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_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
|
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||||
$attribute syntax, which can only set string values to
|
$attribute syntax, which can only set string values to
|
||||||
attributes. The functions keep the value strings that are
|
attributes. The functions keep the value strings that are
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -23,3 +23,7 @@
|
||||||
data_type_t::~data_type_t()
|
data_type_t::~data_type_t()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string_type_t::~string_type_t()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,11 @@ struct real_type_t : public data_type_t {
|
||||||
type_t type_code;
|
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 {
|
struct class_type_t : public data_type_t {
|
||||||
inline explicit class_type_t(perm_string n)
|
inline explicit class_type_t(perm_string n)
|
||||||
: name(n) { }
|
: name(n) { }
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ EXTERN_C_START
|
||||||
#define vpiIntVar 612
|
#define vpiIntVar 612
|
||||||
#define vpiByteVar 614
|
#define vpiByteVar 614
|
||||||
#define vpiLogicVar vpiReg
|
#define vpiLogicVar vpiReg
|
||||||
|
#define vpiStringVar 616
|
||||||
#define vpiBitVar 620
|
#define vpiBitVar 620
|
||||||
|
|
||||||
/********* TYPESPECS *************/
|
/********* TYPESPECS *************/
|
||||||
|
|
|
||||||
|
|
@ -1274,6 +1274,10 @@ static void show_signal(ivl_signal_t net)
|
||||||
data_type = "real";
|
data_type = "real";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IVL_VT_STRING:
|
||||||
|
data_type = "string";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
data_type = "?data?";
|
data_type = "?data?";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -731,6 +731,34 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
return 0;
|
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)
|
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);
|
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);
|
return show_stmt_assign_vector(net);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -502,6 +502,11 @@ static void draw_reg_in_scope(ivl_signal_t sig)
|
||||||
vvp_mangle_name(ivl_signal_basename(sig)),
|
vvp_mangle_name(ivl_signal_basename(sig)),
|
||||||
swapped ? first: last, swapped ? last : first, msb, lsb);
|
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 {
|
} else {
|
||||||
|
|
||||||
fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",
|
fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",
|
||||||
|
|
|
||||||
|
|
@ -964,6 +964,16 @@ static char *get_display(unsigned int *rtnsz, const struct strobe_cb_info *info)
|
||||||
memcpy(rtn+size-1, buf, width);
|
memcpy(rtn+size-1, buf, width);
|
||||||
break;
|
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:
|
case vpiSysFuncCall:
|
||||||
func_name = vpi_get_str(vpiName, item);
|
func_name = vpi_get_str(vpiName, item);
|
||||||
if (strcmp(func_name, "$time") == 0) {
|
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 vpiLongIntVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiRealVar:
|
case vpiRealVar:
|
||||||
|
case vpiStringVar:
|
||||||
case vpiSysFuncCall:
|
case vpiSysFuncCall:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ dllib=@DLLIB@
|
||||||
MDIR1 = -DMODULE_DIR1='"$(libdir)/ivl$(suffix)"'
|
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 \
|
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 \
|
vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
|
||||||
vpip_to_dec.o vpip_format.o vvp_vpi.o
|
vpip_to_dec.o vpip_format.o vvp_vpi.o
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,7 @@ general syntax of a variable is:
|
||||||
<label> .var/2s "name", <msb> <lsb>; Signed bool/bit variable
|
<label> .var/2s "name", <msb> <lsb>; Signed bool/bit variable
|
||||||
<label> .var/real "name", <msb>, <lsb>; real variable
|
<label> .var/real "name", <msb>, <lsb>; real variable
|
||||||
<label> .var/i "name", <msb>, <lsb>; vpiIntegerVar 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
|
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
|
sake of VPI code that might access it. The variable is placed in the
|
||||||
|
|
|
||||||
|
|
@ -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(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_POW_S(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_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_NET(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RELEASE_REG(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);
|
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_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_I0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SHIFTR_S_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(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SUB_WR(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);
|
extern bool of_SUBI(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%pow/s", of_POW_S, 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} },
|
{ "%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/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/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} },
|
{ "%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} },
|
{ "%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/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} },
|
{ "%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", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%sub/wr", of_SUB_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%sub/wr", of_SUB_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||||
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%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;
|
return sig->net;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case vpiStringVar: {
|
||||||
|
__vpiStringVar*sig = dynamic_cast<__vpiStringVar*>(vpi);
|
||||||
|
return sig->get_net();
|
||||||
|
}
|
||||||
|
|
||||||
case vpiNamedEvent: {
|
case vpiNamedEvent: {
|
||||||
__vpiNamedEvent*tmp = dynamic_cast<__vpiNamedEvent*>(vpi);
|
__vpiNamedEvent*tmp = dynamic_cast<__vpiNamedEvent*>(vpi);
|
||||||
return tmp->funct;
|
return tmp->funct;
|
||||||
|
|
|
||||||
|
|
@ -455,8 +455,8 @@ extern void compile_variable(char*label, char*name,
|
||||||
int msb, int lsb, int vpi_type_code,
|
int msb, int lsb, int vpi_type_code,
|
||||||
bool signed_flag, bool local_flag);
|
bool signed_flag, bool local_flag);
|
||||||
|
|
||||||
extern void compile_var_real(char*label, char*name,
|
extern void compile_var_real(char*label, char*name);
|
||||||
int msb, int lsb);
|
extern void compile_var_string(char*label, char*name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is used to create a scope port
|
* This function is used to create a scope port
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,7 @@ static char* strdupnew(char const *str)
|
||||||
".var" { return K_VAR; }
|
".var" { return K_VAR; }
|
||||||
".var/real" { return K_VAR_R; }
|
".var/real" { return K_VAR_R; }
|
||||||
".var/s" { return K_VAR_S; }
|
".var/s" { return K_VAR_S; }
|
||||||
|
".var/str" { return K_VAR_STR; }
|
||||||
".var/i" { return K_VAR_I; /* integer */ }
|
".var/i" { return K_VAR_I; /* integer */ }
|
||||||
".var/2s" { return K_VAR_2S; /* byte/shortint/int/longint signed */ }
|
".var/2s" { return K_VAR_2S; /* byte/shortint/int/longint signed */ }
|
||||||
".var/2u" { return K_VAR_2U; /* byte/shortint/int/longint unsigned */ }
|
".var/2u" { return K_VAR_2U; /* byte/shortint/int/longint unsigned */ }
|
||||||
|
|
|
||||||
|
|
@ -750,6 +750,9 @@ replaces the left operand.
|
||||||
This opcode raises <bit-l> (real) to the power of <bit-r> (real). The
|
This opcode raises <bit-l> (real) to the power of <bit-r> (real). The
|
||||||
result replaces the left operand.
|
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/net <functor-label>, <base>, <width>
|
||||||
* %release/reg <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.
|
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>
|
* %sub <bit-l>, <bit-r>, <wid>
|
||||||
|
|
||||||
This instruction arithmetically subtracts the right vector out of the
|
This instruction arithmetically subtracts the right vector out of the
|
||||||
|
|
|
||||||
|
|
@ -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_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_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_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_call K_vpi_call_w K_vpi_call_i
|
||||||
%token K_vpi_func K_vpi_func_r
|
%token K_vpi_func K_vpi_func_r
|
||||||
%token K_disable K_fork
|
%token K_disable K_fork
|
||||||
|
|
@ -697,7 +697,10 @@ statement
|
||||||
{ compile_variable($1, $4, $6, $7, vpiIntVar, false, $3); }
|
{ compile_variable($1, $4, $6, $7, vpiIntVar, false, $3); }
|
||||||
|
|
||||||
| T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';'
|
| 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
|
/* Net statements are similar to .var statements, except that they
|
||||||
declare nets, and they have an input list. */
|
declare nets, and they have an input list. */
|
||||||
|
|
|
||||||
|
|
@ -794,6 +794,16 @@ void vvp_wire_real::get_signal_value(struct t_vpi_value*vp)
|
||||||
real_signal_value(vp, real_value());
|
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)
|
void vvp_wire_vec4::get_value(struct t_vpi_value*val)
|
||||||
{
|
{
|
||||||
get_signal_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);
|
get_signal_value(val);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
void vvp_wire_string::get_value(struct t_vpi_value*val)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -902,6 +902,11 @@ void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
|
||||||
assert(expr);
|
assert(expr);
|
||||||
assert(vp);
|
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);
|
expr->vpi_get_value(vp);
|
||||||
|
|
||||||
if (vpi_trace) switch (vp->format) {
|
if (vpi_trace) switch (vp->format) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
# include <set>
|
# include <set>
|
||||||
|
# include <string>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Added to use some "vvp_fun_modpath_src"
|
* Added to use some "vvp_fun_modpath_src"
|
||||||
|
|
@ -477,6 +478,23 @@ struct __vpiRealVar : public __vpiHandle {
|
||||||
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
|
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
|
||||||
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
|
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
|
* When a loaded VPI module announces a system task/function, one
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -99,6 +99,13 @@ struct vthread_s {
|
||||||
double w_real;
|
double w_real;
|
||||||
} words[16];
|
} 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. */
|
/* My parent sets this when it wants me to wake it up. */
|
||||||
unsigned i_am_joining :1;
|
unsigned i_am_joining :1;
|
||||||
unsigned i_have_ended :1;
|
unsigned i_have_ended :1;
|
||||||
|
|
@ -4141,6 +4148,41 @@ bool of_POW_WR(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
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
|
* These implement the %release/net and %release/reg instructions. The
|
||||||
* %release/net instruction applies to a net kind of functor by
|
* %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;
|
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)
|
bool of_SUB(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
assert(cp->bit_idx[0] >= 4);
|
assert(cp->bit_idx[0] >= 4);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
char*res = buf;
|
||||||
*buf++ = 'C';
|
*buf++ = 'C';
|
||||||
|
|
@ -2956,6 +2956,13 @@ void vvp_net_fun_t::recv_long_pv(vvp_net_ptr_t, long, unsigned, unsigned)
|
||||||
assert(0);
|
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)
|
void vvp_net_fun_t::force_flag(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ class vvp_vector4_t {
|
||||||
void set_to_x();
|
void set_to_x();
|
||||||
|
|
||||||
// Display the value into the buf as a string.
|
// 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();
|
void invert();
|
||||||
vvp_vector4_t& operator &= (const vvp_vector4_t&that);
|
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_vec8(const vvp_vector8_t&val);
|
||||||
void send_real(double val, vvp_context_t context);
|
void send_real(double val, vvp_context_t context);
|
||||||
void send_long(long val);
|
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,
|
void send_vec4_pv(const vvp_vector4_t&val,
|
||||||
unsigned base, unsigned wid, unsigned vwid,
|
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,
|
virtual void recv_real(vvp_net_ptr_t port, double bit,
|
||||||
vvp_context_t context);
|
vvp_context_t context);
|
||||||
virtual void recv_long(vvp_net_ptr_t port, long bit);
|
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
|
// Part select variants of above
|
||||||
virtual void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
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,
|
extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
|
||||||
unsigned base, unsigned width);
|
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
|
* Part-vector versions of above functions. This function uses the
|
||||||
* corresponding recv_vec4_pv method in the vvp_net_fun_t functor to
|
* 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
|
inline bool vvp_net_fil_t::test_force_mask(unsigned bit) const
|
||||||
{
|
{
|
||||||
if (bit >= force_mask_.size())
|
if (bit >= force_mask_.size())
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
# include "vvp_net_sig.h"
|
# include "vvp_net_sig.h"
|
||||||
# include "statistics.h"
|
# include "statistics.h"
|
||||||
# include "vpi_priv.h"
|
# include "vpi_priv.h"
|
||||||
|
# include <vector>
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
#ifdef CHECK_WITH_VALGRIND
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
# include <valgrind/memcheck.h>
|
# include <valgrind/memcheck.h>
|
||||||
|
|
@ -30,6 +31,8 @@
|
||||||
|
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The filter_mask_ method takes as an input the value to propagate,
|
* The filter_mask_ method takes as an input the value to propagate,
|
||||||
* the mask of what is being forced, and returns a propagation
|
* 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);
|
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()
|
vvp_fun_force::vvp_fun_force()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -1058,3 +1138,67 @@ double vvp_wire_real::real_value() const
|
||||||
else
|
else
|
||||||
return bit_;
|
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
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
# include "vpi_user.h"
|
# include "vpi_user.h"
|
||||||
# include "vvp_net.h"
|
# include "vvp_net.h"
|
||||||
|
# include <string>
|
||||||
# include <cstddef>
|
# include <cstddef>
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
# include <cstring>
|
# 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
|
/* vvp_wire
|
||||||
* The vvp_wire is different from vvp_variable objects in that it
|
* The vvp_wire is different from vvp_variable objects in that it
|
||||||
* exists only as a filter. The vvp_wire class tree is for
|
* 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_;
|
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
|
#endif
|
||||||
|
|
|
||||||
39
vvp/words.cc
39
vvp/words.cc
|
|
@ -65,9 +65,8 @@ static void __compile_var_real(char*label, char*name,
|
||||||
delete[] 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);
|
__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);
|
__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
|
* A variable is a special functor, so we allocate that functor and
|
||||||
* write the label into the symbol table.
|
* write the label into the symbol table.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue