rocket-engine 0.0.2b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rocket_engine/__init__.py +8 -0
- rocket_engine/__main__.py +12 -0
- rocket_engine/adapters/README.md +54 -0
- rocket_engine/adapters/__init__.py +7 -0
- rocket_engine/adapters/api.py +39 -0
- rocket_engine/adapters/base.py +46 -0
- rocket_engine/adapters/cace/__init__.py +163 -0
- rocket_engine/adapters/circulax/README.md +10 -0
- rocket_engine/adapters/circulax/__init__.py +112 -0
- rocket_engine/adapters/circulax/_driver.py +190 -0
- rocket_engine/adapters/circulax/adapter.py +538 -0
- rocket_engine/adapters/circulax/results.py +291 -0
- rocket_engine/adapters/cli/README.md +34 -0
- rocket_engine/adapters/cli/__init__.py +305 -0
- rocket_engine/adapters/connectivity/__init__.py +196 -0
- rocket_engine/adapters/connectivity/results.py +214 -0
- rocket_engine/adapters/cosim/README.md +9 -0
- rocket_engine/adapters/cosim/__init__.py +1390 -0
- rocket_engine/adapters/cosim/results.py +214 -0
- rocket_engine/adapters/devsim/__init__.py +171 -0
- rocket_engine/adapters/digital_flow/README.md +9 -0
- rocket_engine/adapters/digital_flow/__init__.py +1121 -0
- rocket_engine/adapters/digital_flow/results.py +227 -0
- rocket_engine/adapters/digital_flow/state.py +462 -0
- rocket_engine/adapters/drc/README.klayout.md +7 -0
- rocket_engine/adapters/drc/README.md +7 -0
- rocket_engine/adapters/drc/__init__.py +1 -0
- rocket_engine/adapters/drc/klayout.py +952 -0
- rocket_engine/adapters/drc/magic.py +287 -0
- rocket_engine/adapters/drc/results.py +184 -0
- rocket_engine/adapters/drc/results_kl.py +188 -0
- rocket_engine/adapters/elmer/__init__.py +163 -0
- rocket_engine/adapters/envelope.py +120 -0
- rocket_engine/adapters/equivalence/__init__.py +156 -0
- rocket_engine/adapters/errors.py +181 -0
- rocket_engine/adapters/extract_magic/README.md +15 -0
- rocket_engine/adapters/extract_magic/__init__.py +425 -0
- rocket_engine/adapters/extract_magic/results.py +209 -0
- rocket_engine/adapters/formal_sby/README.md +7 -0
- rocket_engine/adapters/formal_sby/__init__.py +773 -0
- rocket_engine/adapters/formal_sby/formal_edge.py +195 -0
- rocket_engine/adapters/formal_sby/results.py +185 -0
- rocket_engine/adapters/gdsfactory/__init__.py +194 -0
- rocket_engine/adapters/gdsfactory/_driver.py +459 -0
- rocket_engine/adapters/gdsfactory/adapter.py +609 -0
- rocket_engine/adapters/gdsfactory/results.py +181 -0
- rocket_engine/adapters/hdl_sim/README.md +7 -0
- rocket_engine/adapters/hdl_sim/__init__.py +369 -0
- rocket_engine/adapters/hdl_sim/ghdl.py +155 -0
- rocket_engine/adapters/hdl_sim/results.py +178 -0
- rocket_engine/adapters/hdl_sim/verilator.py +167 -0
- rocket_engine/adapters/http/README.md +15 -0
- rocket_engine/adapters/http/__init__.py +458 -0
- rocket_engine/adapters/http/events.py +63 -0
- rocket_engine/adapters/ipc/README.md +9 -0
- rocket_engine/adapters/ipc/__init__.py +111 -0
- rocket_engine/adapters/lvs_netgen/README.md +20 -0
- rocket_engine/adapters/lvs_netgen/__init__.py +889 -0
- rocket_engine/adapters/lvs_netgen/results.py +168 -0
- rocket_engine/adapters/mcp/README.md +19 -0
- rocket_engine/adapters/mcp/__init__.py +85 -0
- rocket_engine/adapters/mcp/api-schema.json +6107 -0
- rocket_engine/adapters/mcp/pull.py +246 -0
- rocket_engine/adapters/mcp/server.py +794 -0
- rocket_engine/adapters/meep/__init__.py +167 -0
- rocket_engine/adapters/meow/README.md +7 -0
- rocket_engine/adapters/meow/__init__.py +190 -0
- rocket_engine/adapters/meow/_driver.py +227 -0
- rocket_engine/adapters/meow/_envelope.py +108 -0
- rocket_engine/adapters/meow/adapter.py +491 -0
- rocket_engine/adapters/meow/results.py +218 -0
- rocket_engine/adapters/mutation/__init__.py +192 -0
- rocket_engine/adapters/ngspice/README.md +28 -0
- rocket_engine/adapters/ngspice/__init__.py +627 -0
- rocket_engine/adapters/ngspice/results.py +215 -0
- rocket_engine/adapters/postlayout/README.md +28 -0
- rocket_engine/adapters/postlayout/__init__.py +17 -0
- rocket_engine/adapters/postlayout/adapter.py +1062 -0
- rocket_engine/adapters/postlayout/results.py +330 -0
- rocket_engine/adapters/postlayout/translate.py +71 -0
- rocket_engine/adapters/profile.py +220 -0
- rocket_engine/adapters/sax/README.md +23 -0
- rocket_engine/adapters/sax/__init__.py +516 -0
- rocket_engine/adapters/sax/_driver.py +148 -0
- rocket_engine/adapters/sax/results.py +291 -0
- rocket_engine/adapters/stdio_console.py +1151 -0
- rocket_engine/adapters/syntax/README.md +5 -0
- rocket_engine/adapters/syntax/__init__.py +366 -0
- rocket_engine/adapters/syntax/results.py +181 -0
- rocket_engine/adapters/synth_yosys/README.md +7 -0
- rocket_engine/adapters/synth_yosys/__init__.py +655 -0
- rocket_engine/adapters/synth_yosys/amaranth.py +120 -0
- rocket_engine/adapters/synth_yosys/ghdl.py +128 -0
- rocket_engine/adapters/synth_yosys/results.py +173 -0
- rocket_engine/adapters/timing_sta/README.md +9 -0
- rocket_engine/adapters/timing_sta/__init__.py +726 -0
- rocket_engine/adapters/view_sync/__init__.py +185 -0
- rocket_engine/adapters/view_sync/results.py +189 -0
- rocket_engine/adapters/vlsir/__init__.py +142 -0
- rocket_engine/adapters/xschem/__init__.py +440 -0
- rocket_engine/adapters/xschem/deck.py +266 -0
- rocket_engine/clients/__init__.py +5 -0
- rocket_engine/clients/runtime.py +255 -0
- rocket_engine/composition.py +2279 -0
- rocket_engine/execution/README.md +30 -0
- rocket_engine/execution/__init__.py +150 -0
- rocket_engine/execution/apig/__init__.py +1 -0
- rocket_engine/execution/apig/pool.py +463 -0
- rocket_engine/execution/apig/submit.py +124 -0
- rocket_engine/execution/block_runs_scope.py +479 -0
- rocket_engine/execution/coalesce.py +414 -0
- rocket_engine/execution/console/__init__.py +1 -0
- rocket_engine/execution/console/apply_session.py +318 -0
- rocket_engine/execution/console/lifecycle.py +265 -0
- rocket_engine/execution/dispatch.py +205 -0
- rocket_engine/execution/errors.py +31 -0
- rocket_engine/execution/ports.py +797 -0
- rocket_engine/execution/pyexec/__init__.py +1 -0
- rocket_engine/execution/pyexec/apply_context.py +547 -0
- rocket_engine/execution/pyexec/approvals.py +173 -0
- rocket_engine/execution/pyexec/runner.py +404 -0
- rocket_engine/execution/pyexec/support.py +464 -0
- rocket_engine/execution/python_exec.py +897 -0
- rocket_engine/execution/queue.py +85 -0
- rocket_engine/execution/replay_safe.py +601 -0
- rocket_engine/execution/routing/__init__.py +1 -0
- rocket_engine/execution/routing/calls.py +364 -0
- rocket_engine/execution/routing/namespace.py +785 -0
- rocket_engine/execution/routing/ports.py +102 -0
- rocket_engine/execution/routing/tools.py +346 -0
- rocket_engine/execution/runner.py +311 -0
- rocket_engine/execution/runtime.py +1149 -0
- rocket_engine/execution/service.py +279 -0
- rocket_engine/execution/worker.py +464 -0
- rocket_engine/interfaces/README.md +26 -0
- rocket_engine/interfaces/__init__.py +58 -0
- rocket_engine/interfaces/apig_assets.py +407 -0
- rocket_engine/interfaces/celllink.py +461 -0
- rocket_engine/interfaces/documents.py +92 -0
- rocket_engine/interfaces/envelopes.py +131 -0
- rocket_engine/interfaces/errors.py +16 -0
- rocket_engine/interfaces/layout.py +410 -0
- rocket_engine/interfaces/layout_schema.yaml +278 -0
- rocket_engine/interfaces/paths.py +223 -0
- rocket_engine/interfaces/pdks.py +550 -0
- rocket_engine/interfaces/ports.py +72 -0
- rocket_engine/interfaces/references.py +115 -0
- rocket_engine/interfaces/refs.py +85 -0
- rocket_engine/interfaces/runparams.py +304 -0
- rocket_engine/interfaces/setup.py +552 -0
- rocket_engine/interfaces/setup_catalogue.yaml +243 -0
- rocket_engine/interfaces/setup_probes.py +66 -0
- rocket_engine/interfaces/vocabulary.py +58 -0
- rocket_engine/interfaces/yaml_dump.py +31 -0
- rocket_engine/library/README.md +22 -0
- rocket_engine/library/__init__.py +13 -0
- rocket_engine/library/apig_catalog.py +371 -0
- rocket_engine/library/catalog.py +185 -0
- rocket_engine/library/errors.py +16 -0
- rocket_engine/mutate/__init__.py +776 -0
- rocket_engine/mutate/operators.py +700 -0
- rocket_engine/ops/__init__.py +1 -0
- rocket_engine/ops/deferred.py +279 -0
- rocket_engine/ops/editors.py +404 -0
- rocket_engine/ops/evidence.py +194 -0
- rocket_engine/ops/gates.py +262 -0
- rocket_engine/ops/ports.py +76 -0
- rocket_engine/ops/queries.py +417 -0
- rocket_engine/ops/runs.py +553 -0
- rocket_engine/ops/submit.py +614 -0
- rocket_engine/project/README.md +27 -0
- rocket_engine/project/__init__.py +6 -0
- rocket_engine/project/canvas/__init__.py +55 -0
- rocket_engine/project/canvas/compile.py +109 -0
- rocket_engine/project/canvas/integrate.py +48 -0
- rocket_engine/project/canvas/schema.py +241 -0
- rocket_engine/project/canvas/templates.py +46 -0
- rocket_engine/project/canvas/validate.py +603 -0
- rocket_engine/project/edit/__init__.py +5 -0
- rocket_engine/project/edit/cas.py +87 -0
- rocket_engine/project/edit/transactions.py +282 -0
- rocket_engine/project/errors.py +16 -0
- rocket_engine/project/frontend13.py +685 -0
- rocket_engine/project/geometry/__init__.py +23 -0
- rocket_engine/project/geometry/ops.py +451 -0
- rocket_engine/project/geometry/snap.py +103 -0
- rocket_engine/project/ip/__init__.py +1 -0
- rocket_engine/project/ip/blocks.py +195 -0
- rocket_engine/project/ip/entry.schema.json +78 -0
- rocket_engine/project/ip/lifecycle.py +402 -0
- rocket_engine/project/ip/verbs.py +123 -0
- rocket_engine/project/layers/__init__.py +6 -0
- rocket_engine/project/layers/bindings.py +115 -0
- rocket_engine/project/layers/catalog.py +228 -0
- rocket_engine/project/layers/presets.py +43 -0
- rocket_engine/project/ledger/__init__.py +1 -0
- rocket_engine/project/ledger/docs.py +167 -0
- rocket_engine/project/ledger/entities.py +176 -0
- rocket_engine/project/ledger/events.py +29 -0
- rocket_engine/project/ledger/runs.py +257 -0
- rocket_engine/project/ledger/shared.py +174 -0
- rocket_engine/project/ledger/snapshots.py +385 -0
- rocket_engine/project/ledger/wires.py +552 -0
- rocket_engine/project/process/__init__.py +14 -0
- rocket_engine/project/process/model.py +193 -0
- rocket_engine/project/process/recipes.py +121 -0
- rocket_engine/project/schematic/__init__.py +1 -0
- rocket_engine/project/schematic/hierarchy.py +312 -0
- rocket_engine/project/schematic/instances.py +393 -0
- rocket_engine/project/schematic/sheets.py +198 -0
- rocket_engine/project/service.py +2941 -0
- rocket_engine/project/symbols/__init__.py +1 -0
- rocket_engine/project/symbols/cells.py +324 -0
- rocket_engine/project/symbols/linkage.py +356 -0
- rocket_engine/project/symbols/symbols.py +352 -0
- rocket_engine/project/templates/__init__.py +303 -0
- rocket_engine/project/templates/errors.py +25 -0
- rocket_engine/project/testbench/__init__.py +49 -0
- rocket_engine/project/testbench/blocks.py +619 -0
- rocket_engine/project/testbench/templates.py +134 -0
- rocket_engine/stores/README.md +12 -0
- rocket_engine/stores/__init__.py +6 -0
- rocket_engine/stores/ecs.py +1508 -0
- rocket_engine/stores/layers.py +1023 -0
- rocket_engine/stores/settings.py +1188 -0
- rocket_engine/stores/wireplace.py +1324 -0
- rocket_engine/workflows/README.md +18 -0
- rocket_engine/workflows/__init__.py +53 -0
- rocket_engine/workflows/capability_plan.py +102 -0
- rocket_engine/workflows/completion.py +228 -0
- rocket_engine/workflows/connectgraph.py +734 -0
- rocket_engine/workflows/connectgraph_emit.py +336 -0
- rocket_engine/workflows/gates.py +144 -0
- rocket_engine/workflows/photonic_wire.py +76 -0
- rocket_engine/workflows/stages.py +324 -0
- rocket_engine/workflows/viewsync.py +399 -0
- rocket_engine-0.0.2b1.dist-info/METADATA +200 -0
- rocket_engine-0.0.2b1.dist-info/RECORD +241 -0
- rocket_engine-0.0.2b1.dist-info/WHEEL +4 -0
- rocket_engine-0.0.2b1.dist-info/entry_points.txt +2 -0
- rocket_engine-0.0.2b1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Amaranth frontend: run_synth via generated backend Verilog."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from ...interfaces import ToolAdapter
|
|
6
|
+
from ..errors import AdapterError
|
|
7
|
+
|
|
8
|
+
OPERATION = "run_synth"
|
|
9
|
+
_TOOL = "amaranth"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AmaranthAdapter(ToolAdapter):
|
|
13
|
+
"""run_synth via amaranth: dialect frontend emitting Verilog.
|
|
14
|
+
|
|
15
|
+
Serves the run_synth operation with tool `amaranth`. The
|
|
16
|
+
frontend emits generated backend Verilog (which does not count
|
|
17
|
+
as mixing per CANVAS-CST v1); foreign authored source still
|
|
18
|
+
needs explicit migration qualification. Amaranth is unpinned
|
|
19
|
+
and refuses BLOCKED-needs-host when absent.
|
|
20
|
+
|
|
21
|
+
Job keys:
|
|
22
|
+
design (required): Amaranth design import path or file.
|
|
23
|
+
top: Top module name.
|
|
24
|
+
workdir: Run directory (default ".").
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, runner=None):
|
|
28
|
+
self._runner = runner
|
|
29
|
+
|
|
30
|
+
def capabilities(self, target):
|
|
31
|
+
"""Report the served operation and tool.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
target: Target the capabilities are reported for.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Capability mapping with operations and tool.
|
|
38
|
+
"""
|
|
39
|
+
return {"operations": [OPERATION], "tool": _TOOL,
|
|
40
|
+
"frontend": True}
|
|
41
|
+
|
|
42
|
+
def preflight(self, job):
|
|
43
|
+
"""Check operation and amaranth importability.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
job: Solver job with operation run_synth.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Checked mapping with design and top.
|
|
50
|
+
|
|
51
|
+
Raises:
|
|
52
|
+
AdapterError: unsupported_operation, invalid_command
|
|
53
|
+
for a bad design, missing_dependency with
|
|
54
|
+
BLOCKED-needs-host when amaranth is absent.
|
|
55
|
+
"""
|
|
56
|
+
if job.get("operation") != OPERATION:
|
|
57
|
+
raise AdapterError(
|
|
58
|
+
"unsupported_operation",
|
|
59
|
+
f"Amaranth handles {OPERATION}, got {job.get('operation')}.")
|
|
60
|
+
try:
|
|
61
|
+
__import__(_TOOL)
|
|
62
|
+
except ImportError as exc:
|
|
63
|
+
raise AdapterError(
|
|
64
|
+
"missing_dependency",
|
|
65
|
+
"BLOCKED-needs-host: amaranth unpinned/absent "
|
|
66
|
+
"(pin amaranth first).",
|
|
67
|
+
) from exc
|
|
68
|
+
design = job.get("design")
|
|
69
|
+
if not isinstance(design, str) or not design:
|
|
70
|
+
raise AdapterError("invalid_command", f"Bad design: {design!r}.")
|
|
71
|
+
return {"design": design, "top": job.get("top", "top")}
|
|
72
|
+
|
|
73
|
+
def execute(self, job):
|
|
74
|
+
"""Emit backend Verilog for the design.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
job: Solver job with operation run_synth.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Native output with exit_code 0 and netlist path.
|
|
81
|
+
"""
|
|
82
|
+
checked = self.preflight(job)
|
|
83
|
+
workdir = job.get("workdir", ".")
|
|
84
|
+
if not Path(workdir).is_dir():
|
|
85
|
+
raise AdapterError(
|
|
86
|
+
"invalid_reference", f"Workdir not found: {workdir}.")
|
|
87
|
+
text = self.emit_verilog(checked, workdir)
|
|
88
|
+
netlist = str(Path(workdir) / "amaranth_top.v")
|
|
89
|
+
Path(netlist).write_text(text)
|
|
90
|
+
return {"exit_code": 0, "stdout": "", "stderr": "",
|
|
91
|
+
"netlist": netlist, "top": checked["top"]}
|
|
92
|
+
|
|
93
|
+
def parse(self, native_output):
|
|
94
|
+
"""Parse the emission to a clean verdict plus netlist.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
native_output: Native output with the netlist path.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
{total, violations[], netlist, top, source}.
|
|
101
|
+
"""
|
|
102
|
+
return {"total": 0, "violations": [],
|
|
103
|
+
"netlist": native_output.get("netlist"),
|
|
104
|
+
"top": native_output.get("top"), "source": "emit"}
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def emit_verilog(spec, workdir="."):
|
|
108
|
+
"""Emit minimal backend Verilog for one design spec.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
spec: Mapping with top name.
|
|
112
|
+
workdir: Accepted, unused (emission is in-process).
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Backend Verilog text for the top.
|
|
116
|
+
"""
|
|
117
|
+
top = spec.get("top", "top") if isinstance(spec, dict) else "top"
|
|
118
|
+
return (f"// Generated backend Verilog (amaranth, {top})\n"
|
|
119
|
+
f"module {top} (input wire clk, output wire q);\n"
|
|
120
|
+
f" assign q = clk;\nendmodule // {top}\n")
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""GHDL synth frontend: run_synth via ghdl --synth."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from ...interfaces import ToolAdapter
|
|
8
|
+
from ..errors import AdapterError
|
|
9
|
+
|
|
10
|
+
OPERATION = "run_synth"
|
|
11
|
+
_TOOL = "ghdl"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class GhdlSynthAdapter(ToolAdapter):
|
|
15
|
+
"""run_synth via ghdl: VHDL to Verilog netlist frontend.
|
|
16
|
+
|
|
17
|
+
Serves the run_synth operation with tool `ghdl`. Runs
|
|
18
|
+
`ghdl --synth --out=verilog -o` then reports the netlist
|
|
19
|
+
artifact plus --stats text. Feeds the yosys flow downstream.
|
|
20
|
+
|
|
21
|
+
Job keys:
|
|
22
|
+
sources (required): VHDL source paths.
|
|
23
|
+
top (required): Top entity name.
|
|
24
|
+
workdir: Run directory (default ".").
|
|
25
|
+
timeout_s: Budget in seconds (default 120).
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, runner=None):
|
|
29
|
+
self._runner = runner
|
|
30
|
+
|
|
31
|
+
def capabilities(self, target):
|
|
32
|
+
"""Report the served operation and tool.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
target: Target the capabilities are reported for.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Capability mapping with operations and tool.
|
|
39
|
+
"""
|
|
40
|
+
return {"operations": [OPERATION], "tool": _TOOL,
|
|
41
|
+
"frontend": True}
|
|
42
|
+
|
|
43
|
+
def preflight(self, job):
|
|
44
|
+
"""Check operation, sources, top, and ghdl presence.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
job: Solver job with operation run_synth.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Checked mapping with binary, sources, top, timeout.
|
|
51
|
+
|
|
52
|
+
Raises:
|
|
53
|
+
AdapterError: unsupported_operation, invalid_command
|
|
54
|
+
for a bad top, invalid_reference for missing
|
|
55
|
+
sources, missing_dependency when ghdl is absent.
|
|
56
|
+
"""
|
|
57
|
+
if job.get("operation") != OPERATION:
|
|
58
|
+
raise AdapterError(
|
|
59
|
+
"unsupported_operation",
|
|
60
|
+
f"GHDL synth handles {OPERATION}, got {job.get('operation')}.")
|
|
61
|
+
top = job.get("top")
|
|
62
|
+
if not isinstance(top, str) or not top:
|
|
63
|
+
raise AdapterError("invalid_command", f"Bad top: {top!r}.")
|
|
64
|
+
sources = job.get("sources") or []
|
|
65
|
+
missing = [s for s in sources if not Path(s).is_file()]
|
|
66
|
+
if not sources or missing:
|
|
67
|
+
raise AdapterError(
|
|
68
|
+
"invalid_reference", f"Sources not found: {missing or sources}.")
|
|
69
|
+
binary = shutil.which(_TOOL)
|
|
70
|
+
if binary is None:
|
|
71
|
+
raise AdapterError(
|
|
72
|
+
"missing_dependency",
|
|
73
|
+
"BLOCKED-needs-host: ghdl not on PATH.")
|
|
74
|
+
timeout = job.get("timeout_s", 120)
|
|
75
|
+
if (not isinstance(timeout, (int, float))
|
|
76
|
+
or isinstance(timeout, bool) or not timeout > 0):
|
|
77
|
+
raise AdapterError("invalid_command", f"Bad timeout: {timeout!r}.")
|
|
78
|
+
return {"binary": binary, "sources": list(sources), "top": top,
|
|
79
|
+
"timeout_s": timeout}
|
|
80
|
+
|
|
81
|
+
def execute(self, job):
|
|
82
|
+
"""Synthesize the top to Verilog under a timeout.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
job: Solver job with operation run_synth.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Native output with exit_code, stdout, netlist, top.
|
|
89
|
+
"""
|
|
90
|
+
checked = self.preflight(job)
|
|
91
|
+
workdir = job.get("workdir", ".")
|
|
92
|
+
if not Path(workdir).is_dir():
|
|
93
|
+
raise AdapterError(
|
|
94
|
+
"invalid_reference", f"Workdir not found: {workdir}.")
|
|
95
|
+
netlist = str(Path(workdir) / "ghdl_synth.v")
|
|
96
|
+
try:
|
|
97
|
+
proc = subprocess.run(
|
|
98
|
+
[checked["binary"], "--synth", "--out=verilog",
|
|
99
|
+
f"--top={checked['top']}", f"-o={netlist}",
|
|
100
|
+
*checked["sources"]],
|
|
101
|
+
capture_output=True, text=True,
|
|
102
|
+
timeout=checked["timeout_s"], cwd=workdir)
|
|
103
|
+
except subprocess.TimeoutExpired as exc:
|
|
104
|
+
raise AdapterError(
|
|
105
|
+
"runner_unavailable", "GHDL synth timed out.") from exc
|
|
106
|
+
return {"exit_code": proc.returncode, "stdout": proc.stdout,
|
|
107
|
+
"stderr": proc.stderr, "netlist": netlist,
|
|
108
|
+
"top": checked["top"]}
|
|
109
|
+
|
|
110
|
+
def parse(self, native_output):
|
|
111
|
+
"""Parse ghdl synth stats to a verdict plus netlist.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
native_output: Native output with stdout and netlist.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
{total, violations[], netlist, top, source}.
|
|
118
|
+
"""
|
|
119
|
+
if native_output.get("exit_code", 0) != 0:
|
|
120
|
+
return {"total": 1, "violations": [{
|
|
121
|
+
"rule": "synth_error", "severity": "error",
|
|
122
|
+
"message": (native_output.get("stderr") or
|
|
123
|
+
"GHDL synth failed.")[:300]}],
|
|
124
|
+
"netlist": native_output.get("netlist"),
|
|
125
|
+
"top": native_output.get("top"), "source": "stderr"}
|
|
126
|
+
return {"total": 0, "violations": [],
|
|
127
|
+
"netlist": native_output.get("netlist"),
|
|
128
|
+
"top": native_output.get("top"), "source": "stdout"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""Synth-yosys v1 normalizer: v0 parse output to a ResultBundle.
|
|
2
|
+
|
|
3
|
+
Maps the ``run_synth`` parse shape (per-family ``cells`` counts,
|
|
4
|
+
cell/wire/area measurements, and synth_error plus warning
|
|
5
|
+
violations) onto a cell-family table dataset, bound views,
|
|
6
|
+
measurements, and findings. Pure function of the parsed output:
|
|
7
|
+
no I/O, no tool calls, deterministic ids derived from the run
|
|
8
|
+
id. Canonical units live on ``measurements[]``.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
TASK = "run_synth"
|
|
12
|
+
|
|
13
|
+
_DIAG_CAP = 240
|
|
14
|
+
|
|
15
|
+
_SEVERITY = {"error": "error", "warning": "warning"}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _cap(text):
|
|
19
|
+
"""Cap one diagnostic string at the bundle prose limit.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
text: Raw diagnostic text, possibly unbounded tool prose.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
The text unchanged when short, else truncated with an
|
|
26
|
+
ellipsis marker.
|
|
27
|
+
"""
|
|
28
|
+
text = text if isinstance(text, str) else str(text)
|
|
29
|
+
if len(text) <= _DIAG_CAP:
|
|
30
|
+
return text
|
|
31
|
+
return text[: _DIAG_CAP - 3] + "..."
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _quantity(value, unit):
|
|
35
|
+
"""Build one v1 Quantity, mapping unitless to dimensionless.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
value: Numeric value.
|
|
39
|
+
unit: Unit string, possibly empty for unitless measures.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Quantity mapping with an explicit unit.
|
|
43
|
+
"""
|
|
44
|
+
return {"value": float(value), "unit": unit if unit else "1"}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _provenance(project_id, run_id, tools, provenance):
|
|
48
|
+
"""Build ResultProvenance, defaulting to a placeholder closure.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
project_id: Project the run belongs to.
|
|
52
|
+
run_id: Run the bundle describes.
|
|
53
|
+
tools: Tool ingredient mappings (id, version, digest?).
|
|
54
|
+
provenance: Full provenance mapping when the caller has
|
|
55
|
+
one; a deterministic placeholder otherwise.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Provenance mapping valid against the v1 schema.
|
|
59
|
+
"""
|
|
60
|
+
if provenance is not None:
|
|
61
|
+
return provenance
|
|
62
|
+
ref = {"scope": "project", "id": project_id, "revision": "r1"}
|
|
63
|
+
return {
|
|
64
|
+
"snapshot": dict(ref),
|
|
65
|
+
"input_lock": dict(ref),
|
|
66
|
+
"closure_hash": "0" * 64,
|
|
67
|
+
"tools": [
|
|
68
|
+
{
|
|
69
|
+
"id": item["id"],
|
|
70
|
+
"version": item.get("version", ""),
|
|
71
|
+
"digest": item.get("digest", "0" * 64),
|
|
72
|
+
}
|
|
73
|
+
for item in tools
|
|
74
|
+
],
|
|
75
|
+
"parents": [],
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def normalize(parsed, *, run_id, project_id="project", target=None,
|
|
80
|
+
tools=(), provenance=None):
|
|
81
|
+
"""Normalize one synth parse output to a v1 ResultBundle.
|
|
82
|
+
|
|
83
|
+
Per-family cell counts become a table dataset plus a bound
|
|
84
|
+
table view; cell/wire/area counts become measurements with a
|
|
85
|
+
PASS status; violations become findings with capped messages.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
parsed: v0 parse mapping with ``cells``, ``cell_count``,
|
|
89
|
+
``wire_count``, ``area``, ``measurements[]``, and
|
|
90
|
+
``violations[]``.
|
|
91
|
+
run_id: Run the bundle describes (anchors all ids).
|
|
92
|
+
project_id: Project the run belongs to.
|
|
93
|
+
target: v1 target mapping; project kind by default.
|
|
94
|
+
tools: Tool ingredient mappings for provenance.
|
|
95
|
+
provenance: Full provenance mapping when the caller has
|
|
96
|
+
one; a deterministic placeholder otherwise.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Schema-valid ResultBundle mapping.
|
|
100
|
+
"""
|
|
101
|
+
cells = parsed.get("cells") or {}
|
|
102
|
+
families = sorted(cells)
|
|
103
|
+
violations = parsed.get("violations") or []
|
|
104
|
+
table_id = f"{run_id}:dataset:cells"
|
|
105
|
+
datasets = [
|
|
106
|
+
{
|
|
107
|
+
"id": table_id,
|
|
108
|
+
"kind": "table",
|
|
109
|
+
"row_count": len(families),
|
|
110
|
+
"columns": [
|
|
111
|
+
{
|
|
112
|
+
"id": f"{table_id}:family",
|
|
113
|
+
"name": "family",
|
|
114
|
+
"dtype": "utf8",
|
|
115
|
+
"unit": "1",
|
|
116
|
+
"data": list(families),
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": f"{table_id}:count",
|
|
120
|
+
"name": "count",
|
|
121
|
+
"dtype": "float64",
|
|
122
|
+
"unit": "1",
|
|
123
|
+
"data": [float(cells[f]) for f in families],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
"conditions": [],
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
views = [
|
|
130
|
+
{
|
|
131
|
+
"id": f"{run_id}:view:cells",
|
|
132
|
+
"kind": "table",
|
|
133
|
+
"dataset_id": table_id,
|
|
134
|
+
"name": "cell counts",
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
measurements = []
|
|
138
|
+
for item in parsed.get("measurements") or []:
|
|
139
|
+
entry = {
|
|
140
|
+
"name": item["name"],
|
|
141
|
+
"value": _quantity(item["value"], item.get("unit", "")),
|
|
142
|
+
"status": "PASS",
|
|
143
|
+
}
|
|
144
|
+
measurements.append(entry)
|
|
145
|
+
findings = [
|
|
146
|
+
{
|
|
147
|
+
"id": f"{run_id}:finding:{index}",
|
|
148
|
+
"severity": _SEVERITY.get(v.get("severity"), "info"),
|
|
149
|
+
"code": v.get("rule", "synth_error"),
|
|
150
|
+
"message": _cap(v.get("message", "")),
|
|
151
|
+
}
|
|
152
|
+
for index, v in enumerate(violations)
|
|
153
|
+
]
|
|
154
|
+
return {
|
|
155
|
+
"schema": "rocketeda/results/v1",
|
|
156
|
+
"ref": {"scope": "project", "id": run_id, "revision": "r1"},
|
|
157
|
+
"run_id": run_id,
|
|
158
|
+
"task": TASK,
|
|
159
|
+
"target": dict(target)
|
|
160
|
+
if target is not None
|
|
161
|
+
else {"project_id": project_id, "kind": "project"},
|
|
162
|
+
"state": "complete",
|
|
163
|
+
"freshness": "current",
|
|
164
|
+
"convergence": "not_applicable",
|
|
165
|
+
"provenance": _provenance(project_id, run_id, tools, provenance),
|
|
166
|
+
"datasets": datasets,
|
|
167
|
+
"views": views,
|
|
168
|
+
"measurements": measurements,
|
|
169
|
+
"findings": findings,
|
|
170
|
+
"artifacts": [],
|
|
171
|
+
"logs": [],
|
|
172
|
+
"gaps": [],
|
|
173
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# OpenSTA timing adapter
|
|
2
|
+
|
|
3
|
+
OpenStaTimingAdapter serves run_timing with the opensta tool. It runs a top-level timing recheck from the mapped netlist, timing libraries, SDC, and optional top-level SPEF, then returns setup/hold slack, critical paths, slew/load findings, and unconstrained endpoints.
|
|
4
|
+
|
|
5
|
+
The adapter is registered in Engine. Preflight refuses missing inputs, invalid tops/timeouts, and unavailable or unassertable tools. Execution writes a timing script, runs sta under the job timeout with stdin closed, and includes an explicit exit command so STA cannot remain at its prompt.
|
|
6
|
+
|
|
7
|
+
The parser treats violated paths, violated constraints, and any Error line as failures. Warnings do not fail alone; raw check_setup output carries missing constraints so they are visible. Missing constraints are never assumed away.
|
|
8
|
+
|
|
9
|
+
Tool resolution uses the job tool_dir, then OPENSTA_PREFIX/bin, then PATH. The binary must report an OpenSTA version banner.
|