Implement substring method for string expressions.
This commit is contained in:
parent
bc9e31a444
commit
d6726f62fc
30
elab_expr.cc
30
elab_expr.cc
|
|
@ -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: "
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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} },
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue