Alu Instruction Randomization to maximize Hazards

Consider a processor implementation, one that can execute arithmetic operations such as:
(opcode,destination,source 0,source 1)
Examples and meaning of each instruction:
ADD R2, R1, R0 → R2 = R1+R0
SUB R3, R2, R1 → R3 = R2 -R1

instructions are represented with 32-bits:
Upper 5 bits: opcode (ADD=0, SUB=1,…)
Next 5 bits: Rd (destination)
Next 5 bits: Rs1 (source 1)
Next 5 bits: Rs0 (source 0)
(leftover bits not used/reserved)

We have R0…R31 in the system.
· Write a class to represent an instruction.
· Increase the chances for data hazards (destination of one instruction is one of the source operands for the next instruction).

Here is the implementation which i thought of, is there a better way to implement the same? Can this be implemented using randsequence?

module alu;
  
  class Instruction;
    rand bit [4:0] Rd;
    rand bit [4:0] Rs0;
    rand bit [4:0] Rs1;
    rand enum {Add = 0,Sub,Multiply,Xor,Or,And,Nand,Not,Load,Store} opcode;
    rand enum {RAW =0,WAR,WAW} Hazard;
    rand bit Dependent;
    rand bit [2:0] Interleaving;
    rand bit Rs0_or_Rs1;
    constraint c {Interleaving inside{[1:7]};}
    constraint c_hazard {Hazard dist {RAW := 7, WAR :=2, WAW := 2};}
    constraint c_dependent {Dependent dist {1 := 80, 0 := 40};}
    bit [31:0] My_Instruction;
    
    function void post_randomize();
      My_Instruction = {opcode,Rd,Rs0,Rs1};
    endfunction
   endclass
  
  class my_alu;

    rand Instruction Instruction_h[20];

  
  function new();
    foreach (Instruction_h[i])
      Instruction_h[i] = new;
  endfunction
  
  constraint c1{
  
    foreach (Instruction_h[i])

      {
       
        if(Instruction_h[i].Dependent && Instruction_h[i].Hazard==0)
        {//RAW
          if(Instruction_h[i].Rs0_or_Rs1)
            Instruction_h[i].Rs0==Instruction_h[i-(Instruction_h[i].Interleaving)].Rd;
          else
            Instruction_h[i].Rs1== Instruction_h[i-(Instruction_h[i].Interleaving)].Rd;
        }
          else if (Instruction_h[i].Dependent && Instruction_h[i].Hazard==1)
          {//WAR
            if (Instruction_h[i].Rs0_or_Rs1)
              Instruction_h[i].Rd==Instruction_h[i-(Instruction_h[i].Interleaving)].Rs0;
           else
             Instruction_h[i].Rd==Instruction_h[i-(Instruction_h[i].Interleaving)].Rs1;
          }
            else if (Instruction_h[i].Dependent && Instruction_h[i].Hazard==2) //WAW
              
              Instruction_h[i].Rd==Instruction_h[i-(Instruction_h[i].Interleaving)].Rd; 
            
  
  }
      }
      
         
 endclass   

      
my_alu my_alu_h;
initial begin
  my_alu_h = new;
  assert (my_alu_h.randomize());
  foreach(my_alu_h.Instruction_h[i]) 
    $display("%p",my_alu_h.Instruction_h[i]);
 end
endmodule

In reply to Neal:

This code seems to be fine, I have made few modifications such as,

  1. turning off constraint c1 for the first object.
  2. Replaced “i-(Instruction_h[i].Interleaving)”, might cause failure if i < Instruction_h[i].Interleaving.
  3. Additional interleaving constraint so that the address is picked from a previous instruction “Instruction_h[i].Interleaving == i-1; or Instruction_h[i].Interleaving < i”.
  4. Increased “Interleaving” size and removed its base constraint.

Please find the modified code below.

module alu;
 
  class Instruction;
    rand bit [4:0] Rd;
    rand bit [4:0] Rs0;
    rand bit [4:0] Rs1;
    rand enum {Add = 0,Sub,Multiply,Xor,Or,And,Nand,Not,Load,Store} opcode;
    rand enum {RAW =0,WAR,WAW} Hazard;
    rand bit Dependent;
    rand bit [4:0] Interleaving;
    rand bit Rs0_or_Rs1;
    //constraint c {Interleaving inside{[1:7]};}
    constraint c_hazard {Hazard dist {RAW := 7, WAR :=2, WAW := 2};}
    constraint c_dependent {Dependent dist {1 := 80, 0 := 40};}
    bit [31:0] My_Instruction;
 
    function void post_randomize();
      My_Instruction = {opcode,Rd,Rs0,Rs1};
    endfunction
   endclass
 
  class my_alu;
 
    rand Instruction Instruction_h[20];
 
 
  function new();
    foreach (Instruction_h[i])
      Instruction_h[i] = new;
  endfunction
 
  constraint c1{
 
    foreach (Instruction_h[i])
 
      {
        if(i>0) { 
          Instruction_h[i].Interleaving == i-1; //or Instruction_h[i].Interleaving < i
        if(Instruction_h[i].Dependent && Instruction_h[i].Hazard==0)
        {//RAW
          if(Instruction_h[i].Rs0_or_Rs1)
            Instruction_h[i].Rs0==Instruction_h[(Instruction_h[i].Interleaving)].Rd;
          else
            Instruction_h[i].Rs1== Instruction_h[(Instruction_h[i].Interleaving)].Rd;
        }
          else if (Instruction_h[i].Dependent && Instruction_h[i].Hazard==1)
          {//WAR
            if (Instruction_h[i].Rs0_or_Rs1)
              Instruction_h[i].Rd==Instruction_h[(Instruction_h[i].Interleaving)].Rs0;
           else
             Instruction_h[i].Rd==Instruction_h[(Instruction_h[i].Interleaving)].Rs1;
          }
            else if (Instruction_h[i].Dependent && Instruction_h[i].Hazard==2) //WAW
 
              Instruction_h[i].Rd==Instruction_h[(Instruction_h[i].Interleaving)].Rd; 
 
 
  }
      }
      }
 
 
 endclass   
 
 
my_alu my_alu_h;
initial begin
  my_alu_h = new;
  assert (my_alu_h.randomize());
  foreach(my_alu_h.Instruction_h[i]) 
    $display("%p",my_alu_h.Instruction_h[i]);
 end
endmodule

In reply to Raja Rathinam:

Thank you Raja for your reply, I believe the constraint solver will take care of the failure condition you are mentioning (might cause failure if i < Instruction_h[i].Interleaving)

The value of Interleaving will be set in such a range that it will find an object instance of the class Instruction. I have tried the code and working on EDA playground.

Instruction_h[i].Rs0==Instruction_h[i-(Instruction_h[i].Interleaving)].Rd;

Thanks and Regards,
Neal

In reply to Neal:
Hi Neal,

Thanks for the link, yes it is working with synopsys VCS 2020.03 and mentor questa 2020.1 simulators. But the randomization is failing with cadence xcelium 20.09 simulator, which I was using. Probably its the way constraint solvers are implemented in different EDA simulators.

According me, your solution works and looks fine. Thank you!