PLI 基础
Verilog 提供了PLI(Programming Language Interface)机制, 用来进行硬件设计和软件设计者进行交互。 它可以在Verilog的设计之中加入用户自定义的系统函数,这些系统函数是通过C语言软件的方式实现, 这可以理解为, 通过插件的方式, 来扩充硬件设计语言的功能。
PLI常见的功能如下:
- C语言bus函数建模;
- 访问C语言代码库函数;
- 延时计算功能;
- 自定义输出显示;
- 联合仿真;
- 设计的debug功能;
- 仿真结果分析;
我们比较感兴趣的是访问C语言代码库函数以及design debug功能, 这也是我们后面扩展和使用PLI的功能。 目前的PLI用的比较新的功能是基于VPI的, 我们就忽略ACC/TF部分。
(System)Verilog LRM提供了如下的VPI头文件:
vpi_user.h
sv_vpi_user.h (SystemVerlog部分)
添加系统函数的步骤
The general steps to create a PLI application are:
- Define a system task or system function name for the application.
- Write a C language calltf routine which will be executed by the simulator whenever
simulation encounters the system task name or the system function name.
Optionally, additional C language routines can be written which will be executed
by the simulator for special conditions, such as when the simulator compiler or
elaborator encounters the system task/function name. - Register the system task or system function name and the associated C language
routines with the Verilog simulator.
This registration tells the simulator about the new system task or system function name,
and the name of the calltf routine associated with that task or system function (along with any other routines). - Compile the C source files which contain the PLI application routines, and link the object files into the Verilog simulator.
VPI的常用函数
获取实例, 并且遍历所有的子对象
/* OBJECT CODES */
#define vpiConstant 7
#define vpiFunction 20
#define vpiIntegerVar 25
#define vpiIterator 27
#define vpiMemory 29
#define vpiMemoryWord 30
#define vpiModPath 31
#define vpiModule 32
#define vpiNamedBegin 33
#define vpiNamedEvent 34
#define vpiNamedFork 35
#define vpiNet 36
#define vpiNetBit 37
#define vpiParameter 41
#define vpiPartSelect 42
#define vpiPathTerm 43
#define vpiPort 44
#define vpiRealVar 47
#define vpiReg 48
#define vpiRegBit 49
#define vpiSysFuncCall 56
#define vpiSysTaskCall 57
#define vpiTask 59
#define vpiTimeVar 63
#define vpiUdpDefn 66
#define vpiUserSystf 67
#define vpiNetArray 114
#define vpiIndex 78
#define vpiLeftRange 79
#define vpiParent 81
#define vpiRightRange 83
#define vpiScope 84
#define vpiSysTfCall 85
#define vpiArgument 89
#define vpiInternalScope 92
#define vpiModPathIn 95
#define vpiModPathOut 96
#define vpiVariables 100
#define vpiExpr 102
extern vpiHandle vpi_handle(PLI_INT32 type, vpiHandle ref);
extern vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle ref);
extern vpiHandle vpi_scan(vpiHandle iter);
获取仿真的时间
typedef struct t_vpi_time {
PLI_INT32 type;
PLI_UINT32 high;
PLI_UINT32 low;
double real;
} s_vpi_time, *p_vpi_time;
void vpi_get_time (
vpiHandle object, /* handle for an object, or NULL */
p_vpi_time time ) /* pointer to application-allocated s_vpi_time structure */
获取value change:
typedef struct t_vpi_value {
PLI_INT32 format; /* vpiBinStrVal, vpiDecStrVal,
vpiScalarVal, piRealVal,
vpiOctStrVal, vpiHexStrVal,
vpiIntVal, vpiStringVal,
vpiTimeVal, vpiSuppressVal,
vpiVectorVal, vpiStrengthVal,
vpiObjTypeVal */
union {
char *str;
PLI_INT32 scalar;
PLI_INT32 integer;
double real;
struct t_vpi_time *time;
struct t_vpi_vecval *vector;
struct t_vpi_strengthval *strength;
char *misc;
} value;
} s_vpi_value, *p_vpi_value;
void vpi_get_value(
vpiHandle object, /* handle for an object */
p_vpi_value value) /* pointer to application-allocated s_vpi_value structure */
注册callback 函数:
#define cbValueChange 1
#define cbStmt 2
#define cbForce 3
#define cbRelease 4
#define cbAtStartOfSimTime 5
#define cbReadWriteSynch 6
#define cbReadOnlySynch 7
#define cbNextSimTime 8
#define cbAfterDelay 9
#define cbEndOfCompile 10
#define cbStartOfSimulation 11
#define cbEndOfSimulation 12
#define cbError 13
#define cbTchkViolation 14
#define cbStartOfSave 15
#define cbEndOfSave 16
#define cbStartOfRestart 17
#define cbEndOfRestart 18
#define cbStartOfReset 19
#define cbEndOfReset 20
#define cbEnterInteractive 21
#define cbExitInteractive 22
#define cbInteractiveScopeChange 23
#define cbUnresolvedSystf 24
#define cbAtEndOfSimTime 31
typedef struct t_cb_data {
PLI_INT32 reason;
PLI_INT32 (*cb_rtn)(struct t_cb_data*cb);
vpiHandle obj;
p_vpi_time time;
p_vpi_value value;
PLI_INT32 index;
ICARUS_VPI_CONST PLI_BYTE8 *user_data;
} s_cb_data, *p_cb_data;
extern vpiHandle vpi_register_cb(p_cb_data data);
extern PLI_INT32 vpi_remove_cb(vpiHandle ref);