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

UVM环境介绍
HEAD commitID: 1f968ef

// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
// 
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     https://solderpad.org/licenses/
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


`ifndef __UVMA_INTERRUPT_IF_SV__
`define __UVMA_INTERRUPT_IF_SV__


/**
 * Encapsulates all signals and clocking of Interrupt interface. Used by
 * monitor and driver.
 */
interface uvma_interrupt_if
   (
   );

    // ---------------------------------------------------------------------------
    // Interface wires
    // ---------------------------------------------------------------------------
    wire        clk;
    wire        reset_n;
    wire [31:0] irq;
    wire        irq_ack;
    wire [4:0]  irq_id;

    // Used to time true interrupt entry with tracer instruction retirement
    wire        deferint;
    wire        ovp_cpu_state_stepi;

    // -------------------------------------------------------------------
    // Testbench control
    // ---------------------------------------------------------------------------
    // -------------------------------------------------------------------
    bit         is_active;  // Set to active drive the interrupt lines
    bit [31:0]  irq_drv;       // TB interrupt driver

    // -------------------------------------------------------------------
    // Begin module code
    // -------------------------------------------------------------------

    // Mux in driver to irq lines
    assign irq = is_active ? irq_drv : 1'b0;

    initial begin
        is_active = 1'b0;
        irq_drv = '0;
    end

   
    /**
        * Used by target DUT.
    */
    clocking dut_cb @(posedge clk or reset_n);
    endclocking : dut_cb
    
    /**
       * Used by uvma_interrupt_drv_c.
    */
    clocking drv_cb @(posedge clk or reset_n);
        input #1step irq_ack, 
                     irq_id;
        output       irq_drv;
    endclocking : drv_cb
   
    /**
        * Used by uvma_interrupt_mon_c.
    */
    clocking mon_cb @(posedge clk or reset_n);
        input #1step irq_ack, 
                     irq_id,
                     irq_drv;
    endclocking : mon_cb
      
    modport dut_mp    (clocking dut_cb);
    modport active_mp (clocking drv_cb);
    modport passive_mp(clocking mon_cb);

endinterface : uvma_interrupt_if


`endif // __UVMA_INTERRUPT_IF_SV__

lib/uvm_agents/uvma_interrupt/uvma_interrupt_if.sv

1. 简要介绍

该文件是中断验证环境的接口定义文件,主要功能包括:

  1. 定义中断接口的所有信号
  2. 提供时钟和复位信号
  3. 支持驱动和监控功能
  4. 包含测试平台控制逻辑

2. 接口介绍

2.1 接口信号定义
wire        clk;
wire        reset_n; 
wire [31:0] irq;
wire        irq_ack;
wire [4:0]  irq_id;
  • 代码介绍:定义核心接口信号
  • 信号说明
    • clk:时钟信号
    • reset_n:复位信号(低有效)
    • irq:32位中断请求信号
    • irq_ack:中断响应信号
    • irq_id:中断ID标识
2.2 测试控制信号
bit         is_active;
bit [31:0]  irq_drv;
  • 代码介绍:定义测试平台控制信号
  • 功能
    • is_active:控制是否主动驱动中断
    • irq_drv:测试平台驱动值

3. 参数介绍

3.1 时钟块定义
clocking dut_cb @(posedge clk or reset_n);
endclocking
  • 参数说明:DUT端时钟块
  • 特点:同步于时钟上升沿或复位信号
3.2 驱动时钟块
clocking drv_cb @(posedge clk or reset_n);
    input #1step irq_ack, irq_id;
    output       irq_drv;
endclocking
  • 参数说明:驱动器时钟块
  • 时序特性
    • 输入信号有1step延迟
    • 输出信号无延迟

4. 模块实现介绍

4.1 中断信号多路选择
assign irq = is_active ? irq_drv : 1'b0;
  • 代码分析
    1. 根据is_active选择驱动源
    2. 非主动模式时输出0
  • 关键点:确保安全默认值
4.2 初始值设置
initial begin
    is_active = 1'b0;
    irq_drv = '0;
end
  • 代码分析:初始化测试控制信号
  • 设计特点:防止未定义行为

5. 总结

该接口文件具有以下特点:

  1. 完整的中断信号定义
  2. 清晰的时钟域划分
  3. 安全的测试控制逻辑
  4. 灵活的驱动选择机制
  5. 标准化的接口实现

作为验证环境的基础组件,它为中断验证提供了可靠的接口定义,确保验证组件能够正确访问DUT信号。

// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
// 
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     https://solderpad.org/licenses/
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


`ifndef __UVMA_INTERRUPT_MON_TRN_LOGGER_SV__
`define __UVMA_INTERRUPT_MON_TRN_LOGGER_SV__


/**
 * Component writing Interrupt monitor transactions interrupt data to disk as plain text.
 */
class uvma_interrupt_mon_trn_logger_c extends uvml_logs_mon_trn_logger_c#(
   .T_TRN  (uvma_interrupt_mon_trn_c),
   .T_CFG  (uvma_interrupt_cfg_c    ),
   .T_CNTXT(uvma_interrupt_cntxt_c  )
);
   
   `uvm_component_utils(uvma_interrupt_mon_trn_logger_c)
   
   
   /**
    * Default constructor.
    */
   function new(string name="uvma_interrupt_mon_trn_logger", uvm_component parent=null);
      
      super.new(name, parent);
      
   endfunction : new
   
   /**
    * Writes contents of t to disk
    */
   virtual function void write(uvma_interrupt_mon_trn_c t);
      
      // TODO Implement uvma_interrupt_mon_trn_logger_c::write()
      // Ex: fwrite($sformatf(" %t | %08h | %02b | %04d | %02h |", $realtime(), t.a, t.b, t.c, t.d));
      
   endfunction : write
   
   /**
    * Writes log header to disk
    */
   virtual function void print_header();
      
      // TODO Implement uvma_interrupt_mon_trn_logger_c::print_header()
      // Ex: fwrite("----------------------------------------------");
      //     fwrite(" TIME | FIELD A | FIELD B | FIELD C | FIELD D ");
      //     fwrite("----------------------------------------------");
      
   endfunction : print_header
   
endclass : uvma_interrupt_mon_trn_logger_c


/**
 * Component writing INTERRUPT monitor transactions interrupt data to disk as JavaScript Object Notation (JSON).
 */
class uvma_interrupt_mon_trn_logger_json_c extends uvma_interrupt_mon_trn_logger_c;
   
   `uvm_component_utils(uvma_interrupt_mon_trn_logger_json_c)
   
   
   /**
    * Set file extension to '.json'.
    */
   function new(string name="uvma_interrupt_mon_trn_logger_json", uvm_component parent=null);
      
      super.new(name, parent);
      fextension = "json";
      
   endfunction : new
   
   /**
    * Writes contents of t to disk.
    */
   virtual function void write(uvma_interrupt_mon_trn_c t);
      
      // TODO Implement uvma_interrupt_mon_trn_logger_json_c::write()
      // Ex: fwrite({"{",
      //       $sformatf("\"time\":\"%0t\",", $realtime()),
      //       $sformatf("\"a\":%h,"        , t.a        ),
      //       $sformatf("\"b\":%b,"        , t.b        ),
      //       $sformatf("\"c\":%d,"        , t.c        ),
      //       $sformatf("\"d\":%h,"        , t.c        ),
      //     "},"});
      
   endfunction : write
   
   /**
    * Empty function.
    */
   virtual function void print_header();
      
      // Do nothing: JSON files do not use headers.
      
   endfunction : print_header
   
endclass : uvma_interrupt_mon_trn_logger_json_c


`endif // __UVMA_INTERRUPT_MON_TRN_LOGGER_SV__

lib/uvm_agents/uvma_interrupt/uvma_interrupt_mon_trn_logger.sv

1. 简要介绍

该文件是中断验证环境的监控事务日志记录器实现,主要功能包括:

  1. 记录中断监控事务到磁盘
  2. 支持文本和JSON两种格式
  3. 提供自定义日志头功能
  4. 实现事务格式转换

2. 接口介绍

2.1 基类定义
class uvma_interrupt_mon_trn_logger_c extends uvml_logs_mon_trn_logger_c#(
   .T_TRN(uvma_interrupt_mon_trn_c),
   .T_CFG(uvma_interrupt_cfg_c),
   .T_CNTXT(uvma_interrupt_cntxt_c)
);
  • 代码介绍:定义基础日志记录器类
  • 模板参数
    • T_TRN:监控事务类型
    • T_CFG:配置类型
    • T_CNTXT:上下文类型
2.2 JSON记录器
class uvma_interrupt_mon_trn_logger_json_c extends uvma_interrupt_mon_trn_logger_c;
   function new(string name="uvma_interrupt_mon_trn_logger_json", uvm_component parent=null);
      fextension = "json";
   endfunction
endclass
  • 代码介绍:定义JSON格式记录器
  • 特点:设置文件扩展名为.json

3. 参数介绍

3.1 构造函数
function new(string name="uvma_interrupt_mon_trn_logger", uvm_component parent=null);
   super.new(name, parent);
endfunction
  • 参数说明:初始化日志记录器
  • 关键点:调用父类构造函数

4. 模块实现介绍

4.1 事务写入函数
virtual function void write(uvma_interrupt_mon_trn_c t);
   // TODO Implement write logic
   // Ex: fwrite($sformatf(" %t | %08h |", $realtime(), t.a));
endfunction
  • 代码分析
    1. 预留事务写入实现
    2. 示例展示格式化输出
4.2 日志头函数
virtual function void print_header();
   // TODO Implement header
   // Ex: fwrite("---------------------");
endfunction
  • 代码分析:定义日志头格式
  • 设计特点:可自定义分隔线

5. 总结

该日志记录器组件具有以下特点:

  1. 标准化的UVM实现
  2. 灵活的输出格式支持
  3. 清晰的接口定义
  4. 可扩展的设计架构

作为验证环境的辅助组件,它为中断监控事务提供了可靠的记录能力,便于后续分析和调试。

// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
// 
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     https://solderpad.org/licenses/
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


`ifndef __UVMA_INTERRUPT_MON_TRN_SV__
`define __UVMA_INTERRUPT_MON_TRN_SV__


/**
 * Object rebuilt from the Interrupt monitor Analog of uvma_interrupt_seq_item_c.
 */
class uvma_interrupt_mon_trn_c extends uvml_trn_mon_trn_c;
   
   uvma_interrupt_mon_action_enum action;

   int unsigned  id;

   `uvm_object_utils_begin(uvma_interrupt_mon_trn_c)
      `uvm_field_enum(uvma_interrupt_mon_action_enum, action, UVM_DEFAULT)
      `uvm_field_int(id, UVM_DEFAULT)
   `uvm_object_utils_end
      
   /**
    * Default constructor.
    */
   extern function new(string name="uvma_interrupt_mon_trn");
   
endclass : uvma_interrupt_mon_trn_c


`pragma protect begin


function uvma_interrupt_mon_trn_c::new(string name="uvma_interrupt_mon_trn");
   
   super.new(name);
   
endfunction : new


`pragma protect end


`endif // __UVMA_INTERRUPT_MON_TRN_SV__

lib/uvm_agents/uvma_interrupt/uvma_interrupt_mon_trn.sv

1. 简要介绍

该文件是中断验证环境的监控事务类实现,主要功能包括:

  1. 封装中断监控事务数据
  2. 记录中断动作类型
  3. 存储中断ID标识
  4. 提供UVM自动化支持

2. 接口介绍

2.1 类定义
class uvma_interrupt_mon_trn_c extends uvml_trn_mon_trn_c;
  • 代码介绍:定义监控事务类,继承自基础监控事务类
  • 功能:作为中断监控数据的容器
2.2 UVM宏
`uvm_object_utils_begin(uvma_interrupt_mon_trn_c)
   `uvm_field_enum(uvma_interrupt_mon_action_enum, action, UVM_DEFAULT)
   `uvm_field_int(id, UVM_DEFAULT)
`uvm_object_utils_end
  • 代码介绍:注册UVM对象
  • 功能:支持自动化操作如复制、比较等

3. 参数介绍

3.1 动作类型
uvma_interrupt_mon_action_enum action;
  • 参数说明:记录中断动作类型
  • 数据类型:枚举类型
3.2 中断ID
int unsigned id;
  • 参数说明:存储中断标识符
  • 范围:无符号整型

4. 模块实现介绍

4.1 构造函数
function uvma_interrupt_mon_trn_c::new(string name="uvma_interrupt_mon_trn");
   super.new(name);
endfunction
  • 代码分析
    1. 调用父类构造函数
    2. 初始化事务对象
  • 关键点:确保正确继承父类行为

5. 总结

该监控事务类具有以下特点:

  1. 标准的UVM实现
  2. 简洁的数据封装
  3. 完善的自化支持
  4. 可扩展的设计架构

作为验证环境的基础数据结构,它为中断监控提供了可靠的数据表示能力,确保监控数据能够正确传递和处理。

//
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//


`ifndef __UVMA_INTERRUPT_MON_SV__
`define __UVMA_INTERRUPT_MON_SV__


/**
 * Component sampling transactions from a Clock & Reset virtual interface
 * (uvma_interrupt_if).
 */
class uvma_interrupt_mon_c extends uvm_monitor;

   // Objects
   uvma_interrupt_cfg_c    cfg;
   uvma_interrupt_cntxt_c  cntxt;

   // TLM
   // This analysis port will fire when the irq_ack_o is seen (core acknowledges the interrupt)
   uvm_analysis_port#(uvma_interrupt_mon_trn_c)  ap;

   // This analysis port will fire when the first instruction in the ISR is retired (i.e. the MTVEC location)
   uvm_analysis_port#(uvma_interrupt_mon_trn_c)  ap_iss;

   `uvm_component_utils_begin(uvma_interrupt_mon_c)
      `uvm_field_object(cfg  , UVM_DEFAULT)
      `uvm_field_object(cntxt, UVM_DEFAULT)
   `uvm_component_utils_end

   /**
    * Default constructor.
    */
   extern function new(string name="uvma_interrupt_mon", uvm_component parent=null);

   /**
    * 1. Ensures cfg & cntxt handles are not null.
    * 2. Builds ap.
    */
   extern virtual function void build_phase(uvm_phase phase);

   /**
    * Oversees monitoring via monitor_clk() and monitor_reset() tasks in parallel
    * forks.
    */
   extern virtual task run_phase(uvm_phase phase);

   /**
    * Publish a monitor transactin when interrupt is taken.
    */
   extern virtual task monitor_irq();

   /**
    * Publish a monitor transaction when interrupt is taken (delayed until the first instruction of the ISR is retired)
    */
   extern virtual task monitor_irq_iss();

endclass : uvma_interrupt_mon_c

function uvma_interrupt_mon_c::new(string name="uvma_interrupt_mon", uvm_component parent=null);

   super.new(name, parent);

endfunction : new


function void uvma_interrupt_mon_c::build_phase(uvm_phase phase);

   super.build_phase(phase);

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

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

   ap     = new("ap", this);
   ap_iss = new("ap_iss", this);

endfunction : build_phase

task uvma_interrupt_mon_c::run_phase(uvm_phase phase);

   super.run_phase(phase);

   if (cfg.enabled) begin
      while (1) begin
         wait (cntxt.vif.reset_n === 1'b0);
         wait (cntxt.vif.reset_n === 1'b1);

         fork begin
            // To maintain random thread stability launch iss thread always, but it will exit immediately if no iss configured
            fork
               monitor_irq();
               monitor_irq_iss();
            join_none

            wait (cntxt.vif.reset_n === 1'b0);

            disable fork;
         end
         join
      end
   end
endtask : run_phase

task uvma_interrupt_mon_c::monitor_irq();
   while(1) begin
      @(cntxt.vif.mon_cb);

      if (cntxt.vif.mon_cb.irq_ack) begin
         uvma_interrupt_mon_trn_c mon_trn = uvma_interrupt_mon_trn_c::type_id::create("mon_irq_trn");
         mon_trn.action = UVMA_INTERRUPT_MON_ACTION_IRQ;
         mon_trn.id = cntxt.vif.mon_cb.irq_id;
         ap.write(mon_trn);
      end
   end
endtask : monitor_irq

task uvma_interrupt_mon_c::monitor_irq_iss();
   if ($test$plusargs("USE_ISS")) begin
      while(1) begin
         @(cntxt.vif.mon_cb);

         if (cntxt.vif.mon_cb.irq_ack) begin
            uvma_interrupt_mon_trn_c mon_trn = uvma_interrupt_mon_trn_c::type_id::create("mon_irq_trn");
            mon_trn.action = UVMA_INTERRUPT_MON_ACTION_IRQ;
            mon_trn.id = cntxt.vif.mon_cb.irq_id;

            // Wait for the ISS to enter
            wait (cntxt.vif.deferint == 1'b0);
            wait (cntxt.vif.ovp_cpu_state_stepi == 1'b1);

            ap_iss.write(mon_trn);
         end
      end
   end
endtask : monitor_irq_iss


`endif // __UVMA_INTERRUPT_MON_SV__

lib/uvm_agents/uvma_interrupt/uvma_interrupt_mon.sv

1. 简要介绍

该文件是中断验证环境的监控器实现,主要功能包括:

  1. 采样中断接口信号
  2. 生成监控事务
  3. 通过TLM端口发送监控数据
  4. 支持指令集模拟器(ISS)集成

2. 接口介绍

2.1 类定义
class uvma_interrupt_mon_c extends uvm_monitor;
  • 代码介绍:定义监控器类,继承自UVM基础监控器类
  • 功能:作为标准UVM组件实现接口监控
2.2 TLM端口
uvm_analysis_port#(uvma_interrupt_mon_trn_c) ap;
uvm_analysis_port#(uvma_interrupt_mon_trn_c) ap_iss;
  • 代码介绍:定义两个分析端口
  • 功能
    • ap:用于中断响应监控
    • ap_iss:用于ISS集成监控

3. 参数介绍

3.1 配置对象
uvma_interrupt_cfg_c cfg;
  • 参数说明:存储验证配置
  • 获取方式:通过UVM配置数据库获取
3.2 上下文对象
uvma_interrupt_cntxt_c cntxt;
  • 参数说明:存储运行时状态
  • 包含内容:虚拟接口和事件触发器

4. 模块实现介绍

4.1 run_phase实现
task run_phase(uvm_phase phase);
   while (1) begin
      wait (cntxt.vif.reset_n === 1'b0);
      wait (cntxt.vif.reset_n === 1'b1);
      fork
         monitor_irq();
         monitor_irq_iss();
      join_none
   end
endtask
  • 代码分析
    1. 等待复位信号变化
    2. 并行启动监控任务
    3. 确保复位时终止监控
4.2 中断监控任务
task monitor_irq();
   if (cntxt.vif.mon_cb.irq_ack) begin
      uvma_interrupt_mon_trn_c mon_trn = uvma_interrupt_mon_trn_c::type_id::create("mon_irq_trn");
      mon_trn.action = UVMA_INTERRUPT_MON_ACTION_IRQ;
      mon_trn.id = cntxt.vif.mon_cb.irq_id;
      ap.write(mon_trn);
   end
endtask
  • 代码分析
    1. 检测中断响应信号
    2. 创建监控事务
    3. 通过端口发送事务

5. 总结

该监控器组件具有以下特点:

  1. 完整的UVM标准实现
  2. 双通道监控架构
  3. 可靠的复位处理机制
  4. 灵活的ISS集成支持
  5. 可扩展的设计架构

作为验证环境的关键组件,它为中断接口提供了全面的监控能力,确保验证过程能够正确捕获DUT行为。

//
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//


`ifndef __UVMA_INTERRUPT_SQR_SV__
`define __UVMA_INTERRUPT_SQR_SV__


/**
 * Component running Clock & Reset sequences extending uvma_interrupt_seq_base_c.
 * Provides sequence items for uvma_interrupt_drv_c.
 */
class uvma_interrupt_sqr_c extends uvm_sequencer#(
   .REQ(uvma_interrupt_seq_item_c),
   .RSP(uvma_interrupt_seq_item_c)
);

   // Objects
   uvma_interrupt_cfg_c    cfg;
   uvma_interrupt_cntxt_c  cntxt;


   `uvm_component_utils_begin(uvma_interrupt_sqr_c)
      `uvm_field_object(cfg  , UVM_DEFAULT)
      `uvm_field_object(cntxt, UVM_DEFAULT)
   `uvm_component_utils_end


   /**
    * Default constructor.
    */
   extern function new(string name="uvma_interrupt_sqr", uvm_component parent=null);

   /**
    * Ensures cfg & cntxt handles are not null
    */
   extern virtual function void build_phase(uvm_phase phase);

endclass : uvma_interrupt_sqr_c


function uvma_interrupt_sqr_c::new(string name="uvma_interrupt_sqr", uvm_component parent=null);

   super.new(name, parent);

endfunction : new


function void uvma_interrupt_sqr_c::build_phase(uvm_phase phase);

   super.build_phase(phase);

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

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

endfunction : build_phase


`endif // __UVMA_INTERRUPT_SQR_SV__

lib/uvm_agents/uvma_interrupt/uvma_interrupt_sqr.sv

1. 简要介绍

该文件是中断验证环境的序列器实现,主要功能包括:

  1. 运行中断序列
  2. 为驱动器提供序列项
  3. 管理配置和上下文
  4. 协调序列执行流程

2. 接口介绍

2.1 类定义
class uvma_interrupt_sqr_c extends uvm_sequencer#(
   .REQ(uvma_interrupt_seq_item_c),
   .RSP(uvma_interrupt_seq_item_c)
);
  • 代码介绍:定义序列器类,继承自参数化的UVM序列器基类
  • 模板参数
    • REQ:请求序列项类型
    • RSP:响应序列项类型

3. 参数介绍

3.1 配置对象
uvma_interrupt_cfg_c cfg;
  • 参数说明:存储验证配置
  • 获取方式:通过UVM配置数据库获取
3.2 上下文对象
uvma_interrupt_cntxt_c cntxt;
  • 参数说明:存储运行时状态
  • 包含内容:虚拟接口和事件触发器

4. 模块实现介绍

4.1 build_phase实现
function void build_phase(uvm_phase phase);
   void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
   if (cfg == null) begin
      `uvm_fatal("CFG", "Configuration handle is null")
   end
endfunction
  • 代码分析
    1. 从UVM数据库获取配置
    2. 空指针检查报fatal错误
  • 关键点:确保配置有效性

5. 总结

该序列器组件具有以下特点:

  1. 完整的UVM标准实现
  2. 清晰的序列管理接口
  3. 可靠的配置管理
  4. 可扩展的设计架构

作为验证环境的关键组件,它为中断序列执行提供了可靠的基础设施,确保验证激励能够正确生成和传递。

// Copyright 2021 OpenHW Group
// Copyright 2021 Silicon Labs, Inc.
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0

covergroup cg_executed_type(
    string name,
    instr_name_t instr_name
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_executed: coverpoint instr.name {
   
    bins EXECUTED = {
   [0:$]};
  }

endgroup : cg_executed_type

// There isn't a defined instruction type/format (yet in Zbb)
// The 2-source register format is mapped to R=type (from I spec)
// The 1-source register format is encompassed here
covergroup cg_zb_rstype(
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs_is_signed,
    bit rd_is_signed
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs: coverpoint instr.rs1;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cross_rd_rs: cross cp_rd, cp_rs {
   
    ignore_bins IGN_OFF = cross_rd_rs with (!reg_crosses_enabled);
  }

  cp_rs_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs_is_signed);
  }

  cp_rd_value: coverpoint instr.rd_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rd_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rd_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rd_is_signed);
  }

  `ISACOV_CP_BITWISE(cp_rs_toggle, instr.rs1_value, 1)
  `ISACOV_CP_BITWISE(cp_rd_toggle,  instr.rd_value,  1)

endgroup : cg_zb_rstype

covergroup cg_zb_itype_shift (
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs_is_signed,
    bit rd_is_signed
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs: coverpoint instr.rs1;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cross_rd_rs: cross cp_rd, cp_rs {
   
    ignore_bins IGN_OFF = cross_rd_rs with (!reg_crosses_enabled);
  }

  cp_rs_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs_is_signed);
  }

  cp_shamt: coverpoint instr.immi[4:0] {
   
    bins SHAMT[] = {
   [0:31]};
  }

  cp_rd_value: coverpoint instr.rd_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rd_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rd_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rd_is_signed);
  }

  `ISACOV_CP_BITWISE(cp_rs_toggle,  instr.rs1_value, 1)
  `ISACOV_CP_BITWISE(cp_rd_toggle,  instr.rd_value,  1)

endgroup : cg_zb_itype_shift

covergroup cg_zb_rstype_ext(
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs1_is_signed,
    bit rs2_is_signed,
    bit rd_is_signed
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs1: coverpoint instr.rs1;
  cp_rs2: coverpoint instr.rs2;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs1_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cp_rd_rs2_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs2);
  }

  cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
   
    ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
  }

  cp_rs1_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs1_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs1_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs1_is_signed);
  }

  cp_index: coverpoint instr.rs2[4:0] {
   
    bins INDEX[] = {
   [0:31]};
  }

  cp_rd_value: coverpoint instr.rd_value {
   
    bins ZERO = {
   0};
    bins ONE  = {
   1};
  }

  `ISACOV_CP_BITWISE(cp_rs1_toggle,  instr.rs1_value, 1)
  `ISACOV_CP_BITWISE(cp_rs2_toggle,  instr.rs2_value, 1)

endgroup : cg_zb_rstype_ext

covergroup cg_zb_itype_ext(
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs_is_signed,
    bit rd_is_signed
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs: coverpoint instr.rs1;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cross_rd_rs: cross cp_rd, cp_rs {
   
    ignore_bins IGN_OFF = cross_rd_rs with (!reg_crosses_enabled);
  }

  cp_rs_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs_is_signed);
  }

  cp_shift: coverpoint instr.immi[4:0] {
   
    bins SHIFT[] = {
   [0:31]};
  }

  cp_rd_value: coverpoint instr.rd_value {
   
    bins ZERO = {
   0};
    bins ONE  = {
   1};
  }

  `ISACOV_CP_BITWISE(cp_rs_toggle,  instr.rs1_value, 1)

endgroup : cg_zb_itype_ext

covergroup cg_rtype(
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs1_is_signed,
    bit rs2_is_signed,
    bit rd_is_signed
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs1: coverpoint instr.rs1;
  cp_rs2: coverpoint instr.rs2;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs1_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cp_rd_rs2_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS2_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs2);
  }

  cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
   
    ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
  }

  cp_rs1_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs1_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs1_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs1_is_signed);
  }

  cp_rs2_value: coverpoint instr.rs2_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs2_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs2_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs2_is_signed);
  }

  cross_rs1_rs2_value: cross cp_rs1_value, cp_rs2_value;

  cp_rd_value: coverpoint instr.rd_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rd_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rd_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rd_is_signed);
  }

  `ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
  `ISACOV_CP_BITWISE(cp_rs2_toggle, instr.rs2_value, 1)
  `ISACOV_CP_BITWISE(cp_rd_toggle,  instr.rd_value,  1)

endgroup : cg_rtype

covergroup cg_rtype_lr_w(
    string name,
    bit reg_hazards_enabled,
    bit rs1_is_signed,
    bit rd_is_signed,
    bit unaligned_access_amo_supported
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs1: coverpoint instr.rs1;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs1_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cp_rs1_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs1_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs1_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs1_is_signed);
  }

  cp_rd_value: coverpoint instr.rd_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rd_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rd_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rd_is_signed);
  }

  cp_align_word: coverpoint (instr.rvfi.mem_addr[1:0]) {
   
    ignore_bins IGN_OFF = {
   [0:$]} with (!unaligned_access_amo_supported);
    bins ALIGNED     = {
   0};
    bins UNALIGNED[] = {
   [1:3]};
  }

  `ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
  `ISACOV_CP_BITWISE(cp_rd_toggle,  instr.rd_value,  1)

endgroup : cg_rtype_lr_w

covergroup cg_rtype_sc_w (
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs1_is_signed,
    bit rs2_is_signed,
    bit unaligned_access_amo_supported
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs1: coverpoint instr.rs1;
  cp_rs2: coverpoint instr.rs2;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs1_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cp_rd_rs2_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS2_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs2);
  }

  cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
   
    ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
  }

  cp_rs1_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs1_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs1_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs1_is_signed);
  }

  cp_rs2_value: coverpoint instr.rs2_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs2_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs2_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs2_is_signed);
  }

  cross_rs1_rs2_value: cross cp_rs1_value, cp_rs2_value;

  cp_align_word: coverpoint (instr.rvfi.mem_addr[1:0]) {
   
    ignore_bins IGN_OFF = {
   [0:$]} with (!unaligned_access_amo_supported);
    bins ALIGNED     = {
   0};
    bins UNALIGNED[] = {
   [1:3]};
  }

  `ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
  `ISACOV_CP_BITWISE(cp_rs2_toggle, instr.rs2_value, 1)
  `ISACOV_CP_BITWISE_0_0(cp_rd_toggle, instr.rd_value,  1)
    // Note: "More specific failure codes might be defined in future versions or extensions to the ISA."

endgroup : cg_rtype_sc_w


covergroup cg_rtype_amo (
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs1_is_signed,
    bit rd_is_signed,
    bit unaligned_access_amo_supported
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs1: coverpoint instr.rs1;
  cp_rs2: coverpoint instr.rs2;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs1_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cp_rd_rs2_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS2_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs2);
  }

  cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
   
    ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
  }

  cp_rs1_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs1_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs1_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs1_is_signed);
  }

  cp_align_word: coverpoint (instr.rvfi.mem_addr[1:0]) {
   
    ignore_bins IGN_OFF = {
   [0:$]} with (!unaligned_access_amo_supported);
    bins ALIGNED     = {
   0};
    bins UNALIGNED[] = {
   [1:3]};
  }

  `ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
  `ISACOV_CP_BITWISE(cp_rs2_toggle, instr.rs2_value, 1)
  `ISACOV_CP_BITWISE(cp_rd_toggle,  instr.rd_value,  1)

endgroup : cg_rtype_amo

covergroup cg_rtype_slt(
    string name,
    bit reg_crosses_enabled,
    bit reg_hazards_enabled,
    bit rs1_is_signed,
    bit rs2_is_signed,
    bit rd_is_signed
) with function sample (
    uvma_isacov_instr_c instr
);
  option.per_instance = 1;
  option.name = name;

  cp_rs1: coverpoint instr.rs1;
  cp_rs2: coverpoint instr.rs2;
  cp_rd: coverpoint instr.rd;

  cp_rd_rs1_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS1_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs1);
  }

  cp_rd_rs2_hazard: coverpoint instr.rd {
   
    ignore_bins IGN_RS2_HAZARD_OFF = {
   [0:$]} with (!reg_hazards_enabled);
    bins RD[] = {
   [0:31]} iff (instr.rd == instr.rs2);
  }

  cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
   
    ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
  }

  cp_rs1_value: coverpoint instr.rs1_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs1_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs1_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs1_is_signed);
  }

  cp_rs2_value: coverpoint instr.rs2_value_type {
   
    ignore_bins POS_OFF = {
   POSITIVE} with (!rs2_is_signed);
    ignore_bins NEG_OFF = {
   NEGATIVE} with (!rs2_is_signed);
    ignore_bins NON_ZERO_OFF = {
   NON_ZERO} with (rs2_is_signed);
  }

  cross_rs1_rs2_value: cross cp_rs1_value, cp_rs2_value;

  cp_rd_value: coverpoint instr.rd_value {
   
    bins SLT[] = {
   [0:1]};
  }

  `ISACOV_CP_BITWISE(cp_rs1_toggle<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值