Compare commits

...

10 Commits

Author SHA1 Message Date
2d37af1ac4 增加关于一键更新相关的说明 2025-04-06 17:09:43 +08:00
1f681e62bd 添加一键更新脚本 2025-04-06 16:58:05 +08:00
c87cd667bb 支持添加自定义dns解析 2025-04-06 16:04:28 +08:00
80c9c0be0f add 00_func_return 2025-03-05 11:39:16 +08:00
903d50d4d8 增加pli的书和源代码 2025-03-04 09:56:46 +08:00
bd4cc71c66 增加对系统版本的监测 2024-12-25 10:18:50 +08:00
688cf86133 增加template 2024-12-23 09:59:41 +08:00
18686957fd 删除重复的import 2024-12-10 10:48:03 +08:00
52dc9fe682 配置分离,增加更多dns服务器 2024-12-10 10:47:35 +08:00
7cc9aad0a6 add me241103_cRe 2024-12-09 16:06:47 +08:00
443 changed files with 25554 additions and 16 deletions

14
.gitignore vendored
View File

@ -1,7 +1,5 @@
4_c_re
5_vpi
sv_lab
.vscode/
sv_lab
me241200_zerotierApi/env/
@ -37,4 +35,12 @@ me241102_vpi/ucli.key
me241102_vpi/vc_hdrs.h
me241102_vpi/wave.fsdb
me241102_vpi/*.o
me241102_vpi/*.so
me241102_vpi/*.so
me241103_cRe/main
me250300_pli/00_func_return/vcsworks/
me250300_pli/00_func_return/verdiLog/
me250300_pli/00_func_return/novas.conf
me250300_pli/00_func_return/novas.rc
me250300_pli/00_func_return/*.swp

View File

@ -9,5 +9,6 @@ script work是一系列自己编选的脚本合集。
| [me241100_svExample](./me241100_svExample) | 使用vcs编译sv的简单例子 | 100% | | |
| [me241201_dpi](./me241101_dpi) | 使用vcs编译dpi的简单例子 | 100% | [PLI 学习](https://www.cnblogs.com/fengbohan/p/18595069/pli-learning-zx6kpe) | |
| [me241102_vpi](./me241102_vpi) | 使用vcs编译vpi的简单例子 | 100% | [PLI 学习](https://www.cnblogs.com/fengbohan/p/18595069/pli-learning-zx6kpe) | |
| [me241103_cRe](./me241103_cRe) | 使用c语言进行正则匹配的例子 | 100% | | |
| [me241200_zerotierApi](./me241200_zerotierApi) | 使用zerotier的api获取网络信息生成smartdns的配置文件 | 100% | | |

View File

@ -1,7 +1,22 @@
LSB_RELEASE = $(shell lsb_release -is)
LSB_VERSION = $(shell lsb_release -rs)
ifeq (${LSB_RELEASE}, Ubuntu)
ifeq ($(shell echo "${LSB_VERSION}>18.04" | bc), 1)
CC = gcc-4.8
CPP = g++-4.8
else
CC = gcc
CPP = g++
endif
else
CC = gcc
CPP = g++
endif
comp_c:
- gcc -fPIC -shared -o libfunc.so func.c -I ${VCS_HOME}/include
comp:
- vcs -full64 +v2k -sverilog -LDFLAGS -Wl,--no-as-needed \
- vcs -full64 +v2k -sverilog -LDFLAGS -Wl,--no-as-needed -cc $(CC) -cpp $(CPP)\
-P ${VERDI_HOME}/share/PLI/VCS/LINUX64/novas.tab ${VERDI_HOME}/share/PLI/VCS/LINUX64/pli.a \
-P ./func.tab \
+vcs+fsdbon -debug_access+all \

2
me241103_cRe/Makefile Normal file
View File

@ -0,0 +1,2 @@
main:
gcc -o main main.c

22
me241103_cRe/ReadMe.md Normal file
View File

@ -0,0 +1,22 @@
# cRE
## 概述
使用c语言进行正则表达式的例子。
## 快速开始
### 一、编译
```bash
make
```
### 二、运行
```bash
./main
```

44
me241103_cRe/main.c Normal file
View File

@ -0,0 +1,44 @@
#include <stdio.h>
#include <regex.h>
#define MAX_MATCHES 10
void extract_numbers(const char *text) {
regex_t regex;
regmatch_t matches[MAX_MATCHES];
const char *pattern = "[0-9]+";
int ret;
ret = regcomp(&regex, pattern, REG_EXTENDED);
if (ret != 0) {
char error_message[100];
regerror(ret, &regex, error_message, sizeof(error_message));
printf("Regex compilation error: %s\n", error_message);
return;
}
while (1) {
ret = regexec(&regex, text, MAX_MATCHES, matches, 0);
if (ret != 0) {
break;
}
for (int i = 0; i < MAX_MATCHES && matches[i].rm_so != -1; i++) {
int start = matches[i].rm_so;
int end = matches[i].rm_eo;
printf("Match found: %.*s\n", end - start, text + start);
}
printf("%s\n", text);
text += matches[0].rm_eo;
}
regfree(&regex);
}
int main() {
const char *text = "abc123xyz456";
extract_numbers(text);
return 0;
}

View File

@ -19,8 +19,15 @@ pip install -r requirements.txt
```bash
python main.py
```
打印当前网络的节点信息,并在当前目录下产生文件`smartdns.conf`
### 三、一键更新
```bash
./up_nas_conf.sh
```
可以自动生成`smartdns.conf`的配置文件上传到群晖NAS然后重启容器。
- 需要提前设置ssh密钥登陆否则要手动输入密码
- 确保登录用户具有执行docker的权限sudo需要添加`fengbohan ALL=(ALL) NOPASSWD: ALL` 到文件`/etc/sudoers.d/main`

View File

@ -1,19 +1,46 @@
import requests
import json
token = 'UPmCF82KqqqWghdlnhfUaQ4Kp24c6qth'
networkId = 'af78bf94361850a3'
domainSuffix = 'fbh'
headers={
'Authorization': 'token UPmCF82KqqqWghdlnhfUaQ4Kp24c6qth'
'Authorization': f"token {token}"
}
url=' https://api.zerotier.com/api/v1/network/af78bf94361850a3/member'
url=f"https://api.zerotier.com/api/v1/network/{networkId}/member"
param = {}
response = requests.get(url=url,params=param,headers=headers) #三个参数
memberData = json.loads(response.text)
with open("smartdns.conf", '+w') as f:
f.write(f"bind [::]:53\n")
f.write(f"server 192.168.3.1\n")
# 谷歌
f.write(f"server 8.8.8.8\n")
f.write(f"server 8.8.4.4\n")
# cloudflare
f.write(f"server 1.1.1.1\n")
f.write(f"server 1.0.0.1\n")
# 114
f.write(f"server 114.114.114.114\n")
# baidu
f.write(f"server 180.76.76.76\n")
# 腾讯
f.write(f"server 119.29.29.29\n")
f.write(f"server 119.28.28.28\n")
# 阿里
f.write(f"server 223.5.5.5\n")
f.write(f"server 223.6.6.6\n")
# 字节
f.write(f"server 180.184.1.1\n")
f.write(f"server 180.184.2.2\n")
for i in memberData:
config=i['config']
print(f"id: {config['id']};\tname: {i['name']};\tdescription: {i['description']};\tip: {config['ipAssignments']}")
f.write(f"address /{i['name']}.fbh/{','.join(config['ipAssignments'])}\n")
f.write(f"address /{i['name']}.{domainSuffix}/{','.join(config['ipAssignments'])}\n")
with open("user.json", '+r') as f2:
userData = json.load(f2)
for i in userData:
print(f"name: {i['name']};\tip: {i['ip']}")
f.write(f"address /{i['name']}/{i['ip']}\n")

View File

@ -1,6 +1,5 @@
certifi==2024.8.30
charset-normalizer==2.0.12
certifi==2025.1.31
charset-normalizer==3.4.1
idna==3.10
pkg-resources==0.0.0
requests==2.27.1
urllib3==1.26.20
requests==2.32.3
urllib3==2.3.0

View File

@ -1,8 +1,21 @@
bind [::]:53
server 192.168.3.1
server 8.8.8.8
server 8.8.4.4
server 1.1.1.1
server 1.0.0.1
server 114.114.114.114
server 180.76.76.76
server 119.29.29.29
server 119.28.28.28
server 223.5.5.5
server 223.6.6.6
server 180.184.1.1
server 180.184.2.2
address /main.fbh/192.168.193.24
address /fby.fbh/192.168.193.102
address /honor.fbh/192.168.193.52
address /pad.fbh/192.168.193.118
address /r2s.fbh/192.168.193.20
address /home.fbh/192.168.193.224
address /bak.fbh/192.168.193.36
address /test.fbh/192.168.193.14
@ -10,3 +23,5 @@ address /gs.fbh/192.168.193.101
address /tg.fbh/192.168.193.37
address /phone.fbh/192.168.193.193
address /nas.fbh/192.168.193.7
address /fengbohan.top/192.168.3.7
address /main.fengbohan.top/192.168.3.6

View File

@ -0,0 +1,18 @@
#!/bin/bash
# 更新NAS上的smartdns配置文件自动重启容器
source ./env/bin/activate
echo "-----------------"
echo "-- 生成smartdns配置文件--"
echo "-----------------"
python main.py
echo "-----------------"
echo "-- 更新NAS上的smartdns配置文件--"
echo "-----------------"
scp ./smartdns.conf fengbohan@nas.fbh:/volume2/docker/smartdns/smartdns.conf
echo "-----------------"
echo "-- 重启容器--"
echo "-----------------"
ssh -t fengbohan@nas.fbh "sudo /usr/local/bin/docker restart bdbe37609e7c"
echo "-----------------"
echo "-- 更新完成--"
echo "-----------------"

View File

@ -0,0 +1,10 @@
[
{
"name": "fengbohan.top",
"ip": "192.168.3.7"
},
{
"name": "main.fengbohan.top",
"ip": "192.168.3.6"
}
]

View File

@ -0,0 +1,33 @@
LSB_RELEASE = $(shell lsb_release -is)
LSB_VERSION = $(shell lsb_release -rs)
ifeq (${LSB_RELEASE}, Ubuntu)
ifeq ($(shell echo "${LSB_VERSION}>18.04" | bc), 1)
CC = gcc-4.8
CPP = g++-4.8
else
CC = gcc
CPP = g++
endif
else
CC = gcc
CPP = g++
endif
comp_c:
- gcc -fPIC -shared -o ./vcsworks/libfunc.so func.c -I ${VCS_HOME}/include
comp: comp_c
- pushd ./vcsworks && vcs -full64 +v2k -sverilog -LDFLAGS -Wl,--no-as-needed -cc $(CC) -cpp $(CPP)\
-P ${VERDI_HOME}/share/PLI/VCS/LINUX64/novas.tab ${VERDI_HOME}/share/PLI/VCS/LINUX64/pli.a \
-P ../func.tab \
+vcs+fsdbon -debug_access+all -kdb\
-top testbench -l compile.log -timescale=1ns/1ps\
../testbench.sv && popd
sim:
- pushd vcsworks && ./simv -l sim.log +fsdbfile+wave.fsdb -load ./libfunc.so -ucli -do ../func.tcl && popd
verdi:
- verdi -ssf wave.fsdb -sswr signal.rc &
clean:
- \rm -rf vcsworks/*

View File

@ -0,0 +1,27 @@
# 获取call的返回值
## 概述
使用call调用pli编写的function, 尝试获取function的返回值。
## 快速开始
### 一、编译
```bash
make comp
```
### 二、运行
```bash
make sim
```
### 三、结果
在sv中可以正常获取函数的返回值但是在tcl中使用call命令只能获取INT整数值。
按16进制转10进制然后查ASCII表可以转换成字符串。
*在公司服务器使用vcs2020.03无法复现。call命令获得的INT整数值全是0*

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <vpi_user.h>
void get_arg(PLI_BYTE8 *user_data)
{
// 变量定义
s_vpi_value value_s;
vpiHandle systf_handle, arg_iter, arg_handle;
// 获取函数调用的句柄
systf_handle = vpi_handle(vpiSysTfCall, NULL);
// 从句柄中获取参数迭代器
arg_iter = vpi_iterate(vpiArgument, systf_handle);
if(arg_iter == NULL){
vpi_printf("ERROR: failed to obtain systf arg handles\n");
vpi_control(vpiFinish, 1); /* abort simulation */
return;
}
// 迭代获取第一个参数
arg_handle = vpi_scan(arg_iter);
value_s.format = vpiStringVal;
vpi_get_value(arg_handle, &value_s);
PLI_BYTE8 *arg1 = value_s.value.str;
// 释放迭代器
vpi_free_object(arg_iter); /* because not scanning until null */
vpi_printf("arg[1] = %s", arg1);
/* write result to simulation as return value $pow */
value_s.format = vpiStringVal;
value_s.value.str = arg1;
vpi_put_value(systf_handle, &value_s, NULL, vpiNoDelay);
return;
}

View File

@ -0,0 +1 @@
$get_arg call=get_arg size=88

View File

@ -0,0 +1,18 @@
config cmdecho off
proc hex_to_ascii {hex_str} {
set result ""
foreach hex_pair [regexp -all -inline {..} $hex_str] {
set decimal [expr 0x$hex_pair]
set char [format %c $decimal]
append result $char
}
return $result
}
set str [call {$get_arg("Hello world")}]
puts "\ntcl str = $str"
set str_t [hex_to_ascii $str]
puts "\ntcl str_t = $str_t"

View File

@ -0,0 +1,7 @@
module testbench;
string str;
initial begin
str = $get_arg("Hello world");
$display("\nstr = %s", str);
end
endmodule

9
me250300_pli/ReadMe.md Normal file
View File

@ -0,0 +1,9 @@
# pli
pli是一系列学习pli的项目合集。
## 项目列表
| 项目 | 描述 | 状态 | 博客 | 备注 |
| ---------------------------------------------- | ----------------------------------------------------- | ---- | ------------------------------------------------------------ | ---- |
| [00_func_return](./00_func_return) | 在ucli中使用call获取PLI函数的返回值 | 100% | | |

Binary file not shown.

View File

@ -0,0 +1,12 @@
TARGETS:
cd util; make
cd vpi; make
cd pli; make
clean:
cd util; make clean
cd vpi; make clean
cd pli; make clean
rm -f lib/*

View File

@ -0,0 +1,18 @@
ARCHDEBUG = -g
ARCHLIBFLAGS =
ARCHEXT = o
ARCHEXE =
ARCHCFLAGS = +Z -Aa -Ae
ARCHDEFINES =
ARCHDYNEXT = sl
ARCHDYNEXTL = sl
ARCLIB = a
ARCHDYNLD = -b
ARCHLDFLAG = -l
ARCHLDOUT = -o
ARCHCCOUT = -o
ARCHDYNLIB = -lm
ARCHPLILIB =
RM = rm
LD = ld

View File

@ -0,0 +1,15 @@
ARCHDEBUG = -g
ARCHLIBFLAGS =
ARCHEXT = o
ARCHEXE =
ARCHCFLAGS = -fPIC -Wall
ARCHDEFINES =
ARCHDYNEXT = so
ARCHDYNEXTL = so
ARCLIB = a
ARCHDYNLD = -G -export-dynamic
ARCHLDFLAG = -l
ARCHLDOUT = -o
ARCHCCOUT = -o
ARCHDYNLIB = -lm
ARCHPLILIB =

View File

@ -0,0 +1,15 @@
ARCHDEBUG = -g -xs
ARCHLIBFLAGS = -lsocket -lnsl
ARCHEXT = o
ARCHEXE =
ARCHCFLAGS = -KPIC
ARCHDEFINES = -DSUN4V
ARCHDYNEXT = so
ARCHDYNEXTL = so
ARCLIB = a
ARCHDYNLD = -G
ARCHLDFLAG = -l
ARCHLDOUT = -o
ARCHCCOUT = -o
ARCHDYNLIB = -lm
ARCHPLILIB =

View File

@ -0,0 +1,18 @@
MSD = ${MSDIR}\VC
ARCHDEBUG =
ARCHLIBFLAGS = wsock32.lib kernel32.lib
ARCHEXT = obj
ARCHEXE = .exe
ARCHCFLAGS = -I${MSD}\include
ARCHDEFINES = -DWINNT
ARCHDYNEXT = dll
ARCHDYNEXTL = lib
ARCLIB = a
ARCHDYNLD = /dll /pdb:none /debug
ARCHLDFLAG = lib
ARCHLDOUT = /out:
ARCHCCOUT = /Fe
ARCHDYNLIB = /libpath:${MSD}\lib wsock32.lib kernel32.lib
ARCHLDDYNEXT = .lib
ARCHPLILIB = ${PLILIB}

View File

@ -0,0 +1,67 @@
To be able to build and run these examples you will need to set two
environment variables, ARCH and PLIINC
ARCH - must be set to one of the following
linux for a pc running linux
sun4v for a solaris machine
hppa for a HP PA-RISK machine
winnt for either Win-95/98 or WINNT
PLIINC - must be set to contain the path to where the different PLI
include files are stored.
Windows (Win95/Win98/WinNT) need two other environment variabels set
MSDIR - Path to the microsoft compilier. ex D:/msdev/DevStudio
PLILIB - Path to the simulator's import library
ex:
d:/XYZ/tools/verilog/lib/verilog.lib (VerilogXL)
or
d:/XYZ/tools/lib/pliinterface.lib (NC-Verilog)
or
...
NOTE: The assumption is that you are running in something like the
MKS corn shell and have a real make installed in you search
path. Sorry I am a UNIX bigot at heart. Also seeing that I
was able to make one command "make" work on four different
platforms consistency was a good thing.
To get started type:
make
This will walk down to the util directory and build the different
common utility(s) that will be used by the different example(s). When
the build is completed the required libraries/objects will be copied
into the ./lib directory and the required include files into the
directory ./include.
It will then walk into the different PLI example directory(s) and build
the PLI/VPI code used by the exmple(s).
At this point you can cd to the directory vpi or pli /<example> and
read the file "README" in the given directory.
When you are done playing around and want to clean up you can type
make clean
from this directory. All the generated file will be removed.
**********************************************************************
All the include/Makefile/*.c/*.h files in this directory and lower
directories are free for the taking with no restriction on their usage
being imposed and or implied. While some testing has been done to
make sure the basic functionality works no guarantees are being made
either.
enjoy

View File

@ -0,0 +1,24 @@
=======================================================================
COPYRIGHTS AND OWNERSHIP AND DISCLAIMERS:
The electronic text files in the directory "socket_example_PC" are
provided by David Roberts. These files are provided with no
restrictions on usage, copying or distribution. David Roberts, and
Sutherland HDL, Inc. shall not be liable for damage in connection
with, or arising out of, the furnishing, performance or use of this
information.
This directory contains an example of using sockets to communicate
between a PLI application and another C program. This example was
created by David Roberts. Stuart Sutherland and Sutherland HDL have
no involvement in this example, beyond including the example with
the CD which accompanies "The PLI Handbook" by Stuart Sutherland.
Sutherland HDL includes this example on its web site for informational
purposes only. We hope you find the example useful in learning and
understanding the very complex topic of the Verilog Programming
Language Interface!
Stu Sutherland
=======================================================================

View File

@ -0,0 +1,16 @@
/*
* Use this to export symbols on the Windows Ports
*/
#ifdef WINNT
#ifdef EXPDEF
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
#define DECLEXP __declspec(dllexport)
#define DECLIMP __declspec(dllimport)
#else
#define DECLSPEC
#define DECLEXP
#define DECLIMP
#endif

View File

@ -0,0 +1,12 @@
/*
* Use this to export symbols on the Windows Ports
*/
#ifdef WIN32
#ifdef EXPDEF
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
#else
#define DECLSPEC
#endif

View File

@ -0,0 +1,66 @@
/*
* Make sure to import or export the library functions if we are running
* under windows (Win95/98 or WinNT)
*
* HP also has a default mode where we can TAG which symbols are to be
* exported.
*
* Project do the same for the HP port and remove the
*
*/
/*
* Get a line of data from the socket.
* If the arg "nb" is non 0 then do not block if there is no data.
*/
DECLSPEC
char *sockGetLine(int fd, int nb);
/*
* Put a line of data to the socket.
*/
DECLSPEC
int sockPutLine(int fd, char *buf);
/*
* Make a client socket connection to the specified port and host.
*
* A value of -1 will be returned if an error is detected.
*/
DECLSPEC
int sockMakeClient(int port, char *host);
/*
* Make server to accept a connection. If block is non zero the call will
* block socket blocking.
*
* A value of -1 will be returned if an error is detected.
*/
DECLSPEC
int sockMakeServer(int port, int block);
/*
* Accept a connection on a socket created by sockMakeServer. If the
* socket was created with blocking then the call will block until somebody
* connects to the socket.
*
* If there was a connection was made the point to a char * will contain
* the string identifying who made the connection.
*
* A value of -1 will be returned if an error is detected.
*/
DECLSPEC
int sockAcceptServer(int listener, char **who);
/*
* Shut a server socket down.
*/
DECLSPEC
void sockCloseServer(int fd, int listener);
/*
* Get the text for the last error generated from a call to the socket
* utility.
*/
DECLSPEC
char *sockGetLastError();

View File

@ -0,0 +1,6 @@
TARGETS:
cd dispargs; make
clean:
cd dispargs; make clean

View File

@ -0,0 +1,46 @@
UTILNAME = dispargs
BASEDIR = ../..
include ${BASEDIR}/Makefile.${ARCH}
UTILLIBS =
INCDIRS = -I${BASEDIR}/include -I${PLIINC}
#DFLAGS = ${ARCHDEBUG}
DFLAGs =
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${DFLAGS} ${ARCHGNU} ${INCDIRS}
TARGETS = \
${PLILIBS}
PLIOBJ = dispargs.${ARCHEXT}
PLILIBS = dispargs.${ARCHDYNEXT}
CFILES = \
${MODEL.${ARCHEXT}=.c}
.c.${ARCHEXT}:
$(CC) -c $< ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
target: ${TARGETS}
dispargs.${ARCHDYNEXT}: dispargs.${ARCHEXT}
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}dispargs.${ARCHDYNEXT} dispargs.${ARCHEXT} ${ARCHPLILIB} ${ARCHLIBFLAGS}
TAGS: ${CFILES} ${HFILES}
etags -tTa ${HFILES} ${CFILES}
clean:
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* *.log *.key ${TARGETS}
ship:
-$(RM) ${UTILNAME}.tar.gz
tar -cvf ${UTILNAME}.tar Makefile ${CFILES} ${HFILES}
gzip ${UTILNAME}.tar
depend:
makedepend ${INCDIRS} ${CFILES}
# DO NOT DELETE

View File

@ -0,0 +1,7 @@
This example will dump all the command line arguments. It will also
dump out the contents of any -f <file> being used.
To run the test case:
<simulator> -f run.vc

View File

@ -0,0 +1,93 @@
#include <stdio.h>
#include "veriuser.h"
#include "vxl_veriuser.h"
#include "acc_user.h"
#include "com_exp.h"
int indent = 5;
static void processFileArgs(char **args)
{
int cnt;
io_printf(" %s\n", *args++);
indent += 5;
while(*args != NULL)
{
for (cnt=0;cnt<indent;cnt++)
{
io_printf(" ");
}
io_printf("%s", *args);
if (strcmp("-f", *args) == 0)
{
args++;
cnt++;
processFileArgs(((char **)*args));
}
else
{
io_printf("\n");
}
args++;
}
indent -= 5;
}
static int dispArgs(int data, int reason)
{
int cnt;
char **args;
int numArgs;
args = acc_fetch_argv();
numArgs = acc_fetch_argc();
io_printf("Commandline args used by the simulator: %s\n", *args);
args++;
for (cnt=1;cnt<numArgs;cnt++)
{
io_printf(" %s", *(args));
if (strcmp("-f", *args) == 0)
{
args++;
cnt++;
processFileArgs(((char **)*args));
}
else
{
io_printf("\n");
}
args++;
}
io_printf("\n\n");
return(0);
}
/*
* boot strap for
*
* +loadpli1=dispargs:regDispArgs
* or
* -loadpli1 dispargs:regDispArgs
*
* If using the old veriusertfs method cut and paste the first line
* below into your veriuserts array.
*
*/
static s_tfcell tfTasks[] =
{
{usertask, 0, NULL, NULL, dispArgs, NULL, "$dumpargs", 1},
{0}
};
DECLEXP
p_tfcell regDispArgs()
{
return(&tfTasks[0]);
}

View File

@ -0,0 +1,4 @@
-q
test.v
-f test1.vc
+loadpli1=./dispargs:regDispArgs

View File

@ -0,0 +1,7 @@
module top;
wire a;
initial
$dumpargs;
endmodule

View File

@ -0,0 +1,5 @@
+a
+b
+c
+d
-f test2.vc

View File

@ -0,0 +1,3 @@
+a2
+b2
+c2

View File

@ -0,0 +1,6 @@
TARGETS:
cd socket; make; make install
clean:
cd socket; make clean

View File

@ -0,0 +1,59 @@
UTILNAME = socketUtil
BASEDIR = ../..
include ${BASEDIR}/Makefile.${ARCH}
INCDIRS =
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${ARCHDEBUG} -I${BASEDIR}/include
SOCKETUTIL = \
socketUtil.${ARCHEXT}
SOCKETLIB = libSocketUtil.${ARCHDYNEXT}
SOCKETINC = socketUtil.h
INCS = \
${SOCKETINC}
LIBS = \
${SOCKETLIB}
TARGETS = \
${LIBS}
CFILES = \
${SOCKETUTIL:.${ARCHEXT}=.c}
HFILES = \
socketUtil.h
.c.${ARCHEXT}:
$(CC) -c $< -o $*.${ARCHEXT} ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
all: ${TARGETS}
install: ${TARGETS}
cp ${LIBS} *.${ARCHDYNEXTL} ${BASEDIR}/lib
cp ${INCS} ${BASEDIR}/include
${SOCKETLIB}: ${SOCKETUTIL}
-$(RM) ${SOCKETLIB}
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}${SOCKETLIB} ${SOCKETUTIL} ${ARCHLIBFLAGS}
TAGS: ${CFILES} ${HFILES}
etags -tTa ${HFILES} ${CFILES}
clean:
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* ${TARGETS}
ship:
-$(RM) ${UTILNAME}.tar.gz
tar -cvf ${UTILNAME}.tar Makefile* ${CFILES} ${HFILES}
gzip ${UTILNAME}.tar
depend:
makedepend ${INCDIRS} ${CFILES}
# DO NOT DELETE THIS LINE -- make depend depends on it.

View File

@ -0,0 +1,8 @@
A general purpose utility to send/receive string data from different
machines using sockets.
To do:
Add a mode to the utility that uses the datagram level of sockets.
This sould be much faster the the present stream mode.

View File

@ -0,0 +1,326 @@
#define SOCKUTIL_C
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#ifndef WINNT
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#if defined(SUN4V)
#include <sys/file.h>
#endif
#else
#include <winsock.h>
#endif
#include <errno.h>
#include <string.h>
#define EXPDEF
#include "com_exp.h"
#include "socketUtil.h"
#undef EXPDEF
static char sockErrBuffer[1024];
static int initSocketInterface = 1; /* Initialize the socket environ if needed */
static int initSocket()
{
#ifdef WINNT
WORD wVersionRequested;WSADATA wsaData;int err;
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
/* Tell the user that we couldn't find a usable */
/* WinSock DLL. */
return(1);
}
/* Confirm that the WinSock DLL supports 2.0.*/
/* Note that if the DLL supports versions greater */
/* than 2.0 in addition to 2.0, it will still return */
/* 2.0 in wVersion since that is the version we */
/* requested. */
#if 0
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 )
{
/* Tell the user that we couldn't find a usable */
/* WinSock DLL. */
WSACleanup( );
return(1);
}
#endif
#endif
/* The WinSock DLL is acceptable. Proceed. */
return(0);
}
static struct sockaddr *mkSockAddr(unsigned int port, char *host)
{
static struct hostent *hp = NULL;
static struct sockaddr_in addrIn;
memset(&addrIn, 0, sizeof(addrIn));
/* If !host do not tie socket to a machine name */
if (host)
{
hp = gethostbyname(host);
if (!hp)
{
sprintf(&sockErrBuffer[0], "failed to aquire host info!\n");
return(NULL);
}
else
{
memcpy(&addrIn.sin_addr, hp->h_addr, hp->h_length);
addrIn.sin_family = hp->h_addrtype;
}
}
addrIn.sin_family = AF_INET;
addrIn.sin_port = htons((unsigned short)port);
return((struct sockaddr *)&addrIn);
}
int sockMakeClient(int port, char *host)
{
int fd;
struct sockaddr *servAddr;
int fdCon;
char *defaultHost = "localhost";
if (!host)
host = defaultHost;
if (initSocketInterface)
{
if (initSocket())
{
sprintf(&sockErrBuffer[0], "Sorry could not initialize the SOCKET interfacen!\n");
return(-1);
}
initSocketInterface=0;
}
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
{
#ifdef WINNT
int errorCode = WSAGetLastError();
sprintf(&sockErrBuffer[0], "ERROR code was: %d\n", errorCode);
#endif
sprintf(&sockErrBuffer[0], "Sorry barfed on creating a socket!\n%s\n",
strerror(errno));
return(-1);
}
servAddr = mkSockAddr(port, host);
if (!servAddr)
{
return(-1); /* Unable to grab the socket */
}
fdCon = connect(fd, servAddr, sizeof(struct sockaddr));
if (fdCon < 0)
{
return(-1);
}
return(fd);
}
int sockMakeServer(int port, int block)
{
int fd;
struct sockaddr *servAddr;
int retVal;
if (initSocketInterface)
{
if (initSocket())
{
sprintf(&sockErrBuffer[0], "Sorry could not initialize the SOCKET interfacen!\n");
return(-1);
}
initSocketInterface=0;
}
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
{
#ifdef WINNT
int errorCode = WSAGetLastError();
sprintf(&sockErrBuffer[0], "ERROR code was: %d\n", errorCode);
#endif
sprintf(&sockErrBuffer[0], "Sorry barfed on creating a socket!\n%s\n",
strerror(errno));
return(-1);
}
/* See if we need to make in non blocking */
if (!block)
{
#ifndef WINNT
if (fcntl(fd, F_SETFL, FNDELAY))
{
sprintf(&sockErrBuffer[0], "blocking was requested but could be granted!\n");
return(-1);
}
#endif
}
servAddr = mkSockAddr(port, NULL);
if (!servAddr)
{
return(-1);
}
retVal = bind(fd, servAddr, sizeof(struct sockaddr));
if (retVal != 0)
{
switch(errno)
{
case EBADF:
sprintf(&sockErrBuffer[0], "Server: bad sockfd!\n");
break;
case EINVAL:
sprintf(&sockErrBuffer[0], "Server: socket already bound!\n");
break;
default:
sprintf(&sockErrBuffer[0], "Server Failed to bind to a socket: %s!\n", strerror(errno));
break;
}
return(-1);
}
retVal = listen(fd, 100);
if (retVal != 0)
{
sprintf(&sockErrBuffer[0], "Server Failed to listen to a socket!\n");
return(-1);
}
return(fd);
}
int sockAcceptServer(int listener, char **who)
{
struct sockaddr servAddr;
int clientSize = sizeof(struct sockaddr);
int fd;
static char *buffer = NULL;
static int bufLen = 0;
fd = accept(listener, &servAddr, &clientSize);
if (who)
{
*who = NULL;
if (clientSize >=0)
{
/* See if we can figure out who has connected */
if (fd >=0)
{
struct hostent *hs;
hs = gethostbyaddr(
((char *) &((struct sockaddr_in *)&servAddr)->sin_addr.s_addr),
sizeof(long), AF_INET);
if (hs && hs->h_name)
{
if ((strlen(hs->h_name)+1) > bufLen)
{
bufLen = strlen(hs->h_name)+1;
buffer = malloc(bufLen);
}
strcpy(buffer, hs->h_name);
*who = buffer;
}
}
}
}
return(fd);
}
void sockCloseServer(int fd, int listener)
{
close(fd);
close(listener);
}
int sockPutLine(int fd, char *buf)
{
int retVal = 0;
static int stdTestOut = -1;
if (stdTestOut == -1)
stdTestOut = fileno(stdout);
if (fd == stdTestOut)
{
write(stdTestOut, buf, strlen(buf)+1);
}
else
{
retVal = send(fd, buf, strlen(buf)+1, 0);
}
return(retVal);
}
char *sockGetLine(int fd, int nb)
{
static char buffer[1024];
int cnt;
int status;
fd_set readfd;
struct timeval timeOut;
int retVal;
static int stdTestIn = -1;
if (stdTestIn == -1)
stdTestIn = fileno(stdin);
if (fd == stdTestIn)
{
int len;
fgets(&buffer[0], 1024, stdin);
len = strlen(&buffer[0]);
buffer[len-1] = '\0';
}
else
{
if (nb)
{
/* See if there is any data available */
FD_ZERO(&readfd);
FD_SET(fd, &readfd);
timeOut.tv_sec = 0;
timeOut.tv_usec = 0;
retVal = select(fd+1, &readfd, NULL, NULL, &timeOut);
if (retVal == 0)
return(NULL);
}
for (cnt=0;cnt<1024;cnt++)
{
status = recv(fd, &buffer[cnt], 1, 0);
if (status < 0)
{
/* Most likely the socket was shut down */
return(NULL);
}
if (buffer[cnt] == '\0')
return(&buffer[0]);
}
}
buffer[1023] = '\0';
return(&buffer[0]);
}
/*
* If somebody is interested give them the text from the last
* generated error.
*/
char *sockGetLastError()
{
return(&sockErrBuffer[0]);
}

View File

@ -0,0 +1,66 @@
/*
* Make sure to import or export the library functions if we are running
* under windows (Win95/98 or WinNT)
*
* HP also has a default mode where we can TAG which symbols are to be
* exported.
*
* Project do the same for the HP port and remove the
*
*/
/*
* Get a line of data from the socket.
* If the arg "nb" is non 0 then do not block if there is no data.
*/
DECLSPEC
char *sockGetLine(int fd, int nb);
/*
* Put a line of data to the socket.
*/
DECLSPEC
int sockPutLine(int fd, char *buf);
/*
* Make a client socket connection to the specified port and host.
*
* A value of -1 will be returned if an error is detected.
*/
DECLSPEC
int sockMakeClient(int port, char *host);
/*
* Make server to accept a connection. If block is non zero the call will
* block socket blocking.
*
* A value of -1 will be returned if an error is detected.
*/
DECLSPEC
int sockMakeServer(int port, int block);
/*
* Accept a connection on a socket created by sockMakeServer. If the
* socket was created with blocking then the call will block until somebody
* connects to the socket.
*
* If there was a connection was made the point to a char * will contain
* the string identifying who made the connection.
*
* A value of -1 will be returned if an error is detected.
*/
DECLSPEC
int sockAcceptServer(int listener, char **who);
/*
* Shut a server socket down.
*/
DECLSPEC
void sockCloseServer(int fd, int listener);
/*
* Get the text for the last error generated from a call to the socket
* utility.
*/
DECLSPEC
char *sockGetLastError();

View File

@ -0,0 +1,8 @@
TARGETS:
cd dispargs; make
cd remmodel; make
clean:
cd dispargs; make clean
cd remmodel; make clean

Binary file not shown.

View File

@ -0,0 +1,48 @@
UTILNAME = dispargs
BASEDIR = ../..
PLIINC = ../../pliinc
include ${BASEDIR}/Makefile.${ARCH}
UTILLIBS =
INCDIRS = -I${BASEDIR}/include -I${PLIINC}
DFLAGS = ${ARCHDEBUG}
#DFLAGs =
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${DFLAGS} ${ARCHGNU} ${INCDIRS}
TARGETS = \
${PLILIBS}
PLIOBJ = dispargs.${ARCHEXT}
PLILIBS = dispargs.${ARCHDYNEXT}
CFILES = \
${MODEL.${ARCHEXT}=.c}
.c.${ARCHEXT}:
$(CC) -c $< ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
target: ${TARGETS}
dispargs.${ARCHDYNEXT}: dispargs.${ARCHEXT}
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}dispargs.${ARCHDYNEXT} dispargs.${ARCHEXT} ${ARCHPLILIB} ${ARCHLIBFLAGS}
TAGS: ${CFILES} ${HFILES}
etags -tTa ${HFILES} ${CFILES}
clean:
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* *.log *.key ${TARGETS}
ship:
-$(RM) ${UTILNAME}.tar.gz
tar -cvf ${UTILNAME}.tar Makefile ${CFILES} ${HFILES}
gzip ${UTILNAME}.tar
depend:
makedepend ${INCDIRS} ${CFILES}
# DO NOT DELETE

View File

@ -0,0 +1,7 @@
This example will dump all the command line arguments. It will also
dump out the contents of any -f <file> being used.
To run the test case:
<simulator> -f run.vc

View File

@ -0,0 +1,96 @@
#include <stdio.h>
#include "vpi_user.h"
#include "com_exp.h"
int indent = 5;
static void processFileArgs(char **args)
{
int cnt;
vpi_printf(" %s\n", *args++);
indent += 5;
while(*args != NULL)
{
for (cnt=0;cnt<indent;cnt++)
{
vpi_printf(" ");
}
vpi_printf("%s", *args);
if (strcmp("-f", *args) == 0)
{
args++;
cnt++;
processFileArgs(((char **)*args));
}
else
{
vpi_printf("\n");
}
args++;
}
indent -= 5;
}
static int dispArgs(p_cb_data cbData)
{
s_vpi_vlog_info vlogInfo;
int cnt;
char **args;
vpi_get_vlog_info(&vlogInfo);
args = vlogInfo.argv;
vpi_printf("Commandline args used by the simulator: %s\n", *args);
args++;
for (cnt=1;cnt<vlogInfo.argc;cnt++)
{
vpi_printf(" %s", *(args));
if (strcmp("-f", *args) == 0)
{
args++;
cnt++;
processFileArgs(((char **)*args));
}
else
{
vpi_printf("\n");
}
args++;
}
vpi_printf("\n\n");
return(0);
}
/*
* boot strap for
*
* +loadvpi=dispargs:regDispArgs
* or
* -loadvpi dispargs:regDispArgs
*
* If using the old vlog_start_array method add the routine regDispArgs
* to the array.
*
*/
DECLEXP
void regDispArgs()
{
s_cb_data cbData;
vpiHandle retHand;
cbData.reason = cbStartOfSimulation;
cbData.time = NULL;
cbData.value = NULL;
cbData.user_data = NULL;
cbData.cb_rtn = dispArgs;
retHand = vpi_register_cb(&cbData);
if (retHand)
{
vpi_free_object(retHand);
}
}

View File

@ -0,0 +1,4 @@
-q
test.v
-f test1.vc
+loadvpi=dispargs:regDispArgs

View File

@ -0,0 +1,4 @@
module top;
wire a;
endmodule

View File

@ -0,0 +1,5 @@
+a
+b
+c
+d
-f test2.vc

View File

@ -0,0 +1,3 @@
+a2
+b2
+c2

View File

@ -0,0 +1,59 @@
UTILNAME = dumpToServer
BASEDIR = ../..
PLIINC = ../../pliinc
include ${BASEDIR}/Makefile.${ARCH}
UTILLIBS = -L${BASEDIR}/lib -lSocketUtil
INCDIRS = -I${BASEDIR}/include -I${PLIINC}
DFLAGS = ${ARCHDEBUG}
#DFLAGs =
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${DFLAGS} ${ARCHGNU} ${INCDIRS}
TARGETS = \
runModel${ARCHEXE} \
${REMLIB}
MODEL = modelMain.${ARCHEXT} \
runModel.${ARCHEXT}
REMOBJ = remmodel.${ARCHEXT}
REMLIB = librem.${ARCHDYNEXT}
CFILES = \
${MODEL.${ARCHEXT}=.c}
.c.${ARCHEXT}:
$(CC) -c $< ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
target: ${TARGETS}
${REMLIB}: ${REMOBJ}
-$(RM) ${REMLIB}
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}${REMLIB} ${REMOBJ} ${BASEDIR}/lib/libSocketUtil.${ARCHDYNEXTL} ${ARCHPLILIB} ${ARCHLIBFLAGS}
libvpi.${ARCHDYNEXT}: ${REMOBJ} vlogmodel.${ARCHEXT}
-$(RM) libvpi.dll
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}libvpi.${ARCHDYNEXT} ${ARCHLIBFLAGS} ${REMOBJ} vlogmodel.${ARCHEXT} ${BASEDIR}/lib/libSocketUtil.${ARCHDYNEXTL} ${ARCHPLILIB}
runModel${ARCHEXE}: ${MODEL}
$(CC) ${ARCHCCOUT}$@ ${MODEL} ${BASEDIR}/lib/libSocketUtil.${ARCHDYNEXTL} ${ARCHLIBFLAGS}
TAGS: ${CFILES} ${HFILES}
etags -tTa ${HFILES} ${CFILES}
clean:
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* *.log *.key ${TARGETS}
ship:
-$(RM) ${UTILNAME}.tar.gz
tar -cvf ${UTILNAME}.tar Makefile ${CFILES} ${HFILES}
gzip ${UTILNAME}.tar
depend:
makedepend ${INCDIRS} ${CFILES}
# DO NOT DELETE

View File

@ -0,0 +1,16 @@
To run this example first type make. This will build the dynamic
library that will be used by the simulator to communicate with some
remote simulator. It will also build an exe that is a simple stand
alone model of a multibit latch.
Next to start the remote model running type:
runModel 5511
You can now start the simulator in a different window on the HDL
file test.v by using the command file "run.vc"
<simulator> -f run.vc

View File

@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdlib.h>
#ifndef WINNT
#include <unistd.h>
#endif
#include "com_exp.h"
#include "socketUtil.h"
#include "runModel.h"
extern char *modelWho;
int main(int argc, char *argv[])
{
char *port = NULL;
char *host = NULL;
char *data = NULL;
int cnt = 1;
int fd = fileno(stdin);
int fdOut = fileno(stdout);
int server = -1;
if (argc > 1)
{
while(cnt<argc)
{
if (argv[cnt][0] == '-')
{
if (!strcmp(argv[cnt], "host"))
{
host = argv[cnt];
}
else
{
fprintf(stderr, "Bad argument: %s", argv[cnt]);
exit(1);
}
}
else
{
if (!port)
{
port = argv[cnt];
}
else
{
fprintf(stderr, "The port was already given!\n");
exit(1);
}
}
cnt++;
}
}
if (port)
{
server = sockMakeServer(atoi(port), 1);
if (server == -1)
{
printf("Failed to open the desired socket: %s\n", port);
exit(1);
}
printf("Monitoring port: %s\n", port);
fd = sockAcceptServer(server, &modelWho);
fdOut = fd;
printf("Received connection from host ");
if (modelWho)
{
printf("%s\n", modelWho);
}
else
{
printf("<unknown>\n");
}
}
else
{
fd = fileno(stdin);
fdOut = fileno(stdout);
}
while((data = sockGetLine(fd, 0)))
{
runModel(fdOut, server, data);
}
close(fd);
exit(0);
}

View File

@ -0,0 +1,550 @@
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#include "veriuser.h"
#include "vpi_user.h"
#include "com_exp.h"
#include "socketUtil.h"
/*
* Data structures
*/
typedef struct remPort {
struct remPort *next;
char *name;
int changed;
int id;
int size;
char *val;
vpiHandle obj;
vpiHandle obj2;
struct remModel *root;
} s_remPort, *p_remPort;
typedef struct remModel {
vpiHandle inst;
int conn;
int connIn;
int server;
int numPorts;
p_remPort in;
p_remPort out;
p_remPort inout;
int synched;
p_remPort *portArray;
} s_remModel, *p_remModel;
/*
* Utility routines
*/
static void remError(char *fmt, ...)
{
char buffer[10048]; /* A Large buffer */
va_list ap;
va_start(ap, fmt);
vsprintf(&buffer[0], fmt, ap);
/*
* Use tf_error() to stop things until VPI has an error interface added
*/
tf_error(&buffer[0]);
va_end(ap);
tf_dostop();
}
static void *remAlloc(int size)
{
void *retVal;
assert(size>0);
retVal = malloc(size);
memset(retVal, 0, size);
return(retVal);
}
/*
* Send data down to the remote and get a response if requested
*/
static char *remSendData(int conn, int expectData, char *fmt, ...)
{
char buffer[2048]; /* Cheap lazy large buffer....
* Watch this if you start using large vectors or
* something
*/
char *retVal = NULL;
va_list ap;
va_start(ap, fmt);
vsprintf(&buffer[0], fmt, ap);
sockPutLine(conn , &buffer[0]);
if (expectData)
{
retVal = sockGetLine(expectData, 0);
}
return(retVal);
}
static void remGetOutputs(p_remModel modelStr)
{
char *retVal;
static char *buffer = NULL;
static int bufferLen = 0;
char *tmp;
s_vpi_value valStr;
p_remPort *array = modelStr->portArray;
int len;
int id;
if (modelStr->conn == -1)
return; /* The model has become disfunctional */
/* Tell model all data has been sent */
remSendData(modelStr->conn, FALSE, "done");
while((retVal = sockGetLine(modelStr->connIn, FALSE)))
{
/* See if we are done */
if (!strcmp(retVal, "done"))
{
break;
}
len = strlen(retVal);
if (len+1 > bufferLen)
{
if (buffer)
{
free(buffer);
}
bufferLen = (((len+1)+256)/256)*256; /* Some multiple of 256 */
buffer = remAlloc(bufferLen);
}
strcpy(buffer, retVal);
/* Get the ID */
tmp = strtok(buffer, " ");
id = atoi(tmp);
/* Get the value */
tmp = strtok(NULL, " ");
valStr.format = vpiBinStrVal;
valStr.value.str = tmp;
vpi_put_value((*(array+id))->obj, &valStr, NULL, vpiNoDelay);
}
}
/*
* run time routines
*/
static int remFinishSim(p_cb_data cbData)
{
p_remModel modelStr = (p_remModel)cbData->user_data;
remSendData(modelStr->conn, FALSE, "finished");
close(modelStr->conn);
close(modelStr->connIn);
close(modelStr->server);
vpi_printf("Remote model: %s\n", vpi_get_str(vpiFullName, modelStr->inst));
vpi_printf(" has been terminated\n");
return(0);
}
static int remSynch(p_cb_data cbData)
{
int cnt;
p_remModel modelStr = (p_remModel)cbData->user_data;
p_remPort *ports = modelStr->portArray;
modelStr->synched = FALSE;
/* Send over the value of all the ports that have changed value */
for (cnt=0;cnt<modelStr->numPorts;cnt++)
{
if ((*(ports+cnt))->changed)
{
remSendData(modelStr->conn, FALSE, "set %d %d %s",
(*(ports+cnt))->id, (*(ports+cnt))->size,
(*(ports+cnt))->val);
(*(ports+cnt))->changed = FALSE;
}
}
/* Get any outputs from the model */
remGetOutputs(modelStr);
return(0);
}
static int remCbInput(p_cb_data cbData)
{
p_remPort port = (p_remPort)cbData->user_data;
static s_vpi_time time = {vpiSimTime, 0, 0, 0.0};
static s_cb_data synch = {cbReadWriteSynch, remSynch, NULL, &time, NULL};
/* Schedule a wake up at the end of the present time slice */
if (!port->root->synched)
{
/*
* Register a callback for the end of the time slice.
* remember to free the callback handle, seeing that we will never
* cancel the callback.
*/
vpiHandle hCb;
synch.user_data = (char *)port->root;
hCb = vpi_register_cb(&synch);
vpi_free_object(hCb);
port->root->synched = TRUE;
}
port->changed = TRUE;
strcpy(port->val, cbData->value->value.str);
return(0);
}
static void setupRemModel(p_remModel modelStr)
{
s_vpi_value valStr;
p_remPort port;
char *retOk;
/*
* Now dump the information to the remote model and synch up
*/
valStr.format = vpiBinStrVal;
port = modelStr->in;
while(port)
{
vpi_get_value(port->obj, &valStr);
retOk = remSendData(modelStr->conn, modelStr->connIn,
"init %s %d %d %s", port->name, port->size,
port->id, valStr.value.str);
if (strcmp(retOk, "OK") != 0)
{
remError("model received bad return from remote model -- %s", retOk);
}
port = port->next;
}
port = modelStr->out;
while(port)
{
vpi_get_value(port->obj, &valStr);
retOk = remSendData(modelStr->conn, modelStr->connIn, "init %s %d %d %s",
port->name, port->size,
port->id, valStr.value.str);
if (strcmp(retOk, "OK") != 0)
{
remError("model received bad return from remote model -- %s", retOk);
}
port = port->next;
}
port = modelStr->inout;
while(port)
{
vpi_get_value(port->obj, &valStr);
retOk = remSendData(modelStr->conn, modelStr->connIn, "init %s %d %d %s",
port->name, port->size,
port->id, valStr.value.str);
if (strcmp(retOk, "OK") != 0)
{
remError("model received bad return from remote model -- %s", retOk);
}
port = port->next;
}
}
/*
* Build the models interface and sync up with the remote model.
*/
static int remModelCall(char *data)
{
vpiHandle hModule, hThisTask;
vpiHandle hPortIter, hPort;
vpiHandle hDriverIter, hDriver;
vpiHandle hConn, hLhs;
vpiHandle hArgIter, hArg;
s_vpi_value valStr;
s_cb_data cbData;
int cntId = 0;
int server;
int portNo, portNoIn;
char *remMachine = NULL;
int conn, fdOut;
p_remModel modelStr;
p_remPort port;
char buffer[1024];
/*
* See if we can establish a connection to the remote model.
*/
hThisTask = vpi_handle(vpiSysTfCall, NULL);
hArgIter = vpi_iterate(vpiArgument, hThisTask);
hArg = vpi_scan(hArgIter);
valStr.format = vpiIntVal;
vpi_get_value(hArg, &valStr);
portNo = valStr.value.integer;
hArg = vpi_scan(hArgIter);
if (hArg)
{
if ((vpi_get(vpiType, hArg) == vpiConstant) &&
(vpi_get(vpiConstType, hArg)))
{
valStr.format = vpiStringVal;
vpi_get_value(hArg, &valStr);
remMachine = valStr.value.str;
}
}
vpi_printf("Starting connection for: %s\n",
vpi_get_str(vpiFullName, vpi_handle(vpiScope, hThisTask)));
vpi_printf(" on port = %d\n", portNo);
if (remMachine)
{
vpi_printf(" machine = %s\n", remMachine);
}
/*
* See if we can find a port to receive input on
*/
server = -1;
portNoIn = portNo;
while(server == -1)
{
portNoIn++;
server = sockMakeServer(portNoIn, 1);
}
conn = sockMakeClient(portNo, remMachine);
if (conn == -1)
{
sprintf(&buffer[0],
"Failed to make a connection to the remote model at port = %d ",
portNo);
if (remMachine)
{
strcat(&buffer[0], "machine = ");
strcat(&buffer[0], remMachine);
}
strcat(&buffer[0], " \n");
remError(&buffer[0]);
return(0);
}
/* Now tell the other machine where to send data back */
sprintf(&buffer[0], "port %d", portNoIn);
sockPutLine(conn, &buffer[0]);
fdOut = sockAcceptServer(server, NULL);
/*
* Now start building up the main data structure.
*/
modelStr = remAlloc(sizeof(s_remModel));
modelStr->conn = conn;
modelStr->connIn = fdOut;
modelStr->server = server;
/*
* Before we do anything else lets register for simulation
* finish so we can shut down the remote connection if needed.
*/
cbData.reason = cbEndOfSimulation;
cbData.user_data = (char *)modelStr;
cbData.time = NULL;
cbData.value = NULL;
cbData.obj = NULL;
cbData.cb_rtn = remFinishSim;
vpi_register_cb(&cbData);
/*
* Get the port data.
*/
hModule = vpi_handle(vpiScope, hThisTask);
modelStr->inst = hModule;
hPortIter = vpi_iterate(vpiPort, hModule);
if (!hPortIter)
{
return(0);
}
/* See how many ports there are */
while((hPort = vpi_scan(hPortIter)))
{
cntId++;
}
modelStr->numPorts = cntId;
modelStr->portArray = remAlloc(cntId * sizeof(p_remPort *));
hPortIter = vpi_iterate(vpiPort, hModule);
cntId = 0;
valStr.format = vpiBinStrVal;
while((hPort = vpi_scan(hPortIter)))
{
hConn = vpi_handle(vpiLowConn, hPort);
if (!hConn)
{
/* hmmm an empty port connection */
continue;
}
port = remAlloc(sizeof(s_remPort));
port->id = cntId;
port->root = modelStr;
port->obj = hConn;
port->size = vpi_get(vpiSize, hConn);
port->val = remAlloc(port->size+1);
port->name = strdup(vpi_get_str(vpiName, hConn));
*(modelStr->portArray+cntId) = port;
cntId++;
switch(vpi_get(vpiDirection, hPort))
{
case vpiInput:
port->next = modelStr->in;
modelStr->in = port;
cbData.reason = cbValueChange;
cbData.user_data = (char *)port;
cbData.time = NULL;
cbData.value = &valStr;
cbData.obj = hConn;
cbData.cb_rtn = remCbInput;
vpi_register_cb(&cbData);
break;
case vpiOutput:
port->next = modelStr->out;
modelStr->out = port;
break;
case vpiInout:
port->next = modelStr->inout;
modelStr->inout = port;
cbData.reason = cbValueChange;
cbData.user_data = (char *)port;
cbData.time = NULL;
cbData.value = &valStr;
cbData.obj = hConn;
cbData.cb_rtn = remCbInput;
vpi_register_cb(&cbData);
/* find the reg */
hDriverIter = vpi_iterate(vpiContAssign, hModule);
while((hDriver = vpi_scan(hDriverIter)))
{
hLhs = vpi_handle(vpiLhs, hDriver);
if (vpi_compare_objects(hLhs, hConn))
{
port->obj2 = vpi_handle(vpiRhs, hDriver);
vpi_free_object(hDriverIter);
break;
}
}
break;
case vpiMixedIO:
default:
/* Should never get here */
break;
}
}
setupRemModel(modelStr);
return(0);
}
/*
* Verify the port list is consistent with remote model.
* Walk through the ports
* Verify that all
* inputs are wires
* outputs are registers
* inouts are wires with implicit cont assign with a register
*
*/
static int remModelCompile(char *data)
{
vpiHandle hPortIter, hPort;
vpiHandle hModule, hThisTask;
vpiHandle hLowConn;
vpiHandle hArgIter, hArg;
hThisTask = vpi_handle(vpiSysTfCall, NULL);
hArgIter = vpi_iterate(vpiArgument, hThisTask);
if (!hArgIter)
{
remError("This system task must have a socket number\n");
return(0);
}
hArg = vpi_scan(hArgIter);
if (vpi_get(vpiType, hArg))
{
if (vpi_get(vpiConstType, hArg) == vpiDecConst)
{
}
}
hModule = vpi_handle(vpiScope, hThisTask);
if (hModule == NULL)
{
remError("This system task (%s) must be executed from inside a module\n",
vpi_get_str(vpiName, hThisTask));
return(0);
}
hPortIter = vpi_iterate(vpiPort, hModule);
if (!hPortIter)
{
vpi_printf("There does not appear to be any port. Nothing much is going to happen\n");
return(0);
}
while((hPort = vpi_scan(hPortIter)))
{
hLowConn = vpi_handle(vpiLowConn, hPort);
if (!hLowConn)
{
/* hmmm an empty port connection */
continue;
}
switch(vpi_get(vpiDirection, hPort))
{
case vpiInput:
break;
case vpiOutput:
break;
case vpiInout:
break;
case vpiMixedIO:
default:
break;
}
}
return(0);
}
DECLEXP
void regRemModel()
{
s_vpi_systf_data systf;
systf.type = vpiSysTask;
systf.sysfunctype = 0;
systf.tfname = "$remModel";
systf.calltf = remModelCall;
systf.compiletf = remModelCompile;
systf.sizetf = NULL;
systf.user_data = NULL;
vpi_register_systf(&systf);
}

View File

@ -0,0 +1,5 @@
-q
+accwarn
+loadvpi=librem:regRemModel
test.v

View File

@ -0,0 +1,378 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <assert.h>
#ifndef WINNT
#include <unistd.h>
#endif
#include "com_exp.h"
#include "socketUtil.h"
#define IDEN 0
#define IDIN 1
#define IDOUT 2
typedef struct port {
char *name;
int id;
int realId;
int size;
int changed;
char *value;
} *p_port, s_port;
static s_port enable = {"enable", 0, IDEN, -1, 0, NULL};
static s_port input = {"in", 0, IDIN, -1, 0, NULL};
static s_port output = {"out", 0, IDOUT, -1, 0, NULL};
static p_port portArray[3];
static char buffer[1025];
char *modelWho = NULL;
static void *modelAlloc(int size)
{
void *retVal;
assert(size>0);
retVal = malloc(size);
memset(retVal, 0, size);
return(retVal);
}
static void modelError(int fd, char *fmt, ...)
{
char buffer[2048]; /* Cheap lazy large buffer....
* Watch this if you start using large vectors or
* something
*/
va_list ap;
va_start(ap, fmt);
vsprintf(&buffer[0], fmt, ap);
sockPutLine(fd , &buffer[0]);
exit(1);
}
/*
* Different routines for the different string commands the model supports
*/
static void process_done(int fd, int fdRet)
{
static out = 0;
char *c;
int cnt;
/*
* Ok folks here is the model.
* Yes it's very simple. So what!
*/
out = 0;
if (input.changed || enable.changed)
{
enable.changed = 0;
input.changed = 0;
/* Calculate the new output value */
/* update the output if enable == 1 */
if ((*enable.value == '1') || (*enable.value == 'x'))
{
/* If enable is and X set the output to an X (Quick and dirty) */
if (*enable.value == 'x')
{
if (strcmp(output.value, input.value) != 0)
{
/* If the input has changed then make the output an X */
c = output.value;
for (cnt = 0; cnt < output.size; cnt++)
*(c++) = 'x';
out = 1;
}
}
else
{
if (!strcmp(output.value, input.value))
{
out = 0;
}
else
{
strcpy(output.value, input.value);
out = 1;
}
}
}
if (out)
{
sprintf(buffer, "out %s", output.value);
if (fdRet != -1)
{
sockPutLine(fdRet, buffer);
}
out = 0;
}
if (fdRet != -1)
{
sockPutLine(fdRet, "done");
}
}
return;
}
static void process_init(int fd, int fdRet)
{
char *c;
char *cSize, *cVal;
char *cId;
int id, size;
int cnt;
c = strtok(NULL, " "); /* Get the name of the net */
if ( c == NULL )
{
modelError(fdRet, "Bad init line - missing NAME");
}
cSize = strtok(NULL, " "); /* Get the size of the net */
if ( cSize == NULL )
{
modelError(fdRet, "Bad init line - missing SIZE");
}
cId = strtok(NULL, " "); /* Get the ID */
if ( cId == NULL )
{
modelError(fdRet, "Bad init line - missing ID");
}
cVal = strtok(NULL, " ");
if ( cVal == NULL )
{
modelError(fdRet, "Bad init line - missing VALUE");
}
id = atoi(cId);
size = atoi(cSize);
if ((id < 0) || (id > 2))
{
modelError(fdRet, "ID out of range >>> 0 - 2");
}
if (!strcmp(c, "out"))
{
if (input.size != -1)
{
if (input.size != size)
{
modelError(fdRet, "port input must have the same size of output");
}
}
portArray[id] = &output;
}
else if (!strcmp(c, "in"))
{
if (output.size != -1)
{
if (output.size != size)
{
modelError(fdRet, "port input must have the same size of output");
}
}
portArray[id] = &input;
}
else if (!strcmp(c, "enable"))
{
if (size != 1)
{
modelError(fdRet, "Port enable can only be one bit");
}
portArray[id] = &enable;
}
else
{
modelError(fdRet, "Bad port name - %s", c);
}
portArray[id]->id = id;
portArray[id]->size = size;
portArray[id]->value = modelAlloc(size + 1);
portArray[id]->changed = 1;
c = portArray[id]->value;
for (cnt=0; cnt < size; cnt++)
*c++ = *cVal++;
*c = '\0';
sockPutLine(fdRet, "OK");
}
static void process_set(int fd, int fdRet)
{
char *cId, *cSize, *cVal;
int size;
int id;
cId = strtok(NULL, " ");
if ( cId == NULL )
{
modelError(fdRet, "Bad set line - missing ID");
}
cSize = strtok(NULL, " ");
if ( cSize == NULL )
{
modelError(fdRet, "Bad set line - missing size");
}
cVal = strtok(NULL, " ");
if ( cVal == NULL )
{
modelError(fdRet, "Bad set line - missing value");
}
id = atoi(cId);
if ((id < 0) || (id > 2))
{
modelError(fdRet, "Bad id in set command - %s", cId);
}
size = atoi(cSize);
if (size != portArray[id]->size)
{
modelError(fdRet, "Bad size in set command, does not match objects size");
}
switch(portArray[id]->realId)
{
case IDEN:
case IDIN:
strcpy(portArray[id]->value, cVal);
portArray[id]->changed = 1;
break;
case IDOUT:
modelError(fdRet, "Cannot set a value to the output port");
break;
default:
break;
}
return;
}
static void process_value(int fd, int fdRet)
{
char *cId;
int id;
cId = strtok(NULL, " "); /* Get the id of the net */
if ( cId == NULL )
{
modelError(fdRet, "Bad value line - missing ID");
}
id = atoi(cId);
if ((id < 0) || (id > 2))
{
modelError(fdRet, "Bad id in set command - %s", cId);
}
sockPutLine(fdRet, portArray[id]->value);
}
void runModel(int fd, int fdSrv, char *data)
{
char *c;
static fdRet = -1;
char *cId;
c = strtok(data, " ");
if (c == NULL)
return;
if (*c == '\0')
return;
switch(*c)
{
case 'd':
if (!strcmp(c, "done"))
{
process_done(fd, fdRet);
}
break;
case 'f':
{
if (!strcmp(c, "finished"))
{
if (fdRet > 0)
{
close(fdRet);
}
close(fd);
if (fdSrv > 0)
{
close(fdSrv);
}
printf("Shutting down!\n");
exit(0);
}
break;
}
case 'i':
if (!strcmp(c, "init"))
{
process_init(fd, fdRet);
}
break;
case 'p':
if (!strcmp(c, "port")) /* update an input value */
{
cId = strtok(NULL, " ");
if ( cId == NULL )
{
modelError(fdRet, "Bad portno - missing ID");
}
fdRet = sockMakeClient(atoi(cId), modelWho);
}
break;
case 's':
if (!strcmp(c, "set")) /* update an input value */
{
process_set(fd, fdRet);
}
break;
case 'v':
if (!strcmp(c, "value"))
{
process_value(fd, fdRet);
}
break;
default:
modelError(fdRet, "Bad input command");
break;
}
return;
}

View File

@ -0,0 +1 @@
char *runModel(int fd, int fdServ, char *data);

View File

@ -0,0 +1,63 @@
`timescale 1ns / 1ns
`celldefine
module latch(out, in, enable);
input [3:0] in;
output [3:0] out;
reg [3:0] out;
wire [3:0] outW;
input enable;
initial
$remModel(5510,,out, in, enable);
endmodule
`endcelldefine
module test;
reg enable;
reg [3:0] in;
wire [3:0] out0;
latch u0(out0, in, enable);
initial
begin
$timeformat(-9, 0, "ns", 6);
$monitor("%t", $time, " enable=", enable, " in=%b", in, " out -> %b", out0);
end
initial
begin
// #0 $stop;
#10 enable = 0;
in = 4'b0100;
#10 enable = 1;
#10 enable = 0;
#10 enable = 1'bx;
#10 in = 4'b1000;
// #10 $display("Saving Simulation to file: data.1");
// $save("data.1");
#10 enable = 1;
#10 enable = 1'bx;
// #10 $display("Incremental Save data.2");
// $save("data.2");
#10 in = 4'b0110;
#10 enable = 1;
#10 enable = 0;
#10 enable = 1'bx;
#10 in = 4'b0001;
// #10 $display("Incremental Save data.3");
// $incsave("data.3");
#10 enable = 0;
#10 enable = 1;
#10 enable = 0;
end
endmodule

View File

@ -0,0 +1,10 @@
extern void regRemModel();
#ifdef WINNT
__declspec(dllexport)
#endif
void (*vlog_startup_routines[])() =
{
regRemModel,
0
};

View File

@ -0,0 +1,19 @@
#
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
#
MTI_INSTALL_DIR=c:\progra~1\ModelTech
SOURCES = \
hello_vpi.c \
show_value_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
.c.obj:
$(CC) $(CFLAGS) -c $<
../mti_pli.dll: $(OBJS)
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib

View File

@ -0,0 +1,19 @@
#
# sample NMAKE makefile to make libvpi.dll for Cadence Verilog-XL, using VisualC++ on Windows
#
CDS_INST_DIR=C:/progra~1/cds/
SOURCES = \
hello_vpi.c \
show_value_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
.c.obj:
$(CC) $(CFLAGS) -c $<
libvpi.dll: $(OBJS)
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib

View File

@ -0,0 +1,18 @@
#
# sample NMAKE makefile to make libvpi.dll with VisualC++ on Windows
# see windows.txt for more details.
#
SOURCES = \
hello_vpi.c \
show_value_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
.c.obj:
$(CC) $(CFLAGS) -c $<
libvpi.dll: $(OBJS)
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib

View File

@ -0,0 +1,5 @@
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
Hello World!
Simulation complete via $finish(1) at time 10 NS + 0

View File

@ -0,0 +1,20 @@
/**********************************************************************
* $hello example -- Verilog HDL test bench.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module test;
initial
begin
$hello;
// #10 $stop;
#10 $finish;
end
endmodule
/**********************************************************************/

View File

@ -0,0 +1,45 @@
/**********************************************************************
* $hello example -- PLI application using VPI routines
*
* C source to print "Hello World" as a PLI application.
*
* Usage: $hello;
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
/**********************************************************************
* calltf routine
*********************************************************************/
PLI_INT32 PLIbook_hello_calltf(PLI_BYTE8 *user_data)
{
vpi_printf("\nHello World!\n\n");
return(0);
}
/**********************************************************************
* $hello Registration Data
* (add this function name to the vlog_startup_routines array)
*********************************************************************/
void PLIbook_hello_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.sysfunctype = 0;
tf_data.tfname = "$hello";
tf_data.calltf = PLIbook_hello_calltf;
tf_data.compiletf = NULL;
tf_data.sizetf = NULL;
tf_data.user_data = NULL;
vpi_register_systf(&tf_data);
}

View File

@ -0,0 +1,7 @@
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
Signal test.sum has the value 1
Signal test.co has the value 0
Signal test.i1.n3 has the value 0
Simulation complete via $finish(1) at time 30 NS + 0

View File

@ -0,0 +1,57 @@
/**********************************************************************
* $show_value example -- Verilog HDL test bench.
*
* Verilog test bench to test the $show_value PLI application on a
* 1-bit adder modeled using gate primitives.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module test;
reg a, b, ci, clk;
wire sum, co;
addbit i1 (a, b, ci, sum, co);
initial
begin
// $monitor("At %0d: \t a=%b b=%b ci=%b sum=%b co=%b",
// $time, a, b, ci, sum, co);
clk = 0;
a = 0;
b = 0;
ci = 0;
#10 a = 1;
#10 b = 1;
$show_value(sum);
$show_value(co);
$show_value(i1.n3);
// #10 $stop;
#10 $finish;
end
endmodule
/*** A gate level 1 bit adder model ***/
`timescale 1ns / 1ns
module addbit (a, b, ci, sum, co);
input a, b, ci;
output sum, co;
wire a, b, ci, sum, co,
n1, n2, n3;
xor (n1, a, b);
xor #2 (sum, n1, ci);
and (n2, a, b);
and (n3, n1, ci);
or #2 (co, n2, n3);
endmodule
/**********************************************************************/

View File

@ -0,0 +1,117 @@
/**********************************************************************
* $show_value example -- PLI application using VPI routines
*
* C source to print the name and current logic value of a net.
*
* Usage: $show_value(<signal_name>);
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
#if VPI_1995
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
#endif
/* prototypes of routines in this PLI application */
PLI_INT32 PLIbook_ShowVal_compiletf(PLI_BYTE8 *user_data);
PLI_INT32 PLIbook_ShowVal_calltf(PLI_BYTE8 *user_data);
/**********************************************************************
* $show_value Registration Data
* (add this function name to the vlog_startup_routines array)
*********************************************************************/
void PLIbook_ShowVal_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.sysfunctype = 0;
tf_data.tfname = "$show_value";
tf_data.calltf = PLIbook_ShowVal_calltf;
tf_data.compiletf = PLIbook_ShowVal_compiletf;
tf_data.sizetf = NULL;
tf_data.user_data = NULL;
vpi_register_systf(&tf_data);
return;
}
/**********************************************************************
* compiletf application
*********************************************************************/
PLI_INT32 PLIbook_ShowVal_compiletf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, arg_handle;
PLI_INT32 arg_type;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
if (systf_handle == NULL) {
vpi_printf("ERROR: $show_value failed to obtain systf handle\n");
vpi_control(vpiFinish,0); /* abort simulation */
return(0);
}
/* obtain handles to system task arguments */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
vpi_printf("ERROR: $show_value requires 1 argument\n");
vpi_control(vpiFinish,0); /* abort simulation */
return(0);
}
/* check the type of object in system task arguments */
arg_handle = vpi_scan(arg_iterator);
arg_type = vpi_get(vpiType, arg_handle);
if (arg_type != vpiNet && arg_type != vpiReg) {
vpi_printf("ERROR: $show_value arg must be a net or reg\n");
vpi_free_object(arg_iterator); /* free iterator memory */
vpi_control(vpiFinish,0); /* abort simulation */
return(0);
}
/* check that there are no more system task arguments */
arg_handle = vpi_scan(arg_iterator);
if (arg_handle != NULL) {
vpi_printf("ERROR: $show_value can only have 1 argument\n");
vpi_free_object(arg_iterator); /* free iterator memory */
vpi_control(vpiFinish,0); /* abort simulation */
return(0);
}
return(0);
}
/**********************************************************************
* calltf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowVal_calltf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, arg_handle, net_handle;
s_vpi_value current_value;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handle to system task argument
compiletf has already verified only 1 arg with correct type */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
net_handle = vpi_scan(arg_iterator);
vpi_free_object(arg_iterator); /* free iterator memory */
/* read current value */
current_value.format = vpiBinStrVal; /* read value as a string */
vpi_get_value(net_handle, &current_value);
vpi_printf("Signal %s ", vpi_get_str(vpiFullName, net_handle));
vpi_printf("has the value %s\n", current_value.value.str);
return(0);
}
/*********************************************************************/

View File

@ -0,0 +1,5 @@
// Example Synopsys VCS PLI table to register PLI applications
// For the book, "The Verilog PLI Handbook"
$hello call=PLIbook_hello_calltf data=0
$show_value check=PLIbook_ShowVal_compiletf call=PLIbook_ShowVal_calltf data=0 acc+=read:*

View File

@ -0,0 +1,25 @@
/**********************************************************************
* Example vpi_user.c file
*
* vpi_user.c file to register PLI applications using the VPI library.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#include "vpi_user.h"
/* prototypes of the PLI registration routines */
extern void PLIbook_hello_register();
extern void PLIbook_ShowVal_register();
void (*vlog_startup_routines[])() =
{
/*** add user entries here ***/
PLIbook_hello_register,
PLIbook_ShowVal_register,
0 /*** final entry must be 0 ***/
};

View File

@ -0,0 +1,19 @@
#
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
#
MTI_INSTALL_DIR=c:\progra~1\ModelTech
SOURCES = \
pow_vpi.c \
user_data_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
.c.obj:
$(CC) $(CFLAGS) -c $<
../mti_pli.dll: $(OBJS)
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib

View File

@ -0,0 +1,19 @@
#
# sample NMAKE makefile to make libvpi.dll for Cadence Verilog-XL, using VisualC++ on Windows
#
CDS_INST_DIR=C:/progra~1/cds/
SOURCES = \
pow_vpi.c \
user_data_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
.c.obj:
$(CC) $(CFLAGS) -c $<
libvpi.dll: $(OBJS)
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib

View File

@ -0,0 +1,20 @@
#
# sample NMAKE makefile to make libvpi.dll with VisualC++ on Windows
# see windows.txt for more details.
#
CDS_INST_DIR=C:/progra~1/cds/
SOURCES = \
pow_vpi.c \
user_data_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
.c.obj:
$(CC) $(CFLAGS) -c $<
libvpi.dll: $(OBJS)
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib

View File

@ -0,0 +1,7 @@
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
$pow PLI application is being used.
$pow(2,3) returns 8
$pow(a,b) returns 1 (a=1 b=0)
Simulation complete via $finish(1) at time 4 NS + 0

View File

@ -0,0 +1,41 @@
/**********************************************************************
* $pow example -- Verilog HDL test bench.
*
* Verilog test bench to test the $pow PLI application.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module test;
reg [32:0] result;
reg a, b;
buf i1 (c,a);
initial
begin
a = 1;
b = 0;
/* Test $pow with invalid arguments */
/* These invalid calls will need to be commented out to use */
/* the valid calls to $pow in simulation */
// #1 result = $pow;
// #1 result = $pow();
// #1 result = $pow(1);
// #1 result = $pow(2,i1);
// #1 result = $pow(1,2,3);
/* Test $pow with valid values */
#1 $display("$pow(2,3) returns %d", $pow(2,3));
#1 result = $pow(a,b);
#1 $display("$pow(a,b) returns %d (a=%d b=%d)", result, a, b);
// #1 $stop;
#1 $finish;
end
endmodule
/*********************************************************************/

View File

@ -0,0 +1,172 @@
/**********************************************************************
* $pow example -- PLI application using VPI routines
*
* C source to calculate the result of a number to the power of an
* exponent. The result is returned as a 32-bit integer.
*
* Usage: result = $pow(<base>,<exponent>);
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
#if VPI_1995
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
#endif
/* prototypes of PLI application routine names */
PLI_INT32 PLIbook_PowSizetf(PLI_BYTE8 *user_data),
PLIbook_PowCalltf(PLI_BYTE8 *user_data),
PLIbook_PowCompiletf(PLI_BYTE8 *user_data),
PLIbook_PowStartOfSim(s_cb_data *callback_data);
/**********************************************************************
* $pow Registration Data
* (add this function name to the vlog_startup_routines array)
*********************************************************************/
void PLIbook_pow_register()
{
s_vpi_systf_data tf_data;
s_cb_data cb_data_s;
vpiHandle callback_handle;
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiSysFuncSized;
tf_data.tfname = "$pow";
tf_data.calltf = PLIbook_PowCalltf;
tf_data.compiletf = PLIbook_PowCompiletf;
tf_data.sizetf = PLIbook_PowSizetf;
tf_data.user_data = NULL;
vpi_register_systf(&tf_data);
cb_data_s.reason = cbStartOfSimulation;
cb_data_s.cb_rtn = PLIbook_PowStartOfSim;
cb_data_s.obj = NULL;
cb_data_s.time = NULL;
cb_data_s.value = NULL;
cb_data_s.user_data = NULL;
callback_handle = vpi_register_cb(&cb_data_s);
vpi_free_object(callback_handle); /* don't need callback handle */
}
/**********************************************************************
* Sizetf application
*********************************************************************/
PLI_INT32 PLIbook_PowSizetf(PLI_BYTE8 *user_data)
{
return(32); /* $pow returns 32-bit values */
}
/**********************************************************************
* compiletf application to verify valid systf args.
*********************************************************************/
PLI_INT32 PLIbook_PowCompiletf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_itr, arg_handle;
PLI_INT32 tfarg_type;
int err_flag = 0;
do { /* group all tests, so can break out of group on error */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
arg_itr = vpi_iterate(vpiArgument, systf_handle);
if (arg_itr == NULL) {
vpi_printf("ERROR: $pow requires 2 arguments; has none\n");
err_flag = 1;
break;
}
arg_handle = vpi_scan(arg_itr);
tfarg_type = vpi_get(vpiType, arg_handle);
if ( (tfarg_type != vpiReg) &&
(tfarg_type != vpiIntegerVar) &&
(tfarg_type != vpiConstant) ) {
vpi_printf("ERROR: $pow arg1 must be number, variable or net\n");
err_flag = 1;
break;
}
arg_handle = vpi_scan(arg_itr);
if (arg_handle == NULL) {
vpi_printf("ERROR: $pow requires 2nd argument\n");
err_flag = 1;
break;
}
tfarg_type = vpi_get(vpiType, arg_handle);
if ( (tfarg_type != vpiReg) &&
(tfarg_type != vpiIntegerVar) &&
(tfarg_type != vpiConstant) ) {
vpi_printf("ERROR: $pow arg2 must be number, variable or net\n");
err_flag = 1;
break;
}
if (vpi_scan(arg_itr) != NULL) {
vpi_printf("ERROR: $pow requires 2 arguments; has too many\n");
vpi_free_object(arg_itr);
err_flag = 1;
break;
}
} while (0 == 1); /* end of test group; only executed once */
if (err_flag) {
vpi_control(vpiFinish, 1); /* abort simulation */
}
return(0);
}
/**********************************************************************
* calltf to calculate base to power of exponent and return result.
*********************************************************************/
#include <math.h>
PLI_INT32 PLIbook_PowCalltf(PLI_BYTE8 *user_data)
{
s_vpi_value value_s;
vpiHandle systf_handle, arg_itr, arg_handle;
PLI_INT32 base, exp;
double result;
systf_handle = vpi_handle(vpiSysTfCall, NULL);
arg_itr = vpi_iterate(vpiArgument, systf_handle);
if (arg_itr == NULL) {
vpi_printf("ERROR: $pow failed to obtain systf arg handles\n");
return(0);
}
/* read base from systf arg 1 (compiletf has already verified) */
arg_handle = vpi_scan(arg_itr);
value_s.format = vpiIntVal;
vpi_get_value(arg_handle, &value_s);
base = value_s.value.integer;
/* read exponent from systf arg 2 (compiletf has already verified) */
arg_handle = vpi_scan(arg_itr);
vpi_free_object(arg_itr); /* not calling scan until returns null */
vpi_get_value(arg_handle, &value_s);
exp = value_s.value.integer;
/* calculate result of base to power of exponent */
result = pow( (double)base, (double)exp );
/* write result to simulation as return value $pow */
value_s.value.integer = (PLI_INT32)result;
vpi_put_value(systf_handle, &value_s, NULL, vpiNoDelay);
return(0);
}
/**********************************************************************
* Start-of-simulation application
*********************************************************************/
PLI_INT32 PLIbook_PowStartOfSim(s_cb_data *callback_data)
{
vpi_printf("\n$pow PLI application is being used.\n\n");
return(0);
}
/*********************************************************************/

View File

@ -0,0 +1,75 @@
/*********************************************************************/
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
PLI_INT32 PLIbook_GetVectorCalltf(PLI_BYTE8 *user_data),
PLIbook_GetVectorCompiletf(PLI_BYTE8 *user_data),
PLIbook_GetVectorSizetf(PLI_BYTE8 *user_data);
/**********************************************************************
* VPI Registration Data for $test_user_data_1;
*********************************************************************/
void PLIbook_test_user_data_register()
{
s_vpi_systf_data tf_data;
char *id1 = malloc(sizeof(int)); /* allocate user_data storage */
char *id2 = malloc(sizeof(int)); /* allocate user_data storage */
*id1 = 1;
*id2 = 2;
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiSysFuncSized;
tf_data.tfname = "$get_vector_bin";
tf_data.calltf = PLIbook_GetVectorCalltf;
tf_data.compiletf = PLIbook_GetVectorCompiletf;
tf_data.sizetf = PLIbook_GetVectorSizetf;
tf_data.user_data = (PLI_BYTE8 *)id1;
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiSysFuncSized;
tf_data.tfname = "$get_vector_hex";
tf_data.calltf = PLIbook_GetVectorCalltf;
tf_data.compiletf = PLIbook_GetVectorCompiletf;
tf_data.sizetf = PLIbook_GetVectorSizetf;
tf_data.user_data = (PLI_BYTE8 *)id2;
vpi_register_systf(&tf_data);
}
/**********************************************************************
* sizetf routine
*********************************************************************/
PLI_INT32 PLIbook_GetVectorSizetf(PLI_BYTE8 *user_data)
{
vpi_printf("\nIn sizetf,\tuser_data = %d\n", *user_data);
return(8);
}
/**********************************************************************
* compiletf routine
*********************************************************************/
PLI_INT32 PLIbook_GetVectorCompiletf(PLI_BYTE8 *user_data)
{
vpi_printf("\nIn compiletf,\tuser_data = %d\n", *user_data);
return(0);
}
/**********************************************************************
* test calltf routine
*********************************************************************/
PLI_INT32 PLIbook_GetVectorCalltf(PLI_BYTE8 *user_data)
{
vpi_printf("\nIn calltf,\tuser_data = %d\n", *user_data);
if (*user_data == 1) {
vpi_printf("calltf was invoked by $get_vector_bin()\n");
/* read test vectors as binary values */
}
else if (*user_data == 2) {
vpi_printf("calltf was invoked by $get_vector_hex()\n");
/* read test vectors as hex values */
}
return(0);
}/*********************************************************************/

View File

@ -0,0 +1,26 @@
/**********************************************************************
* $get_vector* example -- Verilog HDL test bench.
*
* Verilog test bench to test the $get_vector* PLI application.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module test;
reg [7:0] vector;
initial
begin
#1 vector = $get_vector_bin;
#1 vector = $get_vector_hex;
#1 $finish;
end
endmodule
/*********************************************************************/

View File

@ -0,0 +1,4 @@
// Example Synopsys VCS PLI table to register PLI applications
// For the book, "The Verilog PLI Handbook"
$pow call=PLIbook_PowCalltf check=PLIbook_PowCompiletf size=32 data=0

View File

@ -0,0 +1,25 @@
/**********************************************************************
* Example vpi_user.c file
*
* vpi_user.c file to register PLI applications using the VPI library.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#include "vpi_user.h"
/* prototypes of the PLI application routines */
extern void PLIbook_pow_register();
extern void PLIbook_test_user_data_register();
void (*vlog_startup_routines[])() =
{
/*** add user entries here ***/
PLIbook_pow_register,
PLIbook_test_user_data_register,
0 /*** final entry must be 0 ***/
};

View File

@ -0,0 +1,21 @@
#
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
#
MTI_INSTALL_DIR=c:\progra~1\ModelTech
SOURCES = \
show_all_nets_vpi.c \
show_all_signals_1_vpi.c \
# show_all_signals_2_vpi.c \
# show_all_signals_3_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
.c.obj:
$(CC) $(CFLAGS) -c $<
../mti_pli.dll: $(OBJS)
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib

View File

@ -0,0 +1,21 @@
#
# sample NMAKE makefile to make libvpi.dll for Cadence Verilog-XL, using VisualC++ on Windows
#
CDS_INST_DIR=C:/progra~1/cds/
SOURCES = \
show_all_nets_vpi.c \
show_all_signals_1_vpi.c \
# show_all_signals_2_vpi.c \
# show_all_signals_3_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
.c.obj:
$(CC) $(CFLAGS) -c $<
libvpi.dll: $(OBJS)
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib

View File

@ -0,0 +1,22 @@
#
# sample NMAKE makefile to make libvpi.dll with VisualC++ on Windows
# see windows.txt for more details.
#
CDS_INST_DIR=C:/progra~1/cds/
SOURCES = \
show_all_nets_vpi.c \
show_all_signals_1_vpi.c \
# show_all_signals_2_vpi.c \
# show_all_signals_3_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
.c.obj:
$(CC) $(CFLAGS) -c $<
libvpi.dll: $(OBJS)
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib

View File

@ -0,0 +1,15 @@
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
At time 20.00, nets in module top (top):
net results value is 10 (binary)
At time 30.00, nets in module top.i1 (addbit):
net a value is 1 (binary)
net b value is 1 (binary)
net ci value is 0 (binary)
net sum value is 0 (binary)
net co value is 1 (binary)
net n1 value is 0 (binary)
net n2 value is 1 (binary)
net n3 value is 0 (binary)
Simulation complete via $finish(1) at time 40 NS + 0

View File

@ -0,0 +1,50 @@
/**********************************************************************
* $show_all_nets example -- Verilog HDL test bench.
*
* Verilog test bench to test the $show_all_nets PLI application on a
* 1-bit adder modeled using gate primitives.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module top;
reg [2:0] test;
tri [1:0] results;
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
initial
begin
test = 3'b000;
#10 test = 3'b011;
#10 $show_all_nets(top);
#10 $show_all_nets(i1);
// #10 $stop;
#10 $finish;
end
endmodule
/*** A gate level 1 bit adder model ***/
`timescale 1ns / 1ns
module addbit (a, b, ci, sum, co);
input a, b, ci;
output sum, co;
wire a, b, ci, sum, co,
n1, n2, n3;
xor (n1, a, b);
xor #2 (sum, n1, ci);
and (n2, a, b);
and (n3, n1, ci);
or #2 (co, n2, n3);
endmodule
/*********************************************************************/

View File

@ -0,0 +1,135 @@
/**********************************************************************
* $show_all_nets example -- PLI application using VPI routines
*
* C source to scan through a module and list the names of all nets in
* the module with the current logic value.
*
* Usage: $show_all_nets(<module_instance>);
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
#if VPI_1995
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
#endif
/* prototypes of the PLI application routines */
PLI_INT32 PLIbook_ShowNets_compiletf(PLI_BYTE8 *user_data),
PLIbook_ShowNets_calltf(PLI_BYTE8 *user_data);
/**********************************************************************
* $show_all_nets Registration Data
*********************************************************************/
void PLIbook_ShowNets_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.sysfunctype = 0;
tf_data.tfname = "$show_all_nets";
tf_data.calltf = PLIbook_ShowNets_calltf;
tf_data.compiletf = PLIbook_ShowNets_compiletf;
tf_data.sizetf = NULL;
tf_data.user_data = NULL;
vpi_register_systf(&tf_data);
return;
}
/**********************************************************************
* compiletf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowNets_compiletf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, arg_handle;
PLI_INT32 tfarg_type;
int err_flag = 0;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handles to system task arguments */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
vpi_printf("ERROR: $show_all_nets requires 1 argument\n");
err_flag = 1;
}
else {
/* check the type of object in system task arguments */
arg_handle = vpi_scan(arg_iterator);
tfarg_type = vpi_get(vpiType, arg_handle);
if (tfarg_type != vpiModule) {
vpi_printf("ERROR: $show_all_nets arg must be module instance\n");
vpi_free_object(arg_iterator); /* free iterator memory */
err_flag = 1;
}
else {
/* check that there is only 1 system task argument */
arg_handle = vpi_scan(arg_iterator);
if (arg_handle != NULL) {
vpi_printf("ERROR: $show_all_nets can only have 1 argument\n");
vpi_free_object(arg_iterator); /* free iterator memory */
err_flag = 1;
} } } /* end of if-else-if-else-if sequence */
if (err_flag) {
vpi_control(vpiFinish, 1); /* abort simulation */
}
return(0);
}
/**********************************************************************
* calltf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowNets_calltf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, module_handle,
net_iterator, net_handle;
s_vpi_time current_time;
s_vpi_value current_value;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handle to system task argument */
/* compiletf has already verified only 1 arg with correct type */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
module_handle = vpi_scan(arg_iterator);
vpi_free_object(arg_iterator); /* free iterator memory */
/* read current simulation time */
current_time.type = vpiScaledRealTime;
vpi_get_time(systf_handle, &current_time);
vpi_printf("\nAt time %2.2f, ", current_time.real);
vpi_printf("nets in module %s ",
vpi_get_str(vpiFullName, module_handle));
vpi_printf("(%s):\n", vpi_get_str(vpiDefName, module_handle));
/* obtain handles to nets in module and read current value */
net_iterator = vpi_iterate(vpiNet, module_handle);
if (net_iterator == NULL)
vpi_printf(" no nets found in this module\n");
else {
current_value.format = vpiBinStrVal; /* read values as a string */
while ( (net_handle = vpi_scan(net_iterator)) != NULL ) {
vpi_get_value(net_handle, &current_value);
vpi_printf(" net %-10s value is %s (binary)\n",
vpi_get_str(vpiName, net_handle),
current_value.value.str);
}
}
return(0);
}
/*********************************************************************/

View File

@ -0,0 +1,17 @@
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
At time 20.00, signals in module top (top):
net results value is 10 (binary)
integer test value is 3 (decimal)
real foo value is 3.14
time bar value is f000000ac000000e
At time 30.00, signals in module top.i1 (addbit):
net a value is 1 (binary)
net b value is 1 (binary)
net ci value is 0 (binary)
reg sum value is 0 (binary)
reg co value is 1 (binary)
Simulation complete via $finish(1) at time 40 NS + 0

View File

@ -0,0 +1,56 @@
/**********************************************************************
* $show_all_signals example 1 -- Verilog HDL test bench.
*
* Verilog test bench to test the $show_all_signals PLI application on
* a 1-bit adder modeled using gate primitives.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module top;
tri [1:0] results;
integer test;
real foo;
time bar;
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
initial
begin
test = 3'b000;
foo = 3.14;
bar = 0;
bar[63:60] = 4'hF;
bar[35:32] = 4'hA;
bar[31:28] = 4'hC;
bar[03:00] = 4'hE;
#10 test = 3'b011;
#10 $show_all_signals(top);
#10 $show_all_signals(i1);
// #10 $stop;
#10 $finish;
end
endmodule
/*** An RTL level 1 bit adder model ***/
`timescale 1ns / 1ns
module addbit (a, b, ci, sum, co);
input a, b, ci;
output sum, co;
wire a, b, ci;
reg sum, co;
always @(a or b or ci)
{co, sum} = a + b + ci;
endmodule
/*********************************************************************/

View File

@ -0,0 +1,193 @@
/**********************************************************************
* $show_all_signals example 1 -- PLI application using VPI routines
*
* C source to scan through a module and list the names of all nets,
* reg and variables in the module, with their current logic value.
*
* Usage: $show_all_signals(<module_instance>);
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
#if VPI_1995
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
#endif
/* prototypes of the PLI application routines */
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data),
PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data);
void PLIbook_PrintSignalValues(vpiHandle signal_iterator);
/**********************************************************************
* $show_all_signals Registration Data
*********************************************************************/
void PLIbook_ShowSignals_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.sysfunctype = 0;
tf_data.tfname = "$show_all_signals";
tf_data.calltf = PLIbook_ShowSignals_calltf;
tf_data.compiletf = PLIbook_ShowSignals_compiletf;
tf_data.sizetf = NULL;
tf_data.user_data = NULL;
vpi_register_systf(&tf_data);
return;
}
/**********************************************************************
* compiletf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, arg_handle;
PLI_INT32 tfarg_type;
int err_flag = 0;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handles to system task arguments */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
vpi_printf("ERROR: $show_all_signals requires 1 argument\n");
err_flag = 1;
}
else {
/* check the type of object in system task arguments */
arg_handle = vpi_scan(arg_iterator);
tfarg_type = vpi_get(vpiType, arg_handle);
if (tfarg_type != vpiModule) {
vpi_printf("ERROR: $show_all_signals arg 1");
vpi_printf(" must be a module instance\n");
vpi_free_object(arg_iterator); /* free iterator memory */
err_flag = 1;
}
else {
/* check that there is only 1 system task argument */
arg_handle = vpi_scan(arg_iterator);
if (arg_handle != NULL) {
vpi_printf("ERROR: $show_all_signals can only have 1 argument\n");
vpi_free_object(arg_iterator); /* free iterator memory */
err_flag = 1;
} } } /* end of if-else-if-else-if sequence */
if (err_flag) {
vpi_control(vpiFinish, 1); /* abort simulation */
}
return(0);
}
/**********************************************************************
* calltf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, module_handle,
signal_iterator;
PLI_INT32 format;
s_vpi_time current_time;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handle to system task argument
compiletf has already verified only 1 arg with correct type */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
module_handle = vpi_scan(arg_iterator);
vpi_free_object(arg_iterator); /* free iterator memory */
/* read current simulation time */
current_time.type = vpiScaledRealTime;
vpi_get_time(systf_handle, &current_time);
vpi_printf("\nAt time %2.2f, ", current_time.real);
vpi_printf("signals in module %s ",
vpi_get_str(vpiFullName, module_handle));
vpi_printf("(%s):\n", vpi_get_str(vpiDefName, module_handle));
/* obtain handles to nets in module and read current value */
signal_iterator = vpi_iterate(vpiNet, module_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
/* obtain handles to regs in module and read current value */
signal_iterator = vpi_iterate(vpiReg, module_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
/* obtain handles to variables in module and read current value */
signal_iterator = vpi_iterate(vpiVariables, module_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
vpi_printf("\n"); /* add some white space to output */
return(0);
}
void PLIbook_PrintSignalValues(vpiHandle signal_iterator)
{
vpiHandle signal_handle;
PLI_INT32 signal_type;
s_vpi_value current_value;
while ( (signal_handle = vpi_scan(signal_iterator)) != NULL ) {
signal_type = vpi_get(vpiType, signal_handle);
switch (signal_type) {
case vpiNet:
current_value.format = vpiBinStrVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" net %-10s value is %s (binary)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.str);
break;
case vpiReg:
current_value.format = vpiBinStrVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" reg %-10s value is %s (binary)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.str);
break;
case vpiIntegerVar:
current_value.format = vpiIntVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" integer %-10s value is %d (decimal)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.integer);
break;
case vpiRealVar:
current_value.format = vpiRealVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" real %-10s value is %0.2f\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.real);
break;
case vpiTimeVar:
current_value.format = vpiTimeVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" time %-10s value is %x%x\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.time->high,
current_value.value.time->low);
break;
}
}
return;
}
/*********************************************************************/

View File

@ -0,0 +1,37 @@
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
At time 0.00, signals in scope top.i1:
net a value is 0 (binary)
net b value is 0 (binary)
net ci value is 0 (binary)
reg sum value is 0 (binary)
reg co value is 0 (binary)
At time 10.00, signals in scope top:
net results value is 00 (binary)
integer test value is 0 (decimal)
real foo value is 3.14
time bar value is f000000ac000000e
At time 20.00, signals in scope top.i1:
net a value is 0 (binary)
net b value is 1 (binary)
net ci value is 0 (binary)
reg sum value is 1 (binary)
reg co value is 0 (binary)
At time 30.00, signals in scope top.local:
reg foobar value is x (binary)
At time 40.00, signals in scope top.i1:
net a value is 0 (binary)
net b value is 1 (binary)
net ci value is 0 (binary)
reg sum value is 1 (binary)
reg co value is 0 (binary)
Simulation complete via $finish(1) at time 50 NS + 0

View File

@ -0,0 +1,61 @@
/**********************************************************************
* $show_all_signals example 2 -- Verilog HDL test bench.
*
* Verilog test bench to test the $show_all_signals PLI application on
* a 1-bit adder modeled using gate primitives.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module top;
tri [1:0] results;
integer test;
real foo;
time bar;
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
initial
begin
test = 3'b000;
foo = 3.14;
bar = 0;
bar[63:60] = 4'hF;
bar[35:32] = 4'hA;
bar[31:28] = 4'hC;
bar[03:00] = 4'hE;
#10 $show_all_signals;
begin: local
reg foobar;
#10 test = 3'b010;
#10 $show_all_signals;
#10 $show_all_signals(top.i1);
end
// #10 $stop;
#10 $finish;
end
endmodule
/*** An RTL level 1 bit adder model ***/
`timescale 1ns / 1ns
module addbit (a, b, ci, sum, co);
input a, b, ci;
output sum, co;
wire a, b, ci;
reg sum, co;
always @(a or b or ci)
{co, sum} = a + b + ci;
always @(sum)
$show_all_signals();
endmodule
/*********************************************************************/

View File

@ -0,0 +1,217 @@
/**********************************************************************
* $show_all_signals example 2 -- PLI application using VPI routines
*
* C source to scan through a scope and list the names of all nets,
* reg and variables in the scope, with their current logic value.
* - No argument or a null argument to $show_all_signals() is
* interpreted as the scope instance that called the application.
*
* Usage: $show_all_signals(<scope_instance>);
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
#if VPI_1995
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
#endif
/* prototypes of the PLI application routines */
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data),
PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data);
void PLIbook_PrintSignalValues(vpiHandle signal_iterator);
/**********************************************************************
* $show_all_signals Registration Data
*********************************************************************/
void PLIbook_ShowSignals_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.sysfunctype = 0;
tf_data.tfname = "$show_all_signals";
tf_data.calltf = PLIbook_ShowSignals_calltf;
tf_data.compiletf = PLIbook_ShowSignals_compiletf;
tf_data.sizetf = NULL;
tf_data.user_data = NULL;
vpi_register_systf(&tf_data);
return;
}
/**********************************************************************
* compiletf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, arg_handle;
PLI_INT32 tfarg_type;
int err_flag = 0;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handles to system task arguments */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
return(0); /* no arguments OK; skip remaining checks */
}
/* check the type of object in system task arguments */
arg_handle = vpi_scan(arg_iterator);
tfarg_type = vpi_get(vpiType, arg_handle);
switch (tfarg_type) {
case vpiModule:
case vpiTask:
case vpiFunction:
case vpiNamedBegin:
case vpiNamedFork:
break; /* arg is a scope instance; continue to next check */
case vpiOperation:
if (vpi_get(vpiOpType, arg_handle) == vpiNullOp)
break; /* null argument OK; continue to next check */
default:
/* wrong type specified for an argument */
vpi_printf("ERROR: $show_all_signals arg 1");
vpi_printf(" must be a scope instance or null\n");
vpi_free_object(arg_iterator); /* free iterator memory */
err_flag = 1;
}
if (err_flag == 0) {
/* check that there is only 1 system task argument */
arg_handle = vpi_scan(arg_iterator);
if (arg_handle != NULL) {
vpi_printf("ERROR: $show_all_signals can only have 1 argument\n");
vpi_free_object(arg_iterator); /* free iterator memory */
err_flag = 1;
} } /* end of tests */
if (err_flag) {
vpi_control(vpiFinish, 1); /* abort simulation */
}
return(0);
}
/**********************************************************************
* calltf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, scope_handle,
signal_iterator;
PLI_INT32 format;
s_vpi_time current_time;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handle to system task argument */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
/* no arguments -- use scope that called this application */
scope_handle = vpi_handle(vpiScope, systf_handle);
}
else {
/* compiletf has already verified arg is scope instance or null */
scope_handle = vpi_scan(arg_iterator);
vpi_free_object(arg_iterator); /* free iterator memory */
if (vpi_get(vpiType, scope_handle) != vpiModule)
/* arg isn't a module instance; assume it is null */
scope_handle = vpi_handle(vpiScope, systf_handle);
}
/* read current simulation time */
current_time.type = vpiScaledRealTime;
vpi_get_time(systf_handle, &current_time);
vpi_printf("\nAt time %2.2f, signals in scope %s:\n",
current_time.real,
vpi_get_str(vpiFullName, scope_handle));
/* obtain handles to nets in module and read current value */
/* nets can only exist if scope is a module */
if (vpi_get(vpiType, scope_handle) == vpiModule) {
signal_iterator = vpi_iterate(vpiNet, scope_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
}
/* obtain handles to regs in scope and read current value */
signal_iterator = vpi_iterate(vpiReg, scope_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
/* obtain handles to variables in scope and read current value */
signal_iterator = vpi_iterate(vpiVariables, scope_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
vpi_printf("\n"); /* add some white space to output */
return(0);
}
void PLIbook_PrintSignalValues(vpiHandle signal_iterator)
{
vpiHandle signal_handle;
int signal_type;
s_vpi_value current_value;
while ( (signal_handle = vpi_scan(signal_iterator)) != NULL ) {
signal_type = vpi_get(vpiType, signal_handle);
switch (signal_type) {
case vpiNet:
current_value.format = vpiBinStrVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" net %-10s value is %s (binary)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.str);
break;
case vpiReg:
current_value.format = vpiBinStrVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" reg %-10s value is %s (binary)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.str);
break;
case vpiIntegerVar:
current_value.format = vpiIntVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" integer %-10s value is %d (decimal)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.integer);
break;
case vpiRealVar:
current_value.format = vpiRealVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" real %-10s value is %0.2f\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.real);
break;
case vpiTimeVar:
current_value.format = vpiTimeVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" time %-10s value is %x%x\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.time->high,
current_value.value.time->low);
break;
}
}
return;
}
/*********************************************************************/

View File

@ -0,0 +1,36 @@
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
At time 0.00, signals in scope top.i1 (addbit):
net a value is 0 (binary)
net b value is 0 (binary)
net ci value is 0 (binary)
reg sum value is 0 (binary)
reg co value is 0 (binary)
At time 10.00, signals in scope top.i1 (addbit):
net a value is 1 (binary)
net b value is 0 (binary)
net ci value is 0 (binary)
reg sum value is 1 (binary)
reg co value is 0 (binary)
At time 20.00, signals in scope top.i1 (addbit):
net a value is 1 (binary)
net b value is 0 (binary)
net ci value is 0 (binary)
reg sum value is 1 (binary)
reg co value is 0 (binary)
At time 20.00, signals in scope top (top):
net results value is 01 (binary)
integer test value is 1 (decimal)
At time 20.00, signals in scope top (top):
net results value is 01 (binary)
integer test value is 1 (decimal)
Simulation complete via $finish(1) at time 30 NS + 0

View File

@ -0,0 +1,49 @@
/**********************************************************************
* $show_all_signals example 3 -- Verilog HDL test bench.
*
* Verilog test bench to test the $show_all_signals PLI application on
* a 1-bit adder modeled using gate primitives.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
`timescale 1ns / 1ns
module top;
integer test;
tri [1:0] results;
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
initial
begin
test = 3'b000;
#10 test = 3'b001;
#10 $show_all_signals(top.i1, ,top); /* second arg is null */
// #10 $stop;
#10 $finish;
end
endmodule
/*** An RTL level 1 bit adder model ***/
`timescale 1ns / 1ns
module addbit (a, b, ci, sum, co);
input a, b, ci;
output sum, co;
wire a, b, ci;
reg sum, co;
always @(a or b or ci)
{co, sum} = a + b + ci;
always @(sum)
$show_all_signals;
endmodule
/*********************************************************************/

View File

@ -0,0 +1,226 @@
/**********************************************************************
* $show_all_signals example 3 -- PLI application using VPI routines
*
* C source to scan through a scope and list the names of all nets,
* reg and variables in the scope, with their current logic value.
* - No argument or a null argument to $show_all_signals() is
* interpreted as the scope instance that called the application.
* - Any number of scope instances can be passed to
* $show_all_instances().
*
* Usage: $show_all_signals(<scope_instance>, <scope_instance>, ...);
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <stdarg.h> /* ANSI C standard arguments library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
#if VPI_1995
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
#endif
/* prototypes of the PLI application routines */
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data),
PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data);
void PLIbook_GetAllSignals(vpiHandle scope_handle,
p_vpi_time current_time),
PLIbook_PrintSignalValues(vpiHandle signal_iterator);
/**********************************************************************
* $show_all_signals Registration Data
*********************************************************************/
void PLIbook_ShowSignals_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.sysfunctype = 0;
tf_data.tfname = "$show_all_signals";
tf_data.calltf = PLIbook_ShowSignals_calltf;
tf_data.compiletf = PLIbook_ShowSignals_compiletf;
tf_data.sizetf = NULL;
tf_data.user_data = NULL;
vpi_register_systf(&tf_data);
return;
}
/**********************************************************************
* compiletf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, arg_handle;
PLI_INT32 tfarg_type;
int err_flag = 0, tfarg_num = 0;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* obtain handles to system task arguments */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
return(0); /* no arguments OK; skip remaining checks */
}
/* check each argument */
while ( (arg_handle = vpi_scan(arg_iterator)) != NULL ) {
tfarg_num++;
/* check the type of object in system task arguments */
tfarg_type = vpi_get(vpiType, arg_handle);
switch (tfarg_type) {
case vpiModule:
case vpiTask:
case vpiFunction:
case vpiNamedBegin:
case vpiNamedFork:
break; /* arg is a scope instance; continue to next check */
case vpiOperation:
if (vpi_get(vpiOpType, arg_handle) == vpiNullOp) {
break; /* null argument OK; continue to next check */
}
default:
/* wrong type specified for an argument */
vpi_printf("ERROR: $show_all_signals arg %d", tfarg_num);
vpi_printf(" must be a scope instance or null\n");
vpi_free_object(arg_iterator); /* free iterator memory */
err_flag = 1;
}
} /* end of tests */
if (err_flag) {
vpi_control(vpiFinish, 1); /* abort simulation */
}
return(0);
}
/**********************************************************************
* calltf routine
*********************************************************************/
PLI_INT32 PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data)
{
vpiHandle systf_handle, arg_iterator, scope_handle;
PLI_INT32 format;
s_vpi_time current_time;
/* obtain a handle to the system task instance */
systf_handle = vpi_handle(vpiSysTfCall, NULL);
/* read current simulation time */
current_time.type = vpiScaledRealTime;
vpi_get_time(systf_handle, &current_time);
/* obtain handle to system task argument */
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
/* no arguments -- use scope that called this application */
scope_handle = vpi_handle(vpiScope, systf_handle);
PLIbook_GetAllSignals(scope_handle, &current_time);
}
else {
/* compiletf has already verified arg is scope instance or null */
while ( (scope_handle = vpi_scan(arg_iterator)) != NULL ) {
if (vpi_get(vpiType, scope_handle) != vpiModule) {
/* arg isn't a module instance; assume it is null */
scope_handle = vpi_handle(vpiScope, systf_handle);
}
PLIbook_GetAllSignals(scope_handle, &current_time);
}
}
return(0);
}
void PLIbook_GetAllSignals(vpiHandle scope_handle, p_vpi_time current_time)
{
vpiHandle signal_iterator;
vpi_printf("\nAt time %2.2f, ", current_time->real);
vpi_printf("signals in scope %s ",
vpi_get_str(vpiFullName, scope_handle));
vpi_printf("(%s):\n", vpi_get_str(vpiDefName, scope_handle));
/* obtain handles to nets in module and read current value */
/* nets can only exist if scope is a module */
if (vpi_get(vpiType, scope_handle) == vpiModule) {
signal_iterator = vpi_iterate(vpiNet, scope_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
}
/* obtain handles to regs in scope and read current value */
signal_iterator = vpi_iterate(vpiReg, scope_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
/* obtain handles to variables in scope and read current value */
signal_iterator = vpi_iterate(vpiVariables, scope_handle);
if (signal_iterator != NULL)
PLIbook_PrintSignalValues(signal_iterator);
vpi_printf("\n"); /* add some white space to output */
return;
}
void PLIbook_PrintSignalValues(vpiHandle signal_iterator)
{
vpiHandle signal_handle;
int signal_type;
s_vpi_value current_value;
while ( (signal_handle = vpi_scan(signal_iterator)) != NULL ) {
signal_type = vpi_get(vpiType, signal_handle);
switch (signal_type) {
case vpiNet:
current_value.format = vpiBinStrVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" net %-10s value is %s (binary)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.str);
break;
case vpiReg:
current_value.format = vpiBinStrVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" reg %-10s value is %s (binary)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.str);
break;
case vpiIntegerVar:
current_value.format = vpiIntVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" integer %-10s value is %d (decimal)\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.integer);
break;
case vpiRealVar:
current_value.format = vpiRealVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" real %-10s value is %0.2f\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.real);
break;
case vpiTimeVar:
current_value.format = vpiTimeVal;
vpi_get_value(signal_handle, &current_value);
vpi_printf(" time %-10s value is %x%x\n",
vpi_get_str(vpiName, signal_handle),
current_value.value.time->high,
current_value.value.time->low);
break;
}
}
return;
}
/*********************************************************************/

View File

@ -0,0 +1,6 @@
// Example Synopsys VCS PLI table to register PLI applications
// For the book, "The Verilog PLI Handbook"
$show_all_nets call=PLIbook_ShowNets_calltf check=PLIbook_ShowNets_compiletf data=0 acc+=read:*
$show_all_signals call=PLIbook_ShowSignals_calltf check=PLIbook_ShowSignals_compiletf data=0 acc+=read:*

View File

@ -0,0 +1,25 @@
/**********************************************************************
* Example vpi_user.c file
*
* vpi_user.c file to register PLI applications using the VPI library.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland-hdl.com
*********************************************************************/
#include "vpi_user.h"
/* prototypes of the PLI registration routines */
extern void PLIbook_ShowNets_register();
extern void PLIbook_ShowSignals_register();
void (*vlog_startup_routines[])() =
{
/*** add user entries here ***/
PLIbook_ShowNets_register,
PLIbook_ShowSignals_register,
0 /*** final entry must be 0 ***/
};

View File

@ -0,0 +1,23 @@
#
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
#
MTI_INSTALL_DIR=c:\progra~1\ModelTech
SOURCES = \
count_args_vpi_test.c \
get_arg_handle_vpi_test.c \
list_pathout_ports_vpi.c \
port_info_vpi.c \
count_all_prims_vpi.c \
invoke_options_vpi.c \
vpi_user.c
OBJS = $(SOURCES:.c=.obj)
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
.c.obj:
$(CC) $(CFLAGS) -c $<
../mti_pli.dll: $(OBJS)
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib

Some files were not shown because too many files have changed in this diff Show More