Vengineerの妄想(準備期間)

人生は短いけど、長いです。人生を楽しみましょう!

BluespecのAWSteria_Infraを調べる(その1)

はじめに

今日は、今年(2023年)前半最後の有給休暇でお休みです。お暇なので、Bluespecのgithub を眺めていたら、面白いものがあったので調べてみたい思いました。

AWSteria_Infra では、下記のような3つの環境をサポートしています。実機が無くても、BluesimとVerilatorでのシミュレーション環境もあります。

  • Simulation in Bluesim and Verilator simulation (infrastructure is in Platform_Sim/).
  • Xilinx VCU118 FPGA board (infrastructure is in Platform_VCU118/).
  • Amazon AWS F1 (infrastructure is in Platform_AWSF1/).

面白そうだったので、Bluespecの環境を構築し、Simulationをやってみたいと思います。

まずは、Bluespecのbscの環境を構築します。

INSTALL.md

を見てやってみました。

準備

clone

$ git clone https://github.com/B-Lang-org/bsc.git

$ cd bsc
$ ls
COPYING     GNUmakefile  LICENSE.txt  README.md  examples     platform.sh  src        util
Dockerfile  INSTALL.md   LICENSES     doc        platform.mk  release      testsuite

Haskell の環境の準備

$ sudo apt-get install ghc
$ sudo apt-get install \
    libghc-regex-compat-dev \
    libghc-syb-dev \
    libghc-old-time-dev \
    libghc-split-dev

$ sudo apt-get install cabal-install

$ cabal update
$ cabal install regex-compat syb old-time split

ビルド

$ make -f GNUmakefile
This Makefile will create an installation of the Bluespec Compiler tools,
in a directory named "inst".  This directory can be moved anywhere, but
the contents should remain in the same relative locations.  Intermediate
files are stored in a directory named "build".  The "clean" target will
delete the "build" directory; the "full_clean" target will delete both
the "build" and "inst" directories.

    make  release      Build a release dir with the tools and docs

    make  install-src  Build and install just the tools
    make  install-doc  Build and install just the documentation

    make  check-smoke  Run a quick smoke test
    make  check-suite  Run the test suite (this will take time!)

    make  clean        Remove intermediate build-files unnecessary for execution
    make  full_clean   Restore to pristine state (pre-building anything)

$ make -f GNUmakefile release
make  -C src  PREFIX=/mnt/c/Users/xxxxx/home/src/bsc/inst  install
make[1]: Entering directory '/mnt/c/Users/xxxxx/home/src/bsc/src'
Makefile:49: *** Submodule vendor/yices/v2.6/yices2 missing. Initialize with
    git submodule update --init --recursive.  Stop.
make[1]: Leaving directory '/mnt/c/Users/xxxxx/home/src/bsc/src'
make: *** [GNUmakefile:41: install-src] Error 2

$ git submodule update --init --recursive
Submodule 'src/vendor/yices/v2.6/yices2' (https://github.com/SRI-CSL/yices2) registered for path 'src/vendor/yices/v2.6/yices2'
Cloning into '/mnt/c/Users/xxxxx/home/src/bsc/src/vendor/yices/v2.6/yices2'...
Submodule path 'src/vendor/yices/v2.6/yices2': checked out 'f705557b7d33d866eb1b47b5471f97189eb31cc4'

下記のパッケージも必要であったので、事前にインストール

$ sudo apt install texlive-full
$ sudo apt-get install -y asciidoctor 
$ sudo gem install asciidoctor-pdf --pre
$ make -f GNUmakefile release
ここで結構時間がかかる

$ make  install-src 
$ make  install-doc

シミュレーションの準備

色々探ってみたら、Host側のビルドとHW側のビルドが必要なことが分かった

下記のように clone したディレクトリを AWSTERIA_INFRA_REPO 環境変数に設定しておく。これは大切です。

$ export AWSTERIA_INFRA_REPO=~/xxx?AWSteria_Infra

Host側のビルド

TestApp/Host/build_sim ディレクトリにて、make exe_Host_sim を実行します。exe_Host_sim が生成されます。

$ cd TestApp/Host/build_sim
$ make
INFO: AWSTERIA_INFRA_REPO = /home/vengineer/home/src/AWSteria_Infra
INFO: TARGET is VCU118 (has DDR A and B)
Usage:
    make exe_Host_sim        create the host-side executable
    make clean         delete temporary files/dirs but keep the executable
    make full_clean    delete temporary files/dirs and delete the executable
  Please define TARGET=VCU118 or TARGET=AWSF1 for proper DDR setup
make exe_Host_sim
INFO: AWSTERIA_INFRA_REPO = /home/vengineer/home/src/AWSteria_Infra
INFO: TARGET is VCU118 (has DDR A and B)
gcc -D SIM_FOR_VCU118 -std=gnu11 -g -Wall -Werror -I /home/vengineer/home/src/AWSteria_Infra/Include_API -I /home/vengineer/home/src/AWSteria_Infra/Platform_Sim/Host -g  -o exe_Host_sim /home/vengineer/home/src/AWSteria_Infra/TestApp/Host/main.c /home/vengineer/home/src/AWSteria_Infra/Platform_Sim/Host/AWSteria_Host_lib.c /home/vengineer/home/src/AWSteria_Infra/Platform_Sim/Host/Bytevec.c /home/vengineer/home/src/AWSteria_Infra/Platform_Sim/Host/TCP_Client_Lib.cc
INFO: Created host-side executable exe_Host_sim

HW側のビルド

$ cd TestApp/HW/build_Bluesim
$ make
Makefile:21: *** ERROR: please define FLUTE_REPO, i.e., path to Flute repo.  Stop.

どうやら、Bluespec の Flute という RISC-V を使うみたい。

cd ~/home/src
git clone --recu https://github.com/bluespec/Flute.git
$ export FLUTE_REPO=~/xxxxx/bsc

BLUESPEC_HOME環境変数の設定が必要のようです。

$ cd TestApp/HW/build_Bluesim
$ make
INFO: FLUTE_REPO is /home/vengineer/home/src/bsc
INFO: AWSTERIA_INFRA_REPO is /home/vengineer/home/src/AWSteria_Infra
Makefile:33: *** ERROR: please define BLUESPEC_HOME, i.e., path to bsc installation.  Stop.
$ export BLUESPEC_HOME=~/xxxxx/bsc
$ make
INFO: FLUTE_REPO is /home/vengineer/home/src/Flute
INFO: AWSTERIA_INFRA_REPO is /home/vengineer/home/src/AWSteria_Infra
INFO: BLUESPEC_HOME is /home/vengineer/home/src/bsc
INFO: TARGET is VCU118 (has DDR A and B)
/home/vengineer/home/src/AWSteria_Infra/Platform_Sim/HW/Include_Common.mk:11: warning: overriding recipe for target 'help'
Makefile:7: warning: ignoring old recipe for target 'help'
    make  compile      Recompile HW-side
    make  simulator    Compiles and links intermediate files/RTL to create simulation executable
                           (Bluesim or verilator)
    make  all          = make  compile  simulator

    make  clean        Remove intermediate build-files unnecessary for execution
    make  full_clean   Restore to pristine state (pre-building anything)

とりあえず、コンパイルしてみます。

$ make compile
.....
compiling /home/vengineer/home/src/AWSteria_Infra/Platform_Sim/HW/Top_HW_Side.bsv
code generation for mkTop_HW_Side starts
Elaborated module file created: build_dir/mkTop_HW_Side.ba
All packages are up to date.
INFO: Re-compiled  Core (CPU, Caches)

simulator を生成します。

$ make simulator
....
Simulation shared library created: exe_HW_sim.so
Simulation executable created: ./exe_HW_sim
INFO: linked bsc-compiled objects into Bluesim executable

シミュレータ(exe_HW_sim)ができたみたいです。exe_HW_sim を実行してみます。2: top.rl_listen で止まります。

$ ./exe_HW_sim
================================================================
Bluespec AWSteria_Infra simulation v2.1
Copyright (c) 2020-2022 Bluespec, Inc. All Rights Reserved.
================================================================
INFO: top.ddr_A
    base 0x0000000000000000  lim 0x0000000080000000    implemented 0x0000000080000000
INFO: top.ddr_B
    base 0x0000000080000000  lim 0x0000000100000000    implemented 0x0000000080000000
INFO: Listening for connection from host-side on TCP port 30000
    (2: top.rl_listen)

Host側のプログラムを実行します。

$ cd TestApp/Host/build_sim
$ ./exe_Host_sim
INFO: TestApp host-side built for simulation of Platform VCU118
    ddr_A_base = 0x               0  ddr_A_lim = 0x        80000000
    ddr_B_base = 0x        80000000  ddr_B_lim = 0x       100000000
    out_of_bounds_addr                         = 0x       100000000
Initializing AWSteria host-side API libs
tcp_client_open: connecting to '127.0.0.1' port 30000
tcp_client_open: connected
Filling wbuf with random data
    filled wbuf with random data

Performing tests ...

test0: ----------------
AXI4: Single-byte write, base_addr 0x0
AXI4: Single-byte read, base_addr 0x0

test0: ----------------
AXI4: Single-byte write, base_addr 0x80000000
AXI4: Single-byte read, base_addr 0x80000000

test50: ----------------
AXI4: Series of small writes/reads across first 128 bytes
    base_addr = 0x0
    at sizes 1, 2, 4, 8 bytes

test50: ----------------
AXI4: Series of small writes/reads across first 128 bytes
    base_addr = 0x80000000
    at sizes 1, 2, 4, 8 bytes

test60: ----------------
AXI4: write/read 0x2000 bytes, base_addr 0x0

test60: ----------------
AXI4: write/read 0x2000 bytes, base_addr 0x80000000

test60: ----------------
AXI4: write/read 0x1001 bytes, base_addr 0x5

test60: ----------------
AXI4: write/read 0x1001 bytes, base_addr 0x80000005

test70: ----------------
AXI4: write DDR_A (addr 0x0); data 0x0 to 0x100
AXI4: write DDR_B (addr 0x80000000); data 0x100 to 0x200
AXI4: read back DDR_A, testing that data was not overwritten
AXI4: read back DDR_B, testing that data was not overwritten

test80: ----------------
AXI4L: Series of 4 byte write/read across first 128 bytes

test90: ----------------
AXI4 write, AXI4-Lite read, base_addr 0x0
AXI4 write 128 bytes
AXI4L: readback 128 bytes

test100: ----------------

AXI4 write, AXI4-Lite read, base_addr 0x0
AXI4L write 128 bytes
AXI4: readback 128 bytes

test990: ----------------
AXI4: Single-byte write, out-of-bounds addr 0x100000000
NOTE: ERROR expected
----
AXI4: Single-byte read, out-of-bounds addr 0x100000000
NOTE: ERROR expected
ERROR: buf_read_AXI4: 1 bytes from addr 0x100000000
    FAILED: rc = 1

END OF TESTS; TEST STATS ----------------
num_ERRORS = 0
num_expected_ERRORS = 1
n_AXI4_reads  = 489, AXI4_read_bytes  = 26244
n_AXI4_writes = 490, AXI4_write_bytes = 26245
n_AXI4L_reads  = 64 (4 bytes each)
n_AXI4L_writes = 64 (4 bytes each)
----------------
Finalizing FPGA lib or simulation lib
AWSteria_Host_shutdown: closing TCP connection
tcp_client_close

HW側も再開されます。

INFO: Listening for connection from host-side on TCP port 30000
    (2: top.rl_listen)
INFO: Accepted connection from host-side on TCP port 30000
    (10539093: top.rl_accept)
10581507: ERROR: rl_wr_xaction_no_such_slave: m0 -> ?
    top.awsteria_hw.fabric
        AXI4_Wr_Addr { awid: 'h0000, awaddr: 'h0000000100000000, awlen: 'h00, awsize: 'h6, awburst: 'h1, awlock: 'h0, awcache: 'h0, awprot: 'h0, awqos: 'h0, awregion: 'h0, awuser: 'h0 }
10581510: ERROR: rl_rd_xaction_no_such_slave: m0 -> ?
    top.awsteria_hw.fabric
        AXI4_Rd_Addr { arid: 'h0000, araddr: 'h0000000100000000, arlen: 'h00, arsize: 'h6, arburst: 'h1, arlock: 'h0, arcache: 'h0, arprot: 'h0, arqos: 'h0, arregion: 'h0, aruser: 'h0 }
c_host_recv2: Connection closed by remote host

Verilator でも実行してみる

$ cd TestApp/HW/build_Verilator
$ make
INFO: FLUTE_REPO is /home/vengineer/home/src/Flute
INFO: AWSTERIA_INFRA_REPO is /home/vengineer/home/src/AWSteria_Infra
INFO: BLUESPEC_HOME is /home/vengineer/home/src/bsc
INFO: TARGET is VCU118 (has DDR A and B)
/home/vengineer/home/src/AWSteria_Infra/Platform_Sim/HW/Include_Common.mk:11: warning: overriding recipe for target 'help'
Makefile:7: warning: ignoring old recipe for target 'help'
    make  compile      Recompile HW-side
    make  simulator    Compiles and links intermediate files/RTL to create simulation executable
                           (Bluesim or verilator)
    make  all          = make  compile  simulator

    make  clean        Remove intermediate build-files unnecessary for execution
    make  full_clean   Restore to pristine state (pre-building anything)

all (compile & simulator) を実行してみる。

$ make all
....
INFO: Verilating Verilog files (in Verilator_Make)
verilator \
        -IVerilator_RTL \
        -I/home/vengineer/home/src/Flute/src_bsc_lib_RTL -Mdir Verilator_Make -O3 --x-assign fast --x-initial fast --noassert --stats -CFLAGS -O3 -CFLAGS -DVL_DEBUG --trace  -CFLAGS -DVM_TRACE --no-timing \
        --cc  --exe --build -j 4 -o exe_HW_sim  mkTop_HW_Side.v \
        --top-module mkTop_HW_Side \
        /home/vengineer/home/src/AWSteria_Infra/Platform_Sim/HW/Verilator_resources/sim_main.cpp \
        /home/vengineer/home/src/AWSteria_Infra/Platform_Sim/HW/C_Imported_Functions.c
%Error: Invalid option: --no-timing
make: *** [/home/vengineer/home/src/AWSteria_Infra/Platform_Sim/HW/Include_Verilator.mk:85: simulator] Error 1

verilatorのオプションで、--no-timing が無いと怒られます。これは、verilator v5でサポートされたオプションです。verilatorのバージョンを調べてみます。

$ which verilator
$ /usr/local/verilator/4.216/bin/verilator

v 4.216 なので、v5.002 のパスに変更します。

$ export PATH=/usr/local/verilator/v5.002/bin:${PATH}
$ make all
...
INFO: Created verilator executable:    exe_HW_sim

exe_HW_sim を実行します。ちょっと時間が経ってからログが出力され、(2: TOP.mkTop_HW_Side.rl_listen) で止まります。

$ /exe_HW_sim


INFO: TOP.mkTop_HW_Side.ddr_A
    base 0x0000000000000000  lim 0x0000000080000000    implemented 0x0000000080000000
INFO: TOP.mkTop_HW_Side.ddr_B
    base 0x0000000080000000  lim 0x0000000100000000    implemented 0x0000000080000000
================================================================
Bluespec AWSteria_Infra simulation v2.1
Copyright (c) 2020-2022 Bluespec, Inc. All Rights Reserved.
================================================================
INFO: Listening for connection from host-side on TCP port 30000
    (2: TOP.mkTop_HW_Side.rl_listen)

Host側のプログラムを実行します。

$ cd TestApp/Host/build_sim
$ ./exe_Host_sim
INFO: TestApp host-side built for simulation of Platform VCU118
    ddr_A_base = 0x               0  ddr_A_lim = 0x        80000000
    ddr_B_base = 0x        80000000  ddr_B_lim = 0x       100000000
    out_of_bounds_addr                         = 0x       100000000
Initializing AWSteria host-side API libs
tcp_client_open: connecting to '127.0.0.1' port 30000
tcp_client_open: Error calling connect()
ERROR: AWSteria_Host_init: failed
vengineer@LAPTOP-HGGR6RPK:~/home/src/AWSteria_Infra/TestApp/Host/build_sim$ ./exe_Host_sim
INFO: TestApp host-side built for simulation of Platform VCU118
    ddr_A_base = 0x               0  ddr_A_lim = 0x        80000000
    ddr_B_base = 0x        80000000  ddr_B_lim = 0x       100000000
    out_of_bounds_addr                         = 0x       100000000
Initializing AWSteria host-side API libs
tcp_client_open: connecting to '127.0.0.1' port 30000
tcp_client_open: connected
Filling wbuf with random data
    filled wbuf with random data

Performing tests ...

test0: ----------------
AXI4: Single-byte write, base_addr 0x0
AXI4: Single-byte read, base_addr 0x0

test0: ----------------
AXI4: Single-byte write, base_addr 0x80000000
AXI4: Single-byte read, base_addr 0x80000000

test50: ----------------
AXI4: Series of small writes/reads across first 128 bytes
    base_addr = 0x0
    at sizes 1, 2, 4, 8 bytes

test50: ----------------
AXI4: Series of small writes/reads across first 128 bytes
    base_addr = 0x80000000
    at sizes 1, 2, 4, 8 bytes

test60: ----------------
AXI4: write/read 0x2000 bytes, base_addr 0x0

test60: ----------------
AXI4: write/read 0x2000 bytes, base_addr 0x80000000

test60: ----------------
AXI4: write/read 0x1001 bytes, base_addr 0x5

test60: ----------------
AXI4: write/read 0x1001 bytes, base_addr 0x80000005

test70: ----------------
AXI4: write DDR_A (addr 0x0); data 0x0 to 0x100
AXI4: write DDR_B (addr 0x80000000); data 0x100 to 0x200
AXI4: read back DDR_A, testing that data was not overwritten
AXI4: read back DDR_B, testing that data was not overwritten

test80: ----------------
AXI4L: Series of 4 byte write/read across first 128 bytes

test90: ----------------
AXI4 write, AXI4-Lite read, base_addr 0x0
AXI4 write 128 bytes
AXI4L: readback 128 bytes

test100: ----------------

AXI4 write, AXI4-Lite read, base_addr 0x0
AXI4L write 128 bytes
AXI4: readback 128 bytes

test990: ----------------
AXI4: Single-byte write, out-of-bounds addr 0x100000000
NOTE: ERROR expected
----
AXI4: Single-byte read, out-of-bounds addr 0x100000000
NOTE: ERROR expected
ERROR: buf_read_AXI4: 1 bytes from addr 0x100000000
    FAILED: rc = 1

END OF TESTS; TEST STATS ----------------
num_ERRORS = 0
num_expected_ERRORS = 1
n_AXI4_reads  = 489, AXI4_read_bytes  = 26244
n_AXI4_writes = 490, AXI4_write_bytes = 26245
n_AXI4L_reads  = 64 (4 bytes each)
n_AXI4L_writes = 64 (4 bytes each)
----------------
Finalizing FPGA lib or simulation lib
AWSteria_Host_shutdown: closing TCP connection
tcp_client_close

HW側も再開して、終了します。

    (2: TOP.mkTop_HW_Side.rl_listen)
INFO: Accepted connection from host-side on TCP port 30000
    (23612169: TOP.mkTop_HW_Side.rl_accept)
23654216: ERROR: rl_wr_xaction_no_such_slave: m0 -> ?
    TOP.mkTop_HW_Side.awsteria_hw.fabric
        AXI4_Wr_Addr { awid: 'h0000, awaddr: 'h0000000100000000, awlen: 'h00, awsize: 'h6, awburst: 'h1, awlock: 'h0, awcache: 'h0, awprot: 'h0, awqos: 'h0, awregion: 'h0, awuser: 'h0 }
23654219: ERROR: rl_rd_xaction_no_such_slave: m0 -> ?
    TOP.mkTop_HW_Side.awsteria_hw.fabric
        AXI4_Rd_Addr { arid: 'h0000, araddr: 'h0000000100000000, arlen: 'h00, arsize: 'h6, arburst: 'h1, arlock: 'h0, arcache: 'h0, arprot: 'h0, arqos: 'h0, arregion: 'h0, aruser: 'h0 }
c_host_recv2: Connection closed by remote host

おわりに

とりあえず、ビルドとサンプルのコードは動くことは確認できました。

次は、中を調べてみます。