Friday, December 30, 2022

RISC-v on ZC706 Evaluation Board - Part II

With RISC-v on ZC706 Evaluation Board - Part I, I was successfully building the boot.bin. I thought I got the work done, but realized it was not when I tried the binary I made: after replaced the 'boot.bin' on the SD card with the one I built, the Init LED turns to green for about 1 second, then turns to red, no output from UART port, so something is wrong. Actually there is a warning while making the boot.bin:

[WARNING]: Partition FSBL.elf.0 range is overlapped with partition rocketchip_wrapper.bit.0 memory range
[INFO]   : Bootimage generated successfully

Would need to check the partition layout.

Beside this problem, I'm seeing another issue when playing more, with the fetched SD binaries: running "./fesvr-zynq pk hello" got "ERROR: No cores found", same error for any command with fesvr-zynq. Search the symptom returned same issue:

https://github.com/chipsalliance/rocket-chip/issues/1390

https://github.com/ucb-bar/fpga-zynq/issues/87

Likely there is an update for zedboard but not for zc706. So likely will have to build this fesvr-zynq by myself. Run 'make fesvr-zynq' lead me realized that all sub-modules of rocket-chip/riscv-tools didn't get cloned, especially 'riscv-fesvr' which is needed for making fesvr-zynq. With that repo cloned, the build did make some progress, but eventually would complain cannot find 'arm-xilinx-linux-gnueabi-g++'. Though I did find the executable under Xilinx Vitis, running environment setup script, or even adding the path of the executable won't help, as it needs the PetaLinux build environment, which seems hasn't been fully integrated to Xilinx Vitis. Have to download PetaLinux Tools from Xilinx site.

Will update this once get some progress on this.

Below is quoted from https://github.com/ucb-bar/fpga-zynq

Overview of System Stack

Our system will allow you to run a RISC-V binary on a rocket core instantiated on a supported Zynq FPGA. This section will outline the stack of all of the parts involved and by proxy, outline the rest of the documentation. Going top-down from the RISC-V binary to the development system:

Target Application (RISC-V binary) will run on top of whatever kernel the rocket chip is running. Compiled by riscv-gcc or riscv-llvm.

RISC-V Kernel (proxy kernel or RISC-V Linux) runs on top of the rocket chip. The proxy kernel is extremely lightweight and designed to be used with a single binary linked against Newlib while RISC-V Linux is appropriate for everything else.

Rocket Chip (rocket core with L1 instruction and data caches) is instantiated on the FPGA. Many of its structures will typically map to various hard blocks including BRAMs and DSP slices. It communicates to the host ARM core on the Zynq via AXI.

Front-end Server (riscv-fesvr) runs on the host ARM core and provides an interface to the rocket chip running on the FPGA (connected via AXI).

Zynq ARM Core (actually dual Cortex A9) runs Linux and simplifies interfacing with the FPGA.

FPGA Board (Zybo, Zedboard, or ZC706) contains the Zynq FPGA and several I/O devices. At power on, the contents of the SD card are used to configure the FPGA and boot Linux on the ARM core.

External Communication (TTY over serial on USB or telnet/ssh over ethernet) allows the development system to communicate with the FPGA board.

Development System (PC with SD card reader) generates the images to configure the FPGA.

Tuesday, December 27, 2022

RISC-v on ZC706 Evaluation Board - Part I

Continue my journey with RISC-v on FPGA. This time, I got a Xilinx Zynq-7000 SoC ZC706 Evaluation kit. The board is at least 7 years old. The FPGA has two Cortex-a9 cores. And there is https://github.com/ucb-bar/fpga-zynq which has everything needed to get RISC-v running on several Zynq FPGA boards, including ZC706. Again, this project has no update for more than four years now, so can foresee something might be out-of-date. Making this blog just for reference.

The fpga-zynq github repo has pretty good documentation. It's very easy to follow the Quick Instruction, just fetch images and load them to SD card. Setup the boot mode of the board, and all done. The only issue I had run into is related to the SD card. There are several links for FPGA boot from SD issue, like https://support.xilinx.com/s/question/0D52E00006hpPfLSAU/sd-card-boot-problems-zc706-board and https://support.xilinx.com/s/article/59476. In general, need to make sure all needed files are properly copied to SD card. For my case, the SD card reader I used first has some weird issue. After I used a newer SD card reader, everything goes very smoothly.

For the 2nd step, pushing Rocket modification to FPGA, I got several problems.

  • Problem 1: the instruction mentioned user can pick own rocket-chip directory by override ROCKET_DIR. Since the freedom repo for Arty A7 contains rocket-chip repo, I was thinking to re-use that to reduce the time and disk usage. However, the 'make rocket' command will run into this error: 
        module not found: edu.berkeley.cs#chisel3_2.12;3.2-SNAPSHOT

The error is like https://github.com/ucb-bar/chiseltest/issues/72 and edu.berkeley.cs#chisel_2.11;3.1-SNAPSHOT: not found · Issue #518 · chipsalliance/chisel3 · GitHub. One post mentioned need to update the dependency from chisel2 to chisel3. I cannot figure out a quick way to get around this, so gave up on this. Instead, remove the setting of ROCKET_DIR. 'make init-submodules' will download rocket_chip repo, and the not found of edu.berkeley.cs:chisel3_2.12:3.3-SNAPSHOT is gone.

  • Problem 2: 'make rocket' successfully created rocket_chip.stamp file, but reported no rule to make testchipip.stamp. This is a weird one, as the Makefile and common/Makefrag file does not have testchipip.stamp as target. Turns out due to the line-ending of generate-pkg-mk.sh file, the shell script failed to finish some work which leads to issue for EXTRA_PACKAGES=testchipip. One problem is the make command line doesn't generate meaningful message pointing to the shell script problem. I figured out that by turning on -d option for make, and run the script manually. For fixing this, do: "git config --global core.autocrlf false" then do git checkout to apply the setting.
  • Problem 3: Seeing error
    Missing dependency 'object java.lang.Object in compiler mirror', 
    required by /.m2/repository/org/scala-lang/scala-library/2.10.4/scala-library-2.10.4.jar(scala/package.class)
    
    JDK version not compatible with scala. As replied for https://stackoverflow.com/questions/53942248/maven-error-missing-dependency-java-lang-object-required-by-scala, each version of scala only works with certain version of JDK (refer to docs.scala-lang.org/overviews/jdk-compatibility/overview.html). For this case, have to stick with JDK8:
sudo apt install openjdk-8-jdk-headless
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/java-8-openjdk-amd64/bin/java" 1
sudo update-alternatives --config java
  • Problem 4: "make project" will need to invoke Vivado. On Windows, this can be achieved by running under Cygwin with Vivado executable added to PATH. However, on both Windows and Linux, I'm seeing same error as:
    ERROR: [Board 49-71] The board_part definition was not found for xilinx.com:zc706:part0:1.0. The project's board_part property was not set, but the project's part property was set to xc7z045ffg900-2. Valid board_part values can be retrieved with the 'get_board_parts' Tcl command. Check if board.repoPaths parameter is set and the board_part is installed from the tcl app store.
    Per this, this and this, as the instruction/repo is for Vivado 2016 but I'm using 2022 version, would need to update the tcl script for creating Vivado project, modify the line like this: 
    1. set_property board_part xilinx.com:zcu102:part0:3.0 [current_project]
    to: xilinx.com:zcu102:part0:3.1
    For my case, would need to update zc706/src/tcl/zc706_rocketchip_ZynqFPGAConfig.tcl, which has line as: set_property "board_part" "xilinx.com:zc706:part0:1.0" $obj
    Run get_board_parts within the tcl console shows xilinx.com:zc706:part0:1.4. So update the tcl script, run "rm -rf zc706_rocketchip_ZynqFPGAConfig" first, then run "make project" again.
    Then run into problem 5:
    ERROR: [BD_TCL-109] This script was generated using Vivado <2016.2> and is being run in <2022.1> of Vivado. Please run the script in Vivado <2016.2> then open the design in Vivado <2022.1>. Upgrade the design by running "Tools => Report => Report IP Status...", then run write_bd_tcl to create an updated script.
    This error is from zc706/src/tcl/zc706_bd.tcl. With 2022.1, "Report" is a separate menu item beside tools, and it only shows up after a project is opened. Really don't want to spend hours to install the 2016.2 version. So I just modified the zc706_bd.tcl to set the version as 2022.1 which matches the version I'm using. With that, there is some critical warning, like this: "CRITICAL WARNING: [BD 41-737] Cannot set the parameter PCW_M_AXI_GP0_FREQMHZ on /processing_system7_0. It is read-only.", but the project (.xpr) file did get created successfully. 
     
    Run "make fpga-images-zc706/boot.bin" will do synthesis and implementation with the project. This somehow not working for me, because of the bit file is missing. Likely this is due to my Vivado installation does not have valid license for creating bit for zynq. Opened the project from Vivado which has valid license, and generate bit file there. It got successfully generated on both Linux and Windows Vivado. However, when run "make fpga-images-zc706/boot.bin" again, the boot.bin would be successfully generated on Linux but not on Windows. Error for Windows/Cygwin run is like this:

    ln -sf ../../zc706_rocketchip_ZynqFPGAConfig/zc706_rocketchip_ZynqFPGAConfig.runs/impl_1/rocketchip_wrapper.bit fpga-images-zc706/boot_image/rocketchip_wrapper.bit
    cd fpga-images-zc706; bootgen -image boot.bif -w -o boot.bin
    ...
    [ERROR]  : Cannot read BIT file - boot_image/rocketchip_wrapper.bit

    The bit file under impl_1 did exist, however, 'ln -sf' may create a junction point on NTFS, which might not work for Xilinx Windows bootgen. To get around this, delete the symbolic link, copy the bit file directly to fpga-images-zc706/boot_image folder, then CD to fpga-images-zc706 folder, and run "bootgen -image boot.bif -w -o boot.bin" directly (don't try the make command, as it will create the soft symbolic link again), and this works under Cygwin.
     
    So finally I got the binary built on both Linux and Windows/Cygwin.  Lesson learned is: for FPGA development, better do everything on Linux but not Windows: too many hassle.

    At this point, I thought I had it completed, but in fact, it is not. So  <to be continue>





Thursday, December 1, 2022

Program Arty A7 FPGA to be a RISC-V processor - Part IV

 So still fighting with the "ERROR: [Synth 8-439] module 'BootROM' not found" issue. More internet search did bring back a clue from https://github.com/sifive/freedom/issues/34, richardxia commented Sep 27, 2017: BootROM uses Chisel's sequential memory feature, so it does not refer to an existing Verilog module. You will need to use the vlsi_rom_gen script from rocket-chip to generate the Verilog file from the ROM parameters. See our Makefile rule for handling this: freedom/bootrom/xip/Makefile, Line 38 in 22ee433: $(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@

But, it didn't explain how this is invoked during the build. In the Makefile it has a line as:

 export BOOTROM_DIR := $(base_dir)/bootrom/xip

In common.mk, target 'romgen' would run make under $BOOTROM_DIR, and target 'bit' is depends on 'romgen', and target 'mcs' is depends on 'bit'. So it should be built while run make ... mcs. So I did a clean build with log captured, and found build error as:

java -Xmx2G -Xss8M -XX:MaxPermSize=256M -cp /mnt/ext4/freedom/rocket-chip/firrtl/utils/bin/firrtl.jar firrtl.Driver -i /mnt/ext4/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.fir -o /mnt/ext4/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.v -X verilog
OpenJDK 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
Total FIRRTL Compile Time: 55117.1 ms
make -C /mnt/ext4/freedom/bootrom/xip romgen
make[1]: Entering directory '/mnt/ext4/freedom/bootrom/xip'
dtc -I dts -O dtb -o /mnt/ext4/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.dtb /mnt/ext4/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.dts
/mnt/ext4/riscv/bin/riscv64-unknown-elf-gcc -march=rv32imac -mabi=ilp32 -O2 -std=gnu11 -Wall -I. -nostartfiles -fno-common -g -DXIP_TARGET_ADDR=0x20400000 -DDEVICE_TREE='"/mnt/ext4/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.dtb"' -static -nostdlib -o /mnt/ext4/freedom/builds/e300artydevkit/xip.elf xip.S
/mnt/ext4/riscv/bin/riscv64-unknown-elf-objcopy -O binary /mnt/ext4/freedom/builds/e300artydevkit/xip.elf /mnt/ext4/freedom/builds/e300artydevkit/xip.bin
od -t x4 -An -w4 -v /mnt/ext4/freedom/builds/e300artydevkit/xip.bin > /mnt/ext4/freedom/builds/e300artydevkit/xip.hex
/mnt/ext4/freedom/rocket-chip/scripts/vlsi_rom_gen /mnt/ext4/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.rom.conf /mnt/ext4/freedom/builds/e300artydevkit/xip.hex > /mnt/ext4/freedom/builds/e300artydevkit/rom.v
Traceback (most recent call last):
  File "/mnt/ext4/freedom/rocket-chip/scripts/vlsi_rom_gen", line 90, in iterate_by_n
    batch += (next(it),)
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/mnt/ext4/freedom/rocket-chip/scripts/vlsi_rom_gen", line 138, in <module>
    main()
  File "/mnt/ext4/freedom/rocket-chip/scripts/vlsi_rom_gen", line 134, in main
    **parse_line(line))
  File "/mnt/ext4/freedom/rocket-chip/scripts/vlsi_rom_gen", line 113, in parse_line
    kwargs = {key: try_cast_int(val)
  File "/mnt/ext4/freedom/rocket-chip/scripts/vlsi_rom_gen", line 113, in <dictcomp>
    kwargs = {key: try_cast_int(val)
RuntimeError: generator raised StopIteration
make[1]: *** [Makefile:38: /mnt/ext4/freedom/builds/e300artydevkit/rom.v] Error 1

make[1]: Leaving directory '/mnt/ext4/freedom/bootrom/xip'
make: *** [common.mk:68: /mnt/ext4/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.rom.v] Error 2

And if re-run the make command, the error would be hidden, might because of rom.v file was already generated, even it was error out for previous make run. To fix that, as mentioned https://github.com/chipsalliance/rocket-chip/issues/1991, need to update rocket-chip/scripts/vlsi_rom_gen line 97, replace 'raise' with 'return', then re-do a clean build. Eventually now it is moving forward. And make .. mcs will have the bit file generated. The bit file was generated under builds/e300artydevkit/obj/ folder. And Vivado project file is also available under builds/e300artydevkit, as E300ArtyDevKitFPGAChip.xpr. It can be opened with Vivado, to view all the settings.

Wednesday, November 23, 2022

Program Arty A7 FPGA to be a RISC-V processor - Part III

 Since having lot of problem to follow https://digilent.com/reference/programmable-logic/arty-a7/reference-manual instruction on Windows/WSL/Cygwin, so I moved to do that on Linux/Ubuntu. Most thing goes smoothly. Do need to update several .gitmodules file to get everything synced, i.e. replace git://github.com to https://github.com.

When start to build the toolchain, I hit the first problem is while building riscv-openocd:

Multiple definitions of bitbang_swd originating from jtag/drivers/bitbang.h

Per https://github.com/riscv/riscv-openocd/issues/480, this likely is due to newer GCC 10+ which defaulting to -fno-common. I'm using GCC 11.3.0. So just as suggested, add the 'extern' keyword in front of the const swd_driver struct in bitbang.h. 

Then hit this one for compiling riscv-fesvr ../fesvr/dtm.cc:

'runtime_error' is not a member of std 

According to https://github.com/Azure/azure-storage-fuse/issues/421, it may relate to g++ version: According to https://en.cppreference.com/w/cpp/error/runtime_error, the include should not be exception.h but <stdexcept>. So the fix is adding #include <stdexcept> to dtm.cc.

Similar need to be done for riscv-isa-sim/riscv/devices.h.

With that, the toolchain build is OK. And make for verilog is done without any issue. However, when run

make -f Makefile.e300artydevkit mcs

Seeing this: ERROR: [Synth 8-439] module 'BootROM' not found [/path_of_freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.v:242627]

Make -f Makefile.e300artydevkit mcs fails - module BootRom not found · Issue #96 · sifive/freedom · GitHub someone says re-sync repo solved the problem for him. My Vivado is 2022.1 build, and Digilent's instruction is using 2017 build. Hopefully the new version Vivado is not the problem.

By looking into the make log (there is log file under builds folder), the BootROM module is referenced in the .v file, which is coming from the .fir file as 'extmodule BootROM'. So likely a dependency is missing.

Then I went back to check files in the repo, and noticed in the root README.md, it mentioned two things:

  • As of March 1 2021, SiFive is archiving the freedom repository. The code here is not being actively maintained, and we can't continue to provide updates while the fpga boards, software ecosystems and other dependencies change.
  • Install sbt, varilator (probably typo of verilator) and scala which are required for building from Chisel

Per https://www.chisel-lang.org/: The Constructing Hardware in a Scala Embedded Language (Chisel) is an open-source hardware description language (HDL) used to describe digital electronics and circuits at the register-transfer level that facilitates advanced circuit generation and design reuse for both ASIC and FPGA digital logic designs. Chisel is powered by FIRRTL (Flexible Intermediate Representation for RTL), a hardware compiler framework that performs optimizations of Chisel-generated circuits and supports custom user-defined circuit transformations.

sbt home site: https://www.scala-sbt.org/. Per Wikipedia:

sbt is an open-source build tool for Scala and Java projects, similar to Apache's Maven and Gradle.

And the keyword extmodule is from Chisel. So likely, would need to install them as the README said. The instruction for installing sbt might need to be updated as it doesn't work with new Ubuntu. Refer to https://www.scala-sbt.org/download.html. Not sure why the README.md specified verilator_3_922. Ubuntu has this package, so I run sudo apt install verilator directly, same for scala.

With that, now running make mcs will ask for python. I installed python-is-python3 package, and now seeing a new error, same as described as https://github.com/chipsalliance/rocket-chip/issues/1991:

Traceback (most recent call last):
  File "rocket-chip/scripts/vlsi_rom_gen", line 90, in iterate_by_n
    batch += (next(it),)
StopIteration

As the ticket said, most likely due to I had Python3 but not Python (2.7) installed. Interestingly, the problem is gone after 2nd run of make, and then back to the no BootROM module issue.

Will chasing down the cause. <to be continue>

Program Arty A7 FPGA to be a RISC-V processor - Part II

 When I started on this journey by following instruction from https://digilent.com/reference/programmable-logic/arty-a7/start, I installed Xilinx Vivado on Windows PC as that is the primary working environment. Then when I started building RISC-v, I realized the instruction is all Linux oriented, so I decided to use WSL2 environment to build. The toolchain was successfully built. "make -f Makefile.e300artydevkit verilog" is also OK. But running into problem with "make -f Makefile.e300artydevkit mcs" runs into problem, as it needs to invoke vivado, which I haven't installed, and do not plan to install it under WSL2, simply because it takes too much disk space, and I'm not sure the sure the GUI would work well under WSL2.

Farther looking into the print out from the make mcs output, turns out it is running this from common.mk:

bit := $(BUILD_DIR)/obj/$(MODEL).bit
$(bit): $(romgen) $(f)
        cd $(BUILD_DIR); vivado \
                -nojournal -mode batch \
                -source $(fpga_common_script_dir)/vivado.tcl \
                -tclargs \
                -top-module "$(MODEL)" \
                -F "$(f)" \
                -ip-vivado-tcls "$(shell find '$(BUILD_DIR)' -name '*.vivado.tcl')" \
                -board "$(BOARD)"


# Build .mcs
mcs := $(BUILD_DIR)/obj/$(MODEL).mcs
$(mcs): $(bit)
        cd $(BUILD_DIR); vivado -nojournal -mode batch -source $(fpga_common_script_dir)/write_cfgmem.tcl -tclargs $(BOARD) $@ $<

So it is possible to utilize the Vivado Windows installation, either still do the make under WSL2, or run the make with GNU shell under Windows (such as Cygwin). 

Approach A: Run make under WSL2, install missing Vivado Linux executable

For Windows Vivado installation, it also include Linux vivado shell script under the bin folder. So would need to add the path to the bin like below:

export PATH=$PATH:/mnt/c/Xilinx/Vivado/2022.1/bin

However, Windows Vivado installation won't have Linux executable installed. Would see error like:

WARNING: /mnt/c/Xilinx/Vivado/2022.1/tps/lnx64/jre11.0.11_9 does not exist.
ERROR: Could not find 64-bit executable.
ERROR: /mnt/c/Xilinx/Vivado/2022.1/bin/unwrapped/lnx64.o/vivado does not exist

So would need to extract these missing binaries from installation package.

Approach B: Run make using Cygwin

My freedom.git was synced to my WSL2 home folder. So first thing is find out the Windows path to it. Information can be found from https://superuser.com/questions/1185033/what-is-the-home-directory-on-windows-subsystem-for-linux. For my WSL2 installed on Windows 11, under %LOCALAPPDATA%\Packages\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState is only a 'ext4.vhdx' file, which likely is a virtual disk file. So the way to access it from Cygwin would be map it as a driver, with command like this: net use U: \\wsl.localhost\Ubuntu

Then from Cygwin, cd U: should change CWD to the root dir of WSL2 Ubuntu. However, the make command might still fail with error like this:

Sourcing tcl script 'C:/Users/$win_user/AppData/Roaming/Xilinx/Vivado/Vivado_init.tcl'
source /cygdrive/u/home/$wsl_user/freedom/fpga-shells/xilinx/common/tcl/vivado.tcl
couldn't read file "/cygdrive/u/home/$wsl_user/freedom/fpga-shells/xilinx/common/tcl/vivado.tcl": no such file or directory

To get around this, I moved the freedom folder to be under /mnt/c, which is the Windows C: drive. And this time, it gave me a new error when running make under Cygwin:

Cannot find a jar file even the file exist. So for now, give up on this, until later have some time. Probably can do that directly from Vivado?

<to be continue: moving to do that on Linux>
 


Wednesday, October 19, 2022

Program Arty A7 FPGA to be a RISC-V processor - Part I

 This is a note for things encounter while following instruction to program a Digilent Arty A7 board as RISC-V core. As https://digilent.com/reference/programmable-logic/arty-a7/reference-manual described: The Arty A7, formerly known as the Arty, is a ready-to-use development platform designed around the Artix-7™ Field Programmable Gate Array (FPGA) from Xilinx

https://digilent.com/reference/programmable-logic/arty-a7/start has tutorials Installing Vivado, Vitis, and Digilent Board Files and Running a RISC-V Processor on the Arty A7. The first link has instruction for how to install software/files for the FPGA development. The second link is for how to program Arty A7 as RISC-v core.

For installing Vivado/Vitis, software package is huge. Xilinx download page recommends to use the web installer. However, people like me was hitting "Peer not authenticated" issue as mentioned here. The solution is download the Xilinx Unified Installer 2022.1 SFD gzip file, extract and install. The gzip file is 73.8G, download and extract would need a lot of hard disk space. At least, it works.

For programming Arty A7 as RISC-V, I'm getting many trouble. First, download SiFive Freedom processor with git command: 

git clone --recursive https://github.com/sifive/freedom.git

this would take quite some time to download the git plus a bunch of sub-modules. And may fail with some sub-modules as there are so many of them, and either there is network issue, or the repo server URL was change. If the clone isn't success, then have to fix that, otherwise, won't be able to build. To sync missing sub-module, refer to Git - Submodules (git-scm.com) May run:

# copy the new URL to your local config
$ git submodule sync --recursive
# update the submodule from the new URL
$ git submodule update --init --recursive

If seeing not empty warning, might need to clean those sub-folder first. Might see different problem like:

  • Submodule 'env' (git://github.com/ucb-bar/riscv-test-env.git) registered for path 'rocket-chip/torture/env'
Cloning into '/home/$user/freedom/rocket-chip/torture/env'...
fatal: unable to connect to github.com:
github.com[0: 140.82.114.3]: errno=Connection timed out

cd to freedom/rocket-chip/torture and check the '.gitmodules' would get:

cat .gitmodules
[submodule "env"]
        path = env
        url = git://github.com/ucb-bar/riscv-test-env.git

Per this post, either need to make sure to have SSH key setup, or use https instead of SSH protocol for the git url. So manually run: git clone https://github.com/ucb-bar/riscv-test-env.git env

Or run this to update the .gitmodules file:

sed s#git://github.com#https://github.com#g -i .gitmodules
git submodule sync 
  • For problem like: "server certificate verification failed. CAfile: none CRLfile: none", try this as mentioned in this stackoverflow post: sudo apt update ; sudo apt-get install apt-transport-https ca-certificates -y ; sudo update-ca-certificates

Once git sync is OK, the first step is building the toolchain. Change working directory to rocket-chip/riscv-tools, and check README.md there: would need to set RISCV environment variable first, like this:  export RISCV=/mnt/c/develop/riscv, also, several packages are needed for building the toolchain. Run the build.sh script to build, and it will take some time.

Next step is building Verilog installation. Please note the instruction

make -f Makefile.e300artydevkit Verilog

should have the target 'Verilog' as all little case 'verilog' (which is in common.mk). There is several other cases in the Digilent instruction which should use all little case as well, such as Xilinx=>xilinx

< to be continue >

Wednesday, September 21, 2022

Install multiple Ubuntu instances in WSL2

 Yes, there are probably many post about this, such as https://cloudbytes.dev/snippets/how-to-install-multiple-instances-of-ubuntu-in-wsl2 and https://stackoverflow.com/questions/51584765/how-do-you-install-multiple-separate-instances-of-ubuntu-in-wsl. Still want to make this post about a special case not covered anywhere else.

Run wsl -l can show all installed distribution.

If want to remove one of the distribution, run: wsl --unregister <DistributionName>

Recently I'm playing with ROS Kinetic. Unfortunately, as mentioned http://wiki.ros.org/kinetic/Installation/Ubuntu, only old Wily (15.10) and Xenial (16.04 LTS) are supported. It's possible to get it setup with VirtualBox or VMware VM, but I'd like to go with WSL2 on Windows 11, as mentioned in my the other post, it is possible to enable Ubuntu GUI with the Windows 11 build 22000+. One problem here is the Xenial Ubuntu is no longer available from Microsoft Store, so would need to use WSL2 very useful 'import' feature. For this, would need a tar.gz file of the Ubuntu distribution, the ISO image file doesn't work with WSL import. Another problem now, seems there is no tar for the Xenial Desktop image, but the base image is available such as the amd64 one as ubuntu-base-16.04.6-base-amd64.tar.gz, and it is pretty small, just 41MB. Using command like this to import it:

wsl --import xenial c:\Users\%USERNAME%\wsl_xenial .\Downloads\ubuntu-base-16.04.6-base-amd64.tar.gz 
(Note: for imported distro, if run wsl --unregister, it will delete distro file). There is no Ubuntu desktop and only user root is created. To add new user, run following command with the root account to add the user and add it to sudo group:

adduser newuser

usermod -aG sudo newuser

Try this to verify the user group and switch to it:

groups newuser
su - newuser 

Type 'exit' to switch back to root, and run 'apt update' and 'apt install sudo', so later the new user can do apt install with sudo command. This is the minimum for installing other package as new user. 

To get the desktop environment, run: 'sudo apt install ubuntu-desktop', which installs most common packages. On WSL/Windows OS side, need to follow https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps, installing the AMD/nVidia/Intel's Virtual GPU (vGPU) driver first, then run: 'wsl --update' and 'wsl --shutdown' for a clean restart. May install gedit and run it to verify the GUI. Per my testing, with Ubuntu 20.04 LTS the GUI works fine. However, doesn't work for Ubuntu 16.04 Xenial, seeing segment fault and probably core dump. Tried Diagnosing "cannot open display" type issues with WSLg but not much luck. So leave it aside for now.

 

Sunday, July 10, 2022

我的小鸡们


 六月18日星期周六,对我们全家来说是悲伤的一天,来到我们家十一天的小芦花鸡大毛不幸在我们的后院失踪了,而且最可能是被鹰之类的飞禽捉走了。本来它们是在纸箱里,上面盖着。因为味有点大,太太把纸箱放后院deck上。风大把盖子吹掉了,小鸡就自己跑了出来,可我们不知道,不然一定会看着它们的,因为以前就有小鹰虎视眈眈的站fence上看我们的小鸟。
六月7日,两只小芦花鸡刚刚落户我们家,大概有一周多大,浑身黄白棕黄色的毛,一只颈背棕色毛多的,我们给它取名一撮毛,另一只颈两侧各有些棕毛,我们叫它俩撮毛,后来就简称大毛二毛。大毛二毛很招人喜爱,总是小声小气的鸡鸡个不停,甚至在边吃饭睡觉时也会唧唧,即像在呼唤同伴,又像在表达很好很舒服很好吃。失去了大毛,让我想起了鲁迅《祝福》里的祥林嫂,好在很快,我们又收养了新的小鸡,给了我们一些抚慰。
失去大毛那天,太太带着孩子去买回两只新小鸡,它们是那么小,恐怕刚出生一两天而已,刚来时,站着就要睡着了,也不大吃东西,好像不知道怎么吃。我们叫它俩团团和圆圆,寄予小鸡一家团圆。为了不再老让孩子们想起大毛伤心,我们叫二毛为芦花。

团团圆圆一来就把芦花当作妈妈,总往芦花的翅膀和肚子下钻。好在芦花很nice,从开始觉得很wierd,到后来就顺其自然,带着两个小妹妹吃饭睡觉草地里跑来跑去。鸡食很让我们发愁,不知道它们爱吃什么,于是给它们吃麦片燕麦片,玉米面拌菜,还有苍蝇。天好时我们经常在后院坐板凳上,地上铺着小鸡pupu的报纸,举着苍蝇拍打苍蝇。小鸡们知道啪一声响就有好吃的,所以经常等在身旁,甚至迫不及待的自己追苍蝇,当然总是一无所获。它们快乐的长大着。为了区分两只小的,我们在圆圆小鸡翅膀上mark黑颜色,就叫它小黑。后来我们又从别人那买回一只毛黑一点的小鸡,主人说5月底买的,叫Fluffy,可个头比芦花还小,它以前常被同养的两只小鸭子欺负,胆子很小,好在很快就和芦花团团圆圆和睦相处,我叫它毛毛。它也很快学会吃苍蝇。六月28日周二,我因有事去了办公室,不幸happens again:太太把小鸡放在纸箱里,然后放deck上。为了透气,我在纸箱上给大毛二毛开了些小窗口,可团团圆圆小,可以从窗口跑出来,太太从后院进屋,随手关拉门,没想到从纸箱外逃出来的小圆圆跟在后面,被挤,不幸。为了不让Emily伤心,我急忙从办公室赶回,几经周折,去卖鸡家又买了个小鸡,找不到大一点的,新小鸡叫声响亮,可不大会吃,总想睡觉。因太小,没法骗小孩,只好说farmer要求把小圆圆换走了。这个小家伙,我叫它球球,因为它跑起来像个滚动的棉花球。它长的好像很慢,都过了一个多星期,它还和刚来时差不多大。它睡觉喜欢钻到芦花的翅膀或肚子下,有时芦花已经趴下,小球球会跳到芦花背上,一旦芦花站起来,小球就有机会钻了。






上周日(Jul 3),太太又从别人那买回两只小鸡,有大毛二毛来时大。这样我们就有6只小鸡了。
芦花很喜欢在后院跑,每次它都是最难捉回来的。它甚至听得懂它的名字,每次听到我们喊芦花,就知道有苍蝇吃了,会从院子的不知那个角落连跑带飞的奔到我们打苍蝇的地方来。后来可能因小鸡太多了,小的小鸡时常在我们身旁等苍蝇吃,芦花再从远处赶来常吃不到,它就不大理会名字被叫到了。芦花很早就学会玩土洗澡了,有时就趴在我们种的西红柿旁的土地里,享受泥土和阳光浴。除了苍蝇,芦花和小鸡们很喜欢吃面条,也喜欢米饭。看小鸡们抢食物吃有时很好笑,小的小鸡抢到好吃的会飞快的在其它鸡面前钻来转去。芦花看着很大,可前几天我们给它称了,却还不到一磅。芦花不在外边跑时很乖,轻轻push它,它就肯安静地趴在我们的手和胳膊上。我们都在想芦花再大一点,就会给我们下蛋了。
8日周五早,Rogers的cell phone和无线网同时down了。今天,六只小鸡一早就又被放出来,吃了些菜拌玉米面,喝了些水,在后院撒欢。突然芦花有些异样,站在草地里不动,我以为它在pupu,果然它拉了一点黑稀东西,可还是很不舒服,没过多久它就开始趴下了,连我走过去摸它,它也没再像以前那样run away。我抚摸了它,没多久它变得更加痛苦,头颈开始使劲扭动,很吓人,又让我们手足无措,不知怎样才能帮它,Rogers的网络还没回来,电话是好了,可我们都不知打给谁。我只能帮它按摩腹部,有那么一刻,芦花又站起来,跑开了,让我以为一切转危为安了,可没多久芦花又趴下了。眼睛也不愿睁开了。生命在慢慢逝去。在最后的一刻里,芦花再次从我的手足挣扎出去,跑到了它心爱的西红柿旁的土地里。我把它再次抱回手里没多久,它终于解脱了,安详的躺在我的胳膊上。

我们把它埋在香椿树和桑树下,离小圆圆埋葬的地方很近,希望它在天堂与一撮毛还有小圆圆团聚。
生命有时是如此的脆弱,我们在不知不觉中付出了关爱,在那一刻被残忍的剥夺了。在我们眼前耳边缠绕着它们的身影和声音,我们恐怕不再有勇气去收养新的小鸡。
愿小芦花安息


 

Thursday, May 19, 2022

Setup Gerrit server using HTTP authentication on Ubuntu

 I know there are quite some posts about how to do that, but decide to make this after I scratched to find solution for problem I faced.

For installing Gerrit server on Linux itself, it is pretty straight forward. Not going to talk about the simple way as it is pretty much just a local git. Will only discuss the Standalone Daemon installation as described here: https://gerrit-review.googlesource.com/Documentation/install.html

The instruction is very simple, adding gerrit as new user to your Linux, use gerrit account to install gerrit war file. And there is a note specifically mentioned you would need manually create the gerrit application folder if user gerrit does not have the privilege to create folder there. It also means there is no need of sudoer right for setting up gerrit server.

I picked most default setting during installation, as to be honestly, I don't know exactly what the option is for. But for authentication method, I'm sure I would want the 'http' option, as I want the users are manageable and there is no LDAP or ActiveDirectory at back end for small projects/small teams. But likely nowhere in the guide mentioned that you would need to setup the HTTP server (such as Apache) to make it working. Like many others, I have set the gerrit server on default port 8080, then I tried using web browser to open http://localhost:8080, and got the error: 

Configuration Error

Check the HTTP server's authentication settings.

The HTTP server did not provide the username in the Authorization header when it forwarded the request to Gerrit Code Review.

Some post like this one clarified that gerrit server is not expecting user to directly access the port reserved for Gerrit. Instead, Gerrit is expecting the http server to forward/redirect the access to the gerrit port. If user want to access Gerrit via a port other than the default http port 80, then a port different from the gerrit port would be need to setup with the http server. And, yes, a http server needs to be setup to make things working, especially, the http server also in charge of user authentication => this is not done by Gerrit server. Below setting is for user using http://gerrit_server_IP:8000 to access gerrit with web browser.

I installed the popular apache2 on Ubuntu: sudo apt install apache2

Then create /etc/apache2/sites-available/010-gerrit.conf with content:

<VirtualHost *:8000>
    ServerName localhost

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On

    <Proxy *>
          Order deny,allow
          Allow from all
    </Proxy>
    <Location "/login/">
          AuthType Basic
          AuthName "Gerrit Code Review"
          AuthBasicProvider file
          AuthUserFile /etc/apache2/gerrit.htpasswd
          Require valid-user
    </Location>

    ProxyPass / http://localhost:8080/
</VirtualHost>

For highlighted, the port 8000 is the port for user to access Gerrit via web browser; The path for AuthUserFile is the file used to store authorized user accounts for the web access (not for the Linux host). The port 8080 is where the Gerrit server is listening to. And cannot add 'no-cannon' after that as many post said, as that will give me error (Invalid ProxyPass|ProxyPassMatch parameter. Parameter must be in the form 'key=value') when I trying to restart Apache server. Also, need to add "Listen 8000" to /etc/apache2/ports.conf to make Apache accept access to the 8000 port. Then would need to enable the Gerrit config and restart Apache server with command:

sudo a2enmod proxy_http
sudo a2ensite 010-gerrit
sudo systemctl restart apache2

At this point, both Apache and Gerrit servers are up and running, but there is no valid user yet. To add the first user which would be the admin of Gerrit server, run this command to create user 'admin':

htpasswd -c /etc/apache2/gerrit.htpasswd admin

Note, usually the password file would be maintained by the web service account, so there is no need 'sudo' for running htpasswd command. Without 'sudo'. would need to run 'sudo chown' and 'sudo chgrp' against the password file to grant permission to the web service account, such as 'gerrit'.

Gerrit server is ready from now on. New user would need be added manually by gerrit account with command:

htpasswd /etc/apache2/gerrit.htpasswd new_user

Note: comparing above, no '-c' here. Otherwise it will overwrite the password file, and the previous added account (admin) would get removed.

There is many way to add a self register user service if that is desired.

Several other notes:

1) gerrit server won't automatically get started. Follow the instruction https://gerrit-review.googlesource.com/Documentation/install.html to make it automatically starts with OS boot.

And keep in mind, for manually starting gerrit, have to run gerrit.sh start with sudo as it needs root right. Make sure seeing 'Starting Gerrit Code Review: OK' after start gerrit.

2) Better update gerrit_application_directory/etc/gerrit.conf port setting of canonicalWebUrl, change to:

 canonicalWebUrl=http://gerrit_server_IP:8000/

i.e. the port number should be matched with Apache server setting for Gerrit. Otherwise, when user trying to logout or other operation, gerrit may direct the access to the Gerrit internal port 8080.

3) Keep in mind the user account for the host PC and Gerrit service are separated. 'gerrit' is account on the host PC, and above 'admin' account is gerrit user account. For gerrit operation via SSH, user would need to upload the SSH key for the Gerrit account first. Also note, with latest Git/OpenSSH, it may no longer accept RSA key, so you may generate ed25519 key pair for current host user account with this command:

ssh-keygen -t ed25519 -C 'some_comment'

Then you can run gerrit ssh command, such as this one for flush project_list:

ssh -p 29418 admin@gerrit_server_IP gerrit flush-caches --cache project_list

Note above command is using the Gerrit account name 'admin' for the SSH session, as the SSH service is provided by Gerrit.

4) Gerrit supports multiple plugin, such as gitiles for browse repo code. It's pretty easy to install plugins, just drop the jar file to gerrit_application_directory/plugins folder. And in fact, the gerrit installer war is coming with several common plugins, include giltes. User can install the plugin with init command (ref link), like this:

java -jar gerrit-3.5.1.war init -d /path/to/gerrit_app --install-plugin gitiles --install-plugin hooks --install-plugin plugin-manager --install-plugin singleusergroup ...

Or just do init with --install-all-plugins to have all default plugins installed.

5) If manually put a bare repo under gerrit git folder, it won't show up in gerrit web view. Running "gerrit flush-caches --cache project_list" won't help. User may explicitly make it visible with gerrit command: gerrit set-project the_hidden_git_name --project-state ACTIVE, or take other approach mentioned in the stackoverflow page: https://stackoverflow.com/questions/27817107/unhide-a-hidden-gerrit-project

And for local git, would need to set or update the remote URL like this:

git remote set-url origin ssh://gerrit_server_IP:29418/git_name 

6) As using HTTP authentication, we are not hooking up to company's LDAP server. The mail setting might be a headache, as it is not easy to setup using company's SMTP server. Even with mail service installed on the local Linux server, email exchange between the Linux and company's email server might be a nightmare. For example, I have Postfix installed on my Linux, and I'm getting 'Rejecting Unknown Local Recipients with Postfix'. Following this I can get the error resolved, the Linux mail system did say mail has been delivered, but I have never got the email from company email server. This would be a problem as user needs to register an email for submit code review: gerrit will send a verification email before adding user email address in record. To get around this, following https://gerrit-review.googlesource.com/Documentation/cmd-set-account.html, set the email address for new user using the admin account:

ssh -p 29418 admin@localhost gerrit set-account --add-email useremail_name@company.com gerrit_username

For gerrit management, there is plugins/admin-console (googlesource.com) which provides  information via SSH commands to Gerrit Administrators.

Note:  if planning to use LDAP, then no need to setup Apache, may just follow https://gerrit-review.googlesource.com/Documentation/config-gerrit.html#ldap.

Sunday, February 20, 2022

Recover USB thumb drive (修复U盘)

USB thumb drive is very popular due to the cheap price, portable, easy to use, and can be used as boot media. However, occasionally user may run into problem with this small piece of hardware, such as the USB device is detected as malfunction USB device, Disk needs to be format but cannot be formatted successfully, No Disk or No Media, etc. In most cases, the hardware wasn't damaged, the real problem is some essential data stored on the flash was corrupted. The flash not only contains area as user storage space, but also reserves several small space for storing this USB drive specific configuration data, and firmware which is used to manage the flash memory, yes, inside the flash drive there is a small controller chip beside the flash chip, and it may consume the firmware we mentioned here. Some vendors sell the USB board with controller, and customer can solder the desired flash chip on it, such as this one from Ali-Express, which is about $14 each:

SM3267L AE UFD PCBA, 3267AE USB3.0 FLASH DRIVE PCBA, DIY UDF Kits, TSOP48+LGA60 Special Pad,ONLY FOR some LGA60 E2NAND.|kit kits|pad padkit diy - AliExpress

The chip in the middle, SM3267L-AE, is an USB 3.0 controller from Silicon Motion(慧荣). The right side is the pads for soldering the flash chip, you can pick compatible chip from Sandisk, Samsung, Intel or any other vendors.

If you run into this problem, you may try to recover your USB thumb drive if you know the detail of the hardware, and can find the right tools to program it. Don't bother to try the vendor's online recovery tools or RMA, mostly those just a waste of time and money.

Luckily, there is popular software/tools and website all about this. To identify the chip info, the most popular tools is the ChipGenius(芯片精灵). You can find this software from many site, likely the tools originally is from Chinese site https://www.mydigit.cn/(数码之家), a Russian website, https://www.usbdev.ru/files/chipgenius/,  has a collection of almost all versions of it. There is a catch, for the latest version v4.20 and v4.21, anti-virus software will report "Trojan:Win32/CryptInject!MSR" . I'm not sure is it a real risk or false alarm, anyway, for anyone who concern about the risk, you can stick with the version 4.19, which works for most chip/devices.

Once you can identify the chip info, then you will need to find the right tools to reprogram the device. For my case, it is the above SM3267AE controller with a Sandisk chip. So I would need the SMI Massive Production Tool (MP Tool). The Russian usbdev site again provide a collection of the tools at here: https://www.usbdev.ru/files/smi/transcendsmbyusbdev/

There is a lot of tutorial of this SM MP Tool, such as this one: 慧荣SMI SM32X量产工具G1219 图文教程.恢复方法. Just several notes here per my experience:

  • 1st need to setting, the password is '320' or two space.  
  • Check 'Download ISP' if you get No Media or Capacity is 0. Do not select specific ISP file if you don't know which one is the right one. Let the tools to select the proper one.
  • may get fail for different reason, just try different setting. For format error, can ignore it. Later do the formatting from Windows.

Sunday, January 23, 2022

Convert image to printable ASCII with Python

我上大学那时还没有喷墨和激光打印机,只有9针/16针的针式打印机,只能打印ASCII字符,不能打印图像。有很酷的程序把图像转换成ASCII符。Google可以找到很多这类程序,如:

https://github.com/qeesung/image2ascii

https://github.com/uvipen/ASCII-generator

https://github.com/LazoCoder/Image-To-ASCII

这里share一个我写的比较简单的程序 (font file can be downloaded from fonts.google.com: hhttps://fonts.google.com/specimen/Courier+Prime?query=courier):

import tkinter
from tkinter import filedialog
from PIL import Image, ImageFont

def create_char_map():
characters = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
weights = []

font_name = "Courier_Prime/CourierPrime-Regular.ttf"
font_size = 16 # px
font_color = "#000000" # HEX Black
font = ImageFont.truetype(font_name, font_size)
max_weight = 0

# Loop through the characters needed and save to desired location
for character in characters:
# Get text size of character
width, height = font.getsize(character)
pix = font.getmask(character)
weight = 0
for y in range(len(pix)//width): # the actual row might be smaller than hegith
for x in range(width):
weight += pix[x+width*y]
weights.append(weight)
if weight>max_weight: max_weight = weight
# uniform the weight to 0~256*3-1
char_map = {767-int(w*767/max_weight):ch for (w, ch) in zip(weights, characters)}
# for revert image: char_map = {int(w*767/max_weight):ch for (w, ch) in zip(weights, characters)}
return char_map

def get_pixmap(path):
im = Image.open(path)
print('Original: ' + str(im.size))
size = 320
if im.size[0] > size:
resized_image = im.resize((size, int(size * im.size[1] / im.size[0])))
pixmap = resized_image.load()
pixmap_size = resized_image.size
print('Resized: ' + str(pixmap_size))
else:
pixmap = im.load()
pixmap_size = im.size
return pixmap, pixmap_size
 
def getchar(rgb_sum):
for i in range(1, len(char_keys)):
if rgb_sum<char_keys[i]:
if char_keys[i]+char_keys[i-1]>rgb_sum*2: i=i-1
break
return char_map[char_keys[i]]

def main():
#return
root = tkinter.Tk()
root.withdraw()
fin=filedialog.askopenfilename()
if(fin):
pixmap, pixmap_size = get_pixmap(fin)
file = open('output.txt', 'w')
for y in range(0, pixmap_size[1]-1, 2):
line=''
for x in range(pixmap_size[0]):
# merge two line into one printed line to keep a better ratio
rgb_sum = (pixmap[x, y][0] + pixmap[x, y][1] + pixmap[x, y][2] +
 pixmap[x, y+1][0] + pixmap[x, y+1][1] + pixmap[x, y+1][2])>>1
line+=getchar(rgb_sum)
file.write(line+'\n')
file.close()

if __name__=="__main__":
char_map = create_char_map()
char_keys = sorted(char_map)
main()