开发指南)
编译器硬件仿真EDA【免费下载链接】iverilogIcarus Verilog项目地址https://gitcode.com/gh_mirrors/iv/iverilog点击查看免费下载本篇指南以 Icarus Verilog 开发者文档 Documentation/developer/guide/vpi/index.rst 及其两个子文档vpi.rst、va_math.rst为核心骨架讲解 Icarus Verilog 中 VPIVerilog Procedural InterfacePLI 2.0 的一部分模块的运行时加载机制、模块搜索路径、内置核心模块以及随发行版附带的 Verilog-A 数学库va_math的完整函数与常量清单。读完本文你将掌握 VPI 模块的导出符号约定vlog_startup_routines与vpip_set_callback、如何编译与加载.vpi模块、如何通过VPI_TRACE环境变量调试 VPI 调用并能在自己的 Verilog/Verilog-A 仿真中直接使用$ln、$sqrt、$sin等数学系统函数与\M_PI 等数学常量。一、VPI 模块的本质把一组 PLI 应用打包成一个共享库Icarus Verilog 的 VPI 接口工作机制与传统的 PLI 1.0TF/ACC不同它不是把一个个 PLI 应用单独加载而是把一组 PLI 应用源码编译链接成一个单一的 VPI 模块.vpi共享对象再由运行时按需加载。这是理解 Icarus Verilog VPI 架构的第一条原则。在 Documentation/developer/guide/vpi/vpi.rst 中对此有明确说明VPI 模块由一系列 PLI 应用的编译代码链接而成连同这些应用依赖的其他库最终产出一个带两个导出符号的模块vpip_set_callback函数vlog_startup_routines数组。这两个符号就是运行时与该模块之间的唯一“握手协议”。1.1 加载协议跳转表 启动例程表调用 VPI 模块的产品通常是仿真运行时vvp加载模块后会执行以下两步定位并调用vpip_set_callback函数向模块传递一张“跳转表”jump table即指向 VPI 例程的函数指针集合使模块能够访问由产品实现的 VPI 例程如vpi_get_value、vpi_put_value、vpi_register_systf等定位vlog_startup_routines表并按顺序调用表中列出的所有启动例程startup routines。一个产品可以同时链接多个模块。此时所有模块都会被链接进来各模块的启动例程按顺序依次被调用——因此模块之间是“先后注册、互不干扰”的关系注册顺序即加载顺序。从源码看这套协议在 vvp/vpi_modules.cc 中实现。vpip_load_module()函数的执行流程与文档描述完全对应先按模块名构造候选文件路径用stat()探测文件是否存在用ivl_dlopen()打开共享库vvp/vpi_modules.cc在 Windows/Cygwin 平台上查找并调用vpip_set_callback符号传入vpi_routines跳转表与vpip_routines_version版本号做兼容性校验vvp/vpi_modules.cc用ivl_dlsym()查找vlog_startup_routines表vvp/vpi_modules.cc若找不到则报错no vlog_startup_routines将 DLL 记入内部dll_list退出时统一dlclose然后置VPI_MODE_REGISTER模式依次执行表中每个启动例程最后恢复VPI_MODE_NONEvvp/vpi_modules.cc。1.2 启动例程表模块作者必须提供vlog_startup_routines是以 0 结尾的函数指针数组模块作者负责把它编译进模块。例如 examples/hello_vpi.c 中的典范写法void (*vlog_startup_routines[])() { my_hello_register, 0 };启动例程的职责是向运行时注册本模块提供的系统任务与系统函数。一个模块可以实现任意多个任务/函数因此一个模块完全可以作为一个“系统任务库”来组织——这正是va_math、v2005_math等内置模块的组织方式。注册的核心调用是vpi_register_systf()例如 vpi/va_math.c 中的va_math_register()正是把所有数学函数注册为vpiSysFunc/vpiRealFunc类型的系统函数。二、模块搜索路径VPI_MODULE_PATH 环境变量产品通过模块名称加载模块时需要知道去哪里找文件。文档规定产品使用环境变量VPI_MODULE_PATH它是一个以冒号:分隔的目录列表即模块搜索路径。当按名称请求一个模块时运行时按顺序扫描该路径直到定位到模块文件为止。需要特别指出当前仓库实现中的一个命名差异从源码看vvp/vpi_modules.cc 实际读取的环境变量名为IVERILOG_VPI_MODULE_PATHvvp/vvp.man.in 手册页中也写作IVERILOG_VPI_MODULE_PATH/some/path:/some/other/path。阅读文档时可将两者视为同一概念的“文档名/实现名”关系配置环境时以仓库实现名为准。实现细节vvp/vpi_modules.cc搜索路径分隔符在类 Unix 平台为:在 WindowsMINGW/Cygwin为;除环境变量外编译期宏MODULE_DIR1、MODULE_DIR2指定的默认目录也会加入搜索路径vvp/vpi_modules.cc路径表容量上限为VPIP_MODULE_PATH_MAX64 条超出会报错退出若模块名中包含目录分隔符/或 Windows 下的\则被视作完整路径直接使用依次尝试name、name.vpi、name.vpl否则在搜索路径的每个目录中依次尝试name.vpi、name.vplvvp/vpi_modules.cc。除了环境变量vvp命令行还提供两个直接控制搜索路径的选项vvp/main.cc-M path VPI module directory 向搜索路径追加一个目录 -M - Clear VPI module path 清空搜索路径 -m module Load vpi module 按名加载模块对应到源码-M path调用vpip_add_module_path()-M -调用vpip_clear_module_paths()并同时禁用默认路径。因此一个典型的运行命令形如vvp -M. -mhello_vpi hello_vpi这正是 examples/hello_vpi.vl 注释中给出的用法-M.把当前目录加入搜索路径-mhello_vpi加载当前目录下的hello_vpi.vpi模块。三、随发行版附带的核心 VPI 模块文档明确列出以下特殊模块名属于 Icarus Verilog 核心发行版的一部分它们实现了标准系统任务/函数模块名用途system.vpi核心系统任务/函数$display、$finish、$monitor等总是随运行时加载v2005_math.vpi2005 版标准数学系统函数v2009.vpi2009 版SystemVerilog 相关系统任务/函数va_math.vpiVerilog-A 数学系统函数详见本文第五、六章vhdl_sys.vpi支持 VHDL 目标所需的私有系统函数vhdl_textio.vpi支持 VHDLtextio所需的私有系统函数其中system.vpi始终加载为设计中的系统任务调用提供实现其余模块按需通过-m加载。这些模块的实现位于仓库的 vpi/ 目录下例如vpi/sys_*.c系列文件对应system.vpi的各项系统任务vpi/v2005_math.c对应v2005_math.vpivpi/vhdl_table.c、vpi/vhdl_textio.c对应 VHDL 辅助模块。四、编译 VPI 模块编译 VPI 模块的完整教程见用户文档 Documentation/usage/vpi.rst即原文档中:doc:Using VPI ../../../usage/vpi 指向的页面位于仓库根目录下的Documentation/usage/vpi.rst。其核心要点是把模块源码当作 DLL/共享对象来编译和链接。手工方式Linux gcc前提是vpi_user.h头文件与libvpi.a库已安装且编译器能找到它们gcc -c -fpic hello.c gcc -shared -o hello.vpi hello.o -lvpi推荐方式跨平台、更省事所有受支持系统上通用iverilog-vpi hello.civerilog-vpi工具接收模块的源码文件作为命令行参数自动带上正确的编译选项、系统相关库与链接选项生成hello.vpi。其底层实现可参考 driver-vpi/iverilog-vpi.shPOSIX shell 脚本与 driver-vpi/main.cWindows 原生 C 实现还支持--name、-I、-D、-l、--cflags、--ldflags、--ldlibs、--install-dir等附加选项。一个最小可用的模块源码模板改自 examples/hello_vpi.c#include vpi_user.h static PLI_INT32 my_hello_calltf(char *xx) { vpi_printf(Hello World, from VPI.\n); return 0; } static void my_hello_register() { s_vpi_systf_data tf_data; tf_data.type vpiSysTask; tf_data.tfname $my_hello; tf_data.calltf my_hello_calltf; tf_data.compiletf 0; tf_data.sizetf 0; vpi_register_systf(tf_data); } void (*vlog_startup_routines[])() { my_hello_register, 0 };配套的 Verilog 测试文件 examples/hello_vpi.vl 展示了完整的编译与运行闭环iverilog -ohello_vpi hello_vpi.vl # 编译设计 vvp -M. -mhello_vpi hello_vpi # 加载模块并运行关于iverilog-vpi与-m选项的更细参数说明可继续阅读 Documentation/usage/vpi.rst 与 Documentation/usage/command_line_flags.rst。五、追踪 VPI 调用VPI_TRACE 环境变量当 VPI 模块行为异常、需要调试问题时vvp提供了 VPI 调用追踪能力。文档给出的启用方法非常简单——设置VPI_TRACE环境变量其值为写入追踪文本的文件路径setenv VPI_TRACE /tmp/foo.txtbash 语法下等价写法为export VPI_TRACE/tmp/foo.txt。从源码看该机制在 vvp/vpi_priv.cc 中实现有两个值得注意的增强细节若VPI_TRACE的值为单个字符-追踪文本会直接写到stdout方便快速查看否则按指定路径以写模式打开文件并用setvbuf(..., _IOLBF, ...)设置为行缓冲确保追踪文本及时落盘。文档同时给出两条重要的实践忠告追踪输出非常冗长verbose日常运行不要开启只在调试时临时启用追踪消息的格式不稳定——作者明确表示格式会随需求甚至心情改变因此不要尝试用软件解析该格式它只适合人类阅读排错。六、va_mathVerilog-A 数学库va_math.vpi是随 Icarus Verilog 发行版附带的 Verilog-A 数学库模块其说明文档为 Documentation/developer/guide/vpi/va_math.rst实现源码为 vpi/va_math.c。它把 Verilog-A 标准提供的数学函数全部实现为Verilog-D 系统函数函数名保持不变只是按 Verilog-D 的惯例在名称前加$前缀。该库基于 GNU GPLv2 或更高版本许可发布。6.1 标准 Verilog-A 数学函数全表文档完整列出了库所实现的函数参数x、y均为数值系统函数含义$ln(x)自然对数$log10(x)常用对数十进制对数$exp(x)指数$sqrt(x)平方根$min(x,y)最小值$max(x,y)最大值$abs(x)绝对值$floor(x)向下取整$ceil(x)向上取整$pow(x,y)幂运算x 的 y 次方$sin(x)正弦$cos(x)余弦$tan(x)正切$asin(x)反正弦$acos(x)反余弦$atan(x)反正切$atan2(y,x)y/x 的反正切四象限$hypot(x,y)斜边长度sqrt(x**2 y**2)$sinh(x)双曲正弦$cosh(x)双曲余弦$tanh(x)双曲正切$asinh(x)反双曲正弦$acosh(x)反双曲余弦$atanh(x)反双曲正切关于参数与结果的约束文档给出了明确的边界说明库对x、y的唯一限制是它们必须是数值number不能是常量字符串其余参数限制完全交给底层 C 数学库决定多数 C 库对无法用实数表示的结果返回-Inf或NaN所有函数都返回 real实数类型结果。6.2 源码层面的实现佐证阅读 vpi/va_math.c 可以印证上述行为模块把函数按参数个数分为两组单参数函数表va_single_data与双参数函数表va_double_datavpi/va_math.c表中以{名字, C函数指针}形式组织以{0,0}结尾参数检查在compiletfva_single_argument_compiletf/va_double_argument_compiletf阶段完成缺参数、多参数会通过va_error_message()报错并vpi_control(vpiFinish, 1)结束仿真va_process_argument()会拒绝字符串常量参数报错信息为%s cannot process stringsvpi/va_math.c真正计算在calltf阶段完成用vpi_get_value()取实参调用底层 C 数学函数计算再用vpi_put_value(..., vpiRealVal, ..., vpiNoDelay)把 real 结果写回调用点vpi/va_math.c注册时统一使用type vpiSysFunc、sysfunctype vpiRealFunc并通过vpip_make_systf_system_defined()标记为系统定义函数vpi/va_math.c模块通过cbEndOfSimulation回调在仿真结束时释放所有分配的用户数据vpi/va_math.c与文档的对应关系上需要注意从源码头部注释看大部分数学函数对数、三角、双曲、幂、开方等已迁移到v2005_math模块Most of the math functions have been moved to v2005_math. This allows them to be supported separately from the Verilog-A specific functions.见 vpi/va_math.c当前va_math自身保留实现的是$abs、$max、$min等 Verilog-A 特定函数$max/$min在系统缺少 C99 的fmax/fmin时还会退回到模块内置的va_fmax/va_fmin等价实现vpi/va_math.c。因此实际仿真中加载-m va_math与-m v2005_math常配合使用以获得完整函数集。6.3 标准 Verilog-A 数学常量Verilog-A 数学常量通过包含头文件constants.vams获得该文件位于标准 include 目录当前仓库中即根目录下的 constants.vams。较新版本的 Icarus Verilog0.9.devel 及之后自动把这个目录追加到 include 文件搜索列表的末尾因此无需手动指定-I路径即可\include constants.vams。文档列出的数学常量完整清单如下宏数值含义M_PIπM_TWO_PI2πM_PI_2π/2M_PI_4π/4M_1_PI1/πM_2_PI2/πM_2_SQRTPI2/√πM_E自然常数 eM_LOG2E以 2 为底 e 的对数M_LOG10E以 10 为底 e 的对数M_LN2e 为底 2 的对数ln 2M_LN10e 为底 10 的对数ln 10M_SQRT2√2M_SQRT1_21/√2实际定义可在 constants.vams 中逐条核对例如define M_PI 3.14159265358979323846、define M_TWO_PI 6.28318530717958647693等均以高精度十进制小数给出。头文件还通过ifdef CONSTANTS_VAMS宏做了包含保护避免重复定义。6.4 使用 va_math 库使用方式极其简洁只需两步对应文档原文“Just add-m va_mathto your iverilog command line/command file and\includetheconstants.vams file as needed.”在iverilog命令行或命令文件中加入-m va_math需要用到数学常量时在源码中include constants.vams。例如include constants.vams module math_demo; real r; initial begin r $sqrt(2.0) * M_PI; // 系统函数 数学常量 $display(result %f, r); $finish; end endmodule编译运行时配合-m va_math以及需要时-m v2005_math加载对应模块即可。值得一提的是该库在仓库中还配套了ivtest/下的回归测试体系可作为验证函数行为的参考用例。七、总结Icarus Verilog 的 VPI 体系由“单一共享模块 两个导出符号”构成模块作者把多个 PLI 应用链接成一个.vpi文件导出vlog_startup_routines启动例程表注册系统任务/函数与vpip_set_callback接收运行时的 VPI 例程跳转表运行时vvp通过-m按名加载、按IVERILOG_VPI_MODULE_PATH文档中写作VPI_MODULE_PATH搜索模块并在加载前先执行全部启动例程完成注册。调试时可用VPI_TRACE输出调用追踪注意其格式不稳定、仅供人工阅读。发行版内置的system.vpi、v2005_math.vpi、v2009.vpi、va_math.vpi及 VHDL 辅助模块覆盖了标准系统任务与数学函数其中va_math将 Verilog-A 的 23 个数学函数以$前缀形式引入 Verilog-D并随 constants.vams 提供 14 个数学常量——这使 Verilog-A 风格的模拟算法可以直接在 Icarus Verilog 仿真中落地运行。赞分享编译器硬件仿真EDA【免费下载链接】iverilogIcarus Verilog项目地址https://gitcode.com/gh_mirrors/iv/iverilog点击查看免费下载相关推荐Icarus Verilog 开源 Verilog 编译器使用指南Icarus Verilog 开源 Verilog 编译器使用指南 Icarus Verilog 是一个开源的 Verilog HDL 编译器旨在完全支持 I编译器硬件仿真EDA开源Verilog仿真工具Icarus Verilog完整实战指南开源Verilog仿真工具Icarus Verilog完整实战指南 开源Verilog仿真工具Icarus Verilog为数字电路设计提供了完整的仿真解决方案编译器硬件仿真EDAOMI macOS 桌面应用本地代码签名完全指南run.sh 签名链路、Team ID 权限决策与 errSecInternalComponent 排障OMI macOS 桌面应用本地代码签名完全指南run.sh 签名链路、Team ID 权限决策与 errSecInternalComponent 排障 导读编译器硬件仿真EDA上一篇ITI/ICS-Security-Tools项目工业控制系统(ICS)实验室建设全指南下一篇WebGui入门教程5分钟快速搭建WebAssembly即时模式GUI应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考