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
    • Designing the Address Map
    • Implementing Address Decode
    • Decode Errors and Default Slaves
    • Register Maps and Banks
    • Security and Privilege Regions
    • The Software View and the Hardware-Software Contract
      • Generated Headers and the Map Document
      • Endianness, Access Width and Ordering
      • Errata and Software Workarounds
    • IP-XACT and Automated Assembly
    • Memory-Map Verification
  • Interconnect and Bus Fabrics26
  • 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

←The Software View and the Hardware-Software Contract
  1. Topics
  2. SoC Design
  3. Memory Maps and Address Decode
  4. The Software View and the Hardware-Software Contract
  5. Generated Headers and the Map Document
On this page

    Part 3 of 14, lesson 18 of 26Part 3 of 14/Memory Maps and Address Decode/Lesson 18 of 26All levels

    Generated Headers and the Map Document

    Headers, linker constants and the map document emitted from one table, with a checker that keeps them honest.

    Why it matters

    Every software bug that starts with a wrong address constant starts here: a header typed from a presentation, a base copied from last year's chip, a linker script nobody regenerated. The hardware team experiences these as mysterious silicon failures weeks later. The fix is boring and total: generate every software-facing artifact from the map table, stamp each with the map version, and check the agreement in the build. This lesson specifies those artifacts for NanoSoC.

    The core idea

    Three artifacts leave the integration team. The C header carries one base define per region and per slot, plus the register offsets for each block, so driver code names registers instead of numbering them. The linker constants carry the memory regions with their lengths and attributes, so the reset vector, the stack top at one past SRAM0 and the image base cannot drift from the map. The map document is the human version of the same table: regions with attributes, holes with their responders, aliases marked as aliases, and the access rules of the next lesson printed where a driver author will actually read them. All three are regenerated, never edited: the header below is illustrative generic format emitted from the NanoSoC table.

    Diagram
    # not-run: format fragment, not executable here
    /* nanosoc_map.h - generated from the NanoSoC map table, map version 1.2. Do not hand-edit. */
    #define BOOTROM_BASE   0x00000000u
    #define SRAM0_BASE     0x20000000u
    #define SRAM1_BASE     0x20010000u
    #define DMA_BASE       0x40000000u
    #define SBR_BASE       0x40001000u
    #define RSTPWR_BASE    0x40006000u
    #define SRAM0_STACK_TOP 0x20010000u  /* one past the end of SRAM0 */

    Generation alone is not the deliverable; the agreement check is. The script below is the smallest honest version: it holds the map table, renders the header text the way the generator would, and asserts every base in the header equals the table, catching the stale-header failure where one artifact was regenerated and the other was not. Run it in the build and a mismatched release cannot be produced, only a failed build.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    MAP = {"BOOTROM": 0x0000_0000, "SRAM0": 0x2000_0000, "SRAM1": 0x2001_0000,
           "DMA": 0x4000_0000, "SBR": 0x4000_1000, "RSTPWR": 0x4000_6000}
    
    def render_header(m):
        lines = ["/* generated; do not hand-edit */"]
        for name, base in m.items():
            lines.append(f"#define {name}_BASE 0x{base:08X}u")
        return chr(10).join(lines) + chr(10)
    
    hdr = render_header(MAP)
    for name, base in MAP.items():
        assert f"#define {name}_BASE 0x{base:08X}u" in hdr
    stale = render_header({**MAP, "SBR": 0x4000_2000})  # header from an old table
    mismatch = [n for n, b in MAP.items() if f"#define {n}_BASE 0x{b:08X}u" not in stale]
    assert mismatch == ["SBR"]
    print("PASS: header agrees with table; stale SBR base detected")

    Versioning the contract

    The map carries a version and every artifact prints it, as the growth lesson required. The compatibility rule is the one software feels: adding a region or filling a reserved slot is a minor change, because existing addresses keep their meanings; moving, resizing or re-purposing a region is major, breaks every binary built against it, and needs the same re-qualification as a new chip. The document states the rule on its first page, and the release process refuses to ship artifacts whose version stamps disagree with each other.

    What the review looks for

    • Header, linker constants and document all carry the same map version, quoted in the review record.

    • No hand-written address constants anywhere in the software tree; a search for hex bases outside generated files comes back empty.

    • The agreement check runs in the build and its failure blocks the release, not just warns.

    Verify and debug

    Change one base in the table and rebuild: both artifacts must change together and the check must pass. Then deliberately stale-date one artifact and confirm the build fails, because a check that cannot fail is decoration. On the bench, the first software act is a reset readback sweep against the header values; the verification topic formalises it as a gate.

    A header generated from an old specification while the RTL moved on: fields land at wrong offsets and the driver corrupts neighbouring registers. Generation from one table plus the agreement check removes the class; disciplined copying does not.

    If asked how software and hardware stay in sync, describe the pipeline: one table, generated header and document, version stamps everywhere, agreement asserted in the build. Then name the failure it replaced.

    Check yourself Why does the header carry a do-not-hand-edit banner rather than relying on process?

    Because the next engineer under time pressure will edit the file in front of them. The banner plus regeneration makes the wrong action visible; process alone makes it invisible until silicon.

    Related topics

    • Next: Endianness, Access Width and Ordering

    • RTL: Generated Register Workflow

    • Generating Decode from a Map Table

    Previous

    56 / 289

    Next: Endianness, Access Width and Ordering

    Up next

    Up nextEndianness, Access Width and Ordering

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Errata and Software Workarounds