Router Handlers
The Controller module defines routing logic for the simulator service. It connects API requests to appropriate handler functions that interact with a SimInterface strategy. Each route parses structured input using Pydantic models, delegates logic to the simulator backend, and returns standardized outputs such as simulation results, extracted data, and modified netlists.
Module Definition
Defined in: sim/controller.py
Purpose: Modular and extensible routing system suitable for simulators that follow different internal implementations.
Key Concepts
Strategy Pattern
All handlers rely on a strategy parameter, which is an instance of a class implementing the SimInterface. This abstracts backend simulator logic, allowing handlers to remain generic.
Data Validation
All handlers receive validated input data, structured using Pydantic models (e.g., Upload, Simulate, ModifyNetlist).
Handler Functions
@router.set("upload")
def upload(data: Upload, strategy: SimInterface) -> dict
Processes schematic upload and dependency management.
Parameters:
- data (Upload): Validated upload data containing schematic and dependencies
- strategy (SimInterface): Backend simulation strategy implementation
Process:
- Saves the schematic and dependencies to the project
- Calls SimInterface.upload() to extract netlist, parameters, components, and nets
- Returns a dictionary with the netlist, extracted data, and circuit graph
@router.set("modify_netlist")
def modify_netlist(data: ModifyNetlist, strategy: SimInterface) -> dict
Replaces existing netlist with provided netlist data.
Parameters:
- data (ModifyNetlist): Validated netlist modification data
- strategy (SimInterface): Backend simulation strategy implementation
Process:
- Replaces the existing netlist with the provided one
- Calls SimInterface.modify_netlist() and re-extracts metadata
- Returns the new netlist and associated metadata
@router.get("extract_parameters")
def extract_parameters(data: Empty, strategy: SimInterface) -> dict
Extracts parameters from the current circuit netlist.
Parameters:
- data (Empty): Empty data payload
- strategy (SimInterface): Backend simulation strategy implementation
Returns: Dictionary with a list of parameters
@router.get("extract_portables")
def extract_portables(data: Empty, strategy: SimInterface) -> dict
Extracts all portable elements including component types and models.
Parameters:
- data (Empty): Empty data payload
- strategy (SimInterface): Backend simulation strategy implementation
Returns: Dictionary with component metadata
@router.get("simulate")
def simulate(data: Simulate, strategy: SimInterface) -> dict
Executes circuit simulation with provided parameters.
Parameters:
- data (Simulate): Validated simulation configuration
- strategy (SimInterface): Backend simulation strategy implementation
Process:
- Constructs a SimulationContext and runs a simulation
- Returns the simulation result as provided by the backend
@router.get("optimize")
def optimize(data: Simulate, strategy: SimInterface) -> dict
Executes circuit optimization with provided parameters.
Parameters:
- data (Simulate): Validated simulation configuration
- strategy (SimInterface): Backend simulation strategy implementation
Process:
- Similar to simulate, but enables optimization mode
- Returns optimization results
@router.get("extract_nets")
def extract_nets(data: Empty, strategy: SimInterface) -> dict
Extracts electrical network information from current circuit.
Parameters:
- data (Empty): Empty data payload
- strategy (SimInterface): Backend simulation strategy implementation
Returns: List of all electrical nets in the current circuit
@router.get("port")
def port(data: Port, strategy: SimInterface) -> dict
Ports netlist to new component mapping based on specified model.
Parameters:
- data (Port): Validated port configuration data
- strategy (SimInterface): Backend simulation strategy implementation
Returns: Updated netlist and extracted metadata
Dependency Management
@router.get("deps")
def get_deps(data: GetCircuitDeps, strategy: SimInterface) -> dict
Lists all dependency files related to the given circuit.
Parameters:
- data (GetCircuitDeps): Circuit dependency query data
- strategy (SimInterface): Backend simulation strategy implementation
Returns: Nested dictionary representing the file structure
@router.set("deps")
def add_dep(data: UploadCircuitDep, strategy: SimInterface) -> dict
Uploads and registers a new circuit dependency file.
Parameters:
- data (UploadCircuitDep): Base64-encoded file upload data
- strategy (SimInterface): Backend simulation strategy implementation
Process:
- Uploads a base64-encoded file and adds it as a dependency
- Returns the updated dependency file structure
@router.delete("deps")
def delete_dep(data: DeleteCircuitDep) -> None
Removes specified circuit dependency file.
Parameters:
- data (DeleteCircuitDep): Dependency deletion specification
Returns: No content
Graph Operations
@router.get("extract_graph")
def extract_graph(data: Empty, strategy: SimInterface) -> dict
Extracts graph representation of the current netlist.
Parameters:
- data (Empty): Empty data payload
- strategy (SimInterface): Backend simulation strategy implementation
Returns: Graph nodes and edges for visualization or analysis
Design Principles
Abstraction
The abstraction via SimInterface allows this module to support multiple backend simulators with minimal changes.
Reliability
All functions are structured to accept validated inputs and return consistent outputs, improving reliability.
Separation of Concerns
The handlers focus solely on routing and delegating logic, adhering to separation of concerns.
Dependencies
- Pydantic models (Upload, Simulate, ModifyNetlist, Empty, Port, GetCircuitDeps, UploadCircuitDep, DeleteCircuitDep)
- SimInterface strategy pattern implementation
- SimulationContext for simulation execution