[i2c, dv] Add i2c_stress_with_rand_reset test
Signed-off-by: Tung Hoang <hoang.tung@wdc.com>
diff --git a/hw/dv/sv/cip_lib/cip_base_vseq.sv b/hw/dv/sv/cip_lib/cip_base_vseq.sv
index 8342b5c..2de8b00 100644
--- a/hw/dv/sv/cip_lib/cip_base_vseq.sv
+++ b/hw/dv/sv/cip_lib/cip_base_vseq.sv
@@ -541,12 +541,12 @@
end
join
wait(ongoing_reset == 0);
- `uvm_info(`gfn, $sformatf("Finished run %0d/%0d w/o reset", i, num_times), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\nFinished run %0d/%0d w/o reset", i, num_times), UVM_LOW)
end
begin : issue_rand_reset
cfg.clk_rst_vif.wait_clks(delay_to_reset);
ongoing_reset = 1'b1;
- `uvm_info(`gfn, $sformatf("Reset is issued for run %0d/%0d", i, num_times), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\nReset is issued for run %0d/%0d", i, num_times), UVM_LOW)
apply_reset("HARD");
ongoing_reset = 1'b0;
do_read_and_check_all_csrs = 1'b1;
@@ -554,7 +554,7 @@
join_any
p_sequencer.tl_sequencer_h.stop_sequences();
disable fork;
- `uvm_info(`gfn, $sformatf("Stress w/ reset is done for run %0d/%0d", i, num_times),
+ `uvm_info(`gfn, $sformatf("\nStress w/ reset is done for run %0d/%0d", i, num_times),
UVM_LOW)
// delay to avoid race condition when sending item and checking no item after reset occur
// at the same time
diff --git a/hw/dv/sv/i2c_agent/i2c_device_driver.sv b/hw/dv/sv/i2c_agent/i2c_device_driver.sv
index e1efdd1..0c4d562 100755
--- a/hw/dv/sv/i2c_agent/i2c_device_driver.sv
+++ b/hw/dv/sv/i2c_agent/i2c_device_driver.sv
@@ -34,47 +34,50 @@
// device driver responses to dut
seq_item_port.get_next_item(rsp_item);
fork
- unique case (rsp_item.drv_type)
- DevAck: begin
- cfg.timing_cfg.tStretchHostClock = gen_num_stretch_host_clks(cfg.timing_cfg);
- fork
- // host clock stretching allows a high-speed host to communicate
- // with a low-speed device by setting TIMEOUT_CTRL.EN bit
- // the device asks host stretching its scl_i by pulling down scl_o
- // the host clock pulse is extended until device scl_o is pulled up
- // once scl_o is pulled down longer than TIMEOUT_CTRL.VAL field,
- // intr_stretch_timeout_o is asserted (ref. https://www.i2c-bus.org/clock-stretching)
- cfg.vif.device_stretch_host_clk(cfg.timing_cfg);
- cfg.vif.device_send_ack(cfg.timing_cfg);
- join
- end
- RdData: begin
- if (rd_data_cnt == 8'd0) `DV_CHECK_MEMBER_RANDOMIZE_FATAL(rd_data)
- for (int i = 7; i >= 0; i--) begin
- cfg.vif.device_send_bit(cfg.timing_cfg, rd_data[rd_data_cnt][i]);
+ begin: iso_fork
+ fork
+ unique case (rsp_item.drv_type)
+ DevAck: begin
+ cfg.timing_cfg.tStretchHostClock = gen_num_stretch_host_clks(cfg.timing_cfg);
+ fork
+ // host clock stretching allows a high-speed host to communicate
+ // with a low-speed device by setting TIMEOUT_CTRL.EN bit
+ // the device asks host stretching its scl_i by pulling down scl_o
+ // the host clock pulse is extended until device scl_o is pulled up
+ // once scl_o is pulled down longer than TIMEOUT_CTRL.VAL field,
+ // intr_stretch_timeout_o is asserted (ref. https://www.i2c-bus.org/clock-stretching)
+ cfg.vif.device_stretch_host_clk(cfg.timing_cfg);
+ cfg.vif.device_send_ack(cfg.timing_cfg);
+ join
+ end
+ RdData: begin
+ if (rd_data_cnt == 8'd0) `DV_CHECK_MEMBER_RANDOMIZE_FATAL(rd_data)
+ for (int i = 7; i >= 0; i--) begin
+ cfg.vif.device_send_bit(cfg.timing_cfg, rd_data[rd_data_cnt][i]);
+ end
+ `uvm_info(`gfn, $sformatf("\ndriver, trans %0d, byte %0d %0x",
+ rsp_item.tran_id, rsp_item.num_data+1, rd_data[rd_data_cnt]), UVM_DEBUG)
+ // rd_data_cnt is rollled back (no overflow) after reading 256 bytes
+ rd_data_cnt++;
+ end
+ WrData:
+ // TODO: consider adding memory (associative array) in device_driver
+ for (int i = 7; i >= 0; i--) begin
+ cfg.vif.get_bit_data("host", cfg.timing_cfg, wr_data[i]);
+ end
+ default: begin
+ `uvm_fatal(`gfn, $sformatf("\ndriver, received invalid request from monitor/seq"))
+ end
+ endcase
+ // handle on-the-fly reset
+ begin
+ process_reset();
+ rsp_item.clear_all();
end
- `uvm_info(`gfn, $sformatf("\ndriver, trans %0d, byte %0d %0x",
- rsp_item.tran_id, rsp_item.num_data+1, rd_data[rd_data_cnt]), UVM_DEBUG)
- // rd_data_cnt is rollled back (no overflow) after reading 256 bytes
- rd_data_cnt++;
- end
- WrData:
- // TODO: consider adding memory (associative array) in device_driver
- for (int i = 7; i >= 0; i--) begin
- cfg.vif.get_bit_data("host", cfg.timing_cfg, wr_data[i]);
- end
- default: begin
- `uvm_fatal(`gfn, $sformatf("\ndriver, received invalid request from monitor/seq"))
- end
- endcase
-
- // handle on-the-fly reset
- begin
- process_reset();
- rsp_item.clear_all();
- end
- join_any
- disable fork;
+ join_any
+ disable fork;
+ end: iso_fork
+ join
seq_item_port.item_done();
end
endtask : get_and_drive
diff --git a/hw/dv/sv/i2c_agent/i2c_if.sv b/hw/dv/sv/i2c_agent/i2c_if.sv
index 844d494..7474c1e 100644
--- a/hw/dv/sv/i2c_agent/i2c_if.sv
+++ b/hw/dv/sv/i2c_agent/i2c_if.sv
@@ -165,7 +165,7 @@
// will be asserted if the IP identifies that some other device (host or target) on the bus
// is forcing scl low and interfering with the transmission.
task automatic device_stretch_host_clk(ref timing_cfg_t tc);
- if (tc.enbTimeOut) begin
+ if (tc.enbTimeOut && tc.tTimeOut > 0) begin
wait_for_dly(tc.tClockLow + tc.tSetupBit + tc.tSclInterference - 1);
scl_o = 1'b0;
wait_for_dly(tc.tStretchHostClock - tc.tSclInterference + 1);
diff --git a/hw/dv/sv/i2c_agent/i2c_monitor.sv b/hw/dv/sv/i2c_agent/i2c_monitor.sv
index 708f29b..5efee93 100755
--- a/hw/dv/sv/i2c_agent/i2c_monitor.sv
+++ b/hw/dv/sv/i2c_agent/i2c_monitor.sv
@@ -35,50 +35,54 @@
virtual task run_phase(uvm_phase phase);
wait(cfg.vif.rst_ni);
- collect_thread(phase);
+ forever begin
+ fork
+ begin: iso_fork
+ fork
+ begin
+ collect_thread(phase);
+ end
+ begin // if (on-the-fly) reset is monitored, drop the item
+ wait_for_reset_and_drop_item();
+ `uvm_info(`gfn, $sformatf("\nmonitor is reset, drop item\n%s",
+ mon_dut_item.sprint()), UVM_DEBUG)
+ end
+ join_any
+ disable fork;
+ end: iso_fork
+ join
+ end
endtask : run_phase
// collect transactions forever
virtual protected task collect_thread(uvm_phase phase);
- i2c_item complete_item;
+ i2c_item complete_item;
- forever begin
- fork
- begin
- wait(cfg.en_monitor);
- if (mon_dut_item.stop ||
- (!mon_dut_item.stop && !mon_dut_item.start && !mon_dut_item.rstart)) begin
- cfg.vif.wait_for_host_start(cfg.timing_cfg);
- `uvm_info(`gfn, "\nmonitor, detect HOST START", UVM_DEBUG)
- end else begin
- mon_dut_item.rstart = 1'b1;
- end
- num_dut_tran++;
- mon_dut_item.start = 1'b1;
- // monitor address for non-chained reads
- address_thread();
- // monitor read/write data
- if (mon_dut_item.bus_op == BusOpRead) read_thread();
- else write_thread();
- // send rsp_item to scoreboard
- `downcast(complete_item, mon_dut_item.clone());
- complete_item.stop = 1'b1;
- if (complete_item.start) begin
- if (complete_item.bus_op == BusOpRead) rd_item_port.write(complete_item);
- else wr_item_port.write(complete_item);
- `uvm_info(`gfn, $sformatf("\nmonitor, send to scb, complete_item\n%s",
- complete_item.sprint()), UVM_DEBUG)
- end
- mon_dut_item.clear_data();
- end
- begin // if (on-the-fly) reset is monitored, drop the item
- wait_for_reset_and_drop_item();
- `uvm_info(`gfn, $sformatf("\nmonitor is reset, drop item\n%s",
- mon_dut_item.sprint()), UVM_DEBUG)
- end
- join_any
- disable fork;
+ wait(cfg.en_monitor);
+ if (mon_dut_item.stop ||
+ (!mon_dut_item.stop && !mon_dut_item.start && !mon_dut_item.rstart)) begin
+ cfg.vif.wait_for_host_start(cfg.timing_cfg);
+ `uvm_info(`gfn, "\nmonitor, detect HOST START", UVM_DEBUG)
+ end else begin
+ mon_dut_item.rstart = 1'b1;
end
+ num_dut_tran++;
+ mon_dut_item.start = 1'b1;
+ // monitor address for non-chained reads
+ address_thread();
+ // monitor read/write data
+ if (mon_dut_item.bus_op == BusOpRead) read_thread();
+ else write_thread();
+ // send rsp_item to scoreboard
+ `downcast(complete_item, mon_dut_item.clone());
+ complete_item.stop = 1'b1;
+ if (cfg.vif.rst_ni && complete_item.stop && complete_item.start) begin
+ if (complete_item.bus_op == BusOpRead) rd_item_port.write(complete_item);
+ else wr_item_port.write(complete_item);
+ `uvm_info(`gfn, $sformatf("\nmonitor, send complete item to scb\n%s",
+ complete_item.sprint()), UVM_DEBUG)
+ end
+ mon_dut_item.clear_data();
endtask: collect_thread
virtual protected task address_thread();
@@ -121,6 +125,8 @@
end
mon_dut_item.data_q.push_back(mon_data);
mon_dut_item.num_data++;
+ `uvm_info(`gfn, $sformatf("\nmonitor, rd_data, trans %0d, byte %0d 0x%0x",
+ mon_dut_item.tran_id, mon_dut_item.num_data, mon_data), UVM_DEBUG)
// sample host ack/nack (in the last byte, nack can be issue if rcont is set)
cfg.vif.wait_for_host_ack_or_nack(cfg.timing_cfg, mon_dut_item.ack, mon_dut_item.nack);
`DV_CHECK_NE_FATAL({mon_dut_item.ack, mon_dut_item.nack}, 2'b11)
diff --git a/hw/ip/i2c/dv/env/i2c_env_cfg.sv b/hw/ip/i2c/dv/env/i2c_env_cfg.sv
index 186e897..bf39efc 100644
--- a/hw/ip/i2c/dv/env/i2c_env_cfg.sv
+++ b/hw/ip/i2c/dv/env/i2c_env_cfg.sv
@@ -10,9 +10,6 @@
// drained time of phase_ready_to_end
uint ok_to_end_delay_ns = 5000;
- // set start_dev_seq at the first time m_dev_seq is started
- bit start_dev_seq = 1'b0;
-
// i2c_agent cfg
rand i2c_agent_cfg m_i2c_agent_cfg;
diff --git a/hw/ip/i2c/dv/env/i2c_scoreboard.sv b/hw/ip/i2c/dv/env/i2c_scoreboard.sv
index d5f27d8..a9d91a0 100644
--- a/hw/ip/i2c/dv/env/i2c_scoreboard.sv
+++ b/hw/ip/i2c/dv/env/i2c_scoreboard.sv
@@ -88,7 +88,7 @@
bit [7:0] fbyte;
bit start, stop, read, rcont, nakok;
- if (host_init) begin
+ if (!cfg.under_reset && host_init) begin
fbyte = get_field_val(ral.fdata.fbyte, item.a_data);
start = bit'(get_field_val(ral.fdata.start, item.a_data));
stop = bit'(get_field_val(ral.fdata.stop, item.a_data));
@@ -164,7 +164,7 @@
if (cfg.seq_cfg.en_rx_overflow) exp_rd_item.num_data--;
// if not a chained read (stop is issued)
if (exp_rd_item.stop) begin
- `uvm_info(`gfn, $sformatf("\nscoreboard, exp_rd_item\n\%s",
+ `uvm_info(`gfn, $sformatf("\nscoreboard, partial exp_rd_item\n\%s",
exp_rd_item.sprint()), UVM_DEBUG)
`downcast(tmp_rd_item, exp_rd_item.clone());
rd_pending_q.push_back(tmp_rd_item);
@@ -205,7 +205,7 @@
end
endcase
// get full write transaction
- if (host_init && sb_exp_wr_item.start && sb_exp_wr_item.stop) begin
+ if (!cfg.under_reset && host_init && sb_exp_wr_item.start && sb_exp_wr_item.stop) begin
exp_wr_q.push_back(sb_exp_wr_item);
num_exp_tran++;
`uvm_info(`gfn, $sformatf("\nscoreboard, push to queue, exp_wr_item\n\%s",
@@ -305,7 +305,12 @@
tran_id = 0;
rdata_cnt = 0;
num_exp_tran = 0;
- `uvm_info(`gfn, "\n>>> scoreboard is reset", UVM_DEBUG)
+ `uvm_info(`gfn, "\n>>> finish resetting scoreboard", UVM_DEBUG)
+ `DV_EOT_PRINT_Q_CONTENTS(i2c_item, exp_wr_q)
+ `DV_EOT_PRINT_Q_CONTENTS(i2c_item, exp_rd_q)
+ `DV_EOT_PRINT_Q_CONTENTS(i2c_item, rd_pending_q)
+ `DV_EOT_PRINT_TLM_FIFO_CONTENTS(i2c_item, rd_item_fifo)
+ `DV_EOT_PRINT_TLM_FIFO_CONTENTS(i2c_item, wr_item_fifo)
endfunction : reset
function void report_phase(uvm_phase phase);
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv
index 323db9c..cb9281d 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_base_vseq.sv
@@ -170,17 +170,17 @@
`uvm_object_new
- task pre_start();
+ virtual task pre_start();
+ cfg.reset_seq_cfg();
// sync monitor and scoreboard setting
cfg.m_i2c_agent_cfg.en_monitor = cfg.en_scb;
`uvm_info(`gfn, $sformatf("\n %s monitor and scoreboard",
cfg.en_scb ? "enable" : "disable"), UVM_DEBUG)
num_runs.rand_mode(0);
super.pre_start();
- print_seq_cfg_vars("pre-start");
endtask : pre_start
- task post_start();
+ virtual task post_start();
// env_cfg must be reset after vseq completion
cfg.reset_seq_cfg();
super.post_start();
@@ -188,22 +188,20 @@
endtask : post_start
virtual task initialization();
+ wait(cfg.m_i2c_agent_cfg.vif.rst_ni);
device_init();
host_init();
+ `uvm_info(`gfn, "\n initialization is done", UVM_DEBUG)
endtask : initialization
virtual task device_init();
i2c_device_seq m_dev_seq;
- if (!cfg.start_dev_seq) begin
- m_dev_seq = i2c_device_seq::type_id::create("m_dev_seq");
- `uvm_info(`gfn, "\n start i2c_device sequence", UVM_DEBUG)
- fork
- m_dev_seq.start(p_sequencer.i2c_sequencer_h);
- join_none
- // prevent multiple starts of m_dev_seq
- cfg.start_dev_seq = 1'b1;
- end
+ m_dev_seq = i2c_device_seq::type_id::create("m_dev_seq");
+ `uvm_info(`gfn, "\n start i2c_device sequence", UVM_DEBUG)
+ fork
+ m_dev_seq.start(p_sequencer.i2c_sequencer_h);
+ join_none
endtask : device_init
virtual task host_init();
@@ -226,7 +224,7 @@
//enable then clear interrupts
csr_wr(.csr(ral.intr_enable), .value({TL_DW{1'b1}}));
- csr_wr(.csr(ral.intr_state), .value({TL_DW{1'b0}}));
+ process_interrupts();
endtask : host_init
virtual task wait_for_reprogram_registers();
@@ -327,7 +325,7 @@
csr_update(ral.fifo_ctrl);
endtask : program_registers
- virtual task program_format_flag(i2c_item item, string msg = "", bit en_print = 1'b0);
+ virtual task program_format_flag(i2c_item item, string msg = "", bit do_print = 1'b0);
bit fmtfull;
ral.fdata.nakok.set(item.nakok);
@@ -350,44 +348,74 @@
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(fmt_fifo_access_dly)
cfg.clk_rst_vif.wait_clks(fmt_fifo_access_dly);
- print_format_flag(item, msg, en_print);
+ print_format_flag(item, msg, do_print);
endtask : program_format_flag
+ // read interrupts and randomly clear interrupts if set
+ virtual task process_interrupts();
+ bit [TL_DW-1:0] intr_state, intr_clear;
- virtual function void print_seq_cfg_vars(string msg = "");
- string str;
+ // read interrupt
+ csr_rd(.ptr(ral.intr_state), .value(intr_state));
+ // clear interrupt if it is set
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(intr_clear,
+ foreach (intr_clear[i]) {
+ intr_state[i] -> intr_clear[i] == 1;
+ })
- str = {str, $sformatf("\n %s, %s, i2c_seq_cfg", msg, get_name())};
- str = {str, $sformatf("\n en_scb %b", cfg.en_scb)};
- str = {str, $sformatf("\n en_monitor %b", cfg.m_i2c_agent_cfg.en_monitor)};
- str = {str, $sformatf("\n do_dut_init %b", do_dut_init)};
- str = {str, $sformatf("\n en_fmt_overflow %b", cfg.seq_cfg.en_fmt_overflow)};
- str = {str, $sformatf("\n en_rx_overflow %b", cfg.seq_cfg.en_rx_overflow)};
- str = {str, $sformatf("\n en_rx_watermark %b", cfg.seq_cfg.en_rx_watermark)};
- str = {str, $sformatf("\n en_sda_unstable %b", cfg.seq_cfg.en_sda_unstable)};
- str = {str, $sformatf("\n en_scl_interference %b", cfg.seq_cfg.en_scl_interference)};
- str = {str, $sformatf("\n en_sda_interference %b", cfg.seq_cfg.en_sda_interference)};
- `uvm_info(`gfn, $sformatf("%s", str), UVM_DEBUG)
+ if (bit'(get_field_val(ral.intr_state.fmt_watermark, intr_clear))) begin
+ `uvm_info(`gfn, "\n clearing fmt_watermark", UVM_DEBUG)
+ end
+ if (bit'(get_field_val(ral.intr_state.rx_watermark, intr_clear))) begin
+ `uvm_info(`gfn, "\n clearing rx_watermark", UVM_DEBUG)
+ end
+
+ `DV_CHECK_MEMBER_RANDOMIZE_FATAL(clear_intr_dly)
+ cfg.clk_rst_vif.wait_clks(clear_intr_dly);
+ csr_wr(.csr(ral.intr_state), .value(intr_clear));
+ endtask : process_interrupts
+
+ virtual task clear_interrupt(i2c_intr_e intr, bit verify_clear = 1'b1);
+ csr_wr(.csr(ral.intr_state), .value(1 << intr));
+ if (verify_clear) wait(!cfg.intr_vif.pins[intr]);
+ endtask : clear_interrupt
+
+ virtual function void print_seq_cfg_vars(string msg = "", bit do_print = 1'b0);
+ if (do_print) begin
+ string str;
+ str = {str, $sformatf("\n %s, %s, i2c_seq_cfg", msg, get_name())};
+ str = {str, $sformatf("\n en_scb %b", cfg.en_scb)};
+ str = {str, $sformatf("\n en_monitor %b", cfg.m_i2c_agent_cfg.en_monitor)};
+ str = {str, $sformatf("\n do_dut_init %b", do_dut_init)};
+ str = {str, $sformatf("\n en_fmt_overflow %b", cfg.seq_cfg.en_fmt_overflow)};
+ str = {str, $sformatf("\n en_rx_overflow %b", cfg.seq_cfg.en_rx_overflow)};
+ str = {str, $sformatf("\n en_rx_watermark %b", cfg.seq_cfg.en_rx_watermark)};
+ str = {str, $sformatf("\n en_sda_unstable %b", cfg.seq_cfg.en_sda_unstable)};
+ str = {str, $sformatf("\n en_scl_interference %b", cfg.seq_cfg.en_scl_interference)};
+ str = {str, $sformatf("\n en_sda_interference %b", cfg.seq_cfg.en_sda_interference)};
+ `uvm_info(`gfn, $sformatf("%s", str), UVM_LOW)
+ end
endfunction : print_seq_cfg_vars
- task print_format_flag(i2c_item item, string msg = "", bit en_print = 1'b0);
- string str;
-
- str = {str, $sformatf("\n%s, format flags 0x%h \n", msg,
- {item.nakok, item.rcont, item.read, item.stop, item.start, item.fbyte})};
- if (item.start) begin
- str = {str, $sformatf(" | %5s | %5s | %5s | %5s | %5s | %8s | %3s |\n",
- "nakok", "rcont", "read", "stop", "start", "addr", "r/w")};
- str = {str, $sformatf(" | %5d | %5d | %5d | %5d | %5d | %8x | %3s |",
- item.nakok, item.rcont, item.read, item.stop, item.start, item.fbyte[7:1],
- (item.fbyte[0]) ? "R" : "W")};
- end else begin
- str = {str, $sformatf(" | %5s | %5s | %5s | %5s | %5s | %8s |\n",
- "nakok", "rcont", "read", "stop", "start", "fbyte")};
- str = {str, $sformatf(" | %5d | %5d | %5d | %5d | %5d | %8x |",
- item.nakok, item.rcont, item.read, item.stop, item.start, item.fbyte)};
+ virtual function print_format_flag(i2c_item item, string msg = "", bit do_print = 1'b0);
+ if (do_print) begin
+ string str;
+ str = {str, $sformatf("\n%s, format flags 0x%h \n", msg,
+ {item.nakok, item.rcont, item.read, item.stop, item.start, item.fbyte})};
+ if (item.start) begin
+ str = {str, $sformatf(" | %5s | %5s | %5s | %5s | %5s | %8s | %3s |\n",
+ "nakok", "rcont", "read", "stop", "start", "addr", "r/w")};
+ str = {str, $sformatf(" | %5d | %5d | %5d | %5d | %5d | %8x | %3s |",
+ item.nakok, item.rcont, item.read, item.stop, item.start, item.fbyte[7:1],
+ (item.fbyte[0]) ? "R" : "W")};
+ end else begin
+ str = {str, $sformatf(" | %5s | %5s | %5s | %5s | %5s | %8s |\n",
+ "nakok", "rcont", "read", "stop", "start", "fbyte")};
+ str = {str, $sformatf(" | %5d | %5d | %5d | %5d | %5d | %8x |",
+ item.nakok, item.rcont, item.read, item.stop, item.start, item.fbyte)};
+ end
+ `uvm_info(`gfn, $sformatf("%s", str), UVM_LOW)
end
- if (en_print) `uvm_info(`gfn, $sformatf("%s", str), UVM_LOW)
- endtask : print_format_flag
+ endfunction : print_format_flag
endclass : i2c_base_vseq
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_error_intr_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_error_intr_vseq.sv
index 81d19d9..8fb8019 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_error_intr_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_error_intr_vseq.sv
@@ -17,18 +17,19 @@
constraint num_trans_c { num_trans inside {[40 : 50]}; }
virtual task pre_start();
+ super.pre_start();
// allow agent/target creating interference and unstable signals so
// sda_interference, scl_interference, sda_unstable are asserted
cfg.seq_cfg.en_sda_unstable = 1'b1;
cfg.seq_cfg.en_sda_interference = 1'b1;
cfg.seq_cfg.en_scl_interference = 1'b1;
- super.pre_start();
+ print_seq_cfg_vars("pre-start");
endtask : pre_start
virtual task body();
-
`uvm_info(`gfn, "\n--> start of i2c_error_intr_vseq", UVM_DEBUG)
initialization();
+ do_dut_init = 1'b1;
for (int i = 1; i <= num_runs; i++) begin
`uvm_info(`gfn, $sformatf("\n run simulation %0d/%0d", i, num_runs), UVM_DEBUG)
fork
@@ -38,10 +39,9 @@
begin
process_error_interrupts();
apply_reset("HARD");
- `uvm_info(`gfn, $sformatf("\n reset is issued"), UVM_DEBUG)
+ `uvm_info(`gfn, $sformatf("\n reset is issued within error_intr_vseq"), UVM_DEBUG)
end
begin
- `DV_CHECK_MEMBER_RANDOMIZE_FATAL(num_trans)
host_send_trans(num_trans);
end
join_any
@@ -53,7 +53,7 @@
#1ps;
if (do_reset) begin
// re-initialize dut after on-the-fly reset
- host_init();
+ initialization();
do_reset = 1'b0;
end
end
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_full_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_full_vseq.sv
index aafe71c..21e74c2 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_full_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_full_vseq.sv
@@ -31,8 +31,9 @@
virtual task pre_start();
// hold reading rx_fifo to ensure rx_fifo gets full
- cfg.seq_cfg.en_rx_watermark = 1'b1;
super.pre_start();
+ cfg.seq_cfg.en_rx_watermark = 1'b1;
+ print_seq_cfg_vars("pre-start");
endtask : pre_start
virtual task body();
@@ -48,7 +49,7 @@
end
join
// verify either fmt_fifo or rx_fifo has been in full status
- `DV_CHECK_EQ((fmt_fifo_full | rx_fifo_full), 1'b1);
+ if (!cfg.under_reset) `DV_CHECK_EQ((fmt_fifo_full | rx_fifo_full), 1'b1);
`uvm_info(`gfn, "\n--> end of i2c_fifo_full_vseq", UVM_DEBUG)
endtask : body
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_overflow_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_overflow_vseq.sv
index 53da53e..13def2a 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_overflow_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_overflow_vseq.sv
@@ -27,10 +27,11 @@
local uint cnt_rx_overflow;
virtual task pre_start();
+ super.pre_start();
// config fmt_overflow and rx_overflow tests
cfg.seq_cfg.en_fmt_overflow = 1'b1;
cfg.seq_cfg.en_rx_overflow = 1'b1;
- super.pre_start();
+ print_seq_cfg_vars("pre-start");
endtask : pre_start
virtual task body();
@@ -81,10 +82,10 @@
end
end
begin
- while (check_fmt_overflow) process_fmt_overflow_intr();
+ while (!cfg.under_reset && check_fmt_overflow) process_fmt_overflow_intr();
end
begin
- while (check_rx_overflow) process_rx_overflow_intr();
+ while (!cfg.under_reset && check_rx_overflow) process_rx_overflow_intr();
end
join
end
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_watermark_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_watermark_vseq.sv
index 7ed583d..6814897 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_watermark_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_fifo_watermark_vseq.sv
@@ -28,9 +28,10 @@
local uint cnt_rx_watermark;
virtual task pre_start();
+ super.pre_start();
// config rx_watermark test (fmt_watermark test is auto configured)
cfg.seq_cfg.en_rx_watermark = 1'b1;
- super.pre_start();
+ print_seq_cfg_vars("pre-start");
endtask : pre_start
virtual task body();
@@ -93,10 +94,10 @@
end
end
begin
- while (check_fmt_watermark) process_fmt_watermark_intr();
+ while (!cfg.under_reset && check_fmt_watermark) process_fmt_watermark_intr();
end
begin
- while (check_rx_watermark) process_rx_watermark_intr();
+ while (!cfg.under_reset && check_rx_watermark) process_rx_watermark_intr();
end
join
end
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_override_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_override_vseq.sv
index 637d0fe..2a36d43 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_override_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_override_vseq.sv
@@ -13,12 +13,12 @@
constraint txovrden_c { txovrden dist {1 :/ 3, 0 :/ 1}; };
task pre_start();
+ super.pre_start();
// for this vseq, $value$plusargs "+en_scb=0" is defined in i2c_sim_cfg.hjson
// disable i2c_monitor and i2c_scoreboard since they can not handle this test
-
// disable clear_all_interrupts task due to abnormal assertion of interrupts
do_clear_all_interrupts = 1'b0;
- super.pre_start();
+ print_seq_cfg_vars("pre-start");
endtask : pre_start
task body();
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv
index 8af9477..df6181c 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_rx_tx_vseq.sv
@@ -10,12 +10,12 @@
local uint total_rd_bytes;
virtual task body();
- bit do_interrupt = 1'b1;
+ bit do_interrupt = 1'b0;
initialization();
`uvm_info(`gfn, "\n--> start of sequence", UVM_DEBUG)
fork
begin
- while (do_interrupt) process_interrupts();
+ while (!cfg.under_reset && do_interrupt) process_interrupts();
end
begin
host_send_trans(num_trans);
@@ -23,7 +23,6 @@
end
join
`uvm_info(`gfn, "\n--> end of sequence", UVM_DEBUG)
-
endtask : body
virtual task host_send_trans(int max_trans = num_trans, tran_type_e trans_type = ReadWrite);
@@ -118,37 +117,34 @@
virtual task program_control_read_to_target(bit last_tran);
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(num_rd_bytes)
- begin
- `DV_CHECK_RANDOMIZE_WITH_FATAL(fmt_item,
- fbyte == num_rd_bytes;
- start == 1'b0;
- read == 1'b1;
- // for the last write byte of last tran., stop flag must be set to issue stop bit (stimulus end)
- // otherwise, stop can be randomly set/unset to issue stop/rstart bit respectively
- // rcont is derived from stop and read to issue chained/non-chained reads
- stop == (last_tran) ? 1'b1 : stop;
- )
- `DV_CHECK_EQ(fmt_item.stop | fmt_item.rcont, 1)
- if (num_rd_bytes == 0) begin
- `uvm_info(`gfn, "\n read transaction length is 256 byte", UVM_DEBUG)
- end
+ `DV_CHECK_RANDOMIZE_WITH_FATAL(fmt_item,
+ fbyte == num_rd_bytes;
+ start == 1'b0;
+ read == 1'b1;
+ // for the last write byte of last tran., stop flag must be set to issue stop bit (stimulus end)
+ // otherwise, stop can be randomly set/unset to issue stop/rstart bit respectively
+ // rcont is derived from stop and read to issue chained/non-chained reads
+ stop == (last_tran) ? 1'b1 : stop;
+ )
+ `DV_CHECK_EQ(fmt_item.stop | fmt_item.rcont, 1)
+ `uvm_info(`gfn, $sformatf("\n read transaction length is %0d byte",
+ num_rd_bytes ? num_rd_bytes : 256), UVM_DEBUG)
- // accumulate number of read byte
- total_rd_bytes += (num_rd_bytes) ? num_rd_bytes : 256;
- // decrement total_rd_bytes since one data is must be dropped in fifo_overflow test
- if (cfg.seq_cfg.en_rx_overflow) total_rd_bytes--;
- `uvm_info(`gfn, $sformatf("\n program_control_read_to_target, read %0d byte",
- total_rd_bytes), UVM_DEBUG)
+ // accumulate number of read byte
+ total_rd_bytes += (num_rd_bytes) ? num_rd_bytes : 256;
+ // decrement total_rd_bytes since one data is must be dropped in fifo_overflow test
+ if (cfg.seq_cfg.en_rx_overflow) total_rd_bytes--;
+ `uvm_info(`gfn, $sformatf("\n program_control_read_to_target, read %0d byte",
+ total_rd_bytes), UVM_DEBUG)
- if (fmt_item.rcont) begin
- `uvm_info(`gfn, "\n transaction READ is chained with next READ transaction", UVM_DEBUG)
- end else begin
- `uvm_info(`gfn, $sformatf("\n transaction READ ended %0s", (fmt_item.stop) ?
- "with STOP, next transaction should begin with START" :
- "without STOP, next transaction should begin with RSTART"), UVM_DEBUG)
- end
- program_format_flag(fmt_item, " program number of bytes to read");
+ if (fmt_item.rcont) begin
+ `uvm_info(`gfn, "\n transaction READ is chained with next READ transaction", UVM_DEBUG)
+ end else begin
+ `uvm_info(`gfn, $sformatf("\n transaction READ ended %0s", (fmt_item.stop) ?
+ "with STOP, next transaction should begin with START" :
+ "without STOP, next transaction should begin with RSTART"), UVM_DEBUG)
end
+ program_format_flag(fmt_item, " program number of bytes to read");
endtask : program_control_read_to_target
virtual task read_data_from_target();
@@ -216,34 +212,4 @@
end
endtask : program_write_data_to_target
- // read interrupts and randomly clear interrupts if set
- virtual task process_interrupts();
- bit [TL_DW-1:0] intr_state, intr_clear;
-
- // read interrupt
- csr_rd(.ptr(ral.intr_state), .value(intr_state));
- // clear interrupt if it is set
- `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(intr_clear,
- foreach (intr_clear[i]) {
- intr_state[i] -> intr_clear[i] == 1;
- })
-
- if (bit'(get_field_val(ral.intr_state.fmt_watermark, intr_clear))) begin
- `uvm_info(`gfn, "\n clearing fmt_watermark", UVM_DEBUG)
- end
- if (bit'(get_field_val(ral.intr_state.rx_watermark, intr_clear))) begin
- `uvm_info(`gfn, "\n clearing rx_watermark", UVM_DEBUG)
- end
-
- `DV_CHECK_MEMBER_RANDOMIZE_FATAL(clear_intr_dly)
- cfg.clk_rst_vif.wait_clks(clear_intr_dly);
- csr_wr(.csr(ral.intr_state), .value(intr_clear));
- endtask : process_interrupts
-
- // TODO: This task could be extended along with V2 test development
- virtual task clear_interrupt(i2c_intr_e intr, bit verify_clear = 1'b1);
- csr_wr(.csr(ral.intr_state), .value(1 << intr));
- if (verify_clear) wait(!cfg.intr_vif.pins[intr]);
- endtask : clear_interrupt
-
endclass : i2c_rx_tx_vseq
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_stress_all_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_stress_all_vseq.sv
index b01931c..bd7ca30 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_stress_all_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_stress_all_vseq.sv
@@ -5,7 +5,7 @@
// combine all i2c seqs (except below vseqs) in one seq to run sequentially
// 1. override_vseq requires scb and monitor to be disabled
// 1. csr seq, which requires scb to be disabled
-class i2c_stress_all_vseq extends i2c_base_vseq;
+class i2c_stress_all_vseq extends i2c_rx_tx_vseq;
`uvm_object_utils(i2c_stress_all_vseq)
`uvm_object_new
@@ -19,15 +19,14 @@
"i2c_fifo_full_vseq",
"i2c_fifo_overflow_vseq",
"i2c_fifo_watermark_vseq",
- "i2c_fifo_full_vseq",
"i2c_stretch_timeout_vseq",
- "i2c_error_intr_vseq",
- "i2c_perf_vseq"
+ "i2c_perf_vseq",
+ "i2c_error_intr_vseq"
};
virtual task body();
- `uvm_info(`gfn, "\n=> start i2c_stress_all_vseq", UVM_LOW)
+ `uvm_info(`gfn, "\n=> start i2c_stress_all_vseq", UVM_DEBUG)
print_seq_names(seq_names);
for (int i = 1; i <= seq_names.size(); i++) begin
seq_run_hist[seq_names[i-1]] = 0;
@@ -40,16 +39,17 @@
seq_name = seq_names[seq_idx];
`uvm_info(`gfn, $sformatf("\n\n=> start stressing vseq %s (%0d/%0d)",
- seq_name, i, num_runs), UVM_LOW)
+ seq_name, i, num_runs), UVM_DEBUG)
seq = create_seq_by_name(seq_name);
`downcast(i2c_vseq, seq)
// if upper seq disables do_dut_init for this seq, then can't issue reset
// as upper seq may drive reset
+ `uvm_info(`gfn, $sformatf("\n *do_dut_init %0b", do_dut_init), UVM_DEBUG)
if (do_dut_init) begin
i2c_vseq.do_dut_init = $urandom_range(0, 1);
if (i2c_vseq.do_dut_init) begin
- `uvm_info(`gfn, "\n *reset is randomly issued with stress_test", UVM_LOW)
+ `uvm_info(`gfn, "\n *reset is randomly issued with stress_test", UVM_DEBUG)
end
end else begin
i2c_vseq.do_dut_init = 0;
@@ -75,10 +75,11 @@
// run vseq
i2c_vseq.start(p_sequencer);
seq_run_hist[seq_name]++;
- `uvm_info(`gfn, $sformatf("\n end stressing vseq %s", seq_name), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\n end stressing vseq %s", seq_name), UVM_DEBUG)
+ wait(cfg.m_i2c_agent_cfg.vif.rst_ni);
end
wait_host_for_idle();
- `uvm_info(`gfn, "\n=> end of i2c_stress_all_vseq", UVM_LOW)
+ `uvm_info(`gfn, "\n=> end of i2c_stress_all_vseq", UVM_DEBUG)
// get the histogram of vseq running
str = {str, "\n\n=> vseq run histogram:"};
@@ -86,17 +87,17 @@
seq_name = seq_names[i];
str = {str, $sformatf("\n %-25s %2d / %2d", seq_name, seq_run_hist[seq_name], num_runs)};
end
- `uvm_info(`gfn, $sformatf("%s\n", str), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("%s\n", str), UVM_DEBUG)
endtask : body
virtual function print_seq_names(string seq_names[]);
string str;
- `uvm_info(`gfn, $sformatf("\n list of %0d vseqs are stressed", seq_names.size()), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\n list of %0d vseqs are stressed", seq_names.size()), UVM_DEBUG)
for (int i = 1; i <= seq_names.size(); i++) begin
str = {str, $sformatf("\n %s", seq_names[i-1])};
end
- `uvm_info(`gfn, $sformatf("%s", str), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("%s", str), UVM_DEBUG)
endfunction : print_seq_names
endclass : i2c_stress_all_vseq
diff --git a/hw/ip/i2c/dv/env/seq_lib/i2c_stretch_timeout_vseq.sv b/hw/ip/i2c/dv/env/seq_lib/i2c_stretch_timeout_vseq.sv
index 2bf1adb..99d5632 100644
--- a/hw/ip/i2c/dv/env/seq_lib/i2c_stretch_timeout_vseq.sv
+++ b/hw/ip/i2c/dv/env/seq_lib/i2c_stretch_timeout_vseq.sv
@@ -20,7 +20,6 @@
local bit check_rd_stretch;
virtual task body();
-
`uvm_info(`gfn, "\n--> start of i2c_stretch_timeout_vseq", UVM_DEBUG)
initialization();
for (int i = 1; i <= num_trans; i++) begin
@@ -52,7 +51,8 @@
end
end
begin
- while (check_wr_stretch || check_rd_stretch) process_stretch_timeout_intr();
+ while (!cfg.under_reset &&
+ (check_wr_stretch || check_rd_stretch)) process_stretch_timeout_intr();
end
join
end
diff --git a/hw/ip/i2c/dv/i2c_sim_cfg.hjson b/hw/ip/i2c/dv/i2c_sim_cfg.hjson
index 392ee80..6ef838a 100644
--- a/hw/ip/i2c/dv/i2c_sim_cfg.hjson
+++ b/hw/ip/i2c/dv/i2c_sim_cfg.hjson
@@ -29,8 +29,7 @@
// Common CIP test lists
"{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson",
"{proj_root}/hw/dv/tools/dvsim/tests/intr_test.hjson",
- //TODO: enable later in V2
- //"{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson",
+ "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson",
"{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson"]
// Add additional tops for simulation.
@@ -85,15 +84,6 @@
name: i2c_error_intr
uvm_test_seq: i2c_error_intr_vseq
}
-
- {
- // TODO: remove later when i2c_stress_all_with_rand_reset is added
- // (then stress_tests.hjson would be included)
- name: i2c_stress_all
- uvm_test_seq: i2c_stress_all_vseq
- // 10ms
- run_opts: ["+test_timeout_ns=10000000000"]
- }
]
// List of regressions.