下冰雹 · 2023年05月12日

浅谈System Verilog的DPI机制

提纲:

1. DPI相关概念介绍

2. 一个通过DPI集成matlab代码的例子。

3. 一个VCS和matlab工具的兼容问题的例子。

4. 题外话:话别。

在上一篇《浅谈建模的意义和验证的危机》中,曾大肆鼓吹“对于认知DUT,行为建模既是方法,也是目的”,“心中没有她,又怎能待好她”,呼吁IC验证者要通过手写DUT的reference model来实现对DUT的规格特性的充分理解。然而,此篇内容却涉及调用第三方的代码作为reference model。此刻耳畔仿佛想起了啪啪的打脸之声。

System Verilog(SV)把其他编程语言统一成为外语,Foreign Programming Language(FPL)。Direct Programming Interface(DPI)是SV定义的一种专门集成外语代码和处理SV之外的业务功能的机制,主要负责和广大的外部语言代码进行沟通和交涉。如果用西安的各所大学来比喻SV的各个机制功能,那么DPI对应的大致就是西安外事学院了。

image.png

海纳百川,有容乃大是川大的校训。SV的制定者希望Test Bench能兼济包容,也不希望所有组件和代码都只能是由SV语言开发。并且不得不承认,通过集成C/C++/Matlab的代码,会缩短搭建验证平台的时间,减少IC验证者的工作量。

在DPI机制中,仿真系统的资源被分成独立的两部分:SV-domain(SV语言区域)和FPL-domain(其他语言区域)。这些资源包括缓存数据和变量的存储资源,也包括程序编译链接和执行的运行资源。在验证平台中调用FPL程序代码时要遵循黑盒原则,即FPL代码涉及的业务功能是独立的,与SV部分要充分解耦。在SV和FPL中无法直接访问对方代码中的变量。

他们就像白天和黑夜。虽然黑夜给了我们黑色眼睛,我们也曾用它去寻找光明,但是黑夜永远不懂光明,正如白天不懂夜色的黑。

image.png

System Verilog 3.1版本支持的FPL只有C。其他语言可以通过C写的wrapper包装一下实现跟SV的通信。

DPI专门定义了一些数据类型,这些数据类型与SV的多种数据有对应关系。在C程序的接口处,使用这些专门定义的参数,利用数据类型的对应关系,实现SV-domain和C-domain的通信。为了便于使用,SV还为某些重要的数据类型,量身定制了一系列的操作和处理函数。如何使用这些数据类型和相应的操作函数实现两个domain的数据传递和转换,是DPI关键技术点,也是本文的干货所在。

通常情况,C的函数都是不消耗仿真时间,即延时是0,瞬间完成,就像在SV中调用function一样。只不过这个function的端口类型只有input,output和inout,不支持ref。

为了把C语言的数据类型能映射到SV语言,SV定义了一个文件svdpi.h。在该文件中定义了许多的数据类型,这些类型基本可以和C语言的数据类型一一对应。

image.png

上面表格是我挑出的比较重要的几种数据类型,而其中比较重要的是open array[]。

绿皮书有一章节(12.5)专门介绍它,在svdpi.h中也专门为它定义了很多的微操函数。

在C语言里面,函数接口的参数会划分方向,对于输入的变量,加上const,一旦在C程序中,对输入变量进行赋值操作,编译器会报错。我觉得犯这种错误的概率太低,没必要加。问道于何同学,觉得这种错误还是比较常见的,建议加上。

image.png

在SV角度看,open array[ ]就是动态数组(dynamic array)。SV之所以选择动态数组来进行SV和C之间的数据内容传递,是因为动态数组的深度可以灵活改变。只要在定义dpi接口的时候,把动态数组的名称和C的对应的数组关联上,那么只需要在不同的场景中,通过动态的改变动态数组的深度,就可实现SV和C的数据传递。

队列(queue)表示有意见,嘟嘟囔囔的撅着小嘴问,为啥不选我?

先坐下吧,闵老师扶了扶眼镜说,SV和C的数据存储虽然都放在内存中,但是系统需要把它们俩的存储空间分开,最忌讳内存越界。动态数组在每次使用之前,需要先通过new[N]来分配空间,之后动态数组的内存空间就确定了。然而队列的存储空间是一直可变的,SV虽然会初始时刻给你分配一定空间,但是当元素把空间装满后,SV会自动分配更多的空间。这样就容易造成内存越界。

关联数组(associative array)也想发言,把肥嘟嘟的小手举得高高的。

先把手放下来,闵老师笑着轻轻摆了摆手,你太离散了,存储的都是稀疏和分散的数据,SV仿真器要采用tree或hash table的方式来存放,会带来额外的存储开销。

以上就是DPI的相关背景介绍。干说不练假把式,我们举个例子吧。

如下图所示,peak\_find是一个matlab函数,输入变量signal包含多个无符号数据,经过一系列运算和处理,输出4个无符号数据到变量peak\_two之中。

image.png

将该函数集成到SV的Test Bench中,使用matlab engine的方式需要定义一个c程序将其包起来,名称如下所示。

void peak_find_dpi(const svOpenArrayHandle signal_i, svOpenArrayHandle peak_two_o);

其接口参数就用到了开放数组。

该C函数可分为如下几步:

image.png
图4 dpi.c的流程图

站在SV角度看,C程序是外来的,是舶来品,需要“进口”,即import。代码只需一行: import “DPI-C” function void name_of_your_c_function();

假如我们国家只能进口美国的商品,其他国家的货物就得都先到美国,再来中国。同样的道理,用matlab engine的方式,调用matlab程序,得用C程序先包装一下。

matlab程序如此,C++程序亦是如此。

对于C程序,仿真时通常是用GCC编译,而matlab程序是用到了mathWorks公司的MATLAB工具,SV仿真需要用到Synopsys公司的VCS工具。夜路走的多了难免遇到鬼,工具用的多了也难免有版本问题。

so文件报错是一个典型的工具版本不一致引入的问题。如下图所示。这个问题其实是IT问题,不是IC验证技术问题,但是它跟IC验证息息相关。

image.png

就像神农尝百草,梅同学通过尝试多个版本的MATLAB,GCC和VCS,最终发现GCC4.8.5+MATLAB2015B+2017以上VCS的组合可以比较稳妥。同时把/usr/lib64/libstdc++.so也要更新到6.0.21。遂搞定这个问题。

题外话:

有人说,这是一个习惯离开的世界,他却不习惯道别。

有人说,天下没有不散的筵席,他也走在赴宴的路上。

祝福曾经的我的同路人,平安顺遂,得偿所愿,幸福安康。

作者:一只特立独行的猪
文章来源:IC验证者之家

推荐阅读
在芯片研发工作中,你犯过哪些“愚蠢”的错误?
UVM response_handler和get_response机制
【芯知识】SoC设计的IO PAD怎么移植到FPGA原型验证

更多FPGA干货请关注IC设计技术专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
19303
内容数
1296
主要交流IC以及SoC设计流程相关的技术和知识
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息