UVM - 寄存器模型如何使用?覆盖率怎么收集?


1. 寄存器模型怎么用

1.1 概览

1.1.1 rgm 有什么用?

  • 硬件、软件之间 交谈的窗口
  • 读取寄存器,获取硬件的状态
  • 配置寄存器,使硬件处于某个工作模式下

寄存器验证,一般放在验证工作的前面部分:先保证 寄存器配置,与 预期的硬件状态 是一致的

1.1.2 怎么学 rgm 部分

  • mcdf 总线 ( lab 4 ) + rgm ,两者之间怎么搭建、配合使用?
  • 设计的过程 是怎样的?
  • 验证过程中
    • 怎么使用 uvm rgm 提供的 一些 class
    • rgm 常用的一些方法
      • 用 rgm 发送激励
      • 怎么用 rgm 测试硬件
      • 完成寄存器读、写的覆盖;寄存器覆盖率 是什么概念

1.1.3 基本术语、概念

  • 寄存器一般是 32-bit (也有更短 bit 或更长 bit 的)
  • 多个寄存器 按地址排列,形成一个 寄存器块 register block
  • 每个寄存器 可以包括不同的 域 field
  • 每个 field :有固定的 位数
  • 每个 field :有不同的 读、写 属性
    • WO
    • RO
    • RW
    • RC (clear-on-read) ,读后擦除
    • W1S (write-one-to-set), 只写 1 次
  • map (address map) 里面放:所有寄存器的 地址信息
  • hw 中所有的 寄存器,在 rgm 中都需要有
  • rgm 是软件环境中的
  • 层次化的寄存器,对应着 层次化的寄存器列表

1.1.4 寄存器 与 总线

  • 除 寄存器,另一个离不开的概念是 总线
    • 总线用于 访问 (读、写) 寄存器
  • 为什么用 总线
    • 为了 复用 测试序列

1.1.5 什么是 中心化管理寄存器(国内暂时没有??)

  • 手写 寄存器模型 不现实(上万个寄存器)
  • rgm 是 高度格式化的,一般包括的内容是:多少位、功能、address 等
    • 可以放到 xml, xls
    • 既然是 高度格式化的,可以 通过脚本去实现自动化寄存器模型
  • 什么是 “中心化”?
    • 单一源管理
    • 核心思想是什么:用结构化的文档、数据,去自动生成 寄存器模型
  • 实现“中心化”,一般是怎么个流程?
    • 先有 寄存器描述文件,如 xml, xls
    • 然后有 自动化的工具、脚本,自动生成 寄存器模型(尽量避免手动去生成)
    • 寄存器描述文件,也可以用来生成文档

1.1.6 uvm_reg 相关的概念(学习过程中,手写此模型;暂时不 自动生成)

  • 关于 rgm 构建,需要用到的 几个类(extends uvm_object)
    • uvm_reg_field
    • uvm_reg
      • 内部包含多个 uvm_reg_field
    • uvm_reg_block
      • 内含多个 uvm_reg (也可以包含 uvm_mem)
      • uvm_reg_map: 各个 register address,读写属性
        a) 读写属性 匹配,才允许访问此 reg_map
  • 看代码,理解怎么用上面几个类创建寄存器?各自 在哪里例化?等
    • uvm_reg 中
      • 有 rand uvm_reg_field pkt_len; 前面有 rand 修饰,为什么?
      • 有 virtual function build( ), 做什么?
        • 对各个 field 创建 (type_id::create),配置 (configure) 域的属性
          • 配置什么:多少位?从哪一个起始位开始?读写属性?reset 值是什么?等
    • uvm_reg 的属性在哪里配置?
      • 在 address map 中配置

1.1.7 创建一个 rgm 的 代码实例

  • mcdf 的硬件情况
    • 两个寄存器:控制寄存器,状态寄存器
    • 一共三个 channel,每个 channel 分别有自己的 一个 控制寄存器、状态寄存器
  • 创建过程如下:
    • 先创建每个 内部的 具体的 寄存器(新加)
      • class ctrl_reg extends uvm_reg
        • 内部包括各个 uvm_reg_field,并且用 rand 修饰
        • 有 virtual function build
          i) 先 create
          ii) 再 configure
      • class state_reg extends uvm_reg
        • 内部包括状态寄存器的 各个域
    • 然后,使用上面这些寄存器,创建 reg_block (新加)
      • class mcdf_rgm extends uvm_reg_block
        • 每个 channel 分别有自己的 一个 控制寄存器、状态寄存器
        • 内部 reg 也是 rand 修饰
        • 内部有 map
        • 内部也有 build 函数, build 中内容如下
          i) 先 reg 例化
          ii) 再 reg configure : reg 与 当前的 reg_block 关联起来(此 reg 属于 此 reg_block)
          iii) 再 reg build: reg 内部的 field build (必须手动写这些代码)
          One. 因为, uvm_object 没有自动的层级调用;必须手动
          iv) map 信息
          One. 创建 map:map 名,map 的基地址 等
          Two. 通过 add_reg:添加每个 reg 相对于 map 的基地址的偏移地址、访问属性 等
          v) 最后,lock_model( );
  • 注意点
    • 创建 uvm_block 时,在其 build 函数中:需要把内部 uvm_reg_field 或 uvm_reg 的 rand 修饰提前写好
    • build 函数调用,在 block 中需要手动写上 内部 uvm_reg 的 build

1.1.8 有了 以上 rgm 后,怎么使用?

  • 要有 总线的适配器 adapter:因为有 总线,需要适配
    • 要完成 抽象级的转化:寄存器 level 到 总线level
  • 做集成
  • 集成后,之前的总线激励依然可以使用;但是,为了做得更好,可以使用 rgm 写一些寄存器级别的激励
    • 可以更方便地发激励、测试硬件
  • 写了寄存器级别的激励后,有两个方面
    • 寄存器模块有无做过检查
    • 对硬件做了完备检测后,是否有寄存器的覆盖率

为了完成以上第 8 点,需要熟悉 rgm 的一些常规使用方法、典型应用场景(后续内容)

1.2 集成

拿到 sw 寄存器模型、并且有 hw 总线(即 bus-agent/hw-register)后,怎么做集成?

1.2.1 以 rgm 集成进 mcdf 总线 为例

  • mcdf :有哪些 class

    • mcdf_bus_transaction (包括可随机化的数据成员)
    • mcdf_bus_sequencer (seq_item_export)
    • mcdf_bus_monitor
      • 有 analysis_port (可以 一对多,可以也连接 predictor 等)
        • monitor 从 virtual interface 上监测数据
        • port 在 build_phase 创建(create)
        • port 在 run_phase 阶段,监测
          • 监测时,用 fork join_none
    • mcdf_bus_driver , 完成驱动和复位
      • 解析三种命令模式: IDLE, WRITE, READ
        1) 在 READ 模式下,将读回的数据通过 item_done(rsp) 写回到 sequencer 和 sequence 一侧。
        2) 返回前,clone rsp
      • 在 run_phase , 监听复位 调用 task reset_listener
        • forever 语句
          a) seq_item_port.get_next_item
          b) 必要的操作
          c) 然后,驱动 driver_bus(rsp)
          d) 最后,item_done (会完成与 seq 的 finish item 完成握手)
      • 其他的 驱动相关 task
        1) drive_read,drive_write
        2) drivre_idle, drive_bus
        3) task reset_listener
    • mcdf_bus_agent
      connect phase 连接 driver 的 seq_item_port 与 sequencer 的 seq_item_export
  • mcdf 寄存器 RTL 设计代码 (HW reg 模块)

    • class ctrl_regs ,设计代码有 3 部分
      i. 信号声明
      ii. alwaya 语句块
      复位、WRITE、READ、DEFAULT 的行为/值;
      非阻塞赋值
      iii. assign 端口信号驱动
  • 软件 rgm 已经 ready

  • mcdf ( 的寄存器 RTL,hw ) 与 rgm (sw) 之间,需要有:adapter

    • rgm 怎么访问、操作:通过 map 获得地址,有 uvm_reg 等一系列方法
    • rgm 得到的数据类型是什么样的: uvm_reg_item
    • rgm 得到的数据类型,怎么映射到 dut bus 一侧;反向怎么操作: adapter
      • 必须实现的两个虚函数: reg2bus, bus2reg
      • adapter 中 rsp 数据存在根据 bus 确定
        有些总线有 rsp,有些总线没有 rsp
        如果有 rsp,需要把 provides_responses 配置为 1
  • rgm 中的 adapter (extends object)
    class reg2mcdf extends uvm_reg_adapter

    • uvm_sequence_item 代表 bus 一侧; uvm_reg_op 代表 rgm 一侧
    • 读、写 都需要经历以下两个方法
      • virtual function reg2bus
        a) 预定义的,必须实现
        b) 映射到 bus 一侧
        c) 把 reg 一侧的 数据,转换成 bus_transaction 类型(转化为 bus 操作)
        d) function 返回 uvm_sequence_item (不是 bus_transaction):父类、子类句柄自动转换
      • virtual function bus2reg
        a) 预定义的,必须实现
        b) 转换成 uvm_reg 可以识别的 uvm_reg_op
  • 顶层集成: adapter, uvm rgm, mcdf (dut) agent

    • 思考
      i. rgm 与 adapter 在哪里集成?彼此什么关系?
      ii. adapter 完成传输,需要什么(需要什么句柄)?
    • 步骤
      • class mcdf_bus_env extends env
        • build_phase
          a) config_db # :尝试得到 rgm
          b) 例化 rgm (type_id::create); rgm build ( ) ;
          set_auto_predict( ): 没集成 predictor 之前,用这个 auto
          c) 例化 adapter (create adapter)
        • connect phase
          a) adapter 与 rgm 中 map 是关联的;adapter 与 agent 的 sequencer 关联;最终 三者关联
          rgm.map.set_sequencer(agent.sequencer, adapter_name)
      • class test1 extends uvm_test
        例化 rgm (create), 例化 env
  • 小结

    • rgm 集成倾向于用 config_db 进行顶层传递
      1) 在 test 层例化 rgm
      2) 在 env 得到 顶层的例化,并进行 build
    • predictor 要 预测什么?
      hw 寄存器变化时,rgm 中的也需要同步更新
      • monitor 监测到 bus 上的值,然后用这些监测到的值 去更新
        i) 通过函数更新(之前的方法)
        ii) 通过 predictor 更新(predictor 可以拿到 adapter 的句柄,可以用 adapter 的 bus2reg 等,更新 rgm)
      • 如果没有 monitor 和 predictor,也可以通过 adapter 预测: 称为 auto_predict
        i) 不完善,如 读状态寄存器时,rgm 一侧怎么预测?
  • 接下来,怎么利用 rgm?怎么去访问 rgm?

    • 前门、后门访问什么区别?
      i. 前门:通过总线,真实的物理操作
      ii. 后门:通过 DPI,不通过物理总线,不是真实的(真实硬件不支持)
      通过 仿真器提供的,可以访问信号的一种手段。
      不耗时、速度快

1.3 集成2

(续上部分:寄存器前门访问、后门访问)

1.3.1. 前门访问

1. 示例中的 uvm_reg_sequence , 继承自 uvm_sequence
	a. 可以使用 `uvm_do, `uvm_do_with 等与 seq 相关的宏;也包括:
		i. uvm_reg_sequence::read_reg( )/write_reg( )
		ii. peek_reg( )/uvm_reg( )
	b. 可以使用 与 uvm_reg 寄存器操作相关的方法
		i. uvm_reg::read( )/write( ) , 参数包括:
			1) path: FRONTDOOR
2. 示例代码
	a. class mcdf_example_seq extends uvm_reg_sequence
		i. 声明 rgm
		ii. task body( ) 中
			1) 可以直接通过 调用寄存器方法,进行读写
				a) rgm.chnl0_ctrl_reg.read(status, data, UVM_FRONTDOOR, .parent(this) )
			2) 也可以调用 uvm_reg_sequence 的方法进行读写
				a) read_reg(rgm.chnl0_ctrl_reg, status, data, UVM_FRONTDOOR)

1.3.2. 后门访问 (0 时刻,立即返回;不耗时)

1. 通过 DPI 的形式(直接 get 到某些路径下的 信号值)
	a. 首先,必须有 信号的 hdl 路径:路径映射
2. 示例代码
	a. class mcdf_rgm extends uvm_reg_block
		i. 寄存器成员 和 map 声明
		ii. virtual function build
			1) 路径关联: 
				a) add_hdl_path("hw 的绝对路径")
				b) chnl0_ctrl_reg.add_hdl_path_slice(" 相对路径", 0, 32) 
			2) PATH 改为 BACKDOOR
		iii. 最后,lock_model( )
3. 有时不需要指定 BACKDOOR
	a. 当有些方法只能 backdoor 用时:peek( ), poke( )
		i. 以上两者,是 read( )/write( ) 的 backdoor 形式

1.3.3. 前门和后门的对比

1. 前门
	a. 反应真实的硬件状态、包括时序问题
	b. 需要总线、耗时
	c. 反应 地址映射关系
	d. 每次总线结束后,获取一个 完整的信号包;不能是单独的域
		i. 前门,怎么改寄存器的域
			1) 先 read 拿到完整寄存器的值
			2) 修改 某个域,write 操作
2. 后门
	a. 不耗时,访问更快(0 时刻完成)
	b. 可以直接 读取值、修改值
	c. 可以直接 对 寄存器的域 进行修改
	d. 是自动预测的
		i. bus_monitor 监测不到任何值
	e. 不受时序的影响(对于一些,对时序有要求的,这也可能会带来一些问题)
		i. 因为,后门的 0 时刻直接读、写;不能等时序

1.3.4. 通常,前门、后门结合使用,一些典型场景

1. 场景1
	a. 首先,先用 前门访问 测试所有寄存器,确认寄存器的硬件路径已调通
	b. 然后,可以通过后门直接访问寄存器
2. 场景2, 有些寄存器如果只能 写一次
	a. 用前门物理访问,测真实情况
3. 场景3:rgm 生成 随机值,
	a. 寄存器模型中 uvm_reg, uvm_reg_field 随机值可以进行设置
		i. 随机化之后的 rgm 中的 值,称为: 期望值 desired value
			1) 期望,后续 hw 中的 registers 配置成这些值
	b. 随机化之后,用这些 desired value 去后门访问 实际 hw 中的 寄存器
4. 与 场景3 相关的问题:怎么对 hw 寄存器做更全面的 随机配置?
	a. 可以通过 寄存器模型_adapter 做配置(不够随机)
	b. 能否通过 随机值,直接去配置?
		i. 没有 constraint,不合理
		ii. 更合理的方法
			1) rgm 中的 rand 随机一遍
			2) 然后,把这些随机后的 value,作为期望值
				a) 用这些 期望值去配置 硬件中的寄存器
5. 场景 4:先写后读,测试一个寄存器
	a. 如果在 dut 中,寄存器地址是错误的;先读后写 也不会有报错
	b. 怎么测?
		i. 通过前门访问,对寄存器进行配置
		ii. 通过后门访问,去监测是否配置成功了
		iii. 比如:前门写 后门读,后门写 前门读,等
6. 场景 5:测试状态寄存器,比如 测试反应 FIFO 余量的寄存器
	a. 从总线读出来(前门访问),在时序上会晚一拍;晚一拍,不能准确反映 FIFO 余量
	b. 为什么 前门访问,会有时序 晚一拍?(后门读,也会有延时)
		i. hw 的 register design 中,always 语句块
			1) <= 赋值,意味着一拍的延时
			2) 多个 <= ,意味着 多拍延时
	c. 应该怎么测试 状态寄存器?
		i. 直接映射、监测一些内部重要信号,反映即时的信息

1.3.5. register model 通过直接调用以上的函数,可以快速产生 sequence;后续,rgm 怎么做预测的?怎么做检查?

1.4 常规方法

(续上部分:register model 已经可以通过 uvm_reg, uvm_reg_sequence 的快速产生 sequence;
后续,rgm 怎么做监测的?怎么做检查?)

1.4.1. 寄存器的 域,每个域 都有两个值:镜像值 mirror value、期望值

1. sw, rgm 一侧
	a. 镜像值, mirror value:根据监测到的硬件 value,去更新 mirror value
		i. 只有做 prediction 的时候,才能去更新 mirror value
		ii. mirror value 可能监测不到,不一定 与 硬件 actual value 一样
	b. 期望值, desired value
		i. 随机化之后的 rgm 中的 值,称为: 期望值 desired value
			1) 期望,后续 hw 中的 registers 配置成这些值
			2) 首先,更新 rgm model desired 值;然后,更新 hw 值;然后,采集 hw 的值,更新 rgm value 值
2. 硬件的 
	a. 实际值 actual value
3. 镜像值、期望值 这两者,可能与 硬件实际值 不一致
	a. rgm sw 一侧,与 hw 实际一侧,可能会存在不一致的情况
	b. 状态寄存器 无法 与 硬件的实际值,保持实时一致
	c. 其他路径修改了实际值,但是,没有监测,可能导致 镜像值、期望值没更新

1.4.2. 预测

1. 如何更新 镜像值、期望值?什么时候更新?
2. 前门访问是 显式预测,需要 bus_monitor,predictor
	a. 更准确,是硬件实际值
3. 后门,只能使用 自动预测:缺少 bus_monitor, predictor
4. 只要通过 bus 访问,希望也要有 predictor (是 component,不是 object)。
	a. predictor 在顶层例化
	b. adapter 与 reg map 的句柄,都要给到 predictor
		i. 需要用 adapter 的函数
		ii. reg map 中的地址信息

1.4.3. 代码示例:如何使用 显示预测,更新值

1. bus_agent 中的 monitor - predictor - adapter 和 reg_map
2. class mcdf_bus_env extends uvm_env
	a. 声明 agent, rgm, adapter (reg2mcdf), predictor
	b. build_phase 
		i. create: agent
		ii. create: rgm.   rgm.build( )
		iii. create: predictor 
			1) (component,需要 parent)
			2) 需要指定 predictor 传输什么数据类型(与bus_agent 中的 monitor 中 analysis  port 数据类型一致)
		iv. adapter 与 reg map 的句柄,都要给到 predictor
			1) predictor.map = rgm.map;
			2) predictor.adapter = reg2mcdf_adapter;
	c. connect_phase 
		i. adapter 与 rgm 中 map 关联;adapter 与 agent 的 sequencer 关联;最终 三者关联
			1) rgm.map.set_sequencer(agent.sequencer, reg2mcdf_adapter)
		ii. monitor 与 predictor 的 TLM 连接
			1) agent.monitor.ap connenct(predictor.bus_in)

1.4.4. adapter 必须要有,predictor 建议要有

1. adapter 需要实现虚函数
2. predictor 只需要指定其类型
	a. 声明、创建时 指定类型

1.4.5. uvm_reg 类,有一些访问方法;这些方法可以用在 前门、后门;uvm_reg_block, uvm_reg_field 也有类似的方法

1. uvm_reg_block
	a. 无 read, write, peek, poke 方法
	b. mirror 方法(前门、后门)
2. uvm_reg
	a. read, write 方法可以用于 前门、后门
		i. 以上方法,获得的是 hw bus actual_value 
			1) (只能得到完整的,如 32-bit;不能操作具体的位)
		ii. 然后,更新 mirror value
	b. peek, poke 只用于 后门
		i. 也是获得值,然后,更新 mirror value
	c. mirror 方法(前门、后门)
3. uvm_field
	a. read, write 只可用于 后门(与 uvm_reg 不同)
	b. peek, poke 也依然只可以用于 后门
	

4. mirror 方法
	a.  (在 uvm_reg_block, uvm_reg 支持 mirror 方法)
	b. 读 actual value 回来值,更新 mirror value (使命:保持 mirror value 与 actual value 一致)
		i. 对 block 调用 mirror, 会对其内的 所有 regs 都更新:在总线上读取所有 regs 的状态
	c. (然后,比较 mirror value 与 hw actual value)
	d. 使用场景举例(不一定都需要这样):
		i. 在 mirror 使用之前,也可以先将读回来的值,与 原 mirror 值进行比较
5. update 方法:更新 hw 的 actual value
	a. (在 uvm_reg_block, uvm_reg 支持 mirror 方法)
	b. 使用的场景
		i. 先修改 rgm 的 desired value,然后,update hw actual value
		ii.  mirror value 与 actual value 不一致, update  hw actual value
6. reset 方法: 软件方法
	a. 复位 sw rgm 一侧的值
	b. 在 uvm_reg_block, uvm_reg, uvm_reg_field 支持 mirror 方法
	c. reset 使用场景: 
		i. hw 复位时,将 sw 也进行复位
		ii. 复位后,读取 rgm 复位值,与 前门访问获得的寄存器值进行比较
7. get_reset 方法
	a. 获得reset value
	b. 在 uvm_reg, uvm_reg_field 支持 mirror 方法
	
8. get/set 方法: 与 hw actual value 无关
	a. get/set 期望值 desired value 
	
9. set 与 update 使用的典型场景
	a. 使用场景
		i. 先将整个 reg_block 中的 reg 进行随机化
		ii. 然后,对具体的某个 reg 进行 set 值
		iii. 然后,做一次 update: 把 hw 一侧的 reg ,update 成上一步中的 set 值
			1) 使 rgm 中的值,与 hw 的 值一致

1.4.6. uvm_reg 提供了一些列方法,uvm_reg_sequence 也可以提供一系列方法 ( 只能用于 uvm_reg)

1. uvm_reg_sequence 方法,都是针对于 uvm_reg 的 (不能用于 uvm_reg_block, uvm_reg_field)
	a. 后门 (所有方法都适用)
	b. read_reg, write_reg
	c. peek_reg, poke_reg

mirror_reg, update_reg

1.5 常规方法2

(前面,介绍 uvm_reg_block, uvm_reg, uvm_reg_field; 后面,介绍 uvm_mem; 重点介绍差别)

1. mem 与 reg 的联系和差别
	a. 一般用 uvm_reg, uvm_reg_block
	b. uvm_mem 针对内部存储建模
		i. 考虑到物理存储,消耗资源比较多;所以,mem 不再支持 预测、影子存储等
		ii. 可以利用自带的方法去访问存储
		iii. 支持前门、后门;通常用法
			1) 先通过后门,加载存储内容
			2) 再通过前门访问,读取存储内容
		iv. 方法
			1) read( ), write( ), peek( ), poke( )
			2) burst_read( ), burst_write( )
				a) 参数 是数组形式
				
2. 用 uvm_rem 时,需要考虑什么
	a. 未看 (TODO)
	
3. rgm ready 后,怎么用了做测试?
	a. uvm_reg 的 built-in sequences
		i. 预定义的 sequences,可以测试 所有的 registers
		ii. uvm_reg_hw_reset_seq
			1) 检查 rgm reset 值 与 hw hdl regsiter reset 值是否一样
		iii. uvm_reg_single_bit_bash_seq
			1) 对每个 域,根据 读写属性,写、读 测试
		iv. uvm_reg_bit_bash_seq
			1) 对所有 reg 执行 uvm_reg_single_bit_bash_seq 
		v. uvm_reg_single_access_seq 
			1) 前门写、后门读;后门读,前门写测试
			2) 用于测试 hdl 路径是否正确;rgm 与 hw register model 是都映射正确
		vi. uvm_reg_access_seq (一个 reg_block 有多个 map 的场景)
			1) 场景举例:
				a) hw/dut 有一个 register block,rgm 中的 uvm_map 有多个,用于 不同的处理器 来访问 dut 中的 register block
				b) 先从一个 map 写入寄存器,然后,通过另外的map读回数据;用来检查,所有可能访问寄存器路径的有效性
				
	b. uvm_mem 的 built-in sequences
		i. 未看
		
	c. 用 uvm_reg built-in sequence 的代码举例
		i. class mcdf_example_seq extends uvm_reg_sequence
			1) rgm 声明
			2) seq 用 object_utils
			3) seqr 进行 declare
			4) task body
				a) 声明需要用到的 built-in sequences 
				b) 先 reset 复位
				c)  (start 之前,需要先告知 seq ,rgm 是哪个?) 
					i) _seq.model = rgm;
				d) 然后,start
					i) _seq.start(m_sequencer);
		ii. 有一些寄存器,不需要用 内建测试序列测试。怎么排除

因为 uvm_reg_block 和 uvm_reg 都是 uvm_object 类,可以使用 uvm_resource_db 在 build 阶段,排除掉一些寄存器

2. 常用应用场景举例

(除了可以用来测试,还可以用来做什么:测试;功能覆盖率)

1. 影子寄存器 shadow register 是什么?有什么用?

2. 对硬件数据通路,做数据比对
	a. 直接用 rgm 中的值,与 硬件中的数据 进行对比
	b. 配合 scoreboard,reference model 进行
	
3. 状态寄存器、非状态寄存器通常怎么测?(内检测试序列支持)

4. 配合 scoreboard 实施检查,注意
	a. scoreboard 要可以 access 到 rgm : 句柄传递
	b. 怎么去 access 到 rgm uvm_reg, uvm_reg_field 中的值:用什么函数?访问 谁
		i. 本质是访问 uvm_reg_field 中的值
		ii. uvm_reg, uvm_reg_field 支持的函数略有不同
		iii. 建议使用  uvm_reg, uvm_reg_field 都有的函数是 get_mirrored_value( )
		
5. rgm 的功能覆盖率
	a. 自动收集 coverage
		i. 首先,定义 coverage bins 
		ii. 其次,决策:是否生成覆盖率代码、是否例化这部分代码、是否启动采样
			1) 有条件的例化
				a) has_coverage()
			2) sample 自动调用:可以理解为 read(), write() 的回调函数
				a) sample_value( ) , 有条件的例化
					i) get_coverage
					
	b. 自定义收集 coverage,基于外部事件触发收集:可以更加贴合实际场景,进行收集
		i. 自定义覆盖率类 (coverage extends subscriber, subscriber extends component)
			1) component:
				a) 参数类
			2) _subscriber 
				a) subcribe info from monitor's analysis_port, send to coverage's analysis's export
				b) 谁用这些信息,谁就可以 extends from subscriber; 如 scoreboard
			3) _coverage
				a) covergroup reg_value_cg
					i) 指定 uvm_reg_field 感兴趣的 域和值的范围
					ii) 将相关的 coverpoint 进行 cross
				b) function void write(T t);
					i) 手动监测
						One.  当 write 捕捉到 transaction 时,调用:reg_value_cg.sample( )
						
	c. 总结:监测总线,更新 rgm;通过 rgm 收 coverage;可以自动、可以手动;可以放在 rgm 外面

3. 寄存器属性的特别说明

1. register model 中,有 25 种访问方式: RC, WC

中断,都是 读了以后,会清除掉:RC (read clear)

4. 寄存器 coverage 如何收集

TODO


参考链接:
NA

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值