下面是System Verilog 内存模型的代码:
一个真实的内存模型会含有诸如读写之类消耗时间的操作,所以使用任务来建模。
//readFile.c
#include <stdio.h>
//调用system verilog 任务
extern void memBuild(int);
extern void memRead(int addr, int *data);
extern void memWrite(int addr, int data);
int readFile(char *fname){
int cmd;
FILE *file;
int addr, data, exp;
file = fopen(fname, "r");
while(!feof(file)){
cmd = fgetc(file);
switch(cmd){
case 'M':{
//分配内存
int hi;
fscanf(file, "%d", &hi);
memBuild(hi);
break;
}
case 'R':{
//读操作
fscanf(file, "%c %d %d",&cmd, &addr, &data);
memRead(addr, &exp);
if(exp == data){
io_printf("read successfully!----addr = %d data = %d\n", addr, data);
}
else{
io_printf("read error!---- addr = %d data should be %d, but it is %d now.\n", addr, exp, data);
}
break;
}
case 'W':{
//写操作
fscanf(file, "%c %d %d",&cmd, &addr, &data);
memWrite(addr, data);
break;
}
}
}
fclose(file);
}
由于导入readFile函数需要调用C任务,所以readFile函数成了一个任务。并且import语句指定它为一个关联函数,原因是仿真器需要在该函数每次被调用的时候创建一个单独的栈
//tb_top.sv
`timescale 1ns/1ns
module tb_top;
//=====================================================================\
// ********** Define Parameter and Internal Signals *************
//=====================================================================/
//======================================================================
// *************** Main Code ****************
//======================================================================
import "DPI-C" context task readFile(string fname);
//导出SV任务
export "DPI-C" task memRead;
export "DPI-C" task memWrite;
export "DPI-C" function memBuild;
initial begin
readFile("mem.dat");
end
int mem[];
//分配内存
function void memBuild(input int mSize);
mem = new[mSize];
//打印提示和时间信息
$display("SV:Allocated memory!----size = %0d----time:%0t", mSize, $time);
endfunction
//内存读取
task memRead(input int addr, output int data);
#20
data = mem[addr];
//打印时间信息
$display("read data.----time:%0t", $time);
endtask:memRead
//内存写入
task memWrite(input int addr, input int data);
#10
mem[addr] = data;
//打印提示和时间信息
$display("write successfully!----addr = %0d, data = %0dd----time:%0t", addr, data, $time);
endtask:memWrite
endmodule
然后创建一个.dat文件,里面写入以下命令:
M 100
W 1 1
W 2 2
W 3 3
R 1 1
R 1 2
第一条命令是创建含有100个元素的内存
第二条命令是在地址1写入数据1
第三条命令是在地址2写入数据2
第四条命令是在地址3写入数据3
第五条命令是读取地址1的数据并和数据1比较
第六条命令是读取地址1的数据并和数据2比较
下面是程序运行的结果
# SV:Allocated memory!----size = 100----time:0
# write successfully!----addr = 1, data = 1d----time:10
# write successfully!----addr = 2, data = 2d----time:20
# write successfully!----addr = 3, data = 3d----time:30
# read data.----time:50
# read successfully!----addr = 1 data = 1
# read data.----time:70
# read error!---- addr = 1 data should be 1, but it is 2 now.