| ||
在上一期的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文件。