Add the .ufunc statement.
This commit is contained in:
parent
7349a6beaf
commit
de252965ac
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.35 2002/02/03 01:01:51 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.36 2002/03/18 00:19:34 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -66,8 +66,8 @@ vpi_priv.o vpi_scope.o vpi_signal.o vpi_tasks.o vpi_time.o vpi_memory.o \
|
|||
vpi_vthr_vector.o vpip_to_dec.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 force.o event.o logic.o delay.o $V
|
||||
functor.o fvectors.o npmos.o resolv.o symbols.o ufunc.o codes.o vthread.o \
|
||||
schedule.o tables.o udp.o memory.o force.o event.o logic.o delay.o $V
|
||||
|
||||
vvp: $O
|
||||
$(CXX) $(rdynamic) $(CXXFLAGS) $(LDFLAGS) -o vvp $O $(LIBS) $(dllib)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: README.txt,v 1.39 2002/01/03 04:19:01 steve Exp $
|
||||
* $Id: README.txt,v 1.40 2002/03/18 00:19:34 steve Exp $
|
||||
*/
|
||||
|
||||
VVP SIMULATION ENGINE
|
||||
|
|
@ -476,6 +476,13 @@ number of data inputs. The first <wid> symbols in the <symbols_list>
|
|||
gives the input data. The remaining hold the shift value, lsb first.
|
||||
|
||||
|
||||
STRUCTURAL FUNCTION CALLS:
|
||||
|
||||
The .ufunc statement defines a call to a user defined function.
|
||||
|
||||
<label> .ufunc ;
|
||||
|
||||
|
||||
THREAD STATEMENTS:
|
||||
|
||||
Thread statements create the initial threads for a simulation. These
|
||||
|
|
|
|||
|
|
@ -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.37 2001/11/07 03:34:42 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.38 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -93,6 +93,8 @@ extern bool of_XORR(vthread_t thr, vvp_code_t code);
|
|||
|
||||
extern bool of_ZOMBIE(vthread_t thr, vvp_code_t code);
|
||||
|
||||
extern bool of_CALL_UFUNC(vthread_t thr, vvp_code_t code);
|
||||
|
||||
/*
|
||||
* This is the format of a machine code instruction.
|
||||
*/
|
||||
|
|
@ -113,6 +115,7 @@ struct vvp_code_s {
|
|||
unsigned short bit_idx[2];
|
||||
vvp_ipoint_t iptr2;
|
||||
vvp_cpoint_t cptr2;
|
||||
struct ufunc_core*ufunc_core_ptr;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -148,6 +151,9 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
|
|||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.38 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
* Revision 1.37 2001/11/07 03:34:42 steve
|
||||
* Use functor pointers where vvp_ipoint_t is unneeded.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.121 2002/03/08 05:41:45 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.122 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
|
|
@ -325,7 +325,6 @@ bool functor_gen_resolv_list_s::resolve(bool mes)
|
|||
return false;
|
||||
}
|
||||
|
||||
inline static
|
||||
void functor_ref_lookup(vvp_ipoint_t *ref, char*lab, unsigned idx)
|
||||
{
|
||||
struct functor_gen_resolv_list_s*res =
|
||||
|
|
@ -418,7 +417,6 @@ bool code_label_resolv_list_s::resolve(bool mes)
|
|||
return false;
|
||||
}
|
||||
|
||||
inline static
|
||||
void code_label_lookup(struct vvp_code_s *code, char *label)
|
||||
{
|
||||
struct code_label_resolv_list_s *res
|
||||
|
|
@ -578,8 +576,8 @@ void const_functor_s::set(vvp_ipoint_t p, bool, unsigned val, unsigned)
|
|||
fprintf(stderr, " : Value is %u, trying to set %u\n",
|
||||
oval, val);
|
||||
|
||||
debug_print(p);
|
||||
#if defined(WITH_DEBUG)
|
||||
debug_print(p);
|
||||
breakpoint();
|
||||
#else
|
||||
fprintf(stderr, " : I'm driving functor 0x%x\n", out);
|
||||
|
|
@ -1389,6 +1387,9 @@ vvp_ipoint_t debug_lookup_functor(const char*name)
|
|||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.122 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
* Revision 1.121 2002/03/08 05:41:45 steve
|
||||
* Debug code for write to constants.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.40 2002/01/03 04:19:02 steve Exp $"
|
||||
#ident "$Id: compile.h,v 1.41 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -118,6 +118,22 @@ extern void compile_shiftr(char*label, long width,
|
|||
extern void compile_vpi_symbol(const char*label, vpiHandle obj);
|
||||
extern void compile_vpi_lookup(vpiHandle *objref, char*label);
|
||||
|
||||
/*
|
||||
* This function schedules a lookup of an indexed label. The ref
|
||||
* points to the vvp_ipoint_t that receives the result. The result may
|
||||
* be assigned later, if the symbol is defined later in the source
|
||||
* file, so the memory that ref points to must persist.
|
||||
*/
|
||||
extern void functor_ref_lookup(vvp_ipoint_t *ref, char*lab, unsigned idx);
|
||||
|
||||
/*
|
||||
* This function schedules a lookup of the labeled instruction. The
|
||||
* code points to a code structure that points to the instruction
|
||||
* field that receives the result, and the label is the name to
|
||||
* lookup. The lookup will free the label text when it is done.
|
||||
*/
|
||||
extern void code_label_lookup(struct vvp_code_s *code, char *label);
|
||||
|
||||
/*
|
||||
* The `compile_udp_def' function creates a UDP. The `table' is a
|
||||
* NULL terminated array of char*, as assembled by `compile_udp_table'.
|
||||
|
|
@ -151,6 +167,13 @@ extern void compile_memory_port(char *label, char *memid,
|
|||
|
||||
extern void compile_memory_init(char *memid, unsigned idx, unsigned char val);
|
||||
|
||||
/*
|
||||
* Compile the .ufunc statement.
|
||||
*/
|
||||
extern void compile_ufunc(char*label, char*code, unsigned wid,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
unsigned portc, struct symb_s*portv,
|
||||
unsigned retc, struct symb_s*retv);
|
||||
|
||||
/*
|
||||
* The compile_event function takes the parts of the event statement
|
||||
|
|
@ -225,6 +248,9 @@ extern void compile_net(char*label, char*name,
|
|||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.41 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
* Revision 1.40 2002/01/03 04:19:02 steve
|
||||
* Add structural modulus support down to vvp.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.31 2002/03/01 05:42:50 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.32 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -87,6 +87,7 @@
|
|||
".shift/l" { return K_SHIFTL; }
|
||||
".shift/r" { return K_SHIFTR; }
|
||||
".thread" { return K_THREAD; }
|
||||
".ufunc" { return K_UFUNC; }
|
||||
".var" { return K_VAR; }
|
||||
".var/s" { return K_VAR_S; }
|
||||
".udp" { return K_UDP; }
|
||||
|
|
@ -158,6 +159,9 @@ int yywrap()
|
|||
|
||||
/*
|
||||
* $Log: lexor.lex,v $
|
||||
* Revision 1.32 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
* Revision 1.31 2002/03/01 05:42:50 steve
|
||||
* out-of-memory asserts.
|
||||
*
|
||||
|
|
|
|||
18
vvp/parse.y
18
vvp/parse.y
|
|
@ -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.43 2002/01/03 04:19:02 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.44 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -60,7 +60,7 @@ extern FILE*yyin;
|
|||
%token K_ARITH_DIV K_ARITH_MOD K_ARITH_MULT K_ARITH_SUB K_ARITH_SUM
|
||||
%token K_CMP_GE K_CMP_GT
|
||||
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S
|
||||
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD
|
||||
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_UFUNC
|
||||
%token K_UDP K_UDP_C K_UDP_S
|
||||
%token K_MEM K_MEM_P K_MEM_I
|
||||
%token K_FORCE
|
||||
|
|
@ -159,6 +159,17 @@ statement
|
|||
| mem_init_stmt
|
||||
|
||||
|
||||
/* The .ufunc functor is for implementing user defined functions, or
|
||||
other thread code that is automatically invoked if any of the
|
||||
bits in the symbols list change. */
|
||||
|
||||
| T_LABEL K_UFUNC T_SYMBOL ',' T_NUMBER ',' symbols
|
||||
'(' symbols ')' symbols ';'
|
||||
{ compile_ufunc($1, $3, $5,
|
||||
$7.cnt, $7.vect,
|
||||
$9.cnt, $9.vect,
|
||||
$11.cnt, $11.vect); }
|
||||
|
||||
/* Resolver statements are very much like functors. They are
|
||||
compiled to functors of a different mode. */
|
||||
|
||||
|
|
@ -538,6 +549,9 @@ int compile_design(const char*path)
|
|||
|
||||
/*
|
||||
* $Log: parse.y,v $
|
||||
* Revision 1.44 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
* Revision 1.43 2002/01/03 04:19:02 steve
|
||||
* Add structural modulus support down to vvp.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright (c) 2002 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: ufunc.cc,v 1.1 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
# include "symbols.h"
|
||||
# include "codes.h"
|
||||
# include "functor.h"
|
||||
# include "ufunc.h"
|
||||
# include "vthread.h"
|
||||
# include "schedule.h"
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
ufunc_core::ufunc_core(unsigned ow, vvp_ipoint_t ob, vvp_ipoint_t*op,
|
||||
unsigned np, vvp_ipoint_t*p,
|
||||
vvp_cpoint_t start_address,
|
||||
struct __vpiScope*run_scope)
|
||||
: owid_(ow), obase_(ob), oports_(op), nports_(np), ports_(p)
|
||||
{
|
||||
thread_ = 0;
|
||||
scope_ = run_scope;
|
||||
code_ = start_address;
|
||||
|
||||
ibits_ = new unsigned char[(nports_+3) / 4];
|
||||
memset(ibits_, 0xaa, (nports_+3) / 4);
|
||||
}
|
||||
|
||||
ufunc_core::~ufunc_core()
|
||||
{
|
||||
delete[] ports_;
|
||||
}
|
||||
|
||||
void ufunc_core::set_bit(unsigned port_idx, unsigned val)
|
||||
{
|
||||
unsigned idx = port_idx / 4;
|
||||
unsigned pp = port_idx % 4;
|
||||
|
||||
static const unsigned char mask[4] = {0xfc, 0xf3, 0xcf, 0x3f};
|
||||
|
||||
ibits_[idx] &= mask[pp];
|
||||
ibits_[idx] |= (val&3) << pp*2;
|
||||
|
||||
if (thread_ == 0) {
|
||||
thread_ = vthread_new(code_, scope_);
|
||||
schedule_vthread(thread_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char strong_values[4] = {St0, St1, StX, HiZ};
|
||||
|
||||
void ufunc_core::assign_bits_to_ports(void)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nports_ ; idx += 1) {
|
||||
unsigned bit_val = ibits_[idx/4] >> (idx%4)*2;
|
||||
bit_val &= 3;
|
||||
|
||||
functor_set(ports_[idx], bit_val, strong_values[bit_val], true);
|
||||
}
|
||||
}
|
||||
|
||||
void ufunc_core::finish_thread(vthread_t thr)
|
||||
{
|
||||
assert(thread_ == thr);
|
||||
thread_ = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < owid_ ; idx += 1) {
|
||||
unsigned val = functor_get(oports_[idx]);
|
||||
vvp_ipoint_t ptr = ipoint_index(obase_, idx);
|
||||
functor_set(ptr, val, strong_values[val], false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* There is an instance of ufunc_output_functor_s for each output bit
|
||||
* of the function. This is the functor that passes the output bits to
|
||||
* the rest of the design. The functor simply puts its input to its
|
||||
* output.
|
||||
*/
|
||||
struct ufunc_output_functor_s : public functor_s {
|
||||
void set(vvp_ipoint_t, bool push, unsigned val, unsigned str = 0);
|
||||
};
|
||||
|
||||
void ufunc_output_functor_s::set(vvp_ipoint_t, bool push, unsigned
|
||||
val, unsigned str)
|
||||
{
|
||||
put_oval(val, push);
|
||||
}
|
||||
|
||||
struct ufunc_input_functor_s : public functor_s {
|
||||
void set(vvp_ipoint_t, bool push, unsigned val, unsigned str = 0);
|
||||
|
||||
unsigned core_base_;
|
||||
ufunc_core*core_;
|
||||
};
|
||||
|
||||
void ufunc_input_functor_s::set(vvp_ipoint_t ptr, bool,
|
||||
unsigned val, unsigned str)
|
||||
{
|
||||
unsigned pp = ipoint_port(ptr);
|
||||
core_->set_bit(core_base_+pp, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function compiles the .ufunc statement that is discovered in
|
||||
* the source file. Create all the functors and the thread, and
|
||||
* connect them all up.
|
||||
*/
|
||||
void compile_ufunc(char*label, char*code, unsigned wid,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
unsigned portc, struct symb_s*portv,
|
||||
unsigned retc, struct symb_s*retv)
|
||||
{
|
||||
|
||||
/* Create an array of vvp_ipoint_t pointers, that point to the
|
||||
.var bits of the function ports. Do this for the input
|
||||
ports and the output port. */
|
||||
assert(argc == portc);
|
||||
vvp_ipoint_t* ports = new vvp_ipoint_t [portc];
|
||||
|
||||
for (unsigned idx = 0 ; idx < portc ; idx += 1) {
|
||||
functor_ref_lookup(ports+idx, portv[idx].text, portv[idx].idx);
|
||||
}
|
||||
|
||||
assert(retc == wid);
|
||||
vvp_ipoint_t* rets = new vvp_ipoint_t [retc];
|
||||
|
||||
for (unsigned idx = 0 ; idx < retc ; idx += 1) {
|
||||
functor_ref_lookup(rets+idx, retv[idx].text, retv[idx].idx);
|
||||
}
|
||||
|
||||
/* Create enough output functors for the output bits of the
|
||||
function. */
|
||||
vvp_ipoint_t obase = functor_allocate(wid);
|
||||
struct ufunc_output_functor_s*fpa
|
||||
= new struct ufunc_output_functor_s[wid];
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(obase,idx);
|
||||
functor_define(ptr, fpa+idx);
|
||||
}
|
||||
|
||||
define_functor_symbol(label, obase);
|
||||
|
||||
/* Construct some phantom code that is the thread of the
|
||||
function call. The first instruction, at the start_address
|
||||
of the function, loads the points and calls the function.
|
||||
The last instruction is the usual %end. */
|
||||
vvp_cpoint_t start_address = codespace_allocate();
|
||||
vvp_code_t start_code = codespace_index(start_address);
|
||||
start_code->opcode = of_CALL_UFUNC;
|
||||
code_label_lookup(start_code, code);
|
||||
|
||||
{ vvp_cpoint_t cur = codespace_allocate();
|
||||
vvp_code_t codep = codespace_index(cur);
|
||||
codep->opcode = &of_END;
|
||||
}
|
||||
|
||||
|
||||
/* Create the function core object that references the output
|
||||
functors and the function ports. The input functors will
|
||||
point to this core to deliver input. */
|
||||
ufunc_core*core = new ufunc_core(wid, obase, rets,
|
||||
portc, ports,
|
||||
start_address,
|
||||
vpip_peek_current_scope());
|
||||
start_code->ufunc_core_ptr = core;
|
||||
|
||||
/* create enough input functors to connect to all the input
|
||||
bits of the function. These are used to detect changes and
|
||||
trigger the function thread. */
|
||||
unsigned icnt = (argc + 3) / 4;
|
||||
vvp_ipoint_t ibase = functor_allocate(icnt);
|
||||
struct ufunc_input_functor_s*ifp
|
||||
= new struct ufunc_input_functor_s[icnt];
|
||||
|
||||
for (unsigned idx = 0 ; idx < icnt ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(ibase,idx);
|
||||
struct ufunc_input_functor_s*cur = ifp+idx;
|
||||
|
||||
cur->core_base_ = idx*4;
|
||||
cur->core_ = core;
|
||||
|
||||
functor_define(ptr, ifp+idx);
|
||||
}
|
||||
|
||||
inputs_connect(ibase, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: ufunc.cc,v $
|
||||
* Revision 1.1 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#ifndef __ufunc_H
|
||||
#define __ufunc_H
|
||||
/*
|
||||
* Copyright (c) 2002 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: ufunc.h,v 1.1 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "pointers.h"
|
||||
|
||||
/*
|
||||
* The .ufunc statement creates functors to represent user defined
|
||||
* functions. The function device itself is implemented as a thread
|
||||
* with a bunch of functors for the output bits. This thread has a set
|
||||
* of outputs, represented by output_functors and a set of inputs
|
||||
* connected to input functors. The input functors detect that a
|
||||
* change has occurred, and invoke the thread to process the new
|
||||
* values. The relationships work like this:
|
||||
*
|
||||
* ufunc_input_functor_s --+--> ufunc_core --+--> ufunc_output_functor_s
|
||||
* | |
|
||||
* ufunc_input_functor_s --+ +--> ufunc_output_functor_s
|
||||
* |
|
||||
* ufunc_input_functor_s --+
|
||||
*/
|
||||
|
||||
class ufunc_core {
|
||||
|
||||
public:
|
||||
ufunc_core(unsigned ow, vvp_ipoint_t ob, vvp_ipoint_t*op,
|
||||
unsigned np, vvp_ipoint_t*p,
|
||||
vvp_cpoint_t start_address,
|
||||
struct __vpiScope*run_scope);
|
||||
~ufunc_core();
|
||||
|
||||
void set_bit(unsigned port_idx, unsigned val);
|
||||
|
||||
void assign_bits_to_ports();
|
||||
void finish_thread(vthread_t thr);
|
||||
|
||||
struct __vpiScope*scope() { return scope_; }
|
||||
|
||||
private:
|
||||
// The owid_ and obase_ point to the functor vector that makes
|
||||
// up the output of the function.
|
||||
unsigned owid_;
|
||||
vvp_ipoint_t obase_;
|
||||
vvp_ipoint_t*oports_;
|
||||
// Keep an array of vvp_ipoint_t pointers that point to .var
|
||||
// functors. These are the input ports of the function.
|
||||
unsigned nports_;
|
||||
vvp_ipoint_t*ports_;
|
||||
// This is a thread to execute the behavioral portion of the
|
||||
// function.
|
||||
vthread_t thread_;
|
||||
struct __vpiScope*scope_;
|
||||
vvp_cpoint_t code_;
|
||||
|
||||
// Save the input bits as I receive them.
|
||||
unsigned char*ibits_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: ufunc.h,v $
|
||||
* Revision 1.1 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -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.66 2002/01/26 02:08:07 steve Exp $"
|
||||
#ident "$Id: vthread.cc,v 1.67 2002/03/18 00:19:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vthread.h"
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
# include "debug.h"
|
||||
# include "schedule.h"
|
||||
# include "functor.h"
|
||||
# include "ufunc.h"
|
||||
# include "event.h"
|
||||
# include "vpi_priv.h"
|
||||
#ifdef HAVE_MALLOC_H
|
||||
|
|
@ -1716,8 +1717,41 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a phantom opcode used to call user defined functions. It is
|
||||
* used in code generated by the .ufunc statement. This instruction
|
||||
* contains a pointer to executable code of the function, and to a
|
||||
* ufunc_core object that has all the port information about the
|
||||
* function.
|
||||
*/
|
||||
bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
/* Copy all the inputs to the ufunc object to the port
|
||||
variables of the function. This copies all the values
|
||||
atomically. */
|
||||
cp->ufunc_core_ptr->assign_bits_to_ports();
|
||||
|
||||
/* Create a temporary thread, and execute it manually. This is
|
||||
necessary so that the previous step (assign_bits_to_ports)
|
||||
and the execution of the function itself are an atomic
|
||||
unit. If it were not, then the inputs might change between
|
||||
setup and execution, causing really bad things to happen. */
|
||||
vthread_t child = vthread_new(cp->cptr, cp->ufunc_core_ptr->scope());
|
||||
vthread_mark_scheduled(child);
|
||||
vthread_run(child);
|
||||
|
||||
/* Now copy the output from the result variable to the output
|
||||
ports of the .ufunc device. */
|
||||
cp->ufunc_core_ptr->finish_thread(thr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vthread.cc,v $
|
||||
* Revision 1.67 2002/03/18 00:19:34 steve
|
||||
* Add the .ufunc statement.
|
||||
*
|
||||
* Revision 1.66 2002/01/26 02:08:07 steve
|
||||
* Handle x in l-value of set/x
|
||||
*
|
||||
|
|
@ -1825,63 +1859,5 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t)
|
|||
* Add strengths to functors at compile time,
|
||||
* and Make functors pass their strengths as they
|
||||
* propagate their output.
|
||||
*
|
||||
* Revision 1.36 2001/05/06 17:42:22 steve
|
||||
* Add the %ix/get instruction. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.35 2001/05/05 23:55:46 steve
|
||||
* Add the beginnings of an interactive debugger.
|
||||
*
|
||||
* Revision 1.34 2001/05/02 23:16:50 steve
|
||||
* Document memory related opcodes,
|
||||
* parser uses numbv_s structures instead of the
|
||||
* symbv_s and a mess of unions,
|
||||
* Add the %is/sub instruction.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.33 2001/05/02 01:57:26 steve
|
||||
* Support behavioral subtraction.
|
||||
*
|
||||
* Revision 1.32 2001/05/02 01:37:38 steve
|
||||
* initialize is_schedule.
|
||||
*
|
||||
* Revision 1.31 2001/05/01 05:00:02 steve
|
||||
* Implement %ix/load.
|
||||
*
|
||||
* Revision 1.30 2001/05/01 01:09:39 steve
|
||||
* Add support for memory objects. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.29 2001/04/21 00:34:39 steve
|
||||
* Working %disable and reap handling references from scheduler.
|
||||
*
|
||||
* Revision 1.28 2001/04/18 05:04:19 steve
|
||||
* %end complete the %join for the parent.
|
||||
*
|
||||
* Revision 1.27 2001/04/18 04:21:23 steve
|
||||
* Put threads into scopes.
|
||||
*
|
||||
* Revision 1.26 2001/04/15 16:37:48 steve
|
||||
* add XOR support.
|
||||
*
|
||||
* Revision 1.25 2001/04/15 04:07:56 steve
|
||||
* Add support for behavioral xnor.
|
||||
*
|
||||
* Revision 1.24 2001/04/14 05:10:05 steve
|
||||
* Initialize the waiting_for_event member.
|
||||
*
|
||||
* Revision 1.23 2001/04/13 03:55:18 steve
|
||||
* More complete reap of all threads.
|
||||
*
|
||||
* Revision 1.22 2001/04/05 01:12:28 steve
|
||||
* Get signed compares working correctly in vvp.
|
||||
*
|
||||
* Revision 1.21 2001/04/03 03:18:34 steve
|
||||
* support functor_set push for blocking assignment.
|
||||
*
|
||||
* Revision 1.20 2001/04/01 22:25:33 steve
|
||||
* Add the reduction nor instruction.
|
||||
*
|
||||
* Revision 1.19 2001/04/01 07:22:08 steve
|
||||
* Implement the less-then and %or instructions.
|
||||
*/
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue