diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 9edeb32ec..de4cbb206 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -49,7 +49,7 @@ CFLAGS = @WARNING_FLAGS@ @CFLAGS@ LDFLAGS = @LDFLAGS@ O = vvp.o draw_enum.o draw_mux.o draw_net_input.o draw_switch.o draw_ufunc.o draw_vpi.o \ - eval_bool.o eval_expr.o eval_real.o modpath.o stmt_assign.o vector.o \ + eval_bool.o eval_expr.o eval_real.o eval_string.o modpath.o stmt_assign.o vector.o \ vvp_process.o vvp_scope.o all: dep vvp.tgt vvp.conf vvp-s.conf diff --git a/tgt-vvp/eval_string.c b/tgt-vvp/eval_string.c new file mode 100644 index 000000000..8c208a91e --- /dev/null +++ b/tgt-vvp/eval_string.c @@ -0,0 +1,51 @@ +/* + * 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 "vvp_priv.h" +# include + + +void draw_eval_string(ivl_expr_t expr) +{ + struct vector_info res; + + switch (ivl_expr_type(expr)) { + case IVL_EX_STRING: + fprintf(vvp_out, " %%pushi/str \"%s\";\n", ivl_expr_string(expr)); + break; + + default: + switch (ivl_expr_value(expr)) { + + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + res = draw_eval_expr(expr, 0); + fprintf(vvp_out, " %%pushv/str %u, %u; Cast BOOL/LOGIC to string\n", + res.base, res.wid); + if (res.base > 0) + clr_vector(res); + break; + + default: + assert(0); + break; + } + break; + } +} diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 242fef33d..3ef0d8cbe 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -733,7 +733,6 @@ static int show_stmt_assign_sig_real(ivl_statement_t net) 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; @@ -742,20 +741,8 @@ static int show_stmt_assign_sig_string(ivl_statement_t net) 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; - } + draw_eval_string(rval); + fprintf(vvp_out, " %%store/str v%p_0;\n", var); return 0; } diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 64fb94571..fe9f44e41 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -313,6 +313,12 @@ extern int draw_eval_real(ivl_expr_t ex); */ extern int draw_eval_bool64(ivl_expr_t ex); +/* + * The draw_eval_string functio evaluates the expression as a string, + * and pushes the string onto the string stack. + */ +extern void draw_eval_string(ivl_expr_t ex); + extern int show_stmt_assign(ivl_statement_t net); extern void show_stmt_file_line(ivl_statement_t net, const char*desc); diff --git a/vvp/codes.h b/vvp/codes.h index f5a99c1d8..a7fe23dde 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -148,6 +148,7 @@ extern bool of_PAD(vthread_t thr, vvp_code_t code); extern bool of_POW(vthread_t thr, vvp_code_t code); extern bool of_POW_S(vthread_t thr, vvp_code_t code); extern bool of_POW_WR(vthread_t thr, vvp_code_t code); +extern bool of_PUSHI_STR(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); @@ -191,6 +192,7 @@ struct vvp_code_s { vvp_array_t array; class __vpiHandle*handle; struct __vpiScope*scope; + const char*text; }; union { diff --git a/vvp/compile.cc b/vvp/compile.cc index 99a21af6e..b53e9b61b 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -70,7 +70,9 @@ enum operand_e { /* The operand is a second functor pointer */ OA_FUNC_PTR2, /* The operand is a VPI handle */ - OA_VPI_PTR + OA_VPI_PTR, + /* String */ + OA_STRING }; struct opcode_table_s { @@ -194,6 +196,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} }, + { "%pushi/str",of_PUSHI_STR,1,{OA_STRING, OA_NONE, 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} }, @@ -1669,6 +1672,15 @@ void compile_code(char*label, char*mnem, comp_operands_t opa) compile_vpi_lookup(&code->handle, opa->argv[idx].symb.text); break; + + case OA_STRING: + if (opa->argv[idx].ltype != L_STRING) { + yyerror("operand format"); + break; + } + + code->text = opa->argv[idx].text; + break; } } diff --git a/vvp/compile.h b/vvp/compile.h index 78b35113f..56ed79e81 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -388,7 +388,7 @@ extern void compile_named_event(char*label, char*type); */ #define OPERAND_MAX 3 -enum ltype_e { L_NUMB, L_SYMB }; +enum ltype_e { L_NUMB, L_SYMB, L_STRING }; struct comp_operands_s { unsigned argc; @@ -397,6 +397,7 @@ struct comp_operands_s { union { unsigned long numb; struct symb_s symb; + const char *text; }; } argv[OPERAND_MAX]; }; diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 6beb9295b..9103d75c2 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -750,6 +750,10 @@ replaces the left operand. This opcode raises (real) to the power of (real). The result replaces the left operand. +* %pushi/str + +Push a literal string to the string stack. + * %pushv/str , Convert a vector to a string and push the string to the string stack. diff --git a/vvp/parse.y b/vvp/parse.y index ee0dbf214..993dc8578 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -883,23 +883,31 @@ operands ; operand - : symbol - { comp_operands_t opa = (comp_operands_t) - calloc(1, sizeof(struct comp_operands_s)); - opa->argc = 1; - opa->argv[0].ltype = L_SYMB; - opa->argv[0].symb = $1; - $$ = opa; - } - | T_NUMBER - { comp_operands_t opa = (comp_operands_t) - calloc(1, sizeof(struct comp_operands_s)); - opa->argc = 1; - opa->argv[0].ltype = L_NUMB; - opa->argv[0].numb = $1; - $$ = opa; - } - ; + : symbol + { comp_operands_t opa = (comp_operands_t) + calloc(1, sizeof(struct comp_operands_s)); + opa->argc = 1; + opa->argv[0].ltype = L_SYMB; + opa->argv[0].symb = $1; + $$ = opa; + } + | T_NUMBER + { comp_operands_t opa = (comp_operands_t) + calloc(1, sizeof(struct comp_operands_s)); + opa->argc = 1; + opa->argv[0].ltype = L_NUMB; + opa->argv[0].numb = $1; + $$ = opa; + } + | T_STRING + { comp_operands_t opa = (comp_operands_t) + calloc(1, sizeof(struct comp_operands_s)); + opa->argc = 1; + opa->argv[0].ltype = L_STRING; + opa->argv[0].text = $1; + $$ = opa; + } + ; /* The argument_list is a list of vpiHandle objects that can be diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 1b6b69d43..51f8ef47a 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -4148,6 +4148,13 @@ bool of_POW_WR(vthread_t thr, vvp_code_t cp) return true; } +bool of_PUSHI_STR(vthread_t thr, vvp_code_t cp) +{ + const char*text = cp->text; + thr->stack_str.push_back(string(text)); + return true; +} + bool of_PUSHV_STR(vthread_t thr, vvp_code_t cp) { unsigned src = cp->bit_idx[0];