Synthesis Dashboard¶
The Synthesis Dashboard provides one-click FPGA synthesis from the Visual SNN Studio. Generate Verilog from your neuron equations, then synthesise to any supported FPGA target to see resource usage and timing estimates.
These reports describe the generated RTL and selected tool targets; physical board deployment needs separate validation.
Quick Start¶
- Write your ODE in the Equation Editor (switch to ODE mode)
- Click Build IR to build the intermediate representation
- Click Emit SystemVerilog to emit SystemVerilog
- Open the FPGA synthesis view
- Select your target FPGA (ice40, ECP5, Gowin, Xilinx)
- Click Synthesise for exact Yosys results, or Estimate for a quick heuristic
Workflows¶
Single-Target Synthesis¶
Select a target from the dropdown, click Synthesise. Yosys runs the target-specific synthesis pass and returns resource counts with utilisation bars.
In catalogue-model mode the same button is labelled Synthesise + Route.
Studio requires the current studio.compile-traceability.v1 object and a
bit-exact studio.cosim-parity.v1 report for the same RTL bytes, then runs
Yosys and nextpnr in one isolated job. The browser does not submit a host
filesystem path. This terminal is available for iCE40 and ECP5; a wide design
can still exceed the selected device/package I/O or logic capacity and fails
with the real tool result.
Multi-Target Comparison¶
Click All Targets to run Yosys synthesis on all four supported targets simultaneously. Results appear in a comparison table showing LUTs, FFs, BRAMs, and DSPs side-by-side, so you can pick the best target for your design.
Resource Estimation (No Yosys Required)¶
If Yosys is not installed, click Estimate after building the IR. The estimator uses a heuristic based on IR operation count:
- Each IR op maps to ~2 LUTs + 1 FF
- LIF step op maps to ~12 LUTs + 8 FFs + 1 DSP
This gives a rough sizing before committing to a full synthesis run.
End-to-End Pipeline¶
ODE equation
→ [IR button] SC Intermediate Representation
→ [SV button] SystemVerilog
→ [FPGA synthesis view → Synthesise + Route] Yosys resource report
→ [same isolated job] nextpnr routed-design and timing report (ice40/ECP5 only)
From differential equation to FPGA resource estimate in seconds, from a single browser tab.
Supported FPGA Targets¶
| Target | Judged against | Synth Tool | PnR Tool | LUTs | FFs | BRAMs | DSPs |
|---|---|---|---|---|---|---|---|
| ice40 | iCE40 UP5K | synth_ice40 |
nextpnr-ice40 | 5,280 | 5,280 | 30 | 8 |
| ECP5 | ECP5 LFE5U-25F | synth_ecp5 |
nextpnr-ecp5 | 24,288 | 24,288 | 56 | 28 |
| Gowin | Gowin GW2A-18 | synth_gowin |
— | 20,736 | 15,552 | 46 | 48 |
| Xilinx | Artix-7 XC7A35T | synth_xilinx -flatten |
— | 20,800 | 41,600 | 100 (RAMB18) | 90 |
Sources: the iCE40 and ECP5 rows are what nextpnr-ice40 --up5k and
nextpnr-ecp5 --25k report for the device (the ECP5 data sheet rounds to
"24K"); Gowin from data sheet DS102 (GW2A-18: 20,736 LUT4, 15,552 flip-flops,
46 B-SRAM, 48 18×18 multipliers); Xilinx from DS180 (XC7A35T: 50 RAMB36, counted
as 100 RAMB18 halves so an 18 Kb block counts once). Gowin and Xilinx
synthesis here is not bound to one device, so every verdict names the device
it was judged against. Each target's netlist is written with write_json:
synth_xilinx has no -json option (the Xilinx target failed on every design
until this was corrected), and synth_gowin -json withholds block RAM for
nextpnr-gowin, which this target does not run.
Resource Metrics¶
The dashboard shows four resource bars:
- LUTs — Look-Up Tables (combinational logic)
- Flip-Flops — Sequential elements (registers)
- Block RAMs — On-chip memory blocks
- DSPs — Digital Signal Processing blocks (multipliers)
Each bar shows absolute count and percentage utilisation against the
target device's capacity; a share above 100 % is shown as it is and marked
over capacity. Every synthesis and estimate result carries fits_device and
exceeds_capacity (per resource, what the design needs and what the device
has), and the view says whether the device holds the design: a netlist that
synthesises is not a design that fits. The network pipeline stops at a fit
step when it does not. When synthesis itself fails the pipeline stops at
synthesise with Yosys's own ERROR: lines (the end of its log is usually
the help text it prints after an error); when Yosys runs past its 60 s limit
(timed_out: true), the stop names the network's size and says the fit is
unknown. The iCE40 capacity is the UltraPlus UP5K's: 5280
LUTs and flip-flops, 30 EBR blocks and 8 SB_MAC16 DSP blocks. The
multi-target comparison table shows all four metrics across all targets.
Resources are counted from each family's own primitives, in the design's
modules only (Yosys also writes the family's cell library, which is not the
design): an ECP5 CCU2C carry cell is two LUT4s, a Gowin MUX2_LUT5–8
wide multiplexer and an iCE40 SB_CARRY take no LUT, Xilinx distributed RAM
counts its LUTs (a RAM256X1S is four) and not block RAM, and SB_MAC16,
DP16KD and RAMB36E1 are counted where substring matching missed them.
A cell whose cost is not known (ECP5 and Gowin distributed RAM such as
TRELLIS_DPR16X4 or RAM16SDP4, a hand-placed primitive) is listed in
uncounted_cells; the counts are then a floor, so fits_device is null
unless they already overflow. capacity_device names the device.
A fit is by count: necessary, not sufficient. On iCE40 and ECP5 a LUT and a
flip-flop share a logic cell (a design of 708 LUTs and 98 flip-flops took
752 UP5K cells), and placement and routing can still fail; /api/synth/pnr
decides that for iCE40 and ECP5.
Tool Installation¶
The synthesis pipeline uses open-source FPGA tools:
# macOS (Homebrew)
brew install yosys nextpnr
# Ubuntu/Debian
apt install yosys nextpnr-ice40
# Windows (MSYS2)
pacman -S mingw-w64-x86_64-yosys
# Verify installation
yosys --version
nextpnr-ice40 --version
The /api/synth/tools-status endpoint reports which tools are available.
The dashboard shows green/grey indicators for each tool, with version
strings when available.
Target Provenance¶
Synthesis responses include target_provenance using the
studio.synthesis-target-provenance.v1 schema. The payload records the target
ID, Yosys synthesis command, optional nextpnr command and device selector,
static capacity metadata, tool availability, tool version strings when
available, readiness booleans, the synthesis evidence classification, and a
provenance_grade claim grade. The grade is tool_backed only when every
required tool for the target was detected and reported a version; otherwise it
is unverified (missing tool, missing version, or no required tools). An
unverified result must not be presented as release-grade PPA evidence — it
records that synthesis ran without confirmed tool provenance.
The serializer validates the class and the completed terminal status
through the shared Studio evidence-classification contract before returning
public metadata. It is path-free and suitable for operator logs and evidence
bundles.
Multi-target responses additionally include
target_provenance_matrix with schema
studio.synthesis-target-provenance-matrix.v1. The matrix captures the same
target records for every supported target, top-level synthesis evidence
classification, top-level completed terminal status, an aggregate
provenance_grade that is tool_backed only when every target is
tool_backed, and a stable
matrix_sha256 digest so operators can compare target-support evidence across
runs without relying on local filesystem paths. The Studio dashboard renders
that matrix after an all-target run, showing each target's device selector,
synthesis readiness, PnR readiness, tool command, evidence classification,
status, and shortened matrix digest without exposing host-local paths.
API Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/synth/tools-status |
Detect installed EDA tools |
| POST | /api/synth/run |
Verilog + target → Yosys synthesis |
| POST | /api/synth/terminal |
Selected RTL + compile/co-sim evidence → same-job Yosys + nextpnr |
| POST | /api/synth/multi-target |
Verilog → all targets comparison |
| POST | /api/synth/estimate |
IR op count → heuristic estimate |
| POST | /api/synth/pnr |
JSON netlist → nextpnr place & route |
/api/synth/run, /api/synth/terminal, /api/synth/multi-target, and
/api/synth/pnr execute
through the Studio local worker manager. They preserve the synchronous response
payloads shown below and additionally create Admin queue records with result
artifacts at synthesis/result.json,
synthesis/terminal-result.json, synthesis/multi-target-result.json, and
synthesis/pnr-result.json. A successful terminal job also retains
synthesis/terminal-netlist.json and synthesis/terminal-routed.config; the
result identifies both artifacts by SHA-256 rather than returning host paths.
On POSIX hosts, Yosys and nextpnr child processes receive configured CPU and
address-space ceilings from SC_NEUROCORE_STUDIO_EDA_PROCESS_CPU_SECONDS and
SC_NEUROCORE_STUDIO_EDA_PROCESS_MEMORY_BYTES; unsupported hosts keep the
existing wall-clock subprocess timeouts.
GET /api/synth/tools-status¶
Returns availability and version for each tool:
{
"yosys": {"available": true, "version": "Yosys 0.40"},
"nextpnr_ice40": {"available": true, "version": "nextpnr-ice40 0.7"},
"nextpnr_ecp5": {"available": false, "version": null},
"firtool": {"available": false, "version": null}
}
POST /api/synth/run¶
{
"verilog": "module sc_lif(...); ... endmodule",
"target": "ice40"
}
Returns:
{
"success": true,
"target": "ice40",
"resources": {"luts": 42, "ffs": 18, "brams": 0, "dsps": 0, "cells": 60, "wires": 85},
"capacity": {"luts": 5280, "ffs": 5280, "brams": 30, "dsps": 8},
"utilisation": {"luts": 0.8, "ffs": 0.3, "brams": 0.0, "dsps": 0.0},
"fits_device": true,
"exceeds_capacity": {},
"capacity_device": "iCE40 UP5K",
"uncounted_cells": {},
"log_excerpt": "...",
"target_provenance": {
"schema_version": "studio.synthesis-target-provenance.v1",
"target": "ice40",
"synthesis_command": "synth_ice40",
"pnr_tool": "nextpnr-ice40",
"device": "up5k",
"synthesis_ready": true,
"pnr_ready": true,
"provenance_grade": "tool_backed",
"evidence_classification": "synthesis",
"status": "completed",
"tools": [
{"key": "yosys", "executable": "yosys", "role": "synthesis", "available": true, "version": "Yosys 0.40"}
]
}
}
POST /api/synth/multi-target¶
{"verilog": "module sc_lif(...); ... endmodule"}
Returns synthesis results for all supported targets:
{
"targets": {
"ice40": {"success": true, "target": "ice40", "resources": {...}, ...},
"ecp5": {"success": true, "target": "ecp5", "resources": {...}, ...},
"gowin": {"success": true, ...},
"xilinx": {"success": true, ...}
},
"target_provenance_matrix": {
"evidence_classification": "synthesis",
"provenance_grade": "tool_backed",
"schema_version": "studio.synthesis-target-provenance-matrix.v1",
"status": "completed",
"matrix_sha256": "<64 lowercase hex characters>",
"targets": {"ice40": {...}, "ecp5": {...}, "gowin": {...}, "xilinx": {...}}
},
"supported": ["ice40", "ecp5", "gowin", "xilinx"]
}
POST /api/synth/terminal¶
The Admin-only selected-model terminal accepts the generated RTL plus the complete compile traceability and co-simulation parity objects returned by the Studio compiler routes:
{
"verilog": "module sc_adaptive_threshold_if_neuron(...); ... endmodule",
"target": "ecp5",
"compile_traceability": {"schema_version": "studio.compile-traceability.v1", "...": "..."},
"cosim_parity": {"schema_version": "studio.cosim-parity.v1", "bit_exact": true, "...": "..."}
}
The backend recomputes the RTL, compile-input, and compile-traceability digests;
requires model source, completed status, bit-exact parity, matching module and
configuration fields; and verifies the co-simulated RTL digest before invoking
EDA tools. The path-free studio.silicon-terminal.v1 response contains the
validated source-chain digests, exact Yosys resource result, nextpnr timing
result, target/tool provenance, and SHA-256 digests for the retained Yosys JSON
netlist and routed design.
This report is pre-bitstream FPGA implementation evidence. It does not claim a board-ready bitstream, pin-constrained board integration, hardware deployment, power, GDSII, or ASIC physical closure.
POST /api/synth/estimate¶
Quick heuristic estimate without running Yosys:
{"ir_op_count": 10, "target": "ice40"}
Returns:
{
"target": "ice40",
"estimated": true,
"resources": {"luts": 32, "ffs": 18, "brams": 0, "dsps": 1},
"capacity": {"luts": 5280, "ffs": 5280, "brams": 30, "dsps": 8},
"utilisation": {"luts": 0.6, "ffs": 0.3, "brams": 0.0, "dsps": 12.5},
"fits_device": true,
"exceeds_capacity": {},
"capacity_device": "iCE40 UP5K",
"uncounted_cells": {}
}
POST /api/synth/pnr¶
Place-and-route a Yosys JSON netlist (ice40 and ECP5 only):
{"json_path": "/path/to/design.json", "target": "ice40"}
Returns timing analysis:
{
"success": true,
"max_freq_mhz": 48.3,
"critical_path": "clk -> neuron.v_reg -> spike_out",
"log_excerpt": "..."
}