Implement comparison operators for strings.
This commit is contained in:
parent
dc39714d65
commit
cf1b83b8f0
|
|
@ -459,6 +459,39 @@ static struct vector_info draw_binary_expr_eq_real(ivl_expr_t expr)
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_eq_string(ivl_expr_t expr)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
||||
|
||||
struct vector_info res;
|
||||
res.base = allocate_vector(1);
|
||||
res.wid = 1;
|
||||
assert(res.base);
|
||||
|
||||
draw_eval_string(le);
|
||||
draw_eval_string(re);
|
||||
|
||||
fprintf(vvp_out, " %%cmp/str;\n");
|
||||
|
||||
switch (ivl_expr_opcode(expr)) {
|
||||
|
||||
case 'e': /* == */
|
||||
fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
case 'n': /* != */
|
||||
fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base);
|
||||
fprintf(vvp_out, " %%inv %u, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_eq(ivl_expr_t expr,
|
||||
unsigned ewid,
|
||||
int stuff_ok_flag)
|
||||
|
|
@ -476,13 +509,30 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t expr,
|
|||
return draw_binary_expr_eq_real(expr);
|
||||
}
|
||||
|
||||
if ((ivl_expr_value(le) == IVL_VT_STRING)
|
||||
&& (ivl_expr_value(re) == IVL_VT_STRING)) {
|
||||
return draw_binary_expr_eq_string(expr);
|
||||
}
|
||||
|
||||
if ((ivl_expr_value(le) == IVL_VT_STRING)
|
||||
&& (ivl_expr_type(re) == IVL_EX_STRING)) {
|
||||
return draw_binary_expr_eq_string(expr);
|
||||
}
|
||||
|
||||
if ((ivl_expr_type(le) == IVL_EX_STRING)
|
||||
&& (ivl_expr_value(re) == IVL_VT_STRING)) {
|
||||
return draw_binary_expr_eq_string(expr);
|
||||
}
|
||||
|
||||
if (number_is_immediate(re,16,0) && !number_is_unknown(re))
|
||||
return draw_eq_immediate(expr, ewid, le, re, stuff_ok_flag);
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(le) == IVL_VT_BOOL);
|
||||
|| ivl_expr_value(le) == IVL_VT_BOOL
|
||||
|| ivl_expr_value(le) == IVL_VT_STRING);
|
||||
assert(ivl_expr_value(re) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(re) == IVL_VT_BOOL);
|
||||
|| ivl_expr_value(re) == IVL_VT_BOOL
|
||||
|| ivl_expr_value(re) == IVL_VT_STRING);
|
||||
|
||||
wid = ivl_expr_width(le);
|
||||
if (ivl_expr_width(re) > wid)
|
||||
|
|
@ -825,6 +875,57 @@ static struct vector_info draw_binary_expr_le_real(ivl_expr_t expr)
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_le_string(ivl_expr_t expr)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
||||
|
||||
res.base = allocate_vector(1);
|
||||
res.wid = 1;
|
||||
|
||||
assert(res.base);
|
||||
|
||||
/* The %cmp/str function implements < and <= operands. To get
|
||||
the > and >= results, simply switch the order of the
|
||||
operands. */
|
||||
switch (ivl_expr_opcode(expr)) {
|
||||
case '<':
|
||||
case 'L':
|
||||
draw_eval_string(le);
|
||||
draw_eval_string(re);
|
||||
break;
|
||||
case '>':
|
||||
case 'G':
|
||||
draw_eval_string(re);
|
||||
draw_eval_string(le);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
switch (ivl_expr_opcode(expr)) {
|
||||
case '<':
|
||||
case '>':
|
||||
fprintf(vvp_out, " %%cmp/str;\n");
|
||||
fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
case 'L': /* <= */
|
||||
case 'G': /* >= */
|
||||
fprintf(vvp_out, " %%cmp/str;\n");
|
||||
fprintf(vvp_out, " %%or 5, 4, 1;\n");
|
||||
fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_le_bool(ivl_expr_t expr,
|
||||
unsigned wid)
|
||||
{
|
||||
|
|
@ -919,6 +1020,21 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t expr,
|
|||
return draw_binary_expr_le_bool(expr, wid);
|
||||
}
|
||||
|
||||
if ((ivl_expr_value(le) == IVL_VT_STRING)
|
||||
&& (ivl_expr_value(re) == IVL_VT_STRING)) {
|
||||
return draw_binary_expr_le_string(expr);
|
||||
}
|
||||
|
||||
if ((ivl_expr_value(le) == IVL_VT_STRING)
|
||||
&& (ivl_expr_type(re) == IVL_EX_STRING)) {
|
||||
return draw_binary_expr_le_string(expr);
|
||||
}
|
||||
|
||||
if ((ivl_expr_type(le) == IVL_EX_STRING)
|
||||
&& (ivl_expr_value(re) == IVL_VT_STRING)) {
|
||||
return draw_binary_expr_eq_string(expr);
|
||||
}
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(le) == IVL_VT_BOOL);
|
||||
assert(ivl_expr_value(re) == IVL_VT_LOGIC
|
||||
|
|
|
|||
|
|
@ -20,32 +20,41 @@
|
|||
# include "vvp_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
static void fallback_eval(ivl_expr_t expr)
|
||||
{
|
||||
struct vector_info 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);
|
||||
}
|
||||
|
||||
static void string_ex_signal(ivl_expr_t expr)
|
||||
{
|
||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||
|
||||
if (ivl_signal_data_type(sig) == IVL_VT_STRING) {
|
||||
fprintf(vvp_out, " %%load/str v%p_0;\n", sig);
|
||||
return;
|
||||
}
|
||||
|
||||
fallback_eval(expr);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
string_ex_signal(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;
|
||||
}
|
||||
fallback_eval(expr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ extern bool of_CAST2(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_CMPIS(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPS(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPSTR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPU(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPWR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPWS(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -121,6 +122,7 @@ extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%cast2", of_CAST2, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/str",of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
|
|
@ -169,6 +170,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/str",of_LOAD_STR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||
{ "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||
{ "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||
|
|
|
|||
|
|
@ -280,6 +280,13 @@ instruction will also treat x values in either operand as don't care.
|
|||
|
||||
Only bit 4 is set by these instructions.
|
||||
|
||||
* %cmp/str
|
||||
|
||||
This instruction pops the top two strings from the string stack and
|
||||
compares them. The results of the comparison go into bits 4 and 5:
|
||||
|
||||
4: eq (equal)
|
||||
5: lt (less than)
|
||||
|
||||
* %cvt/sr <bit-l>, <bit-r>
|
||||
* %cvt/rs <bit-l>, <bit-r>
|
||||
|
|
|
|||
|
|
@ -1491,6 +1491,36 @@ bool of_CMPS(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool of_CMPSTR(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
assert(thr->stack_str.size() >= 2);
|
||||
string re = thr->stack_str.back();
|
||||
thr->stack_str.pop_back();
|
||||
string le = thr->stack_str.back();
|
||||
thr->stack_str.pop_back();
|
||||
|
||||
int rc = strcmp(le.c_str(), re.c_str());
|
||||
|
||||
vvp_bit4_t eq;
|
||||
vvp_bit4_t lt;
|
||||
|
||||
if (rc == 0) {
|
||||
eq = BIT4_1;
|
||||
lt = BIT4_0;
|
||||
} else if (rc < 0) {
|
||||
eq = BIT4_0;
|
||||
lt = BIT4_1;
|
||||
} else {
|
||||
eq = BIT4_0;
|
||||
lt = BIT4_0;
|
||||
}
|
||||
|
||||
thr_put_bit(thr, 4, eq);
|
||||
thr_put_bit(thr, 5, lt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_CMPIS(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_bit4_t eq = BIT4_1;
|
||||
|
|
@ -3153,6 +3183,20 @@ bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool of_LOAD_STR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_net_t*net = cp->net;
|
||||
|
||||
|
||||
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (net->fun);
|
||||
assert(fun);
|
||||
|
||||
const string&val = fun->get_string();
|
||||
thr->stack_str.push_back(val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* %load/v <bit>, <label>, <wid>
|
||||
*
|
||||
* Implement the %load/v instruction. Load the vector value of the
|
||||
|
|
@ -3177,7 +3221,7 @@ static void load_base(vvp_code_t cp, vvp_vector4_t&dst)
|
|||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||
if (sig == 0) {
|
||||
cerr << "%%load/v error: Net arg not a signal? "
|
||||
<< typeid(*net->fil).name() << endl;
|
||||
<< (net->fil ? typeid(*net->fil).name() : typeid(*net->fun).name()) << endl;
|
||||
assert(sig);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue