From 3fc9ad2db0754a777f5a8e01d07c73333d19c3d5 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 17 Nov 2017 19:32:09 -0800 Subject: [PATCH] =?UTF-8?q?Add=20support=20for=20the=20wild=20compare=20op?= =?UTF-8?q?erators=20=3D=3D=3F=20and=20!=3D=3F?= --- design_dump.cc | 18 ++++++++-- elab_expr.cc | 14 ++++++++ eval_tree.cc | 63 +++++++++++++++++++++++++++++++++-- expr_synth.cc | 13 +++++++- ivl_target.h | 6 ++-- lexor.lex | 2 ++ netlist.h | 3 ++ netmisc.cc | 2 ++ parse.y | 14 ++++++-- t-dll-api.cc | 6 ++++ t-dll.cc | 6 ++++ tgt-stub/stub.c | 10 +++++- tgt-vlog95/expr.c | 14 +++++++- tgt-vlog95/logic_lpm.c | 32 +++++++++++++++--- tgt-vvp/draw_net_input.c | 4 ++- tgt-vvp/eval_real.c | 4 ++- tgt-vvp/eval_vec4.c | 20 +++++++---- tgt-vvp/vvp_scope.c | 14 +++++++- vvp/README.txt | 4 ++- vvp/arith.cc | 72 +++++++++++++++++++++++++++++++++++++++- vvp/arith.h | 20 ++++++++++- vvp/codes.h | 4 ++- vvp/compile.cc | 66 +++++++++++++++++++++++++++--------- vvp/compile.h | 6 +++- vvp/lexor.lex | 2 ++ vvp/opcodes.txt | 16 +++++++-- vvp/parse.y | 14 ++++++-- vvp/vthread.cc | 67 ++++++++++++++++++++++++++++++++++++- 28 files changed, 465 insertions(+), 51 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index d42f61485..590ec1e07 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -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; diff --git a/elab_expr.cc b/elab_expr.cc index 019381481..6699823f6 100644 --- a/elab_expr.cc +++ b/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; } diff --git a/eval_tree.cc b/eval_tree.cc index 1da857035..7536bd56b 100644 --- a/eval_tree.cc +++ b/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(le); + const NetEConst*rc = dynamic_cast(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; diff --git a/expr_synth.cc b/expr_synth.cc index cb8ba87f0..6f8ca29b9 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -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)); diff --git a/ivl_target.h b/ivl_target.h index 42dbe167b..f23c3fb58 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -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, diff --git a/lexor.lex b/lexor.lex index 50d8c6ab9..37c3e0207 100644 --- a/lexor.lex +++ b/lexor.lex @@ -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; } diff --git a/netlist.h b/netlist.h index 09856c198..4ba553407 100644 --- a/netlist.h +++ b/netlist.h @@ -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; }; /* diff --git a/netmisc.cc b/netmisc.cc index 1adf66658..59da76061 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -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 diff --git a/parse.y b/parse.y index bf7847ec1..206b6fbb9 100644 --- a/parse.y +++ b/parse.y @@ -465,7 +465,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %token BASED_NUMBER DEC_NUMBER UNBASED_NUMBER %token 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 %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); diff --git a/t-dll-api.cc b/t-dll-api.cc index c07e18366..9c8283ab3 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -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: diff --git a/t-dll.cc b/t-dll.cc index 39f1f892c..29e874154 100644 --- a/t-dll.cc +++ b/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; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index ea71358be..15767349a 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -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; diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index f516a7a9e..b47f6f4d4 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -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': diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 3754c82c9..024325090 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -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: diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index aa43b2203..86ec41657 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -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: diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index a3c4d69c6..d7f1cfb4b 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -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': diff --git a/tgt-vvp/eval_vec4.c b/tgt-vvp/eval_vec4.c index 2afd1fbbc..c4516029e 100644 --- a/tgt-vvp/eval_vec4.c +++ b/tgt-vvp/eval_vec4.c @@ -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; diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 6486d72cb..b272c36fa 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -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; diff --git a/vvp/README.txt b/vvp/README.txt index a6bfe2c01..dea23ae1a 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -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: