1.总体思路
通过正态分布generator产生数据传递item,最终通过driver将数据打印至日志文件,利用python脚本绘制分布图,检验产生数据是否正确
产生正态分布数据有两种方法,第一种是在利用SV中的权重分布模拟正态函数分布,第二种是利用DPI接口实现正态函数。考虑到实现难易程度,选择后者。总体框架如下图所示。
2.在C中实现正态分布函数
实现正态分布函数有两种方法,一种是采用泰勒展开式,计算出最终值,一种是通过中心-极限定理得出正态分布。正态函数的泰勒展开式 -_-|| … 一般采用中心-极限定理比较方便。
中心-极限定理的大致解释,每次从这些总体中随机抽取 n 个抽样,一共抽 m 次。 然后把这 m 组抽样分别求出平均值。 这些平均值的分布接近正态分布。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include<svdpi.h> //dpi头文件,仿真器自带
#include<stdlib.h>
unsigned int get_normal()
{
unsigned int dat=0; //产生数据
unsigned char i;
unsigned int seed; //随机种子
seed = rand();
srand(seed);
for (i=0;i<10;i++)
{
dat += rand()%99; //0~99随机数求和
}
return dat/i; //返回平均值
}
|
3.UVM搭建
测试平台由代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
`include "uvm_macros.svh"
import "DPI-C" function bit [31:0] get_normal(); //导入C函数
import uvm_pkg::*;
class my_trans extends uvm_sequence_item; //定义my_trans
bit [31:0] dat;
`uvm_object_utils_begin(my_trans)
`uvm_field_int(dat,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name =" ");
super.new(name);
dat = get_normal();
endfunction
virtual function void do_print(uvm_printer printer);
// TODO Auto-generated function stub
//super.do_print(printer);
//printer.print_field("dat", dat, $bits(dat), UVM_DEC);
endfunction : do_print
endclass
class my_sequence extends uvm_sequence; //定义my_sequence
`uvm_object_utils(my_sequence)
function new(string name = "my_sequence");
super.new(name);
endfunction
task body();
my_trans dat_trans;
repeat(100000) begin
#1
`uvm_do(dat_trans)
end
endtask
endclass
class my_sequencer extends uvm_sequencer#(.REQ(my_trans),.RSP(my_trans)); //定义my_sequencer
`uvm_component_utils(my_sequencer)
function new(string name = "my_sequencer", uvm_component parent);
super.new(name,parent);
endfunction
endclass
class my_driver extends uvm_driver#(.REQ(my_trans),.RSP(my_trans)); //定义my_driver
`uvm_component_utils(my_driver)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
virtual task main_phase(uvm_phase phase);
REQ req;
uvm_default_printer.knobs.default_radix=UVM_DEC;
forever begin
seq_item_port.get_next_item(req);
req.print();
seq_item_port.item_done();
end
endtask
endclass
class my_env extends uvm_env; //定义my_env
`uvm_component_utils(my_env)
my_sequencer sqr;
my_driver drv;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
drv = my_driver::type_id::create("drv", this);
sqr = my_sequencer::type_id::create("sqr", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction
endclass
class test0 extends uvm_test;
my_env env;
`uvm_component_utils(test0)
function new(string name, uvm_component parent = null);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = my_env::type_id::create("env", this);
endfunction : build_phase
virtual task main_phase(uvm_phase phase);
my_sequence dat_seq;
super.main_phase(phase);
phase.raise_objection(this);
dat_seq = my_sequence::type_id::create("dat_seq");
dat_seq.start(env.sqr);
phase.drop_objection(this);
endtask : main_phase
endclass
|
testbench:
1
2
3
4
5
|
module tb;
initial begin
run_test("test0");
end
endmodule
|
4. 利用python脚本提取数据,查看结果
VCS最终打印数据:
1
2
3
4
5
6
|
--------------------------------
Name Type Size Value
--------------------------------
dat_trans my_trans - @572
dat integral 32 'd43
--------------------------------
|
利用python脚本提取dat的数值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import matplotlib
import matplotlib.pyplot as plt
f = open("sim.log")
line = f.readlines()
dat=[]
for tmp in line:
s = tmp.split()
for i in range(0,len(s)-1):
if s[i] == " ":
s.pop(i)
if len(s) > 3:
if s[0]=="dat":
if s[1] == "integral":
dat.append(int(s[3][2:])) # 提取数据
plt.hist(dat,100,(0,99))
plt.show()
|
5. makefile文件编写
vcs仿真器makefile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
VCS = vcs -f tb.list +vc ../tb/gen.c\
-full64 -debug_all -sverilog -timescale="1ns/1ps" -l log.txt \
+vpi \
+define+UVM_OBJECT_MUST_HAVE_CONSTRUCTOR \
$(UVM_HOME)/src/dpi/uvm_dpi.cc -CFLAGS -DVCS
SIM = ./simv -l sim.log +UVM_TIMEOUT=100000000
DISP = python3 analyze_dat.py
gui:
$(SIM) -gui
comp:
$(VCS)
sim:
$(SIM)
disp:
$(DISP)
run:
$(VCS)
$(SIM)
$(DISP)
clean:
cp makefile ../makefile
cp tb.list ../tb.list
cp analyze_dat.py ../analyze_dat.py
rm -rf *
mv ../makefile makefile
mv ../tb.list tb.list
mv ../analyze_dat.py analyze_dat.py
|
6. 运行结果
make运行
最终结果:
