Skip to content

AMBA CHI · Module 5 · CHI System Components

SN-I (IO Slave Node)

SN-I is the last node in the taxonomy: the subordinate for I/O and peripheral space, behind an HN-I. Like SN-F it is a coherency-agnostic completer, but it backs something fundamentally different from memory — devices. Device registers are not idempotent storage: reading a status register may clear it, writing a control register may trigger an action, a FIFO read pops a word. Each access has a side effect, so SN-I accesses must be exactly-once, in order, and never speculated or coalesced — one access, one device operation. This chapter details that side-effecting nature, contrasts SN-I with SN-F, and closes the six-node taxonomy that Module 5 set out to build. The model here is representative, not the specification.

Intermediate13 min readAMBA CHISN-IIOSide EffectsPeripheral

Module 5 · Chapter 5.6 · CHI System Components

Project thread — 5.5 detailed the coherent-memory subordinate. This chapter takes the I/O subordinate and closes the six-node taxonomy. 5.7 goes inside the RN-F cache agent.

1. Learning Outcomes

By the end of this chapter you should be able to:

  • Define SN-I as the subordinate for non-coherent I/O / peripheral space, behind an HN-I.
  • Contrast SN-I with SN-F: both coherency-agnostic completers, but SN-I backs devices, not memory.
  • Explain why device registers have side effects and are not idempotent storage.
  • State the rule that follows: SN-I accesses are exactly-once, in order, never speculated or coalesced.
  • Place all six node kinds in the completed RN / HN / SN by coherent / I/O matrix.
  • Implement a representative read-to-clear device register in SystemVerilog, Verilog-2001, and VHDL.

2. Why Should I Learn This?

SN-I is where CHI meets real devices — UARTs, timers, interrupt controllers, DMA engines' register files. Getting it right is the difference between a driver that works and one that loses interrupts or double-triggers hardware. The lesson that device registers are not memory — that a read can have a side effect — is one of the most consequential in the whole taxonomy for anyone who touches drivers or SoC integration.

It also completes Module 5. With SN-I, every cell of the RN / HN / SN by coherent / I/O matrix is filled, and you can place any CHI node precisely. This chapter is both a node and a capstone.

3. Key Terms

4. Previous Chapter Connection

Chapter 5.5 gave SN-F its depth: the coherent-region memory controller that completes reads, writebacks, and writes for DRAM. It is a subordinate that backs memory — idempotent, side-effect-free storage.

SN-I is the same kind of node — a coherency-agnostic completer that answers the Home Node (Chapter 4.4) — backing a fundamentally different thing: devices. That single change, from memory to device registers, brings side effects, and side effects bring a new rule that memory never needed: each access must happen exactly once, in order, with no speculation. This chapter is SN-F's I/O counterpart, and the final node.

5. Core Concept — a device endpoint, not memory

SN-I is a completer for device space, and devices behave unlike memory.

  • It backs I/O / peripheral space. SN-I is the endpoint for non-coherent device memory and registers — behind an HN-I. It completes the ReadNoSnp / WriteNoSnp accesses the HN-I forwards, to the actual peripheral.
  • It does no coherency. Like every subordinate (Chapter 4.4), SN-I holds no directory and issues no snoops. It answers only the Home Node, never a requester.
  • Its targets have side effects. A device register is not idempotent storage. Reading a status register may clear it; writing a control register may trigger an action; reading a FIFO pops a word. The act of accessing changes device state.
  • So accesses are exactly-once and ordered. Because each access has a side effect, SN-I must perform exactly one device operation per access — never speculate a read, never coalesce two writes, never reorder relative to the ordering HN-I established. One access, one device operation.

The synthesis:

SN-I is a coherency-agnostic completer like SN-F, but it backs devices, and device registers have side effects — a read can clear, a write can trigger. So the rule memory never needed becomes essential: exactly-once, in order, no speculation, no coalescing. Treating a device register like memory — reading it speculatively, merging accesses — corrupts device state. SN-I's job is to turn each access into precisely one intended device operation.

6. Engineering Mental Model — a vending machine, not a bookshelf

SN-F was a vault (memory): put a book on a shelf, take it off, read it as many times as you like — nothing changes.

SN-I is a vending machine (a device):

  • Pressing a button (a read) dispenses an item and decrements the stock — the act of "reading" changes the machine's state (read-to-clear, FIFO pop).
  • Inserting a coin (a write) commits to a purchase — you cannot un-write it, and doing it twice buys two items (no coalescing).
  • You must press each button exactly once and in the order intended. "Speculatively" pressing a button to see what might come out dispenses a real item you did not want (speculation has a real side effect).

You browse a bookshelf freely; you operate a vending machine deliberately. SN-I endpoints are vending machines.

7. Engineering Diagram — SN-I fronting a device

SN-I in the I/O path. An I/O Home Node HN-I forwards an ordered non-coherent access to an SN-I completer, which performs exactly one device operation per access with no coherency, no speculation, and no coalescing. SN-I drives a peripheral or MMIO device with registers, a FIFO, and side effects, and returns a completion to HN-I.HN-Iforwards ordered IO accessSN-I completerno coherency · exactly-once· no coalescingPeripheral / MMIOregisters · FIFO · sideeffects12
Figure 1 — SN-I in the I/O path. The I/O Home Node HN-I forwards an ordered non-coherent access to SN-I, which completes it against the peripheral — a register file, FIFO, or MMIO device with side effects. SN-I performs exactly one device operation per access, holds no coherency state, and answers only the Home Node.

The peripheral on the right is the difference from SN-F: not DRAM, but a device whose registers act when touched. SN-I's whole discipline follows from that.

8. SN-F vs SN-I — and the complete taxonomy

The two subordinates differ only by the region and the endpoint's nature:

AspectSN-FSN-I
Regioncoherent memoryI/O / peripheral
BacksDRAM (idempotent)device registers (side effects)
BehindHN-FHN-I
Coherencynonenone
Accessesidempotent reads/writesexactly-once, no speculation

With SN-I, the taxonomy Module 5 built is complete — six node kinds along two axes, role (Request / Home / Subordinate) and domain (Coherent / I/O):

Coherent (F)I/O (I)
Request (RN)RN-F — cached, snoopedRN-D — cacheless, not snooped
Home (HN)HN-F — directory, snoopsHN-I — no directory, no snoops
Subordinate (SN)SN-F — coherent memorySN-I — I/O device

Two facts to carry: the F/I split is the same idea at every role — F participates in coherency (or backs coherent space), I does not — and the subordinates never do coherency either way; for them F versus I is purely which endpoint they front (memory vs device).

9. Why Device Registers Aren't Memory

The heart of SN-I is one distinction: memory is idempotent; devices are not.

  • Memory is idempotent. Reading a memory word returns its value and changes nothing; you may read it once, twice, or speculatively — the result is identical. Writes are plain stores. This is why memory tolerates prefetch, speculation, and caching.
  • Device registers have side effects. A read of a read-to-clear status register clears it. A write to a control register launches a transfer. A read of a FIFO removes a word. The access itself is the operation.
  • Therefore: no speculation, no coalescing, no reordering. A speculative read would clear a status the software never saw; two coalesced writes would trigger one action instead of two; a reorder would apply settings out of sequence. Each SN-I access must be exactly the one operation the software intended.

The point to carry:

Device registers are operations, not storage. SN-I must treat every access as a distinct, intended device operation — exactly once, in order, never speculated or merged. The moment a device register is treated like memory (read ahead, coalesce, cache), device state is corrupted and events are lost. This is the reason non-coherent I/O space is marked device / non-cacheable end to end.

10. Transaction Walkthrough — reading a read-to-clear status register

An interrupt handler reads a device's status register to learn and acknowledge pending events.

  1. Event. The device sets bit 2 of its status register (a transfer completed). The bit stays set until read.
  2. Handler reads. Software issues a ReadNoSnp of the status register; HN-I orders it and forwards it to SN-I.
  3. SN-I performs the read once. SN-I strobes the device read exactly once. The device returns the status (bit 2 set) and clears it — read-to-clear.
  4. Handler acts. Software sees bit 2, services the completion, and the status is now clear — the event is acknowledged by the very act of reading.
  5. No repeat. SN-I did not read the register speculatively or twice; if it had, the clear would have consumed the event before software saw it.

The read both observed and acknowledged the event — a side effect. Only exactly-once, non-speculative access makes that correct, which the DebugLab confirms by breaking it.

11. RTL / Hardware View — a read-to-clear device register

To make the side effect concrete, here is a read-to-clear status register — the kind of endpoint SN-I fronts. Representative and simplified.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative read-to-clear device status register (educational).
// Device events SET status bits; a read RETURNS the current value and CLEARS it
// (read-to-clear) — a side effect. SN-I must issue exactly one read per access,
// never speculatively, or events are cleared before software sees them.
module sni_rdclr_reg (
  input  logic        clk,
  input  logic        rst_n,
  input  logic [31:0] event_set,     // device events set status bits this cycle
  input  logic        rd_access,      // a ReadNoSnp reached this register
  output logic [31:0] rdata           // value returned to the read (pre-clear)
);
  logic [31:0] status;
  // What the read observes: accumulated status plus any events this cycle.
  assign rdata = status | event_set;
 
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n)          status <= 32'd0;
    else if (rd_access)  status <= 32'd0;                  // read clears (side effect)
    else                 status <= status | event_set;     // otherwise accumulate events
  end
endmodule

The same behavior in Verilog-2001:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative read-to-clear device status register (Verilog-2001).
module sni_rdclr_reg (
  input         clk, rst_n,
  input  [31:0] event_set,
  input         rd_access,
  output [31:0] rdata
);
  reg [31:0] status;
  assign rdata = status | event_set;
  always @(posedge clk or negedge rst_n)
    if (!rst_n)         status <= 32'd0;
    else if (rd_access) status <= 32'd0;
    else                status <= status | event_set;
endmodule

And in VHDL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Representative read-to-clear device status register (VHDL).
library ieee;
use ieee.std_logic_1164.all;
 
entity sni_rdclr_reg is
  port (
    clk, rst_n : in  std_logic;
    event_set  : in  std_logic_vector(31 downto 0);
    rd_access  : in  std_logic;
    rdata      : out std_logic_vector(31 downto 0)
  );
end entity;
 
architecture rtl of sni_rdclr_reg is
  signal status : std_logic_vector(31 downto 0) := (others => '0');
begin
  rdata <= status or event_set;
  process(clk, rst_n)
  begin
    if rst_n = '0' then
      status <= (others => '0');
    elsif rising_edge(clk) then
      if rd_access = '1' then status <= (others => '0');       -- read clears
      else                    status <= status or event_set;   -- accumulate
      end if;
    end if;
  end process;
end architecture;

All three make the read a side effect: rd_access clears the status. A single, intended read observes and acknowledges the events; a spurious or speculative read clears events no one saw — the DebugLab.

12. Verification View — a read clears exactly once

Two properties: a read clears the status, and without a read the status accumulates events.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bind to sni_rdclr_reg.
// 1. A read clears the status (its side effect) — next cycle status is 0
//    (barring same-cycle events, modelled cleared here for simplicity).
property p_read_clears;
  @(posedge clk) disable iff (!rst_n) rd_access |=> (status == 32'd0);
endproperty
assert property (p_read_clears);
 
// 2. Without a read, a set event persists (it is not lost until read).
property p_event_persists;
  @(posedge clk) disable iff (!rst_n)
    (!rd_access && (event_set != 0)) |=> ((status & $past(event_set)) != 0);
endproperty
assert property (p_event_persists);

The system point, beyond the two checks:

The read-to-clear register is correct only if it is read exactly when software intends — once per real read. The hardware faithfully clears on rd_access; the danger is entirely in who asserts rd_access and how often. A prefetch, a speculative access, or a coalesced double-read all assert it at the wrong time and consume events invisibly. That is why device space must be non-speculative and non-cacheable end to end — the register's correctness depends on the access pattern, not just the register logic. SN-I's discipline (exactly-once, no speculation) is what protects it.

  • What it proves: a read clears; an unread event persists.
  • What it does not prove: that upstream logic never issues a spurious read — that is the access-discipline property (the DebugLab).
  • Bug signature: an event cleared with no corresponding software read — a lost interrupt.

13. Testbench — set an event, read it, confirm the clear

Sets a status bit, reads it (observing then clearing), and confirms it is gone.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_sni_rdclr_reg;
  logic clk = 0, rst_n;
  logic [31:0] event_set, rdata;
  logic rd_access;
  int errors = 0;
 
  sni_rdclr_reg dut (.*);
  always #5 clk = ~clk;
 
  initial begin
    rst_n = 0; event_set = 0; rd_access = 0; @(posedge clk); rst_n = 1;
 
    // Device sets bit 2.
    event_set = 32'h4; @(posedge clk); #1; event_set = 32'h0;
    if ((rdata & 32'h4) == 0) begin errors++; $display("FAIL event not set"); end
    else $display("PASS event bit 2 set, rdata=%h", rdata);
 
    // Software reads -> observes bit 2 and clears it.
    rd_access = 1; @(posedge clk); #1; rd_access = 0;
 
    // Next cycle status is clear (event acknowledged by the read).
    @(posedge clk); #1;
    if ((rdata & 32'h4) != 0) begin errors++; $display("FAIL event not cleared after read"); end
    else $display("PASS event cleared after read, rdata=%h", rdata);
 
    if (errors == 0) $display("ALL TESTS PASSED");
    else             $display("%0d FAILURE(S)", errors);
    $finish;
  end
endmodule

Expected output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
PASS event bit 2 set, rdata=00000004
PASS event cleared after read, rdata=00000000

14. DebugLab — a speculative read clears an event no one saw

1

A speculative read clears an event no one saw

SPECULATIVE READ OF READ-TO-CLEAR -> LOST EVENT / MISSED INTERRUPT
Symptom

A device occasionally misses an interrupt: a transfer completes, but the handler never runs, or runs and finds nothing to do. It is timing-dependent and rare, and appears only with certain prefetch or speculation settings enabled.

Evidence

A read of the status register with no corresponding software read:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
cyc  rd_access  source          status before  status after  note
 40      1       speculative       0x4            0x0          event cleared...
 ..                                                            ...data discarded (squashed)
 55      1       software read     0x0            0x0          handler sees nothing -> lost

At cycle 40 a speculative read cleared bit 2; its data was thrown away. At cycle 55 the real read sees 0.

First Divergence

Cycle 40: a speculative (or prefetched) read reached the read-to-clear register. The read had a side effect — it cleared the status — even though its data was never used. From that access, the event is gone.

Root Cause

The device register was treated like memory — safe to read speculatively. But a read-to-clear register is an operation: reading it consumes the event. A speculative read consumes an event no software observed, and a squashed result cannot un-clear it. Idempotency was assumed where there is none.

Fix

Mark device space non-cacheable and non-speculative end to end, and have SN-I (and the path to it) perform exactly one device operation per intended access — never speculate, prefetch, or coalesce. Then a read-to-clear register is read only when software means to, and events are never silently consumed. The rule is the SN-I discipline: for a side-effecting endpoint, every access must be exactly the operation intended, once.

15. Common Mistakes

  • Treating device registers as memory. Assumption: reads are side-effect-free. Bug: speculative reads clear events (the DebugLab). Prevention: device registers are operations; mark them non-cacheable / non-speculative.
  • Coalescing device writes. Assumption: two writes to one register merge harmlessly. Bug: one trigger instead of two. Prevention: each write is a distinct operation.
  • Reordering device accesses. Assumption: order does not matter. Bug: settings applied out of sequence. Prevention: honor the ordering HN-I established.
  • Expecting SN-I to do coherency. Assumption: it snoops. Bug: looking for a directory. Prevention: no subordinate does coherency.
  • Confusing SN-I with SN-F. Assumption: they behave the same. Bug: idempotent assumptions on a device. Prevention: SN-F backs memory; SN-I backs side-effecting devices.
  • Letting SN-I answer requesters. Assumption: the device replies to the RN. Bug: bypassing the home. Prevention: SN-I answers only the Home Node.

16. Engineering Checklist

  • Use SN-I for non-coherent I/O / peripheral space, behind an HN-I.
  • Treat device registers as side-effecting operations, not idempotent storage.
  • Perform exactly one device operation per access — no speculation, no coalescing.
  • Honor the ordering HN-I established for device accesses.
  • Mark device space non-cacheable / non-speculative end to end.
  • Answer only the Home Node; complete every access.

17. Key Takeaways

  • SN-I is the subordinate for non-coherent I/O / peripheral space, behind an HN-I — a coherency-agnostic completer like SN-F.
  • It backs devices, not memory: device registers have side effects (read-to-clear, write-trigger, FIFO pop) and are not idempotent.
  • Therefore SN-I accesses are exactly-once, in order, never speculated or coalesced — one access, one device operation.
  • Treating a device register like memory (speculating, coalescing) corrupts device state and loses events.
  • SN-I completes the six-node taxonomy: RN / HN / SN, each split coherent (F) / I/O (I).
  • It answers only the Home Node; the model here is representative.

18. Quick Revision

SN-I (I/O slave node). The subordinate for non-coherent I/O / peripheral space, behind an HN-I — a coherency-agnostic completer like SN-F (no directory, no snoops; answers only the Home Node). The difference: it backs devices, not memory. Device registers have side effects — read-to-clear, write-triggers, FIFO pop — and are not idempotent. So SN-I accesses must be exactly-once, in order, never speculated or coalesced: one access, one device operation. Treating a register like memory (speculative read, coalesced writes) corrupts device state and loses events, which is why device space is non-cacheable / non-speculative end to end. With SN-I the taxonomy is complete: RN / HN / SN, each coherent (F) or I/O (I) — six node kinds. Representative model; 5.7 goes inside the RN-F cache agent.

Coming Next

Chapter 5.7 — Cache Agents. The nodes are all in hand; now the taxonomy turns inward. Chapter 5.7 opens up the cache agent — the coherency engine inside an RN-F: the block that holds the cache-line states, decides which coherent request to issue, and runs the snoop-response machine. Where Chapter 5.1 described RN-F's behavior from the outside, 5.7 details the agent that implements it — the state machine and structures that make a Request Node fully coherent.