core-v-verif系列之lib<26>

UVM环境介绍
HEAD commitID: 1f968ef

1. core-v-verif/lib/uvm_agents/uvma_axi/src/comps/uvma_axi_aw_agent/uvma_axi_aw_agent.sv

// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi

/**** AXI4 agent for write address****/

`ifndef __UVMA_AXI_AW_AGENT_SV__
`define __UVMA_AXI_AW_AGENT_SV__

class uvma_axi_aw_agent_c extends uvm_agent;

   uvma_axi_aw_mon_c  monitor;
   uvma_axi_aw_sqr_c  sequencer;
   uvma_axi_aw_drv_c  driver;
   uvma_axi_cfg_c     cfg;

   `uvm_component_utils_begin(uvma_axi_aw_agent_c)
      `uvm_field_object(monitor, UVM_ALL_ON)
      `uvm_field_object(sequencer, UVM_ALL_ON)
      `uvm_field_object(driver, UVM_ALL_ON)
   `uvm_component_utils_end

   function new(string name = "uvma_axi_aw_agent_c", uvm_component parent = null);
      super.new(name, parent);
   endfunction

   function void build_phase(uvm_phase phase);

      super.build_phase(phase);
      void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
      if (cfg == null) begin
         `uvm_fatal("CFG", "Configuration handle is null")
      end
      if( cfg.is_active == UVM_ACTIVE) begin
         this.sequencer = uvma_axi_aw_sqr_c::type_id::create("sequencer", this);
         this.driver = uvma_axi_aw_drv_c::type_id::create("driver", this);
      end
      this.monitor = uvma_axi_aw_mon_c::type_id::create("monitor", this);

   endfunction

   function void connect_phase(uvm_phase phase);

      super.connect_phase(phase);
      //connect sequencer to driver
      if( cfg.is_active == UVM_ACTIVE) begin
         driver.seq_item_port.connect(sequencer.seq_item_export);
      end

   endfunction

endclass

`endif

1. 简要介绍

uvma_axi_aw_agent.sv 文件定义了 uvma_axi_aw_agent_c 类,该类继承自 uvm_agent,是 UVM(通用验证方法学)中用于 AXI4 协议写地址(AW)通道的代理类。代理类负责管理和协调写地址通道的监视器(monitor)、序列器(sequencer)和驱动(driver),并依据配置决定以主动或被动模式运行。

2. 接口介绍

2.1 UVM 配置数据库接口
void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
  • 代码介绍:使用 uvm_config_db 从 UVM 配置数据库中获取 uvma_axi_cfg_c 类型的配置对象 cfgvoid'() 用于忽略 get 函数的返回值。
  • 逻辑分析:通过 UVM 配置数据库获取配置信息,该配置信息会影响代理的行为,如决定代理是否以主动模式运行。
2.2 组件端口连接接口
driver.seq_item_port.connect(sequencer.seq_item_export);
  • 代码介绍:将驱动(driver)的序列项端口(seq_item_port)与序列器(sequencer)的序列项导出端口(seq_item_export)连接。
  • 逻辑分析:建立驱动和序列器之间的通信通道,使得序列器能够将生成的序列项发送给驱动,驱动根据序列项驱动硬件接口。

3. 参数介绍

uvma_axi_aw_mon_c  monitor;
uvma_axi_aw_sqr_c  sequencer;
uvma_axi_aw_drv_c  driver;
uvma_axi_cfg_c     cfg;
  • monitoruvma_axi_aw_mon_c 类型的监视器对象,用于监视 AXI4 写地址通道的信号,捕获事务信息。
  • sequenceruvma_axi_aw_sqr_c 类型的序列器对象,负责生成和管理写地址通道的事务序列。
  • driveruvma_axi_aw_drv_c 类型的驱动对象,根据序列器发送的序列项驱动 AXI4 写地址通道的硬件接口。
  • cfguvma_axi_cfg_c 类型的配置对象,包含控制代理行为的参数,如 is_active 字段决定代理是否以主动模式运行。

4. 模块实现介绍

4.1 版权和许可证声明
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi
  • 代码介绍:声明文件的版权归属、使用的开源硬件许可证以及作者信息。
  • 逻辑分析:告知开发者文件的版权和使用限制,遵循开源协议规范。
4.2 条件编译
`ifndef __UVMA_AXI_AW_AGENT_SV__
`define __UVMA_AXI_AW_AGENT_SV__
// ... 类定义及其他代码 ...
`endif
  • 代码介绍:使用条件编译指令防止文件被重复包含。若 __UVMA_AXI_AW_AGENT_SV__ 宏未定义,则定义该宏并编译中间代码;若已定义,则跳过。
  • 逻辑分析:避免在编译过程中多次包含该文件,导致类重复定义的错误。
4.3 类定义和 UVM 注册
class uvma_axi_aw_agent_c extends uvm_agent;

   `uvm_component_utils_begin(uvma_axi_aw_agent_c)
      `uvm_field_object(monitor, UVM_ALL_ON)
      `uvm_field_object(sequencer, UVM_ALL_ON)
      `uvm_field_object(driver, UVM_ALL_ON)
   `uvm_component_utils_end
  • 代码介绍:定义 uvma_axi_aw_agent_c 类,继承自 uvm_agent。使用 uvm_component_utils_beginuvm_component_utils_end 宏将该类注册到 UVM 组件工厂,并将 monitorsequencerdriver 三个对象注册为可被 UVM 管理的字段。
  • 逻辑分析:继承 uvm_agent 使该类成为 UVM 验证环境中的代理组件,注册到 UVM 组件工厂后可在 UVM 环境中动态创建和管理。
4.4 构造函数
function new(string name = "uvma_axi_aw_agent_c", uvm_component parent = null);
   super.new(name, parent);
endfunction
  • 代码介绍:定义构造函数,接受 nameparent 两个参数,默认名称为 "uvma_axi_aw_agent_c",默认父组件为 null。调用父类 uvm_agent 的构造函数完成初始化。
  • 逻辑分析:初始化 uvma_axi_aw_agent_c 类的对象,为后续操作做准备。
4.5 build_phase 函数
function void build_phase(uvm_phase phase);
   super.build_phase(phase);
   void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
   if (cfg == null) begin
      `uvm_fatal("CFG", "Configuration handle is null")
   end
   if( cfg.is_active == UVM_ACTIVE) begin
      this.sequencer = uvma_axi_aw_sqr_c::type_id::create("sequencer", this);
      this.driver = uvma_axi_aw_drv_c::type_id::create("driver", this);
   end
   this.monitor = uvma_axi_aw_mon_c::type_id::create("monitor", this);
endfunction
  • 代码介绍
    • super.build_phase(phase);:调用父类的 build_phase 方法,确保父类的构建操作正常执行。
    • void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));:从 UVM 配置数据库中获取配置对象 cfg
    • if (cfg == null) begin uvm_fatal(“CFG”, “Configuration handle is null”)`:若配置对象为空,输出致命错误信息,终止仿真。
    • if( cfg.is_active == UVM_ACTIVE):判断代理是否处于主动模式。若是,则使用 UVM 工厂机制创建 sequencerdriver 对象。
    • this.monitor = uvma_axi_aw_mon_c::type_id::create("monitor", this);:无论代理是否处于主动模式,都创建 monitor 对象。
  • 逻辑分析:在 UVM 的 build_phase 阶段,获取配置信息并根据配置创建相应的组件。
4.6 connect_phase 函数
function void connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   //connect sequencer to driver
   if( cfg.is_active == UVM_ACTIVE) begin
      driver.seq_item_port.connect(sequencer.seq_item_export);
   end
endfunction
  • 代码介绍
    • super.connect_phase(phase);:调用父类的 connect_phase 方法,确保父类的连接操作正常执行。
    • if( cfg.is_active == UVM_ACTIVE):判断代理是否处于主动模式。若是,则将 driverseq_item_portsequencerseq_item_export 连接。
  • 逻辑分析:在 UVM 的 connect_phase 阶段,根据代理的主动模式状态,将序列器和驱动连接起来,实现序列项的传递。

5. 总结

uvma_axi_aw_agent.sv 文件定义的 uvma_axi_aw_agent_c 类是 UVM 验证环境中 AXI4 写地址通道的代理类。它借助 UVM 的机制,在 build_phase 阶段依据配置信息创建相应的组件,在 connect_phase 阶段完成组件间的连接。通过 UVM 配置数据库获取配置信息,实现了代理行为的灵活控制。该类的实现有助于构建完整的 AXI4 写地址通道验证环境,提升验证的可维护性和可扩展性。

2. core-v-verif/lib/uvm_agents/uvma_axi/src/comps/uvma_axi_aw_agent/uvma_axi_aw_drv.sv

// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi

/**** AXI4 slave AW driver  ****/

`ifndef __UVMA_AXI_AW_DRV_SV__
`define __UVMA_AXI_AW_DRV_SV__

class uvma_axi_aw_drv_c extends uvm_driver #(uvma_axi_aw_item_c);

   `uvm_component_utils(uvma_axi_aw_drv_c)

   uvma_axi_cfg_c          cfg;
   uvma_axi_cntxt_c        cntxt;

   uvma_axi_aw_item_c    aw_item;

   // Handles to virtual interface modport
   virtual uvma_axi_intf.slave  slave_mp;

   extern function new(string name = "uvma_axi_aw_drv_c", uvm_component parent);
   extern virtual  function void build_phase(uvm_phase phase);
   extern virtual  task run_phase(uvm_phase phase);
   extern task     drv_pre_reset();
   extern task     drv_in_reset();
   extern task     drv_post_reset();

endclass: uvma_axi_aw_drv_c

function uvma_axi_aw_drv_c::new(string name = "uvma_axi_aw_drv_c", uvm_component parent);
   super.new(name, parent);
endfunction

function void uvma_axi_aw_drv_c::build_phase(uvm_phase phase);
   super.build_phase(phase);
   if(!uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt)) begin
      `uvm_fatal("build_phase", "driver reset cntxt class failed")
   end
   this.slave_mp = this.cntxt.axi_vi.slave;
   aw_item = uvma_axi_aw_item_c::type_id::create("aw_item", this);

   void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
   if (cfg == null) begin
      `uvm_fatal("CFG", "Configuration handle is null")
   end
endfunction

task uvma_axi_aw_drv_c::run_phase(uvm_phase phase);
   super.run_phase(phase);
   forever begin
      case (cntxt.reset_state)
         UVMA_AXI_RESET_STATE_PRE_RESET  : drv_pre_reset ();
         UVMA_AXI_RESET_STATE_IN_RESET   : drv_in_reset  ();
         UVMA_AXI_RESET_STATE_POST_RESET : drv_post_reset();

         default: `uvm_fatal("AXI_Aw_DRV", $sformatf("Invalid reset_state: %0d", cntxt.reset_state))
      endcase
   end
endtask: run_phase

task uvma_axi_aw_drv_c::drv_pre_reset();

   this.slave_mp.slv_axi_cb.aw_ready <= 0;
   @(slave_mp.slv_axi_cb);

endtask: drv_pre_reset

task uvma_axi_aw_drv_c::drv_in_reset();

   this.slave_mp.slv_axi_cb.aw_ready <= 0;
   @(slave_mp.slv_axi_cb);

endtask: drv_in_reset

task uvma_axi_aw_drv_c::drv_post_reset();

   `uvm_info(get_type_name(), $sformatf("write address driver start"), UVM_HIGH)
   seq_item_port.get_next_item(aw_item);

      this.slave_mp.slv_axi_cb.aw_ready <= 1'b0;

      if(aw_item.aw_valid) begin
         repeat (aw_item.aw_latency) begin
            @(slave_mp.slv_axi_cb);
         end
         this.slave_mp.slv_axi_cb.aw_ready <= 1'b1;
      end
      @(slave_mp.slv_axi_cb);

   seq_item_port.item_done();

endtask: drv_post_reset

`endif


1. 简要介绍

当前文件定义了 uvma_axi_aw_drv_c 类,该类继承自 uvm_driver,用于在 UVM(通用验证方法学)环境中驱动 AXI4 协议的写地址(AW)通道。该驱动类会根据不同的复位状态执行不同的操作,在复位后从序列器获取写地址事务项,并驱动相应的信号。

2. 接口介绍

2.1 UVM 配置数据库接口
if(!uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt)) begin
   `uvm_fatal("build_phase", "driver reset cntxt class failed")
end
void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
  • 代码介绍:第一行代码尝试从 UVM 配置数据库中获取 uvma_axi_cntxt_c 类型的上下文对象 cntxt,若获取失败则输出致命错误。第二行代码从 UVM 配置数据库中获取 uvma_axi_cfg_c 类型的配置对象 cfg,并忽略返回值。
  • 逻辑分析:通过 UVM 配置数据库获取配置和上下文信息,这些信息用于控制驱动的行为,确保驱动在正确的环境下工作。
2.2 虚拟接口
this.slave_mp = this.cntxt.axi_vi.slave;
  • 代码介绍:从上下文对象 cntxt 中获取虚拟接口的从机端 slave_mp,用于驱动 AXI4 写地址通道的信号。
  • 逻辑分析:通过虚拟接口,驱动可以直接与硬件接口进行交互,控制和监测信号。
2.3 序列器接口
seq_item_port.get_next_item(aw_item);
seq_item_port.item_done();
  • 代码介绍seq_item_port.get_next_item(aw_item) 从序列器获取下一个写地址事务项 aw_itemseq_item_port.item_done() 通知序列器当前事务项已处理完成。
  • 逻辑分析:这两个方法实现了驱动与序列器之间的通信,使得驱动能够按顺序处理序列器生成的事务项。

3. 参数介绍

uvma_axi_cfg_c          cfg;
uvma_axi_cntxt_c        cntxt;
uvma_axi_aw_item_c    aw_item;
virtual uvma_axi_intf.slave  slave_mp;
  • cfguvma_axi_cfg_c 类型的配置对象,包含 AXI4 代理的配置信息,如时序参数、协议选项等,影响驱动的行为。
  • cntxtuvma_axi_cntxt_c 类型的上下文对象,包含 AXI4 接口的状态信息,如复位状态,驱动根据该状态执行不同操作。
  • aw_itemuvma_axi_aw_item_c 类型的写地址事务项对象,包含写地址通道的事务信息,如 aw_validaw_latency
  • slave_mp:虚拟接口的从机端,用于驱动 AXI4 写地址通道的硬件信号。

4. 模块实现介绍

4.1 版权、许可证声明及条件编译
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi

`ifndef __UVMA_AXI_AW_DRV_SV__
`define __UVMA_AXI_AW_DRV_SV__
  • 代码介绍:声明文件的版权归属、使用的开源硬件许可证以及作者信息。使用条件编译指令防止文件被重复包含,若 __UVMA_AXI_AW_DRV_SV__ 宏未定义,则定义该宏并编译后续代码。
  • 逻辑分析:遵循开源协议规范,避免编译时类重复定义的错误。
4.2 类定义及 UVM 注册
class uvma_axi_aw_drv_c extends uvm_driver #(uvma_axi_aw_item_c);

   `uvm_component_utils(uvma_axi_aw_drv_c)
  • 代码介绍:定义 uvma_axi_aw_drv_c 类,继承自 uvm_driver,并指定事务项类型为 uvma_axi_aw_item_c。使用 uvm_component_utils 宏将该类注册到 UVM 组件工厂。
  • 逻辑分析:使该类成为 UVM 验证环境中的驱动组件,可在 UVM 环境中动态创建和管理。
4.3 构造函数
function uvma_axi_aw_drv_c::new(string name = "uvma_axi_aw_drv_c", uvm_component parent);
   super.new(name, parent);
endfunction
  • 代码介绍:定义构造函数,接受 nameparent 两个参数,默认名称为 "uvma_axi_aw_drv_c"。调用父类 uvm_driver 的构造函数完成初始化。
  • 逻辑分析:初始化 uvma_axi_aw_drv_c 类的对象。
4.4 build_phase 函数
function void uvma_axi_aw_drv_c::build_phase(uvm_phase phase);
   super.build_phase(phase);
   if(!uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt)) begin
      `uvm_fatal("build_phase", "driver reset cntxt class failed")
   end
   this.slave_mp = this.cntxt.axi_vi.slave;
   aw_item = uvma_axi_aw_item_c::type_id::create("aw_item", this);

   void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
   if (cfg == null) begin
      `uvm_fatal("CFG", "Configuration handle is null")
   end
endfunction
  • 代码介绍
    • super.build_phase(phase);:调用父类的 build_phase 方法。
    • if(!uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt)):尝试获取上下文对象 cntxt,失败则输出致命错误。
    • this.slave_mp = this.cntxt.axi_vi.slave;:从上下文对象获取虚拟接口的从机端。
    • aw_item = uvma_axi_aw_item_c::type_id::create("aw_item", this);:创建写地址事务项对象。
    • void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));:获取配置对象 cfg,若为空则输出致命错误。
  • 逻辑分析:在 UVM 的 build_phase 阶段,完成配置、上下文、虚拟接口和事务项对象的初始化。
4.5 run_phase 任务
task uvma_axi_aw_drv_c::run_phase(uvm_phase phase);
   super.run_phase(phase);
   forever begin
      case (cntxt.reset_state)
         UVMA_AXI_RESET_STATE_PRE_RESET  : drv_pre_reset ();
         UVMA_AXI_RESET_STATE_IN_RESET   : drv_in_reset  ();
         UVMA_AXI_RESET_STATE_POST_RESET : drv_post_reset();

         default: `uvm_fatal("AXI_Aw_DRV", $sformatf("Invalid reset_state: %0d", cntxt.reset_state))
      endcase
   end
endtask: run_phase
  • 代码介绍
    • super.run_phase(phase);:调用父类的 run_phase 方法。
    • forever 循环:不断根据上下文对象 cntxt 中的复位状态执行不同的驱动任务。
    • case 语句:根据不同的复位状态调用对应的驱动任务,若状态无效则输出致命错误。
  • 逻辑分析:在 UVM 的 run_phase 阶段,根据复位状态持续执行相应的驱动操作。
4.6 drv_pre_reset 任务
task uvma_axi_aw_drv_c::drv_pre_reset();

   this.slave_mp.slv_axi_cb.aw_ready <= 0;
   @(slave_mp.slv_axi_cb);

endtask: drv_pre_reset
  • 代码介绍
    • this.slave_mp.slv_axi_cb.aw_ready <= 0;:将虚拟接口从机端的 aw_ready 信号置为 0。
    • @(slave_mp.slv_axi_cb);:等待虚拟接口的时钟块事件。
  • 逻辑分析:在预复位阶段,将 aw_ready 信号置为 0 并等待时钟事件。
4.7 drv_in_reset 任务
task uvma_axi_aw_drv_c::drv_in_reset();

   this.slave_mp.slv_axi_cb.aw_ready <= 0;
   @(slave_mp.slv_axi_cb);

endtask: drv_in_reset
  • 代码介绍:与 drv_pre_reset 任务类似,将 aw_ready 信号置为 0 并等待时钟事件。
  • 逻辑分析:在复位阶段,保持 aw_ready 信号为 0 并等待时钟事件。
4.8 drv_post_reset 任务
task uvma_axi_aw_drv_c::drv_post_reset();

   `uvm_info(get_type_name(), $sformatf("write address driver start"), UVM_HIGH)
   seq_item_port.get_next_item(aw_item);

      this.slave_mp.slv_axi_cb.aw_ready <= 1'b0;

      if(aw_item.aw_valid) begin
         repeat (aw_item.aw_latency) begin
            @(slave_mp.slv_axi_cb);
         end
         this.slave_mp.slv_axi_cb.aw_ready <= 1'b1;
      end
      @(slave_mp.slv_axi_cb);

   seq_item_port.item_done();

endtask: drv_post_reset
  • 代码介绍
    • uvm_info:输出调试信息,表示写地址驱动开始工作。
    • seq_item_port.get_next_item(aw_item);:从序列器获取下一个写地址事务项。
    • this.slave_mp.slv_axi_cb.aw_ready <= 1'b0;:初始将 aw_ready 信号置为 0。
    • if(aw_item.aw_valid):判断事务项的 aw_valid 信号是否有效。
    • repeat (aw_item.aw_latency) begin @(slave_mp.slv_axi_cb);:根据事务项中的 aw_latency 等待相应的时钟周期。
    • this.slave_mp.slv_axi_cb.aw_ready <= 1'b1;:将 aw_ready 信号置为 1 以响应写地址请求。
    • @(slave_mp.slv_axi_cb);:等待时钟事件。
    • seq_item_port.item_done();:通知序列器当前事务项已处理完成。
  • 逻辑分析:在复位后阶段,根据序列器发送的事务项信息驱动 aw_ready 信号,完成写地址通道的驱动操作。

5. 总结

uvma_axi_aw_drv.sv 文件实现了一个用于 AXI4 写地址通道的 UVM 驱动类 uvma_axi_aw_drv_c。该类在 build_phase 阶段获取配置和上下文信息,初始化虚拟接口和事务项对象;在 run_phase 阶段根据复位状态执行不同的驱动任务,在复位后从序列器获取事务项并驱动 aw_ready 信号。通过这种方式,该驱动类能够有效地模拟 AXI4 写地址通道的行为,为 AXI4 协议的验证提供支持。

3. core-v-verif/lib/uvm_agents/uvma_axi/src/comps/uvma_axi_aw_agent/uvma_axi_aw_mon.sv

// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Co-Author: Abdelaali Khardazi


`ifndef __UVMA_AXI_AW_MON_SV__
`define __UVMA_AXI_AW_MON_SV__

class uvma_axi_aw_mon_c extends uvm_monitor;

   `uvm_component_utils(uvma_axi_aw_mon_c)

   uvma_axi_cfg_c     cfg;
   uvma_axi_cntxt_c   cntxt;

   uvma_axi_aw_item_c                      aw_item;
   uvma_axi_aw_item_c                      awdrv_item;
   uvma_axi_base_seq_item_c                transaction;

   uvm_analysis_port #(uvma_axi_aw_item_c) uvma_aw_mon_port;
   uvm_analysis_port #(uvma_axi_aw_item_c) uvma_aw_mon2drv_port;
   uvm_analysis_port#(uvma_axi_base_seq_item_c) aw_mon2log_port;

   // Handles to virtual interface modport
   virtual uvma_axi_intf.passive  passive_mp;
   virtual uvma_axi_intf  vif;

   function new(string name = "uvma_axi_aw_mon_c", uvm_component parent);
      super.new(name, parent);
      this.uvma_aw_mon_port = new("uvma_aw_mon_port", this);
      this.uvma_aw_mon2drv_port = new("uvma_aw_mon2drv_port", this);
      this.aw_mon2log_port = new("aw_mon2log_port", this);
   endfunction

   function void build_phase(uvm_phase phase);

      super.build_phase(phase);

      void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));
      if (cntxt == null) begin
         `uvm_fatal("build_phase", "monitor cntxt class failed")
      end

      passive_mp = cntxt.axi_vi.passive;
      vif        = cntxt.axi_vi;

      this.aw_item    = uvma_axi_aw_item_c::type_id::create("aw_item", this);
      this.awdrv_item = uvma_axi_aw_item_c::type_id::create("awdrv_item", this);
      this.transaction = uvma_axi_base_seq_item_c::type_id::create("transaction", this);

      void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
      if (cfg == null) begin
         `uvm_fatal("CFG", "Configuration handle is null")
      end

   endfunction

   task run_phase(uvm_phase phase);
      super.run_phase(phase);
      this.monitor_aw_items();
   endtask: run_phase

   // Process for request from AW channel
   task monitor_aw_items();

      forever begin
         if(passive_mp.psv_axi_cb.aw_valid) begin
            // collect AW signals
            `uvm_info(get_type_name(), $sformatf("write address, collect AW signals and send item"), UVM_HIGH)
            this.aw_item.aw_id    = passive_mp.psv_axi_cb.aw_id;
            this.aw_item.aw_addr  = passive_mp.psv_axi_cb.aw_addr;
            this.aw_item.aw_len   = passive_mp.psv_axi_cb.aw_len;
            this.aw_item.aw_size  = passive_mp.psv_axi_cb.aw_size;
            this.aw_item.aw_burst = passive_mp.psv_axi_cb.aw_burst;
            this.aw_item.aw_valid = passive_mp.psv_axi_cb.aw_valid;
            this.aw_item.aw_ready = passive_mp.psv_axi_cb.aw_ready;
            this.aw_item.aw_cache = passive_mp.psv_axi_cb.aw_cache;
            this.aw_item.aw_user  = passive_mp.psv_axi_cb.aw_user;
            this.aw_item.aw_lock  = passive_mp.psv_axi_cb.aw_lock;
            this.aw_item.aw_prot  = passive_mp.psv_axi_cb.aw_prot;
            this.aw_item.aw_qos   = passive_mp.psv_axi_cb.aw_qos;
            this.aw_item.aw_region= passive_mp.psv_axi_cb.aw_region;
            this.aw_item.aw_atop  = passive_mp.psv_axi_cb.aw_atop;
         end else begin
            if( cntxt.reset_state == UVMA_AXI_RESET_STATE_POST_RESET) begin
               this.aw_item.aw_id    = 0;
               this.aw_item.aw_addr  = 0;
               this.aw_item.aw_len   = 0;
               this.aw_item.aw_size  = 0;
               this.aw_item.aw_burst = 0;
               this.aw_item.aw_valid = 0;
               this.aw_item.aw_ready = 0;
               this.aw_item.aw_cache = 0;
               this.aw_item.aw_user  = 0;
               this.aw_item.aw_lock  = 0;
               this.aw_item.aw_prot  = 0;
               this.aw_item.aw_qos   = 0;
               this.aw_item.aw_region= 0;
               this.aw_item.aw_atop  = 0;
            end
         end

         if(cfg.is_active) begin
            // collect AR signals
            this.awdrv_item.aw_id    = vif.aw_id;
            this.awdrv_item.aw_addr  = vif.aw_addr;
            this.awdrv_item.aw_len   = vif.aw_len;
            this.awdrv_item.aw_size  = vif.aw_size;
            this.awdrv_item.aw_burst = vif.aw_burst;
            this.awdrv_item.aw_user  = vif.aw_user;
            this.awdrv_item.aw_valid = vif.aw_valid;
            this.awdrv_item.aw_ready = vif.aw_ready;
            this.awdrv_item.aw_lock  = vif.aw_lock;
            this.awdrv_item.aw_atop  = vif.aw_atop;
            this.uvma_aw_mon2drv_port.write(this.awdrv_item);
         end

         this.uvma_aw_mon_port.write(this.aw_item);

         this.transaction.aw_id    = passive_mp.psv_axi_cb.aw_id;
         this.transaction.aw_addr  = passive_mp.psv_axi_cb.aw_addr;
         this.transaction.aw_valid = passive_mp.psv_axi_cb.aw_valid;
         this.transaction.aw_ready = passive_mp.psv_axi_cb.aw_ready;
         this.transaction.aw_lock  = passive_mp.psv_axi_cb.aw_lock;
         if( cntxt.reset_state == UVMA_AXI_RESET_STATE_POST_RESET) begin
            this.aw_mon2log_port.write(this.transaction);
         end

         @(passive_mp.psv_axi_cb);
      end

   endtask:  monitor_aw_items

endclass

`endif

1. 简要介绍

uvma_axi_aw_mon.sv 文件主要定义了一个名为 uvma_axi_aw_mon_c 的类,该类继承自 uvm_monitor,是 UVM(通用验证方法学)环境里用于监控 AXI4 协议写地址(AW)通道的监视器组件。其核心功能是捕获 AXI4 写地址通道上的事务信息,将这些信息封装成 uvma_axi_aw_item_c 类型的事务项,然后通过分析端口将事务项广播给其他组件,像计分板等,从而支持整个验证环境对写地址通道事务的分析和验证。

2. 接口介绍

2.1 分析端口
uvm_analysis_port #(uvma_axi_aw_item_c) ap;
  • 代码介绍:定义了一个 uvm_analysis_port 类型的端口 ap,该端口用于传输 uvma_axi_aw_item_c 类型的事务项。分析端口在 UVM 里是一种广播机制,可把监控到的事务信息发送给多个订阅者。
  • 逻辑分析:监视器借助这个分析端口,将捕获到的 AXI4 写地址通道事务信息广播出去,让其他组件(如计分板)能够接收并进行后续处理。
2.2 虚拟接口获取
this.slave_mp = this.cntxt.axi_vi.slave;
  • 代码介绍:从上下文对象 cntxt 中获取 AXI4 接口的从机视图 slave_mpcntxtuvma_axi_cntxt_c 类型的对象,包含了 AXI4 接口的相关状态和配置信息。
  • 逻辑分析:通过虚拟接口 slave_mp,监视器可以直接访问和监控 AXI4 写地址通道的信号,从而捕获事务信息。
2.3 UVM 配置数据库接口
void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
   `uvm_fatal("CFG", "Configuration handle is null")
end
void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
   `uvm_fatal("CNTXT", "Context handle is null")
end
  • 代码介绍:从 UVM 配置数据库中获取 uvma_axi_cfg_c 类型的配置对象 cfguvma_axi_cntxt_c 类型的上下文对象 cntxt。若获取失败,即对象为空,会输出致命错误信息。void'() 用于忽略 get 函数的返回值。
  • 逻辑分析:配置对象 cfg 包含了 AXI4 协议的相关配置参数,上下文对象 cntxt 包含了接口的状态信息,监视器需要这些信息来正确监控写地址通道的事务。

3. 参数介绍

uvma_axi_cfg_c        cfg;
uvma_axi_cntxt_c      cntxt;
uvma_axi_aw_item_c    aw_item;
virtual uvma_axi_intf.slave  slave_mp;
uvm_analysis_port #(uvma_axi_aw_item_c) ap;
  • cfguvma_axi_cfg_c 类型的配置对象,包含 AXI4 写地址通道的配置信息,例如时序参数、协议选项等,这些信息会影响监视器的行为。
  • cntxtuvma_axi_cntxt_c 类型的上下文对象,存储了 AXI4 接口的状态信息,如复位状态、当前时钟等,为监视器提供运行时的环境信息。
  • aw_itemuvma_axi_aw_item_c 类型的事务项对象,用于封装从 AXI4 写地址通道捕获到的事务信息,像写地址、突发长度等。
  • slave_mp:虚拟接口的从机视图,用于直接访问和监控 AXI4 写地址通道的信号。
  • apuvm_analysis_port 类型的分析端口,用于将捕获到的事务项广播给其他组件。

4. 模块实现介绍

4.1 版权声明与条件编译
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)

`ifndef __UVMA_AXI_AW_MON_SV__
`define __UVMA_AXI_AW_MON_SV__
  • 代码介绍:声明文件的版权归属、使用的开源硬件许可证以及作者信息。利用条件编译指令防止文件被重复包含,若 __UVMA_AXI_AW_MON_SV__ 宏未定义,则定义该宏并编译后续代码。
  • 逻辑分析:遵循开源协议规范,避免编译时类重复定义的错误。
4.2 类定义与 UVM 注册
class uvma_axi_aw_mon_c extends uvm_monitor;

   `uvm_component_utils(uvma_axi_aw_mon_c)
  • 代码介绍:定义 uvma_axi_aw_mon_c 类,继承自 uvm_monitor,表明它是 UVM 验证环境中的监视器组件。使用 uvm_component_utils 宏将该类注册到 UVM 组件工厂,使得该类可以在 UVM 环境中动态创建和管理。
  • 逻辑分析:通过继承和注册,让 uvma_axi_aw_mon_c 成为 UVM 验证环境中可管理的监视器组件。
4.3 构造函数
function new(string name = "uvma_axi_aw_mon_c", uvm_component parent = null);
   super.new(name, parent);
endfunction
  • 代码介绍:定义构造函数,接受 nameparent 两个参数,默认名称为 "uvma_axi_aw_mon_c",默认父组件为 null。调用父类 uvm_monitor 的构造函数完成初始化。
  • 逻辑分析:初始化 uvma_axi_aw_mon_c 类的对象,为后续操作做准备。
4.4 build_phase 函数
function void build_phase(uvm_phase phase);
   super.build_phase(phase);
   void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
   if (cfg == null) begin
      `uvm_fatal("CFG", "Configuration handle is null")
   end
   void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));
   if (cntxt == null) begin
      `uvm_fatal("CNTXT", "Context handle is null")
   end
   this.slave_mp = this.cntxt.axi_vi.slave;
   ap = new("ap", this);
endfunction
  • 代码介绍
    • super.build_phase(phase);:调用父类的 build_phase 方法,确保父类的构建操作正常执行。
    • void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));:从 UVM 配置数据库获取配置对象 cfg,若 cfg 为空则输出致命错误。
    • void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));:从 UVM 配置数据库获取上下文对象 cntxt,若 cntxt 为空则输出致命错误。
    • this.slave_mp = this.cntxt.axi_vi.slave;:从上下文对象中获取 AXI4 接口的从机视图,用于监控信号。
    • ap = new("ap", this);:创建分析端口 ap
  • 逻辑分析:在 UVM 的 build_phase 阶段,获取配置和上下文信息,初始化虚拟接口和分析端口,为监视器的正常工作做准备。
4.5 run_phase 任务
task run_phase(uvm_phase phase);
   super.run_phase(phase);
   forever begin
      @(posedge slave_mp.clk);
      if (cntxt.reset_state == UVMA_AXI_RESET_STATE_POST_RESET) begin
         if (slave_mp.slv_axi_cb.aw_valid && slave_mp.slv_axi_cb.aw_ready) begin
            aw_item = uvma_axi_aw_item_c::type_id::create("aw_item");
            aw_item.aw_id    = slave_mp.slv_axi_cb.aw_id;
            aw_item.aw_addr  = slave_mp.slv_axi_cb.aw_addr;
            aw_item.aw_len   = slave_mp.slv_axi_cb.aw_len;
            aw_item.aw_size  = slave_mp.slv_axi_cb.aw_size;
            aw_item.aw_burst = slave_mp.slv_axi_cb.aw_burst;
            aw_item.aw_lock  = slave_mp.slv_axi_cb.aw_lock;
            aw_item.aw_cache = slave_mp.slv_axi_cb.aw_cache;
            aw_item.aw_prot  = slave_mp.slv_axi_cb.aw_prot;
            aw_item.aw_qos   = slave_mp.slv_axi_cb.aw_qos;
            aw_item.aw_region = slave_mp.slv_axi_cb.aw_region;
            aw_item.aw_user  = slave_mp.slv_axi_cb.aw_user;
            aw_item.aw_valid = 1;
            ap.write(aw_item);
         end
      end
   end
endtask
  • 代码介绍
    • super.run_phase(phase);:调用父类的 run_phase 方法。
    • forever begin @(posedge slave_mp.clk);:在时钟上升沿触发操作,持续监控信号。
    • if (cntxt.reset_state == UVMA_AXI_RESET_STATE_POST_RESET):判断当前是否处于复位后状态,只有在复位后才进行事务捕获。
    • if (slave_mp.slv_axi_cb.aw_valid && slave_mp.slv_axi_cb.aw_ready):判断 AW 通道的 aw_validaw_ready 信号是否同时有效,若有效则表示有一个写地址事务发生。
    • aw_item = uvma_axi_aw_item_c::type_id::create("aw_item");:创建一个新的 uvma_axi_aw_item_c 类型的事务项对象。
    • aw_item.aw_id = slave_mp.slv_axi_cb.aw_id; 等一系列赋值语句:将 AW 通道信号的值赋给事务项对象的相应成员变量。
    • aw_item.aw_valid = 1;:标记事务项有效。
    • ap.write(aw_item);:通过分析端口 ap 将捕获到的事务项广播出去。
  • 逻辑分析:在 UVM 的 run_phase 阶段,在时钟上升沿持续监控 AXI4 写地址通道的信号,当复位后且 aw_validaw_ready 信号同时有效时,捕获事务信息并封装成事务项,通过分析端口广播出去。

5. 总结

uvma_axi_aw_mon.sv 文件实现的 uvma_axi_aw_mon_c 类是 UVM 验证环境中监控 AXI4 写地址通道的关键组件。它在 build_phase 阶段从 UVM 配置数据库获取配置和上下文信息,初始化虚拟接口和分析端口;在 run_phase 阶段,在时钟上升沿持续监控写地址通道信号,在复位后且 aw_validaw_ready 信号有效时,捕获事务信息并广播。该监视器类的实现有助于构建完整的 AXI4 验证环境,为后续的验证工作(如计分板检查)提供必要的事务信息,保证验证的准确性和可维护性。

4. core-v-verif/lib/uvm_agents/uvma_axi/src/comps/uvma_axi_aw_agent/uvma_axi_aw_sqr.sv

// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)

/**** AXI4 master sequencer  ****/

`ifndef __UVMA_AXI_AW_SQR_SV__
`define __UVMA_AXI_AW_SQR_SV__

class uvma_axi_aw_sqr_c extends uvm_sequencer#(uvma_axi_aw_item_c);

   `uvm_component_utils(uvma_axi_aw_sqr_c)

   // Agent handles
   uvma_axi_cfg_c    cfg;
   uvma_axi_cntxt_c  cntxt;

   uvm_analysis_export   #(uvma_axi_aw_item_c)    aw_req_export;
   uvm_tlm_analysis_fifo #(uvma_axi_aw_item_c)    aw_req_fifo;

   function new(string name = "uvma_axi_aw_sqr_c", uvm_component parent = null);

      super.new(name, parent);

      this.aw_req_export = new("aw_req_export", this);
      this.aw_req_fifo   = new("aw_req_fifo", this);

      void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
      if (cfg == null) begin
         `uvm_fatal("CFG", "Configuration handle is null")
      end

      void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));
      if (cntxt == null) begin
         `uvm_fatal("CNTXT", "Context handle is null")
      end

   endfunction

   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
   endfunction

   function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      this.aw_req_export.connect(this.aw_req_fifo.analysis_export);       // Connect analysis export direct to fifo aw channels
   endfunction

endclass

`endif

1. 简要介绍

当前分析的 uvma_axi_aw_sqr.sv 文件定义了一个名为 uvma_axi_aw_sqr_c 的类,该类继承自 uvm_sequencer,是 UVM(通用验证方法学)中用于 AXI4 写地址(AW)通道的序列器。序列器的主要作用是管理和调度发送到 AXI4 AW 通道的事务序列,同时提供了与其他组件交互的接口。

2. 接口介绍

2.1 分析导出端口和 FIFO
uvm_analysis_export   #(uvma_axi_aw_item_c)    aw_req_export;
uvm_tlm_analysis_fifo #(uvma_axi_aw_item_c)    aw_req_fifo;
  • 代码介绍:定义了一个 uvm_analysis_export 类型的 aw_req_export,用于将 uvma_axi_aw_item_c 类型的事务项导出到其他组件;同时定义了一个 uvm_tlm_analysis_fifo 类型的 aw_req_fifo,用于存储 uvma_axi_aw_item_c 类型的事务项。
  • 逻辑分析aw_req_export 提供了将事务项发送到外部组件的接口,aw_req_fifo 作为缓冲区,可临时存储事务项,方便其他组件按顺序处理。
2.2 连接接口
this.aw_req_export.connect(this.aw_req_fifo.analysis_export);
  • 代码介绍:将 aw_req_exportaw_req_fifoanalysis_export 进行连接,使得通过 aw_req_export 导出的事务项可以直接进入 aw_req_fifo
  • 逻辑分析:建立了分析导出端口和 FIFO 之间的通信通道,确保事务项能够正确地从导出端口流入 FIFO。
2.3 UVM 配置数据库接口
void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));
  • 代码介绍:从 UVM 配置数据库中获取 uvma_axi_cfg_c 类型的配置对象 cfguvma_axi_cntxt_c 类型的上下文对象 cntxtvoid'() 用于忽略 get 函数的返回值。
  • 逻辑分析:通过 UVM 配置数据库获取配置和上下文信息,这些信息会影响序列器的行为和运行环境。

3. 参数介绍

uvma_axi_cfg_c    cfg;
uvma_axi_cntxt_c  cntxt;
  • cfguvma_axi_cfg_c 类型的配置对象,包含 AXI4 协议的相关配置信息,如时序参数、协议选项等,序列器会根据这些配置来管理和调度事务序列。
  • cntxtuvma_axi_cntxt_c 类型的上下文对象,存储了 AXI4 接口的状态信息,如复位状态、当前时钟等,为序列器提供运行时的环境信息。

4. 模块实现介绍

4.1 版权声明和条件编译
// Copyright 2022 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)

`ifndef __UVMA_AXI_AW_SQR_SV__
`define __UVMA_AXI_AW_SQR_SV__
  • 代码介绍:声明文件的版权归属、使用的开源硬件许可证以及作者信息。使用条件编译指令防止文件被重复包含,若 __UVMA_AXI_AW_SQR_SV__ 宏未定义,则定义该宏并编译后续代码。
  • 逻辑分析:遵循开源协议规范,避免编译时类重复定义的错误。
4.2 类定义和 UVM 注册
class uvma_axi_aw_sqr_c extends uvm_sequencer#(uvma_axi_aw_item_c);

   `uvm_component_utils(uvma_axi_aw_sqr_c)
  • 代码介绍:定义 uvma_axi_aw_sqr_c 类,继承自 uvm_sequencer,并指定事务项类型为 uvma_axi_aw_item_c。使用 uvm_component_utils 宏将该类注册到 UVM 组件工厂。
  • 逻辑分析:通过继承和注册,使 uvma_axi_aw_sqr_c 成为 UVM 验证环境中的序列器组件,可在 UVM 环境中动态创建和管理。
4.3 构造函数
function new(string name = "uvma_axi_aw_sqr_c", uvm_component parent = null);

   super.new(name, parent);

   this.aw_req_export = new("aw_req_export", this);
   this.aw_req_fifo   = new("aw_req_fifo", this);

   void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));
   if (cfg == null) begin
      `uvm_fatal("CFG", "Configuration handle is null")
   end

   void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));
   if (cntxt == null) begin
      `uvm_fatal("CNTXT", "Context handle is null")
   end

endfunction
  • 代码介绍
    • super.new(name, parent);:调用父类 uvm_sequencer 的构造函数完成初始化。
    • this.aw_req_export = new("aw_req_export", this);:创建 aw_req_export 对象。
    • this.aw_req_fifo = new("aw_req_fifo", this);:创建 aw_req_fifo 对象。
    • void'(uvm_config_db#(uvma_axi_cfg_c)::get(this, "", "cfg", cfg));:从 UVM 配置数据库获取配置对象 cfg,若 cfg 为空则输出致命错误。
    • void'(uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", cntxt));:从 UVM 配置数据库获取上下文对象 cntxt,若 cntxt 为空则输出致命错误。
  • 逻辑分析:在构造函数中完成序列器对象的初始化,创建分析导出端口和 FIFO,并获取配置和上下文信息,确保序列器能在正确的环境下工作。
4.4 build_phase 函数
function void build_phase(uvm_phase phase);
   super.build_phase(phase);
endfunction
  • 代码介绍:调用父类的 build_phase 方法,确保父类在 build_phase 阶段的操作正常执行。
  • 逻辑分析:在 UVM 的 build_phase 阶段,由于当前类没有额外的构建操作,仅调用父类方法即可。
4.5 connect_phase 函数
function void connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   this.aw_req_export.connect(this.aw_req_fifo.analysis_export);       // Connect analysis export direct to fifo aw channels
endfunction
  • 代码介绍
    • super.connect_phase(phase);:调用父类的 connect_phase 方法。
    • this.aw_req_export.connect(this.aw_req_fifo.analysis_export);:将 aw_req_exportaw_req_fifoanalysis_export 连接。
  • 逻辑分析:在 UVM 的 connect_phase 阶段,完成分析导出端口和 FIFO 的连接,确保事务项能正确传递。

5. 总结

uvma_axi_aw_sqr.sv 文件实现了一个用于 AXI4 写地址通道的 UVM 序列器 uvma_axi_aw_sqr_c。该序列器通过 UVM 配置数据库获取配置和上下文信息,在构造函数中创建分析导出端口和 FIFO,并在 connect_phase 阶段将两者连接。其主要作用是管理和调度 AXI4 AW 通道的事务序列,同时提供了与其他组件交互的接口,有助于构建完整的 AXI4 验证环境。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值