当前位置:网站首页>【数字IC验证快速入门】11、Verilog TestBench(VTB)入门
【数字IC验证快速入门】11、Verilog TestBench(VTB)入门
2022-07-07 04:43:00 【luoganttcc】
导读:作者有幸在中国电子信息领域的排头兵院校“电子科技大学”攻读研究生期间,接触到前沿的数字IC验证知识,旁听到诸如华为海思、清华紫光、联发科技等业界顶尖集成电路相关企业面授课程,对数字IC验证有了一些知识积累和学习心得。为帮助想入门前端IC验证的朋友,思忱一二后,特开此专栏,以期花最短的时间,走最少的弯路,学最多的IC验证技术知识。
前言
IC的整个开发中,验证通常包含两个:
- Function(逻辑功能验证)
- ATE(制造测试验证)【DFX团队做一些可测试性电路,进而进行工艺制造缺陷的测试】
本节学习目标
掌握ASIC设计流程
- 设计、验证、中断(BES)、后端主要解决哪些问题
- 主流EDA工具
- 验证工程师的基本技能需求
掌握ASIC验证的基本概念
- Verilog TestBench 和 testcase(测试点)
掌握ASIC验证策略:RCDV(Random Coverage Driven Verification)
- 随机化策略
- 为什么要做随机化?现在集成电路规模越来越大,设计复杂度越来越高,对于TB,通过直接用例构造可能会不充分,有些边界的corner可能会想不到。另外,设计复杂度越来越高,验证的空间越来越大,直接用例构造,跑的时间越来越长,可能跑不完。随机化则是用时间换空间,每个用例用的时间不长,但是可以每天不停的跑。
- 覆盖率驱动
- 功能覆盖【主观】:人为根据应用场景,把功能点分解出来之后,去设定一个目标,哪些功能需要去覆盖,通过语言描述出来。覆盖率可达100%
- 代码覆盖【客观】:代码写出来之后,工具自动去看跑的激励有没经过代码的所有分支。存在冗余代码,覆盖率达不到100%。
- 随机化策略
如何验证一个加法器【在实例中固化之前学习的知识】
- 掌握EDA工具Questasim进行逻辑仿真的步骤:编译、仿真、vsim查看波形
- 掌握Makefile自动化编译的方法
- 理解testbench和testcase的含义
- 掌握code voverage的含义和Questasim自动化统计代码覆盖率的方法
- 掌握verilog实现随机化验证的基本方法:$random,随机中继(seed)的传递机制
一、ASIC/SoC 设计流程
面试上常常会问,注意理解!
理论上设计流程
注:流程很多,掌握其中一种就可以了。
RTL设计 Design
- 首先会去写一些规格书(Specification):Function Spec(FS) -> Architecture Spec(AS) -> Design Spec(DS),由顶向下去做
- 在做AS期间也会去做一些模块划分(Partition),尽量把一些功能比较内聚的东西划分成一个模块
- 在DS器件会去画一些关键的电路原理图,有了电路之后去RTL Coding,由底向上去做,最后进行集成(IP Integration)
功能验证Verification
- 测试计划:1、测试的对象;2、测试的工具; 3、测试的策略:哪些点用直接用例,哪些点用随机用例;4、功能覆盖率多少算成功;5、验证阶段规划及花费时间
- TestBench和Testcase:分解Testpoint(测试点),写Testcase(测试用例),搭建TestBench
- Regression(回归):验证会去一条条跑用例,用例用的是随机的策略,所以我们会每天都去做回归【时间换空间】。覆盖的面会越来越多越来越广,通过回归把验证做的完备!同时在用例前期,如果代码很复杂,可能还会有一个调试过程(调试验证环境)。
- Integration Verification:小模块集成后,集成性验证。UT(Unit Test) -> BT(Block Test) -> IT(Integration Test)
RTL freeze:RTL冻结
- Pre-synthesis sign-off:预综合,看结构、时序等物理实现方面是否有问题。
逻辑综合 logic synthesis
- map RTL to gate-level netlist
Postsynthesis design validation
- FM:Format Verification,形式验证,看网表和RTL代码是否一致,是静态验证,不需要去灌激励,工具把电路结构分解之后,RTL Transfer Level基于每个寄存器的逻辑椎的顶点,组合逻辑输入的作为椎体输入,遍历去验证。
静态时序分析:STA(static timing analysis)
- Post-synthesis timing verification:根据时序路径检查每个D触发器的setup和hold能不能满足,看物理实现能不能满足器件的时序要求,与功能同样没有太大的关系。
- 逻辑综合之后做STA,里面的走线延时、CELL延时是没有的,因为这个时候还可以做PR,都不知道CELL摆哪个位置,走线有多长,此时是一个零负载模型(走线延时等于0)。此时为了模拟一个走线延时,会把时钟进行一个过约,本来时钟是跑100MHz的,现在将其跑到110MHz。综合的时候,进行STA,可以看到路径有没有违例,一方面工具会进行优化,另外还会反馈到设计,有必要的话也会去改设计。
可测试性设计(DFT,Design For Test):Test generation and fault simulation
- 制造性缺陷涉及,会在D触发器中插一些scan链,在mem中插入一些membist的电路,在芯片的回来之后,做功能测试之前会先去做制造性缺陷验证,没有问题后,才会去做功能测试。
物理实现(PD,Phsical Design)【迭代过程】
- Placement(每个CELL放在DIE里的哪个位置),scan chain(这个在逻辑综合就会去做) and CTS(时钟树),cell routing(CELL之间连线方式) verify physical and electrical design rules(物理电气特性的检查,DRC),Extract parasitics(提取寄生参数)
- 物理实现后还回去做STA,这时有了真实的CELL延时和走线延时信息,这个时候做STA,时钟就需要按照100MHz的频率去分析,因为这个时候很多时序信息就是真实的了。只有时序分析真实了之后,才会去进行sign-off,即tape-out,流片。
Production-ready masks
- 制造厂会去制造掩图,给他们的是GDSII文件
二、ASIC/SoC设计技能
UPF: Universal Power Format,描述芯片电源结构的一种语言,主要用来做功耗分析。【倾向于架构级工程师掌握】
UVM:Universal Verification Methodology
BIST:Build In Self Test,内建性测试。membist,内部自己产生激励并对比结果。当然还有LogicBist,逻辑内建性测试。
SCAN:通过芯片外围的IO管脚灌入激励,看scan chain的输出结果是否正确
ATPG:Automatic Test Pattern Generation,从芯片外部的机台产生的激励。
CTS:Clock Tree Synthesis
DRC:Design Rule Check
LVS:Logic Versus Schematic,类比FM
芯片公司,FPGA用来做原型验证,对于数字验证来讲是一个互补的关系,FPGA更多应用在系统级大的模块的数据流验证中,跑的很快;并且SoC软件的调试等工作也会放到FPGA中进行!
EDA更多的是跑一些BT,IT,系统级的更多会放在FPGA上跑!
三、ASIC/SoC 设计流程中使用的主流EDA
四、数字系统设计节点SoC Design Node
五、VTB练习
5.1、Verilog TestBench (VTB)功能复习
- 产生激励 Generate stimulus
- 将激励输入到待测设计(DUT - Design Under Test)
- 产生预期 Generate Expectation
- 获取响应(Capture response)
- 检查响应的正确性(Check the response for correctness)
- 对于复杂的TestBench,如后续用SystemVerilog写的TestBench(即SVTB),大都需要在TestBench中加入Reference Module(RM)或者又叫Golden Module,然后将激励引入到RM模块中,并将RM的输出结果保存起来,进而与响应输出的结果进行比对(check)。如果结果一致,那么用例通过;如果对不上,那么DUT或RM可能有问题,需要重新检查。
- 对于VTB,测试对象比较小,功能比较简单通常不需要加入RM。
- RM的逻辑行为与DUT一样,只不过其中没有了延时信息!
- 根据验证目标评估验证进度(Measure the progress against the overall verification goals)
- 验证的核心思想:验证完备性,不仅仅是找BUG
- 证明DUT的功能是ok的,所以首先要将DUT的功能点(Feature)给分解完全!然后依次验证每个功能点是否ok,如果error,那么就要去找BUG。
- 验证进度需要看覆盖率CDV(Coverage Driven Verification),通常可分为两种:功能覆盖率【主观】(分解功能点,需要验证每个功能点,= 100%)、代码覆盖率【客观】(可能会存在冗余代码,某些代码会验不到,<100%)
注:输入的信号称为激励,输入激励的不同组合我们称之为不同的Pattern,也叫测试点(Test Pattern)。输出的信号称为响应。
5.2、验证一个32位加法器(VTB)(概览)
- 当我们的输入验证空间很大的时候,会采取随机化策略
- 后面system verilog会更加深入做随机化,这里的verilog随机化简单了解即可!
- system verilog的随机会给权重,届时也会更加深入,这里提这个仅仅作为了解!
5.2.1、编写设计源文件(随机化策略)(概览)
- 问:随机仿真中出现错误,如何复现错误?
- 答:种子不变,随机数据不变,所以只要找到对应错误时刻的种子即可!
5.2.2、编写Makefile文件(覆盖率驱动)(概览)
- 最终验证通过覆盖率去检查!
+plusargs_save +seed=$(SEED)
:把SEED
传入到上面的设计源文件中去!-cm line+cond+fsm+tgl+branch
:代码覆盖率统计,包括行、条件、状态机、tgl、分支- 这个脚本后面还会深入去讲,这里仅仅有个“复杂空间,我们会去做随机化”这个概念即可!
5.2.3、覆盖率check(概览)
- 包含覆盖率示意图
5.3、验证一个32位加法器(VTB)(详细)
5.3.1、添加.vimrc
设置选项
首先在.vimrc
中再添加一些设置选项(具体含义,可自行百度搜索),帮助我们更高效地编程,之前的.vimrc
设置参考:【数字IC验证快速入门】5、快速上手Linux下的文本编辑神器gvim。
如果
.vimrc
打开显示只读,尝试加上前缀sudo
set noai
set nosi
set cursorline
set cursorcolumn
iab md module module_name();<cr><cr><cr>endmodule
iab alc always @(*)begin<cr><cr><cr>end
iab als always @(posedge clk or negedge rst_n) begin<cr>if(rst_n == 1'b0) begin<cr><cr>end<cr>else begin<cr><cr>end
iab if0 if( ) begin<cr><cr>end
iab if1 if( ) begin<cr><cr>end<cr>else begin<cr><cr>end
iab if2 if( ) begin<cr><cr>end<cr>else if( ) begin<cr><cr>end<cr>else begin<cr><cr>end
iab if3 if( ) begin<cr><cr>end<cr>else if( ) begin<cr><cr>end<cr>else if( ) begin<cr><cr>end<cr>else begin<cr><cr>end
iab ini initial begin<cr><cr><cr><cr>end
iab dispb $display("@%0t: xxx a=%0b, b=%0b",$time, a, b);
iab dispd $display("@%0t: xxx a=%0d, b=%0d",$time, a, b);
iab disph $display("@%0t: xxx a=%0h, b=%0h",$time, a, b);
- set cursorline:高亮光标当前行
- set cursorcolumn:高亮光标当前列
- set noai:取消自动对齐
- set nosi:取消自动换行
- iab xxx:在输入模式下,写出缩写,按下空格键即可自动补全!
5.3.2、编写源文件
adder32.v
module adder_32(
input wire [31:0] a_in,
input wire [31:0] b_in,
input wire c_in,
output wire [31:0] sum_out,
output wire c_out
);
assign {c_out, sum_out} = a_in + b_in + c_in;
endmodule
- 输入模式下,输入
md
,然后回车会自动补全我们在.vimrc
设置的对应内容 - 命令模式下,输入
:%s/module_name/adder32_tb_rand/g
,替换module的默认名字 - 命令模式下,使用
ws
来分割窗口,使用ctrl+[h/j/k/l]
在各个窗口之间切换;使用vt
来打开左侧导航窗格,使用r
来刷新显示刚刚新建的adder32_tb_rand.v
- 当然也可以用
:sp .
来分割窗口表示在gvim另开一个窗口,并打开上级目录,然后通过方向键选择文件,回车键确定文件,ctrl + w
可以在两个窗口之间进行切换!
- 当然也可以用
- 例化DUT模块:将
adder32.v
中的module头信息复制到adder32_tb_rand.v
中进行例化,在adder32.v
中光标定位到模块开头,然后8yy
即可赋值8行内容!在adder32_tb_rand.v
合适位置按下p
即可粘贴!粘贴完毕后,选中adder32.v
所在窗口,然后输入wc
即可关闭该窗口! - 在
adder32_tb_rand.v
粘贴的内容中,在c_out
后面加上一个,
,便于后面使用正则表达式进行内容的替换! - 将第四行的
module adder32
改成adder32 u_adder32
,使用正则表达式:4,4s/\(\w\+\)\(\s\+\)\(\w\+\)/\3\2u_\3/g
。正则表达式的框架是%s/①/②/g
,首先作用域是第四行,所以%
改成了4,4
;正则表达式的①
-\(\w\+\)\(\s\+\)\(\w\+\)
是将module adder32
分为3组,注意其中括号()
是需要转义的,所以要用\(\)
;\w\+
是匹配任意多个单词字母;\s\+
是匹配任意多个空格;正则表达式的②
-\3\2u_\3
为要替换的内容,\3
表示第三组的内容,其他以此类推即可! - 接着把
adder32.v
中复制的module头信息中的输入输出接口给删除了,删除方法使用visual模式:先按ctrl+v
进入visual block
模式,然后鼠标或者h/j/k/l
来 - 接着还是改module头信息的输入输出,比如更改
a_in,
为.ain (ain),
。显然可以使用正则将其分为两组,一组是word,一组是逗号。使用的正则表达式::5,10s/\(\w\+\)\(,\)/.\1 (\1)\2/g
,框架还是%s/①/②/g
,首先是5-10行,所以%
改成了5,10
;正则表达式的①
-\(\w\+\)\(,\)
是将a_in,
这一类的代码分为2组,第一组是a_in
之类的字符串,第二组是逗号;正则表达式的②
-\3\2u_\3
为要替换的内容,替换内容是在第一组前面加点,然后第一组括号,最后是第二组。 - 最后再将
c_out
最后的,
进行去除。
同上操作,我们再复制adder32.v
中的信号名到adder32_tb_rand.v
中并用正则表达式进行一些替换操作!至此便把DUT进行了例化并把所有的信号进行了连接,此时代码内容如下:
module adder32_tb_rand();
reg [31:0] a_in;
reg [31:0] b_in;
reg c_in;
wire [31:0] sum_out;
wire c_out;
adder_32 u_adder_32(
.a_in (a_in),
.b_in (b_in),
.c_in (c_in),
.sum_out (sum_out),
.c_out (c_out)
);
endmodule
接下来产生激励,采用的是随机化的方式。
定义一个
reg
型的数组data_in :reg [32:0] data_in = {32'h0, 32'h0, 32'h0};
,还有一个需要注意的是:这里定义的是33bit,因为我们后面要使用系统函数sum
来对data_in的三个元素进行求和!(单比特数组的求和返回单比特的数值)- 这里有必要再解释以下data_in,它是个数组。扩充以下:如果data_in是简单数据,定义
reg [7:0] data_in
,那么data_in[1]
代表数据第1bit;如果data_in是数组,定义reg [7:0] data_in[20]
,那么data_in[1]
代表数据第1元素,元素起始位置也是0,data_in[0]. - 但是需要注意,后面我们要将
data_in
的值赋给a_in
、b_in
,但是a_in
、b_in
是32bit的。一种解决方法是,在产生data_in
的数据的时候,我们只要32bit,如:data_in[0][31:0] = $random(seed);
- 这里有必要再解释以下data_in,它是个数组。扩充以下:如果data_in是简单数据,定义
定义随机种子
seed
和激励数目stimulus_num
,这两个都是外面的脚本(通常是Makefile)传递进来的接下来再initial块中读取
seed
和stimulus_num
,输入ini
即可自动填充完整initial框架!再initial块中输入if1
即可自动填充完整if语句块!- if语句块中使用
$value$plusargs("seed=%d", seed)
来获取seed,如果没有获取成功将seed赋值为100
,获取成功使用系统函数display
将其打印出来!注意我们是十进制打印,直接在输入模式下dispd
,然后按空格即可自动补全! - 同理可以获取
stimulus_num
,直接使用6yy + p
的方式快速复制粘贴!然后使用:32,37s/seed/stimulus_num/g
进行快速替换
- if语句块中使用
接下来使用随机种子来产生激励,在initial块中来赋值,输入
ini
然后按空格即可自动补全!然后使用repeat
来产生stimulus_num
个激励(给data_in
赋值),注意变量名字很长时,可以使用tab
键来快速补全!(Tab键自动补全还有个好处是可以避免拼写错误,这是个不错的好习惯!)- 写完
data_in[0] = $random(seed);
可以yy + p + p
来快速赋值两行,然后在命令模式下使用r + 1
和r + 2
来快速替换data_in
的索引。 - 32位加法器通常没有
c_in
,所以我们将data_in[2]
设置为1'b0
。快速操作的方法:光标定位到$random(seed);
开头,然后在命令模式下按下D
,即可删除光标到行尾的所有内容!
- 写完
为了和其他模块通信,获取激励是否成功产生的标志,我们这里再定义一个信号量
sti_gen
(标志信号),在每次激励产生前sti_gen
等于0,产生后等于1,这样其他模块捕获一个上沿即可获取是否成功产生激励。- 需要注意的是,激励产生完毕,不要立即赋值
sti_gen = 1
,这样可能会造成dut_sum
和gld_sum
错位的情况发生,应该等一会,这里设置为#10;
- 需要注意的是,激励产生完毕,不要立即赋值
产生激励后,将激励值赋给DUT,这里直接使用always的组合逻辑即可,输入模式下输入
alc
,即可自动补全。除了产生激励,还要给出Golden模型(Reference Module),Golden结果通常会放到一个队列中!队列语法后面会详细介绍!
给了Golden model还需要将激励发送到Golden model,使用
initial
块来完成,输入ini
即可自动补全!注意,gld_sum.push_back(data_in.sum);
操作是队列的一些操作,后面会再详细介绍,这里知道作用即可。其中.push_back
和.sum
均是系统函数!golden model
中的.sum
是一个行为级描述,而DUT中的是一个RTL描述,通过比对两者结果即可验证!结果收集好了,接下来就是要做对比了。这里定义两个临时变量
gld_sum_rslt
和dut_sum_rslt
。在比较前,需要等到stimulus产生完之后,所以这里需要定义一个事件event sti_end;
,关于事件的详细介绍,后面也会详细介绍,这里仅仅知道作用。在stimulus发送完毕之后,把这个事件触发,然后才进行结果的比对!如何把这个事件触发,在Step 2
末尾加上-> sti_end
即可。然后在Step5
中加入@sti_end
等待触发即可!然后获取gld_sum和dut_sum进行比对!
在testbench中check最终结果,我们可以增加一个错误标志信号!
err_cnt
来记录错误个数,如果err_cnt
为0那么就可以进行pass!
adder32_tb_rand.v
module adder32_tb_rand();
reg [31:0] a_in;
reg [31:0] b_in;
reg c_in;
wire [31:0] sum_out;
wire c_out;
int seed;
int stimulus_num;
reg sti_gen;
reg [32:0] data_in[3] = {33'h0, 33'h0, 33'h0};
reg [32:0] gld_sum [$];
reg [32:0] dut_sum [$];
reg [32:0] gld_sum_rslt;
reg [32:0] dut_sum_rslt;
event sti_end;
int err_cnt;
adder_32 u_adder_32(
.a_in (a_in),
.b_in (b_in),
.c_in (c_in),
.sum_out (sum_out),
.c_out (c_out)
);
// Step1, Get random seed and stimulus number arguments from external scripts
initial begin
if( ! $value$plusargs("seed=%d", seed) ) begin
seed = 100;
end
else begin
$display("@%0t: seed a=%0d",$time, seed);
end
if( ! $value$plusargs("stimulus_num=%d", stimulus_num) ) begin
stimulus_num = 50;
end
else begin
$display("@%0t: stimulus_num a=%0d",$time, stimulus_num);
end
end
// Step2, Generate stimulus with random seed
initial begin
sti_gen = 1'b0;
repeat(stimulus_num) begin
sti_gen = 1'b0;
#10;
data_in[0][31:0] = $random(seed);
data_in[1][31:0] = $random(seed);
data_in[2] = 1'b0;
#10;
sti_gen = 1'b1;
#10;
end
-> sti_end;
end
// Step2.1, Send stimulus to DUT
always @(*)begin
a_in = data_in[0];
b_in = data_in[1];
c_in = data_in[2];
end
// Step3, Send stimulus to Golden model
initial begin
repeat(stimulus_num) begin
@(posedge sti_gen)
gld_sum.push_back(data_in.sum);
end
end
// Step4, Capture DUT output
initial begin
repeat(stimulus_num) begin
@(posedge sti_gen)
dut_sum.push_back({c_out, sum_out});
end
end
// Step5, Check result
initial begin
gld_sum_rslt = 'h0;
dut_sum_rslt = 'h0;
err_cnt = 'h0;
@sti_end;
repeat(stimulus_num) begin
gld_sum_rslt = gld_sum.pop_front();
dut_sum_rslt = dut_sum.pop_front();
if(gld_sum_rslt != dut_sum_rslt) begin
$display("@%0t: Error: gld_sum != dut_sum; gld_sum=%0h, dut_sum=%0h",$time, gld_sum_rslt, dut_sum_rslt);
err_cnt ++;
end
end
if( err_cnt == 'h0 ) begin
$display("***********************************");
$display("***********************************");
$display("***********************************");
$display("*************TEST PASS*************");
$display("***********************************");
$display("***********************************");
$display("***********************************");
end
$finish();
end
endmodule
至此,TestBench编写完毕,接下来我们来编写Makefile。
Makefile
all: compilation simulation
seed = $(shell date +%s)
stimulus_num = 100
compilation:
vcs -full64 -sverilog adder32.v adder32_tb_rand.v -debug_all -l comp.log
simulation:
./simv -l sim_$(seed).log +plusargs_save +seed=$(seed) +stimulus_num=$(stimulus_num)
seed = $(shell date +%s);
:执行一个shell命令,shell命令叫date
,%s
以serial的形式打印,打印出来是一串数字,固定格式!stimulus_num = 100;
:定义激励个数为100- VCS仿真分为两个部分,其中一个部分是
compilation
-sverilog
:有用到system verilog的语法,所以这里需要加上这个选项!-debug_all
:习惯-l comp.log
:打印记录放里面
- VCS仿真另外一个部分是
simulation
./simv
:仿真命令-l sim_$(seed).log
:记录仿真结果,通常与种子联系起来!+plusargs_save +seed = $(seed) +stimulus_num = $(stimulus_num)
:将外部变量读取到TB中!这里就是读取seed
和stimulus_num
了。要特别注意:seed = $(shell date +%s)
和stimulus_num = 100
这两句后面不能加标点,不然会出现传递不进去参数的情况,如果出现传递参数错误,通常会出现如下提示信息:- 另外一个判断参数传递是否成功的方法,可以通过在程序中加入打印信息。比如本程序如果不能打印
@0: seed a=1630487312
和@0: stimulus_num a=100
则说明参数传递错误,需要及时debug!
...
/bin/sh: .log: command not found
/bin/sh: +stimulus_num: command not found
make: *** [simulation] Error 127
[[email protected] adder32]$
写完之后便可以进行初步的仿真了。
5.3.3、运行仿真
在命令行直接输入make
即可运行仿真!
成功输出后的打印日志如下:
[[email protected] adder32]$ make
vcs -full64 -sverilog adder32.v adder32_tb_rand.v -debug_all -l comp.log
Chronologic VCS (TM)
Version O-2018.09-SP2_Full64 -- Wed Sep 1 17:08:31 2021
Copyright (c) 1991-2018 by Synopsys Inc.
ALL RIGHTS RESERVED
This program is proprietary and confidential information of Synopsys Inc.
and may be used and disclosed only as authorized in a license agreement
controlling such use and disclosure.
Warning-[DEBUG_DEP] Option will be deprecated
The option '-debug_all' will be deprecated in a future release. Please use
'-debug_acc+all -debug_region+cell+encrypt' instead.
Parsing design file 'adder32.v'
Parsing design file 'adder32_tb_rand.v'
Top Level Modules:
adder32_tb_rand
No TimeScale specified
Starting vcs inline pass...
1 module and 0 UDP read.
recompiling module adder32_tb_rand
make[1]: Entering directory `/home/verifier/workspace/adder32/csrc' rm -f _csrc*.so pre_vcsobj_*.so share_vcsobj_*.so if [ -x ../simv ]; then chmod -x ../simv; fi g++ -o ../simv -Wl,-rpath-link=./ -Wl,-rpath='$ORIGIN'/simv.daidir/ -Wl,-rpath=./simv.daidir/ -Wl,-rpath='$ORIGIN'/simv.daidir//scsim.db.dir -rdynamic -Wl,-rpath=/opt/synopsys/vcs/vcs-mx/O-2018.09-SP2/linux64/lib -L/opt/synopsys/vcs/vcs-mx/O-2018.09-SP2/linux64/lib objs/amcQw_d.o _46704_archive_1.so SIM_l.o rmapats_mop.o rmapats.o rmar.o rmar_nd.o rmar_llvm_0_1.o rmar_llvm_0_0.o -lzerosoft_rt_stubs -lvirsim -lerrorinf -lsnpsmalloc -lvfs -lvcsnew -lsimprofile -luclinative /opt/synopsys/vcs/vcs-mx/O-2018.09-SP2/linux64/lib/vcs_tls.o -Wl,-whole-archive -lvcsucli -Wl,-no-whole-archive /opt/synopsys/vcs/vcs-mx/O-2018.09-SP2/linux64/lib/vcs_save_restore_new.o -ldl -lc -lm -lpthread -ldl ../simv up to date make[1]: Leaving directory `/home/verifier/workspace/adder32/csrc'
CPU time: .148 seconds to compile + .118 seconds to elab + .142 seconds to link
./simv -l sim_1630487312.log +plusargs_save +seed=1630487312 +stimulus_num=100
Chronologic VCS simulator copyright 1991-2018
Contains Synopsys proprietary information.
Compiler version O-2018.09-SP2_Full64; Runtime version O-2018.09-SP2_Full64; Sep 1 17:08 2021
@0: seed a=1630487312
@0: stimulus_num a=100
***********************************
***********************************
***********************************
*************TEST PASS*************
***********************************
***********************************
***********************************
$finish called from file "adder32_tb_rand.v", line 116.
$finish at simulation time 3000
V C S S i m u l a t i o n R e p o r t
Time: 3000
CPU Time: 0.150 seconds; Data structure size: 0.0Mb
Wed Sep 1 17:08:32 2021
[[email protected] adder32]$
附录
附录1、VCS 常用编译选项
- 在学习VCS(Verilog Compile Simulator)过程中遇到不知道的编译命令可以使用 vcs -full64 -help 来查看帮助!
- VCS学习过程中可能需要查看对应的 User Guide,一般情况下在vcs的安装目录下的doc文件夹里面会有PDF文件,或者查看这里。
- VCS就是编译用户输入的源文件生成对应的可执行文件(默认是二进制的simv文件),在之后的仿真中运行这个可执行文件。
附录2、常用编译选项及其含义
VCS语法如下:
$ vcs [options] source_files
- 1
常用编译选项及其含义
-help:vcs帮助,有各编译选项意义;
-full64:以64位模式编译设计并创建64位可执行文件用于64位模式下的模拟;
-vpi:允许使用vpi PLI访问例程;
-sverilog:允许在Accellera systemVerilog规范中使用Verilog语言扩展;
-v2k:使用Verilog 1364-2001标准;
-cpp:使用c++编译器;
-debug_pp:允许转储到VPD并使用UCLI命令和DVE;
-debug:启用UCLI命令和DVE;
-debug_all:启用UCLI命令和DVE,也使线路步进;
-notice:启用详细的诊断消息;
+lint=[no]ID|none|all,... 使能或者禁用verilog的lint消息;
+rad:对设计进行辐射技术优化;
+vcs+lic+wait:如果没有可用的通知,则告诉VCS等待网络许可证;
-f <filename>: 指定一个文件,其中包含源文件和编译时选项的路径名列表;
-o <name>:指定输出可执行文件的文件名,默认为 simv;
-R:该选项告诉VCS在编译完后直接运行可执行程序,若没有该选项,那么vcs在编译后直接退出;
-l <filename>:(小写字母L)如果包含-R,-RI或-RIG选项,则指定VCS记录编译消息和运行时消息的日志文件;
-Mupdate[=0]:默认情况下,VCS会在编译之间覆盖Makefile。 如果希望在编译之间保存Makefile,请输入此内容选项与0参数。输入不带0参数的参数,指定默认情况下,增量编译和更新Makefile文件;
-CFLAGS <options>:将选项传递给C编译器,允许多个-CFLAGS,允许传递C编译器优化级别。
-timescale=<time_unit>/<time_precision>:指明时间精度;
-ucli:在运行时指定UCLI模式;
+incdir+<directory>:指定包含使用`include 编译器指令指定的文件的目录,可以指定多个目录,用+字符分隔每个路径名称; +libext+<extension>:指定VCS仅在具有指定扩展名的Verilog库目录中搜索源文件,可以指定多个扩展名,用+字符分隔每个扩展名。例如+libext++.v指定搜索没有扩展名和库扩展名为.v的库文件。 输入-y选项时输入此选项。 +systemverilogext+<ext>:指定包含SystemVerilog源代码的源文件的文件扩展名; -gui[=<dve|verdi>]:启动用户指定的图形用户界面,如果未提供参数,则在检测到有效的VCS_HOME环境变量时,VCS将启动Verdi。 否则DVE将默认启动; -vcd <filename>:将输出VCD文件名设置为指定文件。默认文件名为verilog.dump。Verilog源代码中的$dumpfile系统任务将覆盖此选项; -verdi:使用verdi图形界面; +vcdfile+<filename>:指定想要用于后期处理的VCD文件; -vpd_file <filename>:在运行时,定义VCS写入的VPD文件的替代名称,而不是缺省名称vcdplus.vpd; +define+VCS:定义全局的VCS,编译器在编译时如果源文件有类似`ifdef VCS等字样,那么会执行定义之后的代码。
+vcs+vcdpluson:编译选项,加入后会使能产生vpd文件,默认文件名vcdplus.vpd
常见问题解决办法
问题:'/opt/synopsys/vcs/vcs-mx/O-2018.09-SP2/linux/bin/vcs1' for a machine of this type 'linux'. Please check whether 'VCS_HOME' is incorrect
[[email protected] adder32]$ make compilation
vcs -sverilog adder32.v adder32_tb_rand.v -debug_all -l comp.log
Error-[VCS_COM_UNE] Cannot find VCS compiler
VCS compiler not found. Environment variable VCS_HOME
(/opt/synopsys/vcs/vcs-mx/O-2018.09-SP2/linux) is selecting a directory in
which there isn't a compiler
‘/opt/synopsys/vcs/vcs-mx/O-2018.09-SP2/linux/bin/vcs1’ for a machine of
this type ‘linux’.
Please check whether ‘VCS_HOME’ is incorrect; if not, see below.
Perhaps vcs hasn’t been installed for machine of type“linux”.
Or the installation has been damaged.
To verify whether vcsO-2018.09 supports machine of type“Linux 3.10.0-1160.el7.x86_64”,
please look at ReleaseNotes formore details .
We determine the machine type from uname; maybe uname is incorrect.
You can fix installation problems by reinstalling from CDROM
or downloading it from the Synopsys ftp server.
For assistance, please contact vcs technical support
at [email protected] or call 1-800-VERILOG
make: *** [compilation] Error 1
解决方法:出现这样的问题是因为装的VCS版本是64 bit的,所以要加个-full64
。
参考
边栏推荐
- [UVM foundation] what is transaction
- Numbers that appear only once
- Ansible
- Jenkins remote build project timeout problem
- Zhilian + AV, AITO asked M7 to do more than ideal one
- 大视频文件的缓冲播放原理以及实现
- Pytest+allure+jenkins installation problem: pytest: error: unrecognized arguments: --alluredir
- Leetcode 40: combined sum II
- 自定义类加载器加载网络Class
- [Stanford Jiwang cs144 project] lab3: tcpsender
猜你喜欢
Use and analysis of dot function in numpy
Linux server development, redis source code storage principle and data model
[SUCTF 2019]Game
2022 National latest fire-fighting facility operator (primary fire-fighting facility operator) simulation questions and answers
2022年茶艺师(中级)考试试题及模拟考试
Numbers that appear only once
buuctf misc USB
Main window in QT learning 27 application
misc ez_ usb
Padavan manually installs PHP
随机推荐
pytest+allure+jenkins环境--填坑完毕
2022年全国最新消防设施操作员(初级消防设施操作员)模拟题及答案
Yugu p1020 missile interception (binary search)
[matlab] when matrix multiplication in Simulink user-defined function does not work properly, matrix multiplication module in module library can be used instead
@component(““)
dash plotly
QT learning 26 integrated example of layout management
C语言二叉树与建堆
芯片 设计资料下载
Binary tree and heap building in C language
Wechat applet data binding multiple data
Ansible
Linux server development, MySQL transaction principle analysis
Most elements
微信小程序基本组件使用介绍
大视频文件的缓冲播放原理以及实现
[UTCTF2020]file header
CentOS7下安装PostgreSQL11数据库
这5个摸鱼神器太火了!程序员:知道了快删!
C language flight booking system