// 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 driver for read ****/

`ifndef __UVMA_AXI_R_DRV_SV__
`define __UVMA_AXI_R_DRV_SV__

class uvma_axi_r_drv_c extends uvm_driver #(uvma_axi_r_item_c);

   `uvm_component_utils(uvma_axi_r_drv_c)

   uvma_axi_cntxt_c      cntxt;

   uvma_axi_r_item_c     r_item;

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

   extern function new(string name = "uvma_axi_r_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_r_drv_c

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

function void uvma_axi_r_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 cntxt class failed")
   end
   // uvm_config_db#(uvma_axi_cntxt_c)::set(this, "*", "cntxt", cntxt);
   this.slave_mp = this.cntxt.axi_vi.slave;
   r_item = uvma_axi_r_item_c::type_id::create("r_item");

endfunction

task uvma_axi_r_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_AR_DRV", $sformatf("Invalid reset_state: %0d", cntxt.reset_state))
      endcase
   end

endtask: run_phase

task uvma_axi_r_drv_c::drv_pre_reset();

   this.slave_mp.slv_axi_cb.r_id     <= 0;
   this.slave_mp.slv_axi_cb.r_resp   <= 0;
   this.slave_mp.slv_axi_cb.r_user   <= 0;
   this.slave_mp.slv_axi_cb.r_valid  <= 0;
   this.slave_mp.slv_axi_cb.r_user   <= 0;
   @(slave_mp.slv_axi_cb);

endtask: drv_pre_reset

task uvma_axi_r_drv_c::drv_in_reset();

   this.slave_mp.slv_axi_cb.r_id     <= 0;
   this.slave_mp.slv_axi_cb.r_resp   <= 0;
   this.slave_mp.slv_axi_cb.r_user   <= 0;
   this.slave_mp.slv_axi_cb.r_valid  <= 0;
   this.slave_mp.slv_axi_cb.r_user   <= 0;
   @(slave_mp.slv_axi_cb);

endtask: drv_in_reset

task uvma_axi_r_drv_c::drv_post_reset();

   seq_item_port.get_next_item(r_item);

      `uvm_info(get_type_name(),$sformatf("response, send data to DUT"), UVM_HIGH)
      this.slave_mp.slv_axi_cb.r_id    <= this.r_item.r_id;
      this.slave_mp.slv_axi_cb.r_resp  <= this.r_item.r_resp;
      this.slave_mp.slv_axi_cb.r_user  <= this.r_item.r_user;
      this.slave_mp.slv_axi_cb.r_last  <= this.r_item.r_last;
      this.slave_mp.slv_axi_cb.r_valid <= this.r_item.r_valid;
      this.slave_mp.slv_axi_cb.r_data <= this.r_item.r_data;
      @(slave_mp.slv_axi_cb);

   seq_item_port.item_done();

endtask: drv_post_reset

`endif
