読者です 読者をやめる 読者になる 読者になる

FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

HiFive1のでのArduinoプログラム コンパイル結果の解析

RISC-V

Arduinoのプログラムをコンパイルするとき、最初にターゲットボードを指定して、対応するGCCなどをインストールした。 GCCを利用しているはずなので、コンパイル結果やオブジェクトなどがどこかに生成されているはずだ。 調査してみると、以下のArduino IDEの設定をすることでコンパイル結果などの情報を出力することが可能らしい。

d.hatena.ne.jp

  1. Arduino IDE の [ファイル]>[環境設定] で、preference.txt の場所を確認する。

f:id:msyksphinz:20170311160523p:plain

  1. preference.txtを編集する。以下を追加した。
build.path=/home/masayuki/Arduino/
build.verbose=true

これでBlink.inoをコンパイルするとさまざまな情報が出力されるようになった。 実際に、Blink.inoをコンパイルすると、以下のようなビルドログが生成された。

/home/msyksphinz/work/software/arduino-1.8.1/arduino-builder -dump-prefs -logger=machine -hardware /home/msyksphinz/work/software/arduino-1.8.1/hardware -hardware /home/msyksphinz/.arduino15/packages -tools /home/msyksphinz/work/softwa-1.8.1/tools-builder -tools /home/msyksphinz/work/software/arduino-1.8.1/hardware/tools/avr -tools /home/msyksphinz/.arduino15/packages -built-in-libraries /home/msyksphinz/work/software/arduino-1.8.1/libraries -libraries /home/msyksphinz/Arduino/libraries -fqbn=sifive:riscv:hifive1:toolsloc=default,clksrc=hfxtal -ide-version=10801 -build-path /home/msyksphinz/Arduino -warnings=none -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.riscv32-unknown-elf-gcc.path=/home/msyksphinz/.arduino15/packages/sifive/tools/riscv32-unknown-elf-gcc/3f7b3696217548bc31aeccf9a0c89bdfa4e16a8f -prefs=runtime.tools.openocd.path=/home/msyksphinz/.arduino15/packages/sifive/tools/openocd/9bab0782d313679bb0bfb634e6e87c757b8d5503 -verbose /home/msyksphinz/Blink/Blink.ino
/home/msyksphinz/work/software/arduino-1.8.1/arduino-builder -compile -logger=machine -hardware /home/msyksphinz/work/software/arduino-1.8.1/hardware -hardware /home/msyksphinz/.arduino15/packages -tools /home/msyksphinz/work/software/arduino-1.8.1/tools-builder -tools /home/msyksphinz/work/software/arduino-1.8.1/hardware/tools/avr -tools /home/msyksphinz/.arduino15/packages -built-in-libraries /home/msyksphinz/work/software/arduino-1.8.1/libraries -libraries /home/msyksphinz/Arduino/libraries -fqbn=sifive:riscv:hifive1:toolsloc=default,clksrc=hfxtal -ide-version=10801 -build-path /home/msyksphinz/Arduino -warnings=none -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.riscv32-unknown-elf-gcc.path=/home/msyksphinz/.arduino15/packages/sifive/tools/riscv32-unknown-elf-gcc/3f7b3696217548bc31aeccf9a0c89bdfa4e16a8f -prefs=runtime.tools.openocd.path=/home/msyksphinz/.arduino15/packages/sifive/tools/openocd/9bab0782d313679bb0bfb634e6e87c757b8d5503 -verbose /home/msyksphinz/Blink/Blink.ino

このとき、/home/msyksphinz/Arduino/sketch/Blink.ino.cppが生成されていた。 確かに、ArduinoのプログラムはC/C++と非常に似通っているが、どこが異なるのだろう。

  • diff sketch/Blink.ino.cpp ~/work/software/arduino-1.8.1/examples/01.Basics/Blink/Blink.ino
1,3d0
< #include <Arduino.h>
< #line 1 "/home/masayuki/Blink/Blink.ino"
< #line 1 "/home/masayuki/Blink/Blink.ino"
28,32d24
< #line 25 "/home/masayuki/Blink/Blink.ino"
< void setup();
< #line 31 "/home/masayuki/Blink/Blink.ino"
< void loop();
< #line 25 "/home/masayuki/Blink/Blink.ino"
45d36
<

あんまり違わない。というかこれはcppを通過させただけのようにも見える。

そして、生成されたプログラムはすべてriscv64-unknown-elf-gccを使ってコンパイルされていた。

スケッチをコンパイルしています...
"/home/msyksphinz/.arduino15/packages/sifive/tools/riscv32-unknown-elf-gcc/3f7b3696217548bc31aeccf9a0c89bdfa4e16a8f/bin/riscv32-unknown-elf-g++" -c -O2 -march=rv32imac -fpeel-loops -ffreestanding -ffunction-sections -fdata-sections -fpermissive -Wall -fno-rtti -fno-exceptions -I/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/system/include -I/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/freedom-e-sdk/bsp/include -I/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/freedom-e-sdk/bsp/env -I/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/freedom-e-sdk/bsp/drivers -I/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/freedom-e-sdk/bsp/env/freedom-e300-hifive1 -include sys/cdefs.h -g -DARDUINO=10801 -DF_CPU=16000000LL -DFREEDOM_E300_HIFIVE1  "-I/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/cores/arduino" "-I/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/variants/standard" "/home/msyksphinz/Arduino/sketch/Blink.ino.cpp" -o "/home/msyksphinz/Arduino/sketch/Blink.ino.cpp.o"
...
Linking everything together...
"/home/msyksphinz/.arduino15/packages/sifive/tools/riscv32-unknown-elf-gcc/3f7b3696217548bc31aeccf9a0c89bdfa4e16a8f/bin/riscv32-unknown-elf-g++" -T /home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/freedom-e-sdk/bsp/env/freedom-e300-hifive1/link.lds -nostartfiles -Wl,-N -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--wrap=sbrk  "/home/msyksphinz/Arduino/sketch/Blink.ino.cpp.o" -nostdlib -Wl,--start-group "/home/msyksphinz/Arduino/core/core.a" -lm -lstdc++ -lc -lgloss -Wl,--end-group -lgcc -o "/home/msyksphinz/Arduino/Blink.ino.elf"
"/home/msyksphinz/.arduino15/packages/sifive/tools/riscv32-unknown-elf-gcc/3f7b3696217548bc31aeccf9a0c89bdfa4e16a8f/bin/riscv32-unknown-elf-objcopy" -R .rel.dyn -O binary "/home/msyksphinz/Arduino/Blink.ino.elf" "/home/msyksphinz/Arduino/Blin.ino.bin"
"/home/msyksphinz/.arduino15/packages/sifive/tools/riscv32-unknown-elf-gcc/3f7b3696217548bc31aeccf9a0c89bdfa4e16a8f/bin/riscv32-unknown-elf-objcopy" -R .rel.dyn -O srec "/home/msyksphinz/Arduino/Blink.ino.elf" "/home/msyksphinz/Arduino/Blink.ino.hex"
最大8388608バイトのフラッシュメモリのうち、スケッチが6932バイト(0%)を使っています。

Arduino/Blink.ino.elf をobjdumpすれば、大体中身が分かる。さらに、/home/msyksphinz/.arduino15/packages/sifive/hardware/riscv/1.0.2/freedom-e-sdk/bsp/env/freedom-e300-hifive1/link.ldsに格納されているリンカスクリプトを見れば、HiFive1のメモリアドレスマップも大体分かるわけだ。

riscv64-unknown-elf-objdump -D Blink.ino.elf  | less
20400000 <_start>:
20400000:       5fc01197                auipc   gp,0x5fc01
20400004:       c2818193                addi    gp,gp,-984 # 80000c28 <_gp>
20400008:       5fc04117                auipc   sp,0x5fc04
2040000c:       ff810113                addi    sp,sp,-8 # 80004000 <_sp>
20400010:       00001517                auipc   a0,0x1
20400014:       eac50513                addi    a0,a0,-340 # 20400ebc <__fini_array_end>
20400018:       5fc00597                auipc   a1,0x5fc00
2040001c:       fe858593                addi    a1,a1,-24 # 80000000 <_data>
20400020:       5fc00617                auipc   a2,0x5fc00
20400024:       41460613                addi    a2,a2,1044 # 80000434 <__bss_start>
20400028:       00c5fa63                bleu    a2,a1,2040003c <_start+0x3c>
2040002c:       00052283                lw      t0,0(a0)
...

HiFive1 の環境セットアップとサンプル実行

RISC-V

HiFive1の実行環境を早速構築しよう。まずはすでにHiFiveを使っている方がいらっしゃるので、それを参考に。

qiita.com

HiFive1の実行のためには、Arduino IDEをインストールする必要がある。僕はWindowsユーザなのでWindowsにインストールしようと思ったが、どうやらツールチェインがWindowsでは実行できないようだ。

確かに、RISC-VのGCCなど、Windows版は存在しないしなあ。

f:id:msyksphinz:20170311114042p:plain

そこでUbuntu Linux仮想マシンで立ち上げ、Arduino IDEをインストールした。 こちらだと、ツールチェインもダウンロードできる。

f:id:msyksphinz:20170311114134p:plain

f:id:msyksphinz:20170311114128p:plain

HiFive1ボードを接続して認識させる

HiFive1のボードを、仮想マシンとして実行されているUbuntuに接続しなければならないのだが、これはVirtualBoxの設定で、USBをUbuntu側に認識させる。 FTDI Dual RS232-HSを追加すれば良いのかな。

f:id:msyksphinz:20170311114231p:plain

さらに、dmesgでデバイスを確認する。

$ dmesg | tail
[157958.226380] usbserial: USB Serial support registered for generic
[157958.245744] usbcore: registered new interface driver ftdi_sio
[157958.245781] usbserial: USB Serial support registered for FTDI USB Serial Device
[157958.245814] ftdi_sio 1-3:1.0: FTDI USB Serial Device converter detected
[157958.245838] usb 1-3: Detected FT2232H
[157958.259902] usb 1-3: FTDI USB Serial Device converter now attached to ttyUSB0
[157958.261143] ftdi_sio 1-3:1.1: FTDI USB Serial Device converter detected
[157958.261183] usb 1-3: Detected FT2232H
[157958.268871] usb 1-3: FTDI USB Serial Device converter now attached to ttyUSB1
[screen is terminating]: reset full-speed USB device number 6 using ohci-pci

tt-y-USB1として追加された。まずは、Arduinoとして起動するメッセージをコンソールから見てみよう。

下記を実行して、HiFive1上のリセットボタン(赤色)を押す。

screen /dev/ttyUSB1  115200

f:id:msyksphinz:20170311115031p:plain

起動した。

LED Blinkの例を動かしてみる

Lチカの例を実行してみる。こちらもQittaで既に行われているものだが、とりあえず真似事としてやってみた。

qiita.com

f:id:msyksphinz:20170311115159p:plain

サンプルを開き、「書き込み装置を使って書き込む」を実行する。

f:id:msyksphinz:20170311115251g:plain

動いた!

f:id:msyksphinz:20170311120843p:plain

RISC-VのArduino(HiFive)が我が家にやってきたよ

RISC-V

マルツオンラインが、RISC-VのArduinoボード、HiFive1を取り扱い始めた。

www.marutsu.co.jp

これまで海外で購入可能だったが、海外サイトでわざわざ購入するのが億劫で買っていなかったのだが、マルツだと安心。 購入して即日で届く速さだった。

まだ開封しただけで、ソフトウェアの環境などは用意していないが、ボチボチ構築していこう。

さて、これで何して遊ぼうかな(買ったは良いが何をするか決めていない)。

f:id:msyksphinz:20170307010142p:plain

f:id:msyksphinz:20170307010200p:plain

OpenSPARC T1の調査(7. S1coreでDhrystoneを動作させたい)

S1coreとOpenSPARC T1純正環境との差分は引き続き調査中だ。 とりあえず、S1coreを使いこなせるようになりたい。 まずはベンチマークプログラムを動作させられるようにしたい。Coremarkが動けば面白いのだが、まずはDhrystoneかな。

Dhrystoneは、CPUの基本性能を知るための最も基礎的なベンチマークプログラムだ。

Dhrystone - Wikipedia

S1coreでプログラムを動作させるためには

前回少し解説したが、S1coreでベンチマークプログラムを動作させるためには、以下の2つのファイルを用意する必要がある。

  • rom_harness.hex : リセット後のブート動作を行うためのプログラム。main()に入る直前まで。
  • ram_harness.hex : main()以降のプログラムを格納している。

まずは、S1coreのリリース群に入っているスクリプトを確認して、何をしなければならないのかを確認しよう。

$ less ./tools/bin/compile_test
...
# Compile the boot code
sparc64-linux-gnu-as -ah -am -o boot/boot.bin boot/boot.s
sparc64-linux-gnu-objdump -d -EB -w -z boot/boot.bin > boot/boot.dump
grep "  " boot/boot.dump | egrep -v "elf64-sparc" | dump2hex.bin > boot/rom_harness.hex

# Compile the C test
sparc64-linux-gnu-gcc -c -O0 $1.c
sparc64-linux-gnu-ld -Ur --script=$S1_ROOT/tools/src/linker.map -EB -o $1.bin $1.o
sparc64-linux-gnu-objdump -d -EB -w -z $1.bin > $1.dump
grep "  " $1.dump | egrep -v "elf64-sparc" | dump2hex.bin > ram_harness.hex

基本的にsparcgccを使ってコンパイルし、リンカはlinker.mapを使っている。これはDhrystoneも同じものを使えばよかろう。 このコンパイル手順をDhrystoneにも適用すれば良いと思われる。

Dhrystoneのコードは以下からダウンロードした。

fossies.org

Makefileの編集を行う。

CC=      sparc64-linux-gnu-gcc           # C compiler name goes here (UNIX)
GCC=        sparc64-linux-gnu-gcc
...

CFLAGS= $(OPTIMIZE) $(TIME_FUNC) -DHZ=$(HZ) $(ENUMS) $(STRUCTASSIGN) $(CFL) -Ur -Xlinker --script=/home/masayuki/work/s1_core_opensparc_t1/s1_core/tools/src/linker.map -Xlinker -EB -lc
GCCFLAGS= $(GCCOPTIM) $(TIME_FUNC) -DHZ=$(HZ) $(ENUMS) $(STRUCTASSIGN) $(CFL) -Ur -Xlinker --script=/home/masayuki/work/s1_core_opensparc_t1/s1_core/tools/src/linker.map -Xlinker -EB -lc

さらに、cc_dhryを作成した後に、hexファイルを生成する手順も追加した。

cc_dry2:     $(SRC) $(HDR)
        $(CC) $(CFLAGS) $(SRC) $(LFLAGS) -o $@
        sparc64-linux-gnu-objdump -d -EB -w -z $@ > $@.dump
        grep "  " $@.dump | egrep -v "elf64-sparc" | dump2hex.bin > ram_harness.hex

これで、Dhrystoneのディレクトリにram_harness.hexが生成される。これを既存のs1_core/test/ram_harness.hex (hello.cから生成したもの)と置き換えてシミュレーションを走らせて見ればよい。

OpenSPARC T1の調査(7. OpenSPARC T1の外部ポート制約)

S1coreの動作方法が分かってきたのだが、S1coreとOpenSPARC T1のコアは分離されているが、SPARCコアの部分は共通のものを利用しているので、使いようがあるはずだ。

S1coreの起動方法をトレースすると、OpenSPARC T1も動作させることが出来るに違いないと思い、S1Coreの動作方法について調査を行った。

S1coreは以下のような階層構成を取っている。

f:id:msyksphinz:20170307005317p:plain

ここでsparc_0と表記されているのがOpenSPARCのコア1つ分で、それを包んでいるのがs1_top_0という階層になる。

ここでは、以下の外部ポートが制約されており、駆動しないようになっている。

  • s1_top.v
  /*
   * Continuous assignments
   */

  assign const_cpuid = 4'h0;
  assign const_maskid = 8'h20;

  // sscan
  assign ctu_tck = 1'b0;
  assign ctu_sscan_se = 1'b0;
  assign ctu_sscan_snap = 1'b0;
  assign ctu_sscan_tid = 4'h1;

  // bist
  assign ctu_tst_mbist_enable = 1'b0;

  // efuse
  assign efc_spc_fuse_clk1 = 1'b0;     // Activity
  assign efc_spc_fuse_clk2 = 1'b0;     // Activity
  assign efc_spc_ifuse_ashift = 1'b0;
  assign efc_spc_ifuse_dshift = 1'b0;
  assign efc_spc_ifuse_data = 1'b0;    // Activity
  assign efc_spc_dfuse_ashift = 1'b0;
  assign efc_spc_dfuse_dshift = 1'b0;
  assign efc_spc_dfuse_data = 1'b0;    // Activity

  // scan and macro test
  assign ctu_tst_macrotest = 1'b0;
  assign ctu_tst_scan_disable = 1'b0;
  assign ctu_tst_short_chain = 1'b0;
  assign global_shift_enable = 1'b0;
  assign ctu_tst_scanmode = 1'b0;
  assign spc_scanin0 = 1'b0;
  assign spc_scanin1 = 1'b0;

これをOpenSPARC側にも移植すれば良いのではないか?ということで移植して際シミュレーションしてみたのだが、どうやらそれだけではSPCパケットはまだ発行されない。

まだリセット解除に問題があるようだ。

OpenSPARC T1の調査(6. S1coreのSPC⇔WishBoneの構成)

OpenSPARC T1のインタフェースは、どうやらSPARC固有のパケットを使って通信しているらしい。 このパケットを分解して、S1Coreに搭載されているWishBoneに載せ変えているのがSPC2WBMユニットだ。

インタフェースは以下のようになっており、SPARCのパケットを受信してWishBoneへの変換ステートマシンが搭載されている。

インタフェース名 接続信号
Top-level system inputs sys_clock_i sys_clock_i
sys_reset_i sys_reset_final
sys_interrupt_source_i sys_interrupt_source
Bridge inputs connected to SPARC Core outputs spc_req_i spc_pcx_req_pq
spc_atom_i spc_pcx_atom_pq
spc_packetout_i spc_pcx_data_pa
Bridge outputs connected to SPARC Core inputs spc_grant_o pcx_spc_grant_px
spc_ready_o cpx_spc_data_rdy_cx2
spc_packetin_o cpx_spc_data_cx2
spc_stall_o wbm_spc_stall
spc_resume_o wbm_spc_resume
Top-level Wishbone Interconnect inputs wbm_ack_i wbm_ack_i
wbm_data_i wbm_data_i
Top-level Wishbone Interconnect outputs wbm_cycle_o wbm_cycle_o
wbm_strobe_o wbm_strobe_o
wbm_we_o wbm_we_o
wbm_addr_o wbm_addr_o
wbm_data_o wbm_data_o
wbm_sel_o wbm_sel_o

SPARCの命令フェッチパケットの構成

  • spc_pcx_req_pq[4:0] : processor to pcx request
  • spc_pcx_atom_pq : processor to pcx atomic request
  • spc_pcx_data_pa[123:0] : processor to pcx packet

ちなみに、T1のパケットは以下のような124ビットの構成であり、図に起こすとさらに以下のような図になる。

#define PCX_VLD         123  //PCX packet valid
#define PCX_RQ_HI       122  //PCX request type field
#define PCX_RQ_LO       118
#define PCX_NC          117  //PCX non-cacheable bit
#define PCX_R           117  //PCX read/!write bit
#define PCX_CP_HI       116  //PCX cpu_id field
#define PCX_CP_LO       114
#define PCX_TH_HI       113  //PCX Thread field
#define PCX_TH_LO       112
#define PCX_BF_HI       111  //PCX buffer id field
#define PCX_INVALL      111
#define PCX_BF_LO       109
#define PCX_WY_HI       108  //PCX replaced L1 way field
#define PCX_WY_LO       107
#define PCX_P_HI        108  //PCX packet ID, 1st STQ - 10, 2nd - 01
#define PCX_P_LO        107
#define PCX_SZ_HI       106  //PCX load/store size field
#define PCX_SZ_LO       104
#define PCX_ERR_HI      106  //PCX error field
#define PCX_ERR_LO      104
#define PCX_AD_HI       103  //PCX address field
#define PCX_AD_LO        64
#define PCX_DA_HI        63  //PCX Store data
#define PCX_DA_LO         0

f:id:msyksphinz:20170304115954p:plain

詳細は省略するが、内部にステートマシンが組まれており、SPARCのパケットをWishBoneに変換している。

OpenSPARC T1の調査(5. S1coreをModelSimで動かす環境の構築)

OpenSPARC T1のラッパーであるS1Coreは、デフォルトではVcsもしくはIcarus Verilogで動作するようになっているが、これらで動作するのだったらModelsim Starter Editionでも動作するはずだ。 デバッグにあたり、やはりModelSimの方が簡単なので、Modelsimへの環境を以降しておこう。

まずは、S1Coreのためのリポジトリを作成した。

github.com

環境変数の設定

S1Coreの環境変数では、S1CoreそのものとOpenSPARC T1の場所を設定する必要がある。 これに加えて、ModelSim用のファイルリストを作成する記述を追加した。

  • s1_core/sourceme
diff --git a/s1_core/sourceme b/s1_core/sourceme
index 8f8d03b..01112cb 100755
--- a/s1_core/sourceme
+++ b/s1_core/sourceme
@@ -6,6 +6,7 @@ export PATH=.:$S1_ROOT/tools/bin:$PATH

 # Filelist names
 export FILELIST_ICARUS=$S1_ROOT/hdl/filelist.icarus
+export FILELIST_QUESTA=$S1_ROOT/hdl/filelist.questa
 export FILELIST_VCS=$S1_ROOT/hdl/filelist.vcs
 export FILELIST_FPGA=$S1_ROOT/hdl/filelist.fpga
 export FILELIST_DC=$S1_ROOT/hdl/filelist.dc

さらに、build_questa および run_questaを作成した。

  • build_questa
#!/bin/bash

if [ -z "$S1_ROOT" ]; then echo "***ERROR***: S1_ROOT variable is undefined, please set it and run 'source sourceme'."; exit 1; fi
if ! [ -d "$S1_ROOT" ]; then echo "***ERROR***: directory '$S1_ROOT' does not exist, please check it and run 'source sourceme' again."; exit 1; fi

echo "Building testbench using QuestaSim simulator..."
mkdir -p $S1_ROOT/run/sim/questa
cd $S1_ROOT/run/sim/questa
# rm -rf *
vlib worklib
vlog -work worklib -f $FILELIST_QUESTA
echo -e "Done!"
  • run_questa
#!/bin/bash

if [ -z "$S1_ROOT" ]; then echo "***ERROR***: S1_ROOT variable is undefined, please set it and run 'source sourceme'."; exit 1; fi
if ! [ -d "$S1_ROOT" ]; then echo "***ERROR***: directory '$S1_ROOT' does not exist, please check it and run 'source sourceme' again."; exit 1; fi

cd $S1_ROOT/run/sim/questa
ln -f -s $S1_ROOT/tests/boot/rom_harness.hex .
ln -f -s $S1_ROOT/tests/ram_harness.hex .

vsim -c worklib.testbench -voptargs="+acc" -l sim.log -do "run -all; quit"
echo "Simulation completed!"
echo "To see the output:"
echo "        less $S1_ROOT/run/sim/questa/sim.log"
echo "Too watch the waveforms:"
echo "        gtkwave $S1_ROOT/run/sim/questa/trace.vcd"

動作させるプログラムをコンパイル

S1Coreのリポジトリにはhello.cというサンプルプログラムが用意されているが、これを動作させるためにはもちろんSparcコンパイラコンパイルしなければならない。

  • tests/hello.c
// Sample program that writes two words at a predefined address

int main() {
  unsigned long* address;
  address = (unsigned long*)0x0000CAC0;
  (*address) = 0xC1A0C1A0;  // First store
  address = (unsigned long*)0x0000CAC0;
  (*address) = 0xFABA1210;  // Second store
  return 0;
}

このためにUbuntuのパッケージとしてgcc-sparc64-linux-gnuをインストールした。

sudo aptitude install -y gcc-sparc64-linux-gnu

そしてcompile_testコマンドをいくつか改造する必要がある。 と言っても、sparc64-linux-sparc64-linux-gnu-に変更しただけだ。

  • compile_test
diff --git a/s1_core/tools/bin/compile_test b/s1_core/tools/bin/compile_test
index 5684c25..060ab69 100755
--- a/s1_core/tools/bin/compile_test
+++ b/s1_core/tools/bin/compile_test
@@ -6,7 +6,7 @@
 # Parameter is test name without extension (e.g. to compile
 # $S1_ROOT/tests/hello.c) just run "compile_test hello".
 #
-# Note: requires sparc64-linux-gcc (see Download section on
+# Note: requires sparc64-linux-gnu-gcc (see Download section on
 # http://www.srisc.com).

 if [ -z "$S1_ROOT" ]; then echo "***ERROR***: S1_ROOT variable is undefined, please set it and run 'source sourceme'."; exit 1; fi
@@ -32,15 +32,14 @@ fi
 gcc -o $S1_ROOT/tools/bin/dump2hex.bin $S1_ROOT/tools/src/dump2hex.c

 # Compile the boot code
-sparc64-linux-as -ah -am -o boot/boot.bin boot/boot.s
-sparc64-linux-objdump -d -EB -w -z boot/boot.bin > boot/boot.dump
-grep "  " boot/boot.dump | egrep -v "file format" | dump2hex.bin > boot/rom_harness.hex
+sparc64-linux-gnu-as -ah -am -o boot/boot.bin boot/boot.s
+sparc64-linux-gnu-objdump -d -EB -w -z boot/boot.bin > boot/boot.dump
+grep "  " boot/boot.dump | egrep -v "elf64-sparc" | dump2hex.bin > boot/rom_harness.hex

 # Compile the C test
-sparc64-linux-gcc -c -O0 $1.c
-sparc64-linux-ld -Ur --script=$S1_ROOT/tools/src/linker.map -EB -o $1.bin $1.o
-sparc64-linux-objdump -d -EB -w -z $1.bin > $1.dump
-grep "  " $1.dump | egrep -v "file format" | dump2hex.bin > ram_harness.hex
+sparc64-linux-gnu-gcc -c -O0 $1.c
+sparc64-linux-gnu-ld -Ur --script=$S1_ROOT/tools/src/linker.map -EB -o $1.bin $1.o
+sparc64-linux-gnu-objdump -d -EB -w -z $1.bin > $1.dump
+grep "  " $1.dump | egrep -v "elf64-sparc" | dump2hex.bin > ram_harness.hex

 #rm -f *.o *~ *.bin *.dump           # Make clean
-

最初は何のことだか分からなかったのだが、以下のfile formatを除去するのは、dumpファイルの先頭行を除去したいようなのだが、環境変数が日本語だと違う文字列になってしまうので、共通のelf64-sparcに変更した。

-grep "  " $1.dump | egrep -v "file format" | dump2hex.bin > ram_harness.hex
+grep "  " $1.dump | egrep -v "elf64-sparc" | dump2hex.bin > ram_harness.hex

これで、build_questa && run_questarun/sim/questa/にシミュレーションログが出力された。 正しく動作しているようだ。

cd run/sim/questa
less sim.log

...
# INFO: MEMH testbench.ram_harness: R @             35410000 ns, AD=0800000000040018 SEL=ff DAT=8410a1a0c4704000
# INFO: WBM2SPC: *** RETURN PACKET TO SPARC CORE ***
# INFO: WBM2SPC: Valid bit is 1
# INFO: WBM2SPC: Return Packet of Type IFILL_RET
# INFO: WBM2SPC: L2 Miss is 0
# INFO: WBM2SPC: Error is 0
# INFO: WBM2SPC: Non-Cacheable bit is 1
# INFO: WBM2SPC: Thread is 0
# INFO: WBM2SPC: Way Valid is 0
# INFO: WBM2SPC: Replaced L2 Way is 0
# INFO: WBM2SPC: Fetch for Boot is 0
# INFO: WBM2SPC: Atomic LD/ST or 2nd IFill Packet is 1
# INFO: WBM2SPC: PFL is 0
# INFO: WBM2SPC: Data is c25fa7f7053068308410a1a0c4704000
# INFO: TBENCH: Completed Simply RISC S1 Core simulation!
# ** Note: $finish    : /home/masayuki/work/s1_core_opensparc_t1/s1_core/hdl/behav/testbench/testbench.v(94)
#    Time: 50 us  Iteration: 0  Instance: /testbench
# End time: 01:15:23 on Mar 04,2017, Elapsed time: 0:09:38
# Errors: 0, Warnings: 43

f:id:msyksphinz:20170304014111p:plain