1
\$\begingroup\$

I'm trying to understand a reason for the different results between the usage of the new() constructor in SystemVerilog.

I understood that if once the constructor allocates the memory into the object by new(), then I can use it in a class. I don't need it anymore after constructed by new(). But, I can't understand the result between commented them out and not commented out as below:

typedef enum {GOOD, BAD_ERR1, BAD_ERR2} pkt_type;

class driver;
  pkt_type pkt;
  
  task pkt_sender;
    std::randomize(pkt) with {pkt == GOOD;};
    modify_pkt;
  endtask
  
  virtual task modify_pkt; // callback method
   // $display("Good !! modify_pkt");
  endtask
endclass

// Error introduction via err_driver class where callback method modify_pkt is implemented.
class err_driver extends driver;
  task modify_pkt;
    $display("Injecting error pkt");
    std::randomize(pkt) with {pkt inside {BAD_ERR1, BAD_ERR2};};
  endtask
endclass

class env;
  bit inject_err;
  driver drv;
  err_driver drv_err;
  
  function new();
    drv = new();
    drv_err = new();
  endfunction
  
  task execute;
    if(inject_err) drv = drv_err;
    // Sending a packet
    drv.pkt_sender();
    $display("Sending packet = %s", drv.pkt.name());
  endtask
endclass

module callback_example();
  env env_o;
  initial begin
    // Sending GOOD packet
    env_o = new();
    env_o.inject_err = 0;
    repeat(3) env_o.execute;
    
    // Injecting an error
    //env_o = new(); //Test for new()
    env_o.inject_err = 1;
    repeat(3) env_o.execute;
    
    // Sending GOOD packet
    //env_o = new(); //Test for new()
    env_o.inject_err = 0;
    repeat(3) env_o.execute;
  end
endmodule

If the 2nd and 3rd env_o = new(); statements are commented out, then I expected results below:

Sending packet = GOOD
Sending packet = GOOD
Sending packet = GOOD
Injecting error pkt
Sending packet = BAD_ERR1
Injecting error pkt
Sending packet = BAD_ERR1
Injecting error pkt
Sending packet = BAD_ERR1
Sending packet = GOOD
Sending packet = GOOD
Sending packet = GOOD

But, I get these unexpected result:

Sending packet = GOOD
Sending packet = GOOD
Sending packet = GOOD
Injecting error pkt
Sending packet = BAD_ERR1
Injecting error pkt
Sending packet = BAD_ERR1
Injecting error pkt
Sending packet = BAD_ERR1
Injecting error pkt
Sending packet = BAD_ERR2
Injecting error pkt
Sending packet = BAD_ERR2
Injecting error pkt
Sending packet = BAD_ERR1

I thought that even if I commented them out, then the result of new() constructor is the same in SystemVerilog. But, it is not the same. Could you guide me why the results are different?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

When you call new on the env_o handle, it calls the new function in the env class. This constructs two different objects: drv and drv_err.

When you execute:

env_o.inject_err = 1;
repeat(3) env_o.execute;

the 1st time execute is called, it sets the drv object to be the same as drv_err. drv is permanently set to be drv_err. This is why you keep getting BAD instead of GOOD.

The way to make drv and drv_err different from each other again is to call env_o.new again.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.