在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 3628|回复: 2

[资料] UVM 学习笔记

[复制链接]
发表于 2020-6-11 20:29:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
UVM验证方法学
基于SystemVerilog验证语言的UVM功能验证
1、SV 面向对象编程OOP
2、UVM 验证平台TB
3、事务级建模Transaction modeling
4、产生激励序列Stimulus sequences
5、工厂模式和配置机制Factory and configuration mechanism
6、UVM组建之间的通信机制TLM
7、覆盖率和记分板Coverage and Scoreboard
8、UVM callback
9、Virtual sequencer 和 sequence
10、UVM component phases 机制
11、寄存器抽象层RAL

一,SV OOP复习
OOP封装 继承 多态 编码规则 特殊类:参数类 自定义类 单例类 代理类proxy class
工厂模式factory

封装性
SV中的class:
变量用于数据建模、子程序用于操作数据、变量和子程序称为类的成员。
要跑时间用task,不用时间就用function

继承
通过基类派生新类
新类会继承基类的所有数据和数据处理
重用:子类兼容父类
$cast(etr,tr);强制类型转换

多态
调用哪个子程序,取决于tr的类型,不管子程序是否为virtual
如果子程序不是virtual methods 就看句柄类型,不用看对象类型
如果是virtual methods 看对象类型(虚方法)
利用虚方法可以开发通用型的类子程序

OOP编程规则:在class之外定义子程序
将所有子程序声明在class内:extern
将数据和数据处理放在一屏代码中,可以减少bug
在class文件之外实现函数体
作用域符号::

参数化的class
为通用功能编写参数化的类
通用代码重用
类似与参数的module,在实例化时传递参数
class stack #(type T=int);

自定义的class
应用场景1:
在声明之前使用类
两个类彼此使用对方的句柄
typedef class C2;
class C1;
C2 inside_C1;
...
endclass C1

class C2;
C1 i_an_inside;
...
endeclass

应用场景2:简化参数类的编码
typedef stack #(bit[31:0]) stack32;

Static property 静态变量/数据
在class的定义中声明静态变量static
可以存储本地信息,例如生成的对象的数量index
类的所有对象都共享该静态变量,在编写test的时候,可以用变量id来区分transaction的索引值。

Static method静态子函数/方法
不用句柄就可以调用子函数/方法 transaction::print_count();
只能处理静态变量

Singleton class 单例类
用于定于全局行为,比如打印、工厂
单例类不存在对象
只包含静态变量和子函数

class print;
static int err_count=0, max_errors=10;
static function void error(sring msg);
$display("@%t:ERROR%s",$realtime,msg);
if(err_count++>max_errors) $finish;
endclass:error
endclass:print

Singleton object单例对象
单例对象时一个全局可见/可操作性的对象,提供定制化服务/函数
有且仅有唯一的对象,在编译时创建
在仿真时全局可见/可操作性
可以有静态或者非静态类成员。
class factory;
static singleton me =get();
static function singleton get();
  if(me==null)me==new();return me;
endfunction:get
local function new();endfunction:new
extern function void print();
endclas:fatory

Proxy class 代理类
提供create()等通用型的子函数
class proxy_class #(type T=base);
typedef proxy_class #(T)this_type;
static this_type me=get();

static function this_type get();
   if(me==null)me=new();return me;
  endfunction
static function T creat();
create=new();
endfunction
endclass

class environment;
transaction tr;driver drv;
function new();
tr=transaction::proxy::create();//creat函数替代了new函数
drv=drive::proxy::createa();
endfunction
endclass:environment

Factory mechanism 工厂机制
创建工厂,需要两层代理类
1、虚代理类(virual proxy base class)
2、派生代理类,是实现全部功能,类似工厂中的模具。
虚代理基类()
1、代理基类要具有的多态属性
2、为代理服务提供抽象的接口应用程序:创建对象:new 获取类型名称:get_name
模板
virtual class proxy_base;
  virtual function base create_object(string type_name);
   return null;
  endfunction
  pure virtual function string get_typename();
endclass

factory class
按需创建对象
维护代理对象登记表(registry)
class factory;
static proxy base registry[string];
static factory me=get();
static function factory get();
if(me==null)me=new();return me;
endfunction

function void register(proxy_base proxy);
  registry[proxy.typename()]=proxy;
endfunction

function base creat_object_by_type(proxy_base proxy,string name);
  proxy=find_override(proxy);//
  return proxy.creat_object(name);//
endfunction

维护被覆盖的代理登记表:如果代理类被覆盖,创建覆盖后的类的对象
static string override[string];
static function void override_type(string type_name,override_typename);
override[type_name]=override_typename;
endfunction

function proxy_base find_override(proxy_base proxy);
  if(override.exists(proxy.get_typename()))
return registry.[override[proxy.get_typename()]];
return proxy;
endfunction
endclass

Proxy class代理类
完成抽象的接口函数
在工厂中登记
利用工厂创建对象

class proxyf_class#(type T=base,string Tname="none")extend proxy base;
typedef proxy_class#(T,Tname)this_type;
static string type me_name=Tname;
static this_type me=get();
static function this_type get();
  factory f=factory=get();if(me=null)begin me=new();f.register(me);end
return me;
endfunction
static function T creat(string name);
factory f=factory::get() $cast(creat,f.creat_object by_type(me,name));
endfunction
virtual function base create_object(string name);
T obeject_represented=new(name);
return object_represented,
endfunction
endclass:proxy_class

这么复杂的机制到底如何理解?
我们应该从上层往下去看它的调用关系!!!!
case可以使用工厂机制替换验证平台中创建的任何对象,但却不需要修改验证平台的代码,提高了代码的可重用性
program automatic test;
environment env;
initial begin
  factory:verride type("deiver",new driver");
  env=new();
  ...
  end
enprogram

class environment;
driver drv;monitor mon;
function new();
  drv=driver::proxy::creat();
  mon=monnitor::proxy::creat();
endfunction
endclass:environment

说这么多,无非就是要记住工厂模式的两张表,注册表registry和覆盖表override。至于这些代码,大
如果有大佬想看完整的源码可以去UVM的库里面看,我境界低,我看不懂,太复杂了。
对于像我一样的萌新,首先就是要有一个工厂机制的思路,理解它是怎么通过不修改源代码去经行修改行为的操作的。
 楼主| 发表于 2020-6-20 16:52:45 | 显示全部楼层
带config_db的 aqb_i2c agent



'ifndef APB_MASTER_AGENT_SV
'define APB_MASTER_AGENT_SV
class apb_master_agent extends uvm_agent;

  apb_config cfg;

  apb_monitor monitor;
  apb_collertor collertor;
  apb_master_sequencer sequencer;
  apb_master_driver  driver;

  'uvm_component_utils_begin(apb_master_agent)
   'uvm_field_object(monitor, UVM_DEFAUT|UVM_REFERENCE)
   'uvm_field_object(collector, UVM_DEFAUT|UVM_REFERENCE)
   'uvm_field_enum(uvm_active_passive_enum, is_active, UVM_DEFAULT)
   'uvm_field_object(cfg, UVM_DEFAUT|UVM_REFERENCE)
  'uvm_component_utils_end

//new-constructor
  function new (string name, uvm_component parent);
    super.new(name,parent);
  endfunction:new

//Additional class methods
  extern virtual function void build_phase(uvm_phase phase);
  extern virtual function void connect_phase(uvm_phase phase);
  extern virtual function void updata_config(input apb_config cfg);

endclass:apb_master_agent

//UVM build_phase
function void apb_master_agent::build_phase(uvm_phase phase);
  uvm_object config_obj:
  super.build_phase(phase);
  if(cfg==null)begin
    if(!uvm_config_db#(apb_config)::get(this,"","cfg",cfg))
      'uvm_warining("NOCONFIG",
                    "Config not set for master agent,using default is_active field")
    end
  else is_active==cfg.master_config.is_active;

  if(is_active==UVM_ACTIVE)begin
    sequencer=apb_master_sequencer::type_id::creat("sequencer",this);
    driver=apb_master_driver::type_id::create("driver",this);
  end
endfunction:build_phase

//UVM connect_phase
function void apb_master_agent::connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  if(is_active==UVM_ACTIVE)begin
  //Connect the driver to the sequencer using TLM interface
  driver.seq_item_port.connect(sequencer.seq_item_export);
end
endfunction:connect_phase

//updata_config()
function void apb_master::updata_config(input apb_config cfg);
  if(is_active==UVM_ACTIVE)begin
    sequencer.cfg=cfg;
    driver.cfg=cfg;
  end
endfunction:updata_config

'endif//APB_MASTER_AGENT_SV

发表于 2021-4-24 21:05:27 | 显示全部楼层
very good data sharing
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

×

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-14 12:13 , Processed in 0.017963 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表