sv la3学习记录
#==================================================================================
- lab_tb1
1)generator里创建了两个maibox用来握手。 ① 在generator类中,先将randomize产生的随机数放到 req_mb的mailbox中(发送给initial),然后一直在这里等rsp_mb的get ② 在initial类中,复位后就一直get等待req_mb的数,只要有数来了,就立即执行chnl_write(发送数据),否则就一直在等待。发送完之后,将req clone给rsp,改变rsp这个类中的rsp变量为1;(注意这里有点绕,前面的rsp是个类,后面的rsp是个变量,代表数据是否已经成功发出。而且 这个rsp变量没有rand, 不会被随机化) 将其放到rsp_mb的信箱中发送给generator类 完成一次握手,当generate拿到rsp.rsp = 1时候,代表数据发送成功。
为什么需要这一个bit (即rsp.rsp)? ① 因为后面对于一些复杂的总线,有的时候发送数据会成功,也有时候发送数据失败。我genenrator把数据交给了你initiator,你不仅仅需要把数据发送到总线上,而且如果发送失败,总线(interface)上一般有发送错误或者失败的标志信号,此时initiator需要将error通过put rsp写回给generator。这样的好处是:我generator不仅可以发送随机的数据给总线,而且可以通过initiator获取总线的状态,看我每次产生的激励是否真正的有效的给到了总线上(interface)。 ②有时候激励也需要读数据,那么也可以通过initiator 的put rsp把总线上读的数据返回给generator。这样的好处是:我generator不仅可以发送数据,而且可以读想要的数据。
=》有个这两个fifo, 从generator到总线的数据流就从以前的单向变成了双向。
2)代码中注意事项: ① generator里用new()创建了两个maibox; 而initiator中仅仅是申明了两个mialbox的句柄,并没有创建(new)。 ②在agent中做了连接。在agent中将init中悬空的句柄和gen中创建的句柄连接起来。 通过mailbox沟通的双方,都需要声明mailbox的句柄,但只要一方创建即可,另外一方悬空;在更上层将双方的句柄连接起来。
3)总结 从lab3开始 代码中结构发生了变化 ①产生数据,产生多少次数据,完全交给generator class,agent不再过问。 ②agent完全变成了一个盒子,只负责封装跑run; ③initial 变得贪得无厌了,永远在等待,只要有邮件进来,立即发送出去; ④谁可以控制停下来?initial是停不下来的,只有generator可以停下来,产生完有限的数据后就停下来退出。==》 所以这里用fork … join any(有任何一个线程执行完毕(generator),则停下来跳出)
#================================================================================== 2. lab3 tb2 1) 外部怎么去控制内部的? 通过当前generator中的随机变量来影响chal_trans中的随机变量。实现一层一层的控制。 即如果我generator中的成员变量(以pkt_id为例),我generator中的pkt_id大于0,则chnl_trans中的pkt_id就会和我generator中的值保持一致。更加方便的从外部去控制。 我只要randomize generator就可以间接控制randomize chnl_trans。
而为什么generator中我这些初始值都给负数(-1)? => 默认走内部chnl_trans自己去randomize,外部不去控制。
而randomize generator发生在哪里呢? => 发生在do_config中,所以顺序上要先do_config(); => 我只要在do_config中就可以从外部去影响genenrator中的randomize,从而间接控制randomize chnl_trans。
2)结构图
每一个test里边就是要实现 do_config() I do_config()可以randmoize每一个generator I generator得到randmoize,它又可以进一步randmoize req这个对象
自顶而下实现控制,而每个test只要改变do_config中的值即可。其他部分root_test都已经搭建好了。
3)总结 与tb1 不同: ① generator层已经从agent层中拿出来 ②generator是怎么做随机化的?通过do_config事先对generator做随机化,generator里的run进一步对chnl_trans做随机化 ① 只需要对每一个test做randmoize,接下来每一个generator怎么样randmoize里边的chnl_trans,怎么样把generator发送给initial,每个test都不需要担心,因为这些都全部交给了root_test。==》每个test只需要改do_config就行 root_test整个结构都是确定下来的,各个test不同的部分只有do_config不同
② 当修改test时候,不再需要重复的编译, 通过vsim +TESTNAME=chnl_burst_test work.tb3_ref 指令,就可以选择哪一个软件盒子。大大方便且减少了重复编译的时间。 vsim +TESTNAME=chnl_burst_test work.tb3_ref
加上之前的随机种子,应该是 vsim -novopt -solvefaildebug -sv_seed random +TESTNAME=chnl_burst_test work.tb3_ref
③ 实验2(lab2)中 每个句柄都会被放到这个队列中,即所有的对象都不会销毁。这种代码习惯不好,仅仅可以用来调试,即我跑完以后,用一个循环语句打印出来。 而lab3用的打乒乓球(boxmail)的方式将句柄传递,减少内存消耗。
#================================================================================== 3. lab3 tb3 1)逻辑框图 层次结构图 代码结构图 root test 结构图 2)相关问题归纳 ① checker时,为什么要先从out里边拿数据? 只有从输出的数据中才能知道该数据是从哪个通道过来的,然后再去拿这个通道的in数据 ② 调试的时候发现ch_id永远是0。注意这里打印的是chnl_trans的值。 gen中做的是req 的随机化,而req的约束中ch_id=0; 下面是generator的类 路桑有个小的疏漏,没有将gen[0]-gen[2],分别分配三个chnl_id。框框中的内容是我自己加进去的。否则导致所有的数据通道都是0。
|