Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ Key paths:
- `atdf/` - source ATDF device descriptions
- `docs/` - supplemental JSON docs (`general.json` plus per-chip files)
- `Output/` - generated Swift output
- `Scripts/generate_avr_tools_device_file.swift` - ATDF model regeneration helper
Data flow: `atdf/*.atdf` -> `XMLDecoder` -> `AVRToolsDeviceFile` -> `GenerationPipeline` -> peripheral generators -> formatted Swift output in `Output/<ChipName>/...`

## Extra Rule Files
Expand Down Expand Up @@ -95,7 +94,6 @@ Add new tests under `SwiftAVRGeneratorTests/` unless the work is specifically UI
- Prefer changing generator code or documentation inputs over hand-editing generated files.
- Do not edit `Output/` unless the task is specifically about generated output inspection.
- When changing docs behavior, check both `docs/general.json` and `docs/<Chip>.json`.
- If you need to update the ATDF decode layer, inspect `Scripts/generate_avr_tools_device_file.swift` first.
- Keep changes scoped; generator logic is shared across many chips.
Comment thread
frisodebacker marked this conversation as resolved.
- Match local style in the file you touch; newer code uses `SwiftSyntaxBuilder`, older files sometimes build strings directly.

Expand Down
94 changes: 94 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Contributing to HALGEN

HALGEN generates Swift hardware abstraction layers for AVR microcontrollers. The generator reads bundled ATDF XML files, merges supplemental documentation from `docs/`, and writes formatted Swift source into `Output/`.

The primary development workflow is the command-line generator. The SwiftUI app target exists, but most contributor work should start with the CLI and focused tests.

## First Successful Run

Requirements:

- macOS with Xcode installed
- Xcode command line tools pointed at the full Xcode app

```bash
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
```

Generate the default representative chip:

```bash
./generate.sh
```

Generate into a temporary directory when you want to inspect output without touching `Output/`:

```bash
./generate.sh --output /tmp/halgen-test
```

Run the focused unit test target:

```bash
xcodebuild test \
-project SwiftAVRGenerator.xcodeproj \
-scheme SwiftAVRGenerator \
-destination "platform=macOS,arch=arm64" \
-only-testing:SwiftAVRGeneratorTests/SwiftAVRGeneratorTests
```

If local signing blocks test runs, retry with signing disabled:

```bash
xcodebuild test \
-project SwiftAVRGenerator.xcodeproj \
-scheme SwiftAVRGenerator \
-destination "platform=macOS,arch=arm64" \
-only-testing:SwiftAVRGeneratorTests/SwiftAVRGeneratorTests \
CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY="" DEVELOPMENT_TEAM=""
```

## Golden Rule

Change generator code or documentation inputs. Do not hand-edit files under `Output/` unless you are only inspecting generated output.

Generated files should improve because one of these changed:

- Swift generator logic under `SwiftAVRGenerator/`
- supplemental JSON or templates under `docs/`
- ATDF input data under `atdf/`

## Where To Change Things

| If you are changing... | Start here |
| --- | --- |
| CLI arguments or export behavior | `SwiftAVRGenerator/CLI/main.swift` and `SwiftAVRGenerator/Generators/GenerationApi.swift` |
| ATDF decoding models | `SwiftAVRGenerator/AVRToolsDeviceFile/` |
| supplemental JSON loading | `SwiftAVRGenerator/Documentation/` |
| register or bitfield code generation | `SwiftAVRGenerator/CodeGeneration/` |
| peripheral output | `SwiftAVRGenerator/Generators/Peripherals/` |
| generator registration | `SwiftAVRGenerator/Generators/GeneratorRegistry.swift` |
| generated formatting | `SwiftAVRGenerator/CodeGeneration/Linter/` |
| supplemental docs data | `docs/general.json`, `docs/<Chip>.json`, and `docs/SUPPLEMENTAL_DOCUMENTATION.md` |
| boilerplate module code | `docs/boilerplate/` |
| tests | `SwiftAVRGeneratorTests/` |

## Common Workflows

Read `DeveloperDocs/ARCHITECTURE.md` before making broad generator changes. It explains the data flow from ATDF input to generated Swift output.

Read `DeveloperDocs/DOCUMENTATION_SYSTEM.md` before editing `docs/general.json`, `docs/<Chip>.json`, or boilerplate templates. That guide explains how supplemental data is merged and why missing entries appear in `logs.json`.

Read `DeveloperDocs/ADDING_PERIPHERALS.md` before adding a new peripheral generator or changing an existing generator's structure.

Read `DeveloperDocs/TESTING_AND_GENERATION.md` when you need exact build, test, generation, and inspection commands.

## Review Checklist

Before opening a pull request or asking for review:

- Run focused tests for the area you changed.
- Run `./generate.sh --output /tmp/halgen-test` for generator or documentation changes.
- Inspect `logs.json` for unexpected missing supplemental data.
- Inspect `formatting-report.txt` for generated formatting diagnostics.
- Update contributor docs when behavior, commands, or documentation fields change.
158 changes: 158 additions & 0 deletions DeveloperDocs/ADDING_PERIPHERALS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Adding Or Changing Peripheral Generators

Peripheral generators turn decoded ATDF modules into Swift HAL files. Add a new generator when a peripheral family needs generated APIs that cannot be handled by an existing generator.

## Before You Start

Check whether the peripheral already has a generator under `SwiftAVRGenerator/Generators/Peripherals/`.

Existing generators include:

- `AnalogToDigitalConverter.swift`
- `GPIO.swift`
- `SerialPeripheralInterface.swift`
- `Timers.swift`
- `TwoWireInterface.swift`
- `UART.swift`

If the change is shared register or bitfield behavior, prefer `SwiftAVRGenerator/CodeGeneration/`. If the change is specific to one peripheral family, keep it in that peripheral generator.

## Generator Contract

New generators conform to `PeripheralGenerator`:

```swift
protocol PeripheralGenerator {
var name: String { get }
var logName: String { get }
var subdirectory: String { get }
func supports(device: AVRToolsDeviceFile) -> Bool
func generate(device: AVRToolsDeviceFile, documentation: ChipDocumentationLoader) -> [GeneratedCodeFile]
}
```

`logName` defaults to `name`. Override it when the generated Swift-facing name differs from the ATDF or log grouping name. `TwoWireInterfaceGenerator` does this by using `name = "TwoWireInterface"` and `logName = "TWI"`.

## Minimal Generator Shape

Use this shape as a starting point:

```swift
struct ExampleGenerator: PeripheralGenerator {
let name: String = "Example"
let subdirectory: String = "module/Example"

func supports(device: AVRToolsDeviceFile) -> Bool {
device.modules.module.contains { $0.name == "EXAMPLE" }
}

func generate(device: AVRToolsDeviceFile, documentation: ChipDocumentationLoader) -> [GeneratedCodeFile] {
guard let module = device.modules.module.first(where: { $0.name == "EXAMPLE" }) else {
return []
}

var files: [GeneratedCodeFile] = []

for registerGroup in module.registerGroup {
let structName = "Example\(peripheralInstanceIndex(for: registerGroup.name))"
var code = buildFileHeader(for: structName)

// Build declarations from registers and bitfields here.

files.append(
GeneratedCodeFile(
fileName: "\(structName).swift",
content: code,
subdirectory: subdirectory
)
)
}

return files
}
}
```

Keep `supports(device:)` conservative. Return `true` only when the required ATDF module or register shape exists. If only some chips have the classic register layout your generator supports, check for that exact shape instead of only checking the module name.

## Documentation Context And Logs

`GenerationPipeline` wraps every registered generator with:

```swift
documentation.withPeripheralContext(named: generator.logName) {
generator.generate(device: device, documentation: documentation)
}
```

This means missing supplemental documentation discovered during `generate(device:documentation:)` is grouped under that generator's log name in `logs.json`.

Set `name` and `logName` deliberately. Only call `withPeripheralContext(named:)` inside a generator if the generator intentionally needs multiple log groups.

## Registering The Generator

Add the generator to `SwiftAVRGenerator/Generators/GeneratorRegistry.swift`:

```swift
struct GeneratorRegistry {
static let allGenerators: [PeripheralGenerator] = [
UARTGenerator(),
SPIGenerator(),
TwoWireInterfaceGenerator(),
TimerGenerator(),
ADCGenerator(),
GPIOGenerator(),
ExampleGenerator()
]
}
```

Keep ordering intentional. If output order matters for generated package layout or review readability, place the new generator where it makes sense with the existing families.

## Boilerplate Templates

If the peripheral needs hand-maintained Swift protocols, convenience APIs, or setup helpers, add a template under `docs/boilerplate/` and load it with `BoilerplateTemplate.load` or `BoilerplateTemplate.render`.

Use templates for stable API surfaces. Use Swift generator code for declarations that are derived from ATDF registers or bitfields.

## Tests And Verification

Add focused unit tests under `SwiftAVRGeneratorTests/` for the behavior you changed. Good tests assert generated content for a representative chip or a small constructed model.

Run focused tests first:

```bash
xcodebuild test \
-project SwiftAVRGenerator.xcodeproj \
-scheme SwiftAVRGenerator \
-destination "platform=macOS,arch=arm64" \
-only-testing:SwiftAVRGeneratorTests/SwiftAVRGeneratorTests
```

Then generate a representative chip into a temporary directory:

```bash
./generate.sh --output /tmp/halgen-test
```

Inspect:

- `/tmp/halgen-test/logs.json`
- `/tmp/halgen-test/formatting-report.txt`
- the generated peripheral files under `/tmp/halgen-test/<Chip>/`

For broad generator changes, run all bundled chips:

```bash
./generate.sh --all --output /tmp/halgen-test
```

## Contributor Checklist

- The generator supports only chips with the expected ATDF shape.
- New generated files use the existing `GeneratedCodeFile` export path pattern.
- Register accessors use shared helpers where possible.
- Bitfield accessors use shared helpers where possible.
- Missing supplemental docs appear under a useful peripheral name in `logs.json`.
- Focused tests cover the new behavior.
- Generated output formats cleanly.
82 changes: 82 additions & 0 deletions DeveloperDocs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# HALGEN Architecture

HALGEN is a source generator. It reads Microchip ATDF device descriptions, combines them with supplemental documentation maintained in this repository, and emits Swift HAL source files.

## Data Flow

```text
atdf/*.atdf
-> XMLDecoder
-> AVRToolsDeviceFile
-> ChipDocumentationLoader
-> GenerationPipeline
-> PeripheralGenerator
-> CodeFormatter
-> Output/<Chip>/...
```

The ATDF file is the hardware source of truth. Supplemental JSON improves naming, access metadata, generated documentation, split bitfield handling, and board defaults. Peripheral generators transform the decoded device model plus supplemental data into Swift source files.

## Main Areas

| Area | Responsibility |
| --- | --- |
| `SwiftAVRGenerator/CLI/` | Command-line entry point and argument handling. |
| `SwiftAVRGenerator/App/` | SwiftUI macOS app target. The CLI is the primary contributor workflow. |
| `SwiftAVRGenerator/AVRToolsDeviceFile/` | Codable models for decoded ATDF XML. |
| `SwiftAVRGenerator/Documentation/` | Models and loader for `docs/general.json`, chip JSON files, board metadata, and missing-data logs. |
| `SwiftAVRGenerator/Generators/` | Generation pipeline, generator registry, peripheral generators, and CoreAVR package support. |
| `SwiftAVRGenerator/CodeGeneration/` | Register, bitfield, documentation-comment, formatting, and SwiftSyntax helpers. |
| `Scripts/` | Maintenance scripts for ATDF models and supplemental documentation audits. |
| `docs/` | Supplemental JSON data, boilerplate templates, CoreAVR package template files, and contributor docs. |
| `Output/` | Generated output. Treat this as an artifact, not as source input. |

## Generation Lifecycle

1. The CLI or app chooses one chip or all bundled ATDF files.
2. The selected ATDF XML is decoded into `AVRToolsDeviceFile`.
3. `GenerationPipeline.run(device:documentation:)` loads `docs/general.json` and `docs/<Chip>.json`.
4. `GeneratorRegistry.allGenerators` is scanned in order.
5. Each generator whose `supports(device:)` returns `true` emits one or more `GeneratedCodeFile` values.
6. Documentation lookups go through `ChipDocumentationLoader` while the pipeline sets the current peripheral log context.
7. Generated Swift is formatted before export.
8. Export writes generated files, `logs.json`, and `formatting-report.txt`.

## Core Concepts

### `AVRToolsDeviceFile`

`AVRToolsDeviceFile` is the decoded ATDF model. It should describe hardware structure, not HAL naming policy.

### `ChipDocumentationLoader`

`ChipDocumentationLoader` merges shared docs from `docs/general.json`, chip-specific docs from `docs/<Chip>.json`, and generated fallbacks from ATDF data. It also records missing supplemental entries so the export can write actionable `logs.json` output.

### `PeripheralGenerator`

Each peripheral generator owns one generated peripheral family. A generator decides whether it supports a chip, then emits files under its configured output subdirectory.

### `GeneratedCodeFile`

A generated file contains a file name, file content, and output subdirectory. Generators should return generated files instead of writing to disk directly.

### `CodeFormatter`

Generated Swift is normalized during export. Do not assume generated text is final before formatter diagnostics are written to `formatting-report.txt`.

## Generator Boundaries

Keep hardware discovery close to the relevant peripheral generator. Keep shared register and bitfield formatting in `SwiftAVRGenerator/CodeGeneration/`. Keep supplemental metadata behavior in `SwiftAVRGenerator/Documentation/`.

If a change affects multiple peripheral families, look for a shared helper in `CodeGeneration` before duplicating logic across generators. If a change only affects one peripheral family, keep it in that generator.

## Generated Output Policy

`Output/` is useful for inspection and regression review, but it should not be the place you fix problems. If generated output is wrong, fix the generator, ATDF input, supplemental JSON, or boilerplate template that produced it.

## Related Docs

- `CONTRIBUTING.md` for onboarding and common workflows.
- `DeveloperDocs/DOCUMENTATION_SYSTEM.md` for supplemental docs behavior.
- `DeveloperDocs/ADDING_PERIPHERALS.md` for peripheral generator changes.
- `DeveloperDocs/TESTING_AND_GENERATION.md` for verification commands.
Loading