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