From aacce5ef1bab75c13e55ce1c21e6a051a2137fea Mon Sep 17 00:00:00 2001 From: steve Date: Thu, 22 Mar 2001 05:08:00 +0000 Subject: [PATCH] implement %load, %inv, %jum/0 and %cmp/u --- vvp/codes.cc | 12 ++--- vvp/codes.h | 10 ++++- vvp/compile.cc | 20 ++++++--- vvp/functor.cc | 12 ++++- vvp/functor.h | 7 ++- vvp/opcodes.txt | 88 +++++++++++++++++++++++++++++++++++++ vvp/vthread.cc | 113 +++++++++++++++++++++++++++++++++++++++++++++++- vvp/vthread.txt | 59 +++++++++++++++++++++---- 8 files changed, 298 insertions(+), 23 deletions(-) diff --git a/vvp/codes.cc b/vvp/codes.cc index f9a289577..5411d359c 100644 --- a/vvp/codes.cc +++ b/vvp/codes.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: codes.cc,v 1.3 2001/03/20 06:16:23 steve Exp $" +#ident "$Id: codes.cc,v 1.4 2001/03/22 05:08:00 steve Exp $" #endif # include "codes.h" @@ -94,11 +94,11 @@ void codespace_dump(FILE*fd) vvp_code_t cop = codespace_index(idx); if (cop->opcode == &of_ASSIGN) { - fprintf(fd, "%%assign 0x%u, %lu, %u\n", + fprintf(fd, "%%assign 0x%u, %u, %u\n", cop->iptr, cop->bit_idx1, cop->bit_idx2); } else if (cop->opcode == &of_DELAY) { - fprintf(fd, "%%delay %lu\n", cop->number); + fprintf(fd, "%%delay %lu\n", (unsigned long)cop->number); } else if (cop->opcode == &of_END) { fprintf(fd, "%%end\n"); @@ -107,8 +107,7 @@ void codespace_dump(FILE*fd) fprintf(fd, "%%jmp 0x%u\n", cop->cptr); } else if (cop->opcode == &of_SET) { - fprintf(fd, "%%set 0x%lu, %u\n", - cop->iptr, cop->bit_idx1); + fprintf(fd, "%%set 0x%u, %u\n", cop->iptr, cop->bit_idx1); } else { fprintf(fd, "opcode %p\n", cop->opcode); @@ -119,6 +118,9 @@ void codespace_dump(FILE*fd) /* * $Log: codes.cc,v $ + * Revision 1.4 2001/03/22 05:08:00 steve + * implement %load, %inv, %jum/0 and %cmp/u + * * Revision 1.3 2001/03/20 06:16:23 steve * Add support for variable vectors. * diff --git a/vvp/codes.h b/vvp/codes.h index 4262f6370..befb90e97 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: codes.h,v 1.4 2001/03/20 06:16:24 steve Exp $" +#ident "$Id: codes.h,v 1.5 2001/03/22 05:08:00 steve Exp $" #endif @@ -36,9 +36,14 @@ typedef bool (*vvp_code_fun)(vthread_t thr, vvp_code_t code); * access to the thread context. */ extern bool of_ASSIGN(vthread_t thr, vvp_code_t code); +extern bool of_CMPU(vthread_t thr, vvp_code_t code); extern bool of_DELAY(vthread_t thr, vvp_code_t code); extern bool of_END(vthread_t thr, vvp_code_t code); +extern bool of_INV(vthread_t thr, vvp_code_t code); extern bool of_JMP(vthread_t thr, vvp_code_t code); +extern bool of_JMP0(vthread_t thr, vvp_code_t code); +extern bool of_LOAD(vthread_t thr, vvp_code_t code); +extern bool of_MOV(vthread_t thr, vvp_code_t code); extern bool of_SET(vthread_t thr, vvp_code_t code); extern bool of_NOOP(vthread_t thr, vvp_code_t code); extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code); @@ -86,6 +91,9 @@ extern void codespace_dump(FILE*fd); /* * $Log: codes.h,v $ + * Revision 1.5 2001/03/22 05:08:00 steve + * implement %load, %inv, %jum/0 and %cmp/u + * * Revision 1.4 2001/03/20 06:16:24 steve * Add support for variable vectors. * diff --git a/vvp/compile.cc b/vvp/compile.cc index 741c13cbc..6a0b9fa64 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: compile.cc,v 1.8 2001/03/21 05:13:03 steve Exp $" +#ident "$Id: compile.cc,v 1.9 2001/03/22 05:08:00 steve Exp $" #endif # include "compile.h" @@ -63,11 +63,16 @@ struct opcode_table_s { }; const static struct opcode_table_s opcode_table[] = { - { "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, - { "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, - { "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} }, - { "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} }, + { "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, + { "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} }, + { "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} }, + { "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} }, + { "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { 0, of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} } }; @@ -471,6 +476,9 @@ void compile_dump(FILE*fd) /* * $Log: compile.cc,v $ + * Revision 1.9 2001/03/22 05:08:00 steve + * implement %load, %inv, %jum/0 and %cmp/u + * * Revision 1.8 2001/03/21 05:13:03 steve * Allow var objects as vpiHandle arguments to %vpi_call. * diff --git a/vvp/functor.cc b/vvp/functor.cc index 84d107b14..75aaf39b6 100644 --- a/vvp/functor.cc +++ b/vvp/functor.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.cc,v 1.3 2001/03/20 06:16:24 steve Exp $" +#ident "$Id: functor.cc,v 1.4 2001/03/22 05:08:00 steve Exp $" #endif # include "functor.h" @@ -160,6 +160,13 @@ void functor_set(vvp_ipoint_t ptr, unsigned bit) } } +unsigned functor_get(vvp_ipoint_t ptr) +{ + functor_t fp = functor_index(ptr); + assert(fp); + return fp->oval & 3; +} + /* * This function is used by the scheduler to implement the propagation * event. The input is the pointer to the functor who's output is to @@ -219,6 +226,9 @@ const unsigned char ft_var[16] = { /* * $Log: functor.cc,v $ + * Revision 1.4 2001/03/22 05:08:00 steve + * implement %load, %inv, %jum/0 and %cmp/u + * * Revision 1.3 2001/03/20 06:16:24 steve * Add support for variable vectors. * diff --git a/vvp/functor.h b/vvp/functor.h index 3432df10f..960704d8f 100644 --- a/vvp/functor.h +++ b/vvp/functor.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.h,v 1.3 2001/03/20 06:16:24 steve Exp $" +#ident "$Id: functor.h,v 1.4 2001/03/22 05:08:00 steve Exp $" #endif # include "pointers.h" @@ -85,6 +85,8 @@ extern vvp_ipoint_t functor_allocate(unsigned wid); */ extern void functor_set(vvp_ipoint_t point, unsigned val); +extern unsigned functor_get(vvp_ipoint_t ptr); + /* * When a propagation event happens, this function is called with the * address of the affected functor. It propagates the output to all @@ -111,6 +113,9 @@ extern const unsigned char ft_var[]; /* * $Log: functor.h,v $ + * Revision 1.4 2001/03/22 05:08:00 steve + * implement %load, %inv, %jum/0 and %cmp/u + * * Revision 1.3 2001/03/20 06:16:24 steve * Add support for variable vectors. * diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index fe12dfcf1..e959e9778 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1,3 +1,10 @@ +/* + * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * + * $Id: opcodes.txt,v 1.5 2001/03/22 05:08:00 steve Exp $ + */ + + EXECUTABLE INSTRUCTION OPCODES @@ -13,6 +20,46 @@ the assignment takes place. The delay may be 0. For blocking assignments, see %set. The is the address of the thread register that contains the bit value to assign. +* %cmp/u , , +* %cmp/s , , + +These instructions perform a generic comparison of two vectors of equal +size. The and numbers address the least-significant +bit of each vector, and is the width. If either operator is 0, +1, 2 or 3 then it is taken to be a constant replicated to the selected +width. + +The results of the comparison go into bits 4, 5, 6 and 7: + + 4: eq (equal) + 5: lt (less than) + 6: eeq (case equal) + +The eeq bit is set to 1 if all the bits in the vectors are exactly the +same, or 0 otherwise. The eq bit is true if the values are logically +the same. That is, x and z are considered equal. In other words the eq +bit is the same as ``=='' and the eeq bit ``===''. + +The lt bit is 1 if the left vector is less then the right vector, or 0 +if greater then or equal to the right vector. It is the equivilent of +the Verilog < operator. Combinations of these three bits can be used +to implement all the Verilog comparison operators. + +The %cmp/u and %cmp/s differ only in the handling of the lt bit. The +%cmp/u does an unsigned compare, whereas the %cmp/s does a signed +compare. + +* %cmp/z , , +* %cmp/x , , + +These instructions are for implementing the casez and casex +comparisons. These work similar to the %cmp/u instructions, except +only an eq bit is calculated. These comparisons both treat z values in +the left or right operand as don't care positions. The %cmp/x +instruction will also treat x values in either operand as don't care. + +Only bit 4 is set by these instructions. + * %delay This opcode pauses the thread, and causes it to be rescheduled for a @@ -21,16 +68,38 @@ future to reschedule, and is >= 0. If the %delay is zero, then the thread yields the processor for another thread, but will be resumed in the current time step. +* %inv , + +Perform a bitwise invert of the vector starting at . + * %jmp The %jmp instruction performs an unconditional branch to a given location. The parameter is the label of the destination instruction. +* %jmp/[01xz] , + +This is a conditional version of the %jmp instruction. In this case, +a single bit (addressed by ) is tested. If it is one of the +values in the part after the /, the jump is taken. For example: + + %jmp/xz T_label, 8; + +will jump to T_label if bit 8 is x or z. + * %load , This instruction loads a value from the given functor output into the specified thread register bit. +* %mov , , + +This instruction copies a vector from one place in register space to +another. The destination and source vectors are assumed to be the same +width and non-overlapping. The may not be 0-3, but if the +is one of the 4 constant bits, the effect is to replicate the value +into the destination vector. Useful for filling a vector. + * %set , This sets a bit of a variable, and is used to implement blocking @@ -53,3 +122,22 @@ sensitive list for the addressed functor. The functor holds all the threads that await the functor. When the defined sort of event occurs on the functor, a thread schedule event is created for all the threads in its list and the list is cleared. + +/* + * Copyright (c) 2001 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 56ab25768..dad5b4b06 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vthread.cc,v 1.6 2001/03/20 06:16:24 steve Exp $" +#ident "$Id: vthread.cc,v 1.7 2001/03/22 05:08:00 steve Exp $" #endif # include "vthread.h" @@ -25,13 +25,35 @@ # include "schedule.h" # include "functor.h" # include "vpi_priv.h" +# include # include struct vthread_s { /* This is the program counter. */ unsigned long pc; + unsigned char *bits; + unsigned short nbits; }; +static inline unsigned thr_get_bit(struct vthread_s*thr, unsigned addr) +{ + assert(addr < thr->nbits); + unsigned idx = addr % 4; + addr /= 4; + return (thr->bits[addr] >> (idx*2)) & 3; +} + +static inline void thr_put_bit(struct vthread_s*thr, + unsigned addr, unsigned val) +{ + assert(addr < thr->nbits); + unsigned idx = addr % 4; + addr /= 4; + unsigned mask = 3 << (idx*2); + + thr->bits[addr] = (thr->bits[addr] & ~mask) | (val << (idx*2)); +} + /* * Create a new thread with the given start address. */ @@ -39,7 +61,13 @@ vthread_t v_newthread(unsigned long pc) { vthread_t thr = new struct vthread_s; thr->pc = pc; + thr->bits = (unsigned char*)malloc(16); + thr->nbits = 16*4; + thr_put_bit(thr, 0, 0); + thr_put_bit(thr, 1, 1); + thr_put_bit(thr, 2, 2); + thr_put_bit(thr, 3, 3); return thr; } @@ -81,6 +109,31 @@ bool of_ASSIGN(vthread_t thr, vvp_code_t cp) return true; } +bool of_CMPU(vthread_t thr, vvp_code_t cp) +{ + unsigned eq = 1; + unsigned eeq = 1; + unsigned lt = 2; + + for (unsigned idx = 0 ; idx < cp->number ; idx += 1) { + unsigned lv = thr_get_bit(thr, cp->bit_idx1+idx); + unsigned rv = thr_get_bit(thr, cp->bit_idx2+idx); + + if (lv != rv) + eeq = 0; + if ((lv == 0) && (rv != 0)) + eq = 0; + if ((lv == 1) && (rv != 1)) + eq = 0; + } + + thr_put_bit(thr, 4, eq); + thr_put_bit(thr, 5, lt); + thr_put_bit(thr, 6, eeq); + + return true; +} + bool of_DELAY(vthread_t thr, vvp_code_t cp) { //printf("thread %p: %%delay %lu\n", thr, cp->number); @@ -94,12 +147,67 @@ bool of_END(vthread_t thr, vvp_code_t cp) return false; } +bool of_INV(vthread_t thr, vvp_code_t cp) +{ + assert(cp->bit_idx1 >= 4); + for (unsigned idx = 0 ; idx < cp->bit_idx2 ; idx += 1) { + unsigned val = thr_get_bit(thr, cp->bit_idx1+idx); + switch (val) { + case 0: + val = 1; + break; + case 1: + val = 0; + break; + default: + val = 2; + break; + } + thr_put_bit(thr, cp->bit_idx1+idx, val); + } + return true; +} + bool of_JMP(vthread_t thr, vvp_code_t cp) { thr->pc = cp->cptr; return true; } +bool of_JMP0(vthread_t thr, vvp_code_t cp) +{ + if (thr_get_bit(thr, cp->bit_idx1) == 0) + thr->pc = cp->cptr; + return true; +} + +bool of_LOAD(vthread_t thr, vvp_code_t cp) +{ + assert(cp->bit_idx1 >= 4); + thr_put_bit(thr, cp->bit_idx1, functor_get(cp->iptr)); + return true; +} + +bool of_MOV(vthread_t thr, vvp_code_t cp) +{ + assert(cp->bit_idx1 >= 4); + + if (cp->bit_idx2 >= 4) { + for (unsigned idx = 0 ; idx < cp->number ; idx += 1) + thr_put_bit(thr, + cp->bit_idx1+idx, + thr_get_bit(thr, cp->bit_idx2+idx)); + + } else { + for (unsigned idx = 0 ; idx < cp->number ; idx += 1) + thr_put_bit(thr, + cp->bit_idx1+idx, + thr_get_bit(thr, cp->bit_idx2)); + } + + return true; +} + bool of_NOOP(vthread_t thr, vvp_code_t cp) { return true; @@ -131,6 +239,9 @@ bool of_VPI_CALL(vthread_t thr, vvp_code_t cp) /* * $Log: vthread.cc,v $ + * Revision 1.7 2001/03/22 05:08:00 steve + * implement %load, %inv, %jum/0 and %cmp/u + * * Revision 1.6 2001/03/20 06:16:24 steve * Add support for variable vectors. * diff --git a/vvp/vthread.txt b/vvp/vthread.txt index 339893343..642f7f66e 100644 --- a/vvp/vthread.txt +++ b/vvp/vthread.txt @@ -1,17 +1,60 @@ +/* + * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * + * $Id: vthread.txt,v 1.2 2001/03/22 05:08:00 steve Exp $ + */ + + THREAD DETAILS Thread objects in vvp are created by ``.thread'' statements in the -input source file. These cause +input source file. A thread object includes a program counter and private bit registers. The program counter is used to step the processor through -the code space as it executes instructions. The bit registers are for -use by the arithmetic operators as they operate. +the code space as it executes instructions. The bit registers each +hold Verilog-style 4-value bits and are for use by the arithmetic +operators as they operate. + +The program counter normally increments by one instruction after the +instruction is fetched. If the instruction is a branching instruction, +then the execution of the instruction sets a new value for the pc. Instructions that use the bit registers have as an operand a -value. There is space in the instruction for 2 operands. The -special values 0, 1, 2 and 3 are special constant bits 0, 1, x and z -and are used as immediate values for instructions that take single-bit -values. The remaining of 64K possible values are read-write bit -registers that can be accessed singly or as vectors. +value. There is usually space in the instruction for 2 +operands. Instructions that work on vectors pull the vector values +from the bit registers starting with the LSB and up. + +The bit addresses 0, 1, 2 and 3 are special constant bits 0, 1, x and +z, and are used as read-only immediate values. If the instruction +takes a single bit operand, the the appropriate value is simply read +out. If the instruction expects a vector, then a vector of the +expected width is created by replicating the constant value. + +Bits 4, 5, 6 and 7 are read/write bits but are reserved by many +instructions for special purposes. Comparison operators, for example, +use these as comparison flag bits. + +The remaining 64K-8 possible values are read-write bit registers +that can be accessed singly or as vectors. This obviously implies that +a bit address is 16 bits. + +/* + * Copyright (c) 2001 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */