Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • The NanoSoC Tour
  • Reading Path
  • SoC Glossary10
  • SoC Metrics Reference
  • SoC Cheatsheet
  • What SoC Integration Is12
  • Architecture and Budgets21
  • Memory Maps and Address Decode26
  • Interconnect and Bus Fabrics26
    • Topologies and Bridges
    • AXI Integration Details
    • Ordering and Deadlock at the Top
    • QoS and Arbitration
    • NoC Basics
    • Coherent Interconnect View
    • Firewalls and Protection
    • Bandwidth and Latency Verification
      • The Budget Table as Arithmetic
      • Checking Latency Link by Link
      • Performance Counters and What a Miss Looks Like
  • Clock and Reset Architecture24
  • Power Architecture21
  • Interrupts, DMA and Peripherals15
  • Memories, Boot and Security21
  • IP Integration and Handoff21
  • Top-Level Verification and Bring-up21
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Bandwidth and Latency Verification
  1. Topics
  2. SoC Design
  3. Interconnect and Bus Fabrics
  4. Bandwidth and Latency Verification
  5. Performance Counters and What a Miss Looks Like
On this page

    Part 4 of 14, lesson 26 of 26Part 4 of 14/Interconnect and Bus Fabrics/Lesson 26 of 26All levels

    Performance Counters and What a Miss Looks Like

    The chip-level method: traffic generators, counters per link, and reading a miss down to its link.

    Why it matters

    A method that proves the chip meets its bandwidth and latency budgets before tapeout needs traffic generators standing in for the missing neighbours and counters watching every link. Without it the table is a wish; with it a miss arrives with the link name attached. NanoSoC's block list has no performance monitors, so these are testbench monitors or monitors added for characterisation, and they are part of the verification plan, not of the chip.

    The core idea

    The method has four steps. First, model: the two scripts in this topic predict every number. Second, generate: traffic generators replay the worst-case mix, CPU line fills against full-duplex SBR streaming, with bursts constrained to legal lengths and page edges. Third, count: monitors in the fabric count beats, bubbles, outstanding transactions and wait cycles per link over a window. Fourth, compare: each counter is checked against its model row, and any miss is read down to its link. The width of a counter is a separate sizing question: it must hold the most increments a window can produce, bits at least log2 of window cycles times increments per cycle, so a million-cycle window at one beat per cycle needs 20 bits. The script below models a window of 340 cycles on the SBR copy, with and without the shared-bank trap, and classifies what the counters show.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    # NanoSoC teaching values: per-link beat counters over a 340-cycle window (20 bursts of 17 cycles).
    import math
    BURST = 16
    WINDOW = 340
    
    def run(shared_bank):
        # One SBR copy: a read stream and a write stream, each always asking for 16-beat bursts.
        # A bank port moves one beat per cycle and costs one bubble per burst.
        write_link = "sram0_write" if shared_bank else "sram1_write"
        counts = {"sram0_read": 0, write_link: 0}
        if shared_bank:
            t, turn = 0, 0
            while t + BURST + 1 <= WINDOW: # one port: the two bursts alternate
                counts["sram0_read" if turn == 0 else write_link] += BURST
                t += BURST + 1
                turn ^= 1
        else:
            for name in counts: # two ports: independent
                t = 0
                while t + BURST + 1 <= WINDOW:
                    counts[name] += BURST
                    t += BURST + 1
        return counts
    
    def classify(measured, model, errors=0):
        low = {k: v / model[k] for k, v in measured.items() if v < 0.9 * model[k]}
        if not low:
            return "ok"
        if errors and min(low.values()) == 0:
            return "refusal"
        if len(low) == len(measured) and all(abs(r - 0.5) < 0.05 for r in low.values()):
            return "shared bank"
        return "single link miss"
    
    model = {"sram0_read": 320, "sram1_write": 320} # 20 bursts x 16 beats on each of two ports
    model_shared = {"sram0_read": 320, "sram0_write": 320}
    split, shared = run(False), run(True)
    assert split == {"sram0_read": 320, "sram1_write": 320}
    assert shared == {"sram0_read": 160, "sram0_write": 160} # both directions halved: 180.7 each
    assert classify(split, model) == "ok"
    assert classify(shared, model_shared) == "shared bank"
    assert classify({"sram0_read": 320, "sram1_write": 150}, model) == "single link miss"
    assert classify({"sram0_read": 0, "sram1_write": 0}, model, errors=3) == "refusal"
    # counter width from the window, and a width that would overflow
    window, per_cycle = 1_000_000, 1
    bits = math.ceil(math.log2(window * per_cycle + 1))
    assert bits == 20 and window * per_cycle > 2**16 - 1
    print("PASS: split banks 320 + 320 beats, shared bank 160 + 160 classified as the shared-bank trap, 20-bit counters")

    What the review looks for

    • The performance plan lists every budgeted link with its generator, its counters, and its pass threshold.

    • Counter width is derived from the longest window and the peak increment rate, and overflow is proved impossible, not assumed away.

    • A miss has a named owner and a drill: walk from the lowest count to the shared resource above it.

    Verify and debug

    Run the worst-case mix with the counters free-running, then freeze and read: beats per link against the model rows, bubbles per burst against one, outstanding maxima against the tracking size. A link at partial beats with no error is contention; if both directions of one stream are halved together on one bank, it is the shared-bank trap at 180.7 per stream. A link at zero with errors is refusal, back at the firewall topic. A single link short while its partner is full is a different cause (a stall in that slave or path), so do not call it the shared-bank trap. The full flow this plugs into, with coverage and signoff, lives in the verification and bring-up section.

    Same-bank placement halving the stream: the SBR's source and destination are both in SRAM0, so its read and write streams share one single port and each direction sees 180.7 instead of 361.4 with no error anywhere. The counters show sram0_read and sram0_write both at half; the fix is placement, moving the destination to SRAM1, and the guard is a buffer-placement rule checked at allocation.

    If asked how to prove a bandwidth budget, give the four steps with one NanoSoC number each: model 361.4, generate fills plus duplex streams, count beats per link, compare and walk down from the lowest count. Then name the signature you most expect: both directions of one stream halved together means a shared bank, zero with errors means refusal.

    Check yourself Counters show sram0_read and sram0_write both at half of their model beats, with no errors. Diagnosis and fix?

    The SBR copy's two directions share bank 0, so each gets half the port, 180.7 MB/s: move the destination to SRAM1 and both recover. If only one link were short, the cause would lie in that link's own slave or path.

    Related topics

    • Checking Latency Link by Link

    • QoS in Practice on NanoSoC

    • Verification First Principles: Performance and Power Verification

    Previous

    96 / 289

    Next: Clock Gating Architecture

    Up next

    Up nextClock Gating Architecture

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • The Budget Table as Arithmetic