blob: 37ac4d3224712a0261df9a2f31b1036d69392252 [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 jtag_riscv_agent_pkg;
// dep packages
import uvm_pkg::*;
import dv_utils_pkg::*;
import dv_lib_pkg::*;
import jtag_agent_pkg::*;
// macro includes
`include "uvm_macros.svh"
`include "dv_macros.svh"
// parameters
// JTAG TAP for DMI according to debug spec 0.13
parameter uint DMI_OPW = 2;
parameter uint DMI_DATAW = 32;
parameter uint DMI_ADDRW = 7;
parameter uint DMI_IRW = 5;
parameter uint DMI_DRW = DMI_OPW + DMI_DATAW + DMI_ADDRW;
parameter uint DTMCS_DRW = 32;
// Bits to shift byte address to word address
parameter uint DMI_WORD_SHIFT = $clog2(DMI_DATAW / 8);
uint default_jtag_timeout = 10_000_000;
string msg_id = "jtag_riscv_agent_pkg";
// local types
typedef enum logic [DMI_IRW-1:0] {
JtagBypass0 = 'h0,
JtagIdcode = 'h1,
JtagDtmCsr = 'h10,
JtagDmiAccess = 'h11,
JtagBypass1 = 'h1f
} jtag_ir_e;
typedef enum logic [DMI_OPW-1:0] {
DmiNoErr = 'h0,
DmiReserved = 'h1,
DmiFail = 'h2,
DmiInProgress = 'h3
} jtag_op_status_e;
typedef enum logic [DMI_OPW-1:0] {
DmiStatus = 'h0,
DmiRead = 'h1,
DmiWrite = 'h2
} jtag_op_e;
typedef enum bit [4:0] {
DmiReset = 16,
DmiHardReset = 17
} jtag_dtmcs_e;
typedef enum bit [7:0] {
DmControl = 8'h10,
Sbcs = 8'h38,
SbAddress0 = 8'h39,
SbData0 = 8'h3C
} jtag_dm_csr_e;
typedef enum bit [4:0] {
SbAccess32 = 'd2,
SbAccess = 'd17,
SbReadOnAddr = 'd20,
SbBusy = 'd21
} sbcs_field_e;
// forward declare classes to allow typedefs below
typedef class jtag_riscv_item;
typedef class jtag_riscv_agent_cfg;
// package sources
`include "jtag_riscv_item.sv"
`include "jtag_riscv_agent_cfg.sv"
`include "jtag_riscv_agent_cov.sv"
`include "jtag_riscv_reg_adapter.sv"
`include "jtag_riscv_monitor.sv"
`include "jtag_riscv_driver.sv"
`include "jtag_riscv_sequencer.sv"
`include "jtag_riscv_agent.sv"
`include "jtag_riscv_seq_list.sv"
task automatic jtag_read_csr(bit [bus_params_pkg::BUS_AW-1:0] csr_addr,
jtag_riscv_sequencer seqr,
output bit [bus_params_pkg::BUS_DW-1:0] csr_val);
jtag_riscv_csr_seq jtag_csr_seq = jtag_riscv_csr_seq::type_id::create("jtag_csr_seq");
`DV_CHECK_RANDOMIZE_WITH_FATAL(jtag_csr_seq, addr == csr_addr; do_write == 0;,, msg_id)
jtag_csr_seq.start(seqr);
csr_val = jtag_csr_seq.data;
endtask
task automatic jtag_write_csr(bit [bus_params_pkg::BUS_AW-1:0] csr_addr,
jtag_riscv_sequencer seqr,
bit [bus_params_pkg::BUS_DW-1:0] csr_val);
jtag_riscv_csr_seq jtag_csr_seq = jtag_riscv_csr_seq::type_id::create("jtag_csr_seq");
`DV_CHECK_RANDOMIZE_WITH_FATAL(jtag_csr_seq, addr == csr_addr; do_write == 1; data == csr_val;,
, msg_id)
jtag_csr_seq.start(seqr);
endtask
// spin on a jtag csr read until expected value is matched
task automatic jtag_csr_spinwait(bit [bus_params_pkg::BUS_AW-1:0] csr_addr,
jtag_riscv_sequencer seqr,
bit [bus_params_pkg::BUS_DW-1:0] exp_data,
uint timeout_ns = 1000);
`uvm_info(msg_id, $sformatf("timeout is %d ns", timeout_ns), UVM_MEDIUM)
fork
begin : isolation_fork
bit [bus_params_pkg::BUS_DW-1:0] prev_read_data = 0;
bit [bus_params_pkg::BUS_DW-1:0] read_data = ~exp_data;
fork
while (read_data != exp_data) begin
jtag_read_csr(csr_addr,
seqr,
read_data);
if (prev_read_data != read_data) begin
`uvm_info(msg_id, $sformatf("addr: 0x%0h, data: 0x%0h",
csr_addr, read_data), UVM_LOW)
prev_read_data = read_data;
end
end
begin
`DV_WAIT_TIMEOUT(timeout_ns, msg_id, $sformatf("timeout (addr=0x%0h) == 0x%0h",
csr_addr, exp_data))
end
join_any
disable fork;
end : isolation_fork
join
endtask
endpackage: jtag_riscv_agent_pkg