Merge branch 'master' of ssh://steve-icarus@icarus.com/home/u/icarus/steve/git/verilog
This commit is contained in:
commit
c08e547d1d
164
PExpr.h
164
PExpr.h
|
|
@ -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
|
||||||
|
|
|
||||||
71
compiler.h
71
compiler.h
|
|
@ -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
|
||||||
|
|
|
||||||
93
cprop.cc
93
cprop.cc
|
|
@ -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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
|
||||||
68
elab_expr.cc
68
elab_expr.cc
|
|
@ -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
|
||||||
|
|
|
||||||
11
net_expr.cc
11
net_expr.cc
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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':
|
||||||
assert(lv.wid == rv.wid);
|
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
|
||||||
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
|
if (number_is_immediate(le,16) && !number_is_unknown(le)) {
|
||||||
rv.base, lv.base, lv.wid);
|
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");
|
fprintf(vvp_out, " %%or 5, 4, 1;\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
assert(lv.wid == rv.wid);
|
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
|
||||||
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
|
if (number_is_immediate(re,16) && !number_is_unknown(re)) {
|
||||||
lv.base, rv.base, lv.wid);
|
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");
|
fprintf(vvp_out, " %%or 5, 4, 1;\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
assert(lv.wid == rv.wid);
|
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
|
||||||
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
|
if (number_is_immediate(re,16) && !number_is_unknown(re)) {
|
||||||
lv.base, rv.base, lv.wid);
|
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;
|
break;
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
assert(lv.wid == rv.wid);
|
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
|
||||||
fprintf(vvp_out, " %%cmp/%c %u, %u, %u;\n", s_flag,
|
if (number_is_immediate(le,16) && !number_is_unknown(le)) {
|
||||||
rv.base, lv.base, lv.wid);
|
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;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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} },
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue