新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 基于VMM验证方法学的MCU验证环境

基于VMM验证方法学的MCU验证环境

作者:时间:2016-09-12来源:网络收藏

4.2 指令数据包以及Scenario Generator

环境中,所有的数据都是扩展vmm_data得到,在这里首先对指令分类,相同格式的指令皆为同一类型,具体部分分类表格如表1中所示。

MCU指令分类

分类的依据在于指令格式,例如对从工作寄存器Rn到A的操作,或是从直接地址Rx到A的操作,这样可以通过约束一个种类来随机化指令格式,生成指令格式以后可以根据指令格式来填入相应的随机值。首先就是约束指令格式对应的指令,代码如:

constraint add_mode_decide_kind{

(addr_mode==RN_A) -> kind inside {MOV, ADD, ADDC, SUBB, XCH, ANL, ORL, XRL};

(addr_mode==RX_A) -> kind inside {MOV, ADD, ADDC, SUBB, XCH, ANL, ORL, XRL};

…………}

然后约束对应的寄存器地址,立即数,相对地址等,代码如:

constraint inst_valid{

di_x inside {[0:255]};

reg_y inside {[0:255]};

reg_i inside {0, 1};

reg_n inside {[0: 7]};

…。}

得到了指令的格式,随机得到指令,指令参数,在以上约束下就可以生成一条符合语法的指令。通过在TestCase中约束指令格式,或是地址数据就可以在TestCase中控制Generator生成的指令,通过变换随机种子就可以生成不同类型的指令集合。

使用宏定义对数据类扩展就可以得到数据类的Generator和Channel:

`vmm_channel(inst)

`vmm_scenario_gen(inst, “inst”)

每次scenario Generator生成一条指令,并且通过channel传递给Driver。可以将一系列约束做为一个scenario,这样可以控制指令与指令之间的关系,将一系列scenario合并可以生成更多的随机组合,例如:

$void(scenario_kind) == R0_OP -> {

foreach(items[i]){

items[i].addr_mode inside {0,1,2,4,5,6,7,8,10,11,12,13,14,21,22,23,24,26,27,28=};

items[i].reg_x inside {0};

items[i].reg_n inside {0};

items[i].reg_i inside {0};

}

}

验证这里能够做到尽可能大量重复地测试某些指令的集合,以便将一些边缘情况测到,例如实际应用上会反复使用累加器或是反复调用R0-R7,都可以通过约束来实现。大量随机的代码测试下,可以给出更边缘的TestCase,尽可能地测试到一些边缘情况。

4.3 Driver

这里Driver实现了Transactor的功能,除了实现将asm代码汇编,将16进制代码读入ROM模型中,还要调用MCU的C模型并产生结果,供后续ScoreBoard对比。

由于汇编器需要将所有指令代码读入进行统一汇编,由Generator生成的所有指令代码在Driver中会被写入asm文件,通过DPI调用一个汇编的 C function来处理这个asm文件,生成一个HEX 代码文件,Driver可以读入这个HEX 代码,并且写入一个用实现的ROM模型中,另外通过DPI调用一个C的MCU仿真器,可以实时写出每一条指令MCU的SFR、 RAM状态,同样这些状态都保留在单独的文件中,以作为ScoreBoard的输入。

因为MCU的指令组合可以说是无法测全的,真正的测试往往要发生在应用代码测试上,Driver除了可以接受从channel中得到的指令,也可以直接从外部文件得到asm代码或是16进制代码,这样已有的MCU测试代码或是应用程序都可以在这个环境中直接调用。此外,中断的外部输入也有随机的数据灌入,外部端口的输入数据也是在指令数据包中产生,并且由TestCase控制的。MCU工作方式的特殊性,导致Driver相对于验证环境较为独立,与验证环境的接口都是磁盘文件。

4.4 C模型

环境中使用两个C模型:汇编器和仿真器,将asm代码汇编成为16进制代码,并仿真16进制代码。通过DPI调用C函数如下:

import “DPI” function void asmb_r(string in_file, string out_file);

import “DPI” function void siml(int run_for_n_ins, string in_file2, string in_file1, string in_file, string out_file, string out_file2, string out_file3, string out_file4);

如Driver所示,输入输出都是磁盘文件。汇编器通过查表将指令翻译成16进制代码,对于变量将用哈希表实现,通过查表替换,插入校验码,最后得出的16进制代码,作为MCU的C模型仿真输入,并且由Driver的ROM模型读入。

仿真器输入16进制代码,通过先解码16进制代码,然后逐条执行代码,所有memory都是在C中实现,每个指令分别调用相应的函数,此外还有相应的中断函数处理中断,在每一条指令后写出SFR,Internal RAM以及External RAM中的值到磁盘文件中,以作为RTL仿真的参照,C模型的结果直接影响整个验证的准确性,因为RTL是由时钟驱动,而C模型是不带时序关系,有些指令的执行结果需要根据时序做部分调整,调整模型在验证中占去较多资源。

4.5 memory模型

MCU外围连接了四个外部memory,包括Internal SFR、Internal RAM、External SFR以及External RAM。在验证MCU时,memory中的值就可以保证MCU的工作状态,因此在验证中,MCU的外部memory都是用实现的行为模型,除了通过interface io来响应MCU的读写要求之外,还有数据通道通往ScoreBoard,这里每个MCU时钟都会将memory值记录下来送往ScoreBoard,由于Internal SFR、Internal RAM、External SFR仅有128 byte,数据量较小,可以每个时钟周期来检查,但对于External RAM有64k byte,对比或是传输都比较耗费资源。另外,对External RAM的操作并不多,这里实现的是在Testcases中约束对于External RAM的地址都为低256 byte,这样可以有效地控制数据量并且在每个时钟周期检查memory状态,另外一种可选方式是每隔一定数量的指令来对比External RAM的值,同样对仿真影响较小。

4.6 ScoreBoard

ScoreBoard收集到从各个memory传递过来的memory值,因此对应一块memory就会有一块ScoreBoard,对比通过读取 MCU 的C模型写出的memory状态值,由于MCU模型写出的值是每条指令执行之后的值而memory传递过来的数据为每个时钟周期,这里 ScoreBoard不但要负责解读C模型写出的参照memory结果文件,通过参照将确认每个指令执行时钟周期长度,然后从memory模型传递过来的数据中选取该指令执行之后一个时钟周期的数据与参照数据进行对比,考虑到部分数据会有延迟,ScoreBoard在对比时,不仅仅考虑当前比较时间点上的数据,如果对比失败,ScoreBoard的自检会进入子线程,继续读取memory传递过来的数据,考虑到MCU支持指令延迟操作最多8个时钟周期,如果在后续16个周期内得到正确的值,ScoreBoard会认为结果正确,并且中止子线程返还检查成功标志。



关键词: SystemVerilog VMM

评论


相关推荐

技术专区

关闭