はじめに
今日は、今年(2023年)前半最後の有給休暇でお休みです。お暇なので、Bluespecのgithub を眺めていたら、面白いものがあったので調べてみたい思いました。
- BluespecのAWSteria_Infra
- The Open-Source Bluespec bsc Compiler and Resuable Example Designs(スライド)
- The Open-Source Bluespec bsc Compiler and Reusable Example Designs(論文)
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の環境を構築します。
を見てやってみました。
準備
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
おわりに
とりあえず、ビルドとサンプルのコードは動くことは確認できました。
次は、中を調べてみます。