1. 前言
总线验证会涉及很多Masters和Slaves接口,少则十来个,多则成百上千个,每个口通常都需要挂接对应的VIP来产生激励,如下图示例,有5个Master VIP,4个Slave VIP。挂接的Master VIP用于发起激励,挂接的Slave VIP用于响应激励。在挂接如此众多的VIP验证环境汇总,需要有更高效且灵活的方法去控制每一个VIP激励行为。
图1 总线示例
如何判断一种方法是否灵活且高效呢?有这几个标准:
方便控制;
可读性强;
代码量少且规整;
易于修改和拓展;
我们接下来先举一个直接例化法(不推荐的方法),再引出枚举动态数组法(推荐的方法),方便比较两种方法的差异。
2. 直接例化法
直接例化法是将每一个Master VIP单独声明和例化,每个VIP之间毫无关系,如图2所示,红色字体为句柄名字。
图2 直接例化法环境
例化代码示例如下:
AXI_MST_VIP axi_mst_vip1 = AXI_MST_VIP::type_id::create("axi_mst_vip1", this);AXI_MST_VIP axi_mst_vip2 = AXI_MST_VIP::type_id::create("axi_mst_vip2", this);AXI_MST_VIP axi_mst_vip3 = AXI_MST_VIP::type_id::create("axi_mst_vip3", this);AHB_MST_VIP ahb_mst_vip1 = AHB_MST_VIP::type_id::create("ahb_mst_vip1", this);AHB_MST_VIP ahb_mst_vip2 = AHB_MST_VIP::type_id::create("ahb_mst_vip2", this);AXI_SLV_VIP axi_slv_vip1 = AXI_SLV_VIP::type_id::create("axi_slv_vip1", this);AXI_SLV_VIP axi_slv_vip2 = AXI_SLV_VIP::type_id::create("axi_slv_vip2", this);AHB_SLV_VIP ahb_slv_vip1 = AHB_SLV_VIP::type_id::create("ahb_slv_vip1", this);APB_SLV_VIP apb_slv_vip1 = APB_SLV_VIP::type_id::create("apb_slv_vip1", this);
这个方法的优点是一目了然,但代码不紧凑美观,而且不方便控制、修改和扩展。比如,我们要把所有VIP的sequencer都start起来,需要一行行的写xxx.start(),或者要把VIP monitor的analysis_port和scoreboard连接起来,也需要一行行的写xxx.connect(xxx)。再比如要新增一个或减少一个VIP,要在声明、例化和调用的地方都一一做修改。一旦某个地方漏了改,就可能造成验证激励的完备性不足。
综合来说,这个方法可以用,但是性价比不高,在小规模总线验证中使用还可以。
3. 枚举动态数组法
枚举动态数组法根据VIP类型定义一些动态数组和枚举类型,动态数组的key是枚举类型,value是指向VIP的例化对象。同类VIP会被包裹在同一个动态数组内,如图3所示,相同颜色字体的句柄名字为同一个动态数组。
图3 枚举动态数组法环境
例化代码示例如下:
typedef enum {axi_mst_vip1 = 1,axi_mst_vip2 = 2,axi_mst_vip3 = 3} axi_mst_t;AXI_MST_VIP axi_mst_vip[axi_mst_t];axi_mst_t e = e.first();forever beginaxi_mst_vip[e] = AXI_MST_VIP::type_id::create(e.name(), this);if ( e == e.last() ) break;e = e.next();end
由上代码可以看出,这种方法至少有以下几点好处:
同类型VIP的控制可以使用foreach等循环语句进行操作;
可读性强,根据动态数组axi_mst_vip的key值就可以看出是哪个VIP,引用起来很方便;
在规模很大的总线中,这种做法会使得代码非常简洁,而且让人看起来赏心悦目;
非常容易扩展,比如要新增一个AXI_MST_VIP,只需要在枚举里添加一个新的枚举值就可以了,其它代码都不需要改;反之,删除同理。
当然,可能有人想把上述方法改成静态数组来做,不使用枚举类型。比如:
AXI_MST_VIP axi_mst_vip[3];foreach ( axi_mst_vip[i] ) beginaxi_mst_vip[i] = AXI_MST_VIP::type_id::create(“axi_mst_vip”, this);end
这个确实也可以,但是可读性不强,比如axi_mst_vip[0]对应哪个VIP呢?我们还得需要去查表或看图或记住这些数字的含义,在可读性方便略输一筹。按枚举动态数组法,我们可以很容易的看出来axi_mst_vip[axi_mst_vip1]对应AXI_MST1 VIP,非常好用。当然,这种方式在小规模总线中,优势没有那么大,随着规模越大,它的优势越明显。
479