This commit is contained in:
Peder Bergebakken Sundt 2020-08-15 02:59:40 +02:00
parent 18bf707fdc
commit 5702101d03
14 changed files with 599 additions and 65 deletions

22
.gitignore vendored
View File

@ -1,6 +1,22 @@
.venv/
poetry.toml
# remote-exec:
.remote.toml
.poetry_pypath
# poetry:
*.egg-info
*.pyc
poetry.toml
.venv/
# python:
__pycache__
*.pyc
# migen:
build/

34
.remoteenv Normal file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
POETRY='exit 99'
if type -P poetry >/dev/null; then
POETRY='poetry'
else
if ! type -P pip3 >/dev/null; then
echo "Neither pip3 nor poetry is available on this host: $(hostname)"
exit 1
fi
if ! test -d '.poetry_pypath/poetry'; then
# NOTE: .poetry_pypath should be ignored during remote-exec [pull]
echo "Poetry not found, downloading it to .poetry_pypath/ ..."
pip3 install -t '.poetry_pypath' poetry || exit $?
fi
export PYTHONPATH=".poetry_pypath:$PYTHONPATH"
POETRY='python3 -m poetry'
fi
if ! test -f "poetry.toml" ; then
$POETRY config --local virtualenvs.in-project true
fi
if ! test -d ".venv" ; then
$POETRY install || exit $?
fi
alias poetry="$POETRY"
exec $POETRY shell

View File

@ -33,6 +33,20 @@ To reduce the amount of typing:
poetry shell
# Running stuff remotely
For this you need a host you're able to ssh to.
Setup:
poetry install
poetry run remote-init <user@host>
poetry run remote-ignore '*.egg-info' '.git' '.remote.toml' '.venv' # TODO: get rid of this
poetry run remote poetry config --local virtualenvs.in-project true
poetry run remote poetry install
poetry run remote poetry install -E yosys -E nextpnr-ice40
poetry run remote python -m fpga.foobar generate -t il
# todo:

View File

@ -3,6 +3,7 @@ import "/nmigen_dg/*"
import "/sys"
import "common/to_signed"
import "modules/vga/DviController12"
import "modules/bad_apple/BadAppleDecoder"
import "stdio/ice40pll/add_domain_from_pll"
import "resources/pmod"
@ -22,8 +23,35 @@ Top = subclass Elaboratable where
print pll_config
# Feed a picture to the DVI controller
'''
# Feed bad_apple to the DVI controller
apple = Submodule.apple$ BadAppleDecoder!
buffer = Memory
width: 1
depth: apple.size
rdbuffer = Submodule.rdbuffer$ buffer.read_port!
wrbuffer = Submodule.wrbuffer$ buffer.write_port!
Sync$ wrbuffer.en ::= apple.pixel_valid
Sync$ wrbuffer.addr ::= apple.pixel_x + apple.pixel_y*apple.h
Sync$ wrbuffer.data ::= apple.pixel_data
wait = Signal 30 reset:1
Comb$ apple.next ::= 0
When dvi.vblank_start $ ->
Sync$ wait ::= wait.rotate_left 1
Comb$ apple.next ::= wait!!0
Comb$ rdbuffer.addr ::= (dvi.pixel_x >> 3) + (dvi.pixel_y >> 3)*apple.h
pixel = Cat rdbuffer.data rdbuffer.data rdbuffer.data rdbuffer.data
Sync$ dvi.r ::= pixel
Sync$ dvi.g ::= pixel
Sync$ dvi.b ::= pixel
'''
# Feed a picture to the DVI controller
scroll = Signal 8
period = int$ pll_config.achieved / @fps
@ -32,6 +60,12 @@ Top = subclass Elaboratable where
When (counter==0) $ ->
Sync$ counter ::= int period
Sync$ scroll ::= scroll + 1
asd = Cat
platform.request "led_g" 1
platform.request "led_g" 2
platform.request "led_g" 3
platform.request "led_g" 4
Sync$ asd ::= asd + 1
Sync$ dvi.r ::= 0x0
Sync$ dvi.g ::= 0x0
@ -56,10 +90,13 @@ Top = subclass Elaboratable where
tx2 ^ ty2 ,->
Sync$ dvi.r ::= 0xF
Sync$ dvi.g ::= 0xF
'''
'''
if __name__ == "__main__" =>
plat = ICEBreakerPlatform!
plat.add_resources$ pmod.dvi_12bit 0
plat.add_resources$ plat.break_off_pmod
plat.build (Top 800 480) do_program: ("--flash" in sys.argv) synth_opts: "-dsp"
#(import "/nmigen/cli/main" pure) (Top 800 480) plat
plat.build (Top 800 480 fps:60) do_program: ("--flash" in sys.argv) synth_opts: "-dsp -abc2 -relut"

173
fpga/idea_nmain.md Normal file
View File

@ -0,0 +1,173 @@
# The current `nmigen.cli.main()` can:
- Can display a help text when asked (not done by default)
- Has the ability to elaborate a design
- Has the ability to simulate the design for x cycles with no input
I've worked out a few use-cases i've seen others have, and ones i've run into myself:
# What could we want form a new `main()`?
- It should display the help text by default (better discoverability)
- It should have the ability to elaborate the design
- Perhaps provide the ability to set design parameters from the CLI
- Ability to choose among multiple target platforms provided to `main()`
- Perhaps even provide a mocked/generic platform instead of `None`, with arbitrary clocks and resources available
- It should have the ability to synth+PnR a design and program it
- No more using `platform.build(top, do_program=True)` **instead** of `main()`
- It should provide the option to program in the CLI interface, instead of hardcoding it
- "program" may also differ between platform. Options to just program in RAM or to write to the SPI flash could also be needed
- Have the option to print the list of files generated
- It should provide the option to print the synthesis and PnR output, or silence it
- Have the ability to avoid rebuilding the bitfile, and instead just flash the current one on disk
- Have the ability to override the default "build/" folder from the CLI
- Have the ability to set overrides (the `kwargs` in `platform.build`)
- at least print a list of the supported override environ variables
- Have the ability to run a simulation of the design
- Perhaps with the ability to chose among multiple simulation processes/functions provided to `main()`?
- Give the user the ability to provide binary blobs to be flashed to the SPI flash (see #)
- It could be extendable with plugins
- A plugin system could extend *all* nmigen design, instead of requiring the author to add the plugin
- Have the ability to run a simulation of the design
- Perhaps with the ability to chose among multiple simulation processes/functions provided to `main()`?
## Should a new `main` function be accessible from python?
If you publish your design as a python module, it should
be possible to just `import` it and convert it to verilog/ilang.
This culd be useful when using systems like `litex`.
Therefore i suggest the a new `main` have a pattern like this:
```python
main = nmigen.main(MyDesign(), ...)
if __name__ == "__main__":
main.run_cli()
```
, making a `main` object accessible from within python.
## Should a new `main` function provide an interface to run tests?
Testing is currently done through `unittest` or `pytest`. There is however the issue
of not immediately knowing which test_*.py file covers the module you're currently looking at.
## How does the current "simulate" action differ from tests?
`Assert()` is currently being added to the simulator (see #427), blurring the line
between a pure simulation and a unit test. Should the "simulate" action be renamed? Merged? Leave it as is?
## Should we change and break the old `main()`, or make a new one
Even though the backend API is not declared fully stable yet, breaking old code
sucks. The current `main` could therefore be deprecated and a new one then be added in
a different location or under a different name. (`nmain` is cute)
# While on the topic of platform overrides:
The ability to set platform overrides during elaboration could be usefull:
PLL module for example would then be able to add the proper timing constraints.
(Vivado is able to infer these constraints, but nextpnr do not to my knowledge)
# How could such a new `main` look like?
<details>
<summary>this mess</summary>
```python
class MyModule(Elaboratable):
def __init__(self, param: int):
self.param = param
self.out = Signal()
...
# the largest issue is the lack of a consistent CLI interface
# to expect from a given nmigen .py file
if __name__ == "__main__":
top = MyModule(param=4) # `param` is hardcoded. This may also result in a UnusedElaboratable warning
if sys.argv[1] = "build":
if sys.argv[2] = "icebreaker":
plat = ICEBreakerPlatform()
plat.add_resources(...)
elif sys.argv[2] = "fomu"
plat = FomuHackerPlatform()
plat.add_resources(...)
else:
exit(1)
# `do_program` is usually hard-coded.
# The folder "build" should also be configurable from CLI
plat.build(top, do_program=True)
elif sys.argv[1] == "test": # "simulate" is already taken by main()
# logic for multiple simulations to select from is manually made
sim = Simulator(top)
def my_proc():
yield ...
sim.add_sync_process(my_proc)
with sim.write_vcd("uart.vcd", "uart.gtkw"): # hardcoded filenames, never printed to user
sim.run()
else:
main(top, ports=[ top.out ]) # '-h' doesn't mention the two modes defined above
```
</details>
<details>
<summary>could become </summary>
```python
class MyModule(Elaboratable):
def __init__(self, param):
self.param = param
self.out = Signal()
...
if __name__ == "__main__":
platforms, simulations = [], [] # using lists makes the nMain interface more transparent
# supporting multiple platforms encourages designing the
# top-level module in a platform-agnostic fashion
@platforms.append
def icebreaker(): # nMain infers the name from function.__name__
plat = ICEBreakerPlatform()
plat.add_resources(...)
return plat
@platforms.append
def fomu():
plat = FomuHackerPlatform()
plat.add_resources(...)
return plat
@simulations.append
def sim_the_foo(sim): # sim = Simulator(design)
sim.add_clock(1e-6)
@sim.add_sync_process
def my_proc():
yield ...
# `sim` could then be automatically run by nMain, with configurable wavefile output
nMain(
name = "blinker", # Current default is "top", perhaps default to design.__name__ instead?
design = MyModule, # Pass a class itself instead of an instance, avoids UnusedElaboratable warnings
design_kwargs = {"param": 4} # Optional, should be possible to override in CLI
ports = lambda x: [ x.out ], # Optional due to platform.request() being a thing.
# Perhaps all Signals defined in __init__ could be inferred as ports
# by inspecting it with dir() and getattr() before calling .elaborate()?
platforms = platforms, # Optional
simulations = simulations, # Optional
)
```
</details>

123
fpga/modules/bad_apple.dg Normal file
View File

@ -0,0 +1,123 @@
#!/usr/bin/env -S python3 -m dg
import "/nmigen/cli/main"
import "/nmigen/sim/pysim/Simulator"
import "/nmigen_dg/*"
import "/os/path" qualified
import "../common/deduce_ports"
RleXorPrevDecoder = subclass Elaboratable where
__init__ = w h data ~> None where
@w, @h, @data, @size = w, h, data, w*h
@pixel_x = Signal$ range w # pixel being output
@pixel_y = Signal$ range h # pixel being output
@pixel_data = Signal! # data of pixel being output
@pixel_valid = Signal! # wether pixel being output is valid
@next = Signal! # pulse this to start decoding next frame
elaborate = platform ~> m where with m = Module! =>
# Default output
Sync$ @pixel_valid ::= 0
# Data to decode
data_mem = Memory # TODO: use spi flash instead
width: 8
depth: (len @data)
init: (list$ bytearray$ @data)
rddata = Submodule.rddata$ data_mem.read_port!
# RLE decoder state:
pixel = Signal 1
pixel_prev = Signal 1
n_times = Signal 14
# XOR Frame buffer
frame = Memory
width: 1
depth: @size
rdframe = Submodule.rdframe$ frame.read_port!
wrframe = Submodule.wrframe$ frame.write_port!
offset = Signal$ range @size
Comb$ rdframe.addr ::= offset
Comb$ wrframe.addr ::= offset
Sync$ wrframe.en ::= 0
do_write_pixel = Signal!
pixel_to_write = Signal!
Comb$ do_write_pixel ::= 0 # TODO: needed?
When do_write_pixel $ ->
Sync$ @pixel_data ::= (rdframe.data ^ pixel_to_write)
Sync$ wrframe.data ::= (rdframe.data ^ pixel_to_write)
Sync$ @pixel_valid ::= 1
Sync$ wrframe.en ::= 1
Sync$ offset ::= offset + 1 # needs to start at -1
Sync$ @pixel_y ::= @pixel_y + 1
When (@pixel_y == @h - 1) $ ->
Sync$ @pixel_y ::= 0
Sync$ @pixel_x ::= @pixel_x + 1
# RLE & XOR Decoder
FSM
DECODED ->
When @next $ ->
Sync$ offset ::= -1 # max int
Sync$ @pixel_y ::= -1 # max int
Sync$ @pixel_x ::= 0
DECODED |>. READ
READ ->
Sync$ pixel ::= rddata.data !! 7
Sync$ n_times ::= rddata.data !! slice 0 6 # TODO: proper slicing syntax would be nice
Sync$ rddata.addr ::= rddata.addr + 1
When
rddata.data !! 6 ,-> READ |>. READ_MORE
otherwise ,-> READ |>. WRITE_PIXELS_BEGIN
READ_MORE ->
Sync$ n_times ::= ((n_times << 8) | rddata.data)
Sync$ rddata.addr ::= rddata.addr + 1
READ_MORE |>. WRITE_PIXELS_BEGIN
WRITE_PIXELS_BEGIN ->
is_first = offset == 0
has_changed = pixel != pixel_prev
When (~has_changed & ~is_first) $ -> # there was an omitted n_values=1 in between
Comb$ pixel_to_write ::= ~pixel
Comb$ do_write_pixel ::= 1
Sync$ pixel_prev ::= pixel
WRITE_PIXELS_BEGIN |>. WRITE_PIXELS
WRITE_PIXELS ->
Comb$ pixel_to_write ::= pixel
Comb$ do_write_pixel ::= 1
Sync$ n_times ::= n_times - 1
When (n_times == 1) $ -> When # == 0 next cycle
offset == @size - 1 ,-> WRITE_PIXELS |>. DECODED
otherwise ,-> WRITE_PIXELS |>. READ
BadAppleDecoder = -> RleXorPrevDecoder 85 64 bad_apple_data where
fname = os.path.join
os.path.dirname __file__
"data"
"bad_apple.bin"
with f = open fname "rb" =>
bad_apple_data = f.read!
bad_apple_data = bad_apple_data !! slice 0 ((len bad_apple_data) // 58) # TODO: use full movie when we've moved data to spi flash
print ((len bad_apple_data) // 58)
#bad_apple_data = b"0000"
if __name__ == "__main__" =>
design = RleXorPrevDecoder 85 64 b"1234"
ports = deduce_ports design
main design
name: "bad_apple"
ports: ports

Binary file not shown.

24
fpga/spiflash_ideas.md Normal file
View File

@ -0,0 +1,24 @@
# Ability to provide binary blobs to also be flashed to the FPGA's SPI flash
Whenever a SPI flash module is added to `nmigen-stdio` or wherever,
there should be an option to define binary blobs to be programed/flashed
along with the synthesized bitfile.
These binary blobs could either be added in `if __main__ == ...`, or possibly even during elaboration. Example:
```python
with open("myfile.bin", "rv") as f:
platform.add_spi_flash_data(start_addr=0x020000, label="riscv_program", data=f.read())
# 'data' could be optional for RTL generation, but required for building/programming
# perhaps an 'end_addr' or 'size' kwarg could be needed?
...
def elaborate(self, platform):
start_addr, size = platform.get_spi_flash_data(label="riscv_rom") # throws if the label is not defined
```
# Request for Comment:
Different FPGAs are programmed differently. The Ice40 usually write to the SPI flash when programmed,
but the arty 7 is only programed in RAM, without neccesarily writing to the SPI flash.

0
fpga/stdio/i2c.py Normal file
View File

0
fpga/stdio/i2s.py Normal file
View File

1
fpga/stdio/rom.py Normal file
View File

@ -0,0 +1 @@
# spi flash

0
fpga/stdio/spi.py Normal file
View File

218
poetry.lock generated
View File

@ -13,13 +13,21 @@ description = "Classes Without Boilerplate"
name = "attrs"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "19.3.0"
version = "20.2.0"
[package.extras]
azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"]
docs = ["sphinx", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"]
docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"]
[[package]]
category = "dev"
description = "Composable command line interface toolkit"
name = "click"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "7.1.2"
[[package]]
category = "dev"
@ -103,7 +111,7 @@ description = "More routines for operating on iterables, beyond itertools"
name = "more-itertools"
optional = false
python-versions = ">=3.5"
version = "8.4.0"
version = "8.5.0"
[[package]]
category = "main"
@ -111,7 +119,7 @@ description = "Python toolbox for building complex digital hardware"
name = "nmigen"
optional = false
python-versions = "~=3.6"
version = "0.3.dev156+ge46118d"
version = "0.3.dev183+g69ed491"
[package.dependencies]
Jinja2 = ">=2.11,<3.0"
@ -126,10 +134,11 @@ python = "<3.9"
version = "*"
[package.extras]
builtin-yosys = ["nmigen-yosys (>=0.9)"]
builtin-yosys = ["nmigen-yosys (>=0.9.post3527)"]
remote-build = ["paramiko (>=2.7,<3.0)"]
[package.source]
reference = "e46118dac0df315694b0fc6b9367d285a8fc12dd"
reference = "69ed4918b8b9fc8617064bbfacb92feb720006f2"
type = "git"
url = "https://github.com/nmigen/nmigen"
[[package]]
@ -157,7 +166,7 @@ dg = "rev poetry"
nmigen = "branch master"
[package.source]
reference = "eb673dd91d3b43b81e34e70a004d1d24fa98d6d0"
reference = "52feb02abf437173b5d5098bd60e3db5e07b248e"
type = "git"
url = "https://github.com/pbsds/nmigen_dg"
[[package]]
@ -166,7 +175,7 @@ description = "Specialized WebAssembly build of Yosys used by nMigen"
name = "nmigen-yosys"
optional = true
python-versions = "~=3.5"
version = "0.9.post4757.dev23"
version = "0.9.post3527.dev26"
[package.dependencies]
wasmtime = ">=0.19.0,<0.20.0"
@ -183,6 +192,14 @@ version = "20.4"
pyparsing = ">=2.0.2"
six = "*"
[[package]]
category = "dev"
description = "File system general utilities"
name = "pathtools"
optional = false
python-versions = "*"
version = "0.1.2"
[[package]]
category = "dev"
description = "plugin and hook calling mechanisms for python"
@ -207,6 +224,19 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.9.0"
[[package]]
category = "dev"
description = "Data validation and settings management using python 3.6 type hinting"
name = "pydantic"
optional = false
python-versions = ">=3.6"
version = "1.6.1"
[package.extras]
dotenv = ["python-dotenv (>=0.10.4)"]
email = ["email-validator (>=1.0.3)"]
typing_extensions = ["typing-extensions (>=3.7.2)"]
[[package]]
category = "dev"
description = "Python parsing module"
@ -249,6 +279,20 @@ optional = false
python-versions = ">= 3.6"
version = "0.2.3"
[[package]]
category = "dev"
description = "A CLI to sync codebases and execute commands remotely"
name = "remote-exec"
optional = false
python-versions = ">=3.6"
version = "1.7.0"
[package.dependencies]
click = ">=7.1.1"
pydantic = ">=1.5.1"
toml = ">=0.10.0"
watchdog = ">=0.10.3"
[[package]]
category = "dev"
description = "Python 2 and 3 compatibility utilities"
@ -257,6 +301,14 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
version = "1.15.0"
[[package]]
category = "dev"
description = "Python Library for Tom's Obvious, Minimal Language"
name = "toml"
optional = false
python-versions = "*"
version = "0.10.1"
[[package]]
category = "main"
description = "A WebAssembly runtime powered by Wasmtime"
@ -268,6 +320,20 @@ version = "0.19.0"
[package.extras]
testing = ["coverage", "pytest", "pycparser", "pytest-flake8", "pytest-mypy"]
[[package]]
category = "dev"
description = "Filesystem events monitoring"
name = "watchdog"
optional = false
python-versions = "*"
version = "0.10.3"
[package.dependencies]
pathtools = ">=0.1.1"
[package.extras]
watchmedo = ["PyYAML (>=3.10)", "argh (>=0.24.1)"]
[[package]]
category = "dev"
description = "Measures the displayed width of unicode strings in a terminal"
@ -282,7 +348,7 @@ description = "nextpnr-ecp5 FPGA place and route tool"
name = "yowasp-nextpnr-ecp5"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
wasmtime = ">=0.19.0,<0.20.0"
@ -297,10 +363,10 @@ description = "nextpnr-ecp5 FPGA place and route tool"
name = "yowasp-nextpnr-ecp5-25k"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ecp5 = "0.0.post2658.dev17"
yowasp-nextpnr-ecp5 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -308,10 +374,10 @@ description = "nextpnr-ecp5 FPGA place and route tool"
name = "yowasp-nextpnr-ecp5-45k"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ecp5 = "0.0.post2658.dev17"
yowasp-nextpnr-ecp5 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -319,10 +385,10 @@ description = "nextpnr-ecp5 FPGA place and route tool"
name = "yowasp-nextpnr-ecp5-85k"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ecp5 = "0.0.post2658.dev17"
yowasp-nextpnr-ecp5 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -330,12 +396,12 @@ description = "nextpnr-ecp5 FPGA place and route tool"
name = "yowasp-nextpnr-ecp5-all"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ecp5-25k = "0.0.post2658.dev17"
yowasp-nextpnr-ecp5-45k = "0.0.post2658.dev17"
yowasp-nextpnr-ecp5-85k = "0.0.post2658.dev17"
yowasp-nextpnr-ecp5-25k = "0.0.post2683.dev25"
yowasp-nextpnr-ecp5-45k = "0.0.post2683.dev25"
yowasp-nextpnr-ecp5-85k = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -343,7 +409,7 @@ description = "nextpnr-ice40 FPGA place and route tool"
name = "yowasp-nextpnr-ice40"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
wasmtime = ">=0.19.0,<0.20.0"
@ -358,10 +424,10 @@ description = "nextpnr-ice40 FPGA place and route tool"
name = "yowasp-nextpnr-ice40-1k"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ice40 = "0.0.post2658.dev17"
yowasp-nextpnr-ice40 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -369,10 +435,10 @@ description = "nextpnr-ice40 FPGA place and route tool"
name = "yowasp-nextpnr-ice40-384"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ice40 = "0.0.post2658.dev17"
yowasp-nextpnr-ice40 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -380,10 +446,10 @@ description = "nextpnr-ice40 FPGA place and route tool"
name = "yowasp-nextpnr-ice40-5k"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ice40 = "0.0.post2658.dev17"
yowasp-nextpnr-ice40 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -391,10 +457,10 @@ description = "nextpnr-ice40 FPGA place and route tool"
name = "yowasp-nextpnr-ice40-8k"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ice40 = "0.0.post2658.dev17"
yowasp-nextpnr-ice40 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -402,14 +468,14 @@ description = "nextpnr-ice40 FPGA place and route tool"
name = "yowasp-nextpnr-ice40-all"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ice40-1k = "0.0.post2658.dev17"
yowasp-nextpnr-ice40-384 = "0.0.post2658.dev17"
yowasp-nextpnr-ice40-5k = "0.0.post2658.dev17"
yowasp-nextpnr-ice40-8k = "0.0.post2658.dev17"
yowasp-nextpnr-ice40-u4k = "0.0.post2658.dev17"
yowasp-nextpnr-ice40-1k = "0.0.post2683.dev25"
yowasp-nextpnr-ice40-384 = "0.0.post2683.dev25"
yowasp-nextpnr-ice40-5k = "0.0.post2683.dev25"
yowasp-nextpnr-ice40-8k = "0.0.post2683.dev25"
yowasp-nextpnr-ice40-u4k = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -417,10 +483,10 @@ description = "nextpnr-ice40 FPGA place and route tool"
name = "yowasp-nextpnr-ice40-u4k"
optional = true
python-versions = "~=3.5"
version = "0.0.post2658.dev17"
version = "0.0.post2683.dev25"
[package.dependencies]
yowasp-nextpnr-ice40 = "0.0.post2658.dev17"
yowasp-nextpnr-ice40 = "0.0.post2683.dev25"
[[package]]
category = "main"
@ -441,7 +507,8 @@ nextpnr-ice40 = ["yowasp-nextpnr-ice40-all"]
yosys = ["nmigen-yosys"]
[metadata]
content-hash = "06f48c2528cfb9782e6c9a98bd528b43957258cedc12b41c7b16bfb437dbfc97"
content-hash = "09f1dfd3b664ddf78a84aacc8e0a50add8c4230ee094dbe443eb4077acf43636"
lock-version = "1.0"
python-versions = "~3.7"
[metadata.files]
@ -450,8 +517,12 @@ atomicwrites = [
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
]
attrs = [
{file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
{file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
{file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"},
{file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"},
]
click = [
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
]
colorama = [
{file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
@ -506,8 +577,8 @@ markupsafe = [
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
]
more-itertools = [
{file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"},
{file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"},
{file = "more-itertools-8.5.0.tar.gz", hash = "sha256:6f83822ae94818eae2612063a5101a7311e68ae8002005b5e05f03fd74a86a20"},
{file = "more_itertools-8.5.0-py3-none-any.whl", hash = "sha256:9b30f12df9393f0d28af9210ff8efe48d10c94f73e5daf886f10c4b0b0b4f03c"},
]
nmigen = []
nmigen-boards = [
@ -515,12 +586,15 @@ nmigen-boards = [
]
nmigen-dg = []
nmigen-yosys = [
{file = "nmigen_yosys-0.9.post4757.dev23-py3-none-any.whl", hash = "sha256:f58f8727f98b2ea37f450768aa8de3bf5ace6b1b4fa77a373352ab62ab4b40c5"},
{file = "nmigen_yosys-0.9.post3527.dev26-py3-none-any.whl", hash = "sha256:51e9c08c3a25056bf2d404717b36edb34a9aee30e3838468e517a3b38faacb12"},
]
packaging = [
{file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
{file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
]
pathtools = [
{file = "pathtools-0.1.2.tar.gz", hash = "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0"},
]
pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
@ -529,6 +603,25 @@ py = [
{file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"},
{file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"},
]
pydantic = [
{file = "pydantic-1.6.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:418b84654b60e44c0cdd5384294b0e4bc1ebf42d6e873819424f3b78b8690614"},
{file = "pydantic-1.6.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4900b8820b687c9a3ed753684337979574df20e6ebe4227381d04b3c3c628f99"},
{file = "pydantic-1.6.1-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:b49c86aecde15cde33835d5d6360e55f5e0067bb7143a8303bf03b872935c75b"},
{file = "pydantic-1.6.1-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:2de562a456c4ecdc80cf1a8c3e70c666625f7d02d89a6174ecf63754c734592e"},
{file = "pydantic-1.6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f769141ab0abfadf3305d4fcf36660e5cf568a666dd3efab7c3d4782f70946b1"},
{file = "pydantic-1.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2dc946b07cf24bee4737ced0ae77e2ea6bc97489ba5a035b603bd1b40ad81f7e"},
{file = "pydantic-1.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:36dbf6f1be212ab37b5fda07667461a9219c956181aa5570a00edfb0acdfe4a1"},
{file = "pydantic-1.6.1-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:1783c1d927f9e1366e0e0609ae324039b2479a1a282a98ed6a6836c9ed02002c"},
{file = "pydantic-1.6.1-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:cf3933c98cb5e808b62fae509f74f209730b180b1e3c3954ee3f7949e083a7df"},
{file = "pydantic-1.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f8af9b840a9074e08c0e6dc93101de84ba95df89b267bf7151d74c553d66833b"},
{file = "pydantic-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:40d765fa2d31d5be8e29c1794657ad46f5ee583a565c83cea56630d3ae5878b9"},
{file = "pydantic-1.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3fa799f3cfff3e5f536cbd389368fc96a44bb30308f258c94ee76b73bd60531d"},
{file = "pydantic-1.6.1-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:6c3f162ba175678218629f446a947e3356415b6b09122dcb364e58c442c645a7"},
{file = "pydantic-1.6.1-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:eb75dc1809875d5738df14b6566ccf9fd9c0bcde4f36b72870f318f16b9f5c20"},
{file = "pydantic-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:530d7222a2786a97bc59ee0e0ebbe23728f82974b1f1ad9a11cd966143410633"},
{file = "pydantic-1.6.1-py36.py37.py38-none-any.whl", hash = "sha256:b5b3489cb303d0f41ad4a7390cf606a5f2c7a94dcba20c051cd1c653694cb14d"},
{file = "pydantic-1.6.1.tar.gz", hash = "sha256:54122a8ed6b75fe1dd80797f8251ad2063ea348a03b77218d73ea9fe19bd4e73"},
]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
@ -541,55 +634,66 @@ pyvcd = [
{file = "pyvcd-0.2.3-py2.py3-none-any.whl", hash = "sha256:d4132a03afd353e68fb2a2eb983606603f7e60091198a026fee5fb6da50bbd48"},
{file = "pyvcd-0.2.3.tar.gz", hash = "sha256:c0fd7321143e821033f59dd41fc6b0350d1533ddccd4c8fc1d1f76e21cd667de"},
]
remote-exec = [
{file = "remote-exec-1.7.0.tar.gz", hash = "sha256:ac77b2b45ee94b93d9df9973228c7c948e2057c1f8bcf98c65bd7c72fecef3ee"},
{file = "remote_exec-1.7.0-py3-none-any.whl", hash = "sha256:fe6b969fae5218f51968603e995aa49b22c3d77a5698cda679a5512e93754a07"},
]
six = [
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
]
toml = [
{file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"},
{file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"},
]
wasmtime = [
{file = "wasmtime-0.19.0-py3-none-any.whl", hash = "sha256:def3773817a8923fc71ac1d677a939685b576bc47ac0a1905541f8176eea9049"},
{file = "wasmtime-0.19.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:843ce6e737ef97bce411a34285d10fcbf14d5834b1020a798b7b8c5de5ce60e8"},
{file = "wasmtime-0.19.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:b2b761379d0ce612754437b5dea351ce7371155803dae328f5265335611af3f9"},
{file = "wasmtime-0.19.0-py3-none-win_amd64.whl", hash = "sha256:e986d1a5e9b30fc02ece9cfd55d44d01be0f4e2debd6b32cf52cee37d9b8c6a2"},
]
watchdog = [
{file = "watchdog-0.10.3.tar.gz", hash = "sha256:4214e1379d128b0588021880ccaf40317ee156d4603ac388b9adcf29165e0c04"},
]
wcwidth = [
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]
yowasp-nextpnr-ecp5 = [
{file = "yowasp_nextpnr_ecp5-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:7792c2c6354c1463efee69cd8fee19d655719b01f1315252bd337462b21b615d"},
{file = "yowasp_nextpnr_ecp5-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:afa28b065dcf5b583df4cdeaea634af62a63ed4941ce0834989fd3aada91759c"},
]
yowasp-nextpnr-ecp5-25k = [
{file = "yowasp_nextpnr_ecp5_25k-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:2326efe2cac377d8c951f61d71432b0cc573334d9b2a0154ab9c1d9e6072eaf4"},
{file = "yowasp_nextpnr_ecp5_25k-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:666dc874015489465e92b40b0409b9980f12b7ccbc7ab7d1f69aa106f6163157"},
]
yowasp-nextpnr-ecp5-45k = [
{file = "yowasp_nextpnr_ecp5_45k-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:45679e57d582c178615b055e9d675587f9eb7283ffd3e861f0bc0a9bfcd31004"},
{file = "yowasp_nextpnr_ecp5_45k-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:91eed038f4665a3b788aedbaef53405d4ad035838b14bf04d34124f4502d02af"},
]
yowasp-nextpnr-ecp5-85k = [
{file = "yowasp_nextpnr_ecp5_85k-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:a37d90ee1d936e49794f17e002bee72d0e24fd5e0077784bc31daa2f088806cc"},
{file = "yowasp_nextpnr_ecp5_85k-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:93299536bc6aad1bc08e64f4d5af1538c0161abcdac6fb26d69891cddde26514"},
]
yowasp-nextpnr-ecp5-all = [
{file = "yowasp_nextpnr_ecp5_all-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:148ae0d9b2bddc73d7b7dda6cf850b76b617e6d6784db09e65aa41373fe7e367"},
{file = "yowasp_nextpnr_ecp5_all-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:9acfb842bedf1d3bceab82255dda10c721817702fbcea59581ad71e4891f3d5e"},
]
yowasp-nextpnr-ice40 = [
{file = "yowasp_nextpnr_ice40-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:cc96293ea8fc160c7c97f40ca8f47837e61f47f5fb999f2cd174d470c95bc845"},
{file = "yowasp_nextpnr_ice40-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:7bca1a2ce2d3e43f09aa846d752a390da35ef40f7b980e7b292aacc7f297fe2d"},
]
yowasp-nextpnr-ice40-1k = [
{file = "yowasp_nextpnr_ice40_1k-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:a53eff51f3907c7fc4f926bd7f1c8ede7241118eb0af983d4316183377fd8110"},
{file = "yowasp_nextpnr_ice40_1k-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:bfc638126dfc8f5108ea1b3abbcd6d35fc0a646ff1ec510d9c76a079baa78c00"},
]
yowasp-nextpnr-ice40-384 = [
{file = "yowasp_nextpnr_ice40_384-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:81420f10a3d1f63be9936373ba38f2a581a7df1f4e66ec769b1231c6a0b4b430"},
{file = "yowasp_nextpnr_ice40_384-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:27ec7d283b37a2633cc66190156d644a75b479572c8f7b62c040771cf000a5cd"},
]
yowasp-nextpnr-ice40-5k = [
{file = "yowasp_nextpnr_ice40_5k-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:7809f6b0532d0ff18fbd9968a42d2e0b7e47c96918c3c39e723432a71abbeda9"},
{file = "yowasp_nextpnr_ice40_5k-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:3255e3129a19ef6017378e251314a6d6cc2887d2a30b13e3a50b204c7eb44158"},
]
yowasp-nextpnr-ice40-8k = [
{file = "yowasp_nextpnr_ice40_8k-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:8caa9d001a956181ee8147623129b55441dd4d62ea7e9cc99ec8cc22e1ba5f6b"},
{file = "yowasp_nextpnr_ice40_8k-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:a688a3bb2e8a1e8c0327244d0176a825079ef59ce40698b48c21356efc20fc1d"},
]
yowasp-nextpnr-ice40-all = [
{file = "yowasp_nextpnr_ice40_all-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:d899338055013bb6e7c86fd8f2e6e73125fca0795f84dd16dfb8cb2f9ff0aae1"},
{file = "yowasp_nextpnr_ice40_all-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:ffb9b42f878b2b67fe9d12a344e98aa3593d31565a2543f5db2445cfcb32ed1a"},
]
yowasp-nextpnr-ice40-u4k = [
{file = "yowasp_nextpnr_ice40_u4k-0.0.post2658.dev17-py3-none-any.whl", hash = "sha256:ec0f897707addb1c33fdca70f94c4a55942dfccad78be54f54b16905bf7c08bc"},
{file = "yowasp_nextpnr_ice40_u4k-0.0.post2683.dev25-py3-none-any.whl", hash = "sha256:117e3bfd700c4c8d7767554dd77d2140c0091a4b8b9365d90a1066ba85d33837"},
]
zipp = [
{file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"},

View File

@ -9,18 +9,26 @@ python = "~3.7"
nmigen = {git = "https://github.com/nmigen/nmigen"}
nmigen-dg = {git = "https://github.com/pbsds/nmigen_dg"}
nmigen_boards = "^0.0"
nmigen-yosys = {version = "^0.9.post4757.dev23", optional = true}
yowasp-nextpnr-ecp5-all = {version = "^0.0.post2658.dev17", optional = true}
yowasp-nextpnr-ice40-all = {version = "^0.0.post2658.dev17", optional = true}
nmigen-yosys = {version = "^0.9", optional = true}
yowasp-nextpnr-ecp5-all = {version = "^0.0", optional = true}
yowasp-nextpnr-ice40-all = {version = "^0.0", optional = true}
[tool.poetry.dev-dependencies]
pytest = "^5.2"
remote-exec = "^1.6.1"
[tool.poetry.extras]
yosys = ["nmigen-yosys"]
nextpnr-ecp5 = ["yowasp-nextpnr-ecp5-all"]
nextpnr-ice40 = ["yowasp-nextpnr-ice40-all"]
[tool.portray]
output_dir = "doc_html"
[tool.portray.mkdocs.theme]
name = "material"
palette = {primary = "blue grey", accent = "pink"}
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"