Skip to content

Commit 3cb5f63

Browse files
committed
_toolchain.yosys: add JavaScript (Pyodide) support.
In this environment it's not feasible, or at least it's not documented how, to distribute JavaScript code by packaging it as a wheel; only Wasm code (as shared objects) can be distributed this way. The current `amaranth-yosys` strategy would not work even though wheels can be installed on Pyodide, and Yosys will need to be explicitly provided by the environment instead. The implementation is sufficiently generic that non-Pyodide hosts could potentially make use of it, though it doesn't seem like any exist at the moment.
1 parent 9aebf49 commit 3cb5f63

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

Diff for: amaranth/_toolchain/yosys.py

+43
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,47 @@ def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
177177
return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
178178

179179

180+
class _JavaScriptYosys(YosysBinary):
181+
"""
182+
This toolchain proxy is compatible with Pyodide_. The JavaScript environment must include
183+
the following function:
184+
185+
.. code::
186+
187+
runAmaranthYosys(args: string[], stdin: string): (exit_code: int, stdout: string, stderr: string);
188+
189+
.. _Pyodide: https://pyodide.org/
190+
"""
191+
192+
@classmethod
193+
def available(cls):
194+
try:
195+
return hasattr(__import__("js"), "runAmaranthYosys")
196+
except ImportError:
197+
return False
198+
199+
@classmethod
200+
def version(cls):
201+
version = cls.run(["-V"])
202+
match = re.match(r"^Yosys (\d+)\.(\d+)(?:\+(\d+))?", version)
203+
if match:
204+
return (int(match[1]), int(match[2]), int(match[3] or 0))
205+
else:
206+
return None
207+
208+
@classmethod
209+
def data_dir(cls):
210+
# Not yet clear how this could work in a design with Wasm components. Most likely,
211+
# the component would have to export its filesystem wholesale, and this method would
212+
# return some kind of non-filesystem path-like object.
213+
raise NotImplementedError
214+
215+
@classmethod
216+
def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
217+
exit_code, stdout, stderr = __import__("js").runAmaranthYosys(args, stdin)
218+
return cls._process_result(exit_code, stdout, stderr, ignore_warnings, src_loc_at)
219+
220+
180221
def find_yosys(requirement):
181222
"""Find an available Yosys executable of required version.
182223
@@ -202,6 +243,8 @@ def find_yosys(requirement):
202243
proxies.append(_BuiltinYosys)
203244
elif clause == "system":
204245
proxies.append(_SystemYosys)
246+
elif clause == "javascript":
247+
proxies.append(_JavaScriptYosys)
205248
else:
206249
raise YosysError("The AMARANTH_USE_YOSYS environment variable contains "
207250
"an unrecognized clause {!r}"

0 commit comments

Comments
 (0)