Architecture Overview
SHDL uses a multi-stage compilation pipeline that transforms high-level hardware descriptions into highly optimized, executable simulations.
The Big Picture
┌─────────────────────────────────────────────────────────────────┐
│ EXPANDED SHDL │
│ (Your source code: hierarchy, generators, constants) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────┐
│ FLATTENER │
│ (5 phases) │
└─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BASE SHDL │
│ (Flat, explicit: only primitive gates) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────┐
│ COMPILER │
└─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ C SOURCE CODE │
│ (Bit-packed SIMD-style simulation) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────┐
│ C COMPILER │
│ (clang/gcc) │
└─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ SHARED LIBRARY │
│ (.dylib / .so / .dll) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────┐
│ PYTHON API │
│ (Circuit) │
└─────────────────┘
Two Languages, One System
SHDL actually consists of two related languages:
| Expanded SHDL | Base SHDL | |
|---|---|---|
| Purpose | Human authoring | Compilation target |
| Abstraction | High-level, convenient | Low-level, explicit |
| Hierarchy | Nested components | Flat, single-level |
| Features | Generators, expanders, constants | Primitives only |
Expanded SHDL is what you write. It includes powerful features like:
- Hierarchical component composition
- Generators for repetitive patterns
- Expanders for bit-range operations
- Named constants
- Import statements
Base SHDL is the intermediate representation after flattening. It contains:
- Only primitive gates (
AND,OR,NOT,XOR) - Power pins (
__VCC__,__GND__) - Explicit single-bit connections
- No hierarchy, no abstractions
Why This Architecture?
Separation of Concerns
- Flattener: Handles all language complexity (generators, hierarchy, etc.)
- Compiler: Only deals with simple primitives and connections
- Driver: Provides a clean Python interface
This separation makes each component simpler, easier to test, and easier to maintain.
Performance
The final C code uses a bit-packed SIMD-style approach:
- Gates of the same type are packed into 64-bit integers
- A single CPU operation evaluates up to 64 gates in parallel
- This makes simulation extremely fast
Portability
The generated C code is portable and can be compiled on any platform:
- macOS (
.dylib) - Linux (
.so) - Windows (
.dll)
Key Components
1. Lexer & Parser
Tokenizes and parses SHDL source code into an Abstract Syntax Tree (AST).
from SHDL import parse_file
module = parse_file("adder16.shdl")
for component in module.components:
print(f"Component: {component.name}")
2. Flattener
Transforms Expanded SHDL to Base SHDL through 5 phases:
- Lexical Stripping - Remove comments and imports
- Generator Expansion - Unroll all generators
- Expander Expansion - Expand bit-slice notation
- Constant Materialization - Convert constants to
__VCC__/__GND__ - Hierarchy Flattening - Inline all subcomponents
from SHDL import flatten_file
base_shdl = flatten_file("adder16.shdl", component="Adder16")
print(base_shdl)
3. Compiler
Compiles Base SHDL to optimized C code:
from SHDL import compile_shdl_file
c_code = compile_shdl_file("adder16.shdl")
print(c_code)
4. Driver
The Circuit class handles:
- Compilation to C
- Invoking the C compiler
- Loading the shared library
- Providing
poke(),peek(),step()interface
from SHDL import Circuit
with Circuit("adder16.shdl") as circuit:
circuit.poke("A", 100)
circuit.poke("B", 50)
circuit.step()
print(circuit.peek("Sum")) # 150
What's Next?
- Flattening Pipeline - Deep dive into the 5 flattening phases
- Compiler Internals - How C code generation works
- Base SHDL - The intermediate representation
- SHDB Debugger - Interactive debugging for SHDL circuits