Random Non overlapping Address (Memory allocator)

Hi,

I have Variable memory partitions with each partition having a variable size. Now the thing I want to do is within each of these partition regions I want to generate N addresses (say N =5). I know I have the starting address of each partition with me, but now within each partition I want to generate 5 addresses that are non overlapping.

What is the easiest way to do this additional thing. Should we do in post_randomize() call or can we do it in pre randomize() itself.

class MemoryBlock;
 
  bit [31:0]     m_ram_start;       // Start address of RAM
  bit [31:0]     m_ram_end;         // End address of RAM
 
  rand int      m_num_part;       // Number of partitions  
  rand bit [31:0]   m_part_start [];     // Partition start array
  rand int       m_part_size [];       // Size of each partition
  rand int      m_tmp;
 
  // Constrain number of partitions RAM has to be divided into
  constraint c_parts { m_num_part > 4; m_num_part < 10; }
 
  // Constraint size of each partition
  constraint c_size { m_part_size.size() == m_num_part;
                     m_part_size.sum() == m_ram_end - m_ram_start + 1; 
                     foreach (m_part_size[i]) 
                       m_part_size[i] inside {16, 32, 64, 128, 512, 1024};
                    }
 
  // Constrain start addr of each partition
  constraint c_part { m_part_start.size() == m_num_part;
                      foreach (m_part_start[i]) {
                        if (i>=1) 
                          m_part_start[i] == m_part_start[i-1] + m_part_size[i-1];
                        else
                          m_part_start[i] == m_ram_start;
                      }
                    }                      
 
  function void display();
    $display ("------ Memory Block --------");
    $display ("RAM StartAddr   = 0x%0h", m_ram_start);
    $display ("RAM EndAddr     = 0x%0h", m_ram_end);
    $display ("# Partitions = %0d", m_num_part);
    $display ("------ Partitions --------");
    foreach (m_part_start[i]) 
      $display ("Partition %0d start = 0x%0h, size = %0d bytes", i, m_part_start[i], m_part_size[i]);
  endfunction
endclass
 
module tb;
  initial begin
    MemoryBlock mb = new;
    mb.m_ram_start = 32'h0;
    mb.m_ram_end   = 32'h7FF;     // 2KB RAM
    mb.randomize();
    mb.display();
  end
endmodule

In reply to sriram.seshagiri:

See:

https://verificationacademy.com/forums/systemverilog/constraint-memories#reply-76718
https://verificationacademy.com/forums/uvm/constraining-address-memory-making-sure-offset-not-within-previous-memory-regions.#reply-63179

Hi Dave,

I tried adding this as an additional constraint, but it does not compile in EDA Playground as it does not like constraints on Multi Dimensional Arrays.

Parameter N = 5;
rand bit [31:0] addr[][];

constraint c_addr { addr.size() == m_num_part;
                      foreach(addr[i])  {
                       addr[i].size == N;
                     }

The idea behind this 2nd constraint is that say N = 5 then each addr(0,0) addr(0,1), addr(0,2), addr(0,3), addr(0,4) will all be unique addresses and, will be less than the next address and, addr(0,4) < starting address of the next block at (i+1).

Is this constraint correct. Please correct me if I am wrong.

constraint c_addr {
   foreach(addr[i,j]) {
       if (j != N-1)  
         addr[i][j] < addr[i][j+1];
		  else
            addr[i][j]< m_part_start[i+1];
               OR
//m_part_start[i]<=addr[i][j]<m_part_start[i+1];
     }
   }