• 设计模式在芯片验证中的应用——装饰器


    一、装饰器模式

    装饰器模式(Decorator)是一种结构化软件设计模式,它提供了一种通过向类对象添加行为来修改类对象的方法,而不会影响同一类的其它对象行为。该模式允许在不修改抽象类的情况下添加类功能。它从本质上允许基类代码对不可预见的修改具有前瞻性。

    对于经常需要在最后时刻新增特性的验证工作,装饰器模式的这个特性非常强大。该模式适用于通过向复杂数据项应用额外的约束集来对它们进行建模,或者在原先数据上添加额外数据。与类继承相比,它的主要优点是可以实现向类对象中动态添加或删减行为。在工程中,该技术被广泛用于实现受约束随机激励的生成。

    举个例子,如下图,我们在验证环境中打算开发一个Arm指令生成器,原先RTL只支持基本的load和store指令,过段时间可能又支持atomic指令,再过段时间可能又支持SVE指令了,这样就容易造成我们需要对以往的代码不停地修改。更令人崩溃的是,RTL又搞了其它版本,有的版本只支持load/store指令和SVE指令,有的版本只支持atomic和SVE指令,等等。对于这些行为,第一个跳入脑海的想法可能就是扩展它所属的类,在新的类中添加新功能,但这种方式会使代码量迅速膨胀,而且可能会破坏之前写好的代码。

    针对以上情况,我们可以考虑使用装饰器模式。要构建装饰器设计模式,需要定义几个主要部分:

    • 被包装对象:它声明了被包装对象的共用接口和基本行为,装饰器会在此基础上添加新的行为。
    • 抽象装饰器:定义了基本的装饰器,它拥有一个指向被被包装对象的引用成员变量,因此会将操作委派给被包装的对象。
    • 具体装饰器:定义了可动态增减到被包装对象的额外行为。具体装饰器会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为。

    下图使用UML类图提供了上述三者之间的图形化关系:

    装饰器设计模式背后的主要思想是,各种具体装饰器可以在仿真过程中处于活动状态,灵活地为被包装对象增加新功能。而且可以指令任意组合的具体装饰器同时处于活动状态,这样就可以在任意给定时刻,向被包装的对象添加任何期望的激励组合。

    二、参考代码

    指令生成器的装饰器模式参考代码如下:

    1. class common_base;
    2. int pe;
    3. int scen_weight[string];
    4. int weight_mul = 1;
    5. virtual function void set_scen_weight(common_base _h);
    6. endfunction : set_scen_weight
    7. virtual function void print_msg();
    8. foreach ( scen_weight[t_scen] ) begin
    9. $display("scen[%s]=%0d is added", t_scen, scen_weight[t_scen]);
    10. end
    11. endfunction : print_msg
    12. endclass : common_base
    13. class base_decorator extends common_base;
    14. common_base base;
    15. virtual function void set_scen_weight(common_base _h);
    16. add();
    17. base = _h;
    18. foreach ( scen_weight[t_scen] ) begin
    19. if ( base.scen_weight.exists(t_scen) ) begin
    20. `uvm_error("decorator", $psprintf("The scen(%s) has exists", t_scen))
    21. end else begin
    22. base.scen_weight[t_scen] = scen_weight[t_scen] * weight_mul;
    23. end
    24. end
    25. print_msg();
    26. endfunction : set_scen_weight
    27. virtual function void add();
    28. endfunction : add
    29. endclass : base_decorator
    30. class base_ldst_scen_wei extends base_decorator;
    31. virtual function void add();
    32. scen_weight["load"] = 10;
    33. scen_weight["store"] = 10;
    34. endfunction : add
    35. endclass : base_ldst_scen_wei
    36. class atomic_scen_wei extends base_decorator;
    37. virtual function void add();
    38. scen_weight["atomic_add"] = 5;
    39. scen_weight["atomic_sub"] = 5;
    40. endfunction : add
    41. endclass : atomic_scen_wei
    42. class sve_scen_wei extends base_decorator;
    43. virtual function void add();
    44. scen_weight["gather"] = 8;
    45. scen_weight["scatter"] = 8;
    46. endfunction : add
    47. endclass : sve_scen_wei

    模拟测试代码如下:

    1. class scen_weight_gen;
    2. rand bit base_ldst_scen;
    3. rand bit atomic_scen;
    4. rand bit sve_scen;
    5. function void gen();
    6. common_base base = new();
    7. common_base common;
    8. `uvm_info("", $psprintf("base_ldst_scen:%b, atomic_scen:%b, sve_scen:%b", base_ldst_scen, atomic_scen, sve_scen), UVM_LOW)
    9. if ( base_ldst_scen ) begin
    10. common = base_ldst_scen_wei::new();
    11. common.set_scen_weight(base);
    12. end
    13. if ( atomic_scen ) begin
    14. common = atomic_scen_wei::new();
    15. common.weight_mul = 3;
    16. common.set_scen_weight(base);
    17. end
    18. if ( sve_scen ) begin
    19. common = sve_scen_wei::new();
    20. common.set_scen_weight(base);
    21. end
    22. endfunction : gen
    23. endclass : scen_weight_gen

    输出仿真日志如下:

    1. base_ldst_scen:1, atomic_scen:1, sve_scen:0
    2. | # scen[load]=10 is added
    3. | # scen[store]=10 is added
    4. | # scen[atomic_add]=5 is added
    5. | # scen[atomic_sub]=5 is added

    从仿真结果可以看出,scen_weight_gen类随机后,base_ldst_scen为1,atomic_scen为1,sve_scen为0,因此只有load/store指令和atomic指令功能被添加到指令生成器中。

    好了,今天就写到这里了。下次给大家分享下设计模式中策略模式(Strategy)在芯片验证中的应用。它和装饰器模式很类似,区别是装饰器模式可让你更改对象的外表,但策略模式则让你能够更改其本质。

  • 相关阅读:
    LabVIEW中编程更改进程的优先级
    asp.net家校互动系统VS开发sqlserver数据库web结构c#编程计算机网页项目
    DODAB纳米脂质体囊泡/PANC-1细胞膜的PEG修饰的脂质体M-PEG-LIP的相关研究与制备
    软件工程毕业设计课题(10)基于python的毕业设计python助农商城系统毕设作品源码
    Elasticsearch安装过程出现的问题
    正则表达式replaceAll()方法具有什么功能呢?
    拓端tecdat|R语言实现向量自回归VAR模型
    UniCode 常用字符大全
    vue3(三)动态路由刷新路由失效问题
    Leadshop开源商城小程序源码 – 支持公众号H5
  • 原文地址:https://blog.csdn.net/W1Z1Q/article/details/136766915