Compare commits
3 Commits
e1b0143830
...
eb91af45a1
| Author | SHA1 | Date | |
|---|---|---|---|
|
eb91af45a1
|
|||
|
be0350dfe7
|
|||
|
73b38f7e55
|
@@ -2,6 +2,13 @@
|
|||||||
LOG_REDIR = >&
|
LOG_REDIR = >&
|
||||||
TIME=/usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]"
|
TIME=/usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]"
|
||||||
|
|
||||||
|
# Enable ccache for Verilator compilation
|
||||||
|
export OBJCACHE = ccache
|
||||||
|
export CXX = clang++
|
||||||
|
export CC = clang
|
||||||
|
export OPT_FAST = -O1
|
||||||
|
export OPT_SLOW = -O0
|
||||||
|
|
||||||
# Makefile variables
|
# Makefile variables
|
||||||
# Use as many threads as possible while keeping 2 for IO, browsing, etc.
|
# Use as many threads as possible while keeping 2 for IO, browsing, etc.
|
||||||
# USE_PROCS = $(( $(shell nproc --all) - 2 ))
|
# USE_PROCS = $(( $(shell nproc --all) - 2 ))
|
||||||
@@ -82,7 +89,7 @@ prepare_area:
|
|||||||
@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi
|
@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# C code generation from SystemVerilog
|
# C code generation from SystemVerilog (optional translation/lint)
|
||||||
#
|
#
|
||||||
build_sv: prepare_area $(SV_OUT)
|
build_sv: prepare_area $(SV_OUT)
|
||||||
|
|
||||||
@@ -98,9 +105,9 @@ $(SV_OUT): $(PROJ_BASE)/logs $(SV_DEPS)
|
|||||||
#
|
#
|
||||||
# C code build to generate testbench executable
|
# C code build to generate testbench executable
|
||||||
#
|
#
|
||||||
build_cpp: build_sv $(CPP_OUT)
|
build_cpp: prepare_area $(CPP_OUT)
|
||||||
|
|
||||||
$(CPP_OUT): $(SV_OUT)
|
$(CPP_OUT): $(SV_DEPS)
|
||||||
$(info #-------------------------)
|
$(info #-------------------------)
|
||||||
$(info # Building CPP ($(USE_PROCS) threads))
|
$(info # Building CPP ($(USE_PROCS) threads))
|
||||||
$(info #-------------------------)
|
$(info #-------------------------)
|
||||||
|
|||||||
@@ -102,10 +102,10 @@ class axi_agent extends uvm_agent;
|
|||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Run phase
|
// Run phase
|
||||||
virtual function void run_phase(uvm_phase phase);
|
virtual task run_phase(uvm_phase phase);
|
||||||
`uvm_info("axi_agent", $sformatf("Running AXI agent: %s as %s",
|
`uvm_info("axi_agent", $sformatf("Running AXI agent: %s as %s",
|
||||||
get_full_name(), agent_type.name()), UVM_LOW)
|
get_full_name(), agent_type.name()), UVM_LOW)
|
||||||
endfunction
|
endtask
|
||||||
endclass : axi_agent
|
endclass : axi_agent
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|||||||
@@ -12,6 +12,30 @@ class axi_agent_config extends uvm_object;
|
|||||||
/// Maximum value of pre_response_delay
|
/// Maximum value of pre_response_delay
|
||||||
int pre_response_delay_max = 20;
|
int pre_response_delay_max = 20;
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// Functional coverage
|
||||||
|
// Cover the *actual* delays produced by the getters.
|
||||||
|
// --------------------------------------------------
|
||||||
|
/* verilator lint_off COVERIGN */
|
||||||
|
covergroup cg_pre_transaction_delay with function sample(int dly);
|
||||||
|
option.per_instance = 1;
|
||||||
|
cp_dly: coverpoint dly {
|
||||||
|
bins min = {pre_transaction_delay_min};
|
||||||
|
bins max = {pre_transaction_delay_max};
|
||||||
|
bins in_range[] = {[pre_transaction_delay_min:pre_transaction_delay_max]};
|
||||||
|
}
|
||||||
|
endgroup
|
||||||
|
|
||||||
|
covergroup cg_pre_response_delay with function sample(int dly);
|
||||||
|
option.per_instance = 1;
|
||||||
|
cp_dly: coverpoint dly {
|
||||||
|
bins min = {pre_response_delay_min};
|
||||||
|
bins max = {pre_response_delay_max};
|
||||||
|
bins in_range[] = {[pre_response_delay_min:pre_response_delay_max]};
|
||||||
|
}
|
||||||
|
endgroup
|
||||||
|
/* verilator lint_on COVERIGN */
|
||||||
|
|
||||||
`uvm_object_utils_begin(axi_agent_config)
|
`uvm_object_utils_begin(axi_agent_config)
|
||||||
`uvm_field_int(pre_transaction_delay_min, UVM_DEFAULT)
|
`uvm_field_int(pre_transaction_delay_min, UVM_DEFAULT)
|
||||||
`uvm_field_int(pre_transaction_delay_max, UVM_DEFAULT)
|
`uvm_field_int(pre_transaction_delay_max, UVM_DEFAULT)
|
||||||
@@ -22,6 +46,8 @@ class axi_agent_config extends uvm_object;
|
|||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
function new(string name = "axi_agent_config");
|
function new(string name = "axi_agent_config");
|
||||||
super.new(name);
|
super.new(name);
|
||||||
|
cg_pre_transaction_delay = new();
|
||||||
|
cg_pre_response_delay = new();
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
@@ -45,6 +71,7 @@ class axi_agent_config extends uvm_object;
|
|||||||
// `uvm_error("get_pre_transaction_delay", "Randomization failed")
|
// `uvm_error("get_pre_transaction_delay", "Randomization failed")
|
||||||
// end
|
// end
|
||||||
dly = $urandom_range(pre_transaction_delay_max, pre_transaction_delay_min);
|
dly = $urandom_range(pre_transaction_delay_max, pre_transaction_delay_min);
|
||||||
|
cg_pre_transaction_delay.sample(dly);
|
||||||
return dly;
|
return dly;
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -62,6 +89,7 @@ class axi_agent_config extends uvm_object;
|
|||||||
// `uvm_error("get_pre_response_delay", "Randomization failed")
|
// `uvm_error("get_pre_response_delay", "Randomization failed")
|
||||||
// end
|
// end
|
||||||
dly = $urandom_range(pre_response_delay_max, pre_response_delay_min);
|
dly = $urandom_range(pre_response_delay_max, pre_response_delay_min);
|
||||||
|
cg_pre_response_delay.sample(dly);
|
||||||
return dly;
|
return dly;
|
||||||
endfunction
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class axi_driver extends uvm_driver; // #(axi_transaction);
|
|||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Run phase
|
// Run phase
|
||||||
virtual function void run_phase(uvm_phase phase);
|
virtual task run_phase(uvm_phase phase);
|
||||||
// Open transaction log file
|
// Open transaction log file
|
||||||
trk_file = $fopen($sformatf("axi_driver.%s.log", agent_type.name()), "w");
|
trk_file = $fopen($sformatf("axi_driver.%s.log", agent_type.name()), "w");
|
||||||
if (trk_file == 0) begin
|
if (trk_file == 0) begin
|
||||||
@@ -58,7 +58,7 @@ class axi_driver extends uvm_driver; // #(axi_transaction);
|
|||||||
|
|
||||||
// Start driver
|
// Start driver
|
||||||
drive_axi(phase);
|
drive_axi(phase);
|
||||||
endfunction
|
endtask
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
virtual task drive_axi(uvm_phase phase);
|
virtual task drive_axi(uvm_phase phase);
|
||||||
|
|||||||
+9
-19
@@ -44,7 +44,7 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
|
|||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Run phase
|
// Run phase
|
||||||
virtual function void run_phase(uvm_phase phase);
|
virtual task run_phase(uvm_phase phase);
|
||||||
// Open transaction log file
|
// Open transaction log file
|
||||||
trk_file = $fopen($sformatf("axi_transactions.%s.log", agent_type.name()), "w");
|
trk_file = $fopen($sformatf("axi_transactions.%s.log", agent_type.name()), "w");
|
||||||
if (trk_file == 0) begin
|
if (trk_file == 0) begin
|
||||||
@@ -55,7 +55,7 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
|
|||||||
|
|
||||||
// Start monitoring
|
// Start monitoring
|
||||||
do_monitor();
|
do_monitor();
|
||||||
endfunction
|
endtask
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Monitor logic to capture transactions
|
// Monitor logic to capture transactions
|
||||||
@@ -93,6 +93,7 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
|
|||||||
txn.txn_type = AXI_WRITE;
|
txn.txn_type = AXI_WRITE;
|
||||||
txn.addr = mon_if.AWADDR;
|
txn.addr = mon_if.AWADDR;
|
||||||
txn.length = mon_if.AWLEN;
|
txn.length = mon_if.AWLEN;
|
||||||
|
txn.size = mon_if.AWSIZE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -112,11 +113,12 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
|
|||||||
if (txn_ph == 2) begin
|
if (txn_ph == 2) begin
|
||||||
if (((mon_if.BREADY != prev_bready) || (mon_if.BVALID != prev_bvalid))
|
if (((mon_if.BREADY != prev_bready) || (mon_if.BVALID != prev_bvalid))
|
||||||
&& ((mon_if.BREADY === 1'b1) && (mon_if.BVALID === 1'b1))) begin
|
&& ((mon_if.BREADY === 1'b1) && (mon_if.BVALID === 1'b1))) begin
|
||||||
txn_ph = 2; // DATA
|
txn_ph = 0; // IDLE
|
||||||
|
|
||||||
// Capture transaction details here
|
// Capture transaction details here
|
||||||
txn.resp = mon_if.WSTRB;
|
txn.resp = mon_if.BRESP;
|
||||||
|
|
||||||
|
txn.sample_coverage();
|
||||||
ap.write(txn);
|
ap.write(txn);
|
||||||
write_transaction_to_file(txn);
|
write_transaction_to_file(txn);
|
||||||
end
|
end
|
||||||
@@ -155,6 +157,7 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
|
|||||||
txn.txn_type = AXI_READ;
|
txn.txn_type = AXI_READ;
|
||||||
txn.addr = mon_if.ARADDR;
|
txn.addr = mon_if.ARADDR;
|
||||||
txn.length = mon_if.ARLEN;
|
txn.length = mon_if.ARLEN;
|
||||||
|
txn.size = mon_if.ARSIZE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -166,27 +169,14 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
|
|||||||
|
|
||||||
// Capture transaction details here
|
// Capture transaction details here
|
||||||
txn.data = mon_if.RDATA;
|
txn.data = mon_if.RDATA;
|
||||||
|
txn.resp = mon_if.RRESP;
|
||||||
|
|
||||||
|
txn.sample_coverage();
|
||||||
ap.write(txn);
|
ap.write(txn);
|
||||||
write_transaction_to_file(txn);
|
write_transaction_to_file(txn);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (((mon_if.ARREADY != prev_arready) || (mon_if.ARVALID != prev_arvalid))
|
|
||||||
&& ((mon_if.ARREADY === 1'b1) && (mon_if.ARVALID === 1'b1))) begin
|
|
||||||
axi_transaction txn;
|
|
||||||
|
|
||||||
txn = axi_transaction::type_id::create("txn");
|
|
||||||
|
|
||||||
// Capture transaction details here
|
|
||||||
txn.txn_type = AXI_READ;
|
|
||||||
txn.addr = mon_if.ARADDR;
|
|
||||||
txn.length = mon_if.ARLEN;
|
|
||||||
|
|
||||||
ap.write(txn);
|
|
||||||
write_transaction_to_file(txn);
|
|
||||||
end
|
|
||||||
|
|
||||||
// Update previous values
|
// Update previous values
|
||||||
prev_arready = mon_if.ARREADY;
|
prev_arready = mon_if.ARREADY;
|
||||||
prev_arvalid = mon_if.ARVALID;
|
prev_arvalid = mon_if.ARVALID;
|
||||||
|
|||||||
@@ -9,6 +9,48 @@ class axi_transaction extends uvm_sequence_item;
|
|||||||
rand bit [2:0] size; // Size
|
rand bit [2:0] size; // Size
|
||||||
rand bit [7:0] length; // Length
|
rand bit [7:0] length; // Length
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// Functional coverage
|
||||||
|
// --------------------------------------------------
|
||||||
|
/* verilator lint_off COVERIGN */
|
||||||
|
covergroup cg_axi_transaction with function sample();
|
||||||
|
option.per_instance = 1;
|
||||||
|
|
||||||
|
cp_type: coverpoint txn_type;
|
||||||
|
cp_size: coverpoint size {
|
||||||
|
bins b0 = {3'd0};
|
||||||
|
bins b1 = {3'd1};
|
||||||
|
bins b2 = {3'd2};
|
||||||
|
bins b3 = {3'd3};
|
||||||
|
bins b4 = {3'd4};
|
||||||
|
bins b5 = {3'd5};
|
||||||
|
bins b6 = {3'd6};
|
||||||
|
bins b7 = {3'd7};
|
||||||
|
}
|
||||||
|
cp_len: coverpoint length {
|
||||||
|
bins single = {8'd0};
|
||||||
|
bins short = {[8'd1:8'd3]};
|
||||||
|
bins mid = {[8'd4:8'd15]};
|
||||||
|
bins long = {[8'd16:8'd255]};
|
||||||
|
}
|
||||||
|
cp_resp: coverpoint resp;
|
||||||
|
cp_strb: coverpoint strb {
|
||||||
|
bins none = {'0};
|
||||||
|
bins full = { {`DATA_WIDTH_DIV_8{1'b1}} };
|
||||||
|
bins other = default;
|
||||||
|
}
|
||||||
|
cp_addr_lsb: coverpoint addr[11:0] {
|
||||||
|
bins aligned = {12'h000};
|
||||||
|
bins unaligned = default;
|
||||||
|
}
|
||||||
|
cp_addr_msb: coverpoint addr[`ADDR_WIDTH-1 -: 4] iff (`ADDR_WIDTH >= 4);
|
||||||
|
|
||||||
|
x_type_size: cross cp_type, cp_size;
|
||||||
|
x_type_len: cross cp_type, cp_len;
|
||||||
|
x_type_resp: cross cp_type, cp_resp;
|
||||||
|
endgroup
|
||||||
|
/* verilator lint_on COVERIGN */
|
||||||
|
|
||||||
`uvm_object_utils_begin(axi_transaction)
|
`uvm_object_utils_begin(axi_transaction)
|
||||||
`uvm_field_enum(axi_transaction_type_t, txn_type, UVM_DEFAULT)
|
`uvm_field_enum(axi_transaction_type_t, txn_type, UVM_DEFAULT)
|
||||||
`uvm_field_int(addr, UVM_DEFAULT)
|
`uvm_field_int(addr, UVM_DEFAULT)
|
||||||
@@ -22,6 +64,11 @@ class axi_transaction extends uvm_sequence_item;
|
|||||||
// Constructor
|
// Constructor
|
||||||
function new(string name = "axi_transaction");
|
function new(string name = "axi_transaction");
|
||||||
super.new(name);
|
super.new(name);
|
||||||
|
cg_axi_transaction = new();
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function void sample_coverage();
|
||||||
|
cg_axi_transaction.sample();
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
// Get transaction id - made up of sequence ID and trasacton ID
|
// Get transaction id - made up of sequence ID and trasacton ID
|
||||||
|
|||||||
Reference in New Issue
Block a user