t1c-ir 0.0.2
Intermediate Representation and Compilation for T1C Neuromorphic Hardware
Requires Python: >=3.10
Keywords: neuromorphic, spiking-neural-networks, snn, intermediate-representation, compiler, graph-representation, deep-learning, machine-learning, hardware-acceleration

<div align="center" style="background-color: #08081e; width: 100%; padding: 0;">
  <img alt="T1C-IR Logo" src="https://www.type1compute.com/images/t1c-logo-light.png" style="max-width: 200px; height: auto; display: block;">
</div>

<br>

# T1C-IR - Intermediate Representation for T1C Neuromorphic Hardware

<!-- ![GitHub tag ](https://img.shields.io/github/v/tag/username/repo) -->


T1C-IR is an intermediate representation designed for Type 1 Compute (T1C) neuromorphic hardware. It provides a standardized format for representing spiking neural networks with support for serialization, graph manipulation, and hardware-specific optimizations.

T1C-IR serves as an intermediate format between neuromorphic frameworks and hardware platforms, enabling seamless model portability and deployment.

> Read more about T1C-IR in our [documentation](https://type1compute.github.io/docs/intro)

## Installation

```bash
uv add t1c-ir@git@github.com:type1compute/t1cir.git
```

Or with pip:

```bash
pip install t1c-ir
```

## Usage

T1C-IR serves as a format between neuromorphic platforms and will be installed alongside your framework of choice.
Using T1C-IR follows a simple pattern when you want to move from a *source* to a *target* platform:

```python
from t1c.ir import read, write

# Define a model
my_model = ...
# Save the model (source platform)
write("my_graph.t1c", my_model)
# Load the model (target platform)
imported_graph = read("my_graph.t1c")
```

### Quick Start

```python
from t1c.ir import Graph, Input, Output, Affine, LIF, read, write
import numpy as np

# Create a simple network
nodes = {
    "input": Input(input_type={"input": np.array([784])}),
    "fc1": Affine(
        weight=np.random.randn(128, 784).astype(np.float32),
        bias=np.zeros(128, np.float32)
    ),
    "lif1": LIF(
        tau=np.ones(128, np.float32) * 10.0,
        r=np.ones(128, np.float32) * 10.0,
        v_leak=np.zeros(128, np.float32),
        v_threshold=np.ones(128, np.float32)
    ),
    "output": Output(output_type={"output": np.array([128])})
}
edges = [("input", "fc1"), ("fc1", "lif1"), ("lif1", "output")]
graph = Graph(nodes=nodes, edges=edges)

# Serialize to file
write("model.t1c", graph)

# Load from file
loaded = read("model.t1c")
```

See our [example section](https://github.com/type1compute/snntorch/blob/main/examples/tutorial_snntorch_to_t1cir.ipynb) for a complete pipeline from snnTorch to T1C hardware.

## Frameworks that currently support T1C-IR

| **Framework** | **Write to T1C-IR** | **Read from T1C-IR** | **Examples** |
| --------------- | :--: | :--: | :------: |
| [snnTorch](https://github.com/jeshraghian/snntorch/) | ✓ | ✓ | [snnTorch to T1C tutorial](https://github.com/type1compute/snntorch/blob/main/examples/tutorial_snntorch_to_t1cir.ipynb) |

## Primitives

T1C-IR supports the following computational primitives:

| Primitive | Description |
|-----------|-------------|
| `Input` | Network input node |
| `Output` | Network output node |
| `Affine` | Fully-connected layer (Linear) |
| `SpikingAffine` | Hardware-optimized spiking linear layer |
| `Conv2d` | 2D convolution |
| `SepConv2d` | Depthwise separable convolution |
| `MaxPool2d` | 2D max pooling |
| `AvgPool2d` | 2D average pooling |
| `Upsample` | 2D spatial upsampling (nearest/bilinear) |
| `Flatten` | Tensor flattening |
| `LIF` | Leaky Integrate-and-Fire neuron |
| `Skip` | Skip/residual connection |

## NIR Acknowledgement

T1C-IR is inspired by and builds upon the [Neuromorphic Intermediate Representation (NIR)](https://github.com/neuromorphs/NIR) project, a collaborative effort to create a standardized format for neuromorphic computing across multiple platforms.

We acknowledge the NIR authors and their published work:

> Pedersen, Jens E. et al. "Neuromorphic intermediate representation: A unified instruction set for interoperable brain-inspired computing." *Nature Communications* 15, 8122 (2024). https://doi.org/10.1038/s41467-024-52259-9

### T1C-IR vs NIR: Key Differences

T1C-IR is **not a fork** of NIR. It is an independent implementation that shares similar design principles but is specifically tailored for Type 1 Compute (T1C) FPGA hardware. The key differences are:

| Aspect | NIR | T1C-IR |
|--------|-----|-------|
| **Target** | Cross-platform interoperability | T1C FPGA hardware |
| **Primitives** | General-purpose set (17+ primitives) | Hardware-focused subset |
| **Serialization** | HDF5 (`.nir` files) | HDF5 (`.t1c` files) |
| **Graph structure** | Allows cycles (recurrent) | DAG-only (temporal recurrence via state) |
| **File format** | Compatible structure | Similar but independent |

#### Primitives Comparison

| **T1C-IR Primitive** | **NIR Equivalent** | **Notes** |
|---------------------|-------------------|-----------|
| `Affine` | `Affine` | Same semantics (y = Wx + b) |
| `LIF` | `LIF` | Same NIR-compliant dynamics |
| `Conv2d` | `Conv2d` | Same semantics |
| `Flatten` | `Flatten` | Same semantics |
| `MaxPool2d` | `SumPool2d` | T1C-IR uses max, NIR uses sum |
| `AvgPool2d` | `AvgPool2d` | Same semantics |
| `Upsample` | *(none)* | **T1C-IR addition**: FPN/detection support |
| `Skip` | *(edge-based)* | **T1C-IR addition**: Explicit skip node |
| `SpikingAffine` | *(none)* | **T1C-IR addition**: Hardware hints |
| `SepConv2d` | *(none)* | **T1C-IR addition**: Mobile/edge efficiency |
| *(none)* | `Linear` | NIR has weight-only linear (no bias) |
| *(none)* | `IF`, `LI`, `I` | NIR has more neuron variants |
| *(none)* | `CubaLIF`, `CubaLI` | NIR has current-based neurons |
| *(none)* | `Delay` | NIR has explicit delay nodes |
| *(none)* | `Threshold` | NIR has standalone threshold |
| *(none)* | `Scale` | NIR has scaling operation |
| *(none)* | `Conv1d` | NIR has 1D convolution |

#### Why T1C-IR is Separate

1. **Hardware specificity**: T1C-IR includes primitives like `SpikingAffine` with quantization hints (`weight_bits`, `accumulator_bits`) that are specific to T1C FPGA compilation.

2. **DAG enforcement**: T1C hardware benefits from directed acyclic graphs for pipelining. Temporal recurrence is handled via stateful neurons across timesteps, not graph cycles.

3. **Skip as node**: T1C-IR represents skip/residual connections as explicit nodes rather than edge annotations. This provides clearer hardware mapping for T1C compilers.

4. **Focused primitive set**: T1C-IR only includes primitives relevant to T1C deployment, avoiding complexity from unused neuron types.

5. **Independent evolution**: T1C-IR can evolve to match T1C hardware requirements without being constrained by cross-platform compatibility.

#### File Format Compatibility

T1C-IR `.t1c` files use HDF5 with a structure similar to NIR `.nir` files:

```
├── version          # Format version string
└── node/            # Graph root
    ├── type         # "Graph"
    ├── nodes/       # Node dictionary
    │   ├── input/
    │   ├── fc1/
    │   └── ...
    └── edges/       # Edge list
        ├── src      # Source node names
        └── dst      # Destination node names
```

While structurally similar, T1C-IR files are **not directly interchangeable** with NIR files due to:
- Different primitive type names in some cases
- T1C-IR-specific primitives (`SpikingAffine`, `SepConv2d`, `Skip`)
- Different version strings

## Documentation

For more information, visit the [T1C-IR documentation](https://type1compute.github.io/docs/intro).