1
在一个验证平台中,有众多的参数需要配置。如在mac_driver中,按照以太网相关协议的规定,在发送一帧数据前要先发送几个preamble(即8’h55),1个sfd(即8’hD5)。那要发送几个preamble呢?这个可以在driver中设置一个pre_num的变量来控制。
之后在main_phase中,每发送一个transaction之前,先把pre_num随机化一次,得到一个3~7之间的数字,然后把这个数字作为发送preamble的数量:
在只发送正常帧的情况下,上面的代码是可以工作的。那如果再想增加一个case,测试一下DUT对于preamble数量的敏感性,也就是说要发送小于3个或者大于7个的preamble。那么应该怎么办?很明显的一点,这种情况是跟具体的case相关的,新加的这个case不能影响其他case的正常运行,同时我们也希望,mac_driver尽量不因为加入这个case而做改变。
2
要实现上面的这个功能,有众多的方法。一种方法是把pre_num_max和pre_num_min设置成全局变量,这样,当要发送小于3个的preamble时,可以把pre_num_max设置为2,把pre_num_min设置为0。当要发送大于7个的preamble时,可以把pre_num_min设置为8,把pre_num_max设置为100。前面说过,类似config_over这种全局变量应该尽量避免使用。这里也是如此,过多的使用全局变量最后如果发现全局变量的值跟我们预期的不一样,那么排查这个全局变量是如何改变的将会是一件现代刚痛苦的事情。使用全局变量大大增加了出错的概率。
与全局变量想对应的就是本地变量,但是很明显,本地变量的值要想在不同的case中改变会是相当困难的一件事情。那么有没有这样一种全局变量,即它只能被某些特定的class被修改,而不能被其他的修改呢?也就是说,这个变量对于一些类是可见的,对于另外一些类是不可见的,似乎就像是一个半全局变量一样。
在上图中,我们希望只能在test和env及i_agt中才能改变driver中pre_num_max和pre_num_min的值,而类似monitor,scoreboard,reference model等都不能改变。可以在uvm_test_top使用如下方式给pre_num_max赋值:
env.i_agt.drv.pre_num_max=100;
如果pre_num_max为public,那么这种方法是可行的。但是,在pre_num_max为local的情况下,这种方法是不可行的。
无论任何语言,都不会提供这种半全局变量。要想达到这种半全局变量的效果,必须通过某些特殊的机制实现。UVM提供了config机制用以实现这种要求。
3
config机制在UVM验证平遥中都是成对出现的。如在某个case(派生自uvm_test)的build_phase中可以做如下设置:
uvm_config_db#(int)::set(this,”env.agent.driver”,”pre_num_max”,100);
那么在driver的build_phase中要这样做:
uvm_config_db#(int)::get(this,””,”pre_num_max”,pre_num_max);
这样,设置的pre_num_max的数值100就会传递给driver的pre_num_max。
uvm_config_db中的set和get都是静态函数,所以可以用双冒号的形式调用。上面set中的第一个参数用以说明是哪个component对pre_num_max进行了设置,一般使用填写this,第二个参数表示调用uvm_config_db::set的地方看下去,要设置的变量所在的component路径。第三个参数表示一个记号,用以说明这个值是传给driver中的哪个变量的。第四个参数是需要设置的值。
get中的第一个蚕食一般也是this即可。第二个参数填写一个空的字符串,第三个参数就是set中的第三个参数,这两个参数必须匹配起来,第四个参数是要设置的变量。