google / CFU-Playground

Want a faster ML processor? Do it yourself! -- A framework for playing with custom opcodes to accelerate TensorFlow Lite for Microcontrollers (TFLM). . . . . . Online tutorial: https://google.github.io/CFU-Playground/ For reference docs, see the link below.
http://cfu-playground.rtfd.io/
Apache License 2.0
452 stars 116 forks source link

Is there any way to use CFU Playground with Altera/Intel boards? #774

Closed FelipeWcosta closed 1 year ago

FelipeWcosta commented 1 year ago

Usually CFU Playground is only supported for LiteX boards what exclude Altera/Intel boards, can I use other toolchains and frameworks to do this migration?

mithro commented 1 year ago

At the moment nobody has used the CFU Playground with Altera/Intel boards so it is likely to require a large amount of effort to make it work. It would not be impossible to do this but buying a Xilinx or Lattice boards is probably going to be a better ROI.

FelipeWcosta commented 1 year ago

Thanks for the reply, this really seems like the right decision to make but we have only Altera/Intel boards available in the moment and looking at the documentation of CFU Playground I can see an option of setup that use Yosys and Nextprn with others tools case needed. Searching in the documentation of each of them, Nextprn is supported for Cyclone V (even in the testing phase) family from Altera and Yosys is too supported for some families from Altera like Cyclone IV and Cyclone V. Is this the way to use some of these boards? I think that is necessary an integration with CFU.

FelipeWcosta commented 1 year ago

When I say "to use some of these boards" I want to say use Cyclone V.

mithro commented 1 year ago

Last I heard the Altera support in nextpnr was still not usable for real designs. The first step to understanding if this has changed would be to see if you can get a standard LiteX SoC running on these boards with these tools. Once that is working reliably you can explore if this will also work in the CFU Playground.

FelipeWcosta commented 1 year ago

@mithro thanks, I will research more on the topic.

FelipeWcosta commented 1 year ago

Usually CFU Playground is only supported for LiteX boards what exclude Altera/Intel boards, can I use other toolchains and frameworks to do this migration?

Correction: LiteX supports FPGAs like de0nano, de10nano and others.

tcal-x commented 1 year ago

@FelipeWcosta IF Litex supports the board you want to use, and supports the proprietary tool flow for that board, and you have those tools installed, and you're willing to use them, then there is an unknown but possibly small amount of additional work needed to get it to work in CFU Playground. For example, you can use Vivado with boards having Xilinx FPGAs, and it's also possible to use Radiant software when targeting boards with Lattice FPGAs.

In other words, CFU Playground doesn't need to have support for your specific proprietary tools as long as you have them installed and LiteX knows how to use them.

FelipeWcosta commented 1 year ago

Hi @tcal-x thanks for your reply. Yes, the LiteX has support to the board that we have available de0nano. My professor came up the idea of ​​using OpenFPGA together with Quartus and it worked to the case for syntesis of a riscv processor. Do you have any tips on what scripts I should pay attention to get this working? I saw some scripts about the supported boards write in Python.

Thank you.

tcal-x commented 1 year ago

Hi @FelipeWcosta first step is to just try it! Try running make TARGET=<litex name of board> bitstream and see what happens.

Note, I see our continuous integration tests in Github actions do run a test with the terasic_de0nano (edit: AND terasic_de10nano) board, which means it worked at least in Renode (the CI tests don't try to build a bitstream). However, our tests seem to be broken currently -- test-projects (proj_template, common_soc, terasic_de0nano)

FelipeWcosta commented 1 year ago

Hi @tcal-x, I just ran the command line make TARGET=terasic_de0nano bitstream and everything went fine up to a point where it was impossible to find the Quartus toolchain. So the next step is to add Quartus to the PATH.

I will report everything here.

FelipeWcosta commented 1 year ago

Hi, I bring news. I've installed the quartus II web edition 32-bit (Free) toolchain and a first moment it seems to compile normally but after it stopped. It has a bunch of warnings too.

Do you have any idea what's going on?

FelipeWcosta commented 1 year ago

Here's the exact moment it stopped:

terasic_de0nano_quartus

FelipeWcosta commented 1 year ago

Here's the exact moment it stopped:

terasic_de0nano_quartus

So, I think that I figure out the error, Quartus is just stopping in the place & route stage.

tcal-x commented 1 year ago

Hi @FelipeWcosta !

I have no experience with Altera tools. You may be able to find more information about the problem in the generated files under soc/build/<board>.<proj>/gateware/.

It is probably useful to have an installation of just LiteX and try building the default target for your board.
If you're familiar with Python, it's recommended to do this in a virtual environment. This is the quick start guide: https://github.com/enjoy-digital/litex

Then cd to litex-boards/litex_boards/targets and run something like ./terasic_de10nano.py --build.

Then if you see the same error, open an issue on the LiteX repo :)

FelipeWcosta commented 1 year ago

Hi @tcal-x, that makes sense. I will do some tests with LiteX and a more recent version of Quartus II (it was done with a 2013 version where many libs are obsolete). Thank you for your help!

FelipeWcosta commented 1 year ago

I bring more updates @tcal-x. It was what I suspected, only the version of Quartus II (changed to version 22.1).

Running the command line make TARGET=terasic_de0nano bitstream the compilation completed without any problems and when I look at the directory soc/build/terasic_de0nano.proj_template/gateware I can see some files that normally generated for the Quartus II and the verilog file terasic_de0nano.v. How it is shown in the printscreen below: folder_path

FelipeWcosta commented 1 year ago

So, do you have any suggestions on how I can proceed?

Thanks for all the support here.

tcal-x commented 1 year ago

The terasic_de0nano.v file is generated by LiteX and would be one of the inputs to Quartus. The other inputs would be the VexRiscv CPU and the user's CFU, although they would be directly referenced and not copied to this directory. I'm not sure which of the files would be the "bitstream" that is put onto the Intel FPGA, but you don't really need to know if everything works.

If you didn't see any errors, the next step would be make TARGET=terasic_de0nano prog, and see what happens. If it is successful at programming the FPGA board, you will probably see the classic LiteX LED cycling pattern.

FelipeWcosta commented 1 year ago

Hello @tcal-x, nice to see you again. So I will try to do that as soon as possible.

tcal-x commented 1 year ago

And in case the prog step works, the next step will be:

make TARGET=terasic_de0nano load

which will:

FelipeWcosta commented 1 year ago

Hello everyone. So, I tried to run the command line make TARGET=terasic_de0nano prog and the compilation was executed very well but I find out the error below, I think that could be an driver problem on Quartus. Later, problably, I will bring more informations.

Thanks!

error_cfu

tcal-x commented 1 year ago

@FelipeWcosta have you been able to program the board by other means? If you have never programmed the board from this particular computer, you may have an UDEV permissions issue --- something you just need to address once.

Usually googling "UDEV \<boardname>" turns up something. For example,

https://www.google.com/search?q=udev+terasic_de0nano&oq=udev+terasic_de0nano

has the link

https://www.local-guru.net/blog/2011/9/25/Using-the-terasic-DE0-Nano-on-ubuntu

FelipeWcosta commented 1 year ago

Hi @tcal-x, I not did this. In the first moment I thought that could be any problem with USB Blaster installation. Thank you for the advise.

FelipeWcosta commented 1 year ago

Hi @tcal-x, the tutorial that you showed was util but I had to followed the tutorial on Intel site to can load a design on the DE0Nano board.

So, I mentioned all the files that was generated by Quartus before and I find out an erro with the file terasic_de0nano.bit (I am not sure but I think what is it about the bitstream file). If it is the bitstream file (Quartus use the .sof file to load a design on the board) can we change to read .sof file on the scripts or exists other ways to generate the .bit file?

Thank you!

terasic_de0nano_error

FelipeWcosta commented 1 year ago

Greetings!

So, I've had searching about the problem trying to figure out any way to genarate the .bit file because I thought that will be the best way to slove this problem the other way will be to create an specifc workflow for the board but we have some erros with the general workflow and it going to generate others erros with the others boards (probably). As it is known we have two differents file formats a .sof file for programming Altera's boards and .bit file for Xilinx's boards maybe others boards too.

I am assessing the possibility of conversion of the .sof into .bit file but I couldn't find an relationship between this files formats yet.

If someone has some information about this and wants share with us, I thank!

FelipeWcosta commented 1 year ago

Hello everyone!

I bring more news. So, I was trying to prog the board using CFU directly instead to convert the files manually, to do this I just changed the file extension to .sof (in the general.py file) in the script and the erros that appearing in the other scripts were commented to avoid them because we are not using the othes boards. I am not sure if the board was really programmed because a could not see the LED's pattern (I can see the LED's pattern when I use Quartus to prog).

de0_nano-error

The image above is the command terminal and how we can see probably there is any error with the communication between the host and the board, some advice for this case?

Thaks!

tcal-x commented 1 year ago

Hi @FelipeWcosta , if the LEDs are not flashing, that's probably a bad sign.

In some cases it may look like there are two serial ports and you get the message above (the script is looking for exactly one that matches /dev/ttyUSB or /dev/ttyACM), but more likely in this case the SoC is not working correctly so there's no serial port showing up. Can you do an ls /dev/ttyUSB* /dev/ttyACM*?

When you think it is working and there appears to be a serial port, then the other thing you can do is try to connect to the SoC BIOS without loading the CFU Playground software; you'd just be talking to the LiteX BIOS, but that itself is very useful.

FelipeWcosta commented 1 year ago

Hi @tcal-x, when I dols /dev/ttyUSB* /dev/ttyACM* do not exist these particular paths in the /dev folder but I can see many others tty paths as it shown in the printscreen.

I installed the LiteX and navigate to \litex-boards\litex_boards\targets path, then I run the specific command line:

.\terasic_de0nano.py --uart-jtag-uart --buil --load

And then I could see the LED's pattern. I also could realize a difference to load the bitstream file:

def main():
    from litex.build.parser import LiteXArgumentParser
    parser = LiteXArgumentParser(platform=terasic_de0nano.Platform, description="LiteX SoC on DE0-Nano.")
    parser.add_target_argument("--sys-clk-freq", default=50e6, type=float, help="System clock frequency.")
    parser.add_target_argument("--sdram-rate",   default="1:1",            help="SDRAM Rate (1:1 Full Rate or 1:2 Half Rate).")
    args = parser.parse_args()

    soc = BaseSoC(
        sys_clk_freq = args.sys_clk_freq,
        sdram_rate   = args.sdram_rate,
        **parser.soc_argdict
    )
    builder = Builder(soc, **parser.builder_argdict)
    if args.build:
        builder.build(**parser.toolchain_argdict)

    if args.load:
        prog = soc.platform.create_programmer()
        prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))

Can I use the --uart argument directly in CFU or is not possible?

tty

tcal-x commented 1 year ago

Hi @FelipeWcosta , yes, there is a way to pass any LiteX argument to the LiteX layer. But I think we have a few things to figure out before we're at that point.

First, we should get to the point of loading a bitstream from CFU Playground to the board and see the cycling LEDs.

If you think the uart option is necessary to get the blinking LEDs, then try adding this to your CFU Playground make line: EXTRA_LITEX_ARGS="--uart-xxx", so you'll end up with something like this:

make TARGET=terasic_de0nano EXTRA_LITEX_ARGS="--uart-xxx" prog

And I see your issue on the litex repo about connecting to the system once it's running --- that's the next step! The people there should be able to help.

FelipeWcosta commented 1 year ago

Hi @tcal-x,

Answaering the first question: Yes, I could see the flashing LED's pattern when I use only the argument ./terasic_de0nano.py --build. The command line which I've used before is in the terasic_de0nano.py script.

Now, the second question, looking at litex-boards/litex_boards/targets/terasic_de0nano.py file I can see some diferences between the functions used to load the bitstream in general.py script like this:

if args.load:
        prog = soc.platform.create_programmer()
        prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))

In the builder function too and some other things.

Apparently, --uart-jtag-uart is not a problem it is worked without it, I going to spend more time trying to fix the issue in LiteX repo. Was I thinking if litex-boards/litex_boards/targets/terasic_de0nano.py could be a base to edit the general.py file? What do you think?

The command line make TARGET=terasic_de0nano EXTRA_LITEX_ARGS="--uart-jtag-uart" prog do not have effect.

Here is the entire code of litex-boards/litex_boards/targets/terasic_de0nano.py:

#!/usr/bin/env python3

#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause

# Build/Use:
# ./terasic_de0nano.py --uart-name=jtag_uart --build --load
# litex_term --jtag-config ../prog/openocd_max10_blaster.cfg jtag

from migen import *
from migen.genlib.resetsync import AsyncResetSynchronizer

from litex.gen import *

from litex.build.io import DDROutput

from litex_boards.platforms import terasic_de0nano

from litex.soc.cores.clock import CycloneIVPLL
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.cores.led import LedChaser

from litedram.modules import IS42S16160
from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY

# CRG ----------------------------------------------------------------------------------------------

class _CRG(LiteXModule):
    def __init__(self, platform, sys_clk_freq, sdram_rate="1:1"):
        self.rst    = Signal()
        self.cd_sys = ClockDomain()
        if sdram_rate == "1:2":
            self.cd_sys2x    = ClockDomain()
            self.cd_sys2x_ps = ClockDomain()
        else:
            self.cd_sys_ps = ClockDomain()

        # # #

        # Clk / Rst
        clk50 = platform.request("clk50")

        # PLL
        self.pll = pll = CycloneIVPLL(speedgrade="-6")
        self.comb += pll.reset.eq(self.rst)
        pll.register_clkin(clk50, 50e6)
        pll.create_clkout(self.cd_sys,    sys_clk_freq)
        if sdram_rate == "1:2":
            pll.create_clkout(self.cd_sys2x,    2*sys_clk_freq)
            pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180)  # Idealy 90° but needs to be increased.
        else:
            pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90)

        # SDRAM clock
        sdram_clk = ClockSignal("sys2x_ps" if sdram_rate == "1:2" else "sys_ps")
        self.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk)

# BaseSoC ------------------------------------------------------------------------------------------

class BaseSoC(SoCCore):
    def __init__(self, sys_clk_freq=50e6, sdram_rate="1:1", with_led_chaser=True, **kwargs):
        platform = terasic_de0nano.Platform()

        # CRG --------------------------------------------------------------------------------------
        self.crg = _CRG(platform, sys_clk_freq, sdram_rate=sdram_rate)

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on DE0-Nano", **kwargs)

        # SDR SDRAM --------------------------------------------------------------------------------
        if not self.integrated_main_ram_size:
            sdrphy_cls = HalfRateGENSDRPHY if sdram_rate == "1:2" else GENSDRPHY
            self.sdrphy = sdrphy_cls(platform.request("sdram"), sys_clk_freq)
            self.add_sdram("sdram",
                phy           = self.sdrphy,
                module        = IS42S16160(sys_clk_freq, sdram_rate),
                l2_cache_size = kwargs.get("l2_size", 8192)
            )

        # Leds -------------------------------------------------------------------------------------
        if with_led_chaser:
            self.leds = LedChaser(
                pads         = platform.request_all("user_led"),
                sys_clk_freq = sys_clk_freq)

# Build --------------------------------------------------------------------------------------------

def main():
    from litex.build.parser import LiteXArgumentParser
    parser = LiteXArgumentParser(platform=terasic_de0nano.Platform, description="LiteX SoC on DE0-Nano.")
    parser.add_target_argument("--sys-clk-freq", default=50e6, type=float, help="System clock frequency.")
    parser.add_target_argument("--sdram-rate",   default="1:1",            help="SDRAM Rate (1:1 Full Rate or 1:2 Half Rate).")
    args = parser.parse_args()

    soc = BaseSoC(
        sys_clk_freq = args.sys_clk_freq,
        sdram_rate   = args.sdram_rate,
        **parser.soc_argdict
    )
    builder = Builder(soc, **parser.builder_argdict)
    if args.build:
        builder.build(**parser.toolchain_argdict)

    if args.load:
        prog = soc.platform.create_programmer()
        prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))

if __name__ == "__main__":
    main()

Thanks for all the help so far!

FelipeWcosta commented 1 year ago

Greetings!

Only bringing some informations about the issue on LiteX repo, I made some tests and finally I've could load the bitstream on the board and access the BIOS, I've could do tests using the command line leds <value> through JTAG but after of some time comes this erro on BIOS terminal:

Error: ftdi_write_data: usb bulk write failed

Apparently, ftdi is part (it's a drive) of OpenOCD then I updated using the linux-litex-on-vexriscv repo without sucess because this new erro come out:

Error: No lowlevel driver available

But ftdi is specified on the script (the error could be the conflict between the different paths of OpenOCD since that Quartus use it too). So, we have a drive problem to a estable communication between the host and board through the JTAG.