Handle LPM shifts.

This commit is contained in:
steve 2005-03-19 06:23:49 +00:00
parent 23925b636e
commit ca488dff4e
7 changed files with 149 additions and 247 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.156 2005/03/18 02:56:03 steve Exp $"
#ident "$Id: elab_net.cc,v 1.157 2005/03/19 06:23:49 steve Exp $"
#endif
# include "config.h"
@ -1130,8 +1130,12 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
connect(osig->pin(0), gate->pin_Result());
// Connect the lsig (the left expression) to the Data input,
// and pad it if necessary with constant zeros.
assert(lsig->vector_width() == lwidth);
// and pad it if necessary. The lwidth is the width of the
// NetCLShift gate, and the D input must match.
if (lsig->vector_width() < lwidth)
lsig = pad_to_width(des, lsig, lwidth);
assert(lsig->vector_width() <= lwidth);
connect(lsig->pin(0), gate->pin_Data());
// Connect the rsig (the shift amount expression) to the
@ -2490,6 +2494,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.157 2005/03/19 06:23:49 steve
* Handle LPM shifts.
*
* Revision 1.156 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.117 2005/03/18 02:56:04 steve Exp $"
#ident "$Id: stub.c,v 1.118 2005/03/19 06:23:49 steve Exp $"
#endif
# include "config.h"
@ -594,6 +594,37 @@ static void show_lpm_repeat(ivl_lpm_t net)
}
}
static void show_lpm_shift(ivl_lpm_t net, const char*shift_dir)
{
ivl_nexus_t nex;
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_SHIFT%s %s: <width=%u>\n", shift_dir,
ivl_lpm_basename(net), width);
nex = ivl_lpm_q(net, 0);
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
if (width != width_of_nexus(nex)) {
fprintf(out, " ERROR: Q output nexus width=%u "
"does not match part width\n", width_of_nexus(nex));
stub_errors += 1;
}
nex = ivl_lpm_data(net, 0);
fprintf(out, " D: %s\n", ivl_nexus_name(nex));
if (width != width_of_nexus(nex)) {
fprintf(out, " ERROR: Q output nexus width=%u "
"does not match part width\n", width_of_nexus(nex));
stub_errors += 1;
}
nex = ivl_lpm_data(net, 1);
fprintf(out, " S: %s <width=%u>\n",
ivl_nexus_name(nex), width_of_nexus(nex));
}
static void show_lpm_sub(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
@ -671,37 +702,13 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_re(net);
break;
case IVL_LPM_SHIFTL: {
fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u %s>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net),
ivl_lpm_signed(net)? "signed" : "unsigned");
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Data A %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_data(net, idx)));
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1)
fprintf(out, " Shift %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_select(net, idx)));
break;
}
case IVL_LPM_SHIFTL:
show_lpm_shift(net, "L");
break;
case IVL_LPM_SHIFTR: {
fprintf(out, " LPM_SHIFTR %s: <width=%u, selects=%u %s>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net),
ivl_lpm_signed(net)? "signed" : "unsigned");
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Data A %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_data(net, idx)));
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1)
fprintf(out, " Shift %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_select(net, idx)));
break;
}
case IVL_LPM_SHIFTR:
show_lpm_shift(net, "R");
break;
case IVL_LPM_SUB:
show_lpm_sub(net);
@ -1216,6 +1223,9 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.118 2005/03/19 06:23:49 steve
* Handle LPM shifts.
*
* Revision 1.117 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.122 2005/03/18 02:56:04 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.123 2005/03/19 06:23:49 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1674,40 +1674,19 @@ static void draw_lpm_ff(ivl_lpm_t net)
static void draw_lpm_shiftl(ivl_lpm_t net)
{
unsigned idx, width, selects;
unsigned selwid;
unsigned width = ivl_lpm_width(net);
width = ivl_lpm_width(net);
selects = ivl_lpm_selects(net);
/* The .shift device can only take as many select inputs as
the width of the device.
XXXX I should make some sort of overflow gate for this? If
any high bits are set, then the shift is certain to be
*way* beyond the width of the left shifted value. XXXX */
selwid = selects;
if (selwid > width)
selwid = width;
if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
fprintf(vvp_out, "L_%p .shift/r %u", net, width);
else
fprintf(vvp_out, "L_%p .shift/l %u", net, width);
for (idx = 0 ; idx < width ; idx += 1) {
fprintf(vvp_out, ", ");
draw_input_from_net(ivl_lpm_data(net, idx));
}
fprintf(vvp_out, ", ");
draw_input_from_net(ivl_lpm_data(net, 0));
for (idx = 0 ; idx < selwid ; idx += 1) {
fprintf(vvp_out, ", ");
draw_input_from_net(ivl_lpm_select(net, idx));
}
for (idx = selwid ; idx < width ; idx += 1) {
fprintf(vvp_out, ", C<0>");
}
fprintf(vvp_out, ", ");
draw_input_from_net(ivl_lpm_data(net, 1));
fprintf(vvp_out, ";\n");
}
@ -2007,6 +1986,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.123 2005/03/19 06:23:49 steve
* Handle LPM shifts.
*
* Revision 1.122 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: README.txt,v 1.61 2005/03/18 02:56:04 steve Exp $
* $Id: README.txt,v 1.62 2005/03/19 06:23:49 steve Exp $
*/
VVP SIMULATION ENGINE
@ -598,11 +598,14 @@ STRUCTURAL SHIFTER STATEMENTS:
Variable shifts in structural context are implemented with .shift
statements:
<label> .shift/sl <wid>, <symbols_list>;
<label> .shift/l <wid>, <data symbol>, <shift symbol>;
<label> .shift/r <wid>, <data symbol>, <shift symbol>;
The shifter has a width that defines the number of outputs and the
number of data inputs. The first <wid> symbols in the <symbols_list>
gives the input data. The remaining hold the shift value, lsb first.
The shifter has a width that defines the vector width of the output, a
<data symbol> that is the input data to be shifted and a <shift-symbol>
that is the amount to shift. The vectors that come from port 0 are the
data to be shifted and must have exactly the width of the output. The
input to port 1 is the amount to shift.
STRUCTURAL FUNCTION CALLS:

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: arith.cc,v 1.42 2005/03/12 06:42:28 steve Exp $"
#ident "$Id: arith.cc,v 1.43 2005/03/19 06:23:49 steve Exp $"
#endif
# include "arith.h"
@ -634,110 +634,78 @@ void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
}
#if 0
void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
vvp_shiftl::vvp_shiftl(unsigned wid)
: vvp_arith_(wid)
{
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
unsigned amount = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t fp = functor_index(ptr);
unsigned val = (fp->ival >> 2) & 0x03;
switch (val) {
case 0:
break;
case 1:
amount |= 1 << idx;
break;
default:
output_x_(base, push);
return;
}
}
if (amount >= wid_) {
output_x_(base, push, 0);
return;
} else {
vvp_ipoint_t optr, iptr;
functor_t ofp, ifp;
for (unsigned idx = 0 ; idx < amount ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
ofp->put_oval(0, push);
}
for (unsigned idx = amount ; idx < wid_ ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
iptr = ipoint_index(base, idx - amount);
ifp = functor_index(iptr);
ofp->put_oval(ifp->ival & 3, push);
}
}
}
#endif
#if 0
void vvp_shiftr::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
vvp_shiftl::~vvp_shiftl()
{
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
unsigned amount = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t fp = functor_index(ptr);
unsigned val = (fp->ival >> 2) & 0x03;
switch (val) {
case 0:
break;
case 1:
amount |= 1 << idx;
break;
default:
output_x_(base, push);
return;
}
}
if (amount >= wid_) {
output_x_(base, push, 0);
return;
} else {
vvp_ipoint_t optr, iptr;
functor_t ofp, ifp;
for (unsigned idx = 0 ; idx < (wid_-amount) ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
iptr = ipoint_index(base, idx + amount);
ifp = functor_index(iptr);
ofp->put_oval(ifp->ival & 3, push);
}
for (unsigned idx = wid_-amount; idx < wid_ ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
ofp->put_oval(0, push);
}
}
}
#endif
void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t out (op_a_.size());
unsigned long shift;
if (! vector4_to_value(op_b_, shift)) {
vvp_send_vec4(ptr.ptr()->out, x_val_);
return;
}
if (shift > out.size())
shift = out.size();
for (unsigned idx = 0 ; idx < shift ; idx += 1)
out.set_bit(idx, BIT4_0);
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
out.set_bit(idx, op_a_.value(idx-shift));
vvp_send_vec4(ptr.ptr()->out, out);
}
vvp_shiftr::vvp_shiftr(unsigned wid)
: vvp_arith_(wid)
{
}
vvp_shiftr::~vvp_shiftr()
{
}
void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t out (op_a_.size());
unsigned long shift;
if (! vector4_to_value(op_b_, shift)) {
vvp_send_vec4(ptr.ptr()->out, x_val_);
return;
}
if (shift > out.size())
shift = out.size();
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
out.set_bit(idx-shift, op_a_.value(idx));
for (unsigned idx = 0 ; idx < shift ; idx += 1)
out.set_bit(idx+out.size()-shift, BIT4_0);
vvp_send_vec4(ptr.ptr()->out, out);
}
/*
* $Log: arith.cc,v $
* Revision 1.43 2005/03/19 06:23:49 steve
* Handle LPM shifts.
*
* Revision 1.42 2005/03/12 06:42:28 steve
* Implement .arith/mod.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: arith.h,v 1.28 2005/03/12 06:42:28 steve Exp $"
#ident "$Id: arith.h,v 1.29 2005/03/19 06:23:49 steve Exp $"
#endif
# include "functor.h"
@ -184,21 +184,24 @@ class vvp_arith_sum : public vvp_arith_ {
class vvp_shiftl : public vvp_arith_ {
public:
explicit vvp_shiftl(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
explicit vvp_shiftl(unsigned wid);
~vvp_shiftl();
virtual void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
};
class vvp_shiftr : public vvp_arith_ {
public:
explicit vvp_shiftr(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
explicit vvp_shiftr(unsigned wid);
~vvp_shiftr();
virtual void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
};
/*
* $Log: arith.h,v $
* Revision 1.29 2005/03/19 06:23:49 steve
* Handle LPM shifts.
*
* Revision 1.28 2005/03/12 06:42:28 steve
* Implement .arith/mod.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.cc,v 1.193 2005/03/12 06:42:28 steve Exp $"
#ident "$Id: compile.cc,v 1.194 2005/03/19 06:23:49 steve Exp $"
#endif
# include "arith.h"
@ -849,17 +849,6 @@ static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
}
#endif
#if 0
static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid)
{
for (unsigned i=1; i < wid; i++) {
extra_outputs_functor_s *fu = new extra_outputs_functor_s;
vvp_ipoint_t ipt = ipoint_index(fdx, i);
functor_define(ipt, fu);
fu->base_ = fdx;
}
}
#endif
static void make_arith(vvp_arith_ *arith,
char*label, long wid,
@ -1043,43 +1032,6 @@ void compile_cmp_gt(char*label, long wid, bool signed_flag,
make_arith(arith, label, wid, argc, argv);
}
static void make_shift(vvp_arith_*arith,
char*label, long wid,
unsigned argc, struct symb_s*argv)
{
#if 0
vvp_ipoint_t fdx = functor_allocate(wid);
functor_define(fdx, arith);
define_functor_symbol(label, fdx);
free(label);
make_extra_outputs(fdx, wid);
for (int idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(fdx,idx);
functor_t obj = functor_index(ptr);
if ((wid+idx) >= (long)argc)
obj->ival = 0x02;
else
obj->ival = 0x0a;
struct symb_s tmp_argv[3];
unsigned tmp_argc = 1;
tmp_argv[0] = argv[idx];
if ((wid+idx) < (long)argc) {
tmp_argv[1] = argv[wid+idx];
tmp_argc += 1;
}
inputs_connect(ptr, tmp_argc, tmp_argv);
}
#else
fprintf(stderr, "XXXX make_shift not implemented\n");
#endif
free(argv);
}
/*
* A .shift/l statement creates an array of functors for the
@ -1090,42 +1042,16 @@ void compile_shiftl(char*label, long wid, unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
if ((long)argc < (wid+1)) {
fprintf(stderr, "%s; .shift/l has too few symbols\n", label);
compile_errors += 1;
return;
}
if ((long)argc > (wid*2)) {
fprintf(stderr, "%s; .shift/l has too many symbols\n", label);
compile_errors += 1;
return;
}
vvp_arith_ *arith = new vvp_shiftl(wid);
make_shift(arith, label, wid, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
void compile_shiftr(char*label, long wid, unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
if ((long)argc < (wid+1)) {
fprintf(stderr, "%s; .shift/r has too few symbols\n", label);
compile_errors += 1;
return;
}
if ((long)argc > (wid*2)) {
fprintf(stderr, "%s; .shift/r has too many symbols\n", label);
compile_errors += 1;
return;
}
vvp_arith_ *arith = new vvp_shiftr(wid);
make_shift(arith, label, wid, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
@ -1661,6 +1587,9 @@ void compile_param_string(char*label, char*name, char*str, char*value)
/*
* $Log: compile.cc,v $
* Revision 1.194 2005/03/19 06:23:49 steve
* Handle LPM shifts.
*
* Revision 1.193 2005/03/12 06:42:28 steve
* Implement .arith/mod.
*