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,
Design*des, NetScope*scope,
Design*des, NetScope*,
NetNet*net,
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));
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()) {
@ -2544,9 +2566,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
NetScope*found_in = symbol_search(this, des, scope, path_,
net, par, eve,
ex1, ex2);
/* NetScope*found_in = */ symbol_search(this, des, scope, path_,
net, par, eve,
ex1, ex2);
if (net == 0) {
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);
}
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)
{
@ -106,6 +130,13 @@ void draw_eval_string(ivl_expr_t expr)
string_ex_select(expr);
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:
fallback_eval(expr);
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_WR(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_TEST_NUL(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/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%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} },
{ "%test_nul", of_TEST_NUL, 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
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>

View File

@ -5176,6 +5176,27 @@ bool of_SUBI(vthread_t thr, vvp_code_t cp)
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>
*/