Chapter8 Advanced OOP and Guidelines
1Always declare routines inside a class as virtual so that they
can be redefined in an extended class. This applies to all tasks
and functions, except the new function, which is called when
the object is constructed, so there is no way to extend it.
System
verilog always calls the new function based on the
handle’s type.
2 If your base class constructor has
any arguments, the extend constructor must have a constructor and must call the base’s constructor on its first line.
3 OOP rules say that if you have a handle of the base type (Transaction), it can also point to an object of an extended type (BadTr). This is because the handle tr can only reference the variables src, dst, crc, and data, and the routine calc_crc.
So you can send BadTr objects into the driver without changing it.
When the driver calls tr.calc_crc, SystemVerilog looks at the type of
object stored in tr, because the task was declared as virtual. If the object is of
type Transaction, SystemVerilog calls Transaction::calc_crc. If it is
of type BadTr, SystemVerilog calls BadTr::calc_crc.
//it's true that i don't need to rewrite my code. but if i want to access the unique variable in the extended class, how shall i do??Maybe you shouldn't access that variable, because it should be hidden.
4
class Generator;
mailbox gen2drv;
Transaction blueprint;
function new(mailbox gen2drv);
this.gen2drv = gen2drv;
endfunction
function build;
blueprint = new;
endfunction
task run;
Transaction tr;
forever begin
assert(blueprint.randomize);
tr = blueprint.copy; // *
see below// this is the key point, you copy the father object to the son objectsgen2drv.put(tr); // Send to driver
end
endtask
endclass
// Testbench environment class
class Environment;
Generator gen;
Driver drv;
mailbox gen2drv;
function new;
gen = new(gen2drv);
drv = new(gen2drv);
endfunction
function build;
gen.build;
drv.build;
endfunction
task run;
fork
gen.run;
drv.run;
join_none
endtask
task wrapup;
gen.wrapup;
drv.wrapup;
endtask
endclass
program automatic test;
Environment env;
initial begin
env = new; // Construct the environment
env.build; // Build testbench objects
env.run; // Run the test
env.wrap_up; // Clean up afterwards
end
endprogram
program automatic test;
Environment env;
initial begin
env = new;
env.build; // Construct a blueprint
begin
BadTr bad; // Create a bad transaction
bad = new; // Replace blueprint with
env.drv.tr = bad; // the "bad" one
end
env.run; // Run the test
env.wrap_up; // Clean up afterwards
end
endprogram
Note how all the references to
BadTr are in this one
file, so you don’t have to change the
Environment or
Generator classes