首页 > 其他分享 >PLI 学习

PLI 学习

时间:2024-12-09 15:46:44浏览次数:3  
标签:simv sv 学习 so user vpi hello PLI

PLI 学习

介绍

参考文献:

  1. Verilog PLI已死( 可能), SystemVerilog DPI当立_sutherland hdl-CSDN博客

下面的表格非常详细的讲述了DPI和VPI的区别,总结一下:

  • DPI不是VPI的超集,两个不能完全替代
  • DPI适合verilog和c相互传递数据,互相调用的场景。
  • VPI最早为EDA工具开发,可以实现对设计数据结构的遍历访问。

SystemVerilog DPI与Verilog PLI功能比较.png

使用VPI的步骤(以hello word为例)

参考文献:

  1. linux下gcc编译生成.out,.o,.a,.so文件_gcc *.a *.o-CSDN博客

下面使用的设计文件(testbench.sv​)如下:

`timescale 1ns / 1ns
module test;

  initial
    begin
      $hello;
      #10 $finish;
    end
endmodule

普通方式(一起编译)

这种方式,将c和verilog文件一起编译。可以分成4步:

⚠这种方式,不同通过file_list提供c文件,c文件只能在命令行中提供。因为vcs默认file_list中全是verilog文件。

  1. 定义系统任务或函数

    文件名:hello_vpi.c

    #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);
    }
    
  2. 写一个c语言的calltf routine​,当仿真器遇到用户自定义的系统任务或函数时,就会根据calltf routine​调用指定的c函数

    文件名:veriuser_VCS.tab

    $hello      call=PLIbook_hello_calltf data=
    
  3. 注册用户自定义的系统任务或函数,告诉仿真器任务或函数名,以及相关的calltf routine

    文件名:vpi_user.c

    #include "vpi_user.h"
    
    /* prototypes of the PLI registration routines */
    extern void PLIbook_hello_register();
    
    void (*vlog_startup_routines[])() = 
    {
        /*** add user entries here ***/
      PLIbook_hello_register,
      0 /*** final entry must be 0 ***/
    };
    
  4. 编译c文件

    comp:
    	- vcs -full64 +v2k -sverilog -debug_access+all -top testbench -l compile.log \
    		testbench.sv hello_vpi.c -P veriuser_VCS.tab
    sim:
    	- ./simv -l sim.log
    clean:
    	- \rm -rf *.log simv simv.daidir *.a *.o *.so csrc *.key
    

这样一个简单的Hello world的例子就完成了。

静态库

verdi提供的生成波形的函数,本质上也是利用vpi实现的。观察到使用verdi生成波形时通常需要在vcs编译时加入如下语句:

-P ${VERDI_HOME}/share/PLI/VCS/LINUX64/novas.tab ${VERDI_HOME}/share/PLI/VCS/LINUX64/pli.a

.a​是linux的静态库文件,.so​是linux的动态库文件。可以参考:linux下gcc编译生成.out,.o,.a,.so文件_gcc *.a *.o-CSDN博客

为了方便调用自定义系统函数或任务,我们也采用提供静态连接库的方法。改动后的Makefile如下:

libhello.a: hello_vpi.c vpi_user.c
	- gcc -c hello_vpi.c vpi_user.c -I ${VCS_HOME}/include
	- ar -cr libhello.a hello_vpi.o vpi_user.o
comp_s: libhello.a
	- vcs -full64 +v2k -sverilog -debug_access+all -top testbench -l compile.log \
		testbench.sv -P veriuser_VCS.tab libhello.a
sim:
	- ./simv -l sim.log
clean:
	- \rm -rf *.log simv simv.daidir *.a *.o *.so csrc *.key

这样就完成了静态库的编译和调用,可以在验证环境中自由使用自定义的系统任务或函数。

动态库-sv_lib

同样的我们也可以使用动态库的方式。

首先需要知道simv​文件可以在执行的时候指定库路径和库名称:

  • -sv_root .​: 指定.​为库所在路径
  • -sv_lib libhello​(可以省略库后缀.so​):指定加载库文件libhello.so

官方文档将-sv_lib​选项用于DPI,但是实际验证也可以用于载入VPI,和-load​选项差别不大

采用动态库方式Makefile文件如下:

libhello.so: hello_vpi.c vpi_user.c
	- gcc -fPIC -c hello_vpi.c vpi_user.c -I ${VCS_HOME}/include
	- gcc -shared -o libhello.so hello_vpi.o vpi_user.o
#libhello.so: hello_vpi.c vpi_user.c
#	- gcc -fPIC -shared -o libhello.so -c hello_vpi.c vpi_user.c -I ${VCS_HOME}/include
comp_d: libhello.so
	- vcs -full64 +v2k -sverilog -debug_access+all -top testbench -l compile.log \
		testbench.sv -P veriuser_VCS.tab
sim:
	- ./simv -l sim.log -sv_root . -sv_lib libhello
clean:
	- \rm -rf *.log simv simv.daidir *.a *.o *.so csrc *.key

还可以使用-sv_liblist bootstrap_file​,载入多个库文件

#!SV_LIBRARIES
myclibs/lib1
myclibs/lib3

动态库-load

官方推荐使用-load​载入VPI的库,经过测试可以使用-sv_lib代替-load,但是不能反过来。

  • -load​可以多次指定不同的库
  • -load​可以指定带目录结构的库

image-20241122151559-yfxcjw8.png

libhello.so: hello_vpi.c vpi_user.c
	- gcc -fPIC -c hello_vpi.c vpi_user.c -I ${VCS_HOME}/include
	- gcc -shared -o libhello.so hello_vpi.o vpi_user.o
#libhello.so: hello_vpi.c vpi_user.c
#	- gcc -fPIC -shared -o libhello.so -c hello_vpi.c vpi_user.c -I ${VCS_HOME}/include
comp_d: libhello.so
	- vcs -full64 +v2k -sverilog -debug_access+all -top testbench -l compile.log \
		testbench.sv -P veriuser_VCS.tab
sim:
	- ./simv -l sim.log -load ./libhello.so
clean:
	- \rm -rf *.log simv simv.daidir *.a *.o *.so csrc *.key

小结

优点 缺点
普通方式 编译脚本简单 当c文件多的时候,难以维护
静态库 使用方便简单 需要先编译静态库
动态库 可执行文件体积小,方便多个程序之间共享。
可以单独更新动态库,不重新编译主程序。
需要先编译动态库,还需要在运行时指定库和库路径

三种方法各有优缺点,但从ASIC验证人员角度来说,cmodel通常文件多且较为复杂,并不在乎可执行文件的体积大小。因此优先推荐静态库的方法。

具体使用的时候,推荐将c文件和设计文件分开管理,分开编译。

使用DPI的步骤(以hello world为例)

普通方式(一起编译)

testbench.sv

module testbench;
    import "DPI-C" context function int c_hello(input string name, input int age);
    export "DPI-C" function sv_hello;
    function void sv_hello();
        $display("sv_hello");
    endfunction

    initial begin
        c_hello("testbench", 18);
    end
endmodule

sv_main.c

#include <svdpi.h>
#include <vpi_user.h>
#include <stdio.h>

extern void sv_hello();
int c_hello(const char *name, int age) {
    vpi_printf("c_hello: %s, %d\n", name, age);
    sv_hello();
    return 0;
}

Makefile

comp:
	- vcs -full64 +v2k -sverilog -LDFLAGS -Wl,--no-as-needed -debug_access+all -top testbench -l compile.log \
		sv_main.c testbench.sv
sim:
	- ./simv -l sim.log
clean:
	- \rm -rf *.log simv simv.daidir *.a *.o *.so csrc *.key

⚠ 如果在import的函数中使用了export的函数,则import的时候必须使用context​关键字。

动态库-sv_lib

可以分成两步。首先编译动态库,然后再仿真的时候调用。

⚠ 经过测试不能使用-load​代替-sv_lib​。

Makefile

libsv_main.so: sv_main.c
	- gcc -fPIC -c sv_main.c -I ${VCS_HOME}/include
	- gcc -shared -o sv_main.so sv_main.o
#libsv_main.so: sv_main.c
#	- gcc -fPIC -shared -o libsv_main.so -c sv_main.c -I ${VCS_HOME}/include
comp:
	- vcs -full64 +v2k -sverilog -LDFLAGS -Wl,--no-as-needed -debug_access+all -top testbench -l compile.log \
		testbench.sv
sim: linbsv_main.so
	- ./simv -l sim.log -sv_root . -sv_lib sv_main
clean:
	- \rm -rf *.log simv simv.daidir *.a *.o *.so csrc *.key

标签:simv,sv,学习,so,user,vpi,hello,PLI
From: https://www.cnblogs.com/fengbohan/p/18595069/pli-learning-zx6kpe

相关文章

  • Top Cluster 树分块入门学习笔记
    定义树簇(Cluster):将树上的边划分为若干个连通块,称为树簇。界点、内点:每个树簇内有两个界点,其他点为内点,满足两个树簇至多交于一个界点。簇路径:对于每个树簇,其内部两个界点之间的路径为簇路径。由于这里不是学习TopTree的地方,所以舍去了某些其他内容。树簇分块给定......
  • 【深度学习】图片数据处理和清洗
    数据清洗是数据处理的一项重要步骤,对于深度学习算法至关重要,通常在采集到大量数据进行标注训练前需要做一些数据清洗工作。数据清洗一般包含以下方法:一.去除重复和冗余样本在采集到的数据样本中,可能会存在大量重复或高相似度样本,这些数据可能会导致模型过拟合、降低模......
  • 强化学习:基于课程学习的强化学习算法 —— 《Combining Reward Shaping and Curriculu
    地址:https://www.tesble.com/10.1109/ICTC.2018.8539438我们在四种不同的奖励函数和终止条件下对行走者进行了训练,以评估结合奖励塑形和课程学习的效果。具体如下。1)距离稀疏奖励:行走者到达目标时给予1个奖励,否则为0。2)距离课程奖励:给予行走者的奖励与行走者距离稀疏奖励......
  • 【Linux探索学习】第三弹——Linux的基础指令
    前言:在前面我们已经讲了有十几个Linux的基础指令及相关的知识了,今天我们再补充几个重点的基础指令,给基础指令收个尾,为下面的内容做准备目录一、date指令时间显示设定时间时间戳二、cal指令三、find指令find指令which指令whereis指令四、grep指令五、zip/unzip指......
  • USB PD 3.1协议学习
    USBPD3.1那什么是USB_PD_3.1呢?USB3.1是USB的一种传输标准,速度可以达到10Gbit/s,那PD是什么?PD(PowerDelivery)就是电力输送,也就是充放电用的,它可以达到最高100W的功率。1、资料下载地址USB_Power_Deliery_3.1文档下载链接2、Type-C接口信号组信号描述USB3.1RX2+,R......
  • GObject学习笔记(二)类型创建与注册
    前言本文可在https://paw5zx.github.io/GObject-tutorial-beginner-02/中阅读,体验更加在上一节中我们介绍了GObject类型的类和实例变量的创建和使用。GObject是一个基本的可实例化类类型,是所有使用GObject系统的类型的基类,提供了继承、封装、多态等面向对象的核心特性。不过我们......
  • CTF学习笔记
    RSA入门(二)-Kicky_Mu-博客园按键音(即DTMF)解密网站:DTMFDecoderPHP伪协议e.ghttp://node5.anna.nssctf.cn:25660/falg.php不能通过换思路http://node5.anna.nssctf.cn:25660/flag或者?file=php://filter/resource=flagwebdog1_startif(isset($_GET['web'])){$f......
  • 归纳偏差——深度学习
    一、定义在机器学习和深度学习的语境中,归纳偏差(inductivebias)是指学习算法(如神经网络)在学习过程中对数据所做的假设。这些假设帮助算法在面对有限的训练数据时,能够选择一种合适的模型,并且将从训练数据中学到的知识泛化到未见过的数据上。它就像是一种先验知识,引导模型的学习......
  • 从「读万卷书」到「行万里路」:大语言模型中的强化学习之路
    在过去的两年里,AI尤其是大语言模型(LLM)领域发展迅猛,从ChatGPT的崛起到各大厂纷纷推出自家大模型,几乎天天有新进展。对于许多程序员而言,这些模型在预训练和微调上的方法可能早已耳熟能详:先用海量文本数据进行自监督学习(Self-SupervisedLearning),再通过人类反馈(如RLHF)对模型......
  • 【机器学习】机器学习的基本分类-无监督学习-K-Means聚类
    K-Means是一种基于划分的无监督学习算法,用于数据聚类任务,它通过迭代优化将数据分组为k 个互斥的簇,使得每个簇内数据点的相似性最大化,而簇间的相似性最小化。它通过最小化簇内样本点到簇中心的距离平方和(即误差平方和,SSE)来完成聚类任务。1.算法原理目标函数K-Means的目......