Add force/cassign/release/deassign support. (Stephan Boettcher)

This commit is contained in:
steve 2001-11-01 03:00:19 +00:00
parent 75e78e86d3
commit 82c0a2ebac
13 changed files with 609 additions and 197 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.29 2001/10/21 21:59:50 steve Exp $"
#ident "$Id: Makefile.in,v 1.30 2001/11/01 03:00:19 steve Exp $"
#
#
SHELL = /bin/sh
@ -65,7 +65,7 @@ vpi_vthr_vector.o vvp_vpi.o
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o debug.o \
functor.o fvectors.o npmos.o resolv.o symbols.o codes.o vthread.o schedule.o \
tables.o udp.o memory.o $V
tables.o udp.o memory.o force.o $V
vvp: $O
$(CXX) $(rdynamic) $(CXXFLAGS) $(LDFLAGS) -o vvp $O $(LIBS) $(dllib)

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: README.txt,v 1.37 2001/10/16 02:47:37 steve Exp $
* $Id: README.txt,v 1.38 2001/11/01 03:00:19 steve Exp $
*/
VVP SIMULATION ENGINE
@ -218,12 +218,13 @@ read by behavioral code. If the .var represents a vector of .functors,
the index of the LSB is always, from the perspective of vvp, ZERO. The
<msb>,<lsb> details are there only for the benefit of VPI support.
The variable .functor implicitly has three inputs. The first is the
value that gets set by assignments or procedural continuous
assignments. The second is a forced value that can be connected to a
force expression (as a functor) when a value is being forced. And the
third input selects the source to use. The default is to select the
assignment input.
The variable .functor implicitly has two inputs. The first is the
value that gets set by assignments. The second input is connected to
the driving expression of a procedural continuous assignments.
Variable functors have an extra internal bit that tells if a
procedural continuous assignment is active. The %cassign opcode
connects and activates the procedural continuous assignment. The
%deassign opcode disconnects and deactivates it.
The variable statement also creates a VPI object of the appropriate
type. See the vpi.txt file for details about that object. The msb and
@ -397,6 +398,29 @@ resolution function.
<label> .resolv tri1, <symbols_list>;
FORCE STATEMENTS:
A force statement creates functors that represent a Verilog force
statement.
<label> .force <signal>, <symbol_list>;
The symbol <signal> represents the signal which is to be forced. The
<symbol_list> specifies the bits of the expression that is to be
forced on the <signal>. The <label> identifies the force functors.
There will be as many force functors as there are symbols in the
<symbol_list>.
To activate and deactivate a force on a single bit, use:
%force <label>, <width>;
%release <signal>;
<label>/<width> is the label/width of a vector of force functors.
<signal> is the label of the functor that drives the signal that is
being forced.
STRUCTURAL ARITHMETIC STATEMENTS:
The various Verilog arithmetic opeators (+-*/%) are available to

View File

@ -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.35 2001/10/16 01:26:54 steve Exp $"
#ident "$Id: codes.h,v 1.36 2001/11/01 03:00:19 steve Exp $"
#endif
@ -42,15 +42,18 @@ extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN(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_CMPX(vthread_t thr, vvp_code_t code);
extern bool of_CMPZ(vthread_t thr, vvp_code_t code);
extern bool of_DEASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
extern bool of_DELAYX(vthread_t thr, vvp_code_t code);
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
extern bool of_DIV(vthread_t thr, vvp_code_t code);
extern bool of_END(vthread_t thr, vvp_code_t code);
extern bool of_FORCE(vthread_t thr, vvp_code_t code);
extern bool of_FORK(vthread_t thr, vvp_code_t code);
extern bool of_INV(vthread_t thr, vvp_code_t code);
extern bool of_IX_ADD(vthread_t thr, vvp_code_t code);
@ -74,6 +77,7 @@ extern bool of_NOOP(vthread_t thr, vvp_code_t code);
extern bool of_NORR(vthread_t thr, vvp_code_t code);
extern bool of_OR(vthread_t thr, vvp_code_t code);
extern bool of_ORR(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE(vthread_t thr, vvp_code_t code);
extern bool of_SET(vthread_t thr, vvp_code_t code);
extern bool of_SET_MEM(vthread_t thr, vvp_code_t code);
extern bool of_SET_X(vthread_t thr, vvp_code_t code);
@ -101,25 +105,27 @@ struct vvp_code_s {
vvp_cpoint_t cptr;
vvp_memory_t mem;
struct __vpiHandle*handle;
struct fork_extend*fork;
struct __vpiScope*scope;
};
unsigned short bit_idx1;
unsigned short bit_idx2;
union {
unsigned short bit_idx[2];
vvp_ipoint_t iptr2;
vvp_cpoint_t cptr2;
};
};
struct fork_extend {
vvp_cpoint_t cptr;
struct __vpiScope*scope;
};
/*
* This function clears the code space, ready for initialization. This
* needs to be done exactly once before any instructions are created.
*/
extern void codespace_init(void);
/*
** Return the number of codes
*/
extern unsigned code_limit();
/*
* This function returns a pointer to the next free instruction in the
* code address space.
@ -141,6 +147,9 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
/*
* $Log: codes.h,v $
* Revision 1.36 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.35 2001/10/16 01:26:54 steve
* Add %div support (Anthony Bybell)
*

View File

@ -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.110 2001/10/31 04:27:46 steve Exp $"
#ident "$Id: compile.cc,v 1.111 2001/11/01 03:00:19 steve Exp $"
#endif
# include "arith.h"
@ -27,7 +27,8 @@
# include "functor.h"
# include "resolv.h"
# include "udp.h"
# include "memory.h"
# include "memory.h"
# include "force.h"
# include "symbols.h"
# include "codes.h"
# include "schedule.h"
@ -59,14 +60,16 @@ enum operand_e {
OA_NONE,
/* The operand is a number, an immediate unsigned integer */
OA_NUMBER,
/* The operand is a thread bit index */
/* The operand is a thread bit index or short integer */
OA_BIT1,
OA_BIT2,
/* The operand is a pointer to code space */
OA_CODE_PTR,
/* The operand is a variable or net pointer */
OA_FUNC_PTR,
/* The operand is a pointer to a memory */
/* The operand is a second functor pointer */
OA_FUNC_PTR2,
/* The operand is a pointer to a memory */
OA_MEM_PTR,
};
@ -86,14 +89,17 @@ const static struct opcode_table_s opcode_table[] = {
{ "%assign/m",of_ASSIGN_MEM,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cassign",of_CASSIGN,2, {OA_FUNC_PTR, OA_FUNC_PTR2,OA_NONE} },
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/u", of_CMPU, 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} },
{ "%deassign",of_DEASSIGN,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%force", of_FORCE, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%ix/add", of_IX_ADD, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
{ "%ix/get", of_IX_GET, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@ -116,6 +122,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%release",of_RELEASE,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%set/m", of_SET_MEM,2, {OA_MEM_PTR, OA_BIT1, OA_NONE} },
{ "%set/x", of_SET_X, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
@ -399,7 +406,7 @@ bool code_label_resolv_list_s::resolve(bool mes)
symbol_value_t val = sym_get_value(sym_codespace, label);
if (val.num) {
if (code->opcode == of_FORK)
code->fork->cptr = val.num;
code->cptr2 = val.num;
else
code->cptr = val.num;
free(label);
@ -954,6 +961,28 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
free(argv);
}
void compile_force(char*label, struct symb_s signal,
unsigned argc, struct symb_s*argv)
{
vvp_ipoint_t ifofu = functor_allocate(argc);
define_functor_symbol(label, ifofu);
for (unsigned i=0; i<argc; i++) {
functor_t obj = new force_functor_s;
vvp_ipoint_t iobj = ipoint_index(ifofu, i);
functor_define(iobj, obj);
functor_ref_lookup(&obj->out, strdup(signal.text), signal.idx + i);
// connect the force expression, one bit.
inputs_connect(iobj, 1, &argv[i]);
}
free(argv);
free(signal.text);
free(label);
}
void compile_udp_def(int sequ, char *label, char *name,
unsigned nin, unsigned init, char **table)
{
@ -1176,7 +1205,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
code->bit_idx1 = opa->argv[idx].numb;
code->bit_idx[0] = opa->argv[idx].numb;
break;
case OA_BIT2:
@ -1185,7 +1214,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
code->bit_idx2 = opa->argv[idx].numb;
code->bit_idx[1] = opa->argv[idx].numb;
break;
case OA_CODE_PTR:
@ -1212,6 +1241,20 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
opa->argv[idx].symb.idx);
break;
case OA_FUNC_PTR2:
/* The operand is a functor. Resolve the label to
a functor pointer, or postpone the resolution
if it is not defined yet. */
if (opa->argv[idx].ltype != L_SYMB) {
yyerror("operand format");
break;
}
functor_ref_lookup(&code->iptr2,
opa->argv[idx].symb.text,
opa->argv[idx].symb.idx);
break;
case OA_NUMBER:
if (opa->argv[idx].ltype != L_NUMB) {
yyerror("operand format");
@ -1285,13 +1328,12 @@ void compile_fork(char*label, struct symb_s dest, struct symb_s scope)
/* Fill in the basics of the %fork in the instruction. */
vvp_code_t code = codespace_index(ptr);
code->opcode = of_FORK;
code->fork = new struct fork_extend;
/* Figure out the target PC. */
code_label_lookup(code, dest.text);
/* Figure out the target SCOPE. */
compile_vpi_lookup((vpiHandle*)&code->fork->scope, scope.text);
compile_vpi_lookup((vpiHandle*)&code->scope, scope.text);
}
void compile_vpi_call(char*label, char*name, unsigned argc, vpiHandle*argv)
@ -1422,6 +1464,9 @@ vvp_ipoint_t debug_lookup_functor(const char*name)
/*
* $Log: compile.cc,v $
* Revision 1.111 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.110 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.h,v 1.35 2001/10/31 04:27:46 steve Exp $"
#ident "$Id: compile.h,v 1.36 2001/11/01 03:00:19 steve Exp $"
#endif
# include <stdio.h>
@ -71,6 +71,12 @@ extern void compile_functor(char*label, char*type,
extern void compile_resolver(char*label, char*type,
unsigned argc, struct symb_s*argv);
/*
* This is called by the parser to make force functors.
*/
extern void compile_force(char*label, struct symb_s signal,
unsigned argc, struct symb_s*argv);
/*
* This is called by the parser to make the various arithmetic and
* comparison functors.
@ -202,6 +208,9 @@ extern void compile_net(char*label, char*name,
/*
* $Log: compile.h,v $
* Revision 1.36 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.35 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.

250
vvp/force.cc Normal file
View File

@ -0,0 +1,250 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
*
* 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
*/
#if !defined(WINNT)
#ident "$Id: force.cc,v 1.1 2001/11/01 03:00:19 steve Exp $"
#endif
# include "codes.h"
# include "force.h"
# include <assert.h>
inline bool functor_s::disable(vvp_ipoint_t ptr)
{
bool r = inhibit;
inhibit = 1;
return r;
}
inline bool functor_s::enable(vvp_ipoint_t ptr)
{
unsigned val;
if (ostr == 0)
val = 3;
else switch (ostr & 0x88) {
case 0x00: val = 0; break;
case 0x88: val = 1; break;
default: val = 2;
}
if (val != oval) {
oval = val;
propagate(true);
}
bool r = inhibit;
inhibit = 0;
return r;
}
inline void functor_s::force(unsigned val, unsigned str)
{
if (ostr != str || oval != val) {
unsigned save = ostr;
oval = val;
ostr = str;
propagate(true);
ostr = save;
}
}
void force_functor_s::set(vvp_ipoint_t i, bool, unsigned val, unsigned str)
{
put(i, val);
if (ipoint_port(i) == 0) {
if (active && out) {
functor_t tgt = functor_index(out);
tgt->force(ival&3, get_ostr());
}
}
}
static bool release_force(vvp_ipoint_t itgt, functor_t tgt)
{
vvp_ipoint_t *ref = &tgt->out;
while (*ref) {
functor_t fofu = functor_index(*ref);
unsigned pp = ipoint_port(*ref);
if (pp == 3 && fofu->out == itgt) {
force_functor_s *ff = dynamic_cast<force_functor_s *>(fofu);
if (ff && ff->active) {
ff->active = 0;
*ref = fofu->port[pp];
fofu->port[pp] = 0;
return true;
}
}
ref = &fofu->port[pp];
}
return false;
}
bool of_FORCE(vthread_t thr, vvp_code_t cp)
{
unsigned wid = cp->bit_idx[0];
for (unsigned i=0; i<wid; i++) {
vvp_ipoint_t ifofu = ipoint_index(cp->iptr, i);
functor_t fofu = functor_index(ifofu);
force_functor_s *ff = dynamic_cast<force_functor_s *>(fofu);
assert(ff);
if (ff->active)
return true;
ff->active = 1;
vvp_ipoint_t itgt = fofu->out;
functor_t tgt = functor_index(itgt);
if (tgt->disable(itgt))
release_force(itgt, tgt);
fofu->port[3] = tgt->out;
tgt->out = ipoint_make(ifofu, 3);
fofu->set(ifofu, false, fofu->ival&3, fofu->get_ostr());
}
return true;
}
bool of_RELEASE(vthread_t thr, vvp_code_t cp)
{
vvp_ipoint_t itgt = cp->iptr;
functor_t tgt = functor_index(itgt);
if (release_force(itgt, tgt))
tgt->enable(itgt);
// bug: a strength change will not be propagated.
return true;
}
/*
** Variable functors receive %set or %assign-ed values at port[0].
** Continuous assignments are connected to port[1].
**
** port[3] points back to the functor that drives the continuous
** assignment. This also serves as a flag if assignment is active.
**
** A constant is assigned if the expr ipoint is < 4, i.e. a port of
** the NULL functor. port[3] is set to 3.
*/
void var_functor_s::set(vvp_ipoint_t ptr, bool push, unsigned val, unsigned)
{
unsigned pp = ipoint_port(ptr);
if (assigned() && pp==1 || !assigned() && pp==0) {
put_oval(ptr, push, val);
}
}
bool var_functor_s::deassign(vvp_ipoint_t itgt)
{
if (!assigned())
return false;
vvp_ipoint_t ipt = port[3];
if (ipt == ipoint_make(0, 3)) {
port[3] = 0;
return true;
}
functor_t fp = functor_index(ipt);
vvp_ipoint_t *ref = &fp->out;
itgt = ipoint_make(itgt, 1);
while (*ref) {
if (*ref == itgt) {
*ref = port[1];
port[1] = 0;
return true;
}
functor_t fu = functor_index(*ref);
unsigned pp = ipoint_port(*ref);
ref = &fu->port[pp];
}
return false;
}
bool of_CASSIGN(vthread_t thr, vvp_code_t cp)
{
vvp_ipoint_t itgt = cp->iptr;
vvp_ipoint_t iexp = cp->iptr2;
functor_t tgt = functor_index(itgt);
var_functor_s *var = dynamic_cast<var_functor_s *>(tgt);
assert(var);
var->deassign(itgt);
// a constant expression?
if (ipoint_make(iexp, 0) == 0) {
tgt->port[3] = ipoint_make(0, 3);
tgt->set(ipoint_make(itgt, 1), true, ipoint_port(iexp));
return true;
}
functor_t fu = functor_index(iexp);
tgt->port[3] = iexp;
tgt->port[1] = fu->out;
fu->out = ipoint_make(itgt, 1);
tgt->set(ipoint_make(itgt, 1), true, fu->get());
return true;
}
bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
{
vvp_ipoint_t itgt = cp->iptr;
unsigned wid = cp->bit_idx[0];
for (unsigned i = 0; i<wid; i++) {
vvp_ipoint_t ipt = ipoint_index(itgt, i);
functor_t tgt = functor_index(ipt);
var_functor_s *var = dynamic_cast<var_functor_s *>(tgt);
assert(var);
var->deassign(ipt);
}
return true;
}
/*
* $Log: force.cc,v $
* Revision 1.1 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
*/

59
vvp/force.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef __force_H
#define __force_H
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
*
* 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
*/
#if !defined(WINNT)
#ident "$Id: force.h,v 1.1 2001/11/01 03:00:19 steve Exp $"
#endif
#include "functor.h"
/*
* Force functors
*/
class force_functor_s : public functor_s
{
public:
force_functor_s() : active(0) {}
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
unsigned active : 1;
};
/*
* Variable functors
*/
struct var_functor_s: public functor_s {
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
bool assigned() { return !!port[3]; };
bool deassign(vvp_ipoint_t itgt);
};
/*
* $Log: force.h,v $
* Revision 1.1 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
*/
#endif

View File

@ -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.29 2001/10/31 04:27:46 steve Exp $"
#ident "$Id: functor.cc,v 1.30 2001/11/01 03:00:19 steve Exp $"
#endif
# include "functor.h"
@ -158,21 +158,6 @@ void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
}
}
/*
* Variable functors receive %assign-ed values at port[0].
* Continuous assignments are connected to port[1].
*/
void var_functor_s::set(vvp_ipoint_t ptr, bool push, unsigned val, unsigned)
{
unsigned pp = ipoint_port(ptr);
if (assigned && pp==1 || !assigned && pp==0) {
put_oval(ptr, push, val);
}
}
void extra_outputs_functor_s::set(vvp_ipoint_t i, bool push,
unsigned val, unsigned)
{
@ -201,6 +186,9 @@ void extra_inputs_functor_s::set(vvp_ipoint_t i, bool push,
/*
* $Log: functor.cc,v $
* Revision 1.30 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.29 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.

View File

@ -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.35 2001/10/31 04:27:46 steve Exp $"
#ident "$Id: functor.h,v 1.36 2001/11/01 03:00:19 steve Exp $"
#endif
# include "pointers.h"
@ -197,12 +197,14 @@ struct functor_s {
unsigned val, unsigned str = 0) = 0;
inline unsigned char get() { return oval; }
inline unsigned char get_ostr() { return ostr; }
void put(vvp_ipoint_t ipt, unsigned val);
void put_oval(vvp_ipoint_t ptr, bool push, unsigned val);
void put_ostr(vvp_ipoint_t ptr, bool push, unsigned val, unsigned str);
bool disable(vvp_ipoint_t ptr);
bool enable(vvp_ipoint_t ptr);
void propagate(bool push);
void force(unsigned val, unsigned str);
};
inline functor_s::functor_s()
@ -292,31 +294,6 @@ inline void functor_s::put_ostr(vvp_ipoint_t ptr, bool push,
}
}
inline bool functor_s::disable(vvp_ipoint_t ptr)
{
bool r = inhibit;
inhibit = 1;
return r;
}
inline bool functor_s::enable(vvp_ipoint_t ptr)
{
unsigned val;
if (ostr == 0)
val = 3;
else switch (ostr & 0x88) {
case 0x00: val = 0; break;
case 0x88: val = 1; break;
default: val = 2;
}
if (val != oval) {
schedule_functor(ptr, 0);
}
bool r = inhibit;
inhibit = 0;
return r;
}
/*
* functor_set sets the addressed input to the specified value, and
* calculates a new output value. If there is any propagation to do,
@ -472,17 +449,6 @@ const event_functor_s::edge_t vvp_edge_negedge
const event_functor_s::edge_t vvp_edge_anyedge = 0x7bde;
const event_functor_s::edge_t vvp_edge_none = 0;
/*
* Variable functors
*/
struct var_functor_s: public functor_s {
var_functor_s() : assigned(0) {};
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
unsigned assigned : 1;
};
/*
* Callback functors.
*/
@ -502,6 +468,9 @@ extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p);
/*
* $Log: functor.h,v $
* Revision 1.36 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.35 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: lexor.lex,v 1.27 2001/10/16 02:47:37 steve Exp $"
#ident "$Id: lexor.lex,v 1.28 2001/11/01 03:00:19 steve Exp $"
#endif
# include "parse_misc.h"
@ -90,6 +90,7 @@
".mem" { return K_MEM; }
".mem/p"(ort)? { return K_MEM_P; }
".mem/i"(nit)? { return K_MEM_I; }
".force" { return K_FORCE; }
/* instructions start with a % character. The compiler decides what
kind of instruction this really is. The few exceptions (that have
@ -149,6 +150,9 @@ int yywrap()
/*
* $Log: lexor.lex,v $
* Revision 1.28 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.27 2001/10/16 02:47:37 steve
* Add arith/div object.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.30 2001/10/16 01:26:55 steve Exp $
* $Id: opcodes.txt,v 1.31 2001/11/01 03:00:19 steve Exp $
*/
@ -82,6 +82,21 @@ This may not work on all platforms. If run-time debugging is compiled
out, then this function is a no-op.
* %cassign <var-label>, <expr-label>
Connect and active a procedural continuous assignment to a
variable. The <var-label> identifies the affected variable, and the
<expr-label> is the functor that drives the expression to the
variable. This opcode affects only a single bit.
* %deassign <var-label>, <wid>
Deactive and disconnect a procedural continuous assignment to a
variable. The <var-label> identifies the affected variable. <wid>
specifies the how many bits to deassign.
* %cmp/u <bit-l>, <bit-r>, <wid>
* %cmp/s <bit-l>, <bit-r>, <wid>
@ -151,6 +166,14 @@ This instruction arithmetically divides the <bit-l> vector by the
the bits in either vector are x or z, the entire result is x.
* %force <fofu-label>, <width>
Activate a force represented by the force functors <fofu-label>, which
were created with a .force directive. If any force was active on the
signal, that force is released first. A vector of force functors may
be specified with <width> greater than 1.
* %fork <code-label>, <scope-label>
This instruction is similar to %jmp, except that it creates a new
@ -309,6 +332,7 @@ truth table:
0 or 0 --> 0
otherwise x
* %or/r <dst>, <src>, <wid>
This is a reduction version of the %or opcode. The <src> is a vector,
@ -316,6 +340,22 @@ and the <dst> is a writeable scaler. The <dst> gets the value of the
or of all the bits of the src vector.
* %release <functor-label>
Release the force on the signal that is represented by the functor
<functor-label>. The force was previously activated with a %force
statement. If no force was active on this functor the statement does
nothing. %release restores and propagates the normal value of the
previously forced functor. In case of a forced Verilog register, the
current value of the force expression should be %set to the .var
functor before the force is released, to comply with Verilog release
semantics. Like:
%load <bit>, <functor-label> ; get the forced value
%set <functor-label>, <bit> ; set the .var value
%release <functor-label> ; remove the force
* %set <var-label>, <bit>
This sets a bit of a variable, and is used to implement blocking

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: parse.y,v 1.39 2001/10/31 04:27:47 steve Exp $"
#ident "$Id: parse.y,v 1.40 2001/11/01 03:00:19 steve Exp $"
#endif
# include "parse_misc.h"
@ -59,6 +59,7 @@ extern FILE*yyin;
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD
%token K_UDP K_UDP_C K_UDP_S
%token K_MEM K_MEM_P K_MEM_I
%token K_FORCE
%token K_VAR K_VAR_S K_vpi_call K_vpi_func K_disable K_fork
%token K_vpi_module K_vpi_time_precision
@ -158,6 +159,14 @@ statement
compile_resolver($1, $3, obj.cnt, obj.vect);
}
/* Force statements are very much like functors. They are
compiled to functors of a different mode. */
| T_LABEL K_FORCE symbol ',' symbols ';'
{ struct symbv_s obj = $5;
compile_force($1, $3, obj.cnt, obj.vect);
}
/* Arithmetic statements generate functor arrays of a given width
that take like size input vectors. */
@ -505,6 +514,9 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.40 2001/11/01 03:00:19 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.39 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.

View File

@ -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.62 2001/10/31 04:27:47 steve Exp $"
#ident "$Id: vthread.cc,v 1.63 2001/11/01 03:00:20 steve Exp $"
#endif
# include "vthread.h"
@ -305,10 +305,10 @@ void vthread_schedule_list(vthread_t thr)
bool of_AND(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -336,10 +336,10 @@ bool of_AND(vthread_t thr, vvp_code_t cp)
bool of_ADD(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned long*lva = vector_to_array(thr, cp->bit_idx1, cp->number);
unsigned long*lvb = vector_to_array(thr, cp->bit_idx2, cp->number);
unsigned long*lva = vector_to_array(thr, cp->bit_idx[0], cp->number);
unsigned long*lvb = vector_to_array(thr, cp->bit_idx[1], cp->number);
if (lva == 0 || lvb == 0)
goto x_out;
@ -362,7 +362,7 @@ bool of_ADD(vthread_t thr, vvp_code_t cp)
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned bit = lva[idx/CPU_BITS] >> (idx % CPU_BITS);
thr_put_bit(thr, cp->bit_idx1+idx, (bit&1) ? 1 : 0);
thr_put_bit(thr, cp->bit_idx[0]+idx, (bit&1) ? 1 : 0);
}
delete[]lva;
@ -375,30 +375,30 @@ bool of_ADD(vthread_t thr, vvp_code_t cp)
delete[]lvb;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, 2);
thr_put_bit(thr, cp->bit_idx[0]+idx, 2);
return true;
}
bool of_ASSIGN(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx2);
schedule_assign(cp->iptr, bit_val, cp->bit_idx1);
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
schedule_assign(cp->iptr, bit_val, cp->bit_idx[0]);
return true;
}
bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx2);
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
vvp_ipoint_t itmp = ipoint_index(cp->iptr, thr->index[0]);
schedule_assign(itmp, bit_val, cp->bit_idx1);
schedule_assign(itmp, bit_val, cp->bit_idx[0]);
return true;
}
bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx2);
schedule_memory(cp->mem, thr->index[3], bit_val, cp->bit_idx1);
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
schedule_memory(cp->mem, thr->index[3], bit_val, cp->bit_idx[0]);
return true;
}
@ -416,8 +416,8 @@ bool of_CMPS(vthread_t thr, vvp_code_t cp)
unsigned eeq = 1;
unsigned lt = 0;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
unsigned sig1 = thr_get_bit(thr, idx1 + cp->number - 1);
unsigned sig2 = thr_get_bit(thr, idx2 + cp->number - 1);
@ -466,8 +466,8 @@ bool of_CMPU(vthread_t thr, vvp_code_t cp)
unsigned eeq = 1;
unsigned lt = 0;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lv = thr_get_bit(thr, idx1);
@ -507,8 +507,8 @@ bool of_CMPX(vthread_t thr, vvp_code_t cp)
{
unsigned eq = 1;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lv = thr_get_bit(thr, idx1);
@ -532,8 +532,8 @@ bool of_CMPZ(vthread_t thr, vvp_code_t cp)
{
unsigned eq = 1;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lv = thr_get_bit(thr, idx1);
@ -625,11 +625,11 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
bool of_DIV(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
if(cp->number <= 8*sizeof(unsigned long)) {
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
unsigned long lv = 0, rv = 0;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -653,7 +653,7 @@ bool of_DIV(vthread_t thr, vvp_code_t cp)
lv /= rv;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, (lv&1) ? 1 : 0);
thr_put_bit(thr, cp->bit_idx[0]+idx, (lv&1) ? 1 : 0);
lv >>= 1;
}
@ -675,8 +675,8 @@ bool of_DIV(vthread_t thr, vvp_code_t cp)
int i;
int current, copylen;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
@ -751,7 +751,7 @@ bool of_DIV(vthread_t thr, vvp_code_t cp)
tally:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
// n.b., z[] has the remainder...
thr_put_bit(thr, cp->bit_idx1+idx, b[idx]);
thr_put_bit(thr, cp->bit_idx[0]+idx, b[idx]);
}
delete []t;
@ -763,7 +763,7 @@ bool of_DIV(vthread_t thr, vvp_code_t cp)
x_out:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, 2);
thr_put_bit(thr, cp->bit_idx[0]+idx, 2);
return true;
}
@ -850,7 +850,7 @@ bool of_END(vthread_t thr, vvp_code_t)
*/
bool of_FORK(vthread_t thr, vvp_code_t cp)
{
vthread_t child = vthread_new(cp->fork->cptr, cp->fork->scope);
vthread_t child = vthread_new(cp->cptr2, cp->scope);
child->child = thr->child;
child->parent = thr;
@ -865,9 +865,9 @@ bool of_FORK(vthread_t thr, vvp_code_t cp)
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);
assert(cp->bit_idx[0] >= 4);
for (unsigned idx = 0 ; idx < cp->bit_idx[1] ; idx += 1) {
unsigned val = thr_get_bit(thr, cp->bit_idx[0]+idx);
switch (val) {
case 0:
val = 1;
@ -879,7 +879,7 @@ bool of_INV(vthread_t thr, vvp_code_t cp)
val = 2;
break;
}
thr_put_bit(thr, cp->bit_idx1+idx, val);
thr_put_bit(thr, cp->bit_idx[0]+idx, val);
}
return true;
}
@ -891,25 +891,25 @@ bool of_INV(vthread_t thr, vvp_code_t cp)
bool of_IX_ADD(vthread_t thr, vvp_code_t cp)
{
thr->index[cp->bit_idx1 & 3] += cp->number;
thr->index[cp->bit_idx[0] & 3] += cp->number;
return true;
}
bool of_IX_SUB(vthread_t thr, vvp_code_t cp)
{
thr->index[cp->bit_idx1 & 3] -= cp->number;
thr->index[cp->bit_idx[0] & 3] -= cp->number;
return true;
}
bool of_IX_MUL(vthread_t thr, vvp_code_t cp)
{
thr->index[cp->bit_idx1 & 3] *= cp->number;
thr->index[cp->bit_idx[0] & 3] *= cp->number;
return true;
}
bool of_IX_LOAD(vthread_t thr, vvp_code_t cp)
{
thr->index[cp->bit_idx1 & 3] = cp->number;
thr->index[cp->bit_idx[0] & 3] = cp->number;
return true;
}
@ -917,14 +917,14 @@ bool of_IX_GET(vthread_t thr, vvp_code_t cp)
{
unsigned long v = 0;
for (unsigned i = 0; i<cp->number; i++) {
unsigned char vv = thr_get_bit(thr, cp->bit_idx2 + i);
unsigned char vv = thr_get_bit(thr, cp->bit_idx[1] + i);
if (vv&2) {
v = ~0UL;
break;
}
v |= vv << i;
}
thr->index[cp->bit_idx1 & 3] = v;
thr->index[cp->bit_idx[0] & 3] = v;
return true;
}
@ -942,21 +942,21 @@ bool of_JMP(vthread_t thr, vvp_code_t cp)
bool of_JMP0(vthread_t thr, vvp_code_t cp)
{
if (thr_get_bit(thr, cp->bit_idx1) == 0)
if (thr_get_bit(thr, cp->bit_idx[0]) == 0)
thr->pc = cp->cptr;
return true;
}
bool of_JMP0XZ(vthread_t thr, vvp_code_t cp)
{
if (thr_get_bit(thr, cp->bit_idx1) != 1)
if (thr_get_bit(thr, cp->bit_idx[0]) != 1)
thr->pc = cp->cptr;
return true;
}
bool of_JMP1(vthread_t thr, vvp_code_t cp)
{
if (thr_get_bit(thr, cp->bit_idx1) == 1)
if (thr_get_bit(thr, cp->bit_idx[0]) == 1)
thr->pc = cp->cptr;
return true;
}
@ -985,36 +985,36 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
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));
assert(cp->bit_idx[0] >= 4);
thr_put_bit(thr, cp->bit_idx[0], functor_get(cp->iptr));
return true;
}
bool of_LOAD_MEM(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned char val = memory_get(cp->mem, thr->index[3]);
thr_put_bit(thr, cp->bit_idx1, val);
thr_put_bit(thr, cp->bit_idx[0], val);
return true;
}
bool of_LOAD_X(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx2 < 4);
assert(cp->bit_idx[0] >= 4);
assert(cp->bit_idx[1] < 4);
vvp_ipoint_t ptr = ipoint_index(cp->iptr, thr->index[cp->bit_idx2]);
thr_put_bit(thr, cp->bit_idx1, functor_get(ptr));
vvp_ipoint_t ptr = ipoint_index(cp->iptr, thr->index[cp->bit_idx[1]]);
thr_put_bit(thr, cp->bit_idx[0], functor_get(ptr));
return true;
}
bool of_MOD(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
if(cp->number <= 8*sizeof(unsigned long)) {
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
unsigned long lv = 0, rv = 0;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1038,7 +1038,7 @@ if(cp->number <= 8*sizeof(unsigned long)) {
lv %= rv;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, (lv&1) ? 1 : 0);
thr_put_bit(thr, cp->bit_idx[0]+idx, (lv&1) ? 1 : 0);
lv >>= 1;
}
@ -1059,8 +1059,8 @@ if(cp->number <= 8*sizeof(unsigned long)) {
int i;
int current, copylen;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
@ -1136,7 +1136,7 @@ if(cp->number <= 8*sizeof(unsigned long)) {
tally:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, z[idx]);
thr_put_bit(thr, cp->bit_idx[0]+idx, z[idx]);
}
delete []t;
@ -1147,24 +1147,24 @@ tally:
x_out:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, 2);
thr_put_bit(thr, cp->bit_idx[0]+idx, 2);
return true;
}
bool of_MOV(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
if (cp->bit_idx2 >= 4) {
if (cp->bit_idx[1] >= 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));
cp->bit_idx[0]+idx,
thr_get_bit(thr, cp->bit_idx[1]+idx));
} else {
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, cp->bit_idx2);
thr_put_bit(thr, cp->bit_idx[0]+idx, cp->bit_idx[1]);
}
return true;
@ -1172,11 +1172,11 @@ bool of_MOV(vthread_t thr, vvp_code_t cp)
bool of_MUL(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
if(cp->number <= 8*sizeof(unsigned long)) {
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
unsigned long lv = 0, rv = 0;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1197,14 +1197,14 @@ bool of_MUL(vthread_t thr, vvp_code_t cp)
lv *= rv;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, (lv&1) ? 1 : 0);
thr_put_bit(thr, cp->bit_idx[0]+idx, (lv&1) ? 1 : 0);
lv >>= 1;
}
return true;
} else {
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
unsigned char *a, *b, *sum;
a = new unsigned char[cp->number];
@ -1254,7 +1254,7 @@ bool of_MUL(vthread_t thr, vvp_code_t cp)
}
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, sum[idx]);
thr_put_bit(thr, cp->bit_idx[0]+idx, sum[idx]);
}
delete[]sum;
@ -1265,7 +1265,7 @@ bool of_MUL(vthread_t thr, vvp_code_t cp)
x_out:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, 2);
thr_put_bit(thr, cp->bit_idx[0]+idx, 2);
return true;
}
@ -1277,10 +1277,10 @@ bool of_NOOP(vthread_t thr, vvp_code_t cp)
bool of_NORR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned lb = 1;
unsigned idx2 = cp->bit_idx2;
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1294,17 +1294,17 @@ bool of_NORR(vthread_t thr, vvp_code_t cp)
lb = 2;
}
thr_put_bit(thr, cp->bit_idx1, lb);
thr_put_bit(thr, cp->bit_idx[0], lb);
return true;
}
bool of_ANDR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned lb = 1;
unsigned idx2 = cp->bit_idx2;
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1318,17 +1318,17 @@ bool of_ANDR(vthread_t thr, vvp_code_t cp)
lb = 2;
}
thr_put_bit(thr, cp->bit_idx1, lb);
thr_put_bit(thr, cp->bit_idx[0], lb);
return true;
}
bool of_NANDR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned lb = 0;
unsigned idx2 = cp->bit_idx2;
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1342,17 +1342,17 @@ bool of_NANDR(vthread_t thr, vvp_code_t cp)
lb = 2;
}
thr_put_bit(thr, cp->bit_idx1, lb);
thr_put_bit(thr, cp->bit_idx[0], lb);
return true;
}
bool of_ORR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned lb = 0;
unsigned idx2 = cp->bit_idx2;
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1366,17 +1366,17 @@ bool of_ORR(vthread_t thr, vvp_code_t cp)
lb = 2;
}
thr_put_bit(thr, cp->bit_idx1, lb);
thr_put_bit(thr, cp->bit_idx[0], lb);
return true;
}
bool of_XORR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned lb = 0;
unsigned idx2 = cp->bit_idx2;
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1389,17 +1389,17 @@ bool of_XORR(vthread_t thr, vvp_code_t cp)
}
}
thr_put_bit(thr, cp->bit_idx1, lb);
thr_put_bit(thr, cp->bit_idx[0], lb);
return true;
}
bool of_XNORR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned lb = 1;
unsigned idx2 = cp->bit_idx2;
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1412,17 +1412,17 @@ bool of_XNORR(vthread_t thr, vvp_code_t cp)
}
}
thr_put_bit(thr, cp->bit_idx1, lb);
thr_put_bit(thr, cp->bit_idx[0], lb);
return true;
}
bool of_OR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1451,7 +1451,7 @@ static const unsigned char strong_values[4] = {St0, St1, StX, HiZ};
bool of_SET(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx1);
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[0]);
functor_set(cp->iptr, bit_val, strong_values[bit_val], true);
return true;
@ -1459,7 +1459,7 @@ bool of_SET(vthread_t thr, vvp_code_t cp)
bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
{
unsigned char val = thr_get_bit(thr, cp->bit_idx1);
unsigned char val = thr_get_bit(thr, cp->bit_idx[0]);
memory_set(cp->mem, thr->index[3], val);
return true;
@ -1467,8 +1467,8 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
bool of_SET_X(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx1);
vvp_ipoint_t itmp = ipoint_index(cp->iptr, thr->index[cp->bit_idx2&3]);
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[0]);
vvp_ipoint_t itmp = ipoint_index(cp->iptr, thr->index[cp->bit_idx[1]&3]);
functor_set(itmp, bit_val, strong_values[bit_val], true);
return true;
@ -1476,7 +1476,7 @@ bool of_SET_X(vthread_t thr, vvp_code_t cp)
bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
{
unsigned base = cp->bit_idx1;
unsigned base = cp->bit_idx[0];
unsigned wid = cp->number;
unsigned long shift = thr->index[0];
@ -1501,7 +1501,7 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
*/
bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
{
unsigned base = cp->bit_idx1;
unsigned base = cp->bit_idx[0];
unsigned wid = cp->number;
unsigned long shift = thr->index[0];
@ -1523,10 +1523,10 @@ bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
bool of_SUB(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned long*lva = vector_to_array(thr, cp->bit_idx1, cp->number);
unsigned long*lvb = vector_to_array(thr, cp->bit_idx2, cp->number);
unsigned long*lva = vector_to_array(thr, cp->bit_idx[0], cp->number);
unsigned long*lvb = vector_to_array(thr, cp->bit_idx[1], cp->number);
if (lva == 0 || lvb == 0)
goto x_out;
@ -1544,7 +1544,7 @@ bool of_SUB(vthread_t thr, vvp_code_t cp)
sum += 1 & ~(tmp >> (idx%CPU_BITS));
carry = sum / 2;
thr_put_bit(thr, cp->bit_idx1+idx, (sum&1) ? 1 : 0);
thr_put_bit(thr, cp->bit_idx[0]+idx, (sum&1) ? 1 : 0);
}
delete[]lva;
@ -1557,7 +1557,7 @@ bool of_SUB(vthread_t thr, vvp_code_t cp)
delete[]lvb;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, 2);
thr_put_bit(thr, cp->bit_idx[0]+idx, 2);
return true;
}
@ -1588,10 +1588,10 @@ bool of_WAIT(vthread_t thr, vvp_code_t cp)
bool of_XNOR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1625,10 +1625,10 @@ bool of_XNOR(vthread_t thr, vvp_code_t cp)
bool of_XOR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
@ -1671,6 +1671,9 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t)
/*
* $Log: vthread.cc,v $
* Revision 1.63 2001/11/01 03:00:20 steve
* Add force/cassign/release/deassign support. (Stephan Boettcher)
*
* Revision 1.62 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.