Rework cpuif to support transaction pipelining. Add more docs. update simulator

This commit is contained in:
Alex Mykyta
2022-02-13 17:25:31 -08:00
parent de5eecf0e7
commit d0ba488904
21 changed files with 493 additions and 68 deletions

View File

@@ -40,7 +40,7 @@ interface apb3_intf_driver #(
input PSLVERR;
endclocking
task reset();
task automatic reset();
cb.PSEL <= '0;
cb.PENABLE <= '0;
cb.PWRITE <= '0;
@@ -48,7 +48,10 @@ interface apb3_intf_driver #(
cb.PWDATA <= '0;
endtask
task write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
semaphore txn_mutex = new(1);
task automatic write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
txn_mutex.get();
##0;
// Initiate transfer
@@ -66,9 +69,11 @@ interface apb3_intf_driver #(
// Wait for response
while(cb.PREADY !== 1'b1) @(cb);
reset();
txn_mutex.put();
endtask
task read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
task automatic read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
txn_mutex.get();
##0;
// Initiate transfer
@@ -89,9 +94,10 @@ interface apb3_intf_driver #(
assert(!$isunknown(cb.PSLVERR)) else $error("Read from 0x%0x returned X's on PSLVERR", addr);
data = cb.PRDATA;
reset();
txn_mutex.put();
endtask
task assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
task automatic assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
logic [DATA_WIDTH-1:0] data;
read(addr, data);
data &= mask;

View File

@@ -77,7 +77,7 @@ interface axi4lite_intf_driver #(
input RRESP;
endclocking
task reset();
task automatic reset();
cb.AWVALID <= '0;
cb.AWADDR <= '0;
cb.AWPROT <= '0;
@@ -95,13 +95,20 @@ interface axi4lite_intf_driver #(
@cb;
end
task write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
semaphore txn_aw_mutex = new(1);
semaphore txn_w_mutex = new(1);
semaphore txn_b_mutex = new(1);
semaphore txn_ar_mutex = new(1);
semaphore txn_r_mutex = new(1);
task automatic write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
bit w_before_aw;
w_before_aw = $urandom_range(1,0);
##0;
fork
begin
txn_aw_mutex.get();
##0;
if(w_before_aw) repeat($urandom_range(2,0)) @cb;
cb.AWVALID <= '1;
cb.AWADDR <= addr;
@@ -109,9 +116,12 @@ interface axi4lite_intf_driver #(
@(cb);
while(cb.AWREADY !== 1'b1) @(cb);
cb.AWVALID <= '0;
txn_aw_mutex.put();
end
begin
txn_w_mutex.get();
##0;
if(!w_before_aw) repeat($urandom_range(2,0)) @cb;
cb.WVALID <= '1;
cb.WDATA <= data;
@@ -120,39 +130,47 @@ interface axi4lite_intf_driver #(
while(cb.WREADY !== 1'b1) @(cb);
cb.WVALID <= '0;
cb.WSTRB <= '0;
txn_w_mutex.put();
end
begin
txn_b_mutex.get();
@cb;
while(cb.BREADY !== 1'b1 && cb.BVALID !== 1'b1) @(cb);
assert(!$isunknown(cb.BRESP)) else $error("Read from 0x%0x returned X's on BRESP", addr);
txn_b_mutex.put();
end
join
endtask
task read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
##0;
task automatic read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
fork
begin
txn_ar_mutex.get();
##0;
cb.ARVALID <= '1;
cb.ARADDR <= addr;
cb.ARPROT <= '0;
@(cb);
while(cb.ARREADY !== 1'b1) @(cb);
cb.ARVALID <= '0;
txn_ar_mutex.put();
end
begin
txn_r_mutex.get();
@cb;
while(!(cb.RREADY === 1'b1 && cb.RVALID === 1'b1)) @(cb);
assert(!$isunknown(cb.RDATA)) else $error("Read from 0x%0x returned X's on RDATA", addr);
assert(!$isunknown(cb.RRESP)) else $error("Read from 0x%0x returned X's on RRESP", addr);
data = cb.RDATA;
txn_r_mutex.put();
end
join
endtask
task assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
task automatic assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
logic [DATA_WIDTH-1:0] data;
read(addr, data);
data &= mask;

View File

@@ -9,6 +9,8 @@ interface passthrough_driver #(
output logic m_cpuif_req_is_wr,
output logic [ADDR_WIDTH-1:0] m_cpuif_addr,
output logic [DATA_WIDTH-1:0] m_cpuif_wr_data,
input wire m_cpuif_req_stall_wr,
input wire m_cpuif_req_stall_rd,
input wire m_cpuif_rd_ack,
input wire m_cpuif_rd_err,
input wire [DATA_WIDTH-1:0] m_cpuif_rd_data,
@@ -25,6 +27,8 @@ interface passthrough_driver #(
output m_cpuif_req_is_wr;
output m_cpuif_addr;
output m_cpuif_wr_data;
input m_cpuif_req_stall_wr;
input m_cpuif_req_stall_rd;
input m_cpuif_rd_ack;
input m_cpuif_rd_err;
input m_cpuif_rd_data;
@@ -32,47 +36,70 @@ interface passthrough_driver #(
input m_cpuif_wr_err;
endclocking
task reset();
task automatic reset();
cb.m_cpuif_req <= '0;
cb.m_cpuif_req_is_wr <= '0;
cb.m_cpuif_addr <= '0;
cb.m_cpuif_wr_data <= '0;
endtask
task write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
##0;
semaphore txn_req_mutex = new(1);
semaphore txn_resp_mutex = new(1);
// Initiate transfer
cb.m_cpuif_req <= '1;
cb.m_cpuif_req_is_wr <= '1;
cb.m_cpuif_addr <= addr;
cb.m_cpuif_wr_data <= data;
@(cb);
reset();
task automatic write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
fork
begin
// Initiate transfer
txn_req_mutex.get();
##0;
cb.m_cpuif_req <= '1;
cb.m_cpuif_req_is_wr <= '1;
cb.m_cpuif_addr <= addr;
cb.m_cpuif_wr_data <= data;
@(cb);
while(cb.m_cpuif_req_stall_wr !== 1'b0) @(cb);
reset();
txn_req_mutex.put();
end
// Wait for response
while(cb.m_cpuif_wr_ack !== 1'b1) @(cb);
reset();
begin
// Wait for response
txn_resp_mutex.get();
@cb;
while(cb.m_cpuif_wr_ack !== 1'b1) @(cb);
txn_resp_mutex.put();
end
join
endtask
task read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
##0;
task automatic read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
fork
begin
// Initiate transfer
txn_req_mutex.get();
##0;
cb.m_cpuif_req <= '1;
cb.m_cpuif_req_is_wr <= '0;
cb.m_cpuif_addr <= addr;
@(cb);
while(cb.m_cpuif_req_stall_rd !== 1'b0) @(cb);
reset();
txn_req_mutex.put();
end
// Initiate transfer
cb.m_cpuif_req <= '1;
cb.m_cpuif_req_is_wr <= '0;
cb.m_cpuif_addr <= addr;
@(cb);
reset();
// Wait for response
while(cb.m_cpuif_rd_ack !== 1'b1) @(cb);
assert(!$isunknown(cb.m_cpuif_rd_data)) else $error("Read from 0x%0x returned X's on m_cpuif_rd_data", addr);
data = cb.m_cpuif_rd_data;
reset();
begin
// Wait for response
txn_resp_mutex.get();
@cb;
while(cb.m_cpuif_rd_ack !== 1'b1) @(cb);
assert(!$isunknown(cb.m_cpuif_rd_data)) else $error("Read from 0x%0x returned X's on m_cpuif_rd_data", addr);
data = cb.m_cpuif_rd_data;
txn_resp_mutex.put();
end
join
endtask
task assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
task automatic assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
logic [DATA_WIDTH-1:0] data;
read(addr, data);
data &= mask;

View File

@@ -3,6 +3,8 @@ wire s_cpuif_req;
wire s_cpuif_req_is_wr;
wire [{{exporter.cpuif.addr_width-1}}:0] s_cpuif_addr;
wire [{{exporter.cpuif.data_width-1}}:0] s_cpuif_wr_data;
wire s_cpuif_req_stall_wr;
wire s_cpuif_req_stall_rd;
wire s_cpuif_rd_ack;
wire s_cpuif_rd_err;
wire [{{exporter.cpuif.data_width-1}}:0] s_cpuif_rd_data;
@@ -18,6 +20,8 @@ passthrough_driver #(
.m_cpuif_req_is_wr(s_cpuif_req_is_wr),
.m_cpuif_addr(s_cpuif_addr),
.m_cpuif_wr_data(s_cpuif_wr_data),
.m_cpuif_req_stall_wr(s_cpuif_req_stall_wr),
.m_cpuif_req_stall_rd(s_cpuif_req_stall_rd),
.m_cpuif_rd_ack(s_cpuif_rd_ack),
.m_cpuif_rd_err(s_cpuif_rd_err),
.m_cpuif_rd_data(s_cpuif_rd_data),