Skip to content

hw: Add priority-aware WRRA - #364

Draft
gbellocchi wants to merge 29 commits into
pulp-platform:masterfrom
gbellocchi:gb/qos-wrr
Draft

gbellocchi wants to merge 29 commits into
pulp-platform:masterfrom
gbellocchi:gb/qos-wrr

Conversation

@gbellocchi

@gbellocchi gbellocchi commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR introduces two new common_cells IPs implementing Weighted Round-Robin Arbitration (WRRA) tailored for real-time, mixed-criticality platforms. These modules can be readily used into best-effort interconnects, such as FlooNoC and the AXI4 crossbar.

Features

  • WRRA: Each traffic stream is allocated a configurable credit (weight). Traffic initiators provide the weight value dynamically at injection-time, allowing bandwidth tuning and fairness control across competing traffic initiators.
  • Priority-aware arbitration: Traffic is tagged with a QoS priority field (parameterizable width, defaulting to 4-bit for AXI4 compliance), enabling prioritization of high-priority traffic.
  • Aging: Starvation prevention based on an aging mechanism, which promotes traffic from lower-priority to higher-priority levels after a configurable wait interval (AgingInterval).

Tasks

  • Clean repository components (RTL, sim, docs, etc.).
  • Provide simulation and test components to evaluate and verify the new components.
  • Fix linting errors.

gbellocchi and others added 26 commits June 9, 2026 09:07
Add a generic N-input weighted round-robin arbiter that distributes output
bandwidth proportionally to a per-input weight (w_i / sum_j w_j) by granting
each winner a quantum of up to w_i consecutive beats before the round-robin
pointer advances. Built on cc_rr_arb_tree (FairArb + LockIn) for winner
selection, with a contender snapshot and a quantum counter on top.

Testbenches:
- cc_wrr_arbiter_tb: flat N-input throughput check vs the w_i/sum(w_j) ideal.
- cc_wrr_arbiter_cascade_tb: mixed-radix cascade reproducing and curing NoC
  topological unfairness (Dally & Towles) - unit weights give the unfair
  1/12, 1/4, 1/2 split; source-count weights restore 1/5 fairness.

Add test/simulate-wrra.sh and wire the new files into Bender.yml.
- doc/cc_wrr_arbiter.md: design write-up covering the topological-unfairness
  motivation, the burst weighted-round-robin mechanism, design decisions and
  trade-offs, and the evaluation results (flat throughput + before/after cascade).
- test/waves/cc_wrr_arbiter_tb.wave.do and cc_wrr_arbiter_cascade_tb.wave.do:
  QuestaSim wave setups exposing the TB signals and the quantum-counter internals.
- src/cc_qos_wrr_arbiter.sv: QoS-priority + aging + weighted round-robin. QoS
  selects the served tier (with per-grant aging to prevent starvation); within
  the tier, bandwidth is split by weight via cc_wrr_arbiter.
- test/cc_qos_wrr_arbiter_tb.sv: checks QoS priority, in-tier weighted split, and
  anti-starvation.
- test/cc_arbiter_compare_tb.sv: head-to-head RRA vs WRRA vs QoS+WRRA on identical
  traffic, reporting throughput share and urgent-flow request->grant latency;
  swept over the number of competing flows in simulate-wrra.sh.
- cc_wrr_arbiter: a weight of 0 now excludes an input from arbitration entirely
  (never granted) instead of being clamped to 1; renamed the accepted-transfer
  signal to flit_transfered. Added a weight-0 case to cc_wrr_arbiter_tb.
cc_wrr_arbiter: abandon the current burst if the locked winner stops requesting
(winner_gone) instead of stalling on it forever. When wrapped by a dynamic
eligibility mask (cc_qos_wrr_arbiter), a higher-QoS arrival demotes the current
winner out of the eligible set mid-burst; previously the inner arbiter stayed
locked on that now-ineligible winner and deadlocked, starving the high-QoS flow.
A plain downstream stall (winner still requesting) still only pauses, so under
saturated traffic winner_gone never fires and behaviour is unchanged.

Also add test/cc_qos_wrr_cascade_tb.sv: a 3-hop cascade with per-flit QoS that
measures the farthest flow's end-to-end latency with vs without priority, and
guard the comparison TB's latency print against divide-by-zero.
Assert gnt_o[winner] only when req_o is high (the winning flit actually leaves),
not merely on gnt_i. When an upstream mask (cc_qos_wrr_arbiter) demotes the winner
mid-burst, req_o drops; without this gate the winner got a spurious grant for a
flit that never left - dropping data and skewing throughput accounting. Under
saturated traffic req_o is always high, so behaviour is unchanged.

Also comment out the already-verified baseline WRRA runs in simulate-wrra.sh to
keep the QoS evaluation log short.
- doc/cc_wrr_arbiter.md: add the QoS+WRR arbiter design, the full evaluation
  (two-tier weighting, RRA/WRRA/QoS+WRRA latency sweep, cascade end-to-end
  latency), the intra-tier-fairness-under-periodic-preemption limitation, and an
  engineering-issues-found-and-fixed section.
- test/waves/cc_arbiter_compare_tb.wave.do: GUI wave setup to inspect the QoS
  arbiter internals (served index, ages, eligible set, preemptions).
Testbenches now emit machine-readable "CSV,..." lines and gained sweep knobs:
- cc_wrr_arbiter_tb: WeightMode (weight-pattern select) for the proportionality cloud.
- cc_arbiter_compare_tb: CSV summary; finer NumInp sweep in simulate-wrra.sh.
- cc_qos_wrr_arbiter_tb: SweepMode (relax fixed asserts) + CSV for the aging curve.
simulate-wrra.sh runs the three sweeps and accumulates results.csv.

doc/plots/plot_arbiters.py (matplotlib) turns results.csv + embedded single-config
numbers into the report figures: latency-vs-congestion, topological before/after,
weight proportionality (bars + swept cloud), QoS two-tier shares, aging-tuning curve.
Core PNGs (fig1-4) committed; fig5/fig6 generated once results.csv is produced.
- cc_wrr_arbiter_tb weight sweep overflowed WtWidth (weight i+1 > 15 at NumInp=16
  wrapped to 0); the failing assert aborted the whole sweep. Run that sweep with
  WtWidth=8 so weights fit.
- simulate-wrra.sh: a non-zero-errors run now warns instead of aborting (set -e +
  grep), so one bad config no longer drops the rest of the sweep.
- cc_arbiter_compare_tb: add GapJitter knob (randomize the urgent think-time). It
  breaks the periodic-stimulus resonance -> smooth latency-vs-congestion curves AND
  even bulk-throughput shares (the strobe artifact). The compare sweep enables it.
Regenerate all six figures from the full sweep results:
- fig1: latency vs congestion (jittered -> smooth RRA/WRRA curves, QoS flat)
- fig5: weight-proportionality cloud (3 patterns x 3 input counts, all on y=x)
- fig6: aging-tuning curve (low-tier share down / max-wait up vs AgingInterval)
Plot script dedups repeated AgingInterval points.
Add a weight-config box to the topological figure showing that fairness comes from
the through-port weights (A1=3, A2=4 = #sources aggregated), not per-source weights
(every source injects with local weight 1).
cc_qos_wrr_3tier_tb: 4 inputs at QoS 4/2/2/0, weights 1/3/1/1 (mid tier split 3:1),
emits "CSV,qos3,..." per input. Wired into Bender + simulate-wrra.sh. plot_arbiters.py
gains fig7 (three-tier shares), generated once the qos3 CSV rows are produced.
Real 3-tier run (QoS 4/2/2/0, weights 1/3/1/1): bandwidth is ordered by QoS tier,
but in1(w3) == in2(w1) - the within-tier weights are NOT applied, because an input
promoted into a higher tier by aging is served ~1 flit then demoted (its grant resets
its age), cutting the weighted burst to one. Weights only apply in an input's native
top tier. Figure annotated with this finding.
cc_qos_wrr_3tier_tb gains a Scenario param:
  0 (default): QoS {4,2,2,0} w {1,3,1,1} - weighted pair in mid tier (weights nullified).
  1:           QoS {4,4,2,0} w {3,1,1,1} - weighted pair is native top tier (3:1 applies).
CSV lines tagged with scen=; simulate-wrra.sh runs both; plot_arbiters.py emits fig7
(scenario 0) and fig7b (scenario 1, weighted top tier).
Scenario-1 run (QoS 4/4/2/0, weights 3/1/1/1): the QoS4 pair in0(w3)/in1(w1) is the
native top tier and splits 3:1 (0.680 / 0.227), with in2/in3 aging-rescued below.
Pairs with fig7 (weighted pair in mid tier -> weights nullified by aging) to pin down
exactly when within-tier weighting holds: native top tier yes, aged-up no.
- Inline all eight figures (fig1-7b) in their matching evaluation sections.
- §6.2: reconcile the latency table with the jittered swept figure.
- §6.4: note the GapJitter knob fixes both the jagged curves and the bulk strobe.
- §6.5 (new): aging-knob tradeoff curve (fig6) with the halve/double rule.
- §6.6 (new): three-QoS-tier finding - within-tier weights apply only in an input's
  native top tier, not when aged up (fig7 vs fig7b).
- §8: list the new TBs, the plot script, and the figures.
Add cc_qos_wrr_cascade_share_tb: drives all 5 cascade sources saturated with a
3-high/2-low QoS layout (weighted pair r0:r1=3:1) and measures each source's
end-to-end bandwidth share at the destination, so the QoS evaluation runs on the
same 5-source structure as the topological-fairness study (fig2) and is directly
comparable. Shows QoS priority surviving all 3 hops, the weighted split at the A0
merge, and aging keeping the low tier alive (fig8).

Also anchor the N-sweeps at N=5 (same source count as the cascade): compare and
wrrprop sweeps start at 5, fig1 marks N=5, and the fig1 animation uses N=5.
fig8: high tier r0-r2 = 93% of destination bandwidth despite being farthest;
within-tier r0:r1:r2 = 3:1:1 (weight applied at the A0 merge); low tier r3,r4
kept alive by aging (~3-4%). §6.3.1 updated with the measured shares.

Also refresh fig1/fig5/fig6 from the new sweep (compare and wrrprop anchored at
N=5), and fix a warmup artifact in cc_qos_wrr_cascade_share_tb's maxwait (skip
the first per-source grant gap; shares were always correct).
QoS-aware WRRA for fair service in NoC
@gbellocchi
gbellocchi marked this pull request as draft September 30, 2026 08:15
This was originally included to support the student during his initial familiarization with the round-robin arbiter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants