Q034FreeSystemVerilog
Measure external fragmentation
Interview prompt
Question
Report total free capacity, the largest contiguous free block, and a defined external-fragmentation ratio.
Candidate starting point
Implementation scaffold
typedef struct {
int unsigned lo;
int unsigned hi;
} range_t;
class RangeAllocator;
range_t free_ranges[$];
int unsigned managed_base;
int unsigned managed_limit;
function new(int unsigned base, int unsigned size);
if (size == 0) $fatal(1, "allocator size must be positive");
if (base > 32'hffff_ffff - (size - 1))
$fatal(1, "managed range wraps the address space");
managed_base = base;
managed_limit = base + size - 1;
free_ranges.push_back('{lo: managed_base, hi: managed_limit});
endfunction
function bit alloc(int unsigned size, output int unsigned addr);
if (size == 0) $fatal(1, "allocation size must be positive");
foreach (free_ranges[i]) begin
longint unsigned available =
longint'(free_ranges[i].hi) - free_ranges[i].lo + 1;
if (available >= size) begin
addr = free_ranges[i].lo;
if (available == size) free_ranges.delete(i);
else free_ranges[i].lo += size;
return 1;
end
end
return 0;
endfunction
function void dealloc(int unsigned addr, int unsigned size);
if (size == 0) $fatal(1, "deallocation size must be positive");
if (addr > 32'hffff_ffff - (size - 1))
$fatal(1, "deallocated range wraps the address space");
free_ranges.push_back('{lo: addr, hi: addr + size - 1});
coalesce();
endfunction
function void coalesce();
range_t merged[$];
range_t current;
if (free_ranges.size() <= 1) return;
free_ranges.sort() with (item.lo);
current = free_ranges[0];
for (int i = 1; i < free_ranges.size(); i++) begin
if (free_ranges[i].lo <= current.hi ||
(current.hi != 32'hffff_ffff &&
free_ranges[i].lo == current.hi + 1))
current.hi = (free_ranges[i].hi > current.hi) ?
free_ranges[i].hi : current.hi;
else begin
merged.push_back(current);
current = free_ranges[i];
end
end
merged.push_back(current);
free_ranges = merged;
endfunction
function void fragmentation_metrics(
output longint unsigned total_free,
output longint unsigned largest_block,
output real external_ratio
);
// Implement here: fragmentation_metrics.
endfunction
endclassReviewed example
Trace one case
Input
free=[[0,9],[20,24]]Expected output
total_free=15; largest_block=10; external_ratio=1-10/15=0.3333Inclusive sizes are 10 and 5, and the largest-to-total fraction is subtracted from one.
What to cover
Requirements
- Measure inclusive range sizes correctly.
- Return zeros for an empty free list.
- Define external_ratio as 1 minus largest_block divided by total_free.
- Avoid division by zero.
