Skip to content

AMBA CHI · Module 13 · CHI Data Transfers

Forwarded Data

CHI's key data-path optimization is direct cache-to-cache forwarding — a peer holding a line sends data straight to the requester, no home round-trip. Chapter 9.7 established that forwarding exists; this chapter studies the forwarded packet. For a peer to reach a requester it never spoke to, the home's snoop hands it the requester's node ID and transaction ID, which the peer echoes into the packet. The subtlety is correlation: the requester matches data by its own transaction ID, so the packet must carry the requester's, not the peer's. Tag it wrong and the data arrives but matches no outstanding entry — the requester drops it and the read hangs. Representative model, not the specification.

Intermediate16 min readAMBA CHIForwarded DataDirect Cache TransferFwdTxnIDCorrelation

Module 13 · Chapter 13.4 · CHI Data Transfers

Project thread — 13.3 sank data at the home. 13.4 forwards it peer-to-peer; 13.5 sources it from memory.

1. Learning Outcomes

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

  • Explain that a forwarded data packet goes peer-to-peer, bypassing the home.
  • State that it must carry the requester's node ID (to route) and transaction ID (to correlate).
  • Describe how the home passes the requester's FwdNID / FwdTxnID to the peer in the snoop.
  • Explain that the requester matches incoming data by its transaction ID.
  • Diagnose the hang from forwarded data tagged with the wrong correlation.
  • Implement a representative correlation matcher in SystemVerilog, Verilog-2001, and VHDL.

2. Why Should I Learn This?

Forwarding is where the data path gets fast — a peer's data reaches the requester in one hop instead of routing through the home and back (Chapter 9.7). But that speed depends entirely on the forwarded packet being correlatable at the requester. Data that arrives but cannot be matched to an outstanding transaction is worse than slow data: it is dropped, and the transaction that was waiting for it hangs.

The mechanism that makes a forward correlatable is small but exact: the packet must carry the requester's transaction ID, not the forwarding peer's. The requester has no idea who forwarded to it; it only knows the TxnID it issued and is waiting on. So the peer must echo that ID — which the home handed it in the snoop's FwdTxnID field. Get this one field wrong and a physically-delivered line is discarded as unexpected. This chapter is the packet-level detail that turns "a peer can forward" (Chapter 9.7) into "a forward actually completes."

3. Key Terms

4. Previous Chapter Connection

Chapter 9.7 established Direct Cache Transfer — a peer forwards data straight to the requester, cutting the home round-trip. This chapter opens the packet that carries it.

The correlation ideas are from Module 6: every data packet carries a TxnID that the receiver uses to match it to an outstanding transaction (Chapter 6.6). For a home-sourced completion that TxnID is naturally the requester's — the home is answering the requester directly. For a forwarded packet the twist is that the sender is a peer that was never talking to the requester, so the peer must be told the requester's identity — the FwdNID and FwdTxnID the home embeds in the forwarding snoop (Chapter 9.2). This chapter is how those fields make the forward correlatable.

5. Core Concept — a packet addressed and tagged for a stranger

A forwarded data packet is built by a peer for a requester it never spoke to, so it must carry the requester's identity and correlation — both handed to the peer by the home.

  • Peer-to-peer. The forwarded data goes from the holding peer directly to the requester, bypassing the home (Chapter 9.7).
  • Carry the requester's node ID. The packet targets the requester by FwdNID — the requester's node ID, which the home put in the snoop — so it routes to the requester, not back to the home.
  • Carry the requester's transaction ID. The packet is tagged with FwdTxnID — the requester's TxnID, also from the snoop — so the requester can match it to its outstanding read.
  • The requester matches by TxnID. The requester pairs incoming data to an outstanding transaction by its TxnID. A packet whose TxnID matches no outstanding entry is unexpected and dropped.

The synthesis:

A forwarded data packet is sent peer-to-peer by a holding cache to a requester it never addressed. The home hands the peer the requester's FwdNID (node ID, to route the data direct) and FwdTxnID (transaction ID, to tag it), which the peer echoes into the packet. The requester matches the data by TxnID. Tag it with the wrong ID and it is dropped as unexpected — the read hangs though the bytes arrived.

6. Engineering Mental Model — a relayed parcel with the right name on it

Think of a package you ordered, fulfilled by a third-party seller you never contacted.

  • You (the requester) placed an order and got an order number (your TxnID). You are waiting for a parcel with your order number on it.
  • The warehouse (the home) tells the seller (the peer): "ship directly to this customer, and write their order number on the box." That instruction is the FwdNID and FwdTxnID.
  • The seller ships to your address with your order number on the label. You receive it, match the order number to your open order, and accept it — even though you never spoke to the seller.
  • If the seller instead wrote their own internal reference on the box, the parcel would reach your door but you would not recognize the number — it matches no order you placed — so you refuse it as a misdelivery, and your order stays "waiting" forever.

The order number on the box must be yours, not the seller's. The forwarded data's TxnID must be the requester's, not the peer's — and the home is what tells the peer which number to write.

7. Engineering Diagram — a forward with the requester's tag

A direct cache-to-cache forward. The requester RN1 issues a read to the home node. The home snoops the owner RN0 with a forwarding snoop carrying RN1's node ID as FwdNID and transaction ID as FwdTxnID. RN0 sends the data directly to RN1, tagged with RN1's transaction ID so RN1 can correlate it. RN0 tells the home the snoop is complete. The data never passes through the home.RN1 (requester)Home NodeRN0 (owner)ReadShared (TxnID =T)SnpShared ·FwdNID=RN1,FwdTxnID=TCompData · TxnID = T(direct)SnpResp (complete)
Figure 1 — a direct cache-to-cache forward. The requester RN1 issues a read to the home; the home snoops the owner RN0 with a forwarding snoop that carries RN1's node ID (FwdNID) and transaction ID (FwdTxnID); RN0 sends the data directly to RN1, tagged with RN1's transaction ID so RN1 can correlate it; and RN0 tells the home the snoop is complete. The data never passes through the home.

RN1 waits on TxnID T. The home's snoop tells RN0 to forward to RN1 and tag with T. RN0's data reaches RN1 stamped T, so RN1 matches it to its outstanding read. RN0 separately tells the home the snoop is done. The bug is RN0 stamping something other than T.

8. The Forwarded Packet's Identity Fields

The fields that make a forward routable and correlatable.

FieldValuePurpose
TgtID / FwdNIDthe requester's node IDroute the data direct to the requester
TxnID / FwdTxnIDthe requester's transaction IDlet the requester correlate it
OpcodeCompData (forwarded)a read completion, sinks to the requester
Sourcethe forwarding peerprovenance (informational)

The rule to carry: the forwarded packet is addressed and tagged with the requester's identity, which the peer learns only from the home's snoop. The peer's own node ID and TxnID are irrelevant to the requester — the requester is waiting on its TxnID. So the two fields that matter, FwdNID and FwdTxnID, both come from the home, are both the requester's, and must both be echoed verbatim into the forwarded data.

9. How the Peer Learns the Requester's Identity

The peer cannot invent the requester's identity — it is told.

  • The home embeds it in the snoop. When the home issues a forwarding snoop (Chapter 9.2), it includes FwdNID (the requester's node ID) and FwdTxnID (the requester's TxnID).
  • The peer echoes it into the data. The forwarding peer copies FwdNID into the data's target and FwdTxnID into the data's TxnID — so the packet is addressed and tagged for the requester.
  • The requester recognizes its own tag. The requester sees data stamped with its TxnID and matches it to the outstanding transaction — even though it came from a peer, not the home.
  • The home is told separately. The peer sends a SnpResp to the home to complete the snoop (Chapter 9.3); the data went to the requester, the response to the home.

The point to carry:

Forwarding splits what a non-forwarded transaction keeps together: the data goes to the requester, the response goes to the home. That split is only safe because the home pre-computes the requester's identity and injects it into the snoop, so the peer can address the requester without ever having communicated with it. This is a general pattern for direct transfer in a hierarchical protocol — the coordinator (home) knows both parties, so it briefs the sender with the receiver's identity, and the sender relays it faithfully. The faithfulness is the crux: the peer must treat FwdNID/FwdTxnID as opaque values to echo, not as its own to reinterpret. The moment the peer substitutes its own TxnID, the requester loses the thread, because correlation is by the requester's tag and nothing else.

10. Forwarding a Read — the correlation that completes it

RN1 reads a line RN0 owns; the home forwards.

  1. RN1 issues ReadShared, TxnID T. RN1 records an outstanding entry keyed by T and waits.
  2. Home snoops RN0 with FwdNID=RN1, FwdTxnID=T. The home tells RN0 to forward to RN1 and tag with T.
  3. RN0 forwards CompData to RN1, stamped T. RN0 echoes FwdTxnID into the data's TxnID and FwdNID into its target.
  4. RN1 matches T. RN1 sees data tagged T, finds its outstanding entry, and installs the line — the read completes.
  5. RN0 tells the home the snoop is done. A SnpResp completes the coherence action at the home.

The read completed because the forwarded data carried T — the requester's tag. Had RN0 stamped its own TxnID, RN1 would have seen an unmatched tag and dropped the data — the DebugLab.

11. RTL / Hardware View — the requester's correlation matcher

At the requester, incoming data is matched to an outstanding transaction by TxnID; unmatched data is dropped. Representative.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative requester-side correlation matcher (educational).
// Incoming (forwarded or home) data matches an outstanding transaction IFF its TxnID
// equals a pending TxnID. Unmatched data is UNEXPECTED and dropped -- so a forwarded
// packet must carry the REQUESTER'S TxnID, not the forwarding peer's.
module chi_fwd_match #(parameter NOUT = 8, parameter TW = 4) (
  input  logic              clk, rst_n,
  input  logic              data_valid,      // a data packet arrives
  input  logic [TW-1:0]     data_txnid,      // its TxnID (should be the requester's)
  input  logic [NOUT-1:0]   outstanding,     // which entries are pending
  input  logic [TW-1:0]     out_txnid [NOUT], // each pending entry's TxnID
  output logic              matched,          // data paired to an outstanding entry
  output logic [NOUT-1:0]   match_oh,         // which entry
  output logic              unexpected        // no match -> dropped
);
  always_comb begin
    match_oh = '0;
    for (int i = 0; i < NOUT; i++)
      if (outstanding[i] && out_txnid[i] == data_txnid)
        match_oh[i] = 1'b1;
  end
  assign matched    = data_valid && (|match_oh);
  assign unexpected = data_valid && !(|match_oh);   // arrived but uncorrelatable
endmodule

The same behavior in Verilog-2001 (flattened TxnID array):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative requester-side correlation matcher (Verilog-2001).
module chi_fwd_match #(parameter NOUT = 8, parameter TW = 4) (
  input  wire               clk, rst_n, data_valid,
  input  wire [TW-1:0]      data_txnid,
  input  wire [NOUT-1:0]    outstanding,
  input  wire [NOUT*TW-1:0] out_txnid_flat,   // NOUT TxnIDs packed
  output wire               matched,
  output reg  [NOUT-1:0]    match_oh,
  output wire               unexpected
);
  integer i;
  always @* begin
    match_oh = {NOUT{1'b0}};
    for (i = 0; i < NOUT; i = i + 1)
      if (outstanding[i] && out_txnid_flat[i*TW +: TW] == data_txnid)
        match_oh[i] = 1'b1;
  end
  assign matched    = data_valid & (|match_oh);
  assign unexpected = data_valid & ~(|match_oh);
endmodule

And in VHDL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Representative requester-side correlation matcher (VHDL).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity chi_fwd_match is
  generic ( NOUT : integer := 8; TW : integer := 4 );
  port (
    clk, rst_n   : in  std_logic;
    data_valid   : in  std_logic;
    data_txnid   : in  std_logic_vector(TW-1 downto 0);
    outstanding  : in  std_logic_vector(NOUT-1 downto 0);
    out_txnid    : in  std_logic_vector(NOUT*TW-1 downto 0); -- NOUT TxnIDs packed
    matched      : out std_logic;
    match_oh     : out std_logic_vector(NOUT-1 downto 0);
    unexpected   : out std_logic
  );
end entity;
 
architecture rtl of chi_fwd_match is
begin
  process (data_valid, data_txnid, outstanding, out_txnid)
    variable m : std_logic_vector(NOUT-1 downto 0);
  begin
    m := (others => '0');
    for i in 0 to NOUT-1 loop
      if outstanding(i) = '1' and
         out_txnid((i+1)*TW-1 downto i*TW) = data_txnid then
        m(i) := '1';
      end if;
    end loop;
    match_oh   <= m;
    matched    <= data_valid and (or_reduce(m));
    unexpected <= data_valid and (not or_reduce(m));
  end process;
end architecture;

All three match incoming data by TxnID against the outstanding entries and flag unexpected when nothing matches. A forwarded packet is correlatable only if its TxnID is the requester's — the DebugLab is a peer that stamps the wrong one.

12. Verification View — a forward must be correlatable

The properties that keep forwarding sound: data matches iff its TxnID is outstanding, and mismatched data is flagged.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bind to chi_fwd_match.
// 1. A match implies a one-hot hit on an outstanding entry (never a phantom match).
property p_match_is_onehot;
  @(posedge clk) disable iff (!rst_n)
    matched |-> ($onehot(match_oh) && ((match_oh & outstanding) == match_oh));
endproperty
 
// 2. Data whose TxnID matches nothing outstanding is flagged unexpected (not silently used).
property p_unmatched_is_unexpected;
  @(posedge clk) disable iff (!rst_n)
    (data_valid && !(|match_oh)) |-> unexpected;
endproperty
 
// 3. A packet cannot be both matched and unexpected.
property p_mutually_exclusive;
  @(posedge clk) disable iff (!rst_n)
    !(matched && unexpected);
endproperty

The system point, beyond the checks:

The unexpected signal is the difference between a hang and a detectable error. Forwarded data with the wrong TxnID physically arrives, so a naive requester that only ever waits for its TxnID will simply keep waiting — the wrong-tagged data slides past unrecognized and the transaction stalls with no error anywhere. Exposing an unexpected flag turns that silent stall into an observable event: a data packet arrived that matched no outstanding transaction, which is exactly the fingerprint of a mis-tagged forward. So the matcher is doing two jobs at once — pairing good data to its transaction, and surfacing the bad forward that would otherwise present only as an unexplained timeout. In a real design that flag is what a debugger keys on to distinguish "data never sent" from "data sent with the wrong tag," two failures that look identical from the requester's stalled point of view.

  • What it proves: data matches only an outstanding same-TxnID entry; mismatches are flagged.
  • What it does not prove: the peer stamped the right TxnID — that is the sender's obligation (the DebugLab).
  • Bug signature: unexpected asserting during a forward — data arrived with a tag no transaction owns.

13. Testbench — a mis-tagged forward is unexpected

Presents correctly- and incorrectly-tagged forwarded data and checks correlation.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_chi_fwd_match;
  localparam NOUT = 4, TW = 4;
  logic clk = 0, rst_n = 1, data_valid;
  logic [TW-1:0] data_txnid;
  logic [NOUT-1:0] outstanding;
  logic [TW-1:0] out_txnid [NOUT];
  logic matched; logic [NOUT-1:0] match_oh; logic unexpected;
  int errors = 0;
 
  chi_fwd_match #(.NOUT(NOUT), .TW(TW)) dut (.*);
  always #5 clk = ~clk;
 
  initial begin
    // Requester has an outstanding read with TxnID = 5 in slot 2.
    outstanding = 4'b0100;
    out_txnid[0] = 4'd0; out_txnid[1] = 4'd0; out_txnid[2] = 4'd5; out_txnid[3] = 4'd0;
 
    // Correctly-tagged forward: TxnID = 5 -> matches slot 2.
    @(posedge clk) begin data_valid = 1; data_txnid = 4'd5; end
    #1;
    if (!matched || unexpected || match_oh !== 4'b0100) begin errors++; $display("FAIL good forward not matched"); end
    else $display("PASS good forward matched slot 2");
 
    // Mis-tagged forward: peer stamped its OWN TxnID = 9 -> matches nothing.
    @(posedge clk) begin data_valid = 1; data_txnid = 4'd9; end
    #1;
    if (matched || !unexpected) begin errors++; $display("FAIL mis-tagged forward not flagged"); end
    else $display("PASS mis-tagged forward flagged unexpected (would hang)");
 
    @(posedge clk) data_valid = 0;
    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 good forward matched slot 2
PASS mis-tagged forward flagged unexpected (would hang)
ALL TESTS PASSED

14. DebugLab — a forward tagged with the peer's own TxnID

1

A forward tagged with the peer's own TxnID

FORWARDED DATA TAGGED WITH THE PEER'S OWN TXNID -> REQUESTER CANNOT CORRELATE -> READ HANGS
Symptom

A read hangs — it never completes — yet a data packet was observed arriving at the requester at about the right time. The line is present on the wire but the transaction stays outstanding. It correlates with forwarded (cache-to-cache) transfers, not home-sourced completions.

Evidence

The forwarded data carried the wrong TxnID:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
RN1 issues ReadShared, TxnID = T (RN1's outstanding entry keyed by T)
home snoops RN0 with FwdNID = RN1, FwdTxnID = T
buggy RN0 builds CompData with TxnID = (RN0's own snoop TxnID) = S, not T
  -> data arrives at RN1 stamped S
  -> RN1 has no outstanding entry with TxnID S -> UNEXPECTED -> dropped
  -> RN1's entry T still waiting -> read hangs
correct: RN0 echoes FwdTxnID = T -> data stamped T -> matches -> completes

The bytes arrived; the tag did not match, so the requester threw them away.

First Divergence

RN0 populated the forwarded data's TxnID from its own snoop context (or the home's) instead of echoing the requester's FwdTxnID. From that point the packet was uncorrelatable at RN1.

Root Cause

Forwarded data must carry the requester's transaction ID (FwdTxnID), because the requester correlates data by its own TxnID and knows nothing of the forwarding peer. In a direct forward the sender is a peer the requester never addressed; the only tag the requester recognizes is the one it issued. The home supplies that tag as FwdTxnID in the snoop precisely so the peer can echo it. Substituting the peer's own TxnID makes the data arrive but not match — a hang, not a corruption, because the requester safely drops the unrecognized packet. This is the packet-level obligation behind Chapter 9.7's forwarding: the transfer only completes if the tag is the requester's.

Fix

Echo the requester's FwdNID and FwdTxnID verbatim into the forwarded data — FwdNID as the target, FwdTxnID as the TxnID — so the packet is addressed and tagged with the requester's identity and correlates on arrival, exactly as the matcher expects. The peer relays the home's values; it does not substitute its own.

15. Common Mistakes

  • Tagging with the peer's own TxnID. Assumption: the sender's ID is used. Bug: uncorrelatable data, a hang (the DebugLab). Prevention: echo FwdTxnID.
  • Using the home's TxnID. Assumption: the home is the sender. Bug: wrong tag. Prevention: the requester's FwdTxnID.
  • Targeting the home, not the requester. Assumption: data routes via home. Bug: no direct forward. Prevention: target FwdNID.
  • Silently dropping unmatched data. Assumption: mismatches cannot happen. Bug: undebuggable hang. Prevention: flag unexpected.
  • Forgetting the SnpResp to the home. Assumption: data completes everything. Bug: the home's snoop never closes. Prevention: send SnpResp separately.
  • Assuming forwarding needs no extra fields. Assumption: like a home completion. Bug: missing FwdNID/FwdTxnID. Prevention: carry both from the snoop.

16. Engineering Checklist

  • Send forwarded data peer-to-peer, bypassing the home.
  • Target the packet at the requester's FwdNID.
  • Tag the packet with the requester's FwdTxnID — echoed from the snoop.
  • At the requester, match incoming data by TxnID to an outstanding entry.
  • Flag data matching no outstanding entry as unexpected, not silently drop it.
  • Send the SnpResp to the home separately to close the snoop.

17. Key Takeaways

  • A forwarded data packet goes peer-to-peer, bypassing the home.
  • It must carry the requester's FwdNID (to route) and FwdTxnID (to correlate).
  • The home supplies both in the forwarding snoop; the peer echoes them.
  • The requester matches data by its own TxnID.
  • Data tagged with the wrong TxnID arrives but is dropped as unexpected — the read hangs.
  • Echo the requester's identity faithfully; the model here is representative.

18. Quick Revision

Forwarded data. A forwarded data packet (Direct Cache Transfer, Chapter 9.7) is sent peer-to-peer from a holding cache to the requester, bypassing the home. Because the peer never spoke to the requester, the packet must carry the requester's identity: FwdNID (the requester's node ID, so the data routes direct) and FwdTxnID (the requester's transaction ID, so the requester can correlate it). The home embeds both in the forwarding snoop, and the peer echoes them into the data. The requester matches incoming data to an outstanding transaction by TxnID; a packet whose TxnID matches nothing is unexpected and dropped. The failure to avoid: the peer tags the forwarded data with its own TxnID (or the home's) instead of FwdTxnID, so the data arrives but matches no outstanding entry — the requester discards it and the read hangs though the bytes were delivered. Echo the requester's FwdNID/FwdTxnID verbatim; correlation is by the requester's tag alone. Representative model; 13.5 covers memory-sourced data.

Coming Next

Chapter 13.5 — Memory Data. Forwarding covered cache-to-cache data; the other source is memory. Chapter 13.5 covers memory data — how data supplied by a Subordinate Node is tagged and correlated back through the home, why memory data is always clean (unlike cache data), and how the home matches a memory read's return to the request that issued it.