Commit 39b09dbc authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

testbench/swcore: allocator TB

parent 064fd70e
target = "xilinx" # "altera" #
action = "simulation"
#fetchto = "../../ip_cores"
files = [
"main.sv"
]
vlog_opt="+incdir+../../ip_cores/wr-cores/sim +incdir+../../ip_cores/wr-cores/sim/fabric_emu"
modules = {"local":
[
"../../../ip_cores/wr-cores",
"../../../ip_cores/wr-cores/ip_cores/general-cores/modules/genrams/",
"../../../modules/wrsw_swcore",
],
}
typedef enum
{
ALLOC,
FREE,
FORCE_FREE,
SET_USECOUNT
} alloc_req_type_t ;
typedef struct {
alloc_req_type_t t;
int use_count;
int id, origin;
int page;
time t_event;
} alloc_request_t;
function automatic int first_free(int tab[]);
int i;
for(i=0;i<tab.size;i++)
if(tab[i] < 0)
return i;
endfunction // first_free
function automatic int lookup_origin_page(ref alloc_request_t rqs[$], int id);
foreach(rqs[i])
begin
if(rqs[i].id == id)
begin
// $display("Found t%d page %d\n", rqs[i].t, rqs[i].page);
return rqs[i].page;
end
end
$fatal("ID Not found: %i", id);
endfunction // lookup_origin_page
task automatic count_occupied_pages(ref alloc_request_t rqs[$], ref int peak, output int occupied, input int up_to=0, int verbose=0, int reserve_pages=1);
int i, n =0;
int page_table[1024]; /* fixme: this is ugly */
int pages_allocated = 0;
string s = "";
peak = 0;
if(!up_to)
up_to = rqs.size() - 1;
for(i=0;i<1024;i++) page_table[i] = -1;
// $display("----\n");
for(i=0;i<=up_to;i++)
begin
case(rqs[i].t)
ALLOC:begin
int page = reserve_pages?first_free(page_table) : rqs[i].page;
rqs[i].page = page;
page_table[page] = rqs[i].use_count;
pages_allocated++;
if(verbose) $display("%d : alloc %d [cnt=%d, used=%d]",i, rqs[i].page, rqs[i].use_count, pages_allocated);
end
SET_USECOUNT: begin
int page = reserve_pages?lookup_origin_page(rqs, rqs[i].origin):rqs[i].page;
if(verbose) $display("%d : set_ucnt %d [cnt=%d]", i, page, rqs[i].use_count);
page_table[page] = rqs[i].use_count;
end
FREE: begin
int page = reserve_pages?lookup_origin_page(rqs, rqs[i].origin):rqs[i].page;
if(page_table[page] < 0)
$fatal("attempt to free a free page\n");
page_table[page]--;
if(!page_table[page])
begin
page_table[page] = -1;
pages_allocated--;
end
if(verbose) $display("%d : free %d, used = %d", i, page, pages_allocated);
end
FORCE_FREE:begin
int page = reserve_pages?lookup_origin_page(rqs, rqs[i].origin):rqs[i].page;
page_table[page] = -1;
pages_allocated--;
if(verbose) $display("%d : force_free %d, used = %d", i, page, pages_allocated);
end
endcase // case (rqs[i].t)
if(pages_allocated > peak) peak = pages_allocated;
end
for(i=0;i<1024;i++) begin
if(page_table[i] >= 0) begin
n++;
$sformat(s, "%s %-1d", s, i);
end
end
if(verbose) $display("Pages occupied after test: %s", s);
occupied = n;
endtask // count_occupied_pages
function automatic int my_dist_uniform(ref int seed, input int start, int _end);
if(start >= _end)
return start;
return $dist_uniform(seed, start, _end);
endfunction // my_dist_uniform
task automatic gen_random_requests(ref alloc_request_t rqs[$], input int n, int seed, int max_occupied_pages = 0, int max_use_count = 3);
int i;
static int uniq_id = 0;
int temp_page = 0;
for(i=0;i<=n;i++)
begin
alloc_request_t rq;
int orig_id = uniq_id++;
int j;
int use_count = my_dist_uniform(seed, 0, max_use_count);
int orig_idx;
int idx, peak, occupied;
idx = my_dist_uniform(seed, 0, rqs.size()-1);
orig_idx = idx;
// $display("Gen %d", i);
rq.t = ALLOC;
rq.id = orig_id;
rq.use_count = use_count;
rqs.insert(idx, rq);
if(!use_count) /* Insert a "set use count" command somewhere after the allocation request */
begin
int idx = my_dist_uniform(seed, orig_idx + 1, rqs.size()), peak, occupied;
// $display("InsertUseCnt page=%d at=%d",temp_page-1, idx);
rq.t = SET_USECOUNT;
rq.origin = orig_id;
rq.id = -1;
use_count = my_dist_uniform(seed, 1, max_use_count);
rq.use_count = use_count;
rqs.insert(idx, rq);
orig_idx = idx;
end
for(j=0; j<use_count;j++)
begin
orig_idx = my_dist_uniform(seed, orig_idx + 1, rqs.size());
rq.t = FREE;
rq.id = -1 ;
rq.origin = orig_id;
if(my_dist_uniform(seed, 1, 100) < 20)
begin
rq.t = FORCE_FREE;
end
// $display("Insertidx: %d size %d", idx, rqs.size());
rqs.insert(orig_idx, rq);
if(rq.t == FORCE_FREE)
break;
end // for (j=0; j<use_count;j++)
temp_page++;
end
endtask // gen_random_requests
interface IAllocatorPort (input clk_i);
parameter g_page_addr_width = 10;
parameter g_usecnt_width = 4;
logic alloc=0, free=0, force_free=0, set_usecnt=0, done;
logic alloc_done, free_done, force_free_done, set_usecnt_done;
logic free_last_usecnt;
logic no_mem;
logic [g_page_addr_width-1:0] pg_addr_free;
logic [g_page_addr_width-1:0] pg_addr_force_free;
logic [g_page_addr_width-1:0] pg_addr_usecnt;
logic [g_page_addr_width-1:0] pg_addr_alloc, pg_addr_muxed;
logic [g_usecnt_width-1:0] usecnt;
assign pg_addr_muxed = free ? pg_addr_free :
force_free ? pg_addr_force_free :
pg_addr_usecnt;
endinterface // IAllocatorPort
`ifdef nulll
typedef virtual IAllocatorPort VIAllocatorPort;
task automatic execute_requests(VIAllocatorPort port, ref alloc_request_t rqs[$], input int verbose =0);
int i;
for(i=0;i<rqs.size();i++)
begin
case(rqs[i].t)
ALLOC: begin
port.alloc <= 1;
port.usecnt <= rqs[i].use_count;
@(posedge port.clk_i);
while(!port.done) @(posedge port.clk_i);
port.alloc <= 0;
rqs[i].page = port.pg_addr_alloc;
if(verbose)$display("Alloc [id=%-1d, usecount=%-1d, page=%-1d]", rqs[i].id, rqs[i].use_count, rqs[i].page);
end
SET_USECOUNT:begin
rqs[i].page = lookup_origin_page(rqs, rqs[i].origin);
if(verbose) $display("Set_Usecount [origin=%-1d, usecount=%-1d, page=%-1d]", rqs[i].origin, rqs[i].use_count, rqs[i].page);
port.pg_addr_usecnt <= rqs[i].page;
port.usecnt <= rqs[i].use_count;
port.set_usecnt <= 1;
@(posedge port.clk_i);
while(!port.done) @(posedge port.clk_i);
port.set_usecnt <= 0;
end
FREE: begin
rqs[i].page = lookup_origin_page(rqs, rqs[i].origin);
if(verbose)$display("Free [origin=%-1d, page=%-1d]", rqs[i].origin, rqs[i].page);
port.pg_addr_free <= rqs[i].page;
port.free <= 1;
@(posedge port.clk_i);
while(!port.done) @(posedge port.clk_i);
port.free <= 0;
end
FORCE_FREE: begin
rqs[i].page = lookup_origin_page(rqs, rqs[i].origin);
if(verbose)$display("Forced Free [origin=%-1d, page=%-1d]", rqs[i].origin, rqs[i].page);
port.pg_addr_force_free <= rqs[i].page;
port.force_free <= 1;
@(posedge port.clk_i);
while(!port.done) @(posedge port.clk_i);
port.force_free <= 0;
end
endcase // case (rqs[i].t)
end
endtask // execute_requests
`endif
\ No newline at end of file
This diff is collapsed.
`timescale 1ns/1ns
`include "common.svh"
module main;
`define c_num_ports 7
`define c_page_addr_width 10
`define c_use_count_width 4
reg clk = 0;
reg rst_n = 0;
IAllocatorPort alloc_port[`c_num_ports] (clk) ;
VIAllocatorPort valloc_port[`c_num_ports] = alloc_port;
genvar i;
wire [`c_num_ports-1:0] alloc_v, free_v, force_free_v, set_usecnt_v;
wire [`c_num_ports-1:0] alloc_done_v, free_done_v, force_free_done_v, set_usecnt_done_v;
wire [`c_num_ports * `c_page_addr_width - 1 : 0] pgaddr_free_v, pgaddr_force_free_v, pgaddr_usecnt_v;
wire [`c_num_ports * `c_use_count_width - 1 : 0] usecnt_v;
wire [`c_page_addr_width-1:0] pg_addr_alloc;
generate
for(i=0;i<`c_num_ports;i++)
begin
assign alloc_v[i] = alloc_port[i].alloc;
assign free_v[i] = alloc_port[i].free;
assign force_free_v[i] = alloc_port[i].force_free;
assign set_usecnt_v[i] = alloc_port[i].set_usecnt;
assign alloc_port[i].done = (alloc_done_v[i] | free_done_v[i] | force_free_done_v[i] | set_usecnt_done_v[i]);
assign alloc_port[i].pg_addr_alloc = pg_addr_alloc;
assign pgaddr_free_v[(i+1) * `c_page_addr_width - 1: i * `c_page_addr_width] = alloc_port[i].pg_addr_free;
assign pgaddr_force_free_v[(i+1) * `c_page_addr_width - 1: i * `c_page_addr_width] = alloc_port[i].pg_addr_force_free;
assign pgaddr_usecnt_v[(i+1) * `c_page_addr_width - 1: i * `c_page_addr_width] = alloc_port[i].pg_addr_usecnt;
assign usecnt_v[(i+1) * `c_use_count_width - 1 : i * `c_use_count_width]=alloc_port[i].usecnt;
end
endgenerate
swc_multiport_page_allocator
#(
.g_page_num (1024),
.g_page_addr_width (10),
.g_num_ports (7),
.g_usecount_width (4)
) DUT (
.clk_i (clk),
.rst_n_i (rst_n),
.alloc_i (alloc_v),
.free_i(free_v),
.force_free_i(force_free_v),
.set_usecnt_i(set_usecnt_v),
.alloc_done_o(alloc_done_v),
.free_done_o(free_done_v),
.force_free_done_o(force_free_done_v),
.set_usecnt_done_o(set_usecnt_done_v),
.pgaddr_free_i(pgaddr_free_v),
.pgaddr_force_free_i(pgaddr_force_free_v),
.pgaddr_usecnt_i(pgaddr_usecnt_v),
.usecnt_i(usecnt_v),
.pgaddr_alloc_o(pg_addr_alloc)
);
const int MAX_USE_COUNT=3;
int uniq_id = 0;
always #5ns clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
task automatic test_port(VIAllocatorPort port, int initial_seed, int n_seeds, int n_requests);
alloc_request_t rqs[$];
int seed;
for(seed = initial_seed; seed < initial_seed + n_seeds; seed++)
begin
automatic int init_seed = seed;
int occupied, peak;
rqs = '{};
gen_random_requests(rqs, n_requests, init_seed, 100);
count_occupied_pages(rqs, peak, occupied, rqs.size()-1);
$display("Peak Page Usage: %d\n", peak);
execute_requests(port, rqs, 0);
end
endtask // test_port
initial begin
int port_idx;
while(!rst_n) @(posedge clk);
for(port_idx=0;port_idx < 7; port_idx++)
fork
automatic int k_idx = port_idx;
test_port(valloc_port[k_idx], k_idx * 100, 100, 200);
join_none
repeat(1000000) @(posedge clk);
$display("AtTheEnd: free_blocks = %-1d", DUT.ALLOC_CORE.free_blocks);
if(DUT.ALLOC_CORE.free_blocks != 1023)
$fatal("Pages missing");
end // initial begin
endmodule // main
make -f Makefile
vlog +incdir+../../sim +incdir+../../ip_cores/wr-cores/sim multiport.sv
vsim -L secureip -L unisim -t 10fs work.main -voptargs="+acc" +nowarn8684 +nowarn8683
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
do wave.do
#do wave_allports.do
radix -hexadecimal
run 20us
wave zoomfull
radix -hexadecimal
\ No newline at end of file
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /main/DUT/ALLOC_CORE/g_num_pages
add wave -noupdate /main/DUT/ALLOC_CORE/g_page_addr_width
add wave -noupdate /main/DUT/ALLOC_CORE/g_num_ports
add wave -noupdate /main/DUT/ALLOC_CORE/g_usecount_width
add wave -noupdate /main/DUT/ALLOC_CORE/clk_i
add wave -noupdate /main/DUT/ALLOC_CORE/rst_n_i
add wave -noupdate /main/DUT/ALLOC_CORE/alloc_i
add wave -noupdate /main/DUT/ALLOC_CORE/free_i
add wave -noupdate /main/DUT/ALLOC_CORE/force_free_i
add wave -noupdate /main/DUT/ALLOC_CORE/set_usecnt_i
add wave -noupdate /main/DUT/ALLOC_CORE/usecnt_i
add wave -noupdate /main/DUT/ALLOC_CORE/pgaddr_i
add wave -noupdate /main/DUT/ALLOC_CORE/pgaddr_o
add wave -noupdate /main/DUT/ALLOC_CORE/free_last_usecnt_o
add wave -noupdate /main/DUT/ALLOC_CORE/done_o
add wave -noupdate /main/DUT/ALLOC_CORE/nomem_o
add wave -noupdate /main/DUT/ALLOC_CORE/nomem
add wave -noupdate /main/DUT/ALLOC_CORE/rd_ptr
add wave -noupdate /main/DUT/ALLOC_CORE/wr_ptr
add wave -noupdate /main/DUT/ALLOC_CORE/free_pages
add wave -noupdate /main/DUT/ALLOC_CORE/q_write
add wave -noupdate /main/DUT/ALLOC_CORE/q_read
add wave -noupdate /main/DUT/ALLOC_CORE/pending_free
add wave -noupdate /main/DUT/ALLOC_CORE/read_usecnt
add wave -noupdate /main/DUT/ALLOC_CORE/q_init_data
add wave -noupdate /main/DUT/ALLOC_CORE/initializing
add wave -noupdate /main/DUT/ALLOC_CORE/usecnt_write
add wave -noupdate /main/DUT/ALLOC_CORE/usecnt_addr
add wave -noupdate /main/DUT/ALLOC_CORE/usecnt_rddata
add wave -noupdate /main/DUT/ALLOC_CORE/usecnt_wrdata
add wave -noupdate /main/DUT/ALLOC_CORE/q_output_addr
add wave -noupdate /main/DUT/ALLOC_CORE/alloc_d0
add wave -noupdate /main/DUT/ALLOC_CORE/force_free_d0
add wave -noupdate /main/DUT/ALLOC_CORE/free_d0
add wave -noupdate /main/DUT/ALLOC_CORE/done_int
add wave -noupdate /main/DUT/ALLOC_CORE/ram_ones
add wave -noupdate /main/DUT/ALLOC_CORE/tmp_dbg_dealloc
add wave -noupdate /main/DUT/ALLOC_CORE/tmp_page
add wave -noupdate /main/DUT/ALLOC_CORE/free_blocks
add wave -noupdate /main/DUT/ALLOC_CORE/usecnt_not_zero
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {1845342710 fs} 0}
configure wave -namecolwidth 192
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits fs
update
WaveRestoreZoom {0 fs} {21 us}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment