diff --git a/.gitignore b/.gitignore index 770869b..b6d3d7e 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/.remoteenv b/.remoteenv new file mode 100644 index 0000000..6d32cf3 --- /dev/null +++ b/.remoteenv @@ -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 diff --git a/README.md b/README.md index d7e8b8e..f5909b1 100644 --- a/README.md +++ b/README.md @@ -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 + 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: diff --git a/fpga/icebreaker_vga.dg b/fpga/icebreaker_vga.dg index 47a2cb2..b36927b 100644 --- a/fpga/icebreaker_vga.dg +++ b/fpga/icebreaker_vga.dg @@ -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" diff --git a/fpga/idea_nmain.md b/fpga/idea_nmain.md new file mode 100644 index 0000000..6a3e4ef --- /dev/null +++ b/fpga/idea_nmain.md @@ -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? + +
+this mess + +```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 + +``` + +
+ +
+could become + +```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 + ) + +``` + +
diff --git a/fpga/modules/bad_apple.dg b/fpga/modules/bad_apple.dg new file mode 100644 index 0000000..2a4ab11 --- /dev/null +++ b/fpga/modules/bad_apple.dg @@ -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 diff --git a/fpga/modules/data/bad_apple.bin b/fpga/modules/data/bad_apple.bin new file mode 100644 index 0000000..33ea140 Binary files /dev/null and b/fpga/modules/data/bad_apple.bin differ diff --git a/fpga/spiflash_ideas.md b/fpga/spiflash_ideas.md new file mode 100644 index 0000000..cfd46cb --- /dev/null +++ b/fpga/spiflash_ideas.md @@ -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. diff --git a/fpga/stdio/i2c.py b/fpga/stdio/i2c.py new file mode 100644 index 0000000..e69de29 diff --git a/fpga/stdio/i2s.py b/fpga/stdio/i2s.py new file mode 100644 index 0000000..e69de29 diff --git a/fpga/stdio/rom.py b/fpga/stdio/rom.py new file mode 100644 index 0000000..995e3c0 --- /dev/null +++ b/fpga/stdio/rom.py @@ -0,0 +1 @@ +# spi flash diff --git a/fpga/stdio/spi.py b/fpga/stdio/spi.py new file mode 100644 index 0000000..e69de29 diff --git a/poetry.lock b/poetry.lock index 86bd1fd..4ea7f97 100644 --- a/poetry.lock +++ b/poetry.lock @@ -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"}, diff --git a/pyproject.toml b/pyproject.toml index 6015a69..a535f26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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"