Injecting an extended transaction into testbench

i tried to test injecting an extended transaction into a testbench, Chris Spear said in SV for teshbench 2nd. edition chapter 8. that i can do that by “a standalone begin…end block is used in the middle of the initial block”(in the test program). i didnot understand that way beside it is not working in the below code, the results still refer to the Transaction not the BadTr. please inform me what i missed. the target is to use the extended class badtr instead of transaction without changing in generator and environment.

code:
class Transaction;
rand bit [31:0] src, dst, data[8]; // Random variables
bit [31:0] crc; // Calculated variable
virtual function void calc_crc;
crc = src ^ dst ^ data.xor;
endfunction
virtual function void display(input string prefix=“”);
$display(“%sTr: src=%h, dst=%h, crc=%h”, prefix, src, dst, crc);
endfunction
function Transaction copy();
copy = new();
copy.src = src;
copy.dst = dst;
copy.data = data;
copy.crc = crc;
endfunction
endclass

class BadTr extends Transaction;
rand bit bad_crc;
virtual function void calc_crc;
crc = src ^ dst ^ data.xor;
if (bad_crc) crc = ~crc; // Corrupt the CRC bits
endfunction
virtual function void display(input string prefix=“”);
$write("%sBadTr: bad_crc=%b, ", prefix, bad_crc);
super.display(prefix);
endfunction
function BadTr copy();
copy = new();
copy.src = src;
copy.dst = dst;
copy.data = data;
copy.crc = crc;
copy.bad_crc = bad_crc;
endfunction
endclass

// Generator class that uses Transaction objects
// First attempt… too limited
class Generator;
mailbox gen2drv;
Transaction blueprint;
function new(input mailbox gen2drv);
this.gen2drv = gen2drv; // this-> class-level var
blueprint = new();
endfunction
task run();
Transaction tr;
repeat(5) begin
//tr = new(); // Construct transaction
assert(blueprint.randomize()); // Randomize it
tr = blueprint.copy();
tr.display("gen put ");
gen2drv.put(tr); // Send to driver
end
endtask
endclass

class Driver;
mailbox gen2drv;
function new(input mailbox gen2drv);
this.gen2drv = gen2drv;
endfunction
task run();
Transaction tr; // Handle to a Transaction object or
// an class derived from Transaction
repeat(5) begin
gen2drv.get(tr); // Get transaction from generator
tr.calc_crc(); // Process the transation
tr.display("drv get "); // Send transaction
//…
end
endtask
endclass

// Testbench environment class
class Environment;
Generator gen;
Driver drv;
mailbox gen2drv;
function void build(); // Build the environment by
gen2drv = new(); // constructing the mailbox,
gen = new(gen2drv); // generator,
drv = new(gen2drv); // and driver
endfunction
task run();
fork
gen.run();
drv.run();
join
endtask
task wrap_up();
// Empty for now - call scoreboard for report
endtask
endclass

program automatic test;
Environment env;
initial begin
env = new(); // Construct the environment
env.build(); // Build testbench objects
begin
automatic BadTr bad =new();
env.gen.blueprint = bad;
end
env.run(); // Run the test
env.wrap_up; // Clean up afterwards
end
endprogram

In reply to moustafaali:

i got it, i just forget to define the copy function as virtual.