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 * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 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 <string>
# include <vector> # include <vector>
@ -659,6 +656,10 @@ class PECallFunction : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool sys_task_arg) const; 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: private:
pform_name_t path_; pform_name_t path_;
svector<PExpr *> parms_; svector<PExpr *> parms_;
@ -673,160 +674,9 @@ class PECallFunction : public PExpr {
const NetExpr* decay, const NetExpr* decay,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const; 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 #endif

View File

@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 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 <list>
# include <map> # 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; extern unsigned integer_width;
/* The TIME_WIDTH is the width of time variables. */ /* 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 const struct sfunc_return_type* lookup_sys_func(const char*name);
extern int load_sys_func_table(const char*path); 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 #endif

View File

@ -16,16 +16,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 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 "config.h"
# include "netlist.h" # include "netlist.h"
# include "netmisc.h" # include "netmisc.h"
# include "functor.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) void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
{ {
// 'bz constant values drive high impedance to whatever is // '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; { 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) { if (obj->value(idx) == verinum::Vz) {
obj->pin(idx).unlink();
tmp += 1; tmp += 1;
} }
}
if (tmp == obj->pin_count()) { if (tmp == obj->width()) {
delete obj; delete obj;
return; return;
} }
@ -948,81 +947,3 @@ void cprop(Design*des)
des->functor(&dc); 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * 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 "config.h"
# include "compiler.h" # include "compiler.h"
@ -38,7 +35,8 @@ unsigned PExpr::test_width(Design*des, NetScope*scope,
{ {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_line() << ": debug: test_width defaults to " cerr << get_line() << ": debug: test_width defaults to "
<< min << ", ignoring unsized_flag" << endl; << min << ", ignoring unsized_flag. typeid="
<< typeid(*this).name() << endl;
} }
return min; return min;
} }
@ -148,6 +146,11 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
{ {
bool flag; bool flag;
if (debug_elaborate) {
cerr << get_line() << ": debug: elaborate expression "
<< *this << " expr_wid=" << expr_wid << endl;
}
NetEBinary*tmp; NetEBinary*tmp;
switch (op_) { switch (op_) {
@ -307,6 +310,61 @@ unsigned PEBShift::test_width(Design*des, NetScope*scope,
return wid_left; 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 * 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 one. This expands the expression to account for the largest
possible result. 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 The set_width applied to a constant value will only
truncate the constant so far as it can still hold its truncate the constant so far as it can still hold its
logical value, so this is safe to do. */ logical value, so this is safe to do. */
if ( (tmp = dynamic_cast<NetEConst*>(r)) if ( (tmp = dynamic_cast<NetEConst*>(r))
&& (! tmp->has_width()) && (! 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; unsigned target_width = l->expr_width() + 1;
if (target_width < integer_width)
target_width = integer_width;
r->set_width(target_width); r->set_width(target_width);
/* Note: This constant value will not gain a defined /* 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)) } else if ( (tmp = dynamic_cast<NetEConst*>(l))
&& (! tmp->has_width()) && (! 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; unsigned target_width = r->expr_width() + 1;
if (target_width < integer_width)
target_width = integer_width;
l->set_width(target_width); l->set_width(target_width);
/* Note: This constant value will not gain a defined /* 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); ivl_scope_t def = ivl_expr_def(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned"; const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net); const char*vt = vt_type_string(net);
unsigned idx;
fprintf(out, "%*s<%s %s function %s>\n", ind, "", fprintf(out, "%*s<%s %s function %s with %u arguments>\n", ind, "",
vt, sign, ivl_scope_name(def)); 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) 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; const char*bits;
unsigned idx; unsigned idx;
if (ivl_expr_type(ex) == IVL_EX_ULONG)
return 0;
assert(ivl_expr_type(ex) == IVL_EX_NUMBER); assert(ivl_expr_type(ex) == IVL_EX_NUMBER);
bits = ivl_expr_bits(ex); bits = ivl_expr_bits(ex);
@ -66,6 +69,10 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
if (bits[idx] != '0') if (bits[idx] != '0')
return 0; return 0;
/* Negative numbers are not "immediate". */
if (ivl_expr_signed(ex) && bits[ivl_expr_width(ex)-1]=='1')
return 0;
return 1; 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); return draw_binary_expr_eq_real(exp);
} }
if ((ivl_expr_type(re) == IVL_EX_ULONG) if (number_is_immediate(re,16) && !number_is_unknown(re))
&& (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))
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag); return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
assert(ivl_expr_value(le) == IVL_VT_LOGIC 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 assert(ivl_expr_value(re) == IVL_VT_LOGIC
|| ivl_expr_value(re) == IVL_VT_BOOL); || ivl_expr_value(re) == IVL_VT_BOOL);
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ); lv.wid = 0;
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ); rv.wid = 0;
switch (ivl_expr_opcode(exp)) { switch (ivl_expr_opcode(exp)) {
case 'G': 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); assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
rv.base, lv.base, lv.wid); rv.base, lv.base, lv.wid);
}
fprintf(vvp_out, " %%or 5, 4, 1;\n"); fprintf(vvp_out, " %%or 5, 4, 1;\n");
break; break;
case 'L': 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); assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
lv.base, rv.base, lv.wid); lv.base, rv.base, lv.wid);
}
fprintf(vvp_out, " %%or 5, 4, 1;\n"); fprintf(vvp_out, " %%or 5, 4, 1;\n");
break; break;
case '<': 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); assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
lv.base, rv.base, lv.wid); lv.base, rv.base, lv.wid);
}
break; break;
case '>': 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); assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
rv.base, lv.base, lv.wid); rv.base, lv.base, lv.wid);
}
break; break;
default: default:
assert(0); assert(0);
} }
clr_vector(lv); if (lv.wid > 0) clr_vector(lv);
clr_vector(rv); if (rv.wid > 0) clr_vector(rv);
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) { if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
lv.base = 5; 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. */ load the constant bit values. */
res.base = allocate_vector(wid); 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; idx = 0;
while (idx < nwid) { while (idx < nwid) {
unsigned cnt; unsigned cnt;

View File

@ -412,17 +412,8 @@ static char* draw_C4_to_string(ivl_net_const_t cptr)
dp += strlen(dp); dp += strlen(dp);
for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) { for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
switch (bits[ivl_const_width(cptr)-idx-1]) { char bitchar = bits[ivl_const_width(cptr)-idx-1];
case '0': *dp++ = bitchar;
*dp++ = '0';
break;
case '1':
*dp++ = '1';
break;
default:
*dp++ = bits[idx];
break;
}
assert((dp - result) < result_len); 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_BREAKPOINT(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_LINK(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_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_CMPIU(vthread_t thr, vvp_code_t code);
extern bool of_CMPS(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); 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_MOD_WR(vthread_t thr, vvp_code_t code);
extern bool of_MOV(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_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(vthread_t thr, vvp_code_t code);
extern bool of_MUL_WR(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); 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/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cmp/x", of_CMPX, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/x", of_CMPX, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/z", of_CMPZ, 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} }, { "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/ri", of_CVT_RI, 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} }, { "%mod/wr", of_MOD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mov/wr", of_MOV_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%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", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mul/wr", of_MUL_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%mul/wr", of_MUL_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%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 compare. In either case, if either operand contains x or z, then lt
bit gets the x value. 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> * %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. */ /* Correct the lt bit to account for the sign of the parameters. */
if (lt != BIT4_X) { 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 /* If the first is negative and the last positive, then
a < b for certain. */ a < b for certain. */
if ((sig1 == BIT4_1) && (sig2 == BIT4_0)) if ((sig1 == BIT4_1) && (sig2 == BIT4_0))
@ -891,6 +885,55 @@ bool of_CMPS(vthread_t thr, vvp_code_t cp)
return true; 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) bool of_CMPIU(vthread_t thr, vvp_code_t cp)
{ {
vvp_bit4_t eq = BIT4_1; vvp_bit4_t eq = BIT4_1;
@ -2531,6 +2574,20 @@ bool of_MOV_WR(vthread_t thr, vvp_code_t cp)
return true; 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) bool of_MUL(vthread_t thr, vvp_code_t cp)
{ {
assert(cp->bit_idx[0] >= 4); assert(cp->bit_idx[0] >= 4);