Merge branch 'master' of github.com:steveicarus/iverilog

This commit is contained in:
Cary R 2013-01-11 15:10:17 -08:00
commit 8e515a9a64
20 changed files with 294 additions and 29 deletions

View File

@ -1675,7 +1675,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
} }
static NetExpr* check_for_class_property(const LineInfo*li, static NetExpr* check_for_class_property(const LineInfo*li,
Design*des, NetScope*scope, Design*des, NetScope*,
NetNet*net, NetNet*net,
const name_component_t&comp) const name_component_t&comp)
{ {
@ -1885,6 +1885,28 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
sys_expr->parm(0, new NetESignal(net)); sys_expr->parm(0, new NetESignal(net));
return sys_expr; return sys_expr;
} }
if (method_name == "substr") {
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$substr",
IVL_VT_STRING, 1, 3);
sys_expr->set_line(*this);
// First argument is the source string.
sys_expr->parm(0, new NetESignal(net));
ivl_assert(*this, parms_.size() == 2);
NetExpr*tmp;
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL,
32, parms_[0], false);
sys_expr->parm(1, tmp);
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL,
32, parms_[1], false);
sys_expr->parm(2, tmp);
return sys_expr;
}
} }
if (netenum_t*netenum = net->enumeration()) { if (netenum_t*netenum = net->enumeration()) {
@ -2544,9 +2566,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetEvent* eve = 0; NetEvent* eve = 0;
const NetExpr*ex1, *ex2; const NetExpr*ex1, *ex2;
NetScope*found_in = symbol_search(this, des, scope, path_, /* NetScope*found_in = */ symbol_search(this, des, scope, path_,
net, par, eve, net, par, eve,
ex1, ex2); ex1, ex2);
if (net == 0) { if (net == 0) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "

View File

@ -18,6 +18,7 @@
*/ */
# include "vvp_priv.h" # include "vvp_priv.h"
# include <string.h>
# include <assert.h> # include <assert.h>
static void fallback_eval(ivl_expr_t expr) static void fallback_eval(ivl_expr_t expr)
@ -63,12 +64,25 @@ static void string_ex_signal(ivl_expr_t expr)
{ {
ivl_signal_t sig = ivl_expr_signal(expr); ivl_signal_t sig = ivl_expr_signal(expr);
if (ivl_signal_data_type(sig) == IVL_VT_STRING) { if (ivl_signal_data_type(sig) != IVL_VT_STRING) {
fallback_eval(expr);
return;
}
/* Simple case: This is a simple variable. Generate a load
statement to load the string into the stack. */
if (ivl_signal_dimensions(sig) == 0) {
fprintf(vvp_out, " %%load/str v%p_0;\n", sig); fprintf(vvp_out, " %%load/str v%p_0;\n", sig);
return; return;
} }
fallback_eval(expr); /* There is a word select expression, so load the index into a
register and load from the array. */
ivl_expr_t word_ex = ivl_expr_oper1(expr);
int word_ix = allocate_word();
draw_eval_expr_into_integer(word_ex, word_ix);
fprintf(vvp_out, " %%load/stra v%p, %d;\n", sig, word_ix);
clr_word(word_ix);
} }
static void string_ex_select(ivl_expr_t expr) static void string_ex_select(ivl_expr_t expr)
@ -86,6 +100,30 @@ static void string_ex_select(ivl_expr_t expr)
fprintf(vvp_out, " %%load/dar/str v%p_0;\n", sig); fprintf(vvp_out, " %%load/dar/str v%p_0;\n", sig);
} }
static void string_ex_substr(ivl_expr_t expr)
{
ivl_expr_t arg;
unsigned arg1;
unsigned arg2;
assert(ivl_expr_parms(expr) == 3);
arg = ivl_expr_parm(expr,0);
draw_eval_string(arg);
/* Evaluate the arguments... */
arg = ivl_expr_parm(expr, 1);
arg1 = allocate_word();
draw_eval_expr_into_integer(arg, arg1);
arg = ivl_expr_parm(expr, 2);
arg2 = allocate_word();
draw_eval_expr_into_integer(arg, arg2);
fprintf(vvp_out, " %%substr %u, %u;\n", arg1, arg2);
clr_word(arg1);
clr_word(arg2);
}
void draw_eval_string(ivl_expr_t expr) void draw_eval_string(ivl_expr_t expr)
{ {
@ -106,6 +144,13 @@ void draw_eval_string(ivl_expr_t expr)
string_ex_select(expr); string_ex_select(expr);
break; break;
case IVL_EX_SFUNC:
if (strcmp(ivl_expr_name(expr), "$ivl_string_method$substr") == 0)
string_ex_substr(expr);
else
fallback_eval(expr);
break;
default: default:
fallback_eval(expr); fallback_eval(expr);
break; break;

View File

@ -730,6 +730,7 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
ivl_lval_t lval = ivl_stmt_lval(net, 0); ivl_lval_t lval = ivl_stmt_lval(net, 0);
ivl_expr_t rval = ivl_stmt_rval(net); ivl_expr_t rval = ivl_stmt_rval(net);
ivl_expr_t part = ivl_lval_part_off(lval); ivl_expr_t part = ivl_lval_part_off(lval);
ivl_expr_t aidx = ivl_lval_idx(lval);
ivl_signal_t var= ivl_lval_sig(lval); ivl_signal_t var= ivl_lval_sig(lval);
assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_lvals(net) == 1);
@ -739,12 +740,24 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
/* Simplest case: no mux. Evaluate the r-value as a string and /* Simplest case: no mux. Evaluate the r-value as a string and
store the result into the variable. Note that the store the result into the variable. Note that the
%store/str opcode pops the string result. */ %store/str opcode pops the string result. */
if (part == 0) { if (part == 0 && aidx == 0) {
draw_eval_string(rval); draw_eval_string(rval);
fprintf(vvp_out, " %%store/str v%p_0;\n", var); fprintf(vvp_out, " %%store/str v%p_0;\n", var);
return 0; return 0;
} }
/* Assign to array. The l-value has an index expression
expression so we are assigning to an array word. */
if (aidx != 0) {
unsigned ix;
assert(part == 0);
draw_eval_string(rval);
draw_eval_expr_into_integer(aidx, (ix = allocate_word()));
fprintf(vvp_out, " %%store/stra v%p, %u;\n", var, ix);
clr_word(ix);
return 0;
}
/* Calculate the character select for the word. */ /* Calculate the character select for the word. */
int mux_word = allocate_word(); int mux_word = allocate_word();
draw_eval_expr_into_integer(part, mux_word); draw_eval_expr_into_integer(part, mux_word);

View File

@ -475,6 +475,7 @@ static void draw_reg_in_scope(ivl_signal_t sig)
const char *datatype_flag = ivl_signal_integer(sig) ? "/i" : const char *datatype_flag = ivl_signal_integer(sig) ? "/i" :
ivl_signal_signed(sig)? "/s" : ""; ivl_signal_signed(sig)? "/s" : "";
const char *local_flag = local_flag_str(sig); const char *local_flag = local_flag_str(sig);
int vector_dims = 1;
switch (ivl_signal_data_type(sig)) { switch (ivl_signal_data_type(sig)) {
case IVL_VT_BOOL: case IVL_VT_BOOL:
@ -485,6 +486,11 @@ static void draw_reg_in_scope(ivl_signal_t sig)
break; break;
case IVL_VT_REAL: case IVL_VT_REAL:
datatype_flag = "/real"; datatype_flag = "/real";
vector_dims = 0;
break;
case IVL_VT_STRING:
datatype_flag = "/str";
vector_dims = 0;
break; break;
default: default:
break; break;
@ -492,7 +498,20 @@ static void draw_reg_in_scope(ivl_signal_t sig)
/* If the reg objects are collected into an array, then first /* If the reg objects are collected into an array, then first
write out the .array record to declare the array indices. */ write out the .array record to declare the array indices. */
if (ivl_signal_dimensions(sig) > 0) { if (ivl_signal_dimensions(sig) > 0 && vector_dims==0) {
/* Some types cannot be placed in packed dimensions, so
do not include packed dimensions. */
unsigned word_count = ivl_signal_array_count(sig);
unsigned swapped = ivl_signal_array_addr_swapped(sig);
int last = ivl_signal_array_base(sig)+word_count-1;
int first = ivl_signal_array_base(sig);
fprintf(vvp_out, "v%p .array%s \"%s\", %d %d;\n",
sig, datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
swapped ? first: last, swapped ? last : first);
} else if (ivl_signal_dimensions(sig) > 0) {
unsigned word_count = ivl_signal_array_count(sig); unsigned word_count = ivl_signal_array_count(sig);
unsigned swapped = ivl_signal_array_addr_swapped(sig); unsigned swapped = ivl_signal_array_addr_swapped(sig);
int last = ivl_signal_array_base(sig)+word_count-1; int last = ivl_signal_array_base(sig)+word_count-1;

View File

@ -54,7 +54,7 @@ LDFLAGS = @LDFLAGS@
O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o sys_display.o \ O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o sys_display.o \
sys_fileio.o sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o \ sys_fileio.o sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o \
sys_random.o sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o \ sys_random.o sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o \
sys_sdf.o sys_string.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \ sys_sdf.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \
sys_priv.o sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o \ sys_priv.o sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o \
table_mod.o table_mod_lexor.o table_mod_parse.o table_mod.o table_mod_lexor.o table_mod_parse.o
OPP = vcd_priv2.o OPP = vcd_priv2.o
@ -73,7 +73,7 @@ M = sys_clog2.o v2005_math.o
# Object files for va_math.vpi # Object files for va_math.vpi
V = va_math.o V = va_math.o
V2009 = v2009_table.o v2009_enum.o V2009 = v2009_table.o v2009_enum.o v2009_string.o
VHDL_SYS = vhdl_table.o VHDL_SYS = vhdl_table.o

View File

@ -35,7 +35,6 @@ extern void sys_queue_register();
extern void sys_random_register(); extern void sys_random_register();
extern void sys_random_mti_register(); extern void sys_random_mti_register();
extern void sys_readmem_register(); extern void sys_readmem_register();
extern void sys_string_register();
extern void sys_scanf_register(); extern void sys_scanf_register();
extern void sys_sdf_register(); extern void sys_sdf_register();
extern void sys_time_register(); extern void sys_time_register();
@ -210,7 +209,6 @@ void (*vlog_startup_routines[])() = {
sys_random_mti_register, sys_random_mti_register,
sys_readmem_register, sys_readmem_register,
sys_scanf_register, sys_scanf_register,
sys_string_register,
sys_time_register, sys_time_register,
sys_lxt_or_vcd_register, sys_lxt_or_vcd_register,
sys_sdf_register, sys_sdf_register,

View File

@ -2,4 +2,3 @@
# This is the system function descriptor table for the # This is the system function descriptor table for the
# builtin (system) functions. # builtin (system) functions.
# #

View File

@ -73,7 +73,7 @@ static PLI_INT32 len_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
return 0; return 0;
} }
void sys_string_register(void) void v2009_string_register(void)
{ {
s_vpi_systf_data tf_data; s_vpi_systf_data tf_data;
vpiHandle res; vpiHandle res;

View File

@ -24,8 +24,10 @@
# include <string.h> # include <string.h>
extern void v2009_enum_register(void); extern void v2009_enum_register(void);
extern void v2009_string_register(void);
void (*vlog_startup_routines[])() = { void (*vlog_startup_routines[])() = {
v2009_enum_register, v2009_enum_register,
v2009_string_register,
0 0
}; };

View File

@ -802,23 +802,39 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref)
} }
// This function return true if the underlying array words are real. // This function return true if the underlying array words are real.
static unsigned vpi_array_is_real(vvp_array_t arr) static bool vpi_array_is_real(vvp_array_t arr)
{ {
// Check to see if this is a variable/register array. // Check to see if this is a variable/register array.
if (arr->vals4 != 0) return 0U; // A bit based variable/register array. if (arr->vals4 != 0) // A bit based variable/register array.
return false;
if (dynamic_cast<vvp_darray_real*> (arr->vals)) if (dynamic_cast<vvp_darray_real*> (arr->vals))
return 1U; return true;
if (arr->vals != 0)
return false;
// This must be a net array so look at element 0 to find the type. // This must be a net array so look at element 0 to find the type.
assert(arr->nets != 0); assert(arr->nets != 0);
assert(arr->array_count > 0); assert(arr->array_count > 0);
struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]); struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]);
if (rsig) { if (rsig) {
return 1U; return true;
} }
return 0U; return false;
}
static bool vpi_array_is_string(vvp_array_t arr)
{
// Check to see if this is a variable/register array.
if (arr->vals4 != 0) // A bit based variable/register array.
return false;
if (dynamic_cast<vvp_darray_string*> (arr->vals))
return true;
return false;
} }
static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp)
@ -833,6 +849,9 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp)
if (vpi_array_is_real(parent)) { if (vpi_array_is_real(parent)) {
double tmp = array_get_word_r(parent, index); double tmp = array_get_word_r(parent, index);
vpip_real_get_value(tmp, vp); vpip_real_get_value(tmp, vp);
} else if (vpi_array_is_string(parent)) {
string tmp = array_get_word_str(parent, index);
vpip_string_get_value(tmp, vp);
} else { } else {
vvp_vector4_t tmp = array_get_word(parent, index); vvp_vector4_t tmp = array_get_word(parent, index);
unsigned width = get_array_word_size(parent); unsigned width = get_array_word_size(parent);
@ -1025,6 +1044,18 @@ void array_set_word(vvp_array_t arr, unsigned address, double val)
array_word_change(arr, address); array_word_change(arr, address);
} }
void array_set_word(vvp_array_t arr, unsigned address, const string&val)
{
assert(arr->vals != 0);
assert(arr->nets == 0);
if (address >= arr->vals->get_size())
return;
arr->vals->set_word(address, val);
array_word_change(arr, address);
}
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
{ {
if (arr->vals4) { if (arr->vals4) {
@ -1099,6 +1130,27 @@ double array_get_word_r(vvp_array_t arr, unsigned address)
} }
string array_get_word_str(vvp_array_t arr, unsigned address)
{
if (arr->vals) {
assert(arr->vals4 == 0);
assert(arr->nets == 0);
// In this context, address out of bounds returns 0.0
// instead of an error.
if (address >= arr->vals->get_size())
return "";
string val;
arr->vals->get_word(address, val);
return val;
}
assert(arr->nets);
// Arrays of string nets not implemented!
assert(0);
return "";
}
static vpiHandle vpip_make_array(char*label, const char*name, static vpiHandle vpip_make_array(char*label, const char*name,
int first_addr, int last_addr, int first_addr, int last_addr,
bool signed_flag) bool signed_flag)
@ -1265,8 +1317,7 @@ void compile_var2_array(char*label, char*name, int last, int first,
delete[] name; delete[] name;
} }
void compile_real_array(char*label, char*name, int last, int first, void compile_real_array(char*label, char*name, int last, int first)
int msb, int lsb)
{ {
vpiHandle obj = vpip_make_array(label, name, first, last, true); vpiHandle obj = vpip_make_array(label, name, first, last, true);
@ -1276,8 +1327,22 @@ void compile_real_array(char*label, char*name, int last, int first,
arr->vals = new vvp_darray_real(arr->array_count); arr->vals = new vvp_darray_real(arr->array_count);
arr->vals_width = 1; arr->vals_width = 1;
/* For a real array the MSB and LSB must be zero. */ count_real_arrays += 1;
assert(msb == 0 && lsb == 0); count_real_array_words += arr->array_count;
free(label);
delete[] name;
}
void compile_string_array(char*label, char*name, int last, int first)
{
vpiHandle obj = vpip_make_array(label, name, first, last, true);
struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
/* Make the words. */
arr->vals = new vvp_darray_string(arr->array_count);
arr->vals_width = 1;
count_real_arrays += 1; count_real_arrays += 1;
count_real_array_words += arr->array_count; count_real_array_words += arr->array_count;

View File

@ -43,9 +43,12 @@ extern void array_set_word(vvp_array_t arr, unsigned idx,
unsigned off, vvp_vector4_t val); unsigned off, vvp_vector4_t val);
extern void array_set_word(vvp_array_t arr, unsigned idx, extern void array_set_word(vvp_array_t arr, unsigned idx,
double val); double val);
extern void array_set_word(vvp_array_t arr, unsigned idx,
const std::string&val);
extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address); extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address);
extern double array_get_word_r(vvp_array_t array, unsigned address); extern double array_get_word_r(vvp_array_t array, unsigned address);
extern std::string array_get_word_str(vvp_array_t array, unsigned address);
/* VPI hooks */ /* VPI hooks */

View File

@ -132,6 +132,7 @@ extern bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_OBJ(vthread_t thr, vvp_code_t code); extern bool of_LOAD_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STRA(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code);
@ -186,9 +187,11 @@ extern bool of_STORE_PROP_V(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code); extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code);
extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code); extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code); extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STRA(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);
extern bool of_SUBSTR(vthread_t thr, vvp_code_t code);
extern bool of_SUBSTR_V(vthread_t thr, vvp_code_t code); extern bool of_SUBSTR_V(vthread_t thr, vvp_code_t code);
extern bool of_TEST_NUL(vthread_t thr, vvp_code_t code); extern bool of_TEST_NUL(vthread_t thr, vvp_code_t code);
extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code); extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code);

View File

@ -180,6 +180,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} }, { "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%load/stra", of_LOAD_STRA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
@ -233,9 +234,11 @@ static const struct opcode_table_s opcode_table[] = {
{ "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, { "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/stra", of_STORE_STRA, 2, {OA_ARR_PTR, OA_BIT1, 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, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%substr", of_SUBSTR, 2,{OA_BIT1, OA_BIT2, OA_NONE} },
{ "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },

View File

@ -348,8 +348,9 @@ extern void compile_var2_array(char*label, char*name,
int last, int first, int last, int first,
int msb, int lsb, bool signed_flag); int msb, int lsb, bool signed_flag);
extern void compile_real_array(char*label, char*name, extern void compile_real_array(char*label, char*name,
int last, int first, int last, int first);
int msb, int lsb); extern void compile_string_array(char*label, char*name,
int last, int first);
extern void compile_net_array(char*label, char*name, extern void compile_net_array(char*label, char*name,
int last, int first); int last, int first);
extern void compile_array_alias(char*label, char*name, char*src); extern void compile_array_alias(char*label, char*name, char*src);

View File

@ -126,6 +126,7 @@ static char* strdupnew(char const *str)
".array/i" { return K_ARRAY_I; } ".array/i" { return K_ARRAY_I; }
".array/real" { return K_ARRAY_R; } ".array/real" { return K_ARRAY_R; }
".array/s" { return K_ARRAY_S; } ".array/s" { return K_ARRAY_S; }
".array/str" { return K_ARRAY_STR; }
".array/port" { return K_ARRAY_PORT; } ".array/port" { return K_ARRAY_PORT; }
".cast/2" { return K_CAST_2; } ".cast/2" { return K_CAST_2; }
".cast/int" { return K_CAST_INT; } ".cast/int" { return K_CAST_INT; }

View File

@ -653,6 +653,7 @@ The %load/real instruction reads a real value from the vpi-like object
and pushes it to the top of the real value stack. and pushes it to the top of the real value stack.
* %load/str <var-label> * %load/str <var-label>
* %load/stra <array-label>, <index>
* %load/dar/str <var-label> * %load/dar/str <var-label>
The %load/str instruction gets the string from the string variable and The %load/str instruction gets the string from the string variable and
@ -1009,7 +1010,7 @@ variable given by the label.
See also %load/obj. See also %load/obj.
* %store/real <var-label> * %store/real <var-label>
* %store/reala <var-label> <index> * %store/reala <var-label>, <index>
This pops the top of the real variable stack and write it to the This pops the top of the real variable stack and write it to the
object variable given bu the label. object variable given bu the label.
@ -1018,12 +1019,15 @@ The areal version is similar, but writes to a real array using the
index in the index register <index> index in the index register <index>
* %store/str <var-label> * %store/str <var-label>
* %store/stra <array-label>, <index>
* %store/dar/r <var-label> * %store/dar/r <var-label>
* %store/dar/str <var-label> * %store/dar/str <var-label>
The %store/str instruction pops the top of the string stack and writes The %store/str instruction pops the top of the string stack and writes
it to the string variable. it to the string variable.
The %store/stra targets an array.
The %store/dar/str is similar, but the target is a dynamic array of The %store/dar/str is similar, but the target is a dynamic array of
string string. The index is taken from signed index register 3. string string. The index is taken from signed index register 3.
@ -1053,6 +1057,11 @@ This instruction operates on real values in word registers. The right
value is popped, the left value is popped, the right is subtracted value is popped, the left value is popped, the right is subtracted
from the left, and the result pushed. from the left, and the result pushed.
* %substr <start>, <end>
This instruction takes the substring of the top string in the string
stack. This implements the SystemVerilog style substring. The string
stack is popped and replaced with the result.
* %substr/v <bit-l>, <sel>, <wid> * %substr/v <bit-l>, <sel>, <wid>

View File

@ -77,7 +77,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ARITH_MOD_R K_ARITH_MOD_S %token K_ARITH_MOD_R K_ARITH_MOD_S
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R %token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S %token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
%token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT %token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_STR K_ARRAY_PORT
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2 %token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
%token K_CLASS %token K_CLASS
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R %token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
@ -221,12 +221,15 @@ statement
| T_LABEL K_ARRAY_I T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY_I T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var_array($1, $3, $5, $6, $8, $9, 2); } { compile_var_array($1, $3, $5, $6, $8, $9, 2); }
| T_LABEL K_ARRAY_R T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY_R T_STRING ',' signed_t_number signed_t_number ';'
{ compile_real_array($1, $3, $5, $6, $8, $9); } { compile_real_array($1, $3, $5, $6); }
| T_LABEL K_ARRAY_S T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY_S T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var_array($1, $3, $5, $6, $8, $9, 1); } { compile_var_array($1, $3, $5, $6, $8, $9, 1); }
| T_LABEL K_ARRAY_STR T_STRING ',' signed_t_number signed_t_number ';'
{ compile_string_array($1, $3, $5, $6); }
| T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ';'
{ compile_net_array($1, $3, $5, $6); } { compile_net_array($1, $3, $5, $6); }

View File

@ -902,6 +902,32 @@ double real_from_vpi_value(s_vpi_value*vp)
return result; return result;
} }
void vpip_string_get_value(const string&val, s_vpi_value*vp)
{
char *rbuf = 0;
switch (vp->format) {
default:
fprintf(stderr, "sorry: Format %d not implemented for "
"getting string values.\n", (int)vp->format);
assert(0);
case vpiSuppressVal:
break;
case vpiObjTypeVal:
// Use the following case to actually set the value!
vp->format = vpiStringVal;
case vpiStringVal:
rbuf = need_result_buf(val.size() + 1, RBUF_VAL);
strcpy(rbuf, val.c_str());
vp->value.str = rbuf;
break;
}
}
void vpi_get_value(vpiHandle expr, s_vpi_value*vp) void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
{ {
assert(expr); assert(expr);

View File

@ -771,6 +771,7 @@ extern void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width,
extern void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width, extern void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width,
bool signed_flag, s_vpi_value*vp); bool signed_flag, s_vpi_value*vp);
extern void vpip_real_get_value(double real, s_vpi_value*vp); extern void vpip_real_get_value(double real, s_vpi_value*vp);
extern void vpip_string_get_value(const std::string&val, s_vpi_value*vp);
/* /*
* Function defined in vpi_signal.cc to manage vpi_get_* persistent * Function defined in vpi_signal.cc to manage vpi_get_* persistent

View File

@ -3444,6 +3444,23 @@ bool of_LOAD_STR(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
bool of_LOAD_STRA(vthread_t thr, vvp_code_t cp)
{
unsigned idx = cp->bit_idx[0];
unsigned adr = thr->words[idx].w_int;
string word;
/* The result is 0.0 if the address is undefined. */
if (thr_get_bit(thr, 4) == BIT4_1) {
word = "";
} else {
word = array_get_word_str(cp->array, adr);
}
thr->push_str(word);
return true;
}
/* %load/v <bit>, <label>, <wid> /* %load/v <bit>, <label>, <wid>
* *
* Implement the %load/v instruction. Load the vector value of the * Implement the %load/v instruction. Load the vector value of the
@ -5096,6 +5113,20 @@ bool of_STORE_STR(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %store/stra <array-label> <index>
*/
bool of_STORE_STRA(vthread_t thr, vvp_code_t cp)
{
unsigned idx = cp->bit_idx[0];
unsigned adr = thr->words[idx].w_int;
string val = thr->pop_str();
array_set_word(cp->array, adr, val);
return true;
}
bool of_SUB(vthread_t thr, vvp_code_t cp) bool of_SUB(vthread_t thr, vvp_code_t cp)
{ {
@ -5176,6 +5207,27 @@ bool of_SUBI(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %substr <first>, <last>
* Pop a string, take the substring (SystemVerilog style), and return
* the result to the stack. This opcode actually works by editing the
* string in place.
*/
bool of_SUBSTR(vthread_t thr, vvp_code_t cp)
{
int32_t first = thr->words[cp->bit_idx[0]].w_int;
int32_t last = thr->words[cp->bit_idx[1]].w_int;
string&val = thr->peek_str(0);
if (first < 0 || last < first || last >= (int32_t)val.size()) {
val = string("");
return true;
}
val = val.substr(first, last-first+1);
return true;
}
/* /*
* %substr/v <bitl>, <index>, <wid> * %substr/v <bitl>, <index>, <wid>
*/ */