Skip to content

Spec: Bidirectional Pins

Overview

Add bidirectional pin support to DigitalWorks, enabling pins that can function as both input and output depending on control signals. This is essential for modeling real-world buses (I2C SDA, memory data lines, GPIO ports).

Motivation

Real digital hardware frequently uses bidirectional data lines. Memory chips, microcontrollers, and communication buses (I2C, SPI with MISO/MOSI shared) all use pins that switch direction. Currently, DigitalWorks pins are strictly unidirectional, making it impossible to accurately model these circuits.

Requirements

Functional Requirements

  1. Bidirectional Pin Type: A new pin direction (Bidirectional) alongside existing Input and Output.
  2. Direction Control: A bidirectional pin's effective direction is controlled by an associated direction/enable signal within the component.
  3. Tri-State Behavior: When a bidirectional pin is in input mode, its output driver is in high-impedance (Floating) state.
  4. Bus Contention Detection: When two bidirectional pins on the same net both drive simultaneously, detect and report bus contention.
  5. Wire Connection: Bidirectional pins can connect to any other pin type (input, output, or bidirectional).
  6. Visual Indicator: Bidirectional pins are rendered with a distinct marker (double-headed arrow or diamond).
  7. Component Support: Provide bidirectional pins on Memory component data lines and Tri-State buffer.
  8. Simulation Accuracy: The simulation engine correctly resolves signal values when multiple drivers exist on a net (with priority: driven > floating).

Non-Functional Requirements

  • No performance regression for circuits that don't use bidirectional pins.
  • Existing circuits with tri-state buffers continue to work unchanged.
  • Clear error messages for contention situations.

Design

Domain Model Changes

csharp
public enum PinDirection
{
    Input,
    Output,
    Bidirectional  // NEW
}

public class Pin
{
    // Existing properties...
    public PinDirection Direction { get; set; }
    public bool IsDriverActive { get; set; }  // For bidirectional: is this pin currently driving?
}

Signal Resolution

When multiple drivers exist on a net (wire), resolve using:

  1. If exactly one driver is active → use that signal value.
  2. If zero drivers active → net is Floating.
  3. If multiple drivers active with same value → use that value (no contention).
  4. If multiple drivers active with different values → Bus Contention error.

Simulation Engine Changes

  • Add net-level signal resolution pass after component evaluation.
  • Track which bidirectional pins are actively driving via IsDriverActive.
  • Contention detection integrated into existing bus contention logic.

Rendering

  • Bidirectional pins shown with a diamond symbol (◇) instead of the standard circle/arrow.
  • During simulation, pin color indicates current direction (input=blue, output=red, hi-Z=gray).

UI/UX

  • Component property dialogs allow setting pin as bidirectional when editing macros.
  • Template Editor supports bidirectional pin placement.
  • Tooltip shows current pin state (driving/receiving/hi-Z) during simulation.

Implementation Tasks

  1. Add Bidirectional to PinDirection enum.
  2. Add IsDriverActive property to Pin class.
  3. Implement net-level signal resolution in SimulationStepEngine.
  4. Update contention detection to handle bidirectional scenarios.
  5. Update MemoryComponent data pins to use bidirectional type.
  6. Add bidirectional pin rendering (diamond marker, direction color).
  7. Update Template Editor for bidirectional pin support.
  8. Update wire connection validation rules.
  9. Add simulation tooltip showing pin drive state.
  10. Update file serialization for new pin direction type.

Risks & Open Questions

  • How to handle the transition period when a pin switches direction mid-simulation tick?
  • Should there be a configurable turnaround delay for direction changes?
  • Interaction with bus wires: does a bidirectional bus pin drive/receive all bits simultaneously?

Priority

High — Required for realistic memory and bus modeling.