1、tb1/chnl_pkg1——学习随机约束

  • 测试的流程:

    1、初始化,组件的例化和链接:basic_test = new();

    chnl_basic_test.new(ntrans = 200, name = “chnl_basic_test”),chnl_root_test()的new()中例化3个agent,agent[0/1/2] = new(“chnl_agent0/1/2”, id = 0/1/2, ntrans = 200),每个agent中例化一对generator/initiator,id = 0/1/2和ntrans = 200传入每一个generator的id和ntrans,"chnl_agent0/1/2"传入initiator的name。

    generator和initiator中分别例化和声明两个存放chnl_trans类型句柄的mailbox信箱(initiator只声明并没例化,之后run的时候,在agent()中会将gen的俩mailbox句柄赋给init的信箱句柄)。

    2、连接接口:basic_test.set_interface(chnl0_if, chnl1_if, chnl2_if);

    接口传递的层次:chnl_basic_test.set_interface() → chnl_root_test().set_interface() → chnl_agent.set_interface() → chnl_initiator.set_interface()

    3、运行:basic_test.run(); run的层次:chnl_basic_test.run() → chnl_root_test().run() → chnl_agent.run() → agent[0/1/2]同时并行run,都结束再退出→ 三对gen(0)init(0) / gen(1)init(1) / gen(2)init(2)同时run,有每一对中gen或init有一个结束就退出该agent线程 → 首先是三个gen先被send_trans()方法被激活启动(init中的drive()循环语句中的第一句是"this.req_mb.get(req);"因为req_mb中还没放元素,所以该drive()被阻塞住),先声明俩chnl_trans类型句柄req/rsp,只对req例化,然后对该句柄指向的对象随机化,之后包的ID"pkt_id"累加1, 然后将req对象成员都打印出来,再把它放进req_mb信箱里,此时,init中的get()会拿到req对象便将req这个trans发送到通道上。 之后,再将req对象克隆给rsp(⭐️注意:此处为对象的浅拷贝,两个句柄req和rsp指向两个不同的对象,且rsp的obj_id比req的大1),然后又把rsp对象中的rsp这个变量赋予1,因为变量rsp初始值是0,所以req中的rsp变量是0。 然后又把rsp这个对象放进信箱,此时,gen中的get()会拿到这个返回的rsp对象,并将其成员打印出来,至此完成一次握手。这就意味着,如果打印出的rsp变量如果是1的话,就表明其对应的trans已经成功发送到chnl上了,rsp = 1相当于一个trans成功产生并发送的标志。

  • 要求1.2:obj_id被设置为了static静态变量,它处在一个独立的空间,既不在c里也不在this里。c和this都是通过访问静态变量的空间来获得obj_id的值。也就是说,加了这句话c.obj_id = this.obj_id,其实就相当于obj_id = obj_id,或者按类来索引写成,chnl_trans::obj_id = chnl_trans::obj_id,把自己赋值给自己,没有意义。

  • 要求1.5:同一时间chnl_trans对象的数量是多少?可以使其变少吗?

    对于一个agent,同一时刻最多存在3个对象。整个仿真过程中,在同一时刻,3个agent最多的时候一同有9个chnl_trans对象在仿真器内存中存在。

//chn1_pkg1
package chnl_pkg1;class chnl_trans;rand bit[31:0] data[];rand int ch_id; //表示trans目前想发送、复制到哪一个chnlrand int pkt_id; //当前数据包的id,即第几个transrand int data_nidles; //数据之间的空闲周期数rand int pkt_nidles; //数据包之间的空闲周期数bit rsp; //响应标志位local static int obj_id = 0;

2、tb2/chnl_pkg2——更灵活的测试控制

  • 将chnl_generator放在chnl_agent外边,和chnl_agent并行放在chnl_root_test中,是为了更好的在test中控制激励的产生和随机化。

  • chnl_generator中先给变量(chnl_id、pkt_id、data_size、data_nidles、pkt_nidles等这些供外部test进行随机化使用的变量)都赋初始值为-1,然后约束它们都等于-1,再在send_trans()函数中对chnl_trans类型对象req进行声明、例化、随机化并增加内嵌约束规定这些变量在>=0时才进行ch_id == local::ch_id操作等(将这些供外部随机化的变量的值赋给内部trans类型对象的变量,local::则是说明该变量属于当前chnl_generator类中的变量)。
    想要通过test对trans类型对象变量进行随机化控制,需要在chnl_generator类中对trans类型对象变量进行的soft软约束,然后才可以通过外部进一步约束来改变这些变量值 。也需要将这些外部随机化的变量的值赋给内部trans类型对象的变量,并且这一操作应该是伴随着外部每一次随机化的进行而进行的(即外部对chnl_generator的对象gen进行随机化时,触发了gen内部某些条件,从而进行赋值操作),故在chnl_generator内部将变量都初始为负数(-1),并设置触发条件local::ch_id >= 0时才会进行赋值操作。

  • 源代码缺少对ch_id的约束赋值,在chnl_root_test中的do_config()加上对应的ch_id值即可。

  • 变量pkt_id(记录随机化trans的个数)不需要进行随机化,其设置在chnl_generator的send_trans()中的随机化req语句后累加1,故每随机化一个trans后,pkt_id++1。pkt_id初始值为-1,第一次随机化后pkt_id=0,触发语句local::pkt_id >= 0 -> pkt_id == local::pkt_id,将chnl_generator中的pkt_id值赋给req.pky_id。

  • 2.5:在package中定义一个全局的semaphore旗语run_stop_flags,在chnl_generator中run()的send_trans语句后放入钥匙run_stop_flags.put();在chnl_root_test中定义run_stop_callback()方法,在其中等待三个钥匙run_stop_flags.get(3);也就是说当拿到三个钥匙,说明三个gen已经都发送完数据。

  • 2.6:通过仿真指令项"+TESTNAME=testname"来进行仿真,在仿真时直接利用仿真器来输入不同测试名称,便可进行不同的随机测试,不用更改代码部分。这种方式是回归测试的雏形。

3、tb3+chnl_pkg3——理解测试平台的结构