Add support for the wild compare operators ==? and !=?
This commit is contained in:
parent
d23b046203
commit
3fc9ad2db0
|
|
@ -187,9 +187,15 @@ ostream& operator << (ostream&fd, NetCaseCmp::kind_t that)
|
|||
case NetCaseCmp::NEQ:
|
||||
fd << "!==";
|
||||
break;
|
||||
case NetCaseCmp::XEQ:
|
||||
case NetCaseCmp::WEQ:
|
||||
fd << "==?";
|
||||
break;
|
||||
case NetCaseCmp::WNE:
|
||||
fd << "!=?";
|
||||
break;
|
||||
case NetCaseCmp::XEQ:
|
||||
fd << "==x?";
|
||||
break;
|
||||
case NetCaseCmp::ZEQ:
|
||||
fd << "==z?";
|
||||
break;
|
||||
|
|
@ -1631,11 +1637,14 @@ void NetEBinary::dump(ostream&o) const
|
|||
case 'A':
|
||||
o << "~&";
|
||||
break;
|
||||
case 'e':
|
||||
o << "==";
|
||||
break;
|
||||
case 'E':
|
||||
o << "===";
|
||||
break;
|
||||
case 'e':
|
||||
o << "==";
|
||||
case 'w':
|
||||
o << "==?";
|
||||
break;
|
||||
case 'G':
|
||||
o << ">=";
|
||||
|
|
@ -1652,6 +1661,9 @@ void NetEBinary::dump(ostream&o) const
|
|||
case 'N':
|
||||
o << "!==";
|
||||
break;
|
||||
case 'W':
|
||||
o << "!=?";
|
||||
break;
|
||||
case 'o':
|
||||
o << "||";
|
||||
break;
|
||||
|
|
|
|||
14
elab_expr.cc
14
elab_expr.cc
|
|
@ -329,10 +329,12 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
case '>': // > Should be handled by PEBComp
|
||||
case 'e': // == Should be handled by PEBComp
|
||||
case 'E': // === Should be handled by PEBComp
|
||||
case 'w': // ==? Should be handled by PEBComp
|
||||
case 'L': // <= Should be handled by PEBComp
|
||||
case 'G': // >= Should be handled by PEBComp
|
||||
case 'n': // != Should be handled by PEBComp
|
||||
case 'N': // !== Should be handled by PEBComp
|
||||
case 'W': // !=? Should be handled by PEBComp
|
||||
case 'p': // ** should be handled by PEBPower
|
||||
ivl_assert(*this, 0);
|
||||
default:
|
||||
|
|
@ -668,6 +670,18 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'w': /* ==? */
|
||||
case 'W': /* !=? */
|
||||
if ((lp->expr_type() != IVL_VT_BOOL && lp->expr_type() != IVL_VT_LOGIC) ||
|
||||
(rp->expr_type() != IVL_VT_BOOL && rp->expr_type() != IVL_VT_LOGIC)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< " operator may only have INTEGRAL operands."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
63
eval_tree.cc
63
eval_tree.cc
|
|
@ -571,7 +571,8 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
|
|||
|
||||
verinum::V res = eq_res;
|
||||
|
||||
assert(lv.len() == rv.len());
|
||||
// The two expressions should already be padded to the same size.
|
||||
ivl_assert(*this, lv.len() == rv.len());
|
||||
|
||||
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
|
||||
|
||||
|
|
@ -626,7 +627,8 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
|
|||
|
||||
verinum::V res = verinum::V1;
|
||||
|
||||
assert(lv.len() == rv.len());
|
||||
// The two expressions should already be padded to the same size.
|
||||
ivl_assert(*this, lv.len() == rv.len());
|
||||
|
||||
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
|
||||
if (lv.get(idx) != rv.get(idx)) {
|
||||
|
|
@ -644,6 +646,55 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
|
|||
return result;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
|
||||
if (lc == 0 || rc == 0) return 0;
|
||||
|
||||
const verinum&lv = lc->value();
|
||||
const verinum&rv = rc->value();
|
||||
|
||||
const verinum::V eq_res = ne_flag ? verinum::V0 : verinum::V1;
|
||||
const verinum::V ne_res = ne_flag ? verinum::V1 : verinum::V0;
|
||||
|
||||
verinum::V res = eq_res;
|
||||
|
||||
// The two expressions should already be padded to the same size.
|
||||
ivl_assert(*this, lv.len() == rv.len());
|
||||
|
||||
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
|
||||
// An X or Z in the R-value matches any L-value.
|
||||
switch (rv.get(idx)) {
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// An X or Z in the L-value that is not matches by an R-value X/Z returns undefined.
|
||||
switch (lv.get(idx)) {
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// A hard (0/1) mismatch gives a not-equal result.
|
||||
if (rv.get(idx) != lv.get(idx)) {
|
||||
res = ne_res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst*result = new NetEConst(verinum(res, 1));
|
||||
ivl_assert(*this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
NetEConst*res = 0;
|
||||
|
|
@ -657,6 +708,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
|||
res = eval_eqeq_(false, l, r);
|
||||
break;
|
||||
|
||||
case 'w': // Wild equality (==?)
|
||||
res = eval_weqeq_(false, l, r);
|
||||
break;
|
||||
|
||||
case 'G': // >=
|
||||
res = eval_gteq_(l, r);
|
||||
break;
|
||||
|
|
@ -673,6 +728,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
|||
res = eval_eqeq_(true, l, r);
|
||||
break;
|
||||
|
||||
case 'W': // Wild not-equal (!=?)
|
||||
res = eval_weqeq_(true, l, r);
|
||||
break;
|
||||
|
||||
case '<': // Less than
|
||||
res = eval_less_(l, r);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -274,7 +274,18 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
|
||||
if (op_ == 'E' || op_ == 'N') {
|
||||
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
|
||||
width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ);
|
||||
width, op_=='E' ? NetCaseCmp::EEQ : NetCaseCmp::NEQ);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
des->add_node(gate);
|
||||
return osig;
|
||||
}
|
||||
|
||||
if (op_ == 'w' || op_ == 'W') {
|
||||
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
|
||||
width, op_=='w' ? NetCaseCmp::WEQ : NetCaseCmp::WNE);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_ivl_target_H
|
||||
#define IVL_ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -306,8 +306,10 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CONCATZ = 36, /* Transparent concat */
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (==?) */
|
||||
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (casex) */
|
||||
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
|
||||
IVL_LPM_CMP_WEQ= 41,
|
||||
IVL_LPM_CMP_WNE= 42,
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
IVL_LPM_CMP_GE = 1,
|
||||
IVL_LPM_CMP_GT = 2,
|
||||
|
|
|
|||
|
|
@ -188,6 +188,8 @@ TU [munpf]
|
|||
"!=" { return K_NE; }
|
||||
"===" { return K_CEQ; }
|
||||
"!==" { return K_CNE; }
|
||||
"==?" { return K_WEQ; }
|
||||
"!=?" { return K_WNE; }
|
||||
"||" { return K_LOR; }
|
||||
"&&" { return K_LAND; }
|
||||
"&&&" { return K_TAND; }
|
||||
|
|
|
|||
|
|
@ -2365,6 +2365,8 @@ class NetCaseCmp : public NetNode {
|
|||
enum kind_t {
|
||||
EEQ, // ===
|
||||
NEQ, // !==
|
||||
WEQ, // ==?
|
||||
WNE, // !=?
|
||||
XEQ, // casex guard tests
|
||||
ZEQ // casez guard tests
|
||||
};
|
||||
|
|
@ -4137,6 +4139,7 @@ class NetEBComp : public NetEBinary {
|
|||
NetEConst*eval_gt_(const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_gteq_(const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1260,6 +1260,8 @@ const char *human_readable_op(const char op, bool unary)
|
|||
if (unary) type = "~|"; // NOR
|
||||
else type = "!=="; // Case inequality
|
||||
break;
|
||||
case 'w': type = "==?"; break; // Wild equality
|
||||
case 'W': type = "!=?"; break; // Wild inequality
|
||||
|
||||
case 'l': type = "<<(<)"; break; // Left shifts
|
||||
case 'r': type = ">>"; break; // Logical right shift
|
||||
|
|
|
|||
14
parse.y
14
parse.y
|
|
@ -465,7 +465,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
%token <number> BASED_NUMBER DEC_NUMBER UNBASED_NUMBER
|
||||
%token <realtime> REALTIME
|
||||
%token K_PLUS_EQ K_MINUS_EQ K_INCR K_DECR
|
||||
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LP K_LS K_RS K_RSS K_SG
|
||||
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_WEQ K_WNE K_LP K_LS K_RS K_RSS K_SG
|
||||
/* K_CONTRIBUTE is <+, the contribution assign. */
|
||||
%token K_CONTRIBUTE
|
||||
%token K_PO_POS K_PO_NEG K_POW
|
||||
|
|
@ -678,7 +678,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
%left '|'
|
||||
%left '^' K_NXOR K_NOR
|
||||
%left '&' K_NAND
|
||||
%left K_EQ K_NE K_CEQ K_CNE
|
||||
%left K_EQ K_NE K_CEQ K_CNE K_WEQ K_WNE
|
||||
%left K_GE K_LE '<' '>'
|
||||
%left K_LS K_RS K_RSS
|
||||
%left '+' '-'
|
||||
|
|
@ -3284,6 +3284,11 @@ expression
|
|||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_WEQ attribute_list_opt expression
|
||||
{ PEBinary*tmp = new PEBComp('w', $1, $4);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_LE attribute_list_opt expression
|
||||
{ PEBinary*tmp = new PEBComp('L', $1, $4);
|
||||
FILE_NAME(tmp, @2);
|
||||
|
|
@ -3304,6 +3309,11 @@ expression
|
|||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_WNE attribute_list_opt expression
|
||||
{ PEBinary*tmp = new PEBComp('W', $1, $4);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_LOR attribute_list_opt expression
|
||||
{ PEBinary*tmp = new PEBLogic('o', $1, $4);
|
||||
FILE_NAME(tmp, @2);
|
||||
|
|
|
|||
|
|
@ -1235,6 +1235,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
case IVL_LPM_CMP_WNE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
|
|
@ -1390,6 +1392,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net)
|
|||
case IVL_LPM_CMP_EQX:
|
||||
case IVL_LPM_CMP_EQZ:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
case IVL_LPM_CMP_WNE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
|
|
@ -1540,6 +1544,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
case IVL_LPM_CMP_WNE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
|
|
|
|||
6
t-dll.cc
6
t-dll.cc
|
|
@ -1244,6 +1244,12 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
|||
case NetCaseCmp::NEQ:
|
||||
obj->type = IVL_LPM_CMP_NEE;
|
||||
break;
|
||||
case NetCaseCmp::WEQ:
|
||||
obj->type = IVL_LPM_CMP_WEQ;
|
||||
break;
|
||||
case NetCaseCmp::WNE:
|
||||
obj->type = IVL_LPM_CMP_WNE;
|
||||
break;
|
||||
case NetCaseCmp::XEQ:
|
||||
obj->type = IVL_LPM_CMP_EQX;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -394,6 +394,12 @@ static void show_lpm_cmp_eeq(ivl_lpm_t net)
|
|||
case IVL_LPM_CMP_NEE:
|
||||
str = "NEE";
|
||||
break;
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
str = "WEQ";
|
||||
break;
|
||||
case IVL_LPM_CMP_WNE:
|
||||
str = "WNE";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
|
|
@ -1043,6 +1049,8 @@ static void show_lpm(ivl_lpm_t net)
|
|||
case IVL_LPM_CMP_EQX:
|
||||
case IVL_LPM_CMP_EQZ:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
case IVL_LPM_CMP_WNE:
|
||||
show_lpm_cmp_eeq(net);
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -44,8 +44,10 @@ static expr_sign_t expr_get_binary_sign_type(ivl_expr_t expr)
|
|||
switch (ivl_expr_opcode(expr)) {
|
||||
case 'E':
|
||||
case 'e':
|
||||
case 'w':
|
||||
case 'N':
|
||||
case 'n':
|
||||
case 'W':
|
||||
case '<':
|
||||
case 'L':
|
||||
case '>':
|
||||
|
|
@ -417,8 +419,10 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid,
|
|||
case 'p': oper = "**"; break;
|
||||
case 'E': oper = "==="; break;
|
||||
case 'e': oper = "=="; break;
|
||||
case 'w': oper = "==?"; break;
|
||||
case 'N': oper = "!=="; break;
|
||||
case 'n': oper = "!="; break;
|
||||
case 'W': oper = "!=?"; break;
|
||||
case '<': oper = "<"; break;
|
||||
case 'L': oper = "<="; break;
|
||||
case '>': oper = ">"; break;
|
||||
|
|
@ -465,6 +469,14 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid,
|
|||
fprintf(vlog_out, " %s ", oper);
|
||||
emit_expr(scope, oper2, wid, 0, can_skip_unsigned, is_full_prec);
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
fprintf(stderr, "%s:%u: vlog95 error: The wild equality operators "
|
||||
"cannot be converted.\n",
|
||||
ivl_expr_file(expr),
|
||||
ivl_expr_lineno(expr));
|
||||
vlog_errors += 1;
|
||||
|
||||
case 'E':
|
||||
case 'e':
|
||||
case 'N':
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2016 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -398,6 +398,8 @@ static ivl_nexus_t get_lpm_output(ivl_scope_t scope, ivl_lpm_t lpm)
|
|||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
case IVL_LPM_CMP_WNE:
|
||||
case IVL_LPM_CONCAT:
|
||||
case IVL_LPM_CONCATZ:
|
||||
case IVL_LPM_DIVIDE:
|
||||
|
|
@ -1194,19 +1196,19 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm,
|
|||
fprintf(vlog_out, ")");
|
||||
break;
|
||||
case IVL_LPM_CMP_EQX:
|
||||
// HERE: Need to heck that this is not a real nexus.
|
||||
// HERE: Need to check that this is not a real nexus.
|
||||
fprintf(vlog_out, "(");
|
||||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
|
||||
fprintf(vlog_out, " ==? ");
|
||||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
|
||||
fprintf(vlog_out, ")");
|
||||
fprintf(stderr, "%s:%u: vlog95 error: Compare wildcard equal "
|
||||
fprintf(stderr, "%s:%u: vlog95 error: Compare wildcard equal (caseX) "
|
||||
"operator is not supported.\n",
|
||||
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
|
||||
vlog_errors += 1;
|
||||
break;
|
||||
case IVL_LPM_CMP_EQZ:
|
||||
// HERE: Need to heck that this is not a real nexus.
|
||||
// HERE: Need to check that this is not a real nexus.
|
||||
fprintf(vlog_out, "(");
|
||||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
|
||||
fprintf(vlog_out, " == ");
|
||||
|
|
@ -1245,6 +1247,28 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm,
|
|||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
|
||||
fprintf(vlog_out, ")");
|
||||
break;
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
fprintf(vlog_out, "(");
|
||||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
|
||||
fprintf(vlog_out, " ==? ");
|
||||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
|
||||
fprintf(vlog_out, ")");
|
||||
fprintf(stderr, "%s:%u: vlog95 error: Wild equality "
|
||||
"operator is not supported.\n",
|
||||
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
|
||||
vlog_errors += 1;
|
||||
break;
|
||||
case IVL_LPM_CMP_WNE:
|
||||
fprintf(vlog_out, "(");
|
||||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
|
||||
fprintf(vlog_out, " !=? ");
|
||||
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
|
||||
fprintf(vlog_out, ")");
|
||||
fprintf(stderr, "%s:%u: vlog95 error: Wild inequality "
|
||||
"operator is not supported.\n",
|
||||
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
|
||||
vlog_errors += 1;
|
||||
break;
|
||||
/* A concat-Z should never be generated, but report it as an
|
||||
* error if one is generated. */
|
||||
case IVL_LPM_CONCATZ:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -398,6 +398,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
case IVL_LPM_CONCATZ:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
case IVL_LPM_CMP_WNE:
|
||||
case IVL_LPM_CMP_EQX:
|
||||
case IVL_LPM_CMP_EQZ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -57,6 +57,8 @@ static void draw_binary_real(ivl_expr_t expr)
|
|||
switch (ivl_expr_opcode(expr)) {
|
||||
case 'E':
|
||||
case 'N':
|
||||
case 'w':
|
||||
case 'W':
|
||||
case 'l':
|
||||
case 'r':
|
||||
case 'R':
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2013-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -385,8 +385,7 @@ static void draw_binary_vec4_compare(ivl_expr_t expr)
|
|||
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
|
||||
break;
|
||||
case 'n': /* != */
|
||||
fprintf(vvp_out, " %%cmp/e;\n");
|
||||
fprintf(vvp_out, " %%flag_inv 4;\n");
|
||||
fprintf(vvp_out, " %%cmp/ne;\n");
|
||||
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
|
||||
break;
|
||||
case 'E': /* === */
|
||||
|
|
@ -394,10 +393,17 @@ static void draw_binary_vec4_compare(ivl_expr_t expr)
|
|||
fprintf(vvp_out, " %%flag_get/vec4 6;\n");
|
||||
break;
|
||||
case 'N': /* !== */
|
||||
fprintf(vvp_out, " %%cmp/e;\n");
|
||||
fprintf(vvp_out, " %%flag_inv 6;\n");
|
||||
fprintf(vvp_out, " %%cmp/ne;\n");
|
||||
fprintf(vvp_out, " %%flag_get/vec4 6;\n");
|
||||
break;
|
||||
case 'w': /* ==? */
|
||||
fprintf(vvp_out, " %%cmp/we;\n");
|
||||
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
|
||||
break;
|
||||
case 'W': /* !=? */
|
||||
fprintf(vvp_out, " %%cmp/wne;\n");
|
||||
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
|
@ -689,8 +695,10 @@ static void draw_binary_vec4(ivl_expr_t expr)
|
|||
|
||||
case 'e': /* == */
|
||||
case 'E': /* === */
|
||||
case 'n': /* !== */
|
||||
case 'n': /* != */
|
||||
case 'N': /* !== */
|
||||
case 'w': /* ==? */
|
||||
case 'W': /* !=? */
|
||||
draw_binary_vec4_compare(expr);
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -1521,6 +1521,16 @@ static void draw_lpm_cmp(ivl_lpm_t net)
|
|||
type = "nee";
|
||||
signed_string = "";
|
||||
break;
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
assert(dtc != IVL_VT_REAL); /* Should never get here! */
|
||||
type = "weq";
|
||||
signed_string = "";
|
||||
break;
|
||||
case IVL_LPM_CMP_WNE:
|
||||
assert(dtc != IVL_VT_REAL); /* Should never get here! */
|
||||
type = "wne";
|
||||
signed_string = "";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
|
@ -2143,6 +2153,8 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_CMP_WEQ:
|
||||
case IVL_LPM_CMP_WNE:
|
||||
draw_lpm_cmp(net);
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -684,6 +684,8 @@ similar:
|
|||
<label> .cmp/gt <wid>, <A>, <B>;
|
||||
<label> .cmp/ge.s <wid>, <A>, <B>;
|
||||
<label> .cmp/gt.s <wid>, <A>, <B>;
|
||||
<label> .cmp/weq <wid>, <A>, <B>;
|
||||
<label> .cmp/wne <wid>, <A>, <B>;
|
||||
|
||||
Whereas the arithmetic statements generate an output the width of
|
||||
<wid>, the comparisons produce a single bit vector result. The plain
|
||||
|
|
|
|||
72
vvp/arith.cc
72
vvp/arith.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -868,6 +868,76 @@ void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
recv_vec4_base_(ptr, bit, BIT4_0);
|
||||
}
|
||||
|
||||
vvp_cmp_weq::vvp_cmp_weq(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_weq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t eeq (1);
|
||||
eeq.set_bit(0, BIT4_1);
|
||||
|
||||
assert(op_a_.size() == op_b_.size());
|
||||
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
||||
vvp_bit4_t a = op_a_.value(idx);
|
||||
vvp_bit4_t b = op_b_.value(idx);
|
||||
if (b == BIT4_X)
|
||||
continue;
|
||||
else if (b == BIT4_Z)
|
||||
continue;
|
||||
else if (a == BIT4_X)
|
||||
eeq.set_bit(0, BIT4_X);
|
||||
else if (a == BIT4_Z)
|
||||
eeq.set_bit(0, BIT4_X);
|
||||
else if (a != b) {
|
||||
eeq.set_bit(0, BIT4_0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
net->send_vec4(eeq, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_wne::vvp_cmp_wne(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_wne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t eeq (1);
|
||||
eeq.set_bit(0, BIT4_0);
|
||||
|
||||
assert(op_a_.size() == op_b_.size());
|
||||
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
|
||||
vvp_bit4_t a = op_a_.value(idx);
|
||||
vvp_bit4_t b = op_b_.value(idx);
|
||||
if (b == BIT4_X)
|
||||
continue;
|
||||
else if (b == BIT4_Z)
|
||||
continue;
|
||||
else if (a == BIT4_X)
|
||||
eeq.set_bit(0, BIT4_X);
|
||||
else if (a == BIT4_Z)
|
||||
eeq.set_bit(0, BIT4_X);
|
||||
else if (a != b) {
|
||||
eeq.set_bit(0, BIT4_1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
net->send_vec4(eeq, 0);
|
||||
}
|
||||
|
||||
|
||||
vvp_shiftl::vvp_shiftl(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
|
|
|
|||
20
vvp/arith.h
20
vvp/arith.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_arith_H
|
||||
#define IVL_arith_H
|
||||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -200,6 +200,24 @@ class vvp_cmp_ne : public vvp_arith_ {
|
|||
|
||||
};
|
||||
|
||||
class vvp_cmp_weq : public vvp_arith_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_weq(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
class vvp_cmp_wne : public vvp_arith_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_wne(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This base class implements both GT and GE comparisons. The derived
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_codes_H
|
||||
#define IVL_codes_H
|
||||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -75,6 +75,8 @@ extern bool of_CMPIS(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_CMPIU(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPWE(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPWNE(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);
|
||||
extern bool of_CMPWU(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -117,21 +117,23 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%cassign/vec4", of_CASSIGN_VEC4, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%cassign/vec4/off",of_CASSIGN_VEC4_OFF,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
||||
{ "%cassign/wr", of_CASSIGN_WR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%cast2", of_CAST2, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/e", of_CMPE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/ne", of_CMPNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/str",of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/u", of_CMPU, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmpi/e", of_CMPIE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmpi/ne",of_CMPINE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cast2", of_CAST2, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/e", of_CMPE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/ne", of_CMPNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/str", of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/u", of_CMPU, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/we", of_CMPWE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/wne", of_CMPWNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%cmpi/e", of_CMPIE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmpi/ne", of_CMPINE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%concat/str", of_CONCAT_STR, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%concat/vec4", of_CONCAT_VEC4, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%concati/str", of_CONCATI_STR, 1,{OA_STRING,OA_NONE, OA_NONE} },
|
||||
|
|
@ -1402,6 +1404,38 @@ void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv)
|
|||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
void compile_cmp_weq(char*label, long wid,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert( wid > 0 );
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s .cmp/weq has wrong number of symbols\n",label);
|
||||
compile_errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_arith_ *arith = new vvp_cmp_weq(wid);
|
||||
|
||||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
void compile_cmp_wne(char*label, long wid,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert( wid > 0 );
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s .cmp/wne has wrong number of symbols\n",label);
|
||||
compile_errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_arith_ *arith = new vvp_cmp_wne(wid);
|
||||
|
||||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
void compile_delay(char*label, unsigned width,
|
||||
vvp_delay_t*delay, struct symb_s arg)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_compile_H
|
||||
#define IVL_compile_H
|
||||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -195,6 +195,10 @@ extern void compile_cmp_ge(char*label, long width, bool signed_flag,
|
|||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_gt(char*label, long width, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_weq(char*label, long width,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_wne(char*label, long width,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_arith_mult_r(char*label, unsigned argc,
|
||||
struct symb_s*argv);
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ static char* strdupnew(char const *str)
|
|||
".cmp/gt" { return K_CMP_GT; }
|
||||
".cmp/gt.r" { return K_CMP_GT_R; }
|
||||
".cmp/gt.s" { return K_CMP_GT_S; }
|
||||
".cmp/weq" { return K_CMP_WEQ; }
|
||||
".cmp/wne" { return K_CMP_WNE; }
|
||||
".concat" { return K_CONCAT; }
|
||||
".concat8" { return K_CONCAT8; }
|
||||
".delay" { return K_DELAY; }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -302,6 +302,18 @@ The %cmp/ne and %cmpi/ne variants are the same as the %cmp/e and
|
|||
eliminate the need for a %flag_inv instruction to implement != and !==
|
||||
operations.
|
||||
|
||||
* %cmp/we
|
||||
* %cmp/wne
|
||||
|
||||
These instructions perform a wild comparison of two vectors of equal
|
||||
size. Two values are pulled from the top of the stack, and not replaced.
|
||||
The results are written into flag bit 4. The comparisons work like eq/ne
|
||||
except an x/z bit in the r-value will match any l-value bit.
|
||||
|
||||
The %cmp/wne variant is the same as %cmp/we, but the 4 flag is inverted
|
||||
in order to eliminate the need for a %flag_inv instruction to implement
|
||||
the !=? operator.
|
||||
|
||||
* %cmp/wr
|
||||
|
||||
Compare real values for equality and less-then. This opcode pops to
|
||||
|
|
@ -1299,7 +1311,7 @@ table for the xor is:
|
|||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
|
|||
14
vvp/parse.y
14
vvp/parse.y
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -80,7 +80,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_OBJ K_ARRAY_R K_ARRAY_S K_ARRAY_STR K_ARRAY_PORT
|
||||
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
|
||||
%token K_CLASS
|
||||
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ
|
||||
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ K_CMP_WEQ K_CMP_WNE
|
||||
%token K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
|
||||
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
|
||||
%token K_CONCAT K_CONCAT8 K_DEBUG K_DELAY K_DFF_N K_DFF_N_ACLR
|
||||
|
|
@ -475,6 +475,16 @@ statement
|
|||
compile_cmp_gt($1, $3, true, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_WEQ T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_weq($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CMP_WNE T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_cmp_wne($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
/* Delay nodes take a set of numbers or a set of inputs. The delay
|
||||
node takes two form, one with an array of constants and a single
|
||||
input, and another with an array of inputs. */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -1945,6 +1945,71 @@ bool of_CMPX(vthread_t thr, vvp_code_t)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void do_CMPWE(vthread_t thr, const vvp_vector4_t&lval, const vvp_vector4_t&rval)
|
||||
{
|
||||
assert(rval.size() == lval.size());
|
||||
|
||||
if (lval.has_xz() || rval.has_xz()) {
|
||||
|
||||
unsigned wid = lval.size();
|
||||
vvp_bit4_t eq = BIT4_1;
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_bit4_t lv = lval.value(idx);
|
||||
vvp_bit4_t rv = rval.value(idx);
|
||||
|
||||
if (bit4_is_xz(rv))
|
||||
continue;
|
||||
if ((eq == BIT4_1) && bit4_is_xz(lv))
|
||||
eq = BIT4_X;
|
||||
if ((lv == BIT4_0) && (rv==BIT4_1))
|
||||
eq = BIT4_0;
|
||||
if ((lv == BIT4_1) && (rv==BIT4_0))
|
||||
eq = BIT4_0;
|
||||
|
||||
if (eq == BIT4_0)
|
||||
break;
|
||||
}
|
||||
|
||||
thr->flags[4] = eq;
|
||||
|
||||
} else {
|
||||
// If there are no XZ bits anywhere, then the results of
|
||||
// ==? match the === test.
|
||||
thr->flags[4] = (lval.eeq(rval)? BIT4_1 : BIT4_0);
|
||||
}
|
||||
}
|
||||
|
||||
bool of_CMPWE(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
// We are going to pop these and push nothing in their
|
||||
// place, but for now it is more efficient to use a constant
|
||||
// reference. When we finish, pop the stack without copies.
|
||||
const vvp_vector4_t&rval = thr->peek_vec4(0);
|
||||
const vvp_vector4_t&lval = thr->peek_vec4(1);
|
||||
|
||||
do_CMPWE(thr, lval, rval);
|
||||
|
||||
thr->pop_vec4(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_CMPWNE(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
// We are going to pop these and push nothing in their
|
||||
// place, but for now it is more efficient to use a constant
|
||||
// reference. When we finish, pop the stack without copies.
|
||||
const vvp_vector4_t&rval = thr->peek_vec4(0);
|
||||
const vvp_vector4_t&lval = thr->peek_vec4(1);
|
||||
|
||||
do_CMPWE(thr, lval, rval);
|
||||
|
||||
thr->flags[4] = ~thr->flags[4];
|
||||
|
||||
thr->pop_vec4(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_CMPWR(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
double r = thr->pop_real();
|
||||
|
|
|
|||
Loading…
Reference in New Issue