Implement comparison operators for strings.

This commit is contained in:
Stephen Williams 2012-06-23 08:35:55 -07:00
parent dc39714d65
commit cf1b83b8f0
6 changed files with 199 additions and 19 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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} },

View File

@ -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>

View File

@ -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);
}