Add %load/avp0 opcode and fix %load/vp0.

This patch adds a new opcode %load/avp0 that is used to load a
word from an array and add a value to it. %load/vp0 was
changed/fixed to do the summation at the result width not the
vector width. This allows small vectors to index large arrays with
an offset. A few errors in the opcodes.txt file were also fixed.
This commit is contained in:
Cary R 2008-01-12 18:22:46 -08:00 committed by Stephen Williams
parent e18b64768e
commit c899a6a52e
7 changed files with 107 additions and 202 deletions

View File

@ -28,7 +28,7 @@
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
int ok_flags);
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
int add_index);
int add_index, unsigned long immediate);
int number_is_unknown(ivl_expr_t ex)
{
@ -1020,16 +1020,12 @@ static struct vector_info draw_load_add_immediate(ivl_expr_t le,
unsigned long imm;
imm = get_number_immediate(re);
/* Load the immediate value into word register 0 */
fprintf(vvp_out, " %%ix/load 0, %lu;\n", imm);
lv.base = allocate_vector(wid);
lv.wid = wid;
/* Load the signal value with %loads that add the index
/* Load the signal value with a %load that adds the index
register to the value being loaded. */
draw_signal_dest(le, lv, 0);
draw_signal_dest(le, lv, 0, imm);
return lv;
}
@ -1720,11 +1716,11 @@ void pad_expr_in_place(ivl_expr_t exp, struct vector_info res, unsigned swid)
* offsetting the read from the lsi (least significant index) of the
* signal.
*
* If the add_index is >=0, then generate a %load/vpp to add the
* If the add_index is >=0, then generate a %load/vp0 to add the
* word0 value to the loaded value before storing it into the destination.
*/
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
int add_index)
int add_index, unsigned long immediate)
{
unsigned swid = ivl_expr_width(exp);
ivl_signal_t sig = ivl_expr_signal(exp);
@ -1739,16 +1735,18 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
if (ivl_signal_array_count(sig) > 1) {
ivl_expr_t ix = ivl_expr_oper1(exp);
if (!number_is_immediate(ix, 8*sizeof(unsigned long))) {
if (add_index >= 0) {
fprintf(stderr, "%s:%u: vvp-tgt error: "
"add_index=%d at %s:%d\n",
ivl_expr_file(exp), ivl_expr_lineno(exp),
add_index, __FILE__, __LINE__);
}
assert(add_index < 0);
draw_eval_expr_into_integer(ix, 3);
fprintf(vvp_out, " %%load/av %u, v%p, %u;\n",
res.base, sig, swid);
if (add_index < 0) {
fprintf(vvp_out, " %%load/av %u, v%p, %u;\n",
res.base, sig, swid);
} else {
assert(add_index == 0);
/* Add an immediate value to an array value. */
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
fprintf(vvp_out, " %%load/avp0 %u, v%p, %u;\n",
res.base, sig, swid);
}
pad_expr_in_place(exp, res, swid);
return;
}
@ -1772,8 +1770,11 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
assert(add_index == 0);
/* If this is a REG (a variable) then I can do a vector read. */
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
fprintf(vvp_out, " %%ix/load 2, %lu;\n", res.wid);
fprintf(vvp_out, " %%load/vp0 %u, v%p_%u, %u;\n",
res.base, sig, word, swid);
swid = res.wid;
} else {
@ -1806,7 +1807,7 @@ static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid,
res.wid = wid;
save_expression_lookaside(res.base, exp, wid);
draw_signal_dest(exp, res, -1);
draw_signal_dest(exp, res, -1, 0L);
return res;
}
@ -2289,7 +2290,7 @@ static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
switch (ivl_expr_type(exp)) {
case IVL_EX_SIGNAL:
draw_signal_dest(exp, dest, -1);
draw_signal_dest(exp, dest, -1, 0L);
return;
default:

View File

@ -1,7 +1,7 @@
#ifndef __codes_H
#define __codes_H
/*
* Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2008 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
@ -18,10 +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: codes.h,v 1.84 2007/06/07 03:20:15 steve Exp $"
#endif
# include "pointers.h"
# include "vvp_net.h"
@ -92,6 +88,7 @@ extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_MV(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code);
@ -188,154 +185,4 @@ extern vvp_code_t codespace_allocate(void);
extern vvp_code_t codespace_next(void);
extern vvp_code_t codespace_null(void);
/*
* $Log: codes.h,v $
* Revision 1.84 2007/06/07 03:20:15 steve
* Properly handle signed conversion to real
*
* Revision 1.83 2007/04/14 04:43:02 steve
* Finish up part select of array words.
*
* Revision 1.82 2007/02/14 05:58:14 steve
* Add the mov/wr opcode.
*
* Revision 1.81 2007/01/16 05:44:16 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.80 2006/10/05 01:23:53 steve
* Handle non-constant delays on indexed non-blocking assignments.
*
* Revision 1.79 2006/08/09 05:19:08 steve
* Add support for real valued modulus.
*
* Revision 1.78 2006/02/02 02:44:00 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.77 2005/11/26 17:16:05 steve
* Force instruction that can be indexed.
*
* Revision 1.76 2005/09/17 04:01:01 steve
* Add the load/v.p instruction.
*
* Revision 1.75 2005/09/14 02:50:07 steve
* Add word integer compares.
*
* Revision 1.74 2005/06/14 01:44:09 steve
* Add the assign_v0_d instruction.
*
* Revision 1.73 2005/06/02 16:02:11 steve
* Add support for notif0/1 gates.
* Make delay nodes support inertial delay.
* Add the %force/link instruction.
*
* Revision 1.72 2005/05/07 03:15:42 steve
* Implement non-blocking part assign.
*
* Revision 1.71 2005/05/01 22:05:21 steve
* Add cassign/link instruction.
*
* Revision 1.70 2005/03/03 04:33:10 steve
* Rearrange how memories are supported as vvp_vector4 arrays.
*
* Revision 1.69 2004/12/17 04:47:47 steve
* Replace single release with release/net and release/reg.
*
* Revision 1.68 2004/12/15 17:17:42 steve
* Add the force/v instruction.
*
* Revision 1.67 2004/12/11 02:31:29 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.66 2004/06/19 15:52:53 steve
* Add signed modulus operator.
*
* Revision 1.65 2004/05/19 03:26:24 steve
* Support delayed/non-blocking assignment to reals and others.
*
* Revision 1.64 2003/07/03 20:03:36 steve
* Remove the vvp_cpoint_t indirect code pointer.
*
* Revision 1.63 2003/06/18 03:55:19 steve
* Add arithmetic shift operators.
*
* Revision 1.62 2003/06/17 19:17:42 steve
* Remove short int restrictions from vvp opcodes.
*
* Revision 1.61 2003/05/26 04:44:54 steve
* Add the set/x0/x instruction.
*
* Revision 1.60 2003/05/07 03:39:12 steve
* ufunc calls to functions can have scheduling complexities.
*
* Revision 1.59 2003/03/28 02:33:56 steve
* Add support for division of real operands.
*
* Revision 1.58 2003/02/27 20:36:29 steve
* Add the cvt/vr instruction.
*
* Revision 1.57 2003/02/06 17:41:47 steve
* Add the %sub/wr instruction.
*
* Revision 1.56 2003/01/26 18:16:22 steve
* Add %cvt/ir and %cvt/ri instructions, and support
* real values passed as arguments to VPI tasks.
*
* Revision 1.55 2003/01/25 23:48:06 steve
* Add thread word array, and add the instructions,
* %add/wr, %cmp/wr, %load/wr, %mul/wr and %set/wr.
*
* Revision 1.54 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.53 2002/11/08 04:59:57 steve
* Add the %assign/v0 instruction.
*
* Revision 1.52 2002/11/07 02:32:39 steve
* Add vector set and load instructions.
*
* Revision 1.51 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.50 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.49 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
* Revision 1.48 2002/08/28 17:15:06 steve
* Add the %load/nx opcode to index vpi nets.
*
* Revision 1.47 2002/08/22 03:38:40 steve
* Fix behavioral eval of x?a:b expressions.
*
* Revision 1.46 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.45 2002/07/05 02:50:58 steve
* Remove the vpi object symbol table after compile.
*
* Revision 1.44 2002/06/02 18:55:58 steve
* Add %cmpi/u instruction.
*
* Revision 1.43 2002/05/31 20:04:22 steve
* Add the %muli instruction.
*
* Revision 1.42 2002/05/31 04:09:58 steve
* Slight improvement in %mov performance.
*
* Revision 1.41 2002/05/29 16:29:34 steve
* Add %addi, which is faster to simulate.
*
* Revision 1.40 2002/04/21 22:29:49 steve
* Add the assign/d instruction for computed delays.
*
* Revision 1.39 2002/04/14 18:41:34 steve
* Support signed integer division.
*/
#endif

View File

@ -135,6 +135,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/mv",of_LOAD_MV,3, {OA_BIT1, OA_MEM_PTR, OA_BIT2} },
{ "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },

View File

@ -1,7 +1,6 @@
/*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.78 2007/06/12 02:36:58 steve Exp $
*/
@ -315,7 +314,7 @@ bit:
* %ix/get/s <idx>, <bit>, <wid>
This instruction loads a thread vector starting at <bit>, size <wid>,
into the index register <idx>. The <bit> is the lsb of the value in
into the index register <idx>. The <bit> is the LSB of the value in
thread bit space, and <wid> is the width of the vector.
The function converts the 4-value bits into a binary number, without
@ -394,9 +393,15 @@ This instruction loads a word from the specified array. The word
address is in index register 3. The width should match the width of
the array word.
* %load/avp0 <bit>, <array-label>, <wid>
This instruction is a mix of %load/av and %load/vp0. It loads an array
value like %load/av and then adds a value from index register 0 to the
result like %load/vp0.
* %load/avx.p <bit>, <array-label>, <index>
This instruction is similar ro %load/av, but it loads only a single
This instruction is similar to %load/av, but it loads only a single
bit, and the <index> is the selector for the bit to use. If <index> is
out of range, then x is loaded.
@ -426,9 +431,13 @@ functor, the the most significant bits are dropped.
This instruction is the same as %load/v above, except that it also
adds the integer value is index register 0 into the loaded value. The
addition is a verilog-style add, which means that if any of the input
addition is a Verilog-style add, which means that if any of the input
bits are X or Z, the entire result is turned into a vector of X bits.
Index register 2 contains the result width. The addition of the loaded
value and the index are done at this width to avoid the problem of a
small vector with a large immediate offset indexing an array.
* %load/wr <bit>, <vpi-label>
This instruction reads a real value from the vpi-like object to a word
@ -634,7 +643,7 @@ bits are not written anywhere.
This instruction shifts the vector left (towards more significant
bits) by the amount in index register 0. The <bit> is the address of
the lsb of the vector, and <wid> the width of the vector. The shift is
the LSB of the vector, and <wid> the width of the vector. The shift is
done in place. Zero values are shifted in.
* %shiftr/i0 <bit>, <wid>
@ -642,7 +651,7 @@ done in place. Zero values are shifted in.
This instruction shifts the vector right (towards the less significant
bits) by the amount in the index register 0. The <bit> is the address
of the lsb of the vector, and <wid> is the width of the vector. The
of the LSB of the vector, and <wid> is the width of the vector. The
shift is done in place.
%shiftr/i0 is an unsigned down shift, so zeros are shifted into the
@ -717,15 +726,15 @@ and leaves the result in the <dst> vector. xnor is this:
This does a bitwise exclusive or (^) of the <src> and <dst> vector,
and leaves the result in the <dst> vector. xor is this:
0 xnor 0 --> 0
0 xnor 1 --> 1
1 xnor 0 --> 1
1 xnor 1 --> 0
0 xor 0 --> 0
0 xor 1 --> 1
1 xor 0 --> 1
1 xor 1 --> 0
otherwise x
/*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2008 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2008 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: vthread.cc,v 1.166 2007/06/13 01:03:57 steve Exp $"
#endif
# include "config.h"
# include "vthread.h"
@ -2104,6 +2101,45 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* %load/avp0 <bit>, <array-label>, <wid> ;
*
* <bit> is the thread bit address for the result
* <array-label> is the array to access, and
* <wid> is the width of the word to read.
*
* The address of the word in the array is in index register 3.
* An integer value from index register 0 is added to the value.
*/
bool of_LOAD_AVP0(vthread_t thr, vvp_code_t cp)
{
unsigned bit = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
int64_t addend = thr->words[0].w_int;
unsigned adr = thr->words[3].w_int;
vvp_vector4_t word = array_get_word(cp->array, adr);
if (word.size() != wid) {
fprintf(stderr, "internal error: array width=%u, word.size()=%u, wid=%u\n",
0, word.size(), wid);
}
assert(word.size() == wid);
/* Add the addend value */
word += addend;
/* Check the address once, before we scan the vector. */
thr_check_addr(thr, bit+wid-1);
/* Copy the vector bits into the bits4 vector. Do the copy
directly to skip the excess calls to thr_check_addr. */
thr->bits4.set_vec(bit, word);
return true;
}
/*
* %load/avx.p <bit>, <array-label>, <idx> ;
*
@ -2229,6 +2265,7 @@ vvp_vector4_t load_base(vthread_t thr, vvp_code_t cp)
}
assert(sig);
vvp_vector4_t sig_value = sig->vec4_value();
sig_value.resize(wid);
@ -2253,15 +2290,19 @@ bool of_LOAD_VEC(vthread_t thr, vvp_code_t cp)
}
/*
* This is like of_LOAD_VEC, but includes an add of an integer value.
*/
* This is like of_LOAD_VEC, but includes an add of an integer value from
* index 0. The <wid> is the expected result width not the vector width.
*/
bool of_LOAD_VP0(vthread_t thr, vvp_code_t cp)
{
unsigned bit = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
int64_t addend = thr->words[0].w_int;
unsigned wid = thr->words[2].w_int;
vvp_vector4_t sig_value = load_base(thr, cp);
/* We need a vector this wide to make the math work correctly.
* Copy the base bits into the vector, but keep the width. */
vvp_vector4_t sig_value(wid, BIT4_0);
sig_value.copy_bits(load_base(thr, cp));
/* Add the addend value */
sig_value += addend;
@ -3646,7 +3687,3 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* $Log: vthread.cc,v $
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2008 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
@ -202,6 +202,14 @@ void vvp_send_long(vvp_net_ptr_t ptr, long val)
}
}
void vvp_vector4_t::copy_bits(const vvp_vector4_t&that)
{
unsigned bits_to_copy = (that.size_ < size_) ? that.size_ : size_;
for (unsigned idx = 0; idx < bits_to_copy; idx += 1)
set_bit(idx, that.value(idx));
}
void vvp_vector4_t::copy_from_(const vvp_vector4_t&that)
{
size_ = that.size_;

View File

@ -1,7 +1,7 @@
#ifndef __vvp_net_H
#define __vvp_net_H
/*
* Copyright (c) 2004-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2008 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
@ -18,7 +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
*/
#ident "$Id: vvp_net.h,v 1.58 2007/06/12 02:36:58 steve Exp $"
# include "config.h"
# include <stddef.h>
@ -118,6 +117,9 @@ class vvp_vector4_t {
void set_bit(unsigned idx, vvp_bit4_t val);
void set_vec(unsigned idx, const vvp_vector4_t&that);
// Get the bits from another vector, but keep my size.
void copy_bits(const vvp_vector4_t&that);
// Test that the vectors are exactly equal
bool eeq(const vvp_vector4_t&that) const;