amaranth-lang / amaranth

A modern hardware definition language and toolchain based on Python
https://amaranth-lang.org/docs/amaranth/
BSD 2-Clause "Simplified" License
1.52k stars 168 forks source link

Use nextpnr-himbaechel on Gowin #1007

Open mobilinkd opened 8 months ago

mobilinkd commented 8 months ago

I need help with what appears to be a bug somewhere in the Amaranth/Yosys/Apicula ecosystem. It could also be me because this is my very first day playing around with Amaranth, Yosys, and Apicula. And it's my second day with the Tang Nano 9K.

I created a blinky using a down counter (see below). I programmed it first with the Gowin toolchain. It worked - I got blinky. When I switched to the Apicula toolchain, no blinky.

Both toolchains show that the bitstream was built and programmed successfully. Have I stumbled upon a known problem with the toolchain? A quick search for down-counter problems with Amaranth or Yosys didn't find anything.

The default blinky works. And the code below works with Apicula if I change it from a down counter to an up counter. I extracted the down counter into a separate module and tested it independently. It passes the unit tests and the waveforms look as expected. I just duplicated the test code in the Amaranth tutorial for the up counter. I embedded the down counter module into the blinky code below and verified that the behavior remains the same.

from amaranth import *

class Blinky(Elaboratable):
    def elaborate(self, platform):
        m = Module()

        led = platform.request("led")

        half_freq = int(platform.default_clk_frequency // 2)
        timer = Signal(range(half_freq + 1), reset=half_freq)

        with m.If(timer == 0):
            m.d.sync += led.o.eq(~led.o)
            m.d.sync += timer.eq(timer.reset)
        with m.Else():
            m.d.sync += timer.eq(timer - 1)

        return m

from amaranth_boards.tang_nano_9k import TangNano9kPlatform

# TangNano9kPlatform(toolchain='Gowin').build(Blinky(), do_program=True)
TangNano9kPlatform(toolchain='Apicula').build(Blinky(), do_program=True)
whitequark commented 8 months ago

I would suggest you seek help from the Apicula project. I have not positively excluded this from being an Amaranth issue (and I probably won't before holidays end), but that seems much more likely to be an Apicula-related problem.

How did you install Apicula?

mobilinkd commented 8 months ago

I installed Apicula via pip: Apycula 0.10.0

whitequark commented 8 months ago

cc @yrabbit

yrabbit commented 8 months ago

Uh, oh. How would I get Verilog out of this? (if it possible without the need to install Linux or Windows in virtual machines) :)

mobilinkd commented 8 months ago

Here are two files:

Both had to be renamed with .txt extensions to make github accept the attachments.

I can also provide the top.il which is used for synthesis with Apicula/yosys rather than the Verilog file if that is needed.

blinky.txt top.txt

whitequark commented 8 months ago

How would I get Verilog out of this?

Amaranth runs on macOS, the documentation has instructions for this.

yrabbit commented 8 months ago

Here are two files:

  • blinky.v is produced using verilog.convert(Blinky(), ports=[], platform=TangNano9kPlatform(toolchain='Apicula'))

This blinky will not blink - everything inside will be thrown away by the optimizer due to the fact that the top module does not have output ports, but only an inputs: clock and reset.

module top(rst, clk);
  reg \$auto$verilog_backend.cc:2189:dump_module$1  = 0;
  (* src = "/home/rob/tang_nano_9k/./blinky_orig.py:12" *)
  wire \$1 ;
  (* src = "/home/rob/tang_nano_9k/./blinky_orig.py:13" *)
  wire \$3 ;
  (* src = "/home/rob/tang_nano_9k/./blinky_orig.py:12" *)
  wire \$5 ;
  (* src = "/home/rob/tang_nano_9k/./blinky_orig.py:16" *)
  wire [24:0] \$7 ;
  (* src = "/home/rob/tang_nano_9k/./blinky_orig.py:16" *)
  wire [24:0] \$8 ;
  (* src = "/home/rob/.local/lib/python3.11/site-packages/amaranth/hdl/ir.py:508" *)
  input clk;
  wire clk;
whitequark commented 8 months ago

Thanks @yrabbit! I think @mobilinkd isn't generating the Verilog correctly as TangNano9kPlatform(toolchain='Apicula').build(Blinky(), do_program=True) does pass a non-empty ports argument to verilog.convert internally.

yrabbit commented 8 months ago

It seems that I was able to install amaranth under DragonFlyBSD, but do I still need to get the board descriptions somehow? error

whitequark commented 8 months ago

Use:

pip install git+https://github.com/amaranth-lang/amaranth-boards.git
yrabbit commented 8 months ago

Good news: amaranth works

https://github.com/amaranth-lang/amaranth/assets/6075465/6f67b78d-009a-4d00-9123-bf252e2816a2

Not so good news: himbaechel-gowin is used.

--- amaranth/vendor/_gowin.py   2024-01-10 09:46:07.924651000 +1000
+++ /home/rabbit/tmp/_gowin.py  2024-01-10 09:45:57.974524000 +1000
@@ -201,7 +201,7 @@

     _apicula_required_tools = [
         "yosys",
-        "nextpnr-gowin",
+        "nextpnr-himbaechel",
         "gowin_pack"
     ]
     _apicula_file_templates = {
@@ -241,14 +241,14 @@
             {{name}}.ys
         """,
         r"""
-        {{invoke_tool("nextpnr-gowin")}}
+        {{invoke_tool("nextpnr-himbaechel")}}
             {{quiet("--quiet")}}
             {{get_override("nextpnr_opts")|options}}
             --log {{name}}.tim
             --device {{platform.part}}
-            --family {{platform._chipdb_device}}
+            --vopt family={{platform._chipdb_device}}
             --json {{name}}.syn.json
-            --cst {{name}}.cst
+            --vopt cst={{name}}.cst
             --write {{name}}.pnr.json
         """,
         r"""

I think that searching and fixing in legacy gowin is an extremely inefficient use of time and effort. I could be wrong, of course, but to be honest, I don’t even have legacy chip databases on my computer.

whitequark commented 7 months ago

I think you should stop shipping nextpnr-gowin if you do not support it.

yrabbit commented 7 months ago

Yes, that's reasonable. Stops only the lack of nextpnr release with himbaechel support.