Rewrite vvm VPI support to make objects more
persistent, rewrite the simulation scheduler in C (to interface with VPI) and add VPI support for callbacks.
This commit is contained in:
parent
8bad04a020
commit
d6450599d6
98
t-vvm.cc
98
t-vvm.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: t-vvm.cc,v 1.64 1999/10/23 16:27:53 steve Exp $"
|
||||
#ident "$Id: t-vvm.cc,v 1.65 1999/10/28 00:47:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
|
|
@ -40,6 +40,9 @@ static string make_temp()
|
|||
}
|
||||
|
||||
class target_vvm : public target_t {
|
||||
|
||||
friend class vvm_parm_rval;
|
||||
|
||||
public:
|
||||
target_vvm();
|
||||
|
||||
|
|
@ -105,6 +108,10 @@ class target_vvm : public target_t {
|
|||
// of things that may be scanned multiple times.
|
||||
map<string,bool>esignal_printed_flag;
|
||||
map<string,bool>pevent_printed_flag;
|
||||
|
||||
// String constants that are made into vpiHandles have th
|
||||
// handle name mapped by this.
|
||||
map<string,string>string_constants;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -454,8 +461,8 @@ static string emit_proc_rval(ostream&os, unsigned indent, const NetExpr*expr)
|
|||
class vvm_parm_rval : public expr_scan_t {
|
||||
|
||||
public:
|
||||
explicit vvm_parm_rval(ostream&os)
|
||||
: result(""), os_(os) { }
|
||||
explicit vvm_parm_rval(ostream&o, target_vvm*t)
|
||||
: result(""), os_(o), tgt_(t) { }
|
||||
|
||||
string result;
|
||||
|
||||
|
|
@ -466,54 +473,64 @@ class vvm_parm_rval : public expr_scan_t {
|
|||
|
||||
private:
|
||||
ostream&os_;
|
||||
target_vvm*tgt_;
|
||||
};
|
||||
|
||||
void vvm_parm_rval::expr_const(const NetEConst*expr)
|
||||
{
|
||||
if (expr->value().is_string()) {
|
||||
result = make_temp();
|
||||
os_ << " struct __vpiHandle " << result << ";" << endl;
|
||||
os_ << " vvm_make_vpi_parm(&" << result << ", \""
|
||||
<< expr->value().as_string() << "\");" << endl;
|
||||
result = "&" + result;
|
||||
|
||||
string& res = tgt_->string_constants[expr->value().as_string()];
|
||||
if (res != "") {
|
||||
result = "&" + res + ".base";
|
||||
return;
|
||||
}
|
||||
|
||||
res = make_temp();
|
||||
tgt_->delayed << "struct __vpiStringConst " << res
|
||||
<< ";" << endl;
|
||||
tgt_->init_code << " vpip_make_string_const(&" << res
|
||||
<< ", \"" << expr->value().as_string()
|
||||
<< "\");" << endl;
|
||||
tgt_->defn << " extern struct __vpiStringConst " << res
|
||||
<< ";" << endl;
|
||||
result = "&" + res + ".base";
|
||||
return;
|
||||
}
|
||||
|
||||
string tname = make_temp();
|
||||
os_ << " vvm_bitset_t<" <<
|
||||
tgt_->defn << " vvm_bitset_t<" <<
|
||||
expr->expr_width() << "> " << tname << ";" << endl;
|
||||
for (unsigned idx = 0 ; idx < expr->expr_width() ; idx += 1) {
|
||||
os_ << " " << tname << "[" << idx << "] = ";
|
||||
tgt_->defn << " " << tname << "[" << idx << "] = ";
|
||||
switch (expr->value().get(idx)) {
|
||||
case verinum::V0:
|
||||
os_ << "V0";
|
||||
tgt_->defn << "V0";
|
||||
break;
|
||||
case verinum::V1:
|
||||
os_ << "V1";
|
||||
tgt_->defn << "V1";
|
||||
break;
|
||||
case verinum::Vx:
|
||||
os_ << "Vx";
|
||||
tgt_->defn << "Vx";
|
||||
break;
|
||||
case verinum::Vz:
|
||||
os_ << "Vz";
|
||||
tgt_->defn << "Vz";
|
||||
break;
|
||||
}
|
||||
os_ << ";" << endl;
|
||||
tgt_->defn << ";" << endl;
|
||||
}
|
||||
|
||||
result = make_temp();
|
||||
os_ << " struct __vpiHandle " << result << ";" << endl;
|
||||
os_ << " vvm_make_vpi_parm(&" << result << ", &" << tname
|
||||
<< ");" << endl;
|
||||
tgt_->defn << " struct __vpiHandle " << result << ";" << endl;
|
||||
tgt_->defn << " vvm_make_vpi_parm(&" << result << ", &"
|
||||
<< tname << ");" << endl;
|
||||
result = "&" + result;
|
||||
}
|
||||
|
||||
void vvm_parm_rval::expr_ident(const NetEIdent*expr)
|
||||
{
|
||||
if (expr->name() == "$time") {
|
||||
os_ << " system_time.val.time.low "
|
||||
"= sim_->get_sim_time();" << endl;
|
||||
result = string("&system_time");
|
||||
result = string("vpip_sim_time()");
|
||||
} else {
|
||||
cerr << "Unhandled identifier: " << expr->name() << endl;
|
||||
}
|
||||
|
|
@ -521,13 +538,13 @@ void vvm_parm_rval::expr_ident(const NetEIdent*expr)
|
|||
|
||||
void vvm_parm_rval::expr_signal(const NetESignal*expr)
|
||||
{
|
||||
string res = string("&") + mangle(expr->name()) + "_vpi";
|
||||
string res = string("&") + mangle(expr->name()) + "_vpi.base";
|
||||
result = res;
|
||||
}
|
||||
|
||||
static string emit_parm_rval(ostream&os, const NetExpr*expr)
|
||||
static string emit_parm_rval(ostream&os, target_vvm*tgt, const NetExpr*expr)
|
||||
{
|
||||
vvm_parm_rval scan (os);
|
||||
vvm_parm_rval scan (os, tgt);
|
||||
expr->expr_scan(&scan);
|
||||
return scan.result;
|
||||
}
|
||||
|
|
@ -554,12 +571,11 @@ void target_vvm::start_design(ostream&os, const Design*mod)
|
|||
os << "# include \"vpi_user.h\"" << endl;
|
||||
os << "# include \"vpi_priv.h\"" << endl;
|
||||
|
||||
os << "static struct __vpiHandle system_time;" << endl;
|
||||
process_counter = 0;
|
||||
|
||||
init_code << "static void design_init(vvm_simulation&sim)" << endl;
|
||||
init_code << "{" << endl;
|
||||
init_code << " vvm_init_vpi_timevar(&system_time, \"$time\");"
|
||||
init_code << " vpip_init_simulation();"
|
||||
<< endl;
|
||||
start_code << "static void design_start(vvm_simulation&sim)" << endl;
|
||||
start_code << "{" << endl;
|
||||
|
|
@ -1074,13 +1090,16 @@ void target_vvm::net_esignal(ostream&os, const NetESignal*net)
|
|||
mangle(net->name()) << "(\"" << net->name() << "\", &" <<
|
||||
mangle(net->name()) << "_bits);" << endl;
|
||||
|
||||
os << "static struct __vpiHandle " << mangle(net->name()) <<
|
||||
os << "static struct __vpiSignal " << mangle(net->name()) <<
|
||||
"_vpi;" << endl;
|
||||
|
||||
init_code << " vvm_init_vpi_handle(&" <<
|
||||
mangle(net->name()) << "_vpi, &" << mangle(net->name()) <<
|
||||
"_bits, &" << mangle(net->name()) << ");" << endl;
|
||||
|
||||
string vpi_name = mangle(net->name()) + "_vpi";
|
||||
init_code << " vpip_make_reg(&" << vpi_name << ", \"" <<
|
||||
net->name() << "\");" << endl;
|
||||
init_code << " " << vpi_name << ".bits = " <<
|
||||
mangle(net->name()) << "_bits.bits;" << endl;
|
||||
init_code << " " << vpi_name << ".nbits = " <<
|
||||
net->pin_count() << ";" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1551,22 +1570,19 @@ void target_vvm::proc_stask(ostream&os, const NetSTask*net)
|
|||
for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1) {
|
||||
string val;
|
||||
if (net->parm(idx)) {
|
||||
val = emit_parm_rval(defn, net->parm(idx));
|
||||
val = emit_parm_rval(os, this, net->parm(idx));
|
||||
|
||||
} else {
|
||||
val = make_temp();
|
||||
defn << " struct __vpiHandle " << val << ";" << endl;
|
||||
defn << " vvm_make_vpi_parm(&" << val << ");" << endl;
|
||||
val = string("&") + val;
|
||||
val = string("&vpip_null.base");
|
||||
}
|
||||
|
||||
defn << " " << ptmp << "[" << idx << "] = " << val << ";"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
defn << " vvm_calltask(sim_, \"" << net->name() << "\", " <<
|
||||
defn << " vpip_calltask(\"" << net->name() << "\", " <<
|
||||
net->nparms() << ", " << ptmp << ");" << endl;
|
||||
defn << " if (sim_->finished()) return false;" << endl;
|
||||
defn << " if (vpip_finished()) return false;" << endl;
|
||||
}
|
||||
|
||||
void target_vvm::proc_utask(ostream&os, const NetUTask*net)
|
||||
|
|
@ -1746,6 +1762,12 @@ extern const struct target tgt_vvm = {
|
|||
};
|
||||
/*
|
||||
* $Log: t-vvm.cc,v $
|
||||
* Revision 1.65 1999/10/28 00:47:24 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.64 1999/10/23 16:27:53 steve
|
||||
* assignment to bit select is aa single bit.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: sys_display.c,v 1.4 1999/10/10 14:50:50 steve Exp $"
|
||||
#ident "$Id: sys_display.c,v 1.5 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
|
@ -236,6 +236,30 @@ static int sys_display_calltf(char *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int strobe_cb(p_cb_data cb)
|
||||
{
|
||||
vpi_printf("%s NOT IMPLEMENTED YET\n", cb->user_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_strobe_calltf(char*name)
|
||||
{
|
||||
struct t_cb_data cb;
|
||||
struct t_vpi_time time;
|
||||
|
||||
time.type = vpiSimTime;
|
||||
time.low = 0;
|
||||
time.high = 0;
|
||||
|
||||
cb.reason = cbReadOnlySynch;
|
||||
cb.cb_rtn = strobe_cb;
|
||||
cb.time = &time;
|
||||
cb.obj = 0;
|
||||
cb.user_data = name;
|
||||
vpi_register_cb(&cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_display_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
|
@ -255,11 +279,25 @@ void sys_display_register()
|
|||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$write";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$strobe";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$strobe";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: sys_display.c,v $
|
||||
* Revision 1.5 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.4 1999/10/10 14:50:50 steve
|
||||
* Add Octal dump format.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_user.h,v 1.3 1999/08/19 02:51:03 steve Exp $"
|
||||
#ident "$Id: vpi_user.h,v 1.4 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -95,6 +95,7 @@ typedef struct t_vpi_value {
|
|||
|
||||
/* OBJECT CODES */
|
||||
#define vpiConstant 7
|
||||
#define vpiIterator 27
|
||||
#define vpiNet 36
|
||||
#define vpiReg 48
|
||||
#define vpiSysTaskCall 57
|
||||
|
|
@ -102,6 +103,7 @@ typedef struct t_vpi_value {
|
|||
#define vpiSysTfCall 85
|
||||
#define vpiArgument 89
|
||||
|
||||
#define vpiCallback 1000
|
||||
|
||||
/* PROPERTIES */
|
||||
#define vpiType 1
|
||||
|
|
@ -120,6 +122,46 @@ typedef struct t_vpi_value {
|
|||
extern void vpi_register_systf(const struct t_vpi_systf_data*ss);
|
||||
extern void vpi_printf(const char*fmt, ...);
|
||||
|
||||
/*
|
||||
* support for VPI callback functions.
|
||||
*/
|
||||
typedef struct t_cb_data {
|
||||
int reason;
|
||||
int (*cb_rtn)(struct t_cb_data*cb);
|
||||
vpiHandle obj;
|
||||
p_vpi_time time;
|
||||
p_vpi_value value;
|
||||
int index;
|
||||
char*user_data;
|
||||
} s_cb_data, *p_cb_data;
|
||||
|
||||
#define cbValueChange 1
|
||||
#define cbStmt 2
|
||||
#define cbForce 3
|
||||
#define cbRelease 4
|
||||
#define cbAtStartOfSimTime 5
|
||||
#define cbReadWriteSynch 6
|
||||
#define cbReadOnlySynch 7
|
||||
#define cbNextSimTime 8
|
||||
#define cbAfterDelay 9
|
||||
#define cbEndOfCompile 10
|
||||
#define cbStartOfSimulation 11
|
||||
#define cbEndOfSimulation 12
|
||||
#define cbError 13
|
||||
#define cbTchkViolation 14
|
||||
#define cbStartOfSave 15
|
||||
#define cbEndOfSave 16
|
||||
#define cbStartOfRestart 17
|
||||
#define cbEndOfRestart 18
|
||||
#define cbStartOfReset 19
|
||||
#define cbEndOfReset 20
|
||||
#define cbEnterInteractive 21
|
||||
#define cbExitInteractive 22
|
||||
#define cbInteractiveScopeChange 23
|
||||
#define cbUnresolvedSystf 24
|
||||
|
||||
extern vpiHandle vpi_register_cb(p_cb_data data);
|
||||
|
||||
/*
|
||||
* This function allows a vpi application to control the simulation
|
||||
* engine. The operation parameter specifies the function to
|
||||
|
|
@ -161,6 +203,12 @@ extern void (*vlog_startup_routines[])();
|
|||
|
||||
/*
|
||||
* $Log: vpi_user.h,v $
|
||||
* Revision 1.4 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.3 1999/08/19 02:51:03 steve
|
||||
* Add vpi_sim_control
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.8 1999/10/22 23:58:13 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.9 1999/10/28 00:47:25 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -35,7 +35,7 @@ bindir = $(exec_prefix)/bin
|
|||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
CC = @CC@ -I$(srcdir) -I$(srcdir)/../vpi
|
||||
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/../vpi
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
|
|
@ -43,6 +43,7 @@ INSTALL_DATA = @INSTALL_DATA@
|
|||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: libvvm.a
|
||||
|
|
@ -52,13 +53,25 @@ all: libvvm.a
|
|||
$(CXX) -Wall -fno-exceptions $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
%.o dep/%.d: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall -fno-exceptions $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_monitor.o vvm_pevent.o \
|
||||
vvm_simulation.o vvm_thread.o
|
||||
vvm_simulation.o vvm_thread.o vpip.o
|
||||
|
||||
P = vpi_callback.o \
|
||||
vpi_const.o vpi_iter.o vpi_null.o \
|
||||
vpi_priv.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o
|
||||
|
||||
libvvm.a: $O
|
||||
rm -f $@
|
||||
ar cvq $@ $O
|
||||
|
||||
vpip.o: $P
|
||||
$(LD) -r -o vpip.o $P
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_callback.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
static struct __vpirt vpip_callback_rt = {
|
||||
vpiCallback,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
static void vpip_call_callback(void*cp)
|
||||
{
|
||||
struct __vpiCallback*rfp = (struct __vpiCallback*)cp;
|
||||
assert(rfp->base.vpi_type->type_code == vpiCallback);
|
||||
rfp->cb_data.cb_rtn(&rfp->cb_data);
|
||||
free(rfp);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXX This currently does not support (or pay any attention to) the
|
||||
* delay parameter. Yikes!
|
||||
*/
|
||||
vpiHandle vpi_register_cb(p_cb_data data)
|
||||
{
|
||||
struct __vpiCallback*rfp = calloc(1, sizeof(struct __vpiCallback));
|
||||
rfp->base.vpi_type = &vpip_callback_rt;
|
||||
rfp->cb_data = *data;
|
||||
|
||||
switch (data->reason) {
|
||||
case cbReadOnlySynch:
|
||||
assert(data->time);
|
||||
assert(data->time->type == vpiSimTime);
|
||||
assert(data->time->low == 0);
|
||||
assert(data->time->high == 0);
|
||||
rfp->ev = vpip_sim_insert_event(0, rfp, vpip_call_callback, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return &(rfp->base);
|
||||
}
|
||||
|
||||
|
||||
int vpi_remove_cb(vpiHandle ref)
|
||||
{
|
||||
struct __vpiCallback*rfp = (struct __vpiCallback*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiCallback);
|
||||
vpip_sim_cancel_event(rfp->ev);
|
||||
free(rfp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_callback.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_const.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
static void string_value(vpiHandle ref, p_vpi_value vp)
|
||||
{
|
||||
struct __vpiStringConst*rfp = (struct __vpiStringConst*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiConstant);
|
||||
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
case vpiStringVal:
|
||||
vp->value.str = rfp->value;
|
||||
vp->format = vpiStringVal;
|
||||
break;
|
||||
|
||||
default:
|
||||
vp->format = vpiSuppressVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_string_rt = {
|
||||
vpiConstant,
|
||||
0,
|
||||
0,
|
||||
string_value,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_string_const(struct __vpiStringConst*ref, const char*val)
|
||||
{
|
||||
ref->base.vpi_type = &vpip_string_rt;
|
||||
ref->value = val;
|
||||
return &(ref->base);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_const.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_iter.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find here the methods functions in support of iterator objects.
|
||||
*/
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
static const struct __vpirt vpip_iterator_rt = {
|
||||
vpiIterator,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args)
|
||||
{
|
||||
struct __vpiIterator*res = calloc(1, sizeof(struct __vpiIterator));
|
||||
res->base.vpi_type = &vpip_iterator_rt;
|
||||
res->args = args;
|
||||
res->nargs = nargs;
|
||||
res->next = 0;
|
||||
|
||||
return &(res->base);
|
||||
}
|
||||
|
||||
/*
|
||||
* The vpi_scan function only applies to iterators. It returns the
|
||||
* next vpiHandle in the iterated list.
|
||||
*/
|
||||
vpiHandle vpi_scan(vpiHandle ref)
|
||||
{
|
||||
struct __vpiIterator*hp = (struct __vpiIterator*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiIterator);
|
||||
|
||||
if (hp->next == hp->nargs) {
|
||||
vpi_free_object(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hp->args[hp->next++];
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_iter.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_null.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
|
||||
static const struct __vpirt vpip_null_rt = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
struct __vpiNull vpip_null = {
|
||||
{ &vpip_null_rt }
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: vpi_null.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_priv.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
# include <stdarg.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
/*
|
||||
* Keep a list of vpi_systf_data structures. This list is searched
|
||||
* forward whenever a function is invoked by name, and items are
|
||||
* pushed in front of the list whenever they are registered. This
|
||||
* allows entries to override older entries.
|
||||
*/
|
||||
struct systf_entry {
|
||||
struct systf_entry* next;
|
||||
s_vpi_systf_data systf_data;
|
||||
};
|
||||
|
||||
static struct systf_entry*systf_list = 0;
|
||||
|
||||
/* This is the handle of the task currently being called. */
|
||||
static struct __vpiSysTaskCall*vpip_cur_task;
|
||||
|
||||
|
||||
void vpip_calltask(const char*fname, unsigned nparms, vpiHandle*parms)
|
||||
{
|
||||
struct systf_entry*idx;
|
||||
struct __vpiSysTaskCall cur_task;
|
||||
cur_task.base.vpi_type = &vpip_systask_rt;
|
||||
cur_task.args = parms;
|
||||
cur_task.nargs = nparms;
|
||||
|
||||
vpip_cur_task = &cur_task;
|
||||
|
||||
/* Look for a systf function to invoke. */
|
||||
for (idx = systf_list ; idx ; idx = idx->next)
|
||||
if (strcmp(fname, idx->systf_data.tfname) == 0) {
|
||||
cur_task.info = &idx->systf_data;
|
||||
idx->systf_data.calltf(idx->systf_data.user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Finally, if nothing is found then something is not
|
||||
right. Print out the function name all the parameters
|
||||
passed, so that someone can deal with it. */
|
||||
vpi_printf("Call %s\n", fname);
|
||||
}
|
||||
|
||||
|
||||
int vpi_free_object(vpiHandle ref)
|
||||
{
|
||||
free(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vpi_get(int property, vpiHandle ref)
|
||||
{
|
||||
if (property == vpiType)
|
||||
return ref->vpi_type->type_code;
|
||||
|
||||
if (ref->vpi_type->vpi_get_ == 0)
|
||||
return -1;
|
||||
|
||||
return (ref->vpi_type->vpi_get_)(property, ref);
|
||||
}
|
||||
|
||||
char* vpi_get_str(int property, vpiHandle ref)
|
||||
{
|
||||
if (ref->vpi_type->vpi_get_str_ == 0)
|
||||
return 0;
|
||||
|
||||
return (ref->vpi_type->vpi_get_str_)(property, ref);
|
||||
}
|
||||
|
||||
void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
|
||||
{
|
||||
if (expr->vpi_type->vpi_get_value_) {
|
||||
(expr->vpi_type->vpi_get_value_)(expr, vp);
|
||||
return;
|
||||
}
|
||||
|
||||
vp->format = vpiSuppressVal;
|
||||
}
|
||||
|
||||
vpiHandle vpi_handle(int type, vpiHandle ref)
|
||||
{
|
||||
if (type == vpiSysTfCall) {
|
||||
assert(ref == 0);
|
||||
return &vpip_cur_task->base;
|
||||
}
|
||||
|
||||
assert(ref->vpi_type->handle_);
|
||||
return (ref->vpi_type->handle_)(type, ref);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function asks the object to return an iterator for
|
||||
* the specified reference. It is up to the iterate_ method to
|
||||
* allocate a properly formed iterator.
|
||||
*/
|
||||
vpiHandle vpi_iterate(int type, vpiHandle ref)
|
||||
{
|
||||
assert(ref->vpi_type->iterate_);
|
||||
return (ref->vpi_type->iterate_)(type, ref);
|
||||
}
|
||||
|
||||
void vpi_printf(const char*fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function adds the information that the user supplies to a list
|
||||
* that I keep.
|
||||
*/
|
||||
void vpi_register_systf(const struct t_vpi_systf_data*systf)
|
||||
{
|
||||
struct systf_entry*cur = calloc(1, sizeof(struct systf_entry));
|
||||
cur->systf_data = *systf;
|
||||
cur->systf_data.tfname = strdup(systf->tfname);
|
||||
cur->next = systf_list;
|
||||
systf_list = cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
226
vvm/vpi_priv.h
226
vvm/vpi_priv.h
|
|
@ -19,70 +19,200 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_priv.h,v 1.1 1999/08/15 01:23:56 steve Exp $"
|
||||
#ident "$Id: vpi_priv.h,v 1.2 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This header file describes the "back side" of the VPI
|
||||
* interface. The product that offers the VPI interface uses types and
|
||||
* methods declared here to manage the VPI structures and provide the
|
||||
* needed behaviors.
|
||||
*/
|
||||
# include <vpi_user.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct __vpirt;
|
||||
enum vpip_bit_t { V0 = 0, V1, Vx, Vz };
|
||||
|
||||
/*
|
||||
* This is the most basic type in the vpi implementation. A handle can
|
||||
* exist to refer to most any of the supported vpi objects. The
|
||||
* interpretation of the parts depends in general on the type of the
|
||||
* object.
|
||||
* This structure is the very base of a vpiHandle. Every handle
|
||||
* structure starts with this structure, so that the library can
|
||||
* internally pass the derived types as pointers to one of these.
|
||||
*/
|
||||
struct __vpiHandle {
|
||||
int type;
|
||||
int subtype;
|
||||
const struct __vpirt *vpi_type;
|
||||
};
|
||||
|
||||
/* These are property values. */
|
||||
char*full_name;
|
||||
/*
|
||||
* Objects with this structure are used to represent a type of
|
||||
* vpiHandle. A specific object becomes of this type by holding a
|
||||
* pointer to an instance of this structure.
|
||||
*/
|
||||
struct __vpirt {
|
||||
int type_code;
|
||||
|
||||
/* This pointer is used for to-one references. */
|
||||
struct __vpiHandle*referent;
|
||||
/* These methods extract information from the handle. */
|
||||
int (*vpi_get_)(int, vpiHandle);
|
||||
char* (*vpi_get_str_)(int, vpiHandle);
|
||||
void (*vpi_get_value_)(vpiHandle, p_vpi_value);
|
||||
|
||||
/* This pointer table is used for to-many refrences to
|
||||
arguments, and is used by the vpiArgument iterator. */
|
||||
struct __vpiHandle**arguments;
|
||||
unsigned narguments;
|
||||
/* These methods follow references. */
|
||||
vpiHandle (*handle_)(int, vpiHandle);
|
||||
vpiHandle (*iterate_)(int, vpiHandle);
|
||||
};
|
||||
|
||||
/* These methods support the various vpi_get() functions. */
|
||||
int (*get_)(int property, vpiHandle ref);
|
||||
char* (*get_str_)(int property, vpiHandle ref);
|
||||
/*
|
||||
* This is a private handle type that doesn't seem to be well defined
|
||||
* by the VPI standard.
|
||||
*/
|
||||
struct __vpiCallback {
|
||||
struct __vpiHandle base;
|
||||
struct t_cb_data cb_data;
|
||||
struct vpip_event*ev;
|
||||
};
|
||||
|
||||
/* This method is used to get a value. */
|
||||
void (*get_value_)(struct __vpiHandle*expr, s_vpi_value*vp);
|
||||
/*
|
||||
* This type is occasionally useful. Really! And while we're at it,
|
||||
* create a single instance of the null object. (This is all we need.)
|
||||
*/
|
||||
struct __vpiNull {
|
||||
struct __vpiHandle base;
|
||||
};
|
||||
extern struct __vpiNull vpip_null;
|
||||
|
||||
/* This is a value union, that reflect state or the value of a
|
||||
handle. */
|
||||
union {
|
||||
unsigned unum;
|
||||
struct vvm_bits_t*bits;
|
||||
struct t_vpi_time time;
|
||||
} val;
|
||||
/*
|
||||
* The vpiHandle for an iterator has this structure. The definition of
|
||||
* the methods lives in vpi_iter.c
|
||||
*/
|
||||
struct __vpiIterator {
|
||||
struct __vpiHandle base;
|
||||
|
||||
vpiHandle *args;
|
||||
unsigned nargs;
|
||||
unsigned next;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure represents nets and registers. You can tell which by
|
||||
* the type_code in the base. The bits member points to the actual
|
||||
* array of bits that the environment provides. The bits must persist
|
||||
* as long as this object persists.
|
||||
*/
|
||||
struct __vpiSignal {
|
||||
struct __vpiHandle base;
|
||||
|
||||
const char*name;
|
||||
enum vpip_bit_t*bits;
|
||||
unsigned nbits;
|
||||
};
|
||||
|
||||
|
||||
/* TYPE MEANINGS:
|
||||
*
|
||||
* vpiArgument
|
||||
* This type of handle contains a single referent, the item that has
|
||||
* many arguments. It is an iterator.
|
||||
*
|
||||
* vpiConstant
|
||||
* Constant values, such as strings and numbers, are this type.
|
||||
*
|
||||
* vpiSysTaskCall
|
||||
* This handle type represents a call to a system task. It has a
|
||||
* to-many reference to argument expressions, and a to-one reference
|
||||
* to a vpiUserSystf object.
|
||||
*
|
||||
* vpiTimeVar
|
||||
* This type is a special kind of variable, that holds a time. The
|
||||
* time value is a more complex structure then a single number. The
|
||||
* type really seems to exist to implement the $time system variable.
|
||||
extern const struct __vpirt vpip_systask_rt;
|
||||
struct __vpiSysTaskCall {
|
||||
struct __vpiHandle base;
|
||||
|
||||
s_vpi_systf_data*info;
|
||||
vpiHandle*args;
|
||||
unsigned nargs;
|
||||
|
||||
const char*file;
|
||||
unsigned lineno;
|
||||
int subtype;
|
||||
};
|
||||
|
||||
/*
|
||||
* Represent a TimeVar variable. The actual time is stored in the
|
||||
* "time" member for fast manipulation by various bits of the
|
||||
* simulation engine. The time_obj member is used as persistent
|
||||
* storage of the time value when get_value is used (on the opaque
|
||||
* handle) to the get time.
|
||||
*/
|
||||
struct __vpiTimeVar {
|
||||
struct __vpiHandle base;
|
||||
|
||||
const char*name;
|
||||
unsigned long time;
|
||||
struct t_vpi_time time_obj;
|
||||
};
|
||||
|
||||
|
||||
struct __vpiStringConst {
|
||||
struct __vpiHandle base;
|
||||
|
||||
const char*value;
|
||||
};
|
||||
|
||||
/*
|
||||
* These are methods to initialize specific handle types. Except for
|
||||
* vpip_make_iterator, all the vpi_make_* functions expect the caller
|
||||
* to allocate the memory for the handle. The result is the vpiHandle
|
||||
* of the constructed object.
|
||||
*/
|
||||
extern vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args);
|
||||
extern vpiHandle vpip_make_net(struct __vpiSignal*ref, const char*name);
|
||||
extern vpiHandle vpip_make_string_const(struct __vpiStringConst*ref,
|
||||
const char*val);
|
||||
extern vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name);
|
||||
extern vpiHandle vpip_make_time_var(struct __vpiTimeVar*ref,
|
||||
const char*val);
|
||||
|
||||
/* Use this function to call a registered task. */
|
||||
extern void vpip_calltask(const char*name, unsigned nparms, vpiHandle*parms);
|
||||
|
||||
|
||||
/*
|
||||
* The simulation object holds the current state of the
|
||||
* simulation. There is a single global variable that is the
|
||||
* simulation.
|
||||
*/
|
||||
|
||||
struct vpip_simulation_cycle;
|
||||
struct vpip_event;
|
||||
struct vpip_simulation {
|
||||
/* Current simulation time. */
|
||||
struct __vpiTimeVar sim_time;
|
||||
|
||||
/* List of cbReadOnlySynch callbacks. */
|
||||
struct __vpiCallback*read_sync_list;
|
||||
|
||||
/* List of simulation cycles, starting with the next time. */
|
||||
struct vpip_simulation_cycle*sim;
|
||||
int going_flag;
|
||||
};
|
||||
|
||||
extern struct vpip_simulation vpip_simulation_obj;
|
||||
|
||||
extern void vpip_init_simulation();
|
||||
extern void vpip_simulation_run();
|
||||
|
||||
/*
|
||||
* Schedule an event to be run sometime in the future. The d parmater
|
||||
* is the delay in simulation units before the event is processed. If
|
||||
* the non-block flag is set, the event is scheduled to happen at the
|
||||
* end of the time step.
|
||||
*
|
||||
* The return value from the insert method is a cookie that can be
|
||||
* used to manipulate the event before it is executed.
|
||||
*/
|
||||
extern struct vpip_event* vpip_sim_insert_event(unsigned long d,
|
||||
void*user_data,
|
||||
void (*sim_fun)(void*),
|
||||
int nonblock_flag);
|
||||
extern void vpip_sim_cancel_event(struct vpip_event*cookie);
|
||||
|
||||
/*
|
||||
* This function returns a handle to the vpiTimeVar that is th main
|
||||
* simulation time clock.
|
||||
*/
|
||||
extern vpiHandle vpip_sim_time();
|
||||
|
||||
/*
|
||||
* Return true if the going_flag is false.
|
||||
*/
|
||||
extern int vpip_finished();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
@ -90,6 +220,12 @@ struct __vpiHandle {
|
|||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.2 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.1 1999/08/15 01:23:56 steve
|
||||
* Convert vvm to implement system tasks with vpi.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_signal.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
|
||||
|
||||
static char* signal_get_str(int code, vpiHandle ref)
|
||||
{
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||
|
||||
switch (code) {
|
||||
|
||||
case vpiFullName:
|
||||
return (char*)rfp->name;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is a get_value_ method of a vpiHandle, that supports
|
||||
* reading bits as a string.
|
||||
*/
|
||||
static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||
{
|
||||
static char buff[1024];
|
||||
char*cp;
|
||||
unsigned width;
|
||||
unsigned val;
|
||||
unsigned idx;
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||
|
||||
assert(rfp->bits);
|
||||
width = rfp->nbits;
|
||||
cp = buff;
|
||||
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
case vpiBinStrVal:
|
||||
for (idx = 0 ; idx < width ; idx += 1)
|
||||
switch (rfp->bits[width-idx-1]) {
|
||||
case V0:
|
||||
*cp++ = '0';
|
||||
break;
|
||||
case V1:
|
||||
*cp++ = '1';
|
||||
break;
|
||||
case Vx:
|
||||
*cp++ = 'x';
|
||||
break;
|
||||
case Vz:
|
||||
*cp++ = 'z';
|
||||
break;
|
||||
}
|
||||
vp->format = vpiBinStrVal;
|
||||
break;
|
||||
|
||||
case vpiDecStrVal:
|
||||
val = 0;
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
val *= 2;
|
||||
switch (rfp->bits[width-idx-1]) {
|
||||
case V0:
|
||||
case Vx:
|
||||
case Vz:
|
||||
break;
|
||||
case V1:
|
||||
val += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sprintf(cp, "%u", val);
|
||||
cp += strlen(cp);
|
||||
break;
|
||||
|
||||
case vpiOctStrVal:
|
||||
if (width%3) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
unsigned i;
|
||||
for (i = 0 ; i < width%3 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (rfp->bits[width-i-1]) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == width%3)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == width%3)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "01234567"[v];
|
||||
}
|
||||
|
||||
for (idx = width%3 ; idx < width ; idx += 3) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
unsigned i;
|
||||
for (i = idx ; i < idx+3 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (rfp->bits[width-i-1]) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == 3)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == 3)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "01234567"[v];
|
||||
}
|
||||
break;
|
||||
|
||||
case vpiHexStrVal:
|
||||
if (width%4) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
unsigned i;
|
||||
for (i = 0 ; i < width%4 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (rfp->bits[width-i-1]) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == width%4)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == width%4)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "0123456789abcdef"[v];
|
||||
}
|
||||
|
||||
for (idx = width%4 ; idx < width ; idx += 4) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
unsigned i;
|
||||
for (i = idx ; i < idx+4 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (rfp->bits[width-i-1]) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == 4)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == 4)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "0123456789abcdef"[v];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*cp++ = '(';
|
||||
*cp++ = '?';
|
||||
*cp++ = ')';
|
||||
break;
|
||||
}
|
||||
|
||||
*cp++ = 0;
|
||||
vp->value.str = buff;
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_net_rt = {
|
||||
vpiNet,
|
||||
0,
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_net(struct __vpiSignal*ref, const char*name)
|
||||
{
|
||||
ref->base.vpi_type = &vpip_net_rt;
|
||||
ref->name = name;
|
||||
return &(ref->base);
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_reg_rt = {
|
||||
vpiReg,
|
||||
0,
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name)
|
||||
{
|
||||
ref->base.vpi_type = &vpip_reg_rt;
|
||||
ref->name = name;
|
||||
return &(ref->base);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_signal.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_simulation.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
struct vpip_event {
|
||||
void*user_data;
|
||||
void (*sim_fun)(void*);
|
||||
struct vpip_event*next;
|
||||
};
|
||||
|
||||
struct vpip_simulation vpip_simulation_obj;
|
||||
|
||||
void vpi_sim_control(int func, ...)
|
||||
{
|
||||
switch (func) {
|
||||
case vpiFinish:
|
||||
vpip_simulation_obj.going_flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The simulation event queue is a list of simulation cycles that in
|
||||
* turn contain lists of simulation events. The simulation cycle
|
||||
* represents the happening at some simulation time.
|
||||
*/
|
||||
struct vpip_simulation_cycle {
|
||||
unsigned long delay;
|
||||
|
||||
struct vpip_simulation_cycle*next;
|
||||
struct vpip_simulation_cycle*prev;
|
||||
|
||||
struct vpip_event*event_list;
|
||||
struct vpip_event*event_last;
|
||||
struct vpip_event*nonblock_list;
|
||||
struct vpip_event*nonblock_last;
|
||||
};
|
||||
|
||||
void vpip_init_simulation()
|
||||
{
|
||||
struct vpip_simulation_cycle*cur;
|
||||
|
||||
vpip_make_time_var(&vpip_simulation_obj.sim_time, "$time");
|
||||
vpip_simulation_obj.read_sync_list = 0;
|
||||
|
||||
/* Allocate a header cell for the simulation event list. */
|
||||
cur = calloc(1, sizeof(struct vpip_simulation_cycle));
|
||||
cur->delay = 0;
|
||||
cur->next = cur->prev = cur;
|
||||
vpip_simulation_obj.sim = cur;
|
||||
}
|
||||
|
||||
vpiHandle vpip_sim_time()
|
||||
{
|
||||
return &vpip_simulation_obj.sim_time.base;
|
||||
}
|
||||
|
||||
struct vpip_event* vpip_sim_insert_event(unsigned long delay,
|
||||
void*user_data,
|
||||
void (*sim_fun)(void*),
|
||||
int nonblock_flag)
|
||||
{
|
||||
struct vpip_event*event;
|
||||
struct vpip_simulation_cycle*cur;
|
||||
|
||||
event = calloc(1, sizeof(struct vpip_event));
|
||||
event->user_data = user_data;
|
||||
event->sim_fun = sim_fun;
|
||||
|
||||
cur = vpip_simulation_obj.sim->next;
|
||||
while ((cur != vpip_simulation_obj.sim) && (cur->delay < delay)) {
|
||||
delay -= cur->delay;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
/* If there is no cycle cell for the specified time, create one. */
|
||||
if ((cur == vpip_simulation_obj.sim) || (cur->delay > delay)) {
|
||||
struct vpip_simulation_cycle*cell
|
||||
= calloc(1,sizeof(struct vpip_simulation_cycle));
|
||||
cell->delay = delay;
|
||||
if (cur != vpip_simulation_obj.sim)
|
||||
cur->delay -= delay;
|
||||
cell->next = cur;
|
||||
cell->prev = cur->prev;
|
||||
cell->next->prev = cell;
|
||||
cell->prev->next = cell;
|
||||
cur = cell;
|
||||
}
|
||||
|
||||
/* Put the event into the end of the cycle list. */
|
||||
event->next = 0;
|
||||
if (nonblock_flag) {
|
||||
if (cur->nonblock_list == 0) {
|
||||
cur->nonblock_list = cur->nonblock_last = event;
|
||||
|
||||
} else {
|
||||
cur->nonblock_last->next = event;
|
||||
cur->nonblock_last = event;
|
||||
}
|
||||
} else {
|
||||
if (cur->event_list == 0) {
|
||||
cur->event_list = cur->event_last = event;
|
||||
|
||||
} else {
|
||||
cur->event_last->next = event;
|
||||
cur->event_last = event;
|
||||
}
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
void vpip_sim_cancel_event(struct vpip_event*ev)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int vpip_finished()
|
||||
{
|
||||
return ! vpip_simulation_obj.going_flag;
|
||||
}
|
||||
|
||||
void vpip_simulation_run()
|
||||
{
|
||||
vpip_simulation_obj.sim_time.time = 0;
|
||||
vpip_simulation_obj.going_flag = !0;
|
||||
|
||||
while (vpip_simulation_obj.going_flag) {
|
||||
struct vpip_simulation_cycle*sim = vpip_simulation_obj.sim;
|
||||
|
||||
/* Step the time forward to the next time cycle. */
|
||||
vpip_simulation_obj.sim_time.time += sim->delay;
|
||||
sim->delay = 0;
|
||||
|
||||
while (vpip_simulation_obj.going_flag) {
|
||||
struct vpip_event*active = sim->event_list;
|
||||
sim->event_list = 0;
|
||||
sim->event_last = 0;
|
||||
|
||||
if (active == 0) {
|
||||
active = sim->nonblock_list;
|
||||
sim->nonblock_list = 0;
|
||||
sim->nonblock_last = 0;
|
||||
}
|
||||
|
||||
if (active == 0)
|
||||
break;
|
||||
|
||||
while (active && vpip_simulation_obj.going_flag) {
|
||||
struct vpip_event*cur = active;
|
||||
active = cur->next;
|
||||
(cur->sim_fun)(cur->user_data);
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
if (! vpip_simulation_obj.going_flag)
|
||||
break;
|
||||
|
||||
{ struct vpip_simulation_cycle*next = sim->next;
|
||||
if (next == sim) {
|
||||
vpip_simulation_obj.going_flag = 0;
|
||||
break;
|
||||
}
|
||||
sim->next->prev = sim->prev;
|
||||
sim->prev->next = sim->next;
|
||||
free(sim);
|
||||
vpip_simulation_obj.sim = next;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_simulation.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_systask.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
static vpiHandle systask_iter(int type, vpiHandle ref)
|
||||
{
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiSysTaskCall);
|
||||
|
||||
if (rfp->nargs == 0)
|
||||
return 0;
|
||||
|
||||
return vpip_make_iterator(rfp->nargs, rfp->args);
|
||||
}
|
||||
|
||||
const struct __vpirt vpip_systask_rt = {
|
||||
vpiSysTaskCall,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: vpi_systask.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: vpi_time.c,v 1.1 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
# include <stdio.h>
|
||||
|
||||
/*
|
||||
* IEEE-1364 VPI pretty much mandates the existance of this sort of
|
||||
* thing. (Either this or a huge memory leak.) Sorry.
|
||||
*/
|
||||
static char buf_obj[128];
|
||||
|
||||
static void timevar_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||
{
|
||||
struct __vpiTimeVar*rfp = (struct __vpiTimeVar*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiTimeVar);
|
||||
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
case vpiTimeVal:
|
||||
rfp->time_obj.low = rfp->time;
|
||||
vp->value.time = &rfp->time_obj;
|
||||
vp->format = vpiTimeVal;
|
||||
break;
|
||||
|
||||
case vpiDecStrVal:
|
||||
sprintf(buf_obj, "%lu", rfp->time);
|
||||
vp->value.str = buf_obj;
|
||||
break;
|
||||
|
||||
default:
|
||||
vp->format = vpiSuppressVal;
|
||||
vp->value.str = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const struct __vpirt vpip_time_var_rt = {
|
||||
vpiTimeVar,
|
||||
0,
|
||||
0,
|
||||
timevar_get_value,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_time_var(struct __vpiTimeVar*ref, const char*val)
|
||||
{
|
||||
ref->base.vpi_type = &vpip_time_var_rt;
|
||||
ref->name = val;
|
||||
return &(ref->base);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_time.c,v $
|
||||
* Revision 1.1 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
*/
|
||||
|
||||
118
vvm/vvm.h
118
vvm/vvm.h
|
|
@ -19,12 +19,13 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm.h,v 1.15 1999/10/13 03:15:51 steve Exp $"
|
||||
#ident "$Id: vvm.h,v 1.16 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vector>
|
||||
# include <string>
|
||||
# include <cassert>
|
||||
# include "vpi_priv.h"
|
||||
|
||||
/*
|
||||
* The Verilog Virtual Machine are definitions for the virtual machine
|
||||
|
|
@ -38,14 +39,8 @@ class vvm_simulation;
|
|||
class vvm_simulation_cycle;
|
||||
class vvm_thread;
|
||||
|
||||
/* The vvm_bit_t is the basic unit of value for a scalar signal in
|
||||
Verilog. It represents all the possible values. The vvm_bitstring_t
|
||||
is a vector of vvm_bit_t and is used when variable-length bit
|
||||
arrays are needed. */
|
||||
enum vvm_bit_t { V0 = 0, V1, Vx, Vz };
|
||||
|
||||
|
||||
inline vvm_bit_t operator & (vvm_bit_t l, vvm_bit_t r)
|
||||
inline vpip_bit_t operator & (vpip_bit_t l, vpip_bit_t r)
|
||||
{
|
||||
if (l == V0) return V0;
|
||||
if (r == V0) return V0;
|
||||
|
|
@ -53,7 +48,7 @@ inline vvm_bit_t operator & (vvm_bit_t l, vvm_bit_t r)
|
|||
return Vx;
|
||||
}
|
||||
|
||||
inline vvm_bit_t operator | (vvm_bit_t l, vvm_bit_t r)
|
||||
inline vpip_bit_t operator | (vpip_bit_t l, vpip_bit_t r)
|
||||
{
|
||||
if (l == V1) return V1;
|
||||
if (r == V1) return V1;
|
||||
|
|
@ -61,7 +56,7 @@ inline vvm_bit_t operator | (vvm_bit_t l, vvm_bit_t r)
|
|||
return Vx;
|
||||
}
|
||||
|
||||
inline vvm_bit_t operator ^ (vvm_bit_t l, vvm_bit_t r)
|
||||
inline vpip_bit_t operator ^ (vpip_bit_t l, vpip_bit_t r)
|
||||
{
|
||||
if (l == Vx) return Vx;
|
||||
if (l == Vz) return Vx;
|
||||
|
|
@ -71,7 +66,7 @@ inline vvm_bit_t operator ^ (vvm_bit_t l, vvm_bit_t r)
|
|||
return (r == V0)? V1 : V0;
|
||||
}
|
||||
|
||||
inline vvm_bit_t less_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c)
|
||||
inline vpip_bit_t less_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c)
|
||||
{
|
||||
if (l == Vx) return Vx;
|
||||
if (r == Vx) return Vx;
|
||||
|
|
@ -80,7 +75,7 @@ inline vvm_bit_t less_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c)
|
|||
return c;
|
||||
}
|
||||
|
||||
inline vvm_bit_t greater_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c)
|
||||
inline vpip_bit_t greater_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c)
|
||||
{
|
||||
if (l == Vx) return Vx;
|
||||
if (r == Vx) return Vx;
|
||||
|
|
@ -89,9 +84,9 @@ inline vvm_bit_t greater_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c)
|
|||
return c;
|
||||
}
|
||||
|
||||
extern vvm_bit_t add_with_carry(vvm_bit_t l, vvm_bit_t r, vvm_bit_t&carry);
|
||||
extern vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry);
|
||||
|
||||
inline vvm_bit_t not(vvm_bit_t l)
|
||||
inline vpip_bit_t not(vpip_bit_t l)
|
||||
{
|
||||
switch (l) {
|
||||
case V0:
|
||||
|
|
@ -107,14 +102,14 @@ class vvm_bits_t {
|
|||
public:
|
||||
virtual ~vvm_bits_t() =0;
|
||||
virtual unsigned get_width() const =0;
|
||||
virtual vvm_bit_t get_bit(unsigned idx) const =0;
|
||||
virtual vpip_bit_t get_bit(unsigned idx) const =0;
|
||||
};
|
||||
|
||||
extern ostream& operator << (ostream&os, vvm_bit_t);
|
||||
extern ostream& operator << (ostream&os, vpip_bit_t);
|
||||
extern ostream& operator << (ostream&os, const vvm_bits_t&str);
|
||||
|
||||
/*
|
||||
* The vvm_bitset_t is a fixed width array-like set of vvm_bit_t
|
||||
* The vvm_bitset_t is a fixed width array-like set of vpip_bit_t
|
||||
* items. A number is often times made up of bit sets instead of
|
||||
* single bits. The fixed array is used when possible because of the
|
||||
* more thorough type checking and (hopefully) better optimization.
|
||||
|
|
@ -124,44 +119,38 @@ template <unsigned WIDTH> class vvm_bitset_t : public vvm_bits_t {
|
|||
public:
|
||||
vvm_bitset_t()
|
||||
{ for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
|
||||
bits_[idx] = Vz;
|
||||
bits[idx] = Vz;
|
||||
}
|
||||
//vvm_bitset_t(const vvm_bitset_t<WIDTH>&that)
|
||||
// { bits_ = that.bits_; }
|
||||
|
||||
vvm_bitset_t(const vvm_bits_t&that)
|
||||
{ unsigned wid = WIDTH;
|
||||
if (that.get_width() < WIDTH)
|
||||
wid = that.get_width();
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
bits_[idx] = that.get_bit(idx);
|
||||
bits[idx] = that.get_bit(idx);
|
||||
for (unsigned idx = wid ; idx < WIDTH ; idx += 1)
|
||||
bits_[idx] = V0;
|
||||
bits[idx] = V0;
|
||||
}
|
||||
|
||||
|
||||
vvm_bit_t operator[] (unsigned idx) const { return bits_[idx]; }
|
||||
vvm_bit_t&operator[] (unsigned idx) { return bits_[idx]; }
|
||||
vpip_bit_t operator[] (unsigned idx) const { return bits[idx]; }
|
||||
vpip_bit_t&operator[] (unsigned idx) { return bits[idx]; }
|
||||
|
||||
unsigned get_width() const { return WIDTH; }
|
||||
vvm_bit_t get_bit(unsigned idx) const { return bits_[idx]; }
|
||||
vpip_bit_t get_bit(unsigned idx) const { return bits[idx]; }
|
||||
|
||||
unsigned as_unsigned() const
|
||||
{ unsigned result = 0;
|
||||
for (unsigned idx = WIDTH ; idx > 0 ; idx -= 1) {
|
||||
result <<= 1;
|
||||
if (bits_[idx-1]) result |= 1;
|
||||
if (bits[idx-1]) result |= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//vvm_bitset_t<WIDTH>& operator= (const vvm_bitset_t<WIDTH>&that)
|
||||
// { if (this == &that) return *this;
|
||||
// bits_ = that.bits_;
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
private:
|
||||
vvm_bit_t bits_[WIDTH];
|
||||
public:
|
||||
vpip_bit_t bits[WIDTH];
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -174,12 +163,14 @@ class vvm_event {
|
|||
friend class vvm_simulation;
|
||||
|
||||
public:
|
||||
vvm_event() { }
|
||||
vvm_event();
|
||||
virtual ~vvm_event() =0;
|
||||
virtual void event_function() =0;
|
||||
|
||||
static void callback_(void*);
|
||||
|
||||
private:
|
||||
vvm_event*next_;
|
||||
struct vpip_event*event_;
|
||||
|
||||
private: // not implemented
|
||||
vvm_event(const vvm_event&);
|
||||
|
|
@ -225,72 +216,47 @@ class vvm_simulation {
|
|||
// only one event can be a monitor.
|
||||
void monitor_event(vvm_event*);
|
||||
|
||||
unsigned long get_sim_time() const { return time_; }
|
||||
|
||||
// The s_finish() method marks the simulation as finished and
|
||||
// prevents more events being executed. The finished() method
|
||||
// returns true if the s_finish() method has been called.
|
||||
void s_finish();
|
||||
bool finished() const;
|
||||
|
||||
private:
|
||||
bool going_;
|
||||
vvm_simulation_cycle*sim_;
|
||||
|
||||
// Triggered monitor event.
|
||||
vvm_event*mon_;
|
||||
|
||||
unsigned long time_;
|
||||
|
||||
private: // not implemented
|
||||
vvm_simulation(const vvm_simulation&);
|
||||
vvm_simulation& operator= (const vvm_simulation&);
|
||||
};
|
||||
|
||||
/*
|
||||
* The vvm_monitor_t is usually associated with a vvm_bitset_t that
|
||||
* represents a signal. The VVM code generator generates calls to the
|
||||
* trigger method whenever an assignment or output value is set on
|
||||
* the associated signal. The trigger, if enabled, then causes the
|
||||
* monitor event to be scheduled in the simulation.
|
||||
* The vvm_monitor_t is a way of attaching a name to the signal, for
|
||||
* use by the vpi_ functions. I need to make a base type so that I can
|
||||
* avoid the casting problems with the vvm_signal_t template below.
|
||||
*
|
||||
* This object also carries the canonical signal name, for the use of
|
||||
* %m display patterns.
|
||||
* The vvm_signal_t template is the real object that handles the
|
||||
* receiving of assignments and doing whatever is done.
|
||||
*/
|
||||
class vvm_monitor_t {
|
||||
public:
|
||||
vvm_monitor_t(const char*);
|
||||
|
||||
void trigger(vvm_simulation*sim)
|
||||
{ if (event_) sim->monitor_event(event_); }
|
||||
|
||||
const char* name() const { return name_; }
|
||||
|
||||
void enable(vvm_event*e) { event_ = e; }
|
||||
|
||||
~vvm_monitor_t();
|
||||
const char* name() const;
|
||||
private:
|
||||
const char* name_;
|
||||
vvm_event*event_;
|
||||
|
||||
private: // not implemented
|
||||
vvm_monitor_t(const vvm_monitor_t&);
|
||||
vvm_monitor_t& operator= (const vvm_monitor_t&);
|
||||
};
|
||||
|
||||
|
||||
template <unsigned WIDTH> class vvm_signal_t : public vvm_monitor_t {
|
||||
template <unsigned WIDTH> class vvm_signal_t : public vvm_monitor_t {
|
||||
|
||||
public:
|
||||
vvm_signal_t(const char*n, vvm_bitset_t<WIDTH>*b)
|
||||
: vvm_monitor_t(n), bits_(b)
|
||||
{ }
|
||||
: vvm_monitor_t(n), bits_(b) { }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val)
|
||||
~vvm_signal_t() { }
|
||||
|
||||
void init(unsigned idx, vpip_bit_t val)
|
||||
{ (*bits_)[idx] = val; }
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ (*bits_)[idx] = val;
|
||||
trigger(sim);
|
||||
}
|
||||
|
||||
void set(vvm_simulation*sim, const vvm_bitset_t<WIDTH>&val)
|
||||
|
|
@ -304,6 +270,12 @@ template <unsigned WIDTH> class vvm_signal_t : public vvm_monitor_t {
|
|||
|
||||
/*
|
||||
* $Log: vvm.h,v $
|
||||
* Revision 1.16 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.15 1999/10/13 03:15:51 steve
|
||||
* Remove useless operator=.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_bit.cc,v 1.2 1998/11/10 00:48:31 steve Exp $"
|
||||
#ident "$Id: vvm_bit.cc,v 1.3 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
|
||||
ostream& operator << (ostream&os, vvm_bit_t bit)
|
||||
ostream& operator << (ostream&os, vpip_bit_t bit)
|
||||
{
|
||||
switch (bit) {
|
||||
case V0:
|
||||
|
|
@ -54,7 +54,7 @@ vvm_bits_t::~vvm_bits_t()
|
|||
{
|
||||
}
|
||||
|
||||
vvm_bit_t add_with_carry(vvm_bit_t l, vvm_bit_t r, vvm_bit_t&carry)
|
||||
vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry)
|
||||
{
|
||||
unsigned li, ri, ci;
|
||||
switch (l) {
|
||||
|
|
@ -100,6 +100,12 @@ vvm_bit_t add_with_carry(vvm_bit_t l, vvm_bit_t r, vvm_bit_t&carry)
|
|||
|
||||
/*
|
||||
* $Log: vvm_bit.cc,v $
|
||||
* Revision 1.3 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.2 1998/11/10 00:48:31 steve
|
||||
* Add support it vvm target for level-sensitive
|
||||
* triggers (i.e. the Verilog wait).
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_calltf.cc,v 1.7 1999/10/10 14:57:38 steve Exp $"
|
||||
#ident "$Id: vvm_calltf.cc,v 1.8 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm_calltf.h"
|
||||
|
|
@ -34,359 +34,6 @@
|
|||
|
||||
# define MAX_PATHLEN 1024
|
||||
|
||||
/* This simulation pointer is used by vpi functions to get back to the
|
||||
simulation. */
|
||||
static vvm_simulation*vpi_sim;
|
||||
|
||||
static vpiHandle vvm_vpi_cur_task;
|
||||
|
||||
/*
|
||||
* Keep a list of vpi_systf_data structures. This list is searched
|
||||
* forward whenever a function is invoked by name, and items are
|
||||
* pushed in front of the list whenever they are registered. This
|
||||
* allows entries to override older entries.
|
||||
*/
|
||||
struct systf_entry {
|
||||
struct systf_entry* next;
|
||||
s_vpi_systf_data systf_data;
|
||||
};
|
||||
|
||||
static struct systf_entry*systf_list = 0;
|
||||
|
||||
extern "C" void vpi_register_systf(const struct t_vpi_systf_data*systf)
|
||||
{
|
||||
struct systf_entry*cur = new struct systf_entry;
|
||||
cur->systf_data = *systf;
|
||||
cur->systf_data.tfname = strdup(systf->tfname);
|
||||
cur->next = systf_list;
|
||||
systf_list = cur;
|
||||
}
|
||||
|
||||
extern "C" void vpi_printf(const char*fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
extern "C" void vpi_sim_control(int func, ...)
|
||||
{
|
||||
switch (func) {
|
||||
case vpiFinish:
|
||||
vpi_sim->s_finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" vpiHandle vpi_handle(int type, vpiHandle ref)
|
||||
{
|
||||
switch (type) {
|
||||
case vpiSysTfCall:
|
||||
return vvm_vpi_cur_task;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" vpiHandle vpi_iterate(int type, vpiHandle ref)
|
||||
{
|
||||
vpiHandle res = (vpiHandle)calloc(1, sizeof (struct __vpiHandle));
|
||||
res->type = type;
|
||||
res->referent = ref;
|
||||
res->val.unum = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C" vpiHandle vpi_scan(vpiHandle ref)
|
||||
{
|
||||
assert(ref->type == vpiArgument);
|
||||
if (ref->val.unum >= ref->referent->narguments) {
|
||||
vpi_free_object(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ref->referent->arguments[ref->val.unum++];
|
||||
}
|
||||
|
||||
extern "C" int vpi_get(int property, vpiHandle ref)
|
||||
{
|
||||
if (property == vpiType)
|
||||
return ref->type;
|
||||
|
||||
if (ref->get_ == 0)
|
||||
return -1;
|
||||
|
||||
return (ref->get_)(property, ref);
|
||||
}
|
||||
|
||||
extern "C" char* vpi_get_str(int property, vpiHandle ref)
|
||||
{
|
||||
if (property == vpiFullName)
|
||||
return ref->full_name;
|
||||
|
||||
if (ref->get_str_ == 0)
|
||||
return 0;
|
||||
|
||||
return (ref->get_str_)(property, ref);
|
||||
|
||||
switch (property) {
|
||||
case vpiName:
|
||||
return ref->full_name;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
|
||||
{
|
||||
if (expr->get_value_) {
|
||||
expr->get_value_(expr, vp);
|
||||
return;
|
||||
}
|
||||
|
||||
vp->format = vpiSuppressVal;
|
||||
}
|
||||
|
||||
extern "C" int vpi_free_object(vpiHandle ref)
|
||||
{
|
||||
free(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is a get_value_ method of a vpiHandle, that supports
|
||||
* reading bits as a string.
|
||||
*/
|
||||
static void get_value_bits(vpiHandle ref, s_vpi_value*vp)
|
||||
{
|
||||
static char buff[1024];
|
||||
char*cp;
|
||||
unsigned width;
|
||||
unsigned val;
|
||||
assert(ref->val.bits);
|
||||
width = ref->val.bits->get_width();
|
||||
cp = buff;
|
||||
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
case vpiBinStrVal:
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
switch (ref->val.bits->get_bit(width-idx-1)) {
|
||||
case V0:
|
||||
*cp++ = '0';
|
||||
break;
|
||||
case V1:
|
||||
*cp++ = '1';
|
||||
break;
|
||||
case Vx:
|
||||
*cp++ = 'x';
|
||||
break;
|
||||
case Vz:
|
||||
*cp++ = 'z';
|
||||
break;
|
||||
}
|
||||
vp->format = vpiBinStrVal;
|
||||
break;
|
||||
|
||||
case vpiDecStrVal:
|
||||
val = 0;
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1) {
|
||||
val *= 2;
|
||||
switch (ref->val.bits->get_bit(width-idx-1)) {
|
||||
case V0:
|
||||
case Vx:
|
||||
case Vz:
|
||||
break;
|
||||
case V1:
|
||||
val += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sprintf(cp, "%u", val);
|
||||
cp += strlen(cp);
|
||||
break;
|
||||
|
||||
case vpiOctStrVal:
|
||||
if (width%3) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
for (unsigned i = 0 ; i < width%3 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (ref->val.bits->get_bit(width-i-1)) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == width%3)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == width%3)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "01234567"[v];
|
||||
}
|
||||
|
||||
for (unsigned idx = width%3 ; idx < width ; idx += 3) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
for (unsigned i = idx ; i < idx+3 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (ref->val.bits->get_bit(width-i-1)) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == 3)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == 3)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "01234567"[v];
|
||||
}
|
||||
break;
|
||||
|
||||
case vpiHexStrVal:
|
||||
if (width%4) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
for (unsigned i = 0 ; i < width%4 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (ref->val.bits->get_bit(width-i-1)) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == width%4)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == width%4)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "0123456789abcdef"[v];
|
||||
}
|
||||
|
||||
for (unsigned idx = width%4 ; idx < width ; idx += 4) {
|
||||
unsigned x = 0;
|
||||
unsigned z = 0;
|
||||
unsigned v = 0;
|
||||
for (unsigned i = idx ; i < idx+4 ; i += 1) {
|
||||
v *= 2;
|
||||
switch (ref->val.bits->get_bit(width-i-1)) {
|
||||
case V0:
|
||||
break;
|
||||
case V1:
|
||||
v += 1;
|
||||
break;
|
||||
case Vx:
|
||||
x += 1;
|
||||
break;
|
||||
case Vz:
|
||||
z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x == 4)
|
||||
*cp++ = 'x';
|
||||
else if (x > 0)
|
||||
*cp++ = 'X';
|
||||
else if (z == 4)
|
||||
*cp++ = 'z';
|
||||
else if (z > 0)
|
||||
*cp++ = 'Z';
|
||||
else
|
||||
*cp++ = "0123456789abcdef"[v];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*cp++ = '(';
|
||||
*cp++ = '?';
|
||||
*cp++ = ')';
|
||||
break;
|
||||
}
|
||||
|
||||
*cp++ = 0;
|
||||
vp->value.str = buff;
|
||||
}
|
||||
|
||||
static void get_value_strconst(vpiHandle ref, s_vpi_value*vp)
|
||||
{
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
case vpiStringVal:
|
||||
vp->value.str = ref->full_name;
|
||||
vp->format = vpiStringVal;
|
||||
break;
|
||||
|
||||
default:
|
||||
vp->format = vpiSuppressVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_value_timevar(vpiHandle ref, s_vpi_value*vp)
|
||||
{
|
||||
static char buf[128];
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
case vpiTimeVal:
|
||||
vp->value.time = &ref->val.time;
|
||||
vp->format = vpiTimeVal;
|
||||
break;
|
||||
|
||||
case vpiDecStrVal:
|
||||
sprintf(buf, "%u", ref->val.time.low);
|
||||
vp->value.str = buf;
|
||||
break;
|
||||
|
||||
default:
|
||||
vp->format = vpiSuppressVal;
|
||||
vp->value.str = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The load_vpi_module function attempts to locate and load the named
|
||||
|
|
@ -457,80 +104,16 @@ void vvm_load_vpi_module(const char*name)
|
|||
(routines[idx])();
|
||||
}
|
||||
|
||||
void vvm_make_vpi_parm(vpiHandle ref, const char*val)
|
||||
{
|
||||
memset(ref, 0, sizeof*ref);
|
||||
ref->type = vpiConstant;
|
||||
ref->subtype = vpiStringConst;
|
||||
ref->full_name = const_cast<char*>(val);
|
||||
ref->get_value_ = &get_value_strconst;
|
||||
}
|
||||
|
||||
void vvm_make_vpi_parm(vpiHandle ref, vvm_bits_t*val)
|
||||
{
|
||||
memset(ref, 0, sizeof*ref);
|
||||
ref->type = vpiConstant;
|
||||
ref->subtype = vpiBinaryConst;
|
||||
ref->full_name = "";
|
||||
ref->val.bits = val;
|
||||
ref->get_value_ = &get_value_bits;
|
||||
}
|
||||
|
||||
void vvm_init_vpi_handle(vpiHandle ref, vvm_bits_t*bits, vvm_monitor_t*mon)
|
||||
{
|
||||
memset(ref, 0, sizeof*ref);
|
||||
ref->type = vpiReg;
|
||||
ref->full_name = const_cast<char*>(mon->name());
|
||||
ref->val.bits = bits;
|
||||
ref->get_value_ = &get_value_bits;
|
||||
}
|
||||
|
||||
void vvm_init_vpi_timevar(vpiHandle ref, const char*name)
|
||||
{
|
||||
memset(ref, 0, sizeof*ref);
|
||||
ref->type = vpiTimeVar;
|
||||
ref->full_name = const_cast<char*>(name);
|
||||
ref->get_value_ = &get_value_timevar;
|
||||
}
|
||||
|
||||
void vvm_make_vpi_parm(vpiHandle ref)
|
||||
{
|
||||
memset(ref, 0, sizeof*ref);
|
||||
ref->type = 0;
|
||||
}
|
||||
|
||||
void vvm_calltask(vvm_simulation*sim, const string&fname,
|
||||
unsigned nparms, vpiHandle*parms)
|
||||
{
|
||||
vpi_sim = sim;
|
||||
|
||||
struct __vpiHandle cur_task;
|
||||
cur_task.type = vpiSysTaskCall;
|
||||
cur_task.full_name = 0;
|
||||
cur_task.referent = 0;
|
||||
cur_task.arguments = parms;
|
||||
cur_task.narguments = nparms;
|
||||
|
||||
vvm_vpi_cur_task = &cur_task;
|
||||
|
||||
/* Look for a systf function to invoke. */
|
||||
for (systf_entry*idx = systf_list ; idx ; idx = idx->next)
|
||||
if (fname == idx->systf_data.tfname) {
|
||||
cur_task.full_name = idx->systf_data.tfname;
|
||||
idx->systf_data.calltf(idx->systf_data.user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Finally, if nothing is found then something is not
|
||||
right. Print out the function name all the parameters
|
||||
passed, so that someone can deal with it. */
|
||||
cout << "Call " << fname << endl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: vvm_calltf.cc,v $
|
||||
* Revision 1.8 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.7 1999/10/10 14:57:38 steve
|
||||
* Handle display of odd octal/hex widths (Eric Ardoom)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,13 +19,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_calltf.h,v 1.2 1999/08/15 01:23:56 steve Exp $"
|
||||
#ident "$Id: vvm_calltf.h,v 1.3 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
# include <string>
|
||||
|
||||
typedef struct __vpiHandle*vpiHandle;
|
||||
|
||||
/*
|
||||
* This function loads a vpi module by name.
|
||||
|
|
@ -33,34 +32,14 @@ typedef struct __vpiHandle*vpiHandle;
|
|||
extern void vvm_load_vpi_module(const char*path);
|
||||
|
||||
|
||||
/*
|
||||
* The vvm_init_vpi_handle functions initialize statis VPI handles
|
||||
* that may be used many places within the program.
|
||||
*/
|
||||
extern void vvm_init_vpi_handle(vpiHandle, vvm_bits_t*, vvm_monitor_t*);
|
||||
extern void vvm_init_vpi_timevar(vpiHandle, const char*name);
|
||||
|
||||
/*
|
||||
* The vvm_make_vpi_parm functions initialize the vpiHandles to
|
||||
* represent objects suitable for use as vvm_calltask parameters.
|
||||
*/
|
||||
extern void vvm_make_vpi_parm(vpiHandle ref, const char*val);
|
||||
extern void vvm_make_vpi_parm(vpiHandle ref, vvm_bits_t*val);
|
||||
extern void vvm_make_vpi_parm(vpiHandle ref);
|
||||
|
||||
/*
|
||||
* The vvm environment supports external calls to C++ by
|
||||
* vvm_calltask. The code generator generates calls to vvm_calltask
|
||||
* that corresponds to the system call in the Verilog source. The
|
||||
* vvm_calltask in turn locates the vpi implementation (by name) and
|
||||
* calls the VPI that implements the task.
|
||||
*/
|
||||
|
||||
extern void vvm_calltask(vvm_simulation*sim, const string&name,
|
||||
unsigned nparms, vpiHandle*parms);
|
||||
|
||||
/*
|
||||
* $Log: vvm_calltf.h,v $
|
||||
* Revision 1.3 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.2 1999/08/15 01:23:56 steve
|
||||
* Convert vvm to implement system tasks with vpi.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,18 +17,36 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_event.cc,v 1.1 1998/11/09 23:44:11 steve Exp $"
|
||||
#ident "$Id: vvm_event.cc,v 1.2 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
# include <assert.h>
|
||||
|
||||
vvm_event::vvm_event()
|
||||
{
|
||||
event_ = 0;
|
||||
}
|
||||
|
||||
vvm_event::~vvm_event()
|
||||
{
|
||||
}
|
||||
|
||||
void vvm_event::callback_(void*cbd)
|
||||
{
|
||||
vvm_event*obj = reinterpret_cast<vvm_event*>(cbd);
|
||||
obj->event_function();
|
||||
delete obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vvm_event.cc,v $
|
||||
* Revision 1.2 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.1 1998/11/09 23:44:11 steve
|
||||
* Add vvm library.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_func.h,v 1.14 1999/10/05 06:19:47 steve Exp $"
|
||||
#ident "$Id: vvm_func.h,v 1.15 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
|
|
@ -123,7 +123,7 @@ vvm_bitset_t<WIDTH> vvm_unop_uminus(const vvm_bitset_t<WIDTH>&l)
|
|||
{
|
||||
vvm_bitset_t<WIDTH> res;
|
||||
res = vvm_unop_not(l);
|
||||
vvm_bit_t carry = V1;
|
||||
vpip_bit_t carry = V1;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
res[i] = add_with_carry(res[i], V0, carry);
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ vvm_bitset_t<WIDTH> vvm_binop_plus(const vvm_bitset_t<WIDTH>&l,
|
|||
const vvm_bitset_t<WIDTH>&r)
|
||||
{
|
||||
vvm_bitset_t<WIDTH> result;
|
||||
vvm_bit_t carry = V0;
|
||||
vpip_bit_t carry = V0;
|
||||
for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
|
||||
result[idx] = add_with_carry(l[idx], r[idx], carry);
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ vvm_bitset_t<WIDTH> vvm_binop_minus(const vvm_bitset_t<WIDTH>&l,
|
|||
{
|
||||
vvm_bitset_t<WIDTH> res;
|
||||
res = vvm_unop_not(r);
|
||||
vvm_bit_t carry = V1;
|
||||
vpip_bit_t carry = V1;
|
||||
for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
|
||||
res[idx] = add_with_carry(l[idx], res[idx], carry);
|
||||
|
||||
|
|
@ -593,7 +593,7 @@ vvm_bitset_t<1> vvm_binop_lor(const vvm_bitset_t<LW>&l,
|
|||
}
|
||||
|
||||
template <unsigned W>
|
||||
vvm_bitset_t<W> vvm_ternary(vvm_bit_t c, const vvm_bitset_t<W>&t,
|
||||
vvm_bitset_t<W> vvm_ternary(vpip_bit_t c, const vvm_bitset_t<W>&t,
|
||||
const vvm_bitset_t<W>&f)
|
||||
{
|
||||
switch (c) {
|
||||
|
|
@ -608,6 +608,12 @@ vvm_bitset_t<W> vvm_ternary(vvm_bit_t c, const vvm_bitset_t<W>&t,
|
|||
|
||||
/*
|
||||
* $Log: vvm_func.h,v $
|
||||
* Revision 1.15 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.14 1999/10/05 06:19:47 steve
|
||||
* Add support for reduction NOR.
|
||||
*
|
||||
|
|
|
|||
116
vvm/vvm_gates.h
116
vvm/vvm_gates.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_gates.h,v 1.14 1999/10/10 01:59:55 steve Exp $"
|
||||
#ident "$Id: vvm_gates.h,v 1.15 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
|
|
@ -36,8 +36,8 @@
|
|||
class vvm_out_event : public vvm_event {
|
||||
|
||||
public:
|
||||
typedef void (*action_t)(vvm_simulation*, vvm_bit_t);
|
||||
vvm_out_event(vvm_simulation*s, vvm_bit_t v, action_t o)
|
||||
typedef void (*action_t)(vvm_simulation*, vpip_bit_t);
|
||||
vvm_out_event(vvm_simulation*s, vpip_bit_t v, action_t o)
|
||||
: output_(o), sim_(s), val_(v) { }
|
||||
|
||||
void event_function()
|
||||
|
|
@ -46,7 +46,7 @@ class vvm_out_event : public vvm_event {
|
|||
private:
|
||||
const action_t output_;
|
||||
vvm_simulation*const sim_;
|
||||
const vvm_bit_t val_;
|
||||
const vpip_bit_t val_;
|
||||
};
|
||||
|
||||
template <unsigned WIDTH, unsigned long DELAY> class vvm_and {
|
||||
|
|
@ -55,7 +55,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_and {
|
|||
explicit vvm_and(vvm_out_event::action_t o)
|
||||
: output_(o) { }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val)
|
||||
void init(unsigned idx, vpip_bit_t val)
|
||||
{ input_[idx-1] = val; }
|
||||
|
||||
void start(vvm_simulation*sim)
|
||||
|
|
@ -66,7 +66,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_and {
|
|||
sim->active_event(ev);
|
||||
}
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
|
|
@ -79,14 +79,14 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_and {
|
|||
}
|
||||
|
||||
private:
|
||||
vvm_bit_t compute_() const
|
||||
{ vvm_bit_t outval = input_[0];
|
||||
vpip_bit_t compute_() const
|
||||
{ vpip_bit_t outval = input_[0];
|
||||
for (unsigned i = 1 ; i < WIDTH ; i += 1)
|
||||
outval = outval & input_[i];
|
||||
return outval;
|
||||
}
|
||||
|
||||
vvm_bit_t input_[WIDTH];
|
||||
vpip_bit_t input_[WIDTH];
|
||||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_or {
|
|||
explicit vvm_or(vvm_out_event::action_t o)
|
||||
: output_(o) { }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val)
|
||||
void init(unsigned idx, vpip_bit_t val)
|
||||
{ input_[idx-1] = val; }
|
||||
|
||||
void start(vvm_simulation*sim)
|
||||
|
|
@ -107,7 +107,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_or {
|
|||
sim->active_event(ev);
|
||||
}
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
|
|
@ -120,14 +120,14 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_or {
|
|||
}
|
||||
|
||||
private:
|
||||
vvm_bit_t compute_() const
|
||||
{ vvm_bit_t outval = input_[0];
|
||||
vpip_bit_t compute_() const
|
||||
{ vpip_bit_t outval = input_[0];
|
||||
for (unsigned i = 1 ; i < WIDTH ; i += 1)
|
||||
outval = outval | input_[i];
|
||||
return outval;
|
||||
}
|
||||
|
||||
vvm_bit_t input_[WIDTH];
|
||||
vpip_bit_t input_[WIDTH];
|
||||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_nor {
|
|||
explicit vvm_nor(vvm_out_event::action_t o)
|
||||
: output_(o) { }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val)
|
||||
void init(unsigned idx, vpip_bit_t val)
|
||||
{ input_[idx-1] = val; }
|
||||
|
||||
void start(vvm_simulation*sim)
|
||||
|
|
@ -148,7 +148,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_nor {
|
|||
sim->active_event(ev);
|
||||
}
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
|
|
@ -161,14 +161,14 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_nor {
|
|||
}
|
||||
|
||||
private:
|
||||
vvm_bit_t compute_() const
|
||||
{ vvm_bit_t outval = input_[0];
|
||||
vpip_bit_t compute_() const
|
||||
{ vpip_bit_t outval = input_[0];
|
||||
for (unsigned i = 1 ; i < WIDTH ; i += 1)
|
||||
outval = outval | input_[i];
|
||||
return not(outval);
|
||||
}
|
||||
|
||||
vvm_bit_t input_[WIDTH];
|
||||
vpip_bit_t input_[WIDTH];
|
||||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ template <unsigned long DELAY> class vvm_bufif1 {
|
|||
input_[1] = Vx;
|
||||
}
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
|
|
@ -197,10 +197,10 @@ template <unsigned long DELAY> class vvm_bufif1 {
|
|||
}
|
||||
|
||||
private:
|
||||
vvm_bit_t input_[2];
|
||||
vpip_bit_t input_[2];
|
||||
vvm_out_event::action_t output_;
|
||||
|
||||
vvm_bit_t compute_() const
|
||||
vpip_bit_t compute_() const
|
||||
{ if (input_[1] != V1) return Vz;
|
||||
if (input_[0] == Vz) return Vx;
|
||||
return input_[0];
|
||||
|
|
@ -216,16 +216,16 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_nand {
|
|||
input_[idx] = V0;
|
||||
}
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val) { input_[idx-1] = val; }
|
||||
void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; }
|
||||
|
||||
// Set an input of the NAND gate causes a new output value to
|
||||
// be calculated and an event generated to make the output
|
||||
// happen. The input pins are numbered from 1 - WIDTH.
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
vvm_bit_t outval = input_[0];
|
||||
vpip_bit_t outval = input_[0];
|
||||
for (unsigned i = 1 ; i < WIDTH ; i += 1)
|
||||
outval = outval & input_[i];
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_nand {
|
|||
}
|
||||
|
||||
private:
|
||||
vvm_bit_t input_[WIDTH];
|
||||
vpip_bit_t input_[WIDTH];
|
||||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
|
|
@ -251,11 +251,11 @@ template <unsigned long DELAY> class vvm_not {
|
|||
: output_(o)
|
||||
{ }
|
||||
|
||||
void init(unsigned, vvm_bit_t) { }
|
||||
void init(unsigned, vpip_bit_t) { }
|
||||
void start(vvm_simulation*) { }
|
||||
|
||||
void set(vvm_simulation*sim, unsigned, vvm_bit_t val)
|
||||
{ vvm_bit_t outval = not(val);
|
||||
void set(vvm_simulation*sim, unsigned, vpip_bit_t val)
|
||||
{ vpip_bit_t outval = not(val);
|
||||
vvm_event*ev = new vvm_out_event(sim, outval, output_);
|
||||
if (DELAY > 0)
|
||||
sim->insert_event(DELAY, ev);
|
||||
|
|
@ -273,7 +273,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_xnor {
|
|||
explicit vvm_xnor(vvm_out_event::action_t o)
|
||||
: output_(o) { }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val) { input_[idx-1] = val; }
|
||||
void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; }
|
||||
void start(vvm_simulation*sim)
|
||||
{ vvm_event*ev = new vvm_out_event(sim, compute_(), output_);
|
||||
if (DELAY > 0)
|
||||
|
|
@ -284,11 +284,11 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_xnor {
|
|||
|
||||
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
vvm_bit_t outval = compute_();
|
||||
vpip_bit_t outval = compute_();
|
||||
vvm_event*ev = new vvm_out_event(sim, outval, output_);
|
||||
if (DELAY > 0)
|
||||
sim->insert_event(DELAY, ev);
|
||||
|
|
@ -297,15 +297,15 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_xnor {
|
|||
}
|
||||
|
||||
private:
|
||||
vvm_bit_t compute_() const
|
||||
{ vvm_bit_t outval = input_[0];
|
||||
vpip_bit_t compute_() const
|
||||
{ vpip_bit_t outval = input_[0];
|
||||
for (unsigned i = 1 ; i < WIDTH ; i += 1)
|
||||
outval = outval ^ input_[i];
|
||||
|
||||
outval = not(outval);
|
||||
return outval;
|
||||
}
|
||||
vvm_bit_t input_[WIDTH];
|
||||
vpip_bit_t input_[WIDTH];
|
||||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
|
|
@ -315,7 +315,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_xor {
|
|||
explicit vvm_xor(vvm_out_event::action_t o)
|
||||
: output_(o) { }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val)
|
||||
void init(unsigned idx, vpip_bit_t val)
|
||||
{ input_[idx-1] = val; }
|
||||
|
||||
void start(vvm_simulation*sim)
|
||||
|
|
@ -326,7 +326,7 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_xor {
|
|||
sim->active_event(ev);
|
||||
}
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
|
|
@ -335,14 +335,14 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_xor {
|
|||
|
||||
private:
|
||||
|
||||
vvm_bit_t compute_() const
|
||||
{ vvm_bit_t outval = input_[0];
|
||||
vpip_bit_t compute_() const
|
||||
{ vpip_bit_t outval = input_[0];
|
||||
for (unsigned i = 1 ; i < WIDTH ; i += 1)
|
||||
outval = outval ^ input_[i];
|
||||
return outval;
|
||||
}
|
||||
|
||||
vvm_bit_t input_[WIDTH];
|
||||
vpip_bit_t input_[WIDTH];
|
||||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
|
|
@ -356,7 +356,7 @@ template <unsigned long DELAY> class vvm_eeq {
|
|||
explicit vvm_eeq(vvm_out_event::action_t o)
|
||||
: output_(o) { }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val)
|
||||
void init(unsigned idx, vpip_bit_t val)
|
||||
{ input_[idx-1] = val; }
|
||||
|
||||
void start(vvm_simulation*sim)
|
||||
|
|
@ -367,7 +367,7 @@ template <unsigned long DELAY> class vvm_eeq {
|
|||
sim->active_event(ev);
|
||||
}
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (input_[idx-1] == val)
|
||||
return;
|
||||
input_[idx-1] = val;
|
||||
|
|
@ -376,14 +376,14 @@ template <unsigned long DELAY> class vvm_eeq {
|
|||
|
||||
private:
|
||||
|
||||
vvm_bit_t compute_() const
|
||||
{ vvm_bit_t outval = V0;
|
||||
vpip_bit_t compute_() const
|
||||
{ vpip_bit_t outval = V0;
|
||||
if (input_[0] == input_[1])
|
||||
outval = V1;
|
||||
return outval;
|
||||
}
|
||||
|
||||
vvm_bit_t input_[2];
|
||||
vpip_bit_t input_[2];
|
||||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
|
|
@ -397,7 +397,7 @@ template <unsigned long DELAY> class vvm_eeq {
|
|||
template <unsigned WIDTH> class vvm_udp_ssequ {
|
||||
|
||||
public:
|
||||
explicit vvm_udp_ssequ(vvm_out_event::action_t o, vvm_bit_t i,
|
||||
explicit vvm_udp_ssequ(vvm_out_event::action_t o, vpip_bit_t i,
|
||||
const vvm_u32*tab)
|
||||
: output_(o), table_(tab)
|
||||
{ state_[0] = i;
|
||||
|
|
@ -405,10 +405,10 @@ template <unsigned WIDTH> class vvm_udp_ssequ {
|
|||
state_[idx] = Vx;
|
||||
}
|
||||
|
||||
void init(unsigned pin, vvm_bit_t val)
|
||||
void init(unsigned pin, vpip_bit_t val)
|
||||
{ state_[pin] = val; }
|
||||
|
||||
void set(vvm_simulation*sim, unsigned pin, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned pin, vpip_bit_t val)
|
||||
{ assert(pin > 0);
|
||||
assert(pin < WIDTH+1);
|
||||
if (val == Vz) val = Vx;
|
||||
|
|
@ -435,8 +435,8 @@ template <unsigned WIDTH> class vvm_udp_ssequ {
|
|||
code &= 3;
|
||||
break;
|
||||
}
|
||||
// Convert the code to a vvm_bit_t and run with it.
|
||||
vvm_bit_t outval = (code == 0)? V0 : (code == 1)? V1 : Vx;
|
||||
// Convert the code to a vpip_bit_t and run with it.
|
||||
vpip_bit_t outval = (code == 0)? V0 : (code == 1)? V1 : Vx;
|
||||
state_[0] = outval;
|
||||
state_[pin] = val;
|
||||
vvm_event*ev = new vvm_out_event(sim, outval, output_);
|
||||
|
|
@ -446,7 +446,7 @@ template <unsigned WIDTH> class vvm_udp_ssequ {
|
|||
private:
|
||||
vvm_out_event::action_t output_;
|
||||
const vvm_u32*const table_;
|
||||
vvm_bit_t state_[WIDTH+1];
|
||||
vpip_bit_t state_[WIDTH+1];
|
||||
};
|
||||
|
||||
class vvm_bufz {
|
||||
|
|
@ -455,9 +455,9 @@ class vvm_bufz {
|
|||
: output_(o)
|
||||
{ }
|
||||
|
||||
void init(unsigned idx, vvm_bit_t val) { }
|
||||
void init(unsigned idx, vpip_bit_t val) { }
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ output_(sim, val); }
|
||||
|
||||
private:
|
||||
|
|
@ -502,7 +502,7 @@ template <unsigned WIDTH> class vvm_pevent {
|
|||
|
||||
vvm_bitset_t<WIDTH> get() const { return value_; }
|
||||
|
||||
void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val)
|
||||
void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ if (value_[idx] == val) return;
|
||||
switch (edge_) {
|
||||
case ANYEDGE:
|
||||
|
|
@ -520,7 +520,7 @@ template <unsigned WIDTH> class vvm_pevent {
|
|||
value_[idx] = val;
|
||||
}
|
||||
|
||||
void init(int idx, vvm_bit_t val)
|
||||
void init(int idx, vpip_bit_t val)
|
||||
{ assert(idx < WIDTH);
|
||||
value_[idx] = val;
|
||||
}
|
||||
|
|
@ -537,6 +537,12 @@ template <unsigned WIDTH> class vvm_pevent {
|
|||
|
||||
/*
|
||||
* $Log: vvm_gates.h,v $
|
||||
* Revision 1.15 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.14 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,20 +17,34 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_monitor.cc,v 1.2 1999/08/15 01:23:56 steve Exp $"
|
||||
#ident "$Id: vvm_monitor.cc,v 1.3 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
|
||||
|
||||
vvm_monitor_t::vvm_monitor_t(const char*n)
|
||||
: name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
vvm_monitor_t::~vvm_monitor_t()
|
||||
{
|
||||
}
|
||||
|
||||
const char*vvm_monitor_t::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: vvm_monitor.cc,v $
|
||||
* Revision 1.3 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.2 1999/08/15 01:23:56 steve
|
||||
* Convert vvm to implement system tasks with vpi.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,101 +17,37 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_simulation.cc,v 1.6 1999/10/06 01:28:18 steve Exp $"
|
||||
#ident "$Id: vvm_simulation.cc,v 1.7 1999/10/28 00:47:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
# include "vvm_thread.h"
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* The state of the simulation is stored as a list of simulation
|
||||
* times. Each simulation time contains the delay to get to it, and
|
||||
* also a list of events that are to execute here.
|
||||
*
|
||||
* The "events" member points to a list of inactive events to be made
|
||||
* active as a group. Update events go into this list.
|
||||
*
|
||||
* The "nonblock" member points to a list of events to be executed
|
||||
* only after ordinary events run out. This is intended to support the
|
||||
* semantics of nonblocking assignment.
|
||||
*/
|
||||
struct vvm_simulation_cycle {
|
||||
unsigned long delay;
|
||||
|
||||
struct vvm_simulation_cycle*next;
|
||||
struct vvm_simulation_cycle*prev;
|
||||
|
||||
struct vvm_event*event_list;
|
||||
struct vvm_event*event_last;
|
||||
struct vvm_event*nonblock_list;
|
||||
struct vvm_event*nonblock_last;
|
||||
|
||||
vvm_simulation_cycle()
|
||||
: event_list(0), event_last(0), nonblock_list(0),
|
||||
nonblock_last(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
vvm_simulation::vvm_simulation()
|
||||
{
|
||||
sim_ = new vvm_simulation_cycle;
|
||||
sim_->delay = 0;
|
||||
sim_->next = sim_->prev = sim_;
|
||||
mon_ = 0;
|
||||
}
|
||||
|
||||
vvm_simulation::~vvm_simulation()
|
||||
{
|
||||
}
|
||||
|
||||
void vvm_simulation::insert_event(unsigned long delay, vvm_event*event)
|
||||
void vvm_simulation::monitor_event(vvm_event*)
|
||||
{
|
||||
vvm_simulation_cycle*cur = sim_->next;
|
||||
|
||||
while ((cur != sim_) && (cur->delay < delay)) {
|
||||
delay -= cur->delay;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
|
||||
if ((cur == sim_) || (cur->delay > delay)) {
|
||||
vvm_simulation_cycle*cell = new vvm_simulation_cycle;
|
||||
cell->delay = delay;
|
||||
if (cur != sim_)
|
||||
cur->delay -= delay;
|
||||
cell->next = cur;
|
||||
cell->prev = cur->prev;
|
||||
cell->next->prev = cell;
|
||||
cell->prev->next = cell;
|
||||
cur = cell;
|
||||
}
|
||||
|
||||
event->next_ = 0;
|
||||
if (cur->event_list == 0) {
|
||||
cur->event_list = cur->event_last = event;
|
||||
|
||||
} else {
|
||||
cur->event_last->next_ = event;
|
||||
cur->event_last = event;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvm_simulation::monitor_event(vvm_event*event)
|
||||
void vvm_simulation::insert_event(unsigned long delay, vvm_event*event)
|
||||
{
|
||||
mon_ = event;
|
||||
event->event_ = vpip_sim_insert_event(delay, event,
|
||||
vvm_event::callback_, 0);
|
||||
}
|
||||
|
||||
void vvm_simulation::active_event(vvm_event*event)
|
||||
{
|
||||
event->next_ = 0;
|
||||
if (sim_->event_list == 0) {
|
||||
sim_->event_list = sim_->event_last = event;
|
||||
|
||||
} else {
|
||||
sim_->event_last->next_ = event;
|
||||
sim_->event_last = event;
|
||||
}
|
||||
event->event_ = vpip_sim_insert_event(0, event,
|
||||
vvm_event::callback_, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -121,68 +57,7 @@ void vvm_simulation::active_event(vvm_event*event)
|
|||
*/
|
||||
void vvm_simulation::run()
|
||||
{
|
||||
assert(sim_);
|
||||
time_ = 0;
|
||||
going_ = true;
|
||||
|
||||
while (going_) {
|
||||
|
||||
/* Step the time forward to the cycle I am about to
|
||||
execute. */
|
||||
time_ += sim_->delay;
|
||||
sim_->delay = 0;
|
||||
|
||||
while (going_) {
|
||||
/* Look for some events to make active. If the
|
||||
main event list is empty, then activate the
|
||||
nonblock list. */
|
||||
vvm_event*active = sim_->event_list;
|
||||
sim_->event_list = 0;
|
||||
sim_->event_last = 0;
|
||||
|
||||
if (active == 0) {
|
||||
active = sim_->nonblock_list;
|
||||
sim_->nonblock_list = 0;
|
||||
sim_->nonblock_last = 0;
|
||||
}
|
||||
|
||||
/* Oops, no events left. Break out of this time cycle. */
|
||||
if (active == 0)
|
||||
break;
|
||||
|
||||
while (active && going_) {
|
||||
vvm_event*cur = active;
|
||||
active = cur->next_;
|
||||
cur->event_function();
|
||||
delete cur;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the simulation was stopped by one of the events,
|
||||
then break out of the loop before doing any monitor
|
||||
events, and before clearing the current time. */
|
||||
if (!going_)
|
||||
break;
|
||||
|
||||
/* XXXX Execute monitor events here. */
|
||||
if (mon_) {
|
||||
mon_->event_function();
|
||||
mon_ = 0;
|
||||
}
|
||||
|
||||
/* The time cycle is done, delete it from the list and
|
||||
step to the next time. */
|
||||
struct vvm_simulation_cycle*next = sim_->next;
|
||||
if (next == sim_) {
|
||||
going_ = false;
|
||||
break;
|
||||
}
|
||||
|
||||
sim_->next->prev = sim_->prev;
|
||||
sim_->prev->next = sim_->next;
|
||||
delete sim_;
|
||||
sim_ = next;
|
||||
}
|
||||
vpip_simulation_run();
|
||||
}
|
||||
|
||||
class delay_event : public vvm_event {
|
||||
|
|
@ -194,15 +69,6 @@ class delay_event : public vvm_event {
|
|||
vvm_thread*thr_;
|
||||
};
|
||||
|
||||
void vvm_simulation::s_finish()
|
||||
{
|
||||
going_ = false;
|
||||
}
|
||||
|
||||
bool vvm_simulation::finished() const
|
||||
{
|
||||
return !going_;
|
||||
}
|
||||
|
||||
void vvm_simulation::thread_delay(unsigned long delay, vvm_thread*thr)
|
||||
{
|
||||
|
|
@ -219,6 +85,12 @@ void vvm_simulation::thread_active(vvm_thread*thr)
|
|||
|
||||
/*
|
||||
* $Log: vvm_simulation.cc,v $
|
||||
* Revision 1.7 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.6 1999/10/06 01:28:18 steve
|
||||
* The $finish task should work immediately.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue