UVM设计模式 (十) 观察者模式、uvm_subscriber、TLM、总结

观察者模式

Observer Pattern:对象之间定义一个一对多的依赖关系,当一个对象改变的时候,所有依赖对象都会自动收到通知。

观察目标(Subject)和观察者(Observer)是一对多的关系。有时候观察者模式也叫做发布-订阅模式Publisher-Subscriber)。观察者模式将观察者和被观察者代码解耦。

示例:股民Investor作为观察者,股票Stock作为观察目标。当股价大于20或者小于10时,观察者将会收到通知,执行各自的函数。

可以看到,在Stock中调用notifyObserver,实际是调用Investor中重写的update函数。update函数对于不同观察者,可以有不同的独立的实现。将代码中变化的部分(增加、减少观察者,对观察结果的处理函数)不变的部分(发送通知给观察者)进行了很好的分离,实现代码最小化改动,达到解耦的目的。(代码改写自:🔗设计模式[15]-观察者模式-Observer Pattern

uvm_subscriber

UVM中内建了uvm_subscriber类,可以被当作观察者或者订阅者使用。

一般用在构建功能覆盖率的收集。伪代码如下:

订阅者订阅monitor中收集到的transaction,覆盖率模块,参考模型,scoreboard都是订阅者。每当monitor收集到新的transaction,自动调用write函数,将transaction广播出去(uvm_analysis_port是一个广播的port,可以对应多个接收者)至于write函数如何实现,monitor并不关心,每个订阅者的write实现不同。在覆盖率类中write具体实现就是调用sample函数,收集覆盖率。UVM通过connect函数将TLM端口连接,在订阅者和发布者之间建立了联系。具体分析见下一节。

 TLM

UVM对观察者模式进行了扩充,加入了各种端口类,作为一个中介,专门负责订阅者和发布者建立联系。

如下示例,env中有三个component(A_inst, B_inst, C_inst), 其中A作为发布者,B,C作为订阅者。(源代码:🔗《uvm实战》源码 4.3.1

1. 示例

在UVM树形结构中,我们会看到端口被当作component放入了A_inst的m_children成员变量中(m_children含义参考:🔗UVM设计模式 ( 二 ) ),如下:

2. 将端口加入树形结构

先分析下为什么port会被加入到uvm树结构中。

如下,A_ap 是一个 uvm_analysis_port#(my_transaction)类型的端口。调用new函数传入name = "A_ap", parent = this (A_inst)

uvm_analysis_port#(my_transaction)继承于uvm_port_base。uvm_prot_base的new函数会创建一个m_comp (uvm_port_component类型)的实例,这个实例是一个参数化的类,传入了一个端口类型,这个端口类型就是A_ap的类型。

 如下,m_comp被创建时,同时也会为 m_port 赋值,这个句柄指向A_ap的实例。

 

 uvm_port_component继承于uvm_port_component_base, uvm_port_component_base继承于uvm_component。在uvm_port_component_base中,super.new传入的name = "A_ap", parent = A_inst

 

 所以,并不是A_ap这个端口实例被加入到了UVM树形结构,因为A_ap不属于component,无法加入树形结构。只是A_ap的成员变量m_comp加入到了树形结构,而这个m_comp加入树形结构用的是A_ap的name和A_ap的parent,代表A_ap加入了树形结构。 同时m_comp里也有成员变量m_port,指向A_ap的实例。在sequence中无法使用TLM端口,一般借助sequencer的端口或者使用mailbox代替。

3. connect函数

connect()函数的实现:

A_ap.connect(B_inst.B_imp)A_ap.connect(C_inst.C_imp)后,会在A_ap中的m_provided_by (联合数组,索引是 provider名字,值是 provider的实例,此处是imp型的端口) 加入记录,m_provided_by["B_imp"] = B_imp  m_provided_by["C_imp"] = C_imp

4. write函数

1. A_ap是uvm_analysis_port型的端口,A_ap.write调用的write函数在uvm_analysis_port类中定义

2. analysis_port是广播型的端口,通过for循环遍历 m_imp_list存放 imp型的端口), 执行 tif.write 函数(调用每个 imp端口的 write函数

3. B_imp是uvm_analysi_imp#(my_transaction,B)型的端口,构造函数new会传入B的句柄,所以其内部成员变量 m_imp 指向 class B 的实例。

4. tif.write其实就是调用 m_imp.write, 也就是 class B/ class C 中定义的write函数。

5. m_imp_list

1. 在class uvm_root中,当执行完connect_phase后,会调用do_resolve_bingding函数。这个主体作用是从下往上遍历UVM树形结构,执行resolve_bindings函数

2. resolve_bindings函数是uvm_component函数中的空虚函数,agent,driver类型的component没有实际操作,但在uvm_port_component中重写了。uvm_port_component调用m_port的resolve_bindings函数。

3. A_ap在resolve_bindings函数中遍历联合数组m_provided_by,调用m_add_list将和A_ap connect相连的imp端口放入m_imp_list中。

至于上面提到的,将端口加入树形结构的作用就在这里体现了:端口加入树形结构,才会无遗漏的被遍历循环到。至于为什么不在调用connect函数时直接加入m_imp_list中,这是为了解决connect的传递行为( port_b.connect(imp); port_a.connect(port b); )

在观察者模式的示例中,addObserver 函数相当于UVM中的 connect 函数,对 m_observer_hash 的遍历相当于UVM中 m_imp_list 的遍历。UVM加入了更丰富的端口类,来实现这些功能。UVM还有很多其他端口和端口的方法,这里不在展开。综上,UVM中TLM机制是观察者模式和内建端口类的结合。

总结

UVM作为一种方法学,提供了一种实际工程的验证平台架构。在将近7万行的源代码中,囊括了sequence机制、factory机制、phase机制、寄存器模式等内容。UVM采用systemverilog这种面向对象编程的语言,借鉴了大量的软件设计模式,提高了平台的复用和扩展。

通过这些学习可以发现,设计模式的目的就是解耦。创建型模式是将创建和使用代码解耦,结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦。借助设计模式,我们利用更好的代码结构,将一大坨代码拆分成职责更单一的小类,让其满足开闭原则、高内聚松耦合等特性,以此来控制和应对代码的复杂性,提高代码的可扩展性。

至此一共分析了11种设计模式,剩余的12种设计模式,有些在UVM中也有使用(比如Composite模式等),后续有空补充;有些虽然在UVM中没有使用,但是也可以借鉴到日常使用中(比如 chain of responsibility模式,memento模式等)。

部分设计模式文章: 链接:https://pan.baidu.com/s/1anS9gZECSq2Jh3XsuMohZQ 
提取码:csdn

更多设计模式的应用可以参考历年DVCon中的文章。 🔗dvcon-europe-china-india-us

感谢张强大佬,其所著的《UVM1.1 应用指南及源代码分析》,让我站在巨人的肩膀上,对UVM源码增加了很多了解。本人接触验证2年多,也一直使用UVM验证,这几篇文章也是边学习,边总结,当作笔记方便回顾阅读。如果仅仅使用UVM,不必深究各种机制的源码实现,但是通过这几篇的学习,还是解开了以往使用中的一些疑惑。篇中描述还有些错误和不准确,望留言指出。

CSDN并不支持SV语法高亮,源代码地址🔗github

🔗为超链接;一些截图受页面限制,需要🔍+放大查看;除 uvm_visitor为 uvm1.2的源码,其余截图源码都是uvm1.1源码;UVM源码截图中标注的①②....序号和详解1,2,....序号相对应; 建议使用 verdi的 uvm debug mode, trace uvm代码更方便‘;

  • 16
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

劲仔小鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值