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
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:
| Aspect | SN-F | SN-I |
|---|---|---|
| Region | coherent memory | I/O / peripheral |
| Backs | DRAM (idempotent) | device registers (side effects) |
| Behind | HN-F | HN-I |
| Coherency | none | none |
| Accesses | idempotent reads/writes | exactly-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, snooped | RN-D — cacheless, not snooped |
| Home (HN) | HN-F — directory, snoops | HN-I — no directory, no snoops |
| Subordinate (SN) | SN-F — coherent memory | SN-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.
- Event. The device sets bit 2 of its status register (a transfer completed). The bit stays set until read.
- Handler reads. Software issues a ReadNoSnp of the status register; HN-I orders it and forwards it to SN-I.
- 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.
- 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.
- 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.
// 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
endmoduleThe same behavior in Verilog-2001:
// 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;
endmoduleAnd in VHDL:
-- 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.
// 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 assertsrd_accessand 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.
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
endmoduleExpected output:
PASS event bit 2 set, rdata=00000004
PASS event cleared after read, rdata=0000000014. DebugLab — a speculative read clears an event no one saw
A speculative read clears an event no one saw
SPECULATIVE READ OF READ-TO-CLEAR -> LOST EVENT / MISSED INTERRUPTA 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.
A read of the status register with no corresponding software read:
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 -> lostAt cycle 40 a speculative read cleared bit 2; its data was thrown away. At cycle 55 the real read sees 0.
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.
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.
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.