Skip to content

Commit

Permalink
[i2c] Changes to FIFO watermarks and interrupts
Browse files Browse the repository at this point in the history
Change FIFO level configuration to reflect the introduction of
thresholds for ACQ and TX FIFOs.
Separate FIFO level status into host- and target-side registers in
anticipation of deeper FIFOs.
Fmt/Tx overflow interrupts and testing no longer required.
Re-purpose fmt/tx_overflow interrupts as 'tx_threshold' and
'acq_threshold' interrupts for target mode.
Replace threshold encoding with a simple, more flexible entry count,
supporting FIFO depths of more than 32 bytes.
i2c_target_smoke_vseq anticipates FmtThreshold IRQ assertion
because that host-side FIFO is unused and remains empty.
Minimal changes to i2c_host_fifo_watermark_vseq to maintain operation.

Signed-off-by: Adrian Lees <[email protected]>
  • Loading branch information
alees24 committed Feb 27, 2024
1 parent a0c4975 commit 596ba7b
Show file tree
Hide file tree
Showing 24 changed files with 378 additions and 537 deletions.
143 changes: 77 additions & 66 deletions hw/ip/i2c/data/i2c.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@
desc: "host mode interrupt: raised if the RX FIFO is greater than the high threshold."
type: "status"
}
{ name: "fmt_overflow"
desc: "host mode interrupt: raised if the FMT FIFO has overflowed."
{ name: "acq_threshold"
desc: "host mode interrupt: raised if the ACQ FIFO level is at or above the high threshold."
type: "status"
}
{ name: "rx_overflow"
desc: "host mode interrupt: raised if the RX FIFO has overflowed."
Expand Down Expand Up @@ -79,8 +80,9 @@
desc: "target mode interrupt: raised if the target is stretching clocks for a read command. This is a level status interrupt."
type: "status"
}
{ name: "tx_overflow"
desc: "target mode interrupt: raised if TX FIFO has overflowed."
{ name: "tx_threshold"
desc: "target mode interrupt: raised when the TX FIFO depth is less than the low threshold."
type: "status"
}
{ name: "acq_full"
desc: "target mode interrupt: raised if ACQ FIFO becomes full. This is a level status interrupt."
Expand Down Expand Up @@ -262,6 +264,11 @@
desc: "Target mode receive FIFO is empty"
resval: "1"
}
{ bits: "30"
name: "ACQDEPTH"
desc: "Indicates if ACQ FIFO is deepened"
resval: "0"
}
]
tags: [// Updated by the hw. Exclude from write-checks.
"excl:CsrNonInitTests:CsrExclWriteCheck"]
Expand Down Expand Up @@ -326,58 +333,6 @@
name: "FMTRST"
desc: "FMT fifo reset. Write 1 to the register resets FMT_FIFO. Read returns 0"
}
{ bits: "4:2"
name: "RXILVL"
desc: '''Trigger level for RX interrupts. If the FIFO depth exceeds
this setting, it raises rx_threshold interrupt.
'''
enum: [
{ value: "0",
name: "rxlvl1",
desc: "1 character"
},
{ value: "1",
name: "rxlvl4",
desc: "4 characters"
},
{ value: "2",
name: "rxlvl8",
desc: "8 characters"
},
{ value: "3",
name: "rxlvl16",
desc: "16 characters"
},
{ value: "4",
name: "rxlvl30",
desc: "30 characters"
},
]
}
{ bits: "6:5"
name: "FMTILVL"
desc: '''Trigger level for FMT interrupts. If the FIFO depth falls below
this setting, it raises fmt_threshold interrupt.
'''
enum: [
{ value: "0",
name: "fmtlvl1"
desc: "1 character"
},
{ value: "1",
name: "fmtlvl4",
desc: "4 characters"
},
{ value: "2",
name: "fmtlvl8",
desc: "8 characters"
},
{ value: "3",
name: "fmtlvl16",
desc: "16 characters"
}
]
}
{ bits: "7"
swaccess: "wo"
name: "ACQRST"
Expand All @@ -390,27 +345,83 @@
}
]
}
{ name: "FIFO_STATUS"
desc: "I2C FIFO status register"
{
name: "HOST_FIFO_CONFIG"
desc: "Host mode FIFO configuration"
swaccess: "rw"
hwaccess: "hro"
hwqe: "true"
fields: [
{ bits: "11:0"
name: "RX_THRESH"
desc: '''Threshold level for RX interrupts. Whilst the level of data in the RX FIFO
is above this setting, the rx_threshold interrupt will be asserted.
'''
resval: "0"
}
{ bits: "27:16"
name: "FMT_THRESH"
desc: '''Threshold level for FMT interrupts. Whilst the number of used entries in the
FMT FIFO is below this setting, the fmt_threshold interrupt will be asserted.
'''
resval: "0"
}
]
}
{
name: "TARGET_FIFO_CONFIG"
desc: "Target mode FIFO configuration"
swaccess: "rw"
hwaccess: "hro"
hwqe: "true"
fields: [
{ bits: "11:0"
name: "TX_THRESH"
desc: '''Threshold level for TX interrupts. Whilst the number of used entries in the
TX FIFO is below this setting, the tx_threshold interrupt will be asserted.
'''
resval: "0"
}
{ bits: "27:16"
name: "ACQ_THRESH"
desc: '''Threshold level for ACQ interrupts. Whilst the level of data in the ACQ FIFO
is above this setting, the acq_threshold interrupt will be asserted.
'''
resval: "0"
}
]
}
{ name: "HOST_FIFO_STATUS"
desc: "Host mode FIFO status register"
swaccess: "ro"
hwaccess: "hwo"
hwext: "true"
fields: [
{ bits: "6:0"
{ bits: "11:0"
name: "FMTLVL"
desc: "Current fill level of FMT fifo (Host mode)"
desc: "Current fill level of FMT fifo"
}
{ bits: "22:16"
{ bits: "27:16"
name: "RXLVL"
desc: "Current fill level of RX fifo (Host mode)"
desc: "Current fill level of RX fifo"
}
{ bits: "14:8"
]
tags: [// Updated by the hw. Exclude from write-checks.
"excl:CsrNonInitTests:CsrExclWriteCheck"]
}
{ name: "TARGET_FIFO_STATUS"
desc: "Target mode FIFO status register"
swaccess: "ro"
hwaccess: "hwo"
hwext: "true"
fields: [
{ bits: "11:0"
name: "TXLVL"
desc: "Current fill level of TX fifo (Target mode)"
desc: "Current fill level of TX fifo"
}
{ bits: "30:24"
{ bits: "27:16"
name: "ACQLVL"
desc: "Current fill level of ACQ fifo (Target mode)"
desc: "Current fill level of ACQ fifo"
}
]
tags: [// Updated by the hw. Exclude from write-checks.
Expand Down
26 changes: 5 additions & 21 deletions hw/ip/i2c/data/i2c_testplan.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,15 @@
{
name: host_fifo_overflow
desc: '''
Test the overflow interrupt for fmt_fifo and rx_fifo.
Test the overflow interrupt for rx_fifo.

Stimulus:
- Configure DUT/Agent to Host/Target mode respectively
- DUT keeps sending a number of format byte higher than the size of fmt_fifo and
rx_fifo depth
- DUT keeps receiving a number of bytes higher than the depth of rx_fifo

Checking:
- Ensure excess format bytes are dropped
- Ensure fmt_overflow and rx_overflow interrupt are asserted
- Ensure rx_overflow interrupt are asserted
'''
stage: V2
tests: ["i2c_host_fifo_overflow"]
Expand Down Expand Up @@ -359,21 +358,6 @@
stage: V2
tests: ["i2c_target_perf"]
}
{
name: target_fifo_overflow
desc: '''
Test the overflow interrupt for tx_fifo overflow.

Stimulus:
- Configure DUT/Agent to Target/Host mode respectively
- Agent keeps sending a number of format byte higher than the size of tx_fifo
Checking:
- Ensure excess format bytes are dropped
- Ensure tx_overflow interrupt are asserted
'''
stage: V2
tests: ["i2c_target_tx_ovf"]
}
{
name: target_fifo_empty
desc: '''
Expand Down Expand Up @@ -509,10 +493,10 @@
Cover the FIFO reset bits in FIFO_CTL register
Cross fmt_threshold with FMTRST
Cross rx_threshold with RXRST
Cross fmt_overflow with FMTRST
Cross acq_threshold with FMTRST
Cross rx_overflow with RXRST
Cross acq_overflow with ACQRST
Cross tx_overflow with TXRST
Cross tx_treshold with TXRST
'''
}
{
Expand Down
17 changes: 11 additions & 6 deletions hw/ip/i2c/doc/theory_of_operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,13 @@ In the first two scenarios, it is after the ACK bit sent by the target, in the l
The I2C module has a few interrupts including general data flow interrupts and unexpected event interrupts.

#### Host Mode
If the RX FIFO exceeds the designated depth of entries, the interrupt `rx_threshold` is raised to inform firmware.
Firmware can configure the threshold value via the register [`FIFO_CTRL.RXILVL`](registers.md#fifo_ctrl).
Whenever the RX FIFO exceeds the designated number of entries, the interrupt `rx_threshold` is asserted to inform firmware.
Firmware can configure the threshold value via the register [`HOST_FIFO_CONFIG.RX_THRESH`](registers.md#host_fifo_config).

Meanwhile it the FMT FIFO level falls below a designated depth of entries the `fmt_threshold` interrupt is raised.
(Note that this behavior differs from similar interrupts in other modules, such as the UART IP module.)
Firmware can configure the threshold value via the register [`FIFO_CTRL.FMTILVL`](registers.md#fifo_ctrl).
Whilst the FMT FIFO level lies below a designated number of entries, the `fmt_threshold` interrupt is asserted.
Firmware can configure the threshold value via the register [`HOST_FIFO_CONFIG.FMT_THRESH`](registers.md#host_fifo_config).

If either FIFO receives an additional write request when its FIFO is full, the interrupt `fmt_overflow` or `rx_overflow` is asserted and the format indicator or character is dropped.
If the RX FIFO receives an additional write request when its FIFO is full, the interrupt `rx_overflow` is asserted and the character is dropped.

If the module transmits a byte, but receives no ACK signal, the `nak` interrupt is usually asserted.
In cases where a byte is transmitted and no ACK is expected or required, that byte should be submitted with NAKOK flag also asserted.
Expand Down Expand Up @@ -276,6 +275,12 @@ In a case when a target receives a STOP without the prerequisite NACK, the inter
This interrupt just means that a STOP was unexpectedly observed during a host read.
It is not necessarily harmful, but software can be made aware just in case.

If the ACQ FIFO exceeds the designated number of entries, the interrupt `acq_threshold` is raised to inform firmware.
Firmware can configure the threshold value via the register [`TARGET_FIFO_CONFIG.ACQ_THRESH`](registers.md#target_fifo_config).

Whilst the TX FIFO level is below a designated number of entries the `tx_threshold` interrupt is asserted.
Firmware can configure the threshold value via the register [`TARGET_FIFO_CONFIG.TX_THRESH`](registers.md#target_fifo_config).

If ACQ FIFO becomes full, the interrupt `acq_full` is asserted.

If a host ceases to send SCL pulses at any point during an ongoing transaction, the target waits for a specified time period and then asserts the interrupt `host_timeout`.
Expand Down
1 change: 0 additions & 1 deletion hw/ip/i2c/dv/env/i2c_env.core
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ filesets:
- seq_lib/i2c_target_stress_wr_vseq.sv: {is_include_file: true}
- seq_lib/i2c_target_stress_rd_vseq.sv: {is_include_file: true}
- seq_lib/i2c_target_stretch_vseq.sv: {is_include_file: true}
- seq_lib/i2c_target_tx_ovf_vseq.sv: {is_include_file: true}
- seq_lib/i2c_target_timeout_vseq.sv: {is_include_file: true}
- seq_lib/i2c_target_ack_stop_vseq.sv: {is_include_file: true}
- seq_lib/i2c_target_fifo_reset_acq_vseq.sv: {is_include_file: true}
Expand Down
6 changes: 0 additions & 6 deletions hw/ip/i2c/dv/env/i2c_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ class i2c_env_cfg extends cip_base_env_cfg #(.RAL_T(i2c_reg_block));
// Slow tx process
bit slow_txq = 1'b0;

// For tx fifio overflow test.
// If this bit is set, tx fifo is fed by 'drooling_write_tx_fifo()' in i2c_base_vseq.sv
bit use_drooling_tx = 1'b0;

// ack stop test
int sent_ack_stop = 0;
int rcvd_ack_stop = 0;
Expand Down Expand Up @@ -91,7 +87,6 @@ class i2c_env_cfg extends cip_base_env_cfg #(.RAL_T(i2c_reg_block));

// this function is called after reset or end of vseq run
virtual function void reset_seq_cfg();
seq_cfg.en_fmt_overflow = 1'b0;
seq_cfg.en_rx_overflow = 1'b0;
seq_cfg.en_rx_threshold = 1'b0;
seq_cfg.en_sda_unstable = 1'b0;
Expand All @@ -100,7 +95,6 @@ class i2c_env_cfg extends cip_base_env_cfg #(.RAL_T(i2c_reg_block));

// target mode cfg params.
slow_acq = 0;
use_drooling_tx = 0;
wr_pct = 1;
rd_pct = 1;
min_data = 1;
Expand Down
24 changes: 12 additions & 12 deletions hw/ip/i2c/dv/env/i2c_env_cov.sv
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ covergroup i2c_interrupts_cg with function sample(
cp_fmt_threshold : coverpoint intr_state[ 0] iff (intr_enable[ 0]);
// host mode interrupt: raised if the RX FIFO is greater than the high threshold.
cp_rx_threshold : coverpoint intr_state[ 1] iff (intr_enable[ 1]);
// host mode interrupt: raised if the FMT FIFO has overflowed.
cp_fmt_overflow : coverpoint intr_state[ 2] iff (intr_enable[ 2]);
// target mode interrupt: raised if the ACQ FIFO depth is greater than the high threshold.
cp_acq_threshold : coverpoint intr_state[ 2] iff (intr_enable[ 2]);
// host mode interrupt: raised if the RX FIFO has overflowed.
cp_rx_overflow : coverpoint intr_state[ 3] iff (intr_enable[ 3]);
// host mode interrupt: raised if there is no ACK in response to an address or data
Expand All @@ -39,8 +39,8 @@ covergroup i2c_interrupts_cg with function sample(
// target mode interrupt: raised if the target is stretching clocks for a read command.
// This is a level status interrupt.
cp_tx_stretch : coverpoint intr_state[10] iff (intr_enable[10]);
// target mode interrupt: raised if TX FIFO has overflowed.
cp_tx_overflow : coverpoint intr_state[11] iff (intr_enable[11]);
// target mode interrupt: raised if TX FIFO depth is less than the low threshold.
cp_tx_threshold : coverpoint intr_state[11] iff (intr_enable[11]);
// target mode interrupt: raised if ACQ FIFO becomes full. This is a level status
// interrupt.
cp_acq_full : coverpoint intr_state[12] iff (intr_enable[12]);
Expand All @@ -53,7 +53,7 @@ covergroup i2c_interrupts_cg with function sample(

cp_fmt_threshold_test : coverpoint intr_state[ 0] iff (intr_test[ 0]){ ignore_bins dis = {0}; }
cp_rx_threshold_test : coverpoint intr_state[ 1] iff (intr_test[ 1]){ ignore_bins dis = {0}; }
cp_fmt_overflow_test : coverpoint intr_state[ 2] iff (intr_test[ 2]){ ignore_bins dis = {0}; }
cp_acq_threshold_test : coverpoint intr_state[ 2] iff (intr_test[ 2]){ ignore_bins dis = {0}; }
cp_rx_overflow_test : coverpoint intr_state[ 3] iff (intr_test[ 3]){ ignore_bins dis = {0}; }
cp_nak_test : coverpoint intr_state[ 4] iff (intr_test[ 4]){ ignore_bins dis = {0}; }
cp_scl_interference_test : coverpoint intr_state[ 5] iff (intr_test[ 5]){ ignore_bins dis = {0}; }
Expand All @@ -62,7 +62,7 @@ covergroup i2c_interrupts_cg with function sample(
cp_sda_unstable_test : coverpoint intr_state[ 8] iff (intr_test[ 8]){ ignore_bins dis = {0}; }
cp_cmd_complete_test : coverpoint intr_state[ 9] iff (intr_test[ 9]){ ignore_bins dis = {0}; }
cp_tx_stretch_test : coverpoint intr_state[10] iff (intr_test[10]){ ignore_bins dis = {0}; }
cp_tx_overflow_test : coverpoint intr_state[11] iff (intr_test[11]){ ignore_bins dis = {0}; }
cp_tx_threshold_test : coverpoint intr_state[11] iff (intr_test[11]){ ignore_bins dis = {0}; }
cp_acq_full_test : coverpoint intr_state[12] iff (intr_test[12]){ ignore_bins dis = {0}; }
cp_unexp_stop_test : coverpoint intr_state[13] iff (intr_test[13]){ ignore_bins dis = {0}; }
cp_host_timeout_test : coverpoint intr_state[14] iff (intr_test[14]){ ignore_bins dis = {0}; }
Expand All @@ -75,27 +75,27 @@ covergroup i2c_fifo_reset_cg with function sample(
bit txrst,
bit fmt_threshold,
bit rx_threshold,
bit fmt_overflow,
bit acq_threshold,
bit rx_overflow,
bit acq_overflow,
bit tx_overflow
bit tx_threshold
);
cp_fmtrst : coverpoint fmtrst;
cp_rxrst : coverpoint rxrst;
cp_acqrst : coverpoint acqrst;
cp_txrst : coverpoint txrst;
cp_fmt_threshold : coverpoint fmt_threshold;
cp_rx_threshold : coverpoint rx_threshold;
cp_fmt_overflow : coverpoint fmt_overflow;
cp_acq_threshold : coverpoint acq_threshold;
cp_rx_overflow : coverpoint rx_overflow;
cp_acq_overflow : coverpoint acq_overflow;
cp_tx_overflow : coverpoint tx_overflow;
cp_tx_threshold : coverpoint tx_threshold;
cp_fmt_threshold_cross : cross cp_fmt_threshold, cp_fmtrst;
cp_rx_threshold_cross : cross cp_rx_threshold, cp_rxrst;
cp_fmt_overflow_cross : cross cp_fmt_overflow, cp_fmtrst;
cp_acq_threshold_cross : cross cp_acq_threshold, cp_fmtrst;
cp_rx_overflow_cross : cross cp_rx_overflow, cp_rxrst;
cp_acq_overflow_cross : cross cp_acq_overflow, cp_acqrst;
cp_tx_overflow_cross : cross cp_tx_overflow, cp_txrst;
cp_tx_threshold_cross : cross cp_tx_threshold, cp_txrst;
endgroup

covergroup i2c_fifo_level_cg (uint fifo_depth)
Expand Down
Loading

0 comments on commit 596ba7b

Please sign in to comment.