Skip to content

Commit

Permalink
[rv_dm dv] Instantiate jtag DMI monitor and RAL, tests
Browse files Browse the repository at this point in the history
This commit instantiates the JTAG DMI monitor, the DMI RAL model
adds some exclusions and runs the standard CSR suite of tests on
it.

Signed-off-by: Srikrishna Iyer <sriyer@google.com>
  • Loading branch information
Srikrishna Iyer authored and sriyerg committed Feb 28, 2022
1 parent 272bd8c commit 1f3a0e5
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 43 deletions.
7 changes: 5 additions & 2 deletions hw/ip/rv_dm/dv/env/rv_dm_env.core
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ filesets:
depend:
- lowrisc:dv:ralgen
- lowrisc:dv:cip_lib
- lowrisc:dv:jtag_agent
- lowrisc:dv:dv_base_reg
- lowrisc:dv:jtag_agent
- lowrisc:dv:jtag_dmi_agent
# TODO: we only depend on dm_pkg, which should be separated into its own core file.
- pulp-platform:riscv-dbg:0.1
files:
- rv_dm_env_pkg.sv
- rv_dm_if.sv
Expand All @@ -24,6 +27,7 @@ filesets:
- seq_lib/rv_dm_common_vseq.sv: {is_include_file: true}
- seq_lib/rv_dm_smoke_vseq.sv: {is_include_file: true}
- seq_lib/rv_dm_jtag_dtm_csr_vseq.sv: {is_include_file: true}
- seq_lib/rv_dm_jtag_dmi_csr_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource

generate:
Expand All @@ -38,7 +42,6 @@ generate:
name: rv_dm_debug_mem
ip_hjson: ../../data/rv_dm_debug_mem.hjson


targets:
default:
filesets:
Expand Down
22 changes: 12 additions & 10 deletions hw/ip/rv_dm/dv/env/rv_dm_env.sv
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ class rv_dm_env extends cip_base_env #(
);
`uvm_component_utils(rv_dm_env)

tl_agent m_tl_sba_agent;
jtag_agent m_jtag_agent;
tl_agent m_tl_sba_agent;
jtag_agent m_jtag_agent;
jtag_dmi_monitor m_jtag_dmi_monitor;

`uvm_component_new

Expand Down Expand Up @@ -39,26 +40,27 @@ class rv_dm_env extends cip_base_env #(
end

// create components
m_jtag_agent = jtag_agent::type_id::create("m_jtag_agent", this);
uvm_config_db#(jtag_agent_cfg)::set(this, "m_jtag_agent*", "cfg", cfg.m_jtag_agent_cfg);
cfg.m_jtag_agent_cfg.en_cov = cfg.en_cov;

m_tl_sba_agent = tl_agent::type_id::create("m_tl_sba_agent", this);
uvm_config_db#(tl_agent_cfg)::set(this, "m_tl_sba_agent*", "cfg",
cfg.m_tl_sba_agent_cfg);
cfg.m_tl_sba_agent_cfg.en_cov = cfg.en_cov;

m_jtag_agent = jtag_agent::type_id::create("m_jtag_agent", this);
uvm_config_db#(jtag_agent_cfg)::set(this, "m_jtag_agent*", "cfg", cfg.m_jtag_agent_cfg);
cfg.m_jtag_agent_cfg.en_cov = cfg.en_cov;

m_jtag_dmi_monitor = jtag_dmi_monitor::type_id::create("m_jtag_dmi_monitor", this);
m_jtag_dmi_monitor.cfg = cfg.m_jtag_agent_cfg;
endfunction

function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
if (cfg.en_scb) begin
m_jtag_agent.monitor.analysis_port.connect(scoreboard.jtag_fifo.analysis_export);
m_jtag_agent.monitor.analysis_port.connect(m_jtag_dmi_monitor.jtag_item_fifo.analysis_export);
m_jtag_dmi_monitor.analysis_port.connect(scoreboard.jtag_dmi_fifo.analysis_export);
m_tl_sba_agent.monitor.a_chan_port.connect(scoreboard.tl_sba_a_chan_fifo.analysis_export);
m_tl_sba_agent.monitor.d_chan_port.connect(scoreboard.tl_sba_d_chan_fifo.analysis_export);
end
if (cfg.en_scb) begin
m_jtag_agent.monitor.analysis_port.connect(scoreboard.jtag_fifo.analysis_export);
end
if (cfg.is_active && cfg.m_jtag_agent_cfg.is_active) begin
virtual_sequencer.jtag_sequencer_h = m_jtag_agent.sequencer;
end
Expand Down
99 changes: 97 additions & 2 deletions hw/ip/rv_dm/dv/env/rv_dm_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ class rv_dm_env_cfg extends cip_base_env_cfg #(.RAL_T(rv_dm_regs_reg_block));
rand jtag_agent_cfg m_jtag_agent_cfg;
rand tl_agent_cfg m_tl_sba_agent_cfg;

// The JTAG DMI register model.
rand jtag_dmi_reg_block jtag_dmi_ral;

// A constant that can be referenced from anywhere.
string rom_ral_name = "rv_dm_debug_mem_reg_block";

`uvm_object_utils_begin(rv_dm_env_cfg)
`uvm_field_object(m_jtag_agent_cfg, UVM_DEFAULT)
`uvm_field_object(m_jtag_agent_cfg, UVM_DEFAULT)
`uvm_field_object(m_tl_sba_agent_cfg, UVM_DEFAULT)
`uvm_field_object(jtag_dmi_ral, UVM_DEFAULT)
`uvm_object_utils_end

`uvm_object_new
Expand Down Expand Up @@ -46,9 +50,25 @@ class rv_dm_env_cfg extends cip_base_env_cfg #(.RAL_T(rv_dm_regs_reg_block));
m_jtag_agent_cfg.jtag_dtm_ral.idcode.set_reset(RV_DM_JTAG_IDCODE);

// Create TL agent config obj for the SBA port.
m_tl_sba_agent_cfg = tl_agent_cfg::type_id::create("m_tl_sba_agent_cfg");
m_tl_sba_agent_cfg = tl_agent_cfg::type_id::create("m_tl_sba_agent_cfg");
m_tl_sba_agent_cfg.if_mode = dv_utils_pkg::Device;
m_tl_sba_agent_cfg.is_active = 1'b1;

jtag_dmi_ral = create_jtag_dmi_reg_block(m_jtag_agent_cfg);
// Fix the reset values of these fields based on our design.
`uvm_info(`gfn, "fixing reset values in jtag_dmi_ral", UVM_LOW)
jtag_dmi_ral.hartinfo.dataaddr.set_reset(dm::DataAddr);
jtag_dmi_ral.hartinfo.datasize.set_reset(dm::DataCount);
jtag_dmi_ral.hartinfo.dataaccess.set_reset(1); // TODO: verify this!
jtag_dmi_ral.hartinfo.nscratch.set_reset(2); // TODO: verify this!
jtag_dmi_ral.abstractcs.datacount.set_reset(dm::DataCount);
jtag_dmi_ral.abstractcs.progbufsize.set_reset(dm::ProgBufSize);
jtag_dmi_ral.dmstatus.authenticated.set_reset(1); // No authentication performed.
jtag_dmi_ral.sbcs.sbaccess32.set_reset(1);
jtag_dmi_ral.sbcs.sbasize.set_reset(32);
// TODO(#11095): Sub-word accesses are not implemented.
void'(jtag_dmi_ral.sbcs.sbaccess.set_access("RO"));
apply_jtag_dmi_ral_csr_excl();
endfunction

protected virtual function void post_build_ral_settings(dv_base_reg_block ral);
Expand Down Expand Up @@ -81,4 +101,79 @@ class rv_dm_env_cfg extends cip_base_env_cfg #(.RAL_T(rv_dm_regs_reg_block));
end
endfunction

// Apply RAL exclusions externally since the RAL itself is considered generic. The IP it is used
// in constrains the RAL with its implementation details.
virtual function void apply_jtag_dmi_ral_csr_excl();
csr_excl_item csr_excl = jtag_dmi_ral.get_excl_item();

// We leave the DM 'activated' for CSR tests to reduce noise. We exclude this from further
// writes to avoid side-effects.
csr_excl.add_excl(jtag_dmi_ral.dmcontrol.dmactive.get_full_name(),
CsrExclWrite, CsrNonInitTests);

// This field is tied off to 0 due to no hart array mask being implemented.
// TODO: Change these to access policy.
csr_excl.add_excl(jtag_dmi_ral.dmcontrol.hasel.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.dmcontrol.hartreset.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);

// Selecting a different hart in the middle of random read/writes impact other registers.
csr_excl.add_excl(jtag_dmi_ral.dmcontrol.hartsello.get_full_name(),
CsrExclWrite, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.dmcontrol.hartselhi.get_full_name(),
CsrExclWrite, CsrNonInitTests);

// Writes to other CSRs may affect dmstatus, even the HW reset test.
csr_excl.add_excl(jtag_dmi_ral.dmstatus.get_full_name(), CsrExclCheck, CsrAllTests);

// We have only upto dm::DataCount number of these registers available.
foreach (jtag_dmi_ral.abstractdata[i]) begin
if (i >= dm::DataCount) begin
csr_excl.add_excl(jtag_dmi_ral.abstractdata[i].get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
end
end

// We have only upto dm::ProgBufSize number of these registers available.
foreach (jtag_dmi_ral.progbuf[i]) begin
if (i >= dm::ProgBufSize) begin
csr_excl.add_excl(jtag_dmi_ral.progbuf[i].get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
end
end

// These prevent an SBA access from being triggered, which have other side effects.
csr_excl.add_excl(jtag_dmi_ral.sbcs.sbreadondata.get_full_name(),
CsrExclWrite, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.sbcs.sbreadonaddr.get_full_name(),
CsrExclWrite, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.sbdata0.get_full_name(),
CsrExclWrite, CsrNonInitTests);

// TODO: This should be an access policy change.
csr_excl.add_excl(jtag_dmi_ral.sbcs.sbaccess.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);

// These SBA registers are not implemented, or unsupported due to 32-bit system.
csr_excl.add_excl(jtag_dmi_ral.sbaddress1.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.sbaddress2.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.sbaddress3.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.sbdata2.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
csr_excl.add_excl(jtag_dmi_ral.sbdata3.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);

// Abstractcs cmderr bits are updated by RTL.
csr_excl.add_excl(jtag_dmi_ral.abstractcs.cmderr.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);

// Not all bits of abstractauto are set - and its also impacted by writes to other CSRs.
csr_excl.add_excl(jtag_dmi_ral.abstractauto.get_full_name(),
CsrExclWriteCheck, CsrNonInitTests);
endfunction

endclass
1 change: 1 addition & 0 deletions hw/ip/rv_dm/dv/env/rv_dm_env_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package rv_dm_env_pkg;
import top_pkg::*;
import dv_utils_pkg::*;
import jtag_agent_pkg::*;
import jtag_dmi_agent_pkg::*;
import dv_lib_pkg::*;
import tl_agent_pkg::*;
import cip_base_pkg::*;
Expand Down
18 changes: 9 additions & 9 deletions hw/ip/rv_dm/dv/env/rv_dm_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class rv_dm_scoreboard extends cip_base_scoreboard #(
// TLM agent fifos
uvm_tlm_analysis_fifo #(tl_seq_item) tl_sba_a_chan_fifo;
uvm_tlm_analysis_fifo #(tl_seq_item) tl_sba_d_chan_fifo;
uvm_tlm_analysis_fifo #(jtag_item) jtag_fifo;
uvm_tlm_analysis_fifo #(jtag_dmi_item)jtag_dmi_fifo;

// local queues to hold incoming packets pending comparison
jtag_item jtag_q[$];
Expand All @@ -23,7 +23,7 @@ class rv_dm_scoreboard extends cip_base_scoreboard #(

function void build_phase(uvm_phase phase);
super.build_phase(phase);
jtag_fifo = new("jtag_fifo", this);
jtag_dmi_fifo = new("jtag_dmi_fifo", this);
tl_sba_a_chan_fifo = new("tl_sba_a_chan_fifo", this);
tl_sba_d_chan_fifo = new("tl_sba_d_chan_fifo", this);
// TODO: remove once support alert checking
Expand All @@ -37,17 +37,17 @@ class rv_dm_scoreboard extends cip_base_scoreboard #(
task run_phase(uvm_phase phase);
super.run_phase(phase);
fork
process_jtag_fifo();
process_jtag_dmi_fifo();
process_tl_sba_a_chan_fifo();
process_tl_sba_d_chan_fifo();
join_none
endtask

virtual task process_jtag_fifo();
jtag_item item;
virtual task process_jtag_dmi_fifo();
jtag_dmi_item item;
forever begin
jtag_fifo.get(item);
`uvm_info(`gfn, $sformatf("Received jtag item:\n%0s", item.sprint()), UVM_HIGH)
jtag_dmi_fifo.get(item);
`uvm_info(`gfn, $sformatf("Received jtag DMI item:\n%0s", item.sprint()), UVM_HIGH)
end
endtask

Expand Down Expand Up @@ -133,14 +133,14 @@ class rv_dm_scoreboard extends cip_base_scoreboard #(

virtual function void reset(string kind = "HARD");
super.reset(kind);
jtag_fifo.flush();
jtag_dmi_fifo.flush();
tl_sba_a_chan_fifo.flush();
tl_sba_d_chan_fifo.flush();
endfunction

function void check_phase(uvm_phase phase);
super.check_phase(phase);
`DV_EOT_PRINT_TLM_FIFO_CONTENTS(jtag_item, jtag_fifo)
`DV_EOT_PRINT_TLM_FIFO_CONTENTS(jtag_dmi_item, jtag_dmi_fifo)
`DV_EOT_PRINT_TLM_FIFO_CONTENTS(tl_seq_item, tl_sba_a_chan_fifo)
`DV_EOT_PRINT_TLM_FIFO_CONTENTS(tl_seq_item, tl_sba_d_chan_fifo)
endfunction
Expand Down
26 changes: 25 additions & 1 deletion hw/ip/rv_dm/dv/env/seq_lib/rv_dm_base_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ class rv_dm_base_vseq extends cip_base_vseq #(

// Handles for convenience.
jtag_dtm_reg_block jtag_dtm_ral;
jtag_dmi_reg_block jtag_dmi_ral;

virtual function void set_handles();
super.set_handles();
jtag_dtm_ral = cfg.m_jtag_agent_cfg.jtag_dtm_ral;
jtag_dmi_ral = cfg.jtag_dmi_ral;
endfunction

task pre_start();
Expand All @@ -38,13 +40,17 @@ class rv_dm_base_vseq extends cip_base_vseq #(
virtual task dut_init(string reset_kind = "HARD");
super.dut_init();
// TODO: Randomize the contents of the debug ROM & the program buffer once out of reset.

// "Activate" the DM to facilitate ease of testing.
csr_wr(.ptr(jtag_dmi_ral.dmcontrol.dmactive), .value(1), .blocking(1), .predict(1));
endtask

// Have scan reset also applied at the start.
virtual task apply_reset(string kind = "HARD");
fork
if (kind inside {"HARD", "TRST"}) begin
jtag_dtm_ral.reset(kind);
jtag_dtm_ral.reset("HARD");
jtag_dmi_ral.reset("HARD");
cfg.m_jtag_agent_cfg.vif.do_trst_n();
end
if (kind inside {"HARD", "SCAN"}) apply_scan_reset();
Expand All @@ -71,4 +77,22 @@ class rv_dm_base_vseq extends cip_base_vseq #(
cfg.clk_rst_vif.wait_clks(200);
endtask

// Spawns off a thread to auto-respond to incoming TL accesses on the SBA host interface.
// TODO: Drive intg error on D channel.
// TODO: Drive d_error.
virtual task launch_tl_sba_device_seq(bit blocking = 1'b0);
cip_tl_device_seq m_tl_sba_device_seq;
m_tl_sba_device_seq = cip_tl_device_seq::type_id::create("m_tl_sba_device_seq");
m_tl_sba_device_seq.max_rsp_delay = 80;
m_tl_sba_device_seq.rsp_abort_pct = 25;
`DV_CHECK_RANDOMIZE_FATAL(m_tl_sba_device_seq)
if (blocking) begin
m_tl_sba_device_seq.start(p_sequencer.tl_sba_sequencer_h);
end else begin
fork m_tl_sba_device_seq.start(p_sequencer.tl_sba_sequencer_h); join_none
// To ensure the seq above starts executing before the code following it starts executing.
#0;
end
endtask

endclass : rv_dm_base_vseq
32 changes: 32 additions & 0 deletions hw/ip/rv_dm/dv/env/seq_lib/rv_dm_jtag_dmi_csr_vseq.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// Run the JTAG DMT CSRs through our standard CSR suite via JTAG.
class rv_dm_jtag_dmi_csr_vseq extends rv_dm_base_vseq;
`uvm_object_utils(rv_dm_jtag_dmi_csr_vseq)
`uvm_object_new

constraint num_trans_c {
num_trans inside {[1:2]};
}

// We set these initial inputs to known values to prevent side effects that may affect these
// common tests.
constraint lc_hw_debug_en_c {
lc_hw_debug_en == lc_ctrl_pkg::On;
}
constraint scanmode_c {
scanmode == prim_mubi_pkg::MuBi4False;
}
constraint unavailable_c {
unavailable == 0;
}

virtual task body();
// If writes to DMI SBA registers triggers an access, then ensure the response is sent.
launch_tl_sba_device_seq();
run_csr_vseq_wrapper(.num_times(num_trans), .models({jtag_dmi_ral}));
endtask : body

endclass
2 changes: 1 addition & 1 deletion hw/ip/rv_dm/dv/env/seq_lib/rv_dm_jtag_dtm_csr_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ class rv_dm_jtag_dtm_csr_vseq extends rv_dm_base_vseq;

virtual task body();
run_csr_vseq_wrapper(.num_times(num_trans), .models({jtag_dtm_ral}));
endtask : body
endtask : body

endclass
1 change: 1 addition & 0 deletions hw/ip/rv_dm/dv/env/seq_lib/rv_dm_vseq_list.sv
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
`include "rv_dm_smoke_vseq.sv"
`include "rv_dm_common_vseq.sv"
`include "rv_dm_jtag_dtm_csr_vseq.sv"
`include "rv_dm_jtag_dmi_csr_vseq.sv"
Loading

0 comments on commit 1f3a0e5

Please sign in to comment.