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:
steve 1999-10-28 00:47:24 +00:00
parent 8bad04a020
commit d6450599d6
23 changed files with 1611 additions and 823 deletions

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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
*

View File

@ -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

90
vvm/vpi_callback.c Normal file
View File

@ -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.
*
*/

70
vvm/vpi_const.c Normal file
View File

@ -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.
*
*/

77
vvm/vpi_iter.c Normal file
View File

@ -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.
*
*/

47
vvm/vpi_null.c Normal file
View File

@ -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.
*
*/

160
vvm/vpi_priv.c Normal file
View File

@ -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.
*
*/

View File

@ -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.
*

286
vvm/vpi_signal.c Normal file
View File

@ -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.
*
*/

205
vvm/vpi_simulation.c Normal file
View File

@ -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.
*
*/

56
vvm/vpi_systask.c Normal file
View File

@ -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.
*
*/

84
vvm/vpi_time.c Normal file
View File

@ -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
View File

@ -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=.
*

View File

@ -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).

View File

@ -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)
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*