Architecture
This document describes ALY’s internal architecture and design principles.
System Overview
ALY is designed as a modular, extensible tool for HDL development workflows.
Figure 28 High-Level Architecture
Module Structure
Figure 29 Python Module Organization
Configuration System
The configuration system uses a hierarchical loading mechanism.
Figure 30 Configuration Loading Sequence
Configuration Class Hierarchy
Figure 31 Configuration Classes
Unit Registry System
ALY uses a unified unit registry that tracks individual components (modules, testbenches, builds) separately from their parent manifests. This enables efficient lookup and dependency resolution without requiring knowledge of the parent manifest.
Figure 32 Unit Reference Architecture
The unit registry provides several key capabilities:
- Direct Lookup
Components can be retrieved by name without knowing which manifest contains them:
# Get RTL module from anywhere in the project ref = config.get_rtl_module("cpu_core") module = ref.obj # RTLModule object manifest = ref.manifest # Parent RTLManifest
- Dependency Resolution
Dependencies are resolved recursively with automatic cycle detection:
# Resolve all RTL dependencies for a testbench deps = config.resolve_rtl_deps(testbench) for dep_ref in deps: module = dep_ref.obj files = dep_ref.manifest.get_files_for_module(module.name)
- Type Safety
Each unit type has dedicated accessor methods with proper typing:
# Type-safe accessors rtl_modules = config.list_rtl_modules() # List[str] testbenches = config.list_testbenches() # List[str] fw_builds = config.list_firmware_builds() # List[str] packages = config.list_packages() # List[str]
- Manifest Context
Units maintain bidirectional references to their parent manifests for path resolution and file access:
ref = config.get_rtl_module("alu") # Access module object module_name = ref.obj.name module_files = ref.obj.files # Access parent manifest for path resolution resolved_files = ref.manifest.get_files_for_module(ref.obj.name)
Unit Types
The registry tracks four unit types:
Unit Kind |
Source |
Description |
|---|---|---|
|
RTL manifests |
Individual synthesizable modules |
|
Testbench manifests |
Individual simulation testbenches |
|
Firmware manifests |
Individual firmware build configurations |
|
RTL manifests |
Named SystemVerilog packages |
Discovery Process
Units are registered during manifest discovery:
Figure 33 Unit Registration Flow
Manifest Validation
ALY validates manifests at load time to catch configuration errors early.
Figure 34 Manifest Validation Process
Validation checks include:
Syntax validation: YAML structure is well-formed
Schema validation: Required fields are present with correct types
Reference validation: Dependencies reference existing components
Path validation: File paths exist relative to manifest location
Uniqueness validation: Module/build names are unique within manifest
Type compatibility: Dependency types match referenced component types
Validation errors are reported with the manifest file path, line number (when available), and a descriptive error message to help users quickly locate and fix issues.
Backend System
Backends abstract tool-specific implementations.
Figure 35 Simulator Backend Architecture
Synthesis Backend Architecture
Figure 36 Synthesis Backend Architecture
Command Processing
Commands are processed through the Typer CLI framework.
Figure 37 Command Processing Flow
Error Handling
ALY uses a structured error handling approach to provide clear, actionable feedback.
Error Type |
Description |
Example |
|---|---|---|
Configuration Error |
Invalid or missing configuration files |
|
Manifest Error |
Invalid manifest structure or references |
|
Dependency Error |
Missing or circular dependencies |
|
Tool Error |
External tool execution failure |
|
File Error |
Missing or inaccessible files |
|
Backend Error |
Backend-specific errors |
|
Error messages include:
Context: Which file or component caused the error
Location: Line number or path when available
Description: Clear explanation of what went wrong
Suggestion: Recommended fix or next steps
Example error output:
Error: Manifest validation failed
File: testbench/tb_cpu/manifest.yaml
Line: 12
Issue: Dependency 'cpu_core' not found
The testbench references RTL module 'cpu_core' but this module
does not exist in rtl/manifest.yaml.
Suggestion: Add cpu_core to rtl/manifest.yaml or check the spelling.
Dependency Resolution
ALY resolves module dependencies through a graph-based approach.
Figure 38 Dependency Resolution Example
Resolution Algorithm
Figure 39 Dependency Resolution Algorithm
File Organization
aly-tool/
+-- src/
| +-- aly/
| +-- __init__.py # Package init
| +-- __main__.py # Entry point
| +-- commands.py # CLI command registration
| +-- configuration.py # Config loading utilities
| +-- backends.py # Backend registry
| +-- util.py # Utility functions
| +-- log.py # Logging setup
| |
| +-- app/ # CLI command implementations
| | +-- main.py # Main app
| | +-- init.py # Project init
| | +-- simulate.py # Simulation commands
| | +-- synthesize.py # Synthesis commands
| | +-- lint.py # Linting commands
| | +-- firmware.py # Firmware commands
| | +-- program.py # FPGA programming
| | +-- config.py # Config commands
| | +-- rtl.py # RTL management
| | +-- ip.py # IP management
| | +-- constraints.py # Constraint management
| |
| +-- config/ # Configuration system
| | +-- __init__.py
| | +-- project_config.py
| | +-- models/ # Data model classes
| | +-- __init__.py
| | +-- core.py # Core config models
| | +-- rtl.py # RTL manifest
| | +-- testbench.py # Testbench manifest
| | +-- firmware.py # Firmware manifest
| | +-- ip.py # IP manifest
| | +-- tools.py # Tool configs
| | +-- helpers.py # Helper classes
| |
| +-- sim_xsim.py # XSim backend
| +-- sim_verilator.py # Verilator backend
| +-- sim_questa.py # QuestaSim backend
| +-- synth_vivado.py # Vivado backend
| +-- synth_yosys.py # Yosys backend
| +-- fw_gcc.py # GCC firmware backend
| |
| +-- templates/ # Project templates
| +-- loader.py # Template loader
| +-- basic/ # Basic template
| +-- soc/ # SoC template
|
+-- docs/ # Documentation
+-- tests/ # Test suite
Design Principles
Modularity: Each component is self-contained and testable
Extensibility: New backends can be added without modifying core
Configuration-Driven: Behavior controlled through YAML configuration
Tool Abstraction: Unified interface regardless of underlying tool
Manifest-Based: Components described declaratively
Extension Points
Figure 40 Extension Points
Next Steps
API Reference - Python API reference
Contributing - Contributing guidelines