优化函数传参,花里胡哨的那种

文摘   2024-08-03 12:07   上海  

任何编程语言中,函数都是进行功能封装,模块化设计的必备手段之一。在Systemverilog中也不例外,SV中有function和task之分,都属于广义上的函数。

在函数的设计和编码规范中,我们往往会尽量减少入参的个数,一方面是为了函数的简洁和可读性,另一方面也是对环境质量和仿真性能有所裨益。

此前,在验证环境中看到一个对用户开放的API函数,含有多达6个传递参数。便想着,如何能减少函数传递参数的个数?下面是一些粗浅的见解和尝试,分享如下。

一开始的API函数原型如下,目的在于实现一个支持不同需求的总线读写请求,如读/写地址和数据,总线master的ID,是否返回resp,安全或非安全访问,byte操作,device/cacheble。

用户侧的调用大概是这样的:

bus_write(32'h1000_0000,32'hA5A5_5A5A,,1,write_resp,1,0);

其实无论从API的维护和用户的使用角度来看,似乎都可以做一些简单的改进。

用户侧

首先从用户侧来看,即使API函数的参数无法减少,也可以使用参数名bind的方式,以增加可读性,如:

开发维护侧

单一功能函数划分

开发侧而言,可以采用划分单一功能函数的方法进行折中处理。相比对用户开放大而全的API函数而言,换而开放多个单一功能的函数,如安全/非安全写,device/非device操作,带resp/不带resp操作。

如此上述的bus_write可以拆分为:

task bus_write_sec(input  bit[63:0] x_addr,
       input  bit[63:0] x_write_data,
       input  bus_idx x_bus_id=BUS_VIP_0, 
       input  bit is_non_sec = 1);
//.......
endtask

task bus_write_device(input  bit[63:0] x_addr,
       input  bit[63:0] x_write_data,
       input  bus_idx x_bus_id=BUS_VIP_0, 
       input  bit is_device = 1);
//.......
endtask

task bus_write_with_resp(input  bit[63:0] x_addr,
       input  bit[63:0] x_write_data,
       input  bus_idx x_bus_id=BUS_VIP_0, 
       input  bit is_get_resp = 1);)
//.......
endtask

而每个单一功能函数的实现上,既可以调用原"大而全"的函数,也可以自行开发,如此可把复杂内聚化,对外易用简单化。

改变参数传递的数据结构--联合数组

如果用户侧仍是需要"大而全"的API函数,比如随机这些参数进行测试,那可以尝试改变用户和API函数参数传递的数据结构。

联合数组,也称字典,是一种非常使用而又功能强大的数据结构,是"架构级的数组形式"。---一种架构级的数组形式  联合数组

我们可以把众多的参数封装在联合数组内,由用户传递对应的key-value。如此原来函数的入参结构可以修改为:

task bus_write_api(
    input  bit[63:0] x_addr,
    input  bit[63:0] x_write_data,
    input  bit[31:0] x_ctrl_para[string]='{}
       );
      //....
endtask

用户侧的调用修改为:

对于用户未传入的参数,API函数内部自行取得默认值即可。

参数化函数

此外还有一种可以实现,但好像有没有太多收益的办法,就是把原来函数的一些入参成为参数化函数的parameter。在调用函数时,把入参作为函数的parameter。

在这种方法下,原API定义改写如下:

用户侧的调用则修改为:

bus_operation #(BUS_VIP_0,1,0,1)::bus_write_api(32'h1000_0000,32'hA5A5_5A5A);
bus_operation #(.x_bus_idx(BUS_VIP_0)
         .x_get_resp(1),
         .is_device(0),
         .is_non_sec(1))::bus_write_api(32'h1000_0000,32'hA5A5_5A5A);

但这种方式需要virtual class内部的task是static类型,某些场景下还是会受到限制。



这里是验证芯发现,原创不易,欢迎赞赏、点赞、在看和分享。

感谢关注和支持。


验证芯发现
验证工程师的公众号,记录芯片验证的方方面面。