前面提到过TOS,在Fusion面前,TOS的灵活性就显得捉襟见肘了。为了不致于很快忘记,我尽量写的详细些,尽量粘一些伪代码(如有侵权问题,请通知我,即可删除)。
1. What is Fusion
叫fusion的实在是太多了,可能就是因为这个世界里太多杂乱无章吧。像amd 的fusion, 软件fusion,乐队fusion,福特fusion,哈哈。
在A公司的验证圈子里,fusion是一种软件框架,其中集成了randomization, reusability等概念。对了fusion是C++写的。在该框架下,Generator负责产生测试激励,Driver负责将Generator产生的激励转变成真实的信号驱动dut,Monitors负责监视dut端口信号的变化进而产生一些event来通知上层的Checker。这些就是基本的构成,和UVM/OVM基本相同哦,注意Fusion可是90年代的产物 :)
2. How it works
2.1 testcase 示例
Testcase是由配置信息,一个最简单的case应该是这样的:
EtnGen.InitCmd = {
CMD1: Write, 0x1000ff0c, 0x3, 0xffffffff, 0x0000000f;
CMD2: Read, ....
}
EtnGen制定了一个generator, InitCmd是该generator所使用的命令列表,该列表会在runtime读到generator中并指导gen产生相应的激励。
值得说明的是当有多个generator协同工作的时候,我们会写一个更上层的结构,来指导这些generator工作,基本上和UVM的virtual sequencer对应,如:
Workboard.CmdQ = {
EtnGen.CMD1, AXIGen.CMD1, ...
}
这些实例都是针对dedicated的case而言的,所谓dedicate case就是这些case完成特定序列,没有random机制,产生跑的pattern不会随仿真环境变化而变化。
另外一种,也更重要的case是random的case,我们尽量会把generator写的智能些,这样只需简单的配置就可以产生多种多样的传输,例如:
rk.pc0.AceMasterGenerator.AceCommandSelector.CommandBias = distribution(Poisson)
{
// Read
{ "Read", 2400 } // Snoopable commands 70% of the time
{ "ReadAtomic", 400 } // Snoopable commands 70% of the time
{ "RWITM", 1400 } // Reads 60% of snoopable commands. 2-1 Read-RWITM
{ "RWNITC", 0000 } // Snoopable RWNITC to Seg 0 cannot be issued
// Write
...}}
上述代码都属于一个叫做parameter的文件,在运行时,generator会解析这些信息并指导该如何运行。
2.2 fusion和simulator的交互
fusion的最底层是和simulator进行交互的layer,目前支持ncsim和mesa。对该层的作用,你可以理解成他可以把c++用到的变量和信号建立起联系,例如:
#prefix TP.tpiReadDataEvt CORE_0.TP_SUB{
ReadDataR 0 31 I_TPI_RDDATA_R 63 32 [71]
ReadDataEccR 0 7 I_TPI_RDDATA_R 71 64 [71]
}
上述代码中ReadDataR是tpiReadDataEvt这个C++文件中的一个变量,而 I_TPI_RDDATA_R是CORE_0.TP_SUB层次中的一个信号。
2.3 关于simulator
在A公司,验证工程师会使用2中仿真工具,就是上面提到的mesa和ncsim,其中以mesa为主。mesa是一种基于cycle的simulator,ncsim是基于事件队列的simulator。mesa不支持verilog中的延迟语句,所有的事件都会调度到一个tick的沿(ticktime可以设置成所有clock的最小公倍数)。举例说明:
上述例子很好的代表了eventsim和cyclesim的区别,此外cyclesim目前无法支持analogcore的仿真,而起有些verilog或vhdl的写法也会导致仿真问题。那既然这么多缺点为什么还要用mesa呢?因为
对于那些缺点,本人也在和eda team合作来搞一个hybrid的env,对于不能在mesa上跑的,我们会使用ncsim,主体还在mesa上。后面会有介绍该项目。
3. 更高层次的抽象
前面提到testcase是由parameter写好来指导generator产生激励,这对于unit level或者soc的验证还行的通。但是对于复杂的ip,如多核处理器,这种方法就不够好了。于是抓到机会的中东某国工程师们搞出来一个Gensys-Gpro-XGen的工具。简单来说,该工具是针对cpu验证的,验证工程师可以使用一种简单语言告诉此工具说我要产生一个能够让cpu产生缺页中断的scenario,或者我要多个cpu核产生coherency intervention的操作,或者简单点的如我要写一条简单的load操作,等等,该工具就能生成一个或多个指令序列。然后fusion里面有一个叫avp的code负责把这些代码编译并preload到相应的位置。
当然,如果你想使用xgen比较高级的用法,你需要很detail的为xgen写一个该cpu的architecture描述。
在我们做一个3核cpu项目的时候,大量的case都是这么弄的,而且xgen支持random,整个regression的testcase全部是xgen或者gpro的配置信息,可以很好的集成在hdwb(hardware work bench),一个可视化的数据库前端,支持script接口,方便验证工程师跑regression,和cadence的某一个gui工具类似,但比cdn早了很多年。
补充一下,xgen不会产生期待结果,可能是random的太厉害了吧 :) 所以我们又写了很多代码来监视L1L2一致性信息。由于当时刚开始接触C++,这些代码写的简直就是个噩梦,在此对这些代码后来的维护者表示歉意。
4. 配套工具以及开发语言
4.1 geyzer
该工具号称是A公司eda多年的智慧结晶,geyzer是一种验证异步接口的工具。应用场景应该是这样的:
当芯片设计完成了,设计者或者geyzar supporter会写一个该芯片的clock文件,例如某个signal是clock,频率是多少和其他的哪些clock有关系。然后进入静态分析的阶段,该阶段和后端的著名的einstimer(是不是很像einstein :))的某一个功能点类似,分析整个芯片的clock结构,找出所有异步的接口并生成报告供review。该步骤结束后,进入仿真验证阶段,在把设计文件编译成仿真model的时候,可以指定clock信息,这样编译出来的model会在异步接口上插入一种随机的latch结构,仿真的时候,该机构就会随机的插入1个ticktime或者多个ticktime的延迟,看你的case是否会因此fail。当然因为用到了tick概念,geyzer目前只能工作在mesa环境下。
4.2 bugspray
bsp是一种语言,可以写成断言也可以写出来逻辑,实际上在a公司也正是这么用的。
coverage是基于bsp的断言,其中又分assertion和harvest断言,assertion失败导致case fail,harvest是收割coverage,针对functional coverage。
在modelbuild好之后,仿真开始之前,我们会建立bsp服务器来收集该model的所有仿真结论。当case pass,fusion最后阶段会把coverage信息发送到bsp server, 工程师可以使用bspserver分析coverage数据。
4.3 6senses
6senses基于sequencial equivalence check的概念。一个简单的例子:对于MUX的验证,如果很多输入,你怎么保证coverage。6senses可以帮助你。你写一个约束告诉它在什么情况下,输出和输入什么关系,然后,6senses就帮你遍历所有情况了,如果出错会保存错误scenario的波形。
另外6senses还可以这么用,你有2个版本的design file,需要看是否等价,你就告诉6senses他们在什么情况下应该等价,然后就没有然后了 :)
本文出自 “Hardware_Accelerator” 博客,转载请与作者联系!