Implement substring method for string expressions.

This commit is contained in:
Stephen Williams 2013-01-05 11:40:12 -08:00
parent bc9e31a444
commit d6726f62fc
6 changed files with 85 additions and 4 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

@ -86,6 +86,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 +130,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

@ -189,6 +189,7 @@ 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);
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

@ -236,6 +236,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%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

@ -1053,6 +1053,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

@ -5176,6 +5176,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>
*/ */