A way to write constraint which allocates active channels to ports

Hi,

DUT has 2 output ports, and 16 input port channels.

DUT can have either only single output port active or both output ports active.
Channels are associated mutually exclusive per output port.
For the purposes of verification, total number of active channels can vary from 1 to 16.
Need to write set of constraints to configure the DUT state registers.

Looking for a elegant way to write set of constraints which implement it, and eventually to receive 2 arrays/lists one per each output port which has the indexes of the active channels associated to the specific output port.

Thanks in advance,
Michael

In reply to Michael54:

I think you need more detail in what you are looking to generate. Can you provide an example of sets of solutions you are looking for?

Hi Dave,

few possible sets:

  1. Only one output port is active, for example: port1, all input channels are associated to it.
    So the list of channels indexes for port0 is empty list.
    List of channel indexes for port1 has 16 items, with values from 0…15 → meaning all input channels are active.

  2. Both output ports are active: port0 and port1.
    list of associated channels to port0: 3,9,15
    list of associated channels to port1: 1,4,5,6,10,11
    So we have only 9 input channels active and associated to output ports.
    Rest of input channels: 0,2,7,8,12,13,14 are not active. So no stimuli will be injected to it in this specific test.

  3. Both output ports are active.
    Each has only one input channel associated to it.
    Channel #8 associated to output port0
    Channel #4 associated to output port1

Started next code implementation:



parameter NUM_OF_PORTS=2;
parameter NUM_OF_CHANNELS=16;

rand bit[$clog2(NUM_OF_PORTS)-1:0]         num_of_active_ports;                                   
rand bit[NUM_OF_PORTS-1:0]                 active_ports_bitmap;                                  // Bitmap vector which means what port index is active.
rand bit[$clog2(NUM_OF_CHANNELS)-1:0]      total_num_of_active_channels;
rand bit[NUM_OF_CHANNELS-1:0]              active_channels_bitmap;
rand bit[$clog2(NUM_OF_CHANNELS)-1:0]      num_of_active_channels_per_port[NUM_OF_PORTS];
    
rand bit[NUM_OF_CHANNELS-1:0]              active_channels_in_port_bitmap[NUM_OF_PORTS]; // Looking how to create these 2 items of the array, each per port. It should have association of input channels to output port.

constraint num_of_active_mipi_csi_ports_c {
            
        num_of_active_ports inside {[1:NUM_OF_PORTS]};
        $countbits(active_ports_bitmap) == num_of_active_ports;

        total_num_of_active_channels inside {[1:NUM_OF_CHANNELS]};
        $countbits(active_channels_bitmap) == total_num_of_active_channels;
        
        ((num_of_active_channels_per_port[0] + num_of_active_channels_per_port[1]) ==  total_num_of_active_channels);
        
        ..........
    }


But do not know how to create the 2 array items of: active_channels_in_port_bitmap
So the logical OR operation of these 2 array items will be: active_channels_bitmap

Hope explained it better.
Open to suggestions, maybe my direction is not that good at all.

Thanks,
Michael

class AA;

rand bit[7:0] x[], y[];

constraint x_y_val
  {
    (x.size+y.size)<=16;
    foreach(x[i])
      {
        x[i] inside{[0:15]};
      }
    foreach(y[i])
      {
        y[i] inside{[0:15]};
      }
    unique{x,y};
  }
endclass

module main;

AA a;

initial
  begin
    a=new;
    for(int i=0;i<10;i++)
      begin
        a.randomize;
        $display("%0p", a);
      end
  end
endmodule

the values of x and y presents associated channels to respective port


rand int port0[];
rand int port1[];

constraint output_sel_c{

port0 inside {[0:16]};
port1 inside {[0:16]};
port0.size() + port1.size() <= 16;
unique{port0,port1};

}


In reply to Michael54:

you can control complete i/o mapping using below code:



class dut_io_map #(N_OUTPUT=2, N_INPUT=16);
  rand int unsigned io_map[N_INPUT][N_OUTPUT];
  rand bit use_iport[N_INPUT];
  rand bit use_oport[N_OUTPUT];
  rand int use_n_iport;
  rand int use_n_oport;

  constraint map_c {
     use_n_iport                      inside {[1:N_INPUT]};
     use_iport.sum() with(int'(item)) == use_n_iport;
     use_oport.sum() with(int'(item)) inside {[1:3]};
     
     foreach(io_map[i,j])  { io_map[i][j] inside {0,1}; }
     foreach(use_iport[i]) { 
                              io_map[i].sum() == use_iport[i]; 
                             (use_oport[0]==0) -> (io_map[i][0] == 0);
                             (use_oport[1]==0) -> (io_map[i][1] == 0);
                           }
   }

   function void post_randomize();
     $display("active out_port : port_0=%b, port_1=%b", use_oport[0], use_oport[1]);
     $display("active in_port  : %p, num in ports=%0d", use_iport, use_n_iport);
     foreach(io_map[i]) begin
       $display("input_port_%02d=%b : io_map=%p",i,use_iport[i],io_map[i]);
     end
   endfunction

endclass

module test;
  dut_io_map txn=new();

  initial begin
     txn.randomize() with {
        //use_oport[0]==1; 
        //use_oport[1]==0;
        use_n_iport ==7;   //Num of Active input ports
        io_map[2][1]==1;   //input 2 mapped to output 1
        io_map[5][0]==1;   //input 5 mapped to output 0
        use_iport[9]==1;   //input port 9, random out port mapping
        };
  end

endmodule


/*
OUTPUT:
active out_port : port_0=1, port_1=1
active in_port  : '{'h0, 'h0, 'h1, 'h1, 'h0, 'h1, 'h1, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0} , num in ports=7
input_port_00=0 : io_map='{'h0, 'h0} 
input_port_01=0 : io_map='{'h0, 'h0} 
input_port_02=1 : io_map='{'h0, 'h1} //
input_port_03=1 : io_map='{'h1, 'h0} 
input_port_04=0 : io_map='{'h0, 'h0} 
input_port_05=1 : io_map='{'h1, 'h0} //
input_port_06=1 : io_map='{'h0, 'h1} 
input_port_07=1 : io_map='{'h0, 'h1} 
input_port_08=0 : io_map='{'h0, 'h0} 
input_port_09=1 : io_map='{'h1, 'h0} //
input_port_10=0 : io_map='{'h0, 'h0} 
input_port_11=1 : io_map='{'h1, 'h0} 
input_port_12=0 : io_map='{'h0, 'h0} 
input_port_13=0 : io_map='{'h0, 'h0} 
input_port_14=0 : io_map='{'h0, 'h0} 
input_port_15=0 : io_map='{'h0, 'h0} 
*/

In reply to Michael54:


class register_config#(parameter NUM_INPUT_PORTS = 16, NUM_OUTPUT_PORTS = 2);
  rand bit [NUM_INPUT_PORTS-1:0]  input_ports;
  rand bit [NUM_OUTPUT_PORTS-1:0] output_ports;
  rand int output_list1[];
  rand int output_list2[];
  
  constraint list{output_list1.size() + output_list2.size() == $countones(input_ports);
                  if(output_ports[0] == 0) output_list1.size() == 0;
                  if(output_ports[1] == 0) output_list2.size() == 0;
                  foreach(output_list1[i]){
                    output_list1[i] inside {[0:NUM_INPUT_PORTS-1]};
                    input_ports[output_list1[i]] == 1; 
                  }
                  foreach(output_list2[i]) {
                    output_list2[i] inside {[0:NUM_INPUT_PORTS-1]};
                    input_ports[output_list2[i]] == 1;
                  }
                  
                  unique{output_list2,output_list1};
                 }
  function void display();
    $display("++++++++++++++++++++++++++++++++++++++++++++++++++");
    $display("INPUT PORT::%b OUTPUTPORT::%b OUTPUTLIST1::%p OUTPUTLIST2::%p",input_ports,output_ports,output_list1,output_list2);
    $display("++++++++++++++++++++++++++++++++++++++++++++++++++");
  endfunction: display
endclass

module tb;
  register_config cfg;
  
  initial begin
    cfg=new();
    cfg.randomize();
    cfg.display();
  end
endmodule: tb