rtl: PCIeHostBridge v1 — TLP route decode + MSI-X doorbell + completion FIFO #128

Closed
opened 2026-06-18 04:32:14 -03:00 by navigator · 4 comments
Owner

Goal

Implement v1 behaviour of PCIeHostBridge per Draft SPEC at rtl/src/pop/specs/PCIeHostBridge.SPEC.md (#94). The skeleton (#65) lands four empty sub-bundles (pipe, hostTlp, fabric, msix); this issue lands the actual host-side TLP termination + MSI-X doorbell logic. Master-only per ADR-008.

Scope — strictly what the Draft SPEC pins

  • Constructor: class PCIeHostBridge(tlpHdrBits: Int = 96, dataBits: Int = 256, numMsiXVectors: Int = 32) — Gen4 x16 framing leaves the dataBits default at 256 (32 lanes × 8 bits per Gen4 PIPE), TLP header at 96 bits (3-DW format per PCIe 5.0 §2). All parameterised; the actual PHY-PCS framing decision lands when the vendor PHY ADR closes.
  • IO surface materialises (per SPEC §Interface bullets):
    • hostTlp: ingress Flipped(Decoupled(TlpRequest)) + egress Decoupled(TlpCompletion) with header = UInt(tlpHdrBits.W), data = UInt(dataBits.W), dataValid = Bool().
    • fabric: mirror of MultiGemminiCluster.io.mem (TBD width per §Interface). Use opaque UInt(64.W) placeholder addr/data, annotate as Open.
    • msix: numMsiXVectors-deep doorbell write port (Flipped(Decoupled(MsiXDoorbell)) with vector = UInt(log2Ceil(numMsiXVectors).W)).
    • pipe: empty (PHY attach not decided).
  • Behavior:
    • TLP route decode: extract request_type from header bits [31:24]. MemRd/MemWr forward to fabric egress. MSI-X doorbell write extracts vector and forwards to msix egress.
    • Per-TLP completion queue: pair each MemRd with a TlpCompletion, FIFO depth inflight = 16.
    • Back-pressure: hostTlp.ingress.ready falls when completion queue or fabric egress is full.

Open Questions — do NOT invent

  • PHY-PCS framing — Open (pipe stays empty).
  • Concrete TLP header field layout beyond request_type byte — Open. Don't invent the rest of the header; pass through opaque.
  • ATU programming + DMA descriptor processing — Open. Out of scope for v1.

Acceptance criteria

  • rtl/src/pop/PCIeHostBridge.scala body materialises route decoder + completion queue + MSI-X dispatch
  • rtl/tests/PCIeHostBridge/PCIeHostBridgeSpec.scala extended with three scenarios:
    • MemRd TLP routes to fabric and arrives back as hostTlp.egress completion within inflight + 2 cycles
    • MemWr TLP routes to fabric with no completion expected
    • MSI-X doorbell write extracts vector field and forwards to msix egress
  • sbt -no-colors test green
  • No fabricated TLP header semantics beyond request_type byte

Plan refs

PLAN.md §8.2; ADR-008 (designated master), ADR-009 (PopLink supersedes inter-chip PCIe).

## Goal Implement v1 behaviour of `PCIeHostBridge` per Draft SPEC at `rtl/src/pop/specs/PCIeHostBridge.SPEC.md` (#94). The skeleton (#65) lands four empty sub-bundles (`pipe`, `hostTlp`, `fabric`, `msix`); this issue lands the actual host-side TLP termination + MSI-X doorbell logic. Master-only per ADR-008. ## Scope — strictly what the Draft SPEC pins - Constructor: `class PCIeHostBridge(tlpHdrBits: Int = 96, dataBits: Int = 256, numMsiXVectors: Int = 32)` — Gen4 x16 framing leaves the dataBits default at 256 (32 lanes × 8 bits per Gen4 PIPE), TLP header at 96 bits (3-DW format per PCIe 5.0 §2). All parameterised; the actual PHY-PCS framing decision lands when the vendor PHY ADR closes. - IO surface materialises (per SPEC §Interface bullets): - `hostTlp`: ingress `Flipped(Decoupled(TlpRequest))` + egress `Decoupled(TlpCompletion)` with `header = UInt(tlpHdrBits.W)`, `data = UInt(dataBits.W)`, `dataValid = Bool()`. - `fabric`: mirror of `MultiGemminiCluster.io.mem` (TBD width per §Interface). Use opaque `UInt(64.W)` placeholder addr/data, annotate as Open. - `msix`: `numMsiXVectors`-deep doorbell write port (`Flipped(Decoupled(MsiXDoorbell))` with `vector = UInt(log2Ceil(numMsiXVectors).W)`). - `pipe`: empty (PHY attach not decided). - Behavior: - TLP route decode: extract `request_type` from header bits [31:24]. MemRd/MemWr forward to `fabric` egress. MSI-X doorbell write extracts vector and forwards to `msix` egress. - Per-TLP completion queue: pair each MemRd with a `TlpCompletion`, FIFO depth `inflight = 16`. - Back-pressure: `hostTlp.ingress.ready` falls when completion queue or `fabric` egress is full. ## Open Questions — do NOT invent - PHY-PCS framing — Open (`pipe` stays empty). - Concrete TLP header field layout beyond `request_type` byte — Open. Don't invent the rest of the header; pass through opaque. - ATU programming + DMA descriptor processing — Open. Out of scope for v1. ## Acceptance criteria - [ ] `rtl/src/pop/PCIeHostBridge.scala` body materialises route decoder + completion queue + MSI-X dispatch - [ ] `rtl/tests/PCIeHostBridge/PCIeHostBridgeSpec.scala` extended with three scenarios: - MemRd TLP routes to `fabric` and arrives back as `hostTlp.egress` completion within `inflight + 2` cycles - MemWr TLP routes to `fabric` with no completion expected - MSI-X doorbell write extracts vector field and forwards to `msix` egress - [ ] `sbt -no-colors test` green - [ ] No fabricated TLP header semantics beyond `request_type` byte ## Plan refs PLAN.md §8.2; ADR-008 (designated master), ADR-009 (PopLink supersedes inter-chip PCIe).
Author
Owner
No description provided.
<!-- agent:claim by=dispatcher run=20260618T073350Z_issue128 ts=1781768032 -->
Author
Owner
No description provided.
<!-- agent:heartbeat run=20260618T073350Z_issue128 ts=1781768332 -->
Author
Owner
No description provided.
<!-- agent:heartbeat run=20260618T073350Z_issue128 ts=1781768632 -->
Author
Owner
No description provided.
<!-- agent:pr pr=#129 branch=auto/issue-128-20260618T073350Z_issue128 -->
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Fluid/fluidpop-v1#128
No description provided.