Base-class casting to extended class handle in do_methods()

Currently I’m trying to understand about standard transaction class.
Especially, Overriding the do_copy() and do_compare() methods with uvm_object inputs.

Here example for do_copy of spi_seq_item class.


class spi_seq_item extends uvm_sequence_item;

// UVM Factory Registration Macro
//
`uvm_object_utils(spi_seq_item)

//------------------------------------------
// Data Members (Outputs rand, inputs non-rand)
//------------------------------------------
rand logic[127:0] spi_data;
rand bit[6:0] no_bits;
rand bit RX_NEG;

// Analysis members:
logic[127:0] nedge_mosi;
logic[127:0] pedge_mosi;
logic[127:0] nedge_miso;
logic[127:0] pedge_miso;
logic[7:0] cs;


//------------------------------------------
// Methods
//------------------------------------------

// Standard UVM Methods:
extern function new(string name = "spi_seq_item");
extern function void do_copy(uvm_object rhs);
extern function bit do_compare(uvm_object rhs, uvm_comparer comparer);
extern function string convert2string();
extern function void do_print(uvm_printer printer);
extern function void do_record(uvm_recorder recorder);

endclass:spi_seq_item

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

function void spi_seq_item::do_copy(uvm_object rhs);
  spi_seq_item rhs_;

  if(!$cast(rhs_, rhs)) begin
    `uvm_fatal("do_copy", "cast of rhs object failed")
  end
  super.do_copy(rhs);
  // Copy over data members:
  spi_data = rhs_.spi_data;
  no_bits = rhs_.no_bits;
  RX_NEG = rhs_.RX_NEG;
  nedge_mosi = rhs_.nedge_mosi;
  pedge_mosi = rhs_.pedge_mosi;
  nedge_miso = rhs_.nedge_miso;
  pedge_miso = rhs_.pedge_miso;
  cs = rhs_.cs;

endfunction:do_copy
...

I have some question about do_methods().

Q1. In do_copy() function, $cast(rhs_, rhs) implemented with rhs_, rhs.
rhs_ is spi_seq_item object. and rhs is uvm_object object.
rhs has no spi_seq_item’s properties. so $cast() was used.
In rhs_.spi_data, this spi_data is declared in spi_seq_item as rand logic[127:0] spi_data;
But I’m confused that where “spi_data” is declared from “spi_data = rhs_.spi_data;”?

In reply to UVM_LOVE:

It is implicitly

this.spi_data = rhs_.spi_data;
this.no_bits = rhs_.no_bits;
...