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

UVM环境介绍
HEAD commitID: 1f968ef

1. core-v-verif/lib/uvm_agents/uvma_axi5/src/seq/uvma_axi_seq_lib.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) – sub-contractor MU-Electronics for Thales group


`ifndef __UVMA_AXI_SEQ_LIB_SV__
`define __UVMA_AXI_SEQ_LIB_SV__

`include "uvma_axi_base_seq.sv"
`include "uvma_axi_slv_seq.sv"

`include "uvma_axi_fw_preload_seq.sv"
`include "uvma_axi_vseq.sv"

/**
 * Object holding sequence library for Open Bus Interface agent.
 */
class uvma_axi_seq_lib_c extends uvm_sequence_library;

   `uvm_object_utils          (uvma_axi_seq_lib_c)
   `uvm_sequence_library_utils(uvma_axi_seq_lib_c)

   /**
    * Initializes sequence library
    */
   extern function new(string name="uvma_axi_seq_lib");
   
endclass : uvma_axi_seq_lib_c


function uvma_axi_seq_lib_c::new(string name="uvma_axi_seq_lib");

   super.new(name);
   init_sequence_library();

endfunction : new

`endif // __UVMA_AXI_SEQ_LIB_SV__


1. 简要介绍

当前文件定义了一个 SystemVerilog 类 uvma_axi_seq_lib_c,它继承自 uvm_sequence_library。该类的主要作用是管理和组织与 AXI 代理相关的序列库,为 AXI 协议验证提供一系列可复用的序列。

2. 接口介绍

此文件定义的是类,并非硬件模块,所以没有传统意义上的输入输出接口。不过,作为 UVM 序列库类,它通过 UVM 框架与其他组件交互。主要通过 UVM 的注册机制和序列启动方法与序列器、环境等组件进行交互。

3. 参数介绍

该类没有显式定义的参数。不过,它继承了 uvm_sequence_library 的特性,在创建对象时可以传入一个字符串参数 name,用于标识该序列库对象。默认值为 "uvma_axi_seq_lib"

extern function new(string name="uvma_axi_seq_lib");
  • name:序列库对象的名称,方便在 UVM 调试和日志输出中识别该对象。

4. 模块实现介绍

4.1 条件编译保护
`ifndef __UVMA_AXI_SEQ_LIB_SV__
`define __UVMA_AXI_SEQ_LIB_SV__
  • 代码介绍:使用 ifndefdefine 进行条件编译。如果 __UVMA_AXI_SEQ_LIB_SV__ 宏未定义,则定义该宏,后续代码会被编译;若已定义,则跳过后续代码。
  • 逻辑分析:防止文件被重复包含,避免类的重复定义。
4.2 包含其他文件
`include "uvma_axi_base_seq.sv"
`include "uvma_axi_slv_seq.sv"
`include "uvma_axi_fw_preload_seq.sv"
`include "uvma_axi_vseq.sv"
  • 代码介绍:使用 include 指令将其他与 AXI 序列相关的文件包含进来,使得这些文件中定义的类和类型可以在当前文件中使用。
  • 逻辑分析:将不同功能的序列文件整合到当前文件中,方便统一管理和使用。
4.3 类定义与注册
class uvma_axi_seq_lib_c extends uvm_sequence_library;
   `uvm_object_utils          (uvma_axi_seq_lib_c)
   `uvm_sequence_library_utils(uvma_axi_seq_lib_c)
  • 代码介绍
    • class uvma_axi_seq_lib_c extends uvm_sequence_library;:定义 uvma_axi_seq_lib_c 类,继承自 uvm_sequence_library,表明这是一个 UVM 序列库类。
    • uvm_object_utils (uvma_axi_seq_lib_c)`:将该类注册到 UVM 对象工厂,允许在 UVM 环境中动态创建该类的对象。
    • uvm_sequence_library_utils(uvma_axi_seq_lib_c)`:注册该序列库,使得 UVM 能够识别并使用该序列库中的序列。
  • 逻辑分析:通过继承和注册,让 uvma_axi_seq_lib_c 类成为一个标准的 UVM 序列库类,可在 UVM 验证环境中使用。
4.4 构造函数声明与实现
// 声明
extern function new(string name="uvma_axi_seq_lib");

// 实现
function uvma_axi_seq_lib_c::new(string name="uvma_axi_seq_lib");
   super.new(name);
   init_sequence_library();
endfunction : new
  • 代码介绍
    • extern function new(string name="uvma_axi_seq_lib");:在类定义中声明构造函数,extern 表示函数体在类外部实现。
    • function uvma_axi_seq_lib_c::new(string name="uvma_axi_seq_lib");:构造函数的实现部分。
    • super.new(name);:调用父类 uvm_sequence_library 的构造函数,完成父类部分的初始化。
    • init_sequence_library();:调用 init_sequence_library 方法初始化序列库,该方法应该是 uvm_sequence_library 类提供的,用于初始化序列库中的序列列表。
  • 逻辑分析:构造函数负责初始化序列库对象,先完成父类的初始化,再初始化序列库本身。
4.5 条件编译结束
`endif // __UVMA_AXI_SEQ_LIB_SV__
  • 代码介绍:结束 ifndef 条件编译块。
  • 逻辑分析:标志着条件编译部分的结束。

5. 总结

该文件定义了一个 UVM 序列库类 uvma_axi_seq_lib_c,用于管理和组织 AXI 协议验证所需的序列。通过条件编译防止文件重复包含,使用 include 指令整合相关序列文件,借助 UVM 宏将类注册到对象工厂和序列库系统。构造函数完成对象的初始化工作。这个序列库类为 AXI 协议的验证提供了一个可复用的框架,方便验证人员在 UVM 环境中管理和使用各种 AXI 序列。

2. core-v-verif/lib/uvm_agents/uvma_axi5/src/seq/uvma_axi_slv_seq.sv


// Copyright 2023 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) – sub-contractor MU-Electronics for Thales group


//=============================================================================
// Description: Sequence for agent axi_ar
//=============================================================================

`ifndef UVMA_AXI_SLV_SEQ_SV
`define UVMA_AXI_SLV_SEQ_SV

/**
 * Virtual sequence implementing the CVA6 memory iterface virtual peripheral.
 */
class uvma_axi_slv_seq_c extends uvma_axi_base_seq_c;

   uvma_axi_synchronizer_c  synchronizer;

   int ar_seq_status = 0;
   int aw_seq_status = 0;
   int w_seq_status = 0;

   int last_ar_ready_delay = 0;
   int last_aw_ready_delay = 0;
   int last_w_ready_delay = 0;

   `uvm_object_utils_begin(uvma_axi_slv_seq_c)
   `uvm_object_utils_end

   extern function new(string name = "uvma_axi_slv_seq_c");

   /**
    * Assigns synchronizer handles from p_sequencer.
    */
   extern virtual task pre_body();

   /**
    * TODO Describe uvma_axi_slv_base_seq_c::body()
    */
   extern task body();

   /**
    * TODO Describe uvma_axi_slv_seq_c::do_response()
    */
   extern virtual task do_response();

   /**
    * Convenience function to encapsulate the axi request in the synchronizer
    */
   extern virtual task trs_registration(uvma_axi_transaction_c mon_req);

   /**
    * TODO Describe uvma_axi_slv_seq_c::do_mem_operation()
    */
   extern virtual task do_mem_operation(uvma_axi_transaction_c mon_req);

   /**
    * Method to prepare the write response in the B channel
    */
   extern virtual task prepare_w_resp();

   /**
    * Method to prepare the read response in the R channel
    */
   extern virtual task prepare_r_resp();

   /**
    * Method to prepare the read response in the R channel
    */
   extern virtual task prepare_ar_resp();

   /**
    * Method to prepare the read response in the R channel
    */
   extern virtual task prepare_aw_resp();

   /**
    * Method to prepare the read response in the R channel
    */
   extern virtual task prepare_wdata_resp();

endclass : uvma_axi_slv_seq_c


function uvma_axi_slv_seq_c::new(string name = "uvma_axi_slv_seq_c");

   super.new(name);

endfunction : new

task uvma_axi_slv_seq_c::pre_body();

   synchronizer   = p_sequencer.synchronizer;

endtask : pre_body

task uvma_axi_slv_seq_c::body();

   uvma_axi_transaction_c   ar_mon_trn;
   uvma_axi_transaction_c   aw_mon_trn;
   uvma_axi_transaction_c   w_mon_trn;
   uvma_axi_transaction_c   mon_trn;

   ar_mon_trn = uvma_axi_transaction_c::type_id::create("ar_mon_trn");
   aw_mon_trn = uvma_axi_transaction_c::type_id::create("aw_mon_trn");
   w_mon_trn  = uvma_axi_transaction_c::type_id::create("w_mon_trn");
   mon_trn    = uvma_axi_transaction_c::type_id::create("mon_trn");

   // Wait for the monitor to send us the mstr's "req" with an access request
   fork
      begin
         forever begin
            p_sequencer.ar_mon2seq_fifo_port.get(ar_mon_trn);
            do_mem_operation(ar_mon_trn);
         end
      end

      begin
         forever begin
            p_sequencer.aw_mon2seq_fifo_port.get(aw_mon_trn);
            do_mem_operation(aw_mon_trn);
         end
      end

      begin
         forever begin
            p_sequencer.w_mon2seq_fifo_port.get(w_mon_trn);
            do_mem_operation(w_mon_trn);
         end
      end

      begin
         forever begin
            p_sequencer.mon2seq_fifo_port.get(mon_trn);
            do_response();
         end
      end
   join_none

endtask : body

task uvma_axi_slv_seq_c::do_response();

   if(cntxt.reset_state == UVMA_AXI_RESET_STATE_POST_RESET) begin
      prepare_w_resp();
      prepare_r_resp();
      prepare_ar_resp();
      prepare_aw_resp();
      prepare_wdata_resp();
   end else begin
      synchronizer.w_trs_queue.delete();
      synchronizer.r_trs_queue.delete();
      synchronizer.w_trs_item_bp.delete();
      synchronizer.w_trs_class.delete();
      synchronizer.w_finished_trs_id.delete();
      synchronizer.r_finished_trs_id.delete();
      synchronizer.exclusive_r_access.delete();
      synchronizer.exclusive_w_access.delete();

      synchronizer.outstanding_read_call_times  = 0;
      synchronizer.outstanding_write_call_times = 0;

      ar_seq_status = 0;
      aw_seq_status = 0;
      w_seq_status = 0;

      last_ar_ready_delay = 0;
      last_aw_ready_delay = 0;
      last_w_ready_delay = 0;
   end

endtask : do_response

task uvma_axi_slv_seq_c::do_mem_operation(uvma_axi_transaction_c mon_req);

   if(cntxt.reset_state == UVMA_AXI_RESET_STATE_POST_RESET) begin
      `uvm_info(get_type_name(), $sformatf("TRX TYPE = %s", mon_req.m_txn_type), UVM_HIGH)
      trs_registration(mon_req);
   end

endtask : do_mem_operation

task uvma_axi_slv_seq_c::trs_registration(uvma_axi_transaction_c mon_req);

   if(mon_req.m_txn_type == UVMA_AXI_WRITE_ADD_REQ || mon_req.m_txn_type == UVMA_AXI_WRITE_DATA_REQ) begin
      `uvm_info(get_type_name(), $sformatf("Write trx registration "), UVM_HIGH)
      synchronizer.add_w_trs(mon_req);
   end else if(mon_req.m_txn_type == UVMA_AXI_READ_REQ) begin
      `uvm_info(get_type_name(), $sformatf("Read trx registration "), UVM_HIGH)
      synchronizer.add_r_trs(mon_req);
   end

endtask : trs_registration

task uvma_axi_slv_seq_c::prepare_w_resp();

   uvma_axi_transaction_c w_slv_rsp;
   int exc_resp = 0;
   int w_selected_id;

   w_selected_id = synchronizer.w_select_id(synchronizer.w_finished_trs_id);

   if(w_selected_id != -1) begin
      `uvm_create(w_slv_rsp)

      w_slv_rsp = new synchronizer.w_trs_queue[w_selected_id][0];
      `uvm_info(get_type_name(), $sformatf("Write Response Transaction is created"), UVM_HIGH)

      exc_resp = synchronizer.check_exclusive_resp(w_selected_id);
      if(exc_resp == 1) w_slv_rsp.m_resp.push_back(1)   ;
      else w_slv_rsp.m_resp.push_back(0);

      w_slv_rsp.m_id         = w_selected_id;
      w_slv_rsp.m_user       = 0;
      w_slv_rsp.m_txn_type   = UVMA_AXI_WRITE_RSP;

      w_slv_rsp.set_config(cfg.txn_config) ;

      if(!cfg.disable_trs_randomization) begin
         w_slv_rsp.m_id.rand_mode(0);
         w_slv_rsp.m_txn_type.rand_mode(0);
         w_slv_rsp.m_axi_version.rand_mode(0);
         w_slv_rsp.m_lite.rand_mode(0);
         w_slv_rsp.m_err.rand_mode(0);
//         w_slv_rsp.lower_byte_lane.rand_mode(0);
//         w_slv_rsp.upper_byte_lane.rand_mode(0);

         if(!cfg.resp_randomization_enabled) begin
            w_slv_rsp.m_resp.rand_mode(0);
         end
         if(!cfg.user_randomization_enabled) begin
            w_slv_rsp.m_user.rand_mode(0);
         end

         if(!cfg.rand_channel_delay_enabled) begin
            w_slv_rsp.m_delay_cycle_chan_X.rand_mode(0);
            w_slv_rsp.m_delay_cycle_chan_X = 0;
         end

         // Randomization of the transaction
         w_slv_rsp.randomize();
      end else begin
         w_slv_rsp.m_delay_cycle_chan_X = 0;
      end

      `uvm_info(get_type_name(), $sformatf("FINICH WRITE TRANSACTION"), UVM_HIGH)
      synchronizer.write_burst_complete(w_selected_id);

      w_slv_rsp.set_sequencer(p_sequencer);

      `uvm_send(w_slv_rsp)
   end

endtask : prepare_w_resp

task uvma_axi_slv_seq_c::prepare_r_resp();

   uvma_axi_transaction_c r_slv_rsp;
   int r_selected_id = -1;

   synchronizer.r_select_id(synchronizer.r_finished_trs_id, r_selected_id);

   if(r_selected_id != -1) begin
      `uvm_create(r_slv_rsp)

      foreach(synchronizer.r_trs_queue[r_selected_id][i]) begin
         if(synchronizer.r_trs_queue[r_selected_id][i].m_trs_status == WAITING_RESP) begin
            r_slv_rsp = new synchronizer.r_trs_queue[r_selected_id][i];
            break;
         end
      end

      if(r_slv_rsp.m_last[0]) synchronizer.read_burst_complete(r_selected_id);
      else synchronizer.read_data_complete(r_selected_id);

      r_slv_rsp.set_config(cfg.txn_config) ;
      r_slv_rsp.m_txn_type = UVMA_AXI_READ_RSP;

      if(!cfg.disable_trs_randomization) begin
         r_slv_rsp.m_id.rand_mode(0);
         r_slv_rsp.m_txn_type.rand_mode(0);
         r_slv_rsp.m_axi_version.rand_mode(0);
         r_slv_rsp.m_lite.rand_mode(0);
         r_slv_rsp.m_err.rand_mode(0);
//         r_slv_rsp.lower_byte_lane.rand_mode(0);
//         r_slv_rsp.upper_byte_lane.rand_mode(0);
         if(!cfg.resp_randomization_enabled == 1) begin
            r_slv_rsp.m_resp.rand_mode(0);
         end
         if(!cfg.user_randomization_enabled == 1) begin
            r_slv_rsp.m_x_user.rand_mode(0);
         end
         if(!cfg.rand_channel_delay_enabled) begin
            r_slv_rsp.m_delay_cycle_flits.rand_mode(0);
            for(int i = 0; i <= r_slv_rsp.m_len; i++)
               r_slv_rsp.m_delay_cycle_flits.push_back(0);
         end
         r_slv_rsp.m_last.rand_mode(0);
         r_slv_rsp.m_data.rand_mode(0);
         r_slv_rsp.c_last.constraint_mode(0);

	     // Randomization of the transaction
         r_slv_rsp.randomize();
      end else begin
         for(int i = 0; i <= r_slv_rsp.m_len; i++)
            r_slv_rsp.m_delay_cycle_flits.push_back(0);
      end
      r_slv_rsp.set_sequencer(p_sequencer);

      `uvm_send(r_slv_rsp)
   end

endtask : prepare_r_resp


task uvma_axi_slv_seq_c::prepare_ar_resp();
   uvma_axi_transaction_c ar_slv_rsp;
   `uvm_info(get_type_name(), $sformatf("ARREADY Transaction Response Started"), UVM_HIGH)
   if(ar_seq_status == last_ar_ready_delay) begin
      `uvm_create(ar_slv_rsp)

      ar_seq_status = -1;

      ar_slv_rsp.set_config(cfg.txn_config) ;
      ar_slv_rsp.m_txn_type = UVMA_AXI_READ_REQ;
      ar_slv_rsp.m_txn_type.rand_mode(0);

      // Randomization of the transaction
      if(cfg.rand_channel_delay_enabled) ar_slv_rsp.randomize();
      else ar_slv_rsp.ready_delay_cycle_chan_ax = 0;

      ar_slv_rsp.set_sequencer(p_sequencer);
      last_ar_ready_delay = ar_slv_rsp.ready_delay_cycle_chan_ax;

      `uvm_send(ar_slv_rsp)
   end
   ar_seq_status++;

endtask : prepare_ar_resp

task uvma_axi_slv_seq_c::prepare_aw_resp();
   uvma_axi_transaction_c aw_slv_rsp;

   `uvm_info(get_type_name(), $sformatf("AWREADY Transaction Response Started"), UVM_HIGH)
   if(aw_seq_status == last_aw_ready_delay) begin
      `uvm_create(aw_slv_rsp)

      aw_seq_status = -1;

      aw_slv_rsp.set_config(cfg.txn_config) ;
      aw_slv_rsp.m_txn_type = UVMA_AXI_WRITE_ADD_REQ;
      aw_slv_rsp.m_txn_type.rand_mode(0);

      // Randomization of the transaction
      if(cfg.rand_channel_delay_enabled) aw_slv_rsp.randomize();
      else aw_slv_rsp.ready_delay_cycle_chan_ax = 0;

      aw_slv_rsp.set_sequencer(p_sequencer);
      last_aw_ready_delay = aw_slv_rsp.ready_delay_cycle_chan_ax;

      `uvm_send(aw_slv_rsp)
   end
   aw_seq_status++;

endtask : prepare_aw_resp

task uvma_axi_slv_seq_c::prepare_wdata_resp();

   uvma_axi_transaction_c wdata_slv_rsp;
   `uvm_info</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值