FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RISC-VのSupervisor Binary Interface(SBI)について

RISC-Vのハイパーバイザについて調べているとき登場したが、Supervisor Binary Interface(SBI)というものが定義されている。

f:id:msyksphinz:20181030225822p:plain

詳細はRISC-V SBI specificationに説明がされている。

SBIというのはスーパバイザ実行環境(Supervisor Execution Environment)で実行できる機能群を示している。 SBIはBerkeley Boot Loader(BBL)上で実装されており、以下のSBIコールが定義されている。

Type Function Function ID
Timer sbi_set_timer 0
IPI sbi_clear_ipi
sbi_send_ipi
3
4
Memory Model sbi_remote_fence_i
sbi_remote_sfence_vma
sbi_remote_sfence_vma_asid
5
6
7
Console sbi_console_putchar
sbi_console_getchar
1
2
Shutdown sbi_shutdown 8

ここからは、それぞれのSBIコールの中身を、riscv-pk/machine/mtrap.cから観測していく。

タイマー

void sbi_set_timer(uint64_t stime_value)
  • mtrap.c
void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc)
{
...
    case SBI_SET_TIMER:
#if __riscv_xlen == 32
      retval = mcall_set_timer(arg0 + ((uint64_t)arg1 << 32));
#else
      retval = mcall_set_timer(arg0);
#endif
      break;
...
}

static uintptr_t mcall_set_timer(uint64_t when)
{
  *HLS()->timecmp = when;
  clear_csr(mip, MIP_STIP);
  set_csr(mie, MIP_MTIP);
  return 0;
}

IPI (Inter processor Interrupt)

他のプロセッサへの割り込み処理は、HLSというメモリ空間を使用して実行するらしい。

void sbi_send_ipi(const unsigned long *hart_mask)
  • mtrap.c
void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc)
{
...
    case SBI_SEND_IPI:
      ipi_type = IPI_SOFT;
      goto send_ipi;
...
send_ipi:
      send_ipi_many((uintptr_t*)arg0, ipi_type);
...
}

static void send_ipi(uintptr_t recipient, int event)
{
  if (((disabled_hart_mask >> recipient) & 1)) return;
  atomic_or(&OTHER_HLS(recipient)->mipi_pending, event);
  mb();
  *OTHER_HLS(recipient)->ipi = 1;
}
  • mtrap.h
// hart-local storage, at top of stack
#define HLS() ((hls_t*)(MACHINE_STACK_TOP() - HLS_SIZE))
#define OTHER_HLS(id) ((hls_t*)((void*)HLS() + RISCV_PGSIZE * ((id) - read_const_csr(mhartid))))

メモリモデル

sfenceによるメモリのバリアも、マルチコアで同期をとる必要があるためIPIを使って割り込みを出している。

  • mtrap.c
void sbi_remote_fence_i(const unsigned long *hart_mask)
void sbi_remote_sfence_vma(const unsigned long *hart_mask,
                           unsigned long start,
                           unsigned long size)
void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
                                unsigned long start,
                                unsigned long size,
                                unsigned long asid)

コンソール

putchar()getchar()である。これは普通にメモリストアして文字を書き出したりメモリリードして文字を読み取る。

static uintptr_t mcall_console_putchar(uint8_t ch)
{
  if (uart) {
    uart_putchar(ch);
  } else if (htif) {
    htif_console_putchar(ch);
  }
  return 0;
}

static uintptr_t mcall_console_getchar()
{
  if (uart) {
    return uart_getchar();
  } else if (htif) {
    return htif_console_getchar();
  } else {
    return '\0';
  }
}

Shutdown

シャットダウン用のSBIも定義されている。これも単純にfinisherとして定義されたメモリ位置を操作するだけである。

void poweroff(uint16_t code)
{
  printm("Power off\n");
  finisher_exit(code);
  if (htif) {
    htif_poweroff();
  } else {
    while (1);
  }
}

void finisher_exit(uint16_t code)
{
  if (!finisher) return;
  if (code == 0) {
    *finisher = FINISHER_PASS;
  } else {
    *finisher = code << 16 | FINISHER_FAIL;
  }
}

RISC-Vのハイパーバイザ仕様について調べる(2. ハイパーバイザのCSRとアドレス変換について)

RISC-Vのハイパーバイザの仕様について調査中。前回の続き。

参考にしているのは、 RISC-V ISA Manualの最新版(正式リリース版ではなくDraft版。こちらにはハイパーバイザの仕様案が含まれている)。

github.com

また、RISC-VのSBI(Supervisor Binary Interface)については以下を参考にする。こちらも時間を見つけて読み込んでいく。

github.com

以下の文章はRISC-V ISA Manual Draft をベースにしていますが、直訳ではありません。 また、ブログ著者の知識不足のため多分に間違いが入っている可能性があります。 間違いを見つけましたらご指摘いただけますとうれしく思います。

まだ途中だけれど、追記もしくは別のエントリ作成予定。

5.2.3 Hypervisor Guest Address Translation and Protection Register(hgatp)

hgatpはsatp命令と同様に、ゲスト物理アドレスのアドレス変換の起点となるレジスタである。このレジスタの値をベースに、ゲスト物理アドレスの変換が行われる。

f:id:msyksphinz:20181029225811p:plain

ForegroundとBackgroundで切り替えられるCSRについて

以下のレジスタについては、ForegroundとBackgroundでレジスタの値が切り替えられる。

Foreground Background
Supervisor Status Register sstatus bsstatus
Supervisor Interrupt Registers sip / sie bsip / bsie
Supervisor Trap Vector Base Address Register stvec bstvec
Supervisor Scratch Register sscratch bsscratch
Supervisor Exception Program Counter sepc bsepc
Supervisor Cause Register scause bscause
Supervisor Trap Value Register stval bstval
Supervisor Address Translation and Protection Register satp bsatp

5.3 ハイパーバイザの命令について

HS-modeでは、以下の2つの命令が追加される。

  • HFENCE.GVMA
    • SFENCE.VMA命令とほぼ同一の命令だが、hgatpレジスタにより制御されるゲスト物理メモリ管理データ構造に対して適用されることが異なる。
    • この命令が実行されると、HFENCE.GVMAよりも前のすべての暗黙的あゲスト物理メモリデータ構造への参照は、HFENCE.GVMAよりも後続の命令よりも前に実行されることが保証される。
  • HFENCE.BVMA
    • SFENCE.VMA命令とほぼ同一の命令だが、bsatpレジスタにより制御されるVSレベルメモリ管理データ構造に対して適用されることが異なる。
    • この命令が例外なく実行されると、一時的にVS-modeに入ってSFENCE.VMA命令が実行されたものと同様の効果がある。

hgatp.VMIDが異なるHFENCE.BVMAが実行されても、メモリアクセスの順番は守られる必要が無い。 オペランドrs1が0でないならば、ゲスト仮想アドレスが設定される。 オペランドrs2が0でないならば、ゲストのアドレス空間識別子(ASID)が設定される。

5.5 2レベルアドレス変換

ハイパーバイザモード(V=1)の時は、メモリアドレスは2レベルのアドレス変換が行われる。

  1. オリジナル仮想アドレス→ゲスト物理アドレス (VSレベルのsatpレジスタによって制御される)
  2. ゲスト物理アドレス → スーパバイザ物理アドレス (hgatpレジスタによって制御される)
f:id:msyksphinz:20181029232502p:plain
  1. のオリジナル仮想アドレス→ゲスト物理アドレスは通常のSv32, Sv39, Sv48を使って変換が行われるが、2.は別の変換アルゴリズム(Sv32x4, Sv39x4, Sv48x4)を使って変換が行われる。 これはSv32, Sv39, Sv48に対して入力アドレスが2ビットほど拡張されており、ページのサイズが4kBから16kBに拡張されている(ただしこの理由は良く分からない)。

このページ変換アルゴリズムは、SV32, Sv39, Sv48とほぼ同様である(と思う)。

f:id:msyksphinz:20181030004017p:plain

RISC-Vのハイパーバイザ仕様について調べる(1. ハイパーバイザのモードと主要システムレジスタについて)

RISC-V Day Tokyo 2018にも出てきたハイパーバイザ仕様、はっきり言って自分にはさっぱり理解できなかった。 そもそもハイパーバイザの知識が無さすぎるので、これが良い機会なので一から勉強してみることにする。

参考にしているのは、 RISC-V ISA Manualの最新版(正式リリース版ではなくDraft版。こちらにはハイパーバイザの仕様案が含まれている)。

github.com

また、RISC-VのSBI(Supervisor Binary Interface)については以下を参考にする。こちらも時間を見つけて読み込んでいく。

github.com

以下の文章はRISC-V ISA Manual Draft をベースにしていますが、直訳ではありません。 また、ブログ著者の知識不足のため多分に間違いが入っている可能性があります。 間違いを見つけましたらご指摘いただけますとうれしく思います。

まだ途中だけれど、追記もしくは別のエントリ作成予定。


ハイパーバイザ拡張, Version 0.2-draft

Type-1とType-2のハイパーバイザをサポートするための命令セット仕様。

  • Type-1のハイパーバイザとは

ハイパーバイザ - Wikipedia

ハイパーバイザがハードウェア上で直接動作し、全てのOS(ゲストOS)はそのハイパーバイザ上で動作する方式を指す。狭義の「ハイパーバイザ」はこちらのみを指す。

https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Diagramme_ArchiHyperviseur.png/300px-Diagramme_ArchiHyperviseur.png

  • Type-2のハイパーバイザとは

ハイパーバイザ - Wikipedia

ハードウェア上でまず別のOSが稼働し(このOSをホストOSと呼ぶ)、その上でハイパーバイザが(ホストOSのアプリケーションとして)稼働し、更にはハイパーバイザの上で更に別のOS(このOSをゲストOSと呼ぶ)を稼働させる方法である。狭義においては、Type 2はハイパーバイザには含まれない。

https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Diagramme_ArchiEmulateur.png/300px-Diagramme_ArchiEmulateur.png

RISC-V のハイパーバイザ

ハイパーバイザの構成

ハイパーバイザがサポートされている場合、RISC-Vのスーパバイザモードは、

  • Hypervisor-extended Supervisor Mode(HS-Modeもしくは単純にハイパーバイザモード)

となる。

また、ハイパーバイザ拡張のために、"Guest Physical Address"から、スーパーバイザ物理アドレスへの変換機構が新たに定義される。

HS-ModeはS-Modeと同様の動作をするが、HS-Modeでの命令動作とCSRは上記のアドレス変換を行うことにより、ゲストOSを仮想S-Mode(VS-Mode)で動作するように制御が行われる。

通常のオペレーティングシステムはS-Modeで動作するようになっているが、HS-ModeとVS-Modeは同様に動作できるように定義される。

HS-Modeでは、OSもしくはハイパーバイザはRISC-VのSBI(Supervisor Binary Interface)を用いて互いに制御が行われる。HS-ModeのハイパーバイザはVS-ModeのゲストのためにSBIが実装されていることが想定されている。

f:id:msyksphinz:20181029010031p:plain

ハイパーバイザサポート時のmisaレジスタ

ハイパーバイザが実装されている場合、CSRmisaレジスタの7ビット目が1に設定される。また、ハイパーバイザが実装されている実装でも、misaの7ビット目をハードウェア的に0に設定されることは推奨されず、無効にできるようにすべきである。

※注釈1. Privileged Architectureはクラシックな仮想化の技術、つまりゲストOSがユーザレベルで動作し、いくつかのPrivileged命令が実行されると簡単に例外が検出できる、という構成に対して設計されている。ハイパーバイザ拡張は、これらの頻発される例外にを削減して、性能を向上させるために設計されている。

※注釈2. ハイパーバイザ拡張は、ハイパーバイザ拡張が実装されていないプラットフォームでも、この拡張を効率的にエミュレートできるように実装されている。つまり、ハイパーバイザがSモードで実行されて、ハイパーバイザのCSRへのアクセスにより例外が発生してM-Modeに移行し、Shadow Page Tableを管理する必要になる場合である。Type-2ハイパーバイザのCSRアクセスの大半はS-Modeでも違反ではなく、したがって例外は発生しない。ハイパーバイザは同様にネストされた仮想化にも対応できる。

5.1 ハイパーバイザ

仮想モード(Virtualization Mode, Vビット)により、現在のHartがゲストとして実行されているのかどうかを判定する。

  • V=1 : 仮想S-Mode(VS-Mode), 仮想U-Mode(VU-Mode)で動作している。これはゲストOS上で動作していることを意味する。また、V=1の場合は2レベルアドレス変換が有効である。
  • V=0 : M-Mode, HS-Mode, HS-Mode下のOS上で動作しているU-Modeのどれかである。
f:id:msyksphinz:20181029004754p:plain

5.2 ハイパーバイザCSR

ハイパーバイザにおけるバックグラウンドCSR、フォアグラウンドCSRの役割

HS-Mode上で動作するOSとハイパーバイザは、例外と割り込み、アドレス変換を処理するためにスーパバイザCSRを使用する。CSRはHS-Modeモード上で実装されており、VS-Modeで実装されていない。しかし、VS-Modeの2レベルアドレス変換と動作の制御を管理するために使用させる。これらは、hstatus, hedeleg, hideleg, hgatpとする。

「バックグラウンド」のスーパバイザCSRは、いくつかの存在している「フェアグラウンド」スーパバイザのコピーである。例えば、bsstatusCSRsstatusのコピーである。仮想モードが切り替わるとき、バックグラウンドのスーパバイザCSRとフォアグラウンドのCSRスワップする。

  • V=0
    • バックグラウンドCSR : VS-Modeの情報
    • フォアグラウンドCSR : HS-Modeの情報
  • V=1
    • バックグラウンドCSR : HS-Modeの情報
    • フォアグラウンドCSR : VS-Modeの情報

HS-mode時のXLENのことをHSXLENと呼ぶ。

5.2.1 Hypervisor Status Register (hstatus)

mstatusレジスタと同様のレジスタであり、VS-modeのゲストの例外動作について記録している。

f:id:msyksphinz:20181029004700p:plain

各ビットの役割

  • VTSR / VTW, VTVMビット : mstatusと同様だが、V=1の時に、RSET, WFI命令で使用される。

  • SPV(Supervisor Previous Virtualization Mode)ビット : 例外が発生したときにの、仮想モードの情報を記録する。V=0時にSRET命令が実行されると、SPVにVが設定される。

  • HS-mode時に例外が発生すると、例外が発生する前にSP2VとSP2PにSPVとHSレベルのSPPの値が設定される(例外の前に、HSレベルのSPPはV=0時にはsstatus.SPPであり、V=1時にはbssatus.SPPである)。V=0のときにSRET命令が実行されると、逆の操作が行われる: つまり、SPVsstatus.SPPが新しい仮想モードの例外モードに設定される:つまり、それぞれの値はSP2V, SP2Pに書き込まれる。

  • STL(Supervisor Translation Level)はメモリアクセス失敗、ページ例外時のアドレス変換レベルを示している。HS-modeで例外が発生した場合には必ず設定される。

    • ゲスト物理アドレス変換中によるアクセス例外が発生した場合 : STLは1が設定される。
    • 他の例外の場合には : STLは0が設定される。
  • SPRVビット
    • SPRV=0の場合 : メモリアクセス・プロテクションは通常通り行われる。
    • SPRV=1の場合 : ロード・ストアメモリアクセスは、現在の仮想モードがhstatus.SPVとして扱われ、現在の特権モードがHSレベルのSPPとして扱われる(V=0の場合はsstatus.SPPが使用され、V=1の場合はbsstatus.SPPとなる)。
f:id:msyksphinz:20181029004637p:plain

5.2.2 Hypervisor Exception Delegation, Interrupt Delegation (hedeleg, hideleg)

Arm DesignStart Cortex-M3を試す(5. オリジナルプログラムをビルドしてシミュレーションする試行)

f:id:msyksphinz:20181026004305p:plain

Arm DesignStart ProgramではCortex-M3も開放されており、こちらもRTLシミュレーション環境が用意されていた。

前回はDhrystoneやhelloを動かしてみたが、オリジナルプログラムをコンパイルして動作させることはできるだろうか。試行する。

例えばhelloのプログラムは、ディレクトリ内のAT421-MN-80001-r0p0-02rel0/m3designstart/logical/testbench/testcodes/helloに存在している。 Ubuntu-18.04ならばapt-getでArmのコンパイルツールをダウンロードできるので、ダウンロードしてみる。

$ sudo apt install binutils-arm-none-eabi gcc-arm-none-eabi

これでリコンパイルした。当該ディレクトリに移って、makeをたたいてみる。

$ cd AT421-MN-80001-r0p0-02rel0/m3designstart/logical/testbench/testcodes/hello
$ make
$ make
arm-none-eabi-gcc -g -O3 -mthumb -mcpu=cortex-m3 --specs=nosys.specs --specs=nano.specs -Wl,--gc-sections -D__STARTUP_CLEAR_BSS ../../../../software/cmsis/Device/ARM/CM3DS/Source/GCC/startup_CM3DS.s \
        hello.c \
        ../../../../software/common/retarget/retarget.c \
        ../../../../software/common/retarget/uart_stdout.c \
        ../../../../software/cmsis/Device/ARM/CM3DS/Source/system_CM3DS.c \
        -I ../../../../software/cmsis/Device/ARM/CM3DS/Include -I ../../../../software/cmsis/CMSIS/Include \
                -I ../../../../software/common/retarget  \
        -L ../../../../software/common/scripts \
        -D__STACK_SIZE=0x200 \
        -D__HEAP_SIZE=0x1000 \
        -DCORTEX_M3 -T ../../../../software/common/scripts/cm3ds.ld -o hello.o
# Generate disassembly code
arm-none-eabi-objdump -S hello.o > hello.lst
# Generate binary file
arm-none-eabi-objcopy -S hello.o -O binary hello.bin
# Generate hex file
arm-none-eabi-objcopy -S hello.o -O verilog hello.hex

コンパイルしてみたコードをさっそくシミュレーションしてみたのだが、最後まで完走しない。 というか、まったくprintf()が表示されない。

よくよく調べてみると、どうも生成されているtest.binが大きすぎる。 最終的にodコマンドなどを使用してflash_main.iniに変換されてシミュレータに流されるのだが、どうも生成されているバイナリがそもそもおかしいようだ。

Armの公式Webサイトからツールチェインをダウンロードして、使ってみよう。 まずはaptで入手したツールを削除する。

$ sudo apt remove gcc-arm-none-eabi binutils-arm-none-eabi

下記から最新版のArmのツールチェインをダウンロードして、PATHを通した。これで再度バイナリを作成した。

developer.arm.com

同様にコンパイルしてみたが、やはりコンパイル結果は同じだ。どのように変えれば良いのだろうか? 引き続き解析する。

参考:ツールチェインを使ってコンパイルした結果をobjdumpすると、以下のように0x00がコードになっていない気がするぞ?

hello.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <__isr_vector>:
   0:   2000fc00        .word   0x2000fc00
   4:   00000125        .word   0x00000125
   8:   0000016d        .word   0x0000016d
   c:   0000016f        .word   0x0000016f
  10:   00000171        .word   0x00000171
  14:   00000173        .word   0x00000173
  18:   00000175        .word   0x00000175
        ...
  2c:   00000177        .word   0x00000177
  30:   00000179        .word   0x00000179
  34:   00000000        .word   0x00000000
  38:   0000017b        .word   0x0000017b
  3c:   0000017d        .word   0x0000017d
  40:   0000017f        .word   0x0000017f
...

2018/10/28追記。先ほどリトライしたら上手くいった。 どうもisr_vectorを最初にフェッチした後に割り込み(か単なる分岐?)を使って本当のブート位置にジャンプするらしい。 例えば、m3designstart/logical/testbench/testcodes/hello/hello.cを以下のように変更すると、ちゃんと変更したプログラムが動いた。

--- a/arm_designstart/AT421-MN-80001-r0p0-02rel0/m3designstart/logical/testbench/testcodes/hello/hello.c
+++ b/arm_designstart/AT421-MN-80001-r0p0-02rel0/m3designstart/logical/testbench/testcodes/hello/hello.c
@@ -31,7 +31,7 @@ int main (void)
   // UART init
   UartStdOutInit();

-  printf("Hello world\n");
+  printf("Hello world MSYKSPHINZ\n");

   printf("** TEST PASSED **\n");

@@ -40,4 +40,3 @@ int main (void)

   return 0;
 }
f:id:msyksphinz:20181028200126p:plain

TOKYOトライアルハーフマラソン2018に参加

ハーフマラソンに参加するのは人生で2回目。 TOKYOトライアルハーフマラソンは、東京マラソンと同じ財団が運営しているハーフマラソン大会らしい。

場所は四ツ木駅の付近。参加者は2000~3000人程度?だったと思われる。

ラソン初心者にとってうれしいのは、30秒毎のペースセッターが配置されている。 私は普段の練習の経験から、6:00のペースのグループに入った。

f:id:msyksphinz:20181027190814p:plain

スタートすると、予想外に気温が上がり、最初から少しばてたような状態になった。

5kmの地点でいつもよりも疲れているぞ?コースも単純なので、あまり面白くない。

15km地点からかなり疲れてきて、18kmくらいからは地獄のようになってきた。

10kmのあたりで6:00のペースセッターははるか遠くに行ってしまったのだけれども、15km地点で6:30のペースセッターにも追い抜かれてしまった。 自分でもわかるくらいにかなりペースが落ちてたなあ。

最終的に2時間24分58秒でゴール。前回参加(5年くらい前)は2時間16分くらいだったのでかなりダウン。 足が動かなくなって途中で歩いたのが効いているなあ。。。

とりあえず完走できたので良しとする。

次回は、、一年後かなあ。すこし鍛えなおさないと。

Arm DesignStart Cortex-M3を試す(5. オリジナルプログラムをビルドしてシミュレーションする試行)

f:id:msyksphinz:20181026004305p:plain

Arm DesignStart ProgramではCortex-M3も開放されており、こちらもRTLシミュレーション環境が用意されていた。

前回はDhrystoneやhelloを動かしてみたが、オリジナルプログラムをコンパイルして動作させることはできるだろうか。試行する。

例えばhelloのプログラムは、ディレクトリ内のAT421-MN-80001-r0p0-02rel0/m3designstart/logical/testbench/testcodes/helloに存在している。 Ubuntu-18.04ならばapt-getでArmのコンパイルツールをダウンロードできるので、ダウンロードしてみる。

$ sudo apt install binutils-arm-none-eabi gcc-arm-none-eabi

これでリコンパイルした。当該ディレクトリに移って、makeをたたいてみる。

$ cd AT421-MN-80001-r0p0-02rel0/m3designstart/logical/testbench/testcodes/hello
$ make
$ make
arm-none-eabi-gcc -g -O3 -mthumb -mcpu=cortex-m3 --specs=nosys.specs --specs=nano.specs -Wl,--gc-sections -D__STARTUP_CLEAR_BSS ../../../../software/cmsis/Device/ARM/CM3DS/Source/GCC/startup_CM3DS.s \
        hello.c \
        ../../../../software/common/retarget/retarget.c \
        ../../../../software/common/retarget/uart_stdout.c \
        ../../../../software/cmsis/Device/ARM/CM3DS/Source/system_CM3DS.c \
        -I ../../../../software/cmsis/Device/ARM/CM3DS/Include -I ../../../../software/cmsis/CMSIS/Include \
                -I ../../../../software/common/retarget  \
        -L ../../../../software/common/scripts \
        -D__STACK_SIZE=0x200 \
        -D__HEAP_SIZE=0x1000 \
        -DCORTEX_M3 -T ../../../../software/common/scripts/cm3ds.ld -o hello.o
# Generate disassembly code
arm-none-eabi-objdump -S hello.o > hello.lst
# Generate binary file
arm-none-eabi-objcopy -S hello.o -O binary hello.bin
# Generate hex file
arm-none-eabi-objcopy -S hello.o -O verilog hello.hex

コンパイルしてみたコードをさっそくシミュレーションしてみたのだが、最後まで完走しない。 というか、まったくprintf()が表示されない。

よくよく調べてみると、どうも生成されているtest.binが大きすぎる。 最終的にodコマンドなどを使用してflash_main.iniに変換されてシミュレータに流されるのだが、どうも生成されているバイナリがそもそもおかしいようだ。

Armの公式Webサイトからツールチェインをダウンロードして、使ってみよう。 まずはaptで入手したツールを削除する。

$ sudo apt remove gcc-arm-none-eabi binutils-arm-none-eabi

下記から最新版のArmのツールチェインをダウンロードして、PATHを通した。これで再度バイナリを作成した。

developer.arm.com

同様にコンパイルしてみたが、やはりコンパイル結果は同じだ。どのように変えれば良いのだろうか? 引き続き解析する。

参考:ツールチェインを使ってコンパイルした結果をobjdumpすると、以下のように0x00がコードになっていない気がするぞ?

hello.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <__isr_vector>:
   0:   2000fc00        .word   0x2000fc00
   4:   00000125        .word   0x00000125
   8:   0000016d        .word   0x0000016d
   c:   0000016f        .word   0x0000016f
  10:   00000171        .word   0x00000171
  14:   00000173        .word   0x00000173
  18:   00000175        .word   0x00000175
        ...
  2c:   00000177        .word   0x00000177
  30:   00000179        .word   0x00000179
  34:   00000000        .word   0x00000000
  38:   0000017b        .word   0x0000017b
  3c:   0000017d        .word   0x0000017d
  40:   0000017f        .word   0x0000017f
...

Arm DesignStart Cortex-M3を試す(4. Modelsimを使ってCortex-M3の波形を観測する)

Arm DesignStart ProgramではCortex-M3も開放されており、こちらもRTLシミュレーション環境が用意されていた。

RTLシミュレーションができるようになったので、波形を観測してみよう。 ModelSimでGUIを立ち上げて、バスを観測する。

ModelSim IntelFPGA Starter EditionでGUIを立ち上げるためには、いくつか処置が必要なようだ。 以下を参考にした。

uzusayuu.hatenadiary.jp

-64を入れるとまだ不具合があるっぽい?ので32ビット版で立ち上げる。makeを使うと落ちるので、そのままコマンドを叩いてデザインを立ち上げた。

cd Arm_DesignStart/AT421-MN-80001-r0p0-02rel0/m3designstart/logical/testbench/execution_tb
vsim  -quiet -assertdebug -voptargs="+acc=blnr"  tb_fpga_shield -gui

tb_fpga_shield/u_fpga_top/u_fpga_system/u_user_partition/u_iot_top/u_CORTEXM3INTEGRATIONが、Cortex-M3本体のようだ。そこからは、大きく分けて3種類のバスが出ているようだ。

  • Cortex-M3 テクニカルリファレンス マニュアル Appendix A. 信号の説明

ARM Information Center

AHBのバスが出ているので、それをすべて出して観測した。TESTNAME=helloを実行すると波形が表示される。

f:id:msyksphinz:20181026004305p:plain

一応動作しているように見える。ただしデバッグする方法が無いので良く分からないけれども。。。

ちなみに、Cortex-M3のデザインの中身はこのように暗号化されている。 名前は全てReplaceされており、中身を垣間見ることはできなかった。

f:id:msyksphinz:20181026004840p:plain