Merge branch 'master' of ssh://steve-icarus@icarus.com/home/u/icarus/steve/git/verilog

This commit is contained in:
Stephen Williams 2007-10-09 10:12:55 -07:00
commit c08e547d1d
12 changed files with 238 additions and 358 deletions

164
PExpr.h
View File

@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.90 2007/06/04 19:14:06 steve Exp $"
#endif
# include <string>
# include <vector>
@ -659,6 +656,10 @@ class PECallFunction : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool sys_task_arg) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
private:
pform_name_t path_;
svector<PExpr *> parms_;
@ -673,160 +674,9 @@ class PECallFunction : public PExpr {
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
};
/*
* $Log: PExpr.h,v $
* Revision 1.90 2007/06/04 19:14:06 steve
* Build errors in picky GCC compilers.
*
* Revision 1.89 2007/06/04 02:19:07 steve
* Handle bit/part select of array words in nets.
*
* Revision 1.88 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.87 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.86 2006/11/10 04:54:26 steve
* Add test_width methods for PETernary and PEString.
*
* Revision 1.85 2006/11/04 06:19:24 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.84 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.83 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.82 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.81 2006/04/28 04:28:35 steve
* Allow concatenations as arguments to inout ports.
*
* Revision 1.80 2006/04/16 00:54:04 steve
* Cleanup lval part select handling.
*
* Revision 1.79 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.78 2006/03/25 02:36:26 steve
* Get rid of excess PESTring:: prefix within class declaration.
*
* Revision 1.77 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.76 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.75 2005/12/07 04:04:23 steve
* Allow constant concat expressions.
*
* Revision 1.74 2005/11/27 17:01:56 steve
* Fix for stubborn compiler.
*
* Revision 1.73 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.72 2005/11/10 13:28:11 steve
* Reorganize signal part select handling, and add support for
* indexed part selects.
*
* Expand expression constant propagation to eliminate extra
* sums in certain cases.
*
* Revision 1.71 2005/10/04 04:09:25 steve
* Add support for indexed select attached to parameters.
*
* Revision 1.70 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
*
* Revision 1.69 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.68 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.67 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.66 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space.
*
* Revision 1.65 2003/02/08 19:49:21 steve
* Calculate delay statement delays using elaborated
* expressions instead of pre-elaborated expression
* trees.
*
* Remove the eval_pexpr methods from PExpr.
*
* Revision 1.64 2003/01/30 16:23:07 steve
* Spelling fixes.
*
* Revision 1.63 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.62 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.61 2002/06/04 05:38:43 steve
* Add support for memory words in l-value of
* blocking assignments, and remove the special
* NetAssignMem class.
*
* Revision 1.60 2002/05/23 03:08:51 steve
* Add language support for Verilog-2001 attribute
* syntax. Hook this support into existing $attribute
* handling, and add number and void value types.
*
* Add to the ivl_target API new functions for access
* of complex attributes attached to gates.
*
* Revision 1.59 2002/04/23 03:53:59 steve
* Add support for non-constant bit select.
*
* Revision 1.58 2002/04/14 03:55:25 steve
* Precalculate unary - if possible.
*
* Revision 1.57 2002/04/13 02:33:17 steve
* Detect missing indices to memories (PR#421)
*
* Revision 1.56 2002/03/09 04:02:26 steve
* Constant expressions are not l-values for task ports.
*
* Revision 1.55 2002/03/09 02:10:22 steve
* Add the NetUserFunc netlist node.
*
* Revision 1.54 2001/12/30 21:32:03 steve
* Support elaborate_net for PEString objects.
*
* Revision 1.53 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.52 2001/11/08 05:15:50 steve
* Remove string paths from PExpr elaboration.
*
* Revision 1.51 2001/11/07 04:26:46 steve
* elaborate_lnet uses scope instead of string path.
*
* Revision 1.50 2001/11/07 04:01:59 steve
* eval_const uses scope instead of a string path.
*/
#endif

View File

@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compiler.h,v 1.33 2007/04/19 02:52:53 steve Exp $"
#endif
# include <list>
# include <map>
@ -32,7 +29,11 @@
*/
/* The integer_width is the width of integer variables. */
/*
* The integer_width is the width of integer variables. This is also
* the minimum width of unsized integers when they are found in
* self-determined contexts.
*/
extern unsigned integer_width;
/* The TIME_WIDTH is the width of time variables. */
@ -154,66 +155,4 @@ struct sfunc_return_type {
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
extern int load_sys_func_table(const char*path);
/*
* $Log: compiler.h,v $
* Revision 1.33 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.32 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.31 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.30 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.29 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.28 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
*
* Revision 1.27 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
*
* Revision 1.26 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
* Revision 1.25 2004/09/25 01:58:44 steve
* Add a debug_elaborate flag
*
* Revision 1.24 2004/09/10 23:51:42 steve
* Fix the evaluation of constant ternary expressions.
*
* Revision 1.23 2004/09/05 17:44:41 steve
* Add support for module instance arrays.
*
* Revision 1.22 2004/03/10 04:51:24 steve
* Add support for system function table files.
*
* Revision 1.21 2004/03/09 04:29:42 steve
* Separate out the lookup_sys_func table, for eventual
* support for function type tables.
*
* Remove ipal compile flags.
*
* Revision 1.20 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.19 2003/11/13 05:55:33 steve
* Move the DLL= flag to target config files.
*
* Revision 1.18 2003/11/08 20:06:21 steve
* Spelling fixes in comments.
*
* Revision 1.17 2003/09/25 00:25:14 steve
* Summary list of missing modules.
*
* Revision 1.16 2003/03/01 06:25:30 steve
* Add the lex_strings string handler, and put
* scope names and system task/function names
* into this table. Also, permallocate event
* names from the beginning.
*/
#endif

View File

@ -16,16 +16,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cprop.cc,v 1.56 2007/03/07 00:38:15 steve Exp $"
#endif
# include "config.h"
# include "netlist.h"
# include "netmisc.h"
# include "functor.h"
# include <assert.h>
# include "ivl_assert.h"
@ -846,15 +843,17 @@ struct cprop_dc_functor : public functor_t {
void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
{
// 'bz constant values drive high impedance to whatever is
// connected to it. In other words, it is a noop.
// connected to it. In other words, it is a noop. But that is
// only true if *all* the bits of the vectors.
{ unsigned tmp = 0;
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1)
ivl_assert(*obj, obj->pin_count()==1);
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (obj->value(idx) == verinum::Vz) {
obj->pin(idx).unlink();
tmp += 1;
}
}
if (tmp == obj->pin_count()) {
if (tmp == obj->width()) {
delete obj;
return;
}
@ -948,81 +947,3 @@ void cprop(Design*des)
des->functor(&dc);
}
/*
* $Log: cprop.cc,v $
* Revision 1.56 2007/03/07 00:38:15 steve
* Lint fixes.
*
* Revision 1.55 2006/05/24 04:32:57 steve
* Fix handling of ternary-to-bufif0 constant propagation.
*
* Revision 1.54 2005/07/15 19:22:52 steve
* bufif enable is LOGIC.
*
* Revision 1.53 2005/05/15 04:44:30 steve
* Disable obsolete logic constant fixup code.
*
* Revision 1.52 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
*
* Revision 1.51 2005/02/12 22:52:45 steve
* Fix copyright notice.
*
* Revision 1.50 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,
* Reduce NetMux devices to bufif when appropriate.
*
* Revision 1.49 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors.
*
* Revision 1.48 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.47 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.46 2003/11/08 17:53:34 steve
* Do not remove constants accessible to VPI.
*
* Revision 1.45 2003/10/31 02:40:06 steve
* Donot elide FF that has set or clr connections.
*
* Revision 1.44 2003/04/25 05:06:32 steve
* Handle X values in constant == nets.
*
* Revision 1.43 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.42 2003/02/26 01:29:24 steve
* LPM objects store only their base names.
*
* Revision 1.41 2003/01/30 16:23:07 steve
* Spelling fixes.
*
* Revision 1.40 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.39 2002/08/20 04:12:22 steve
* Copy gate delays when doing gate delay substitutions.
*
* Revision 1.38 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.37 2002/06/25 01:33:22 steve
* Cache calculated driven value.
*
* Revision 1.36 2002/06/24 01:49:38 steve
* Make link_drive_constant cache its results in
* the Nexus, to improve cprop performance.
*
* Revision 1.35 2002/05/26 01:39:02 steve
* Carry Verilog 2001 attributes with processes,
* all the way through to the ivl_target API.
*
* Divide signal reference counts between rval
* and lval references.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2006 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2007 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
@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_expr.cc,v 1.126 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
# include "compiler.h"
@ -38,7 +35,8 @@ unsigned PExpr::test_width(Design*des, NetScope*scope,
{
if (debug_elaborate) {
cerr << get_line() << ": debug: test_width defaults to "
<< min << ", ignoring unsized_flag" << endl;
<< min << ", ignoring unsized_flag. typeid="
<< typeid(*this).name() << endl;
}
return min;
}
@ -148,6 +146,11 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
{
bool flag;
if (debug_elaborate) {
cerr << get_line() << ": debug: elaborate expression "
<< *this << " expr_wid=" << expr_wid << endl;
}
NetEBinary*tmp;
switch (op_) {
@ -307,6 +310,61 @@ unsigned PEBShift::test_width(Design*des, NetScope*scope,
return wid_left;
}
unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const
{
perm_string name = peek_tail_name(path_);
if (name=="$signed"|| name=="$unsigned") {
PExpr*expr = parms_[0];
if (expr == 0)
return 0;
unsigned wid = expr->test_width(des, scope, min, lval, unsized_flag);
if (debug_elaborate)
cerr << get_line() << ": debug: test_width"
<< " of $signed/$unsigned returns test_width"
<< " of subexpression." << endl;
return wid;
}
if (debug_elaborate)
cerr << get_line() << ": debug: test_width "
<< "of system function " << name
<< " returns 32 always?" << endl;
return 32;
}
unsigned PECallFunction::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const
{
if (peek_tail_name(path_)[0] == '$')
return test_width_sfunc_(des, scope, min, lval, unsized_flag);
NetFuncDef*def = des->find_function(scope, path_);
if (def == 0) {
if (debug_elaborate)
cerr << get_line() << ": debug: test_width "
<< "cannot find definition of " << path_
<< " in " << scope_path(scope) << "." << endl;
return 0;
}
NetScope*dscope = def->scope();
assert(dscope);
if (NetNet*res = dscope->find_signal(dscope->basename())) {
if (debug_elaborate)
cerr << get_line() << ": debug: test_width "
<< "of function returns width " << res->vector_width()
<< "." << endl;
return res->vector_width();
}
ivl_assert(*this, 0);
return 0;
}
/*
* Given a call to a system function, generate the proper expression

View File

@ -45,14 +45,19 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
one. This expands the expression to account for the largest
possible result.
Remember to handle the special case of an unsized constant,
which we define to be at least "integer_width" bits.
The set_width applied to a constant value will only
truncate the constant so far as it can still hold its
logical value, so this is safe to do. */
if ( (tmp = dynamic_cast<NetEConst*>(r))
&& (! tmp->has_width())
&& (tmp->expr_width() > l->expr_width()) ) {
&& (tmp->expr_width() > l->expr_width() || integer_width > l->expr_width()) ) {
unsigned target_width = l->expr_width() + 1;
if (target_width < integer_width)
target_width = integer_width;
r->set_width(target_width);
/* Note: This constant value will not gain a defined
@ -61,9 +66,11 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
&& (! tmp->has_width())
&& (tmp->expr_width() > r->expr_width()) ) {
&& (tmp->expr_width() > r->expr_width() || integer_width > r->expr_width()) ) {
unsigned target_width = r->expr_width() + 1;
if (target_width < integer_width)
target_width = integer_width;
l->set_width(target_width);
/* Note: This constant value will not gain a defined

View File

@ -80,9 +80,13 @@ static void show_function_call(ivl_expr_t net, unsigned ind)
ivl_scope_t def = ivl_expr_def(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
unsigned idx;
fprintf(out, "%*s<%s %s function %s>\n", ind, "",
vt, sign, ivl_scope_name(def));
fprintf(out, "%*s<%s %s function %s with %u arguments>\n", ind, "",
vt, sign, ivl_scope_name(def), ivl_expr_parms(net));
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1)
show_expression(ivl_expr_parm(net,idx), ind+4);
}
static void show_memory_expression(ivl_expr_t net, unsigned ind)

View File

@ -36,6 +36,9 @@ int number_is_unknown(ivl_expr_t ex)
const char*bits;
unsigned idx;
if (ivl_expr_type(ex) == IVL_EX_ULONG)
return 0;
assert(ivl_expr_type(ex) == IVL_EX_NUMBER);
bits = ivl_expr_bits(ex);
@ -66,6 +69,10 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
if (bits[idx] != '0')
return 0;
/* Negative numbers are not "immediate". */
if (ivl_expr_signed(ex) && bits[ivl_expr_width(ex)-1]=='1')
return 0;
return 1;
}
@ -290,13 +297,7 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
return draw_binary_expr_eq_real(exp);
}
if ((ivl_expr_type(re) == IVL_EX_ULONG)
&& (0 == (ivl_expr_uvalue(re) & ~0xffff)))
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
if ((ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re))
&& number_is_immediate(re, 16))
if (number_is_immediate(re,16) && !number_is_unknown(re))
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
assert(ivl_expr_value(le) == IVL_VT_LOGIC
@ -683,42 +684,78 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
assert(ivl_expr_value(re) == IVL_VT_LOGIC
|| ivl_expr_value(re) == IVL_VT_BOOL);
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
lv.wid = 0;
rv.wid = 0;
switch (ivl_expr_opcode(exp)) {
case 'G':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
if (number_is_immediate(le,16) && !number_is_unknown(le)) {
unsigned imm = get_number_immediate(le);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
rv.base, imm, rv.wid);
} else {
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
rv.base, lv.base, lv.wid);
}
fprintf(vvp_out, " %%or 5, 4, 1;\n");
break;
case 'L':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
if (number_is_immediate(re,16) && !number_is_unknown(re)) {
unsigned imm = get_number_immediate(re);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
lv.base, imm, lv.wid);
} else {
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
lv.base, rv.base, lv.wid);
}
fprintf(vvp_out, " %%or 5, 4, 1;\n");
break;
case '<':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
if (number_is_immediate(re,16) && !number_is_unknown(re)) {
unsigned imm = get_number_immediate(re);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
lv.base, imm, lv.wid);
} else {
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
lv.base, rv.base, lv.wid);
}
break;
case '>':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
if (number_is_immediate(le,16) && !number_is_unknown(le)) {
unsigned imm = get_number_immediate(le);
assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag,
rv.base, imm, rv.wid);
} else {
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
rv.base, lv.base, lv.wid);
}
break;
default:
assert(0);
}
clr_vector(lv);
clr_vector(rv);
if (lv.wid > 0) clr_vector(lv);
if (rv.wid > 0) clr_vector(rv);
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
lv.base = 5;
@ -1365,6 +1402,12 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
load the constant bit values. */
res.base = allocate_vector(wid);
if ((!number_is_unknown(exp)) && number_is_immediate(exp, 16)) {
int val = get_number_immediate(exp);
fprintf(vvp_out, " %%movi %u, %d, %u;\n", res.base, val, wid);
return res;
}
idx = 0;
while (idx < nwid) {
unsigned cnt;

View File

@ -412,17 +412,8 @@ static char* draw_C4_to_string(ivl_net_const_t cptr)
dp += strlen(dp);
for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
switch (bits[ivl_const_width(cptr)-idx-1]) {
case '0':
*dp++ = '0';
break;
case '1':
*dp++ = '1';
break;
default:
*dp++ = bits[idx];
break;
}
char bitchar = bits[ivl_const_width(cptr)-idx-1];
*dp++ = bitchar;
assert((dp - result) < result_len);
}

View File

@ -54,6 +54,7 @@ extern bool of_BLEND(vthread_t thr, vvp_code_t code);
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_V(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_CMPU(vthread_t thr, vvp_code_t code);
@ -103,6 +104,7 @@ extern bool of_MOD_S(vthread_t thr, vvp_code_t code);
extern bool of_MOD_WR(vthread_t thr, vvp_code_t code);
extern bool of_MOV(vthread_t thr, vvp_code_t code);
extern bool of_MOV_WR(vthread_t thr, vvp_code_t code);
extern bool of_MOVI(vthread_t thr, vvp_code_t code);
extern bool of_MUL(vthread_t thr, vvp_code_t code);
extern bool of_MUL_WR(vthread_t thr, vvp_code_t code);
extern bool of_MULI(vthread_t thr, vvp_code_t code);

View File

@ -124,6 +124,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cmp/x", of_CMPX, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/z", of_CMPZ, 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} },
{ "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
@ -164,6 +165,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%mod/wr", of_MOD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mov/wr", of_MOV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%movi", of_MOVI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mul", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mul/wr", of_MUL_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },

View File

@ -189,6 +189,12 @@ The %cmp/u and %cmp/s differ only in the handling of the lt bit. The
compare. In either case, if either operand contains x or z, then lt
bit gets the x value.
* %cmpi/s <bit-l>, <immr>, <wid>
* %cmpi/u <bit-l>, <immr>, <wid>
These instructions are similar to the %cmp instructions above, except
that the right hand operand is an immediate value. This is a positive
number that the vector is compared with.
* %cmp/wr <bit-l>, <bit-r>

View File

@ -867,12 +867,6 @@ bool of_CMPS(vthread_t thr, vvp_code_t cp)
/* Correct the lt bit to account for the sign of the parameters. */
if (lt != BIT4_X) {
/* If both numbers are negative (and not equal) then
switch the direction of the lt. */
if ((sig1 == BIT4_1) && (sig2 == BIT4_1) && (eq != BIT4_1))
lt = ~lt;
/* If the first is negative and the last positive, then
a < b for certain. */
if ((sig1 == BIT4_1) && (sig2 == BIT4_0))
@ -891,6 +885,55 @@ bool of_CMPS(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_CMPIS(vthread_t thr, vvp_code_t cp)
{
vvp_bit4_t eq = BIT4_1;
vvp_bit4_t eeq = BIT4_1;
vvp_bit4_t lt = BIT4_0;
unsigned idx1 = cp->bit_idx[0];
unsigned imm = cp->bit_idx[1];
const unsigned end1 = (idx1 < 4)? idx1 : idx1 + cp->number - 1;
thr_check_addr(thr, end1);
const vvp_bit4_t sig1 = thr_get_bit(thr, end1);
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
vvp_bit4_t lv = thr_get_bit(thr, idx1);
vvp_bit4_t rv = (imm & 1)? BIT4_1 : BIT4_0;
imm >>= 1;
if (lv > rv) {
lt = BIT4_0;
eeq = BIT4_0;
} else if (lv < rv) {
lt = BIT4_1;
eeq = BIT4_0;
}
if (eq != BIT4_X) {
if ((lv == BIT4_0) && (rv != BIT4_0))
eq = BIT4_0;
if ((lv == BIT4_1) && (rv != BIT4_1))
eq = BIT4_0;
if (bit4_is_xz(lv) || bit4_is_xz(rv))
eq = BIT4_X;
}
if (idx1 >= 4) idx1 += 1;
}
if (eq == BIT4_X)
lt = BIT4_X;
else if (sig1 == BIT4_1)
lt = BIT4_1;
thr_put_bit(thr, 4, eq);
thr_put_bit(thr, 5, lt);
thr_put_bit(thr, 6, eeq);
return true;
}
bool of_CMPIU(vthread_t thr, vvp_code_t cp)
{
vvp_bit4_t eq = BIT4_1;
@ -2531,6 +2574,20 @@ bool of_MOV_WR(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_MOVI(vthread_t thr, vvp_code_t cp)
{
unsigned dst = cp->bit_idx[0];
unsigned val = cp->bit_idx[1];
unsigned wid = cp->number;
thr_check_addr(thr, dst+wid);
for (unsigned idx = 0 ; idx < wid ; idx += 1, val >>= 1)
thr->bits4.set_bit(dst+idx, (val&1)? BIT4_1 : BIT4_0);
return true;
}
bool of_MUL(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);