constraintssystem-verilogoverlapping

SV randomization - generating non-overlapping memory regions using constraints


I want to generate random regions in memory such that they do not overlap. Below code is generating such regions but they are in order (i.e., region-0 is before region-1, region-1 is before region-2).

But I want to have the regions in random order. I can use shuffle() in post_randomize, but I want to know if we can do this using just constraints ?

class test;
  typedef struct{
    rand int unsigned indx;
    rand bit [31:0] addr_s;
    rand bit [31:0] addr_e;
    rand bit [31:0] sz;
  } regions_t;
  rand regions_t regions[];
  constraint c_regions{
    regions.size() == 3;
    foreach(regions[i]) {
      regions[i].indx == i;
      regions[i].sz inside {10, 20}; // size of each region
      regions[i].addr_e == regions[i].addr_s + regions[i].sz - 1;
      regions[i].addr_s < regions[i].addr_e;
      regions[i].addr_e < 60; // uppler limit of all memory regions
      foreach(regions[j]) {
        //if(i!=j) !((regions[i].addr_s >= regions[j].addr_s) && (regions[i].addr_s <= regions[j].addr_e));
        if(i<j) (regions[i].addr_e < regions[j].addr_s);
      }
    }
    
  }

  function void post_randomize();
      //regions.shuffle();
      $display($sformatf("post_randomize(): regions = %0p", regions));
  endfunction : post_randomize
endclass: test

program prog;
  test tst;
  initial begin
    tst = new();
    repeat(10) begin
        tst.randomize();
    end

  end
endprogram: prog

This constraint if(i!=j) !((regions[i].addr_s >= regions[j].addr_s) && (regions[i].addr_s <= regions[j].addr_e)); seems to be working, but wanted to sure if it will have issues.


Solution

  • Change your last inner foreach loop to what I show below. You were very close/

    typedef bit [7:0] addr_t;
    class test;
      typedef struct{
        int unsigned indx;
        addr_t addr_s;
        addr_t addr_e;
        int sz;
      } regions_t;
      rand regions_t regions[];
      constraint c_regions{
        regions.size() == 3;
        foreach(regions[i]) {
          regions[i].indx == i;
          regions[i].sz inside {10, 20}; // size of each region
          regions[i].addr_e == regions[i].addr_s + regions[i].sz - 1;
          regions[i].addr_s < regions[i].addr_e;
          regions[i].addr_e < 80; // upper limit of all memory regions
          foreach(regions[j]) // start address cannot be inside another range
            i!=j -> !(regions[i].addr_s inside {[regions[j].addr_s:regions[j].addr_e]});
        }
      }
    
      function void post_randomize();
          $display($sformatf("post_randomize(): regions = %p", regions));
      endfunction : post_randomize
    endclass: test
    
    module prog;
      test tst;
      initial begin
        tst = new();
        repeat(10) begin
          assert(tst.randomize());
        end
    
      end
    endmodule: prog