Skip to content

Commit 1cc36c2

Browse files
authored
Merge branch 'amaranth-lang:main' into main
2 parents 51f5769 + 3c870d6 commit 1cc36c2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+21629
-7748
lines changed

.coveragerc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ branch = True
33
include =
44
amaranth/*
55
omit =
6-
amaranth/test/*
6+
tests/*
77

88
[report]
99
exclude_lines =

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
indent_style = space
6+
indent_size = 4
7+
max_line_length = 100
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true

.github/workflows/main.yaml

Lines changed: 132 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ jobs:
2424
include:
2525
- python-version: '3.13-dev'
2626
allow-failure: true
27-
continue-on-error: '${{ matrix.allow-failure }}'
27+
continue-on-error: ${{ matrix.allow-failure }}
2828
name: 'test (${{ matrix.python-version }})'
2929
steps:
3030
- name: Check out source code
31-
uses: actions/checkout@v3
31+
uses: actions/checkout@v4
3232
with:
3333
fetch-depth: 0
3434
- name: Set up PDM
35-
uses: pdm-project/setup-pdm@v3
35+
uses: pdm-project/setup-pdm@v4
3636
with:
3737
python-version: ${{ matrix.python-version }}
3838
- name: Install dependencies
@@ -41,10 +41,10 @@ jobs:
4141
sudo add-apt-repository 'deb http://ppa.launchpad.net/sri-csl/formal-methods/ubuntu bionic main'
4242
sudo apt-get update
4343
sudo apt-get install yices2
44-
pip install codecov
44+
pip install codecov build
4545
pdm install --dev
4646
- name: Cache YoWASP build products
47-
uses: actions/cache@v3
47+
uses: actions/cache@v4
4848
with:
4949
path: ~/.cache/YoWASP
5050
key: YoWASP-${{ runner.os }}-${{ hashFiles('./.venv/**/*.wasm') }}
@@ -54,21 +54,65 @@ jobs:
5454
run: |
5555
pdm run test
5656
- name: Submit code coverage
57-
run:
57+
run: |
5858
codecov
5959
60+
smoketest: # If we plug this into downstream projects, does magic smoke escape?
61+
runs-on: ubuntu-latest
62+
strategy:
63+
fail-fast: false
64+
matrix:
65+
project:
66+
- amaranth-lang/amaranth-boards
67+
- amaranth-lang/amaranth-stdio
68+
- amaranth-lang/amaranth-soc
69+
name: 'smoke (${{ matrix.project }})'
70+
steps:
71+
- name: Check out Amaranth source code
72+
uses: actions/checkout@v4
73+
with:
74+
path: amaranth
75+
fetch-depth: 0
76+
- name: Check out source code
77+
uses: actions/checkout@v4
78+
with:
79+
repository: ${{ matrix.project }}
80+
path: project
81+
fetch-depth: 0
82+
- name: Set up PDM
83+
uses: pdm-project/setup-pdm@v4
84+
- name: Install dependencies
85+
working-directory: project
86+
run: |
87+
pdm install --dev
88+
- name: Use Amaranth HEAD revision
89+
working-directory: project
90+
run: |
91+
pdm add ../amaranth
92+
- name: Cache YoWASP build products
93+
uses: actions/cache@v4
94+
with:
95+
path: ~/.cache/YoWASP
96+
key: YoWASP-${{ runner.os }}-${{ hashFiles('./.venv/**/*.wasm') }}
97+
restore-keys: |
98+
YoWASP-${{ runner.os }}-
99+
- name: Run tests
100+
working-directory: project
101+
run: |
102+
pdm run test
103+
60104
document:
61105
runs-on: ubuntu-latest
62106
steps:
63107
- name: Check out source code
64-
uses: actions/checkout@v3
108+
uses: actions/checkout@v4
65109
with:
66110
fetch-depth: 0
67111
- name: Fetch tags from upstream repository
68112
run: |
69113
git fetch --tags https://github.com/amaranth-lang/amaranth.git
70114
- name: Set up PDM
71-
uses: pdm-project/setup-pdm@v3
115+
uses: pdm-project/setup-pdm@v4
72116
with:
73117
python-version: '3.12'
74118
- name: Install dependencies
@@ -78,36 +122,52 @@ jobs:
78122
run: |
79123
pdm run document
80124
- name: Upload documentation archive
81-
uses: actions/upload-artifact@v3
125+
uses: actions/upload-artifact@v4
82126
with:
83127
name: docs
84128
path: docs/_build
85129

130+
check-links:
131+
runs-on: ubuntu-latest
132+
steps:
133+
- name: Check out source code
134+
uses: actions/checkout@v4
135+
- name: Set up PDM
136+
uses: pdm-project/setup-pdm@v4
137+
with:
138+
python-version: '3.12'
139+
- name: Install dependencies
140+
run: |
141+
pdm install --dev
142+
- name: Check links in documentation
143+
run: |
144+
pdm run document-linkcheck
145+
86146
required: # group all required workflows into one to avoid reconfiguring this in Actions settings
87147
needs:
88148
- test
89149
- document
90-
if: always() && !contains(needs.*.result, 'cancelled')
150+
if: ${{ always() && !contains(needs.*.result, 'cancelled') }}
91151
runs-on: ubuntu-latest
92152
steps:
93153
- run: ${{ contains(needs.*.result, 'failure') && 'false' || 'true' }}
94154

95155
publish-docs:
96156
needs: document
97-
if: github.repository == 'amaranth-lang/amaranth'
157+
if: ${{ github.repository == 'amaranth-lang/amaranth' }}
98158
runs-on: ubuntu-latest
99159
steps:
100160
- name: Check out source code
101-
uses: actions/checkout@v3
161+
uses: actions/checkout@v4
102162
with:
103163
fetch-depth: 0
104164
- name: Download documentation archive
105-
uses: actions/download-artifact@v3
165+
uses: actions/download-artifact@v4
106166
with:
107167
name: docs
108168
path: docs/
109169
- name: Publish development documentation
110-
if: github.event_name == 'push' && github.event.ref == 'refs/heads/main'
170+
if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/main' }}
111171
uses: JamesIves/github-pages-deploy-action@releases/v4
112172
with:
113173
repository-name: amaranth-lang/amaranth-lang.github.io
@@ -116,7 +176,7 @@ jobs:
116176
folder: docs/
117177
target-folder: docs/amaranth/latest/
118178
- name: Publish release documentation
119-
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
179+
if: ${{ github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') }}
120180
uses: JamesIves/github-pages-deploy-action@releases/v4
121181
with:
122182
repository-name: amaranth-lang/amaranth-lang.github.io
@@ -127,15 +187,15 @@ jobs:
127187

128188
publish-docs-dev:
129189
needs: document
130-
if: github.repository != 'amaranth-lang/amaranth'
190+
if: ${{ github.repository != 'amaranth-lang/amaranth' }}
131191
runs-on: ubuntu-latest
132192
steps:
133193
- name: Check out source code
134-
uses: actions/checkout@v3
194+
uses: actions/checkout@v4
135195
with:
136196
fetch-depth: 0
137197
- name: Download documentation archive
138-
uses: actions/download-artifact@v3
198+
uses: actions/download-artifact@v4
139199
with:
140200
name: docs
141201
path: pages/docs/${{ github.ref_name }}/
@@ -147,3 +207,57 @@ jobs:
147207
with:
148208
folder: pages/
149209
clean: false
210+
211+
publish-package:
212+
needs: required
213+
runs-on: ubuntu-latest
214+
environment: publish
215+
permissions:
216+
id-token: write
217+
steps:
218+
- name: Check out source code
219+
uses: actions/checkout@v4
220+
with:
221+
fetch-depth: 0
222+
- name: Build package
223+
run: |
224+
pip install build
225+
python -m build
226+
- name: Upload package artifact
227+
uses: actions/upload-artifact@v4
228+
with:
229+
name: package
230+
path: dist/
231+
- name: Verify package metadata
232+
run: |
233+
pip install twine
234+
twine check dist/*
235+
- name: Publish package to Test PyPI
236+
if: ${{ github.repository == 'amaranth-lang/amaranth' && github.event_name == 'push' && github.event.ref == 'refs/heads/main' }}
237+
uses: pypa/gh-action-pypi-publish@release/v1
238+
with:
239+
repository-url: https://test.pypi.org/legacy/
240+
- name: Publish package to PyPI
241+
if: ${{ github.repository == 'amaranth-lang/amaranth' && github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/') }}
242+
uses: pypa/gh-action-pypi-publish@release/v1
243+
244+
publish-release:
245+
needs: publish-package
246+
if: ${{ github.repository == 'amaranth-lang/amaranth' && github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/') }}
247+
runs-on: ubuntu-latest
248+
permissions:
249+
contents: write
250+
steps:
251+
- name: Determine release metadata
252+
id: metadata
253+
env:
254+
REF_NAME: ${{ github.ref_name }}
255+
run: |
256+
echo name=${REF_NAME/v/} >>$GITHUB_OUTPUT
257+
- name: Create release
258+
uses: comnoco/create-release-action@v2
259+
env:
260+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
261+
with:
262+
tag_name: ${{ github.ref_name }}
263+
release_name: ${{ steps.metadata.outputs.name }}

CONTRIBUTING.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ We love contributions from the community. Please send pull requests and raise
44
issues! All code submissions require review. We use GitHub pull requests for
55
this purpose.
66

7+
See the "Contributing" section of the documentation manual for more details
8+
about contributing to Amaranth.
9+
710

811
COPYRIGHTS and LICENSE
912

README.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,27 @@ See the [Introduction](https://amaranth-lang.org/docs/amaranth/latest/intro.html
2222

2323
See the [Installation](https://amaranth-lang.org/docs/amaranth/latest/install.html) section of the documentation.
2424

25-
## Supported devices
25+
## Usage
26+
27+
See the [Language guide](https://amaranth-lang.org/docs/amaranth/latest/guide.html) section of the documentation.
28+
29+
## Platform support
2630

2731
Amaranth can be used to target any FPGA or ASIC process that accepts behavioral Verilog-2001 as input. It also offers extended support for many FPGA families, providing toolchain integration, abstractions for device-specific primitives, and more. Specifically:
2832

2933
* Lattice iCE40 (toolchains: **Yosys+nextpnr**, LSE-iCECube2, Synplify-iCECube2);
3034
* Lattice MachXO2 (toolchains: Diamond);
3135
* Lattice MachXO3L (toolchains: Diamond);
3236
* Lattice ECP5 (toolchains: **Yosys+nextpnr**, Diamond);
33-
* Xilinx Spartan 3A (toolchains: ISE);
34-
* Xilinx Spartan 6 (toolchains: ISE);
35-
* Xilinx 7-series (toolchains: Vivado);
36-
* Xilinx UltraScale (toolchains: Vivado);
37-
* Intel (toolchains: Quartus);
37+
* Lattice Nexus (toolchains: **Yosys+nextpnr**, Diamond);
38+
* AMD Virtex, Virtex E, Spartan 2, Spartan 2E (toolchains: ISE);
39+
* AMD Virtex II, Virtex II Pro (toolchains: ISE);
40+
* AMD Spartan 3, Spartan 3E, Spartan 3A, Spartan 3AN, Spartan 3A DSP (toolchains: ISE);
41+
* AMD Virtex 4, Virtex 5, Virtex 6 (toolchains: ISE);
42+
* AMD Spartan 6 (toolchains: ISE);
43+
* AMD 7-series (toolchains: Vivado, ISE);
44+
* AMD UltraScale, UltraScale+ (toolchains: Vivado);
45+
* Altera (toolchains: Quartus);
3846
* Quicklogic EOS S3 (toolchains: **Yosys+VPR**).
3947

4048
FOSS toolchains are listed in **bold**.
@@ -47,4 +55,4 @@ Amaranth has a dedicated IRC channel, [#amaranth-lang at libera.chat](https://we
4755

4856
## License
4957

50-
Amaranth is released under the very permissive [two-clause BSD license](LICENSE.txt). Under the terms of this license, you are authorized to use Amaranth for closed-source proprietary designs.
58+
Amaranth is released under the [two-clause BSD license](LICENSE.txt). You are permitted to use Amaranth for open-source and proprietary designs provided that the copyright notice in the license file is reproduced.

amaranth/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212

1313
from .hdl import *
1414

15-
15+
# must be kept in sync with docs/reference.rst!
1616
__all__ = [
1717
"Shape", "unsigned", "signed",
18-
"Value", "Const", "C", "Mux", "Cat", "Repl", "Array", "Signal", "ClockSignal", "ResetSignal",
18+
"Value", "Const", "C", "Mux", "Cat", "Array", "Signal", "ClockSignal", "ResetSignal",
19+
"Format", "Print", "Assert",
1920
"Module",
2021
"ClockDomain",
2122
"Elaboratable", "Fragment", "Instance",

amaranth/_toolchain/yosys.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ def available(cls):
120120
@classmethod
121121
def version(cls):
122122
version = importlib_metadata.version(cls.YOSYS_PACKAGE)
123-
match = re.match(r"^(\d+)\.(\d+)(?:\.post(\d+))?", version)
124-
return (int(match[1]), int(match[2]), int(match[3] or 0))
123+
match = re.match(r"^(\d+)\.(\d+)\.(?:\d+)(?:\.(\d+))?(?:\.post(\d+))?", version)
124+
return (int(match[1]), int(match[2]), int(match[3] or 0), int(match[4] or 0))
125125

126126
@classmethod
127127
def data_dir(cls):
@@ -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)