设计模式在芯片验证中的应用——策略

ops/2024/9/25 17:12:13/

1. 策略模式

策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。

在RTL设计中可能包含了复杂的多个访问仲裁逻辑,使用了多种算法来确定访问内存优先级顺序,包括规定优先级、轮询仲裁等等。仲裁器的输入是多个请求者信号,以及选择要使用的仲裁算法的配置。根据选择的类型和请求者信号的值,仲裁器确定具有最高优先级的请求源,并授予它访问内存的权利。如下图所示,仲裁类型可以动态配置,这就是为什么该特性适合使用策略设计模式进行建模。在该模式中,可以在testcase运行中从提供的一系列算法中选择要应用的特定算法。此外,还可以直接为仲裁添加新算法,而无需修改之前代码。值得注意的是,之前讲到的装饰器设计模式也可用于动态更改行为,关键的区别在于,装饰器模式在原功能基础上添加额外的功能,而策略者模式直接更改原先功能。总得来说,策略模式可以让你改变对象的内部结构,装饰器模式允许你更改对象的皮肤。

策略设计模式主要包括以下几个组件:

策略(Strategy):定义了所有具体策略(Concrete Strategies)的通用接口,它声明了一个上下文(Context)用于执行策略的方法。在这个例子中,策略定义了仲裁的接口函数arb_winner()。

具体策略(Concrete Strategies):实现了上下文所用算法的各种不同变体。在这个例子中,对于每个必要的算法,定义了一个具体策略类,提供特定算法的实现。将每个算法包装到一个单独的类中可以提高代码的可读性和可扩展性。

上下文(Context):维护指向具体策略的引用,且仅通过策略接口与该对象进行交流。比如UVM scoreboard组件依赖于Strategy,检查RTL内的仲裁逻辑是否正确实现,那么UVM scoreboard可以被认为是Context。

客户端(Client):会创建一个特定策略对象并将其传递给上下文。上下文则会提供一个设置函数以便客户端在运行时替换相关联的策略。当上下文需要运行算法时,它会在其已连接的策略对象上调用执行方法。上下文并不清楚其所涉及的策略类型与算法的执行方式。本例的客户端是example_application。

下图为策略设计模式在仲裁中应用的UML类图。

策略模式让你能将不同行为抽取到一个独立类层次结构中, 并将原始类组合成同一个, 从而减少重复代码。而且让你能将各种算法的代码、 内部数据和依赖关系与其他代码隔离开来。 不同客户端可通过一个简单接口执行算法, 并能在运行时进行切换。

2. 参考代码

仲裁处理的策略设计模式参考代码如下:

virtual class strategy;pure virtual function int arb_winner(ref bit req_arr[3]);
endclass : strategyclass strategy_low_priority extends strategy;virtual function int arb_winner(ref bit req_arr[3]);for (int i=0; i<3; i++) beginif (req_arr[i] == 1) beginreturn i;endendreturn -1;endfunction : arb_winnerendclass : strategy_low_priorityclass strategy_high_priority extends strategy;virtual function int arb_winner(ref bit req_arr[3]);for (int i=2; i>=0; i++) beginif (req_arr[i] == 1) beginreturn i;endendreturn -1;endfunction : arb_winnerendclass : strategy_high_priorityclass my_context;local strategy m_strategy;function void set_strategy(strategy _m);m_strategy = _m;endfunction : set_strategyfunction int execute_strategy(ref bit req_arr[3]);return m_strategy.arb_winner(req_arr);endfunction : execute_strategyendclass : my_context

模拟测试代码如下:

class example_application;rand bit low_priority;rand bit high_priority;constraint p_cons { low_priority + high_priority >= 1; }function void main();int result;bit req_arrary[3] = '{1'b0, 1'b1, 1'b1};strategy stg;my_context m_ctx = new();`uvm_info("strategy", $psprintf("low_priority:%b, high_priority:%b", low_priority, high_priority), UVM_LOW)$display("The input req0:%b, req1:%b, req2:%b", req_arrary[0], req_arrary[1], req_arrary[2]);if ( low_priority ) beginstg = strategy_low_priority::new();m_ctx.set_strategy(stg);result = m_ctx.execute_strategy(req_arrary);$display("For low priority, the result is: %0d", result);endif ( high_priority ) beginstg = strategy_high_priority::new();m_ctx.set_strategy(stg);result = m_ctx.execute_strategy(req_arrary);$display("For high priority, the result is: %0d", result);endendfunction : mainendclass : example_application

输出仿真日志如下:

 | # [strategy] low_priority:1, high_priority:1| # The input req0:0, req1:1, req2:1| # For low priority, the result is: 1| # For high priority, the result is: 2

从仿真结果可知,low_priority为1,high_priority为1,因此example_application类选取了strategy_low_priority类和strategy_high_priority类两个算法。

在strategy_low_priority类中,输入信号中,req0=0,req1=1,req2=1,req1输入口被选中,因此输出的结果是1。

在strategy_high_priority类中,输入信号中,req0=0,req1=1,req2=1,req2输入口被选中,因此输出的结果是2。


http://www.ppmy.cn/ops/5150.html

相关文章

Python爬虫:urllib库的基本使用

文章目录 一、urllib简介二、请求的发送和响应&#xff08;一&#xff09;发送请求&#xff08;二&#xff09;获取相应内容&#xff08;三&#xff09;下载所需文件 三、URL请求对象的定制四、常见请求方式&#xff08;一&#xff09;get请求方式&#xff08;二&#xff09;po…

打开电脑底部导航栏的任务

from pywinauto import Application app Application("uia").connect(path"explorer") app["任务栏"].print_control_identifiers() task app["任务栏"].child_window(title"酷狗音乐", auto_id"D:\soft\kugou\KGMus…

immutable variables, constants的区别(rust)

let immutable_variable 1590865; //不可变变量 const constant_variable 0096; //常量常量、不可变变量一样&#xff0c;都无法更改变量的值&#xff0c;但是常量和不可变变量之间存在以下区别&#xff1a; 不可变变量默认不可变&#xff0c;编译器会进行检查。常量不仅在默…

面向对象——类与对象

文章目录 类与对象构造函数、析构函数get/set方法函数&#xff1a;类内声明、类外定义static 类与对象 #include<iostream> #include<string> using namespace std; /* 类与对象 */ class Person{public:string name;// 固有属性&#xff0c;成员变量 int age;pu…

第一章:系统架构概述之系统架构的定义以及发展

什么是系统架构 系统架构 (System Architecture )是系统的一种整体的高层次的结构表示&#xff0c; 是系统的骨架和根基&#xff0c;也决定 了系统的健壮性和生命周期的长短。 什么系统架构设计师 系统架构设计师在整个项目研制中的主导地位愈加重要。可以说&#xff0c;系统架…

MongoDB快速启动

两种方法: 方式 1 &#xff1a;命令行参数方式启动服务 在 bin 目录中打开命令行提示符&#xff0c;输入如下命令&#xff1a; (mongod --dbpath..\data\db) mongod --dbpath..\data\db 方式 2 &#xff1a;配置文件方式启动服务 在解压目录中新建 config 文件夹&#xff0…

C语言入门第四天(数组)

一、C语言数组的基本语法 1.数组的定义 数组是 C 语言中的一种数据结构&#xff0c;用于存储一组具有相同数据类型的数据。数组中的每个元素可以通过一个索引&#xff08;下标&#xff09;来访问&#xff0c;索引从 0 开始&#xff0c;最大值为数组长度减 1。 2.定义语法格式 …

llama-factory SFT 系列教程 (四),lora sft 微调后,使用vllm加速推理

文章目录 文章列表&#xff1a;背景简介llama-factory vllm API 部署融合 lora 模型权重 vllm API 部署HuggingFace API 部署推理API 部署总结 vllm 不使用 API 部署&#xff0c;直接推理数据集 tenplatevllm 代码部署 文章列表&#xff1a; llama-factory SFT系列教程 (一)&a…