Skip to content

Spec: Plugin/Extension API

Overview

Provide a plugin system that allows users and third parties to extend DigitalWorks with custom components, analysis tools, exporters, and UI panels without modifying the core application.

Motivation

  • Users with specialized needs can create custom components (FPGA primitives, industry-specific ICs).
  • Educators can build course-specific extensions (grading tools, guided exercises).
  • Community can contribute features without core team involvement.
  • Keeps the core application lean while enabling unlimited extensibility.

Requirements

Functional Requirements

Plugin System

  1. Plugin Discovery: Automatically discover plugins in a designated folder.
  2. Plugin Loading: Load .NET assemblies at runtime as plugins.
  3. Plugin Lifecycle: Init, Activate, Deactivate, Unload lifecycle hooks.
  4. Plugin Isolation: Plugins cannot crash the host application.
  5. Plugin Manager UI: View installed plugins, enable/disable, configure.
  6. Hot Reload: Reload plugins without restarting the application (dev mode).

Extension Points

  1. Custom Components: Define new components with custom logic, pins, and rendering.
  2. Custom Exporters: Add new export formats (File → Export → [plugin format]).
  3. Custom Importers: Add new import formats.
  4. Custom Analysis Tools: Add analysis panels/windows.
  5. Custom Renderers: Override or extend component rendering.
  6. Menu Extensions: Add custom menu items and commands.
  7. Toolbox Extensions: Add custom categories and components to the toolbox.
  8. Context Menu Extensions: Add items to right-click context menus.
  9. Event Hooks: Subscribe to circuit events (component added, simulation step, etc.).

Scripting (Lightweight Alternative)

  1. C# Scripting: Write simple components using C# scripting (Roslyn) without full projects.
  2. Script Editor: Built-in editor for quick component scripts.
  3. Script Components: Components defined by a script file (evaluate function).

Non-Functional Requirements

  • Plugins cannot access the filesystem beyond their own data folder without permission.
  • Plugin API is versioned; old plugins work with new app versions (backward compatible).
  • Plugin loading adds < 500ms to application startup.
  • Plugins are sandboxed: memory limits, no UI thread blocking.
  • API is well-documented with examples and templates.

Design

Plugin Architecture

DigitalWorks Host
    → PluginManager
        → discovers plugins in /plugins/ folder
        → loads assemblies via AssemblyLoadContext (isolation)
        → creates plugin instances
        → registers extension points

Plugin Assembly
    → implements IPlugin interface
    → uses DigitalWorks.SDK NuGet package
    → declares capabilities via attributes

Core Interfaces

csharp
public interface IPlugin
{
    string Name { get; }
    string Version { get; }
    string Description { get; }
    void Initialize(IPluginContext context);
    void Activate();
    void Deactivate();
}

public interface IPluginContext
{
    IComponentRegistry Components { get; }
    IExporterRegistry Exporters { get; }
    IMenuRegistry Menus { get; }
    IEventBus Events { get; }
    IStorageProvider Storage { get; }  // plugin-local storage
}

public interface ICustomComponent
{
    string TypeName { get; }
    string Category { get; }
    IReadOnlyList<PinDefinition> Pins { get; }
    void Evaluate(IEvaluationContext context);
    ShapeDefinition GetShape();
}

Plugin Manifest

Each plugin folder contains a plugin.json:

json
{
  "name": "My Custom Components",
  "version": "1.0.0",
  "author": "John Doe",
  "description": "Adds custom FPGA primitives",
  "assembly": "MyPlugin.dll",
  "minHostVersion": "2.0.0",
  "permissions": ["filesystem:read", "network:none"],
  "extensionPoints": ["components", "exporters"]
}

Script Component Example

csharp
// File: scripts/my_gate.csx
#r "DigitalWorks.SDK"

[Component("MySpecialGate", Category = "Custom")]
[Pin("A", Direction.Input)]
[Pin("B", Direction.Input)]
[Pin("Y", Direction.Output)]
public void Evaluate(IEvaluationContext ctx)
{
    var a = ctx.GetInput("A");
    var b = ctx.GetInput("B");
    ctx.SetOutput("Y", (a == Signal.High && b == Signal.Low) ? Signal.High : Signal.Low);
}

Plugin Manager UI

┌──────────────────────────────────────┐
│ Plugin Manager                       │
├──────────────────────────────────────┤
│ Installed Plugins:                   │
│                                      │
│ [✓] FPGA Primitives v1.2.0         │
│     Adds Xilinx LUT, BRAM, DSP     │
│     [Configure] [Disable] [Remove]  │
│                                      │
│ [✓] SPICE Exporter v0.9.0          │
│     Advanced SPICE netlist export   │
│     [Configure] [Disable] [Remove]  │
│                                      │
│ [ ] Grading Tool v1.0.0 (disabled)  │
│     Auto-grades student circuits    │
│     [Configure] [Enable]  [Remove]  │
│                                      │
│ [Install from file...]  [Open folder]│
└──────────────────────────────────────┘

Implementation Tasks

  1. Design and document the Plugin SDK (interfaces, attributes, base classes).
  2. Create DigitalWorks.SDK NuGet package (public API surface).
  3. Implement PluginManager with assembly discovery and loading.
  4. Implement AssemblyLoadContext-based isolation.
  5. Implement IComponentRegistry for custom component registration.
  6. Implement IExporterRegistry for custom export formats.
  7. Implement IMenuRegistry for menu/toolbar extensions.
  8. Implement IEventBus for plugin event subscriptions.
  9. Implement C# scripting engine (Roslyn) for script components.
  10. Create Plugin Manager UI.
  11. Create plugin project template (dotnet new template).
  12. Write SDK documentation and sample plugins.

Risks & Open Questions

  • Security: how to sandbox plugins effectively in .NET? (AssemblyLoadContext has limits)
  • Should there be a plugin marketplace/repository?
  • How to handle plugin conflicts (two plugins register same component name)?
  • Performance impact of event bus with many subscribers?
  • Should plugins be able to modify the UI (add panels, windows)?
  • Versioning: how to handle breaking API changes without breaking all plugins?

Priority

Medium-Low — Significant architecture investment; valuable for ecosystem growth.