blob: fea93611117c5fb598405469f58397ead88a482c [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
package dv_utils_pkg;
// dep packages
import uvm_pkg::*;
import bus_params_pkg::*;
// macro includes
`include "dv_macros.svh"
`ifdef UVM
`include "uvm_macros.svh"
`endif
// common parameters used across all benches
parameter int NUM_MAX_INTERRUPTS = 32;
parameter int NUM_MAX_ALERTS = 32;
// types & variables
typedef bit [31:0] uint;
typedef bit [7:0] uint8;
typedef bit [15:0] uint16;
typedef bit [31:0] uint32;
typedef bit [63:0] uint64;
// typedef parameterized pins_if for ease of implementation for interrupts and alerts
typedef virtual pins_if #(NUM_MAX_INTERRUPTS) intr_vif;
typedef virtual pins_if #(1) devmode_vif;
// interface direction / mode - Host or Device
typedef enum bit {
Host,
Device
} if_mode_e;
// speed for the clock
typedef enum int {
ClkFreq24Mhz = 24,
ClkFreq25Mhz = 25,
ClkFreq48Mhz = 48,
ClkFreq50Mhz = 50,
ClkFreq100Mhz = 100
} clk_freq_mhz_e;
// compare operator types
typedef enum {
CompareOpEq,
CompareOpCaseEq,
CompareOpNe,
CompareOpCaseNe,
CompareOpGt,
CompareOpGe,
CompareOpLt,
CompareOpLe
} compare_op_e;
// mem address struct
typedef struct {
uvm_reg_addr_t start_addr;
uvm_reg_addr_t end_addr;
} addr_range_t;
// Enum representing a bus operation type - read or write.
typedef enum bit {
BusOpWrite = 1'b0,
BusOpRead = 1'b1
} bus_op_e;
// Enum representing a type of host requests - read only, write only or random read & write
typedef enum int {
HostReqNone = 0,
HostReqReadOnly = 1,
HostReqWriteOnly = 2,
HostReqReadWrite = 3
} host_req_type_e;
string msg_id = "dv_utils_pkg";
// return the smaller value of 2 inputs
function automatic int min2(int a, int b);
return (a < b) ? a : b;
endfunction
// return the bigger value of 2 inputs
function automatic int max2(int a, int b);
return (a > b) ? a : b;
endfunction
// get absolute value of the input. Usage: absolute(val) or absolute(a - b)
function automatic uint absolute(int val);
return val >= 0 ? val : -val;
endfunction
// endian swaps a 32-bit data word
function automatic logic [31:0] endian_swap(logic [31:0] data);
return {<<8{data}};
endfunction
// endian swaps bytes at a word granularity, while preserving overall word ordering.
//
// e.g. if `arr[] = '{'h0, 'h1, 'h2, 'h3, 'h4, 'h5, 'h6, 'h7}`, this function will produce:
// `'{'h3, 'h2, 'h1, 'h0, 'h7, 'h6, 'h5, 'h4}`
function automatic void endian_swap_byte_arr(ref bit [7:0] arr[]);
arr = {<< byte {arr}};
arr = {<< 32 {arr}};
endfunction
`ifdef UVM
// Simple function to set max errors before quitting sim
function automatic void set_max_quit_count(int n);
uvm_report_server report_server = uvm_report_server::get_server();
report_server.set_max_quit_count(n);
endfunction
// return if uvm_fatal occurred
function automatic bit has_uvm_fatal_occurred();
uvm_report_server report_server = uvm_report_server::get_server();
return report_server.get_severity_count(UVM_FATAL) > 0;
endfunction
// task that waits for the specfied timeout
task automatic wait_timeout(input uint timeout_ns,
input string error_msg_id = msg_id,
input string error_msg = "timeout occurred!",
input bit report_fatal = 1);
#(timeout_ns * 1ns);
if (report_fatal) `uvm_fatal(error_msg_id, error_msg)
else `uvm_error(error_msg_id, error_msg)
endtask : wait_timeout
// get masked data based on provided byte mask; if csr reg handle is provided (optional) then
// masked bytes from csr's mirrored value are returned, else masked bytes are 0's
function automatic bit [bus_params_pkg::BUS_DW-1:0]
get_masked_data(bit [bus_params_pkg::BUS_DW-1:0] data,
bit [bus_params_pkg::BUS_DBW-1:0] mask,
uvm_reg csr = null);
bit [bus_params_pkg::BUS_DW-1:0] csr_data;
csr_data = (csr != null) ? csr.get_mirrored_value() : '0;
get_masked_data = data;
foreach (mask[i]) begin
if (~mask[i]) get_masked_data[i * 8 +: 8] = csr_data[i * 8 +: 8];
end
endfunction
// create a sequence by name and return the handle of uvm_sequence
function automatic uvm_sequence create_seq_by_name(string seq_name);
uvm_object obj;
uvm_factory factory;
uvm_sequence seq;
factory = uvm_factory::get();
obj = factory.create_object_by_name(seq_name, "", seq_name);
if (obj == null) begin
// print factory overrides to help debug
factory.print(1);
`uvm_fatal(msg_id, $sformatf("could not create %0s seq", seq_name))
end
if (!$cast(seq, obj)) begin
`uvm_fatal(msg_id, $sformatf("cast failed - %0s is not a uvm_sequence", seq_name))
end
return seq;
endfunction
`endif
// Returns the hierarchical path to the interface / module N levels up.
//
// Meant to be invoked inside a module or interface.
// hier: String input of the interface / module, typically $sformatf("%m").
// n_levels_up: Integer number of levels up the hierarchy to omit.
// Example: if (hier = tb.dut.foo.bar, n_levels_up = 2), then return tb.dut
function automatic string get_parent_hier(string hier, int n_levels_up = 1);
int idx;
int level;
if (n_levels_up <= 0) return hier;
for (idx = hier.len() - 1; idx >= 0; idx--) begin
if (hier[idx] == ".") level++;
if (level == n_levels_up) break;
end
return (hier.substr(0, idx - 1));
endfunction
// sources
`ifdef UVM
`include "dv_report_server.sv"
`include "dv_vif_wrap.sv"
`endif
endpackage