Test-Bench methodolgy issue

3 posts / 0 new
Last post
vmdb
Offline
Academy Forum User
Joined: 11/15/2011
Posts: 4
Test-Bench methodolgy issue

Looking for the best & elegant way of handling the situation I have, in SVTB.

DUT has an input GMII interface and a CPU interface. Generator at GMII i/f generates packets in the routine say GMII.RUN(). So is CPU.RUN() does the initial configuration of DUT. There is ENV class, which has BUILD() routine. ENV.BUILD() builds GMII and CPU. ENV.RUN() forks GMII.RUN and CPU.RUN(). CPU.RUN() has functionality to monitor various registers at various points in time and varies from test to test.

GMII related code is in <>/behavioral/GMII, CPU is in <>/behavioral/CPU. test-case is in <>/test/basic/test_1.sv. In <>/test/basic directory, say there are abt 10 tests. How one can modify the CPU.RUN() from test-case which is embedded 2 levels below ? I do have the handle to ENV in my test-case.

mperyer
Offline
Verification Forum Moderator
Joined: 07/24/2010
Posts: 146
Re: Test-Bench methodolgy issue

I gather that you are not using OVM or UVM, although you seem to be using the same sort of structure.

One way to do this, is to make all the test cases extend a base class with a set of common methods. For the sake of argument lets call one of the methods run_cpu_test() and this is populated for each test with the code that you want to run. Then what you need to do is something like:

In the test_case:
class test_case extends test_case_base;

ENV env_h;

// Setting up a handle in the CPU for the test
function void setup_test;
env_h.CPU.test = this;
endfunction: setup_test

task run_cpu_test(virtual CPU_IF CPU);

// Stuff that does what ever with the CPU interface

endtask

endclass: test_case

In the CPU:

class CPU;

test_case_base test;
virtual CPU_IF CPU; //

task RUN();
test.run_cpu_test(CPU);
endtask: RUN

endclass

You don't describe how you order the creation of the classes and the control of the test case, but I assume that you'll see that there is a back-pointer to the test_case from the CPU.

vmdb
Offline
Academy Forum User
Joined: 11/15/2011
Posts: 4
Re: Test-Bench methodolgy issue

You are right, I 'm using PURE SVTB with UVM/VMM like hierarchy, with no OVM/UVM. I think I better give my code snippets (it's not complete, but gives an idea of TB), for a better understanding. It could be verbose, will do my best to get the point across.

In this TB architecture, wondering the elegant way of controlling the CPU.RUN() in "test-case" as CPU.RUN() will have to change from test-to-test.

Initially, I was thinking of controlling the handle of CPU in test-case. So that CPU_EXTEND.RUN() coded in test-case and assigning the CPU_EXTEND handle to CPU base handle, make CPU_EXTEND.RUN(), run in ENV.RUN()

Appreciate your inputs in context to the TB arch I have

// File: obj_Pkt.sv
class obj_Pkt;
    rand bit [47:0] da
    rand bit [47:0] sa
    rand bit [15:0] etherType
 
    extern function new();
   <some more functions>
 
    constraints default_constraints { constraints }
    constraints test_constraints;  // specified in TEST-CASE
endclass
// File: genGmii.sv
class genGmiiPkt
    protected cfg cfgPkt;
    function new(
        input cfg cfg
        input mailbox mbox
        input event ev)
    {
        this.cfgPkt = cfg
        <<some more functions>>
    }
 
    function run()
    {
        <statements>
    }
endclass
// File: cpu.sv
class cpu;
    cfg cfgPkt
    function new (input if_cpu cpuPorts,
                  input cfg cfg)
    {
        this.cfgPkt = cfg;
    }
 
    function write(input addr, data)
    {
    }
    byte function read (input addr)
    {
    }
    task run() // this task will change from test to test and should have
           // control to modify this routine
    {
        basic_config_dut();
    }
endclass
// File: cfg.sv
class cfg;
   protected obj_Pkt pktToGenerate; // this helps to create a diff
                                    // type of pkt in TEST-CASE, by extending
                                    // base class "obj_Pkt" and setting the
                                    // extended class to base class in generator
   protected rand maxPkt;
 
   function new()
   {
       this.pktToGenerate = new();
       this.seed = seed
   };
   function setPkt (input objPkt pkt)
   {
       this.pktToGenerate = pkt;
   }
   <some more functions>
   constraints default_constraints { constraints }
   constraints test_constraints;  // specified in TEST-CASE
endclass
//File: env.sv
class env
    cfg cfgPkt;
    genGmii genGmiiPkt
    cpu     cpuDrv
 
    function new()
    {
        this.cfgPkt = new();
    }
 
    function build()
    {
       genGmiiPkt = new();
       genGmiiPktDrv = new(); // not captured here, as it is not relevant
       cpuDrv = new(); 
    }
 
    function configure()
    {
       cfgPkt.randomize()
    }
 
    task reset()
    {
       cpudrv.reset();
       gmiiDrrv.reset()
    }
    function run()
    {
       fork
           genGmiPkt.run
           cpuDrv.run
      join
    }
endclass
// File: obj_TestBase
class obj_TestBase;
    env envPkt;
    virtual interface cpuPort
    virtual interface gmiiPort
    function new( input interface cpuPort,
                  input interface gmiiPort);
    function preRun()
    {
        envPkt.configure()
        envPkt.build();
    }
    function run()
    {
        envPkt.reset()
        envPkt.run()
    }
endclass
// File: test-case
 
program automatic test_DriverToDut ( <interfaces> );
obj_TestCase test;
 
initial
begin
    test = new ( <interfaces> );
    test.preRun();
    test.run();
end
 
class obj_TestCase extens obj_TestBase
 
    function new ( <all interfaces> ){
       super.new( <interfaces> );
    }
    virtual function preRun() {
       super.preRun()
    }
    virtual function run() {
       super.run();
    }
endclass
 
endprogram