Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Python Tests

on:
push:
branches: [main, corrina, dev]
paths:
- 'driver/python/**'
- 'test/quantum/**'
- 'api_server.py'
- 'pyproject.toml'
- 'requirements.txt'
pull_request:
branches: [main, corrina]
paths:
- 'driver/python/**'
- 'test/quantum/**'
- 'api_server.py'
- 'pyproject.toml'
- 'requirements.txt'

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Run quantum driver tests
run: |
python -m pytest test/quantum/ -v --tb=short

- name: Run demo script
run: |
python demo_accl_q.py
Comment on lines +23 to +48

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 7 months ago

In general, the fix is to explicitly define a permissions block that grants only the minimal required scopes for the GITHUB_TOKEN. For a pure test workflow that only checks out code and runs tests, read‑only repository contents access is sufficient, so contents: read at the workflow or job level is appropriate.

The best fix here, without changing existing functionality, is to add a workflow‑level permissions block near the top of .github/workflows/python-tests.yml, right after the name: and before the on: section. This will apply to all jobs in this workflow (there is only one job, test). The block should set contents: read, which is enough for actions/checkout@v4 and does not grant write privileges. No steps in this workflow require write access to issues, pull requests, or other resources, so we do not need additional scopes.

Concretely:

  • Edit .github/workflows/python-tests.yml.

  • Insert:

    permissions:
      contents: read

    between line 2 (blank line after name: Python Tests) and line 3 (on:). No other imports, methods, or definitions are needed because this is GitHub Actions configuration only.

Suggested changeset 1
.github/workflows/python-tests.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml
--- a/.github/workflows/python-tests.yml
+++ b/.github/workflows/python-tests.yml
@@ -1,5 +1,8 @@
 name: Python Tests
 
+permissions:
+  contents: read
+
 on:
   push:
     branches: [main, corrina, dev]
EOF
@@ -1,5 +1,8 @@
name: Python Tests

permissions:
contents: read

on:
push:
branches: [main, corrina, dev]
Copilot is powered by AI and may make mistakes. Always verify output.
36 changes: 33 additions & 3 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
# Installation instructions
# Installation Instructions

## Pull project
## ACCL-Q Python Driver (Quick Start)

```sh
git clone https://github.com/The-AI-Cowboys-Projects/ACCL_NEW.git
cd ACCL_NEW

# Install Python dependencies
pip install -r requirements.txt

# Run the demo
python demo_accl_q.py

# Run the test suite
python -m pytest test/quantum/ -v

# Start the API server
python -m uvicorn api_server:app --host 0.0.0.0 --port 8080
```

### Requirements

- Python 3.11+
- numpy >= 1.24
- fastapi, uvicorn, pydantic (for API server)
- pytest, pytest-asyncio, httpx (for tests)

---

## ACCL Hardware Build (Original)

### Pull project
```sh
git clone https://github.com/Xilinx/ACCL.git
git submodule update --init --recursive
```

## Install dependencies
### Install dependencies
The project has been tested with Xilinx Vitis 2022.1 on Ubuntu 20.04.
```sh
sudo apt update
Expand Down
79 changes: 72 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ This demonstrates sufficient margin for multi-round QEC within coherence limits.
│ Operation Modes │
│ ├── STANDARD - Default operation │
│ ├── DETERMINISTIC - Hardware-synchronized, minimal jitter │
│ └── LOW_LATENCY - Optimized for speed over consistency │
│ ├── LOW_LATENCY - Optimized for speed over consistency │
│ └── ULTRA_LOW_LATENCY - Hardware-autonomous sub-50ns feedback │
├─────────────────────────────────────────────────────────────────┤
│ Infrastructure │
│ └── IBM Cloud Code Engine (Serverless Container) │
Expand Down Expand Up @@ -181,6 +182,27 @@ curl -X POST ".../qec/syndrome" \
-d '{"num_ranks": 8, "syndrome_bits": 4}'
```

### ULL Pipeline

```bash
# Configure ULL pipeline
curl -X POST ".../ull/configure" \
-H "Content-Type: application/json" \
-d '{"syndrome_bits": 16, "coherence_time_us": 50.0}'

# Run autonomous feedback cycle
curl -X POST ".../ull/feedback?num_cycles=1"

# Run 100 continuous cycles
curl -X POST ".../ull/feedback?num_cycles=100"

# Check ULL status
curl ".../ull/status"

# Disarm pipeline
curl -X POST ".../ull/disarm"
```

### Qubit Emulator

```bash
Expand Down Expand Up @@ -266,23 +288,34 @@ docker run -p 8080:8080 accl-q

```
ACCL_NEW/
├── api_server.py # FastAPI REST API server
├── demo_accl_q.py # Comprehensive demo script
├── api_server.py # FastAPI REST API (includes ULL endpoints)
├── demo_accl_q.py # Comprehensive demo (6 demos incl. ULL)
├── pyproject.toml # Python packaging configuration
├── requirements.txt # Python dependencies
├── Dockerfile # Production container definition
├── .dockerignore # Docker build exclusions
├── driver/
│ └── python/
│ └── accl_quantum/ # Core ACCL-Q driver
│ ├── __init__.py # Package exports
│ ├── driver.py # ACCLQuantum main class
│ ├── constants.py # Enums, ULL config, latency budgets
│ ├── hardware_accel.py # DMA pool, LUT decoder, FPGA regs
│ ├── feedback.py # Feedback pipelines (std + ULL)
│ ├── emulator.py # RealisticQubitEmulator
│ ├── feedback.py # MeasurementFeedbackPipeline
│ ├── profiler.py # Critical path profiler
│ ├── stats.py # LatencyMonitor
│ └── constants.py # Enums and configuration
│ ├── deployment.py # Multi-board RFSoC deployment
│ ├── integrations.py # QubiC/QICK integrations
│ └── docs/ # Documentation
├── kernels/cclo/hls/quantum/ # HLS constants
│ └── quantum_hls_constants.h
├── test/
│ └── quantum/ # Test suite
│ └── quantum/ # Test suite (~200 tests)
│ ├── test_collective_ops.py
│ ├── test_integration.py
│ ├── test_ull_optimization.py
│ ├── test_ull_latency_validation.py
│ ├── test_module_coverage.py
│ └── test_latency_validation.py
└── README.md # This file
```
Expand All @@ -303,6 +336,38 @@ This experimental deployment validates that FPGA-based collective communication

---

## Ultra-Low-Latency (ULL) Mode

ACCL-Q v0.3.0 introduces ULL mode for hardware-autonomous feedback execution targeting **<50ns latency** (0.1% of 50us coherence time) — a 10x improvement over standard feedback.

| Component | Standard | ULL Target |
|-----------|----------|-----------|
| Multicast | 300ns | 10ns |
| Reduce | 400ns | 4ns |
| Decode | 50-200ns | 8ns |
| Trigger | 50ns | 2ns |
| **Total** | **~500ns** | **~34ns** |

```python
from accl_quantum import ACCLQuantum, ACCLMode
from accl_quantum.feedback import HardwareFeedbackEngine
from accl_quantum.constants import ULLPipelineConfig

# Zero-copy ULL collectives
accl = ACCLQuantum(num_ranks=4, local_rank=0)
accl.configure(mode=ACCLMode.ULTRA_LOW_LATENCY)
result = accl.broadcast(data, root=0) # 10ns, zero-copy

# Autonomous hardware feedback
engine = HardwareFeedbackEngine(ULLPipelineConfig())
engine.program_pipeline(decoder_fn=my_decoder, syndrome_bits=16)
result = engine.run_autonomous_cycle() # ~34ns per cycle
```

See [Performance Tuning Guide](driver/python/accl_quantum/docs/performance_tuning.md) for details.

---

## Future Work

- Integration with IBM Quantum systems via Qiskit
Expand Down
113 changes: 108 additions & 5 deletions api_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
NoiseParameters,
GateType,
)
from accl_quantum.feedback import MeasurementFeedbackPipeline, FeedbackConfig
from accl_quantum.feedback import MeasurementFeedbackPipeline, FeedbackConfig, HardwareFeedbackEngine
from accl_quantum.hardware_accel import HardwareAccelerator
from accl_quantum.constants import ULLPipelineConfig, ULL_TARGET_TOTAL_NS

# Constants
MAX_EMULATORS = 50
Expand All @@ -48,6 +50,7 @@
"standard": ACCLMode.STANDARD,
"deterministic": ACCLMode.DETERMINISTIC,
"low_latency": ACCLMode.LOW_LATENCY,
"ultra_low_latency": ACCLMode.ULTRA_LOW_LATENCY,
}

# Global instances
Expand All @@ -59,7 +62,7 @@
# Request/Response models
class CreateClusterRequest(BaseModel):
num_ranks: int = Field(default=4, ge=2, le=16, description="Number of FPGA ranks to simulate")
mode: str = Field(default="deterministic", description="Operation mode: standard, deterministic, low_latency")
mode: str = Field(default="deterministic", description="Operation mode: standard, deterministic, low_latency, ultra_low_latency")


class BroadcastRequest(BaseModel):
Expand Down Expand Up @@ -116,8 +119,8 @@ async def lifespan(app: FastAPI):

app = FastAPI(
title="ACCL-Q API",
description="Quantum Collective Communication Emulator API",
version="0.2.0",
description="Quantum Collective Communication Emulator API with Ultra-Low-Latency support",
version="0.3.0",
lifespan=lifespan
)

Expand All @@ -142,7 +145,7 @@ async def root():
"""API info."""
return {
"service": "ACCL-Q Quantum Emulator",
"version": "0.2.0",
"version": "0.3.0",
"endpoints": {
"/health": "Health check",
"/cluster": "Create/manage ACCL cluster",
Expand All @@ -151,6 +154,8 @@ async def root():
"/collective/allreduce": "Allreduce operation",
"/collective/barrier": "Barrier synchronization",
"/qec/syndrome": "QEC syndrome aggregation demo",
"/ull/status": "ULL pipeline status",
"/ull/feedback": "Run ULL autonomous feedback cycle",
"/emulator": "Create qubit emulator",
"/emulator/{id}/gate": "Apply quantum gate",
"/emulator/{id}/measure": "Measure qubits",
Expand Down Expand Up @@ -508,6 +513,104 @@ async def delete_emulator(emulator_id: str):
return {"success": True, "message": f"Emulator {emulator_id} deleted"}


# ULL Pipeline Endpoints
_ull_engine: Optional[HardwareFeedbackEngine] = None


class ULLConfigRequest(BaseModel):
syndrome_bits: int = Field(default=16, ge=1, le=512)
coherence_time_us: float = Field(default=50.0, gt=0)
fiber_length_m: float = Field(default=1.0, ge=0)


@app.get("/ull/status")
async def ull_status():
"""Get ULL pipeline status."""
if _ull_engine is None:
return {
"initialized": False,
"message": "ULL engine not initialized. POST /ull/configure first."
}

stats = _ull_engine.get_stats()
return {
"initialized": True,
"armed": _ull_engine._armed,
"stats": stats,
"latency_budget_ns": ULL_TARGET_TOTAL_NS,
}


@app.post("/ull/configure")
async def ull_configure(request: ULLConfigRequest):
"""Configure and arm the ULL hardware feedback pipeline."""
global _ull_engine

config = ULLPipelineConfig(
max_syndrome_bits=request.syndrome_bits,
coherence_time_us=request.coherence_time_us,
fiber_length_m=request.fiber_length_m,
)

_ull_engine = HardwareFeedbackEngine(config)

def simple_decoder(syndrome):
return syndrome

entries = _ull_engine.program_pipeline(
decoder_fn=simple_decoder,
syndrome_bits=request.syndrome_bits,
)

return {
"success": True,
"lut_entries": entries,
"estimated_latency_ns": _ull_engine._hw_accel.estimate_latency_ns(),
"message": f"ULL pipeline armed with {entries} LUT entries"
}


@app.post("/ull/feedback")
async def ull_feedback(num_cycles: int = 1):
"""Run ULL autonomous feedback cycle(s)."""
if _ull_engine is None:
raise HTTPException(
status_code=400,
detail="ULL engine not initialized. POST /ull/configure first."
)

if num_cycles == 1:
result = _ull_engine.run_autonomous_cycle()
return {
"success": result.success,
"total_latency_ns": result.total_latency_ns,
"within_budget": result.within_budget,
"phases": result.phases,
}
else:
results = _ull_engine.run_continuous(num_cycles=min(num_cycles, 1000))
violations = sum(1 for r in results if not r.within_budget)
latencies = [r.total_latency_ns for r in results]
return {
"success": all(r.success for r in results),
"num_cycles": len(results),
"violations": violations,
"mean_latency_ns": float(np.mean(latencies)),
"max_latency_ns": float(np.max(latencies)),
"min_latency_ns": float(np.min(latencies)),
}


@app.post("/ull/disarm")
async def ull_disarm():
"""Disarm the ULL pipeline."""
global _ull_engine
if _ull_engine is None:
raise HTTPException(status_code=400, detail="ULL engine not initialized")
_ull_engine.disarm()
return {"success": True, "message": "ULL pipeline disarmed"}


if __name__ == "__main__":
import uvicorn
port = int(os.environ.get("PORT", 8080))
Expand Down
Loading
Loading