路科验证官网:路科验证 - 专注于数字芯片验证的系统思想和前沿工程领域
EETOP路科首页: EETOP - 路科验证 - IC验证培训
CSDN路科首页:CSDN - 路科验证 - IC验证培训
分享给微电子相关专业新生:微电子新生入坑指南
在上一期的Lab4中,我们对数据信息等进行了封装。今天的Lab5的学习目标是:
1.创建一个Generator transactor的类。
2.创建一个Driver的类。
3.创建一个Reciever的类。
4.拓展这个测试平台,并将Driver和Monitor同时连接到所有输入端和输出端。
在lab4中,你创建了一个封装好的数据包。但是,在一个时间内只能把数据包从一个输入端驱动到另一个输出端。
在这次的lab中,你会把generator,driver,monitor和checke等程序封装进Generator类,Driver类,Receiver类,Scoreboard类中。同时,你会创建一个testbench架构,从而将上面所有部分都容纳进来。
为了促进Packet对象从一个组件传到另一个组件,你将会使用Mailbox作为一个交流机制。
最终结构如下图所示:
任务一:发展Driver类
在之前的实验中,我们已经用一个Driverbase类封装了driver程序和program的全局变量。你将扩展这个基础类从而去产生一个新的Driver类。
1.用编辑器打开已经存在的DriverBaser.sv 文件。
2.检查Driverbase类。
在这个基础类中,下面的属性需要被声明。
对于driver中的每一个方法,有一个if-$display()连接在子程序的开始处。在debug时,它可以帮助打印出子程序所执行的序列。TRACE_ON是一个program全局变量,你稍后将会在test.sv文件中声明它和控制它。
3.关闭DriverBaser.sv文件。
4.用编辑器打开Driver.sv文件。
这个Driver类源于DriverBase类。其中In_box将会用来从Generator向Driver通过Packet对象。Out_box将用来从Driver向Scoreboard发送Packet对象。In_box和out_box都是pkt_mbox的类型。
下面是一个定义在router_test.h文件中的邮箱(mailbox)类型:
这个sem[ ]序列将会被当作一个防止多个输入端同时给同一个输出端发送数据包的仲裁机制。这个方法的结构体中在参数列表中有五个变量。name,sem[], in_box, out_box, start()。start()方法可以从in_box中获取Packet对象。
任务二:将Driver类中的new()填写完整
1.在外部所声明的结构体new(),调用super.new()和name,rtr_io argument。
2.在调用super.new()后添加一个踪迹(tracing)语句.
3.assign 属性sa和port_id。
4通过assign属性sem[],in_box,out_box等,来完成new()结构体的拓展。
任务三:将Driver类中的方法start()填写完整
在program中要例化的事务对象需要一个机制去开始,你将这个方法标准化为start()。
在这个Driver中,start()方法是在一个无限的循环中执行的。在这个循环的每一次执行中,都会从In_box中获取一个packet对象。这个数据包对象的内容将会通过send()发送经过DUT。 一旦这个packet对象的发送过程完成后,这个packet对象会被发送到计分板。
Driver的对象开始后,期望testbench中的所有其它组件可以同时运行。Start()方法中的trace语句都要在一个non-blocking的fork-join结构中。
1.在已存在的start()体内,添加一个trace语句。
2.在trace语句后,创建一个non-blocking的fork-join模块。
3.在fork-join结构里面,创建一个单独的无限循环。
4.每一个循环中将会做以下事情:
a) 从in_box中获取packet对象。
b)如果sa与获取的packet对象的this.sa中的不匹配,继续下一次循环。
c)如果获取的packet sa与this.sa匹配,用pkt2send中的内容更新da和payload类。
d).为了到达正确的目的地址,使用sem[ ]序列去仲裁。
e)一旦仲裁成功,调用send()去驱动数据包通过DUT。
f)当send()完成后,发送数据包对象到out_box。
g)在循环的最后一步,将semaphore的key返回给它的bin。
5.保存和关闭Driver.sv。
任务四:发展一个Receiver
1.用编辑器打开已经存在的Receiver.sv框架文件。
任务五:填写Receiver类的方法new()
1.在外部声明的结构体new()中,调用super.new()中的name和rtr_io argument。
2.在调用的super.new()后添加一个tracing语句。
3.将类的属性da的值通过port_id发出去。
4.将out_box 的属性通过参数列表传递出去。
任务六:填写reciever类中的方法start()
在start()方法中将会执行一个非阻塞的无限循环。每次循环中,都会从DUT中重新构建一个packet对象。一旦重新获取后,这个Packet对象将会通过发出邮箱(out mailbox)发送到scoreboard。
1.在start()方法的体中,添加一个trace语句。
2.在这个trace语句之后,创建一个非阻塞(non-blocking)的并行的线程(processthread)。
3.在fork-Join结构内部,创建一个单独的无限循环的代码块。
4.每一次循环中都会做以下的事情:
a) 调用recv()来从DUT中重新获取packet对象。
b)将从DUT中获取的packet对象复制一份到out_box中去。
5.保存和关闭Receive.sv文件。
任务七:检查generator类
已经准备好了Generater.sv文件,它已经封装了你之前完成的gen()程序和一个start()方法。
这个Start()方法和前面的相比有两个重大的不同。一是:这个start()方法的循环由系统全局变量run_for_n_packets控制。如果run_for_n_packet<=0,则这个循环是无限的。如果它>0,则这个循环在循环这么多次后会停止。二是:在调用方法gen()之后,会创建一个随机化packet对象(pkt2send)的拷贝,并且通过out_box邮箱发送到Driver。
任务八: 检查scoreboard的类
scoreboard.sv文件已经为你写好了,它主要封装了你之前已经写好的check()程序。这个类的新特征是可以实现Scoreboard,Driver和Receiver之间的通信。Driver在发送数据包对象到DUT中时,也会将它发送到driver_mbox邮箱。一个Receiver在从DUT接收到数据时,也会发送packet对象到receiver_mbox邮箱中去。
当scoreboard在receiver_mbox中发现一个packet对象时,它会把这个对象存储为pkt2cmp中去。接着,推动所有从driver_mbox中获得的packet对象到refPkt[$]序列中去。然后,在pkt2cmp对象中的输出端口地址(da)的基础上,将会查找在refPkt[$]序列的相应位置上的packet,并比较它们的内容。如果发现存在不匹配的packet,就报告一个错误。
当packet对象的数量与全局变量run_for_n_packets相匹配的话,一个叫DONE的事件flag会被触发。这个DONE flag将会让整个仿真在合适的时间结束。
任务九:修改test.sv来使用这些新类
你将会修改这个testbench,使它拥有一个Generator,一个Scoreboard,16个Driver和16个Receiver。
testbench整体结构:
1.用编辑器打开test.sv文件。
2.删除所有全局变量除了run_for_n-packets。
3.创建int型变量 TRACE_ON并且初始化它到0(当想去debug时将其变为1,从而让子程序执行tracing)。
4.在两个全局变量后面,添加include语句来包括所有头文件和这些新的类文件(router_test.h Driver.sv,Receiver.sv, Generator.sv, Scoreboard.sv)
5.在这些include语句后面,添加如下的程序全局变量:
6.删除所有initial块中的内容除了下面这两个:
7.构造所有声明在program块中的对象,确保这些邮箱都是正确连接的:
Generator到所有Driver(gen.out_box[i]);所有Driver到一个Scoreboardmailbox(sb.driver_mbox); 所有Receiver到一个Scoreboardmailbox(sb.receiver_mbox)。
8.在所有对象都被声明之后,调用reset()来重置DUT。
9.接着开始所有事务(transactor)。
10.最后,在program结束之前,设置scoreboard“DONE”的事件flag。
任务十:混合检查
1.下面子程序应该从test.sv文件中删除
(确保reset()没有被删除)
当完成以上步骤时,你的test.sv文件应该如下所示:
2.保存和关闭test.sv文件.
任务十一:编译和仿真(略)
至此,Lab5已经完成啦。点击左下角的阅读原文,即可查看这次Lab所用到的全部代码。下周四Lab6的内容是:
1.实现功能覆盖率功能从而决定仿真该何时结束。