diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index d57b9af54..105da8b59 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -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: diff --git a/vvp/codes.h b/vvp/codes.h index 1a82b2ad1..b227cedf8 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -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 diff --git a/vvp/compile.cc b/vvp/compile.cc index d4bb4e6a9..6c6320598 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 42cac7f40..c4cf2199b 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -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 , , This instruction loads a thread vector starting at , size , -into the index register . The is the lsb of the value in +into the index register . The is the LSB of the value in thread bit space, and 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 , , + +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 , , -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 is the selector for the bit to use. If 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 , 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 is the address of -the lsb of the vector, and the width of the vector. The shift is +the LSB of the vector, and the width of the vector. The shift is done in place. Zero values are shifted in. * %shiftr/i0 , @@ -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 is the address -of the lsb of the vector, and is the width of the vector. The +of the LSB of the vector, and 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 vector. xnor is this: This does a bitwise exclusive or (^) of the and vector, and leaves the result in the 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 diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 74ffccdd7..bb5b34977 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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 , , ; + * + * is the thread bit address for the result + * is the array to access, and + * 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 , , ; * @@ -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 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 $ - */ - diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index cf383fe18..d9cf949c3 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -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_; diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 6bc809c5b..d4627fddd 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -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 @@ -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;