// 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 B channel driver  ****/

`ifndef __UVMA_AXI_B_DRV_SV__
`define __UVMA_AXI_B_DRV_SV__

class uvma_axi_b_drv_c extends uvm_driver #(uvma_axi_b_item_c);

   `uvm_component_utils(uvma_axi_b_drv_c)

   uvma_axi_cntxt_c     cntxt;

   uvma_axi_b_item_c    b_item;

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

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

   function void build_phase(uvm_phase phase);

      super.build_phase(phase);

      if(!uvm_config_db#(uvma_axi_cntxt_c)::get(this, "", "cntxt", this.cntxt)) begin
         `uvm_fatal("build_phase", "driver cntxt class failed")
      end

      this.slave_mp = this.cntxt.axi_vi.slave;
      b_item = uvma_axi_b_item_c::type_id::create("b_item", this);

   endfunction

   task 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 drv_pre_reset();

      this.slave_mp.slv_axi_cb.b_id     <= 0;
      this.slave_mp.slv_axi_cb.b_resp   <= 0;
      this.slave_mp.slv_axi_cb.b_user   <= 0;
      this.slave_mp.slv_axi_cb.b_valid  <= 0;
      this.slave_mp.slv_axi_cb.b_user   <= 0;
      @(slave_mp.slv_axi_cb);

   endtask: drv_pre_reset

   task drv_in_reset();

      this.slave_mp.slv_axi_cb.b_id     <= 0;
      this.slave_mp.slv_axi_cb.b_resp   <= 0;
      this.slave_mp.slv_axi_cb.b_user   <= 0;
      this.slave_mp.slv_axi_cb.b_valid  <= 0;
      this.slave_mp.slv_axi_cb.b_user   <= 0;
      @(slave_mp.slv_axi_cb);

   endtask: drv_in_reset

   task drv_post_reset();

      seq_item_port.get_next_item(b_item);

         `uvm_info(get_type_name(),$sformatf("response, send resp to DUT"), UVM_HIGH)

         this.slave_mp.slv_axi_cb.b_id    <= this.b_item.b_id;
         this.slave_mp.slv_axi_cb.b_resp  <= this.b_item.b_resp;
         this.slave_mp.slv_axi_cb.b_user  <= this.b_item.b_user;
         this.slave_mp.slv_axi_cb.b_user  <= this.b_item.b_user;
         this.slave_mp.slv_axi_cb.b_valid <= this.b_item.b_valid;
         @(slave_mp.slv_axi_cb);

      seq_item_port.item_done();

   endtask: drv_post_reset

endclass

`endif
