ますます注目されるオープンCPUアーキテクチャRISC-Vの最新動向

39660b800174f05657f47a30ff8258c7?s=47 msyksphinz
November 14, 2018

 ますます注目されるオープンCPUアーキテクチャRISC-Vの最新動向

39660b800174f05657f47a30ff8258c7?s=128

msyksphinz

November 14, 2018
Tweet

Transcript

  1. 1.

    TS-3 ますます注目される オープンCPUアーキテクチャ RISC-Vの最新動向 The latest trend of RISC-V, attracted

    open CPU architecture FPGA開発日記 著者 @msyksphinz_dev http://msyksphinz.hatenablog.com 1
  2. 5.

    RISC-V発展の歴史 2011 2012 2013 2014 2015 2016 2017 RISC-V Processor

    Raven-1 7th RISC-V Workshop 6th RISC-V Workshop RISC-V Processor Raven-2 RISC-V Processor Raven-3 5th RISC-V Workshop 4th RISC-V Workshop 3th RISC-V Workshop 1th RISC-V Workshop 2th RISC-V Workshop User-Level ISA Ver. 1.0 User-Level ISA Ver. 2.0 User-Level ISA Ver. 2.1 User-Level ISA Ver. 2.2 Privileged ISA Ver. 1.7 Privileged ISA Ver. 1.9 Privileged ISA Ver. 1.10 世界発の商用 RISC-Vボード 研究チップの制御 プロセッサとして利用 ヘネパタ第6版は RISC-Vで刷新 パタヘネのRISC-V 版が登場 約半年に1回の頻度で Workshop開催 8th RISC-V Workshop in Barcelona RISC-V Day in Shanghai 9th RISC-V Workshop in Chennai RISC-V Day in Tokyo RISC-V Day in MICRO51 RISC-V Summit in Santa Clara Linuxが動作す るRISC-Vボード 2018 ◼ 2015年から定期的にWorkshopを開催 ◼ トップカンファレンスにRISC-Vネタで 通している。 ◼ パタヘネ・ヘネパタはRISC-Vに移行 ◼ 2017年/2018年に日本でイベント開催
  3. 7.

    気づかぬ間に浸透しています “RISC-V” According to the LinkedIn profile, work on the

    Exynos 9820 began in January this year, and the Samsung engineer appears to have been working on a 5G RF chip based on the RISC-V architecture ever since May 2017, which could reinforce a 2019 release for the 5G smartphones. (https://www.notebookcheck.net/Samsung-Exynos-9820-SoC-and-5G-RF-chips-already-in-the- works.295886.0.html) WD、同社製品搭載のプロセッサ/コントローラなどをRISC-Vへ移行 (https://pc.watch.impress.co.jp/docs/news/1094891.html) NVIDIA gave a presentation about how its proprietary Falcon (Fast Logic CONtroller) core will be replaced by RISC-V cores. (https://www.electronicdesign.com/industrial-automation/rise-risc-v-display-workshop) Internal Project to demonstrate ability to easily develop custom RISC-V implementation by leveraging Rocket Chip. (https://content.riscv.org/wp-content/uploads/2018/05/13.15-13.30-matt-Cockrell.pdf) BSC is promoting the adoption of RISC-V as a key partner of the European Processor Initiative, the consortium to design and develop Europe’s low-power processors and related technologies for extreme- scale, high-performance computing, which will be funded by the European Commission under the Horizon 2020 program. (https://insidehpc.com/2018/05/bsc-host-risc-v-workshop-road- european-processor-initiative/)
  4. 8.

    “RISC-V 命令セットアーキテクチャ” を支えるエコシステム RISC-V Foundation Working Group GCC Binutils LLVM

    Linux QEMU ISS BOOM Rocket- Chip Freedom SoC HiFive1 HiFive Unleashed ボード・ プラットフォーム SIMD拡張 Privileged Spec セキュリティ メモリモデル ソフトウェア ツールチェイン Board of Directorsを中心に、ISAの各分野でWorking Groupが存在している。 … Linux パッケージメンテナ 有志によるOS 移植 Foundation 加入 メンバによるメンテ Foundation 加入 メンバによる開発 Board of Directors RISC-V ISA Manual
  5. 10.
  6. 12.

    RISC-Vアーキテクチャ 命令セット外観 12 ARM Manual 6000ページくらい RISC-V Manual 200ページくらい どっちが良いかは別にして…

    細かいことをいろいろ喋っても仕方がないので外観だけ。 ざっくりと必要なところだけ説明します。 もはや凶器
  7. 13.

    RISC-Vの特権モードと動作モード • 3種類の動作モードが定義されている • 最初の版では4種類だったが削減されて3種類 • ユーザモード • 最も権限の少ないモード。アプリケーション を動かすためのモード

    • スーパバイザモード • OSが例外処理などを行うための権限の高い モード。 • マシンモード • 最も権限が高い。マシンモード。何でもでき る • モード間の遷移について • 外部から割り込み挿入 or 命令実行中に例外発 生 • ECALL命令によるSupervisor Call • 例外処理後に実行するMRET / SRET / URET 13 マシンモード スーパバイザモード ユーザモード
  8. 14.

    RISC-V命令セットアーキテクチャ形態について • RISC-Vは大きく「基本命令セット」と 「拡張命令セット」に分かれる。 • 基本命令セット : RV32I / RV32E

    / RV64I / RV128I • 拡張命令セット : 基本命令セット+特定向け命令 • 浮動小数点とか、ベクトル命令とか 14 “A” atomic拡張 “C” 16bit短縮命令 “F” 単精度浮動小数点 “D” 倍精度浮動小数点 “L” 10進数浮動小数点 “Q” 4倍精度浮動小数点 “M” 乗除算命令 “S” スーパバイザモード “P” Packed SIMD “V” Vector拡張 “N” ユーザレベル割り込み RV32I RV32E RV64I RV128I 拡張命令 基本命令 RV32I RV32E RV64I RV128I + M A F D + + + M A F D C = RV32G = RV64GC ▪ RISC-V アーキテクチャの呼び方 アーキテクチャ識別子を付加して呼ぶ
  9. 15.

    RISC-Vのレジスタ 15 x0 x1 x2 x3 x4 x5 x31 …

    XLEN=128 x0 x1 x2 x3 x4 x5 x31 … XLEN=64 x0 x1 x2 x3 x4 x5 x31 … XLEN=32 f0 f1 f2 f3 f4 f5 f31 … FLEN=128, Q Extension f0 f1 f2 f3 f4 f5 f31 … FLEN=64, D Extension f0 f1 f2 f3 f4 f5 f31 … FLEN=32, F Extension 整数レジスタの表記は全てxN x0 – x31まで定義 整数レジスタ長はXLENで表記される RV32 : XLEN=32 RV64 : XLEN=64 RV128 : XLEN=128 浮動小数点レジスタの表記は全てfN f0 – f31まで定義 浮動小数点レジスタ長はFLENで表記される F拡張 : FLEN=32 D拡張 : FLEN=64 Q拡張 : FLEN=128
  10. 16.

    Floatレジスタは Single/Double/Quadで共有 • 例えば、Float⇔DoubleのConvert命令の場合 • FCVT.D.S fd, fs • FCVT.S.D

    fd, fs • DoubleとFloatがレジスタを 共有しているので • NaN Boxingをサポートする必要がある • FLEN>32で、Single Floating Pointの命令を実行するときは、 32bit以上の値は全て1が設定されている必要がある 16 fd fs Convert 1111…1111 Single-Float Value FLEN=64 Single値として見た場合 : 普通の値 Double値としてみた場合 : 上位がすべて1 なので NaN → 型を明確に識別するための手法
  11. 17.

    割り込み・例外 • RISC-Vの割り込み・例外要因は多くない • 割り込み • ソフトウェア割り込み • タイマ―割り込み •

    外部割込み • ユーザ・スーパバイザ・ マシンモード毎に定義 • 外部割込みが少ないので PLICを外部に定義 17
  12. 20.

    RISC-Vのシステムレジスタ • システムレジスタは専用命令でアクセスする。 • csrrw (CSR Register Read/Write) • csrrs

    (CSR Register Set) • csrrc (CSR Register Clear) • csrrwi (CSR Register Read/Write Immediate) • csrrsi (CSR Register Set Immediate) • csrrci (CSR Register Clear Immediate) • 汎用レジスタとCSRレジスタの交換 (csrrw / csrrwi) • 即値を指定してCSRの特定のビットを1に設定する (csrrs/csrrsi) • 即値を指定してCSRの特定のビットを0に設定する(csrrc/csrrci) 20 x0 x1 x2 x31 CSR 基本は1命令で データを交換
  13. 22.

    仮想メモリ • RISC-Vの仮想メモリは(比較的)複雑 • Sv32 : VA 32bit → PA

    : 34bit • Sv39 : VA 39bit → PA : 56bit • Sv48 : VA 48bit → PA : 56bit 22 Bare Sv32 Bare Sv39 Sv48 RV32 RV64 SATP vpn[2] vpn[1] vpn[0] offset ppn[1] ppn[0] + + ppn[1]ppn[0] + ppn[1]ppn[0] + Supervisor Address Translation and Protection Register 物理メモリ アドレス 仮想メモリ アドレス
  14. 23.

    RISC-V命令セットの実際性能 23 ・RV32 / RV64は他のISAに比べて コードサイズが大きい → フェッチサイズが大きい。 ・そこで、RV32C /

    RV64Cという 圧縮命令を活用する。 → フェッチサイズを圧縮できる。 Computer Architecture Research with RISC-V Krste Asanovic より抜粋 ISA Shootout: Comparing RISC-V, ARM, and x86 on SPECInt 2006 より抜粋 RV32GC / RV64GCでは、多くの ベンチマークプログラムで他の 命令セットよりも優れる。
  15. 27.

    メリット RISC-Vを導入することによる メリット・デメリット RISC-Vを導入すれば、すべてが解決するなどと言うつもりはありません。 企業が作ったアーキテクチャ ではないので、企業の 経営状態に左右されない ◼ 注目されている分、メリット・デメリットがある。 ◼

    冷静に分析し、「自社にとってどのようなメリットがあるのか?」を解析する必要がある。 デメリット RISC-Vはカスタマイズが可能 RISC-Vは商用プロセッサほど 実装技術が最適化されていない ソフトウェアエコシステムが ある程度用意されている RISC-Vは ISAの断片化の恐れがある 一社で開発される実装は仕様が 統一されている RISC-Vはライセンス料の 問題を削減できる 歴史あるアーキテクチャは プラットフォームも豊富
  16. 29.

    RISC-Vを導入することによるメリットを しっかり考えること • 自社独自コアを持っているが、メンテナンスに手が回らない場合 • ソフトウェアエコシステムを含めてRISC-Vを導入することによりコストを削減する • 独自開発したことによる特許の問題が心配な場合 • 本当に力を入れたいのは、CPUコアではなく別のところにある場合

    • 補助プロセッサとしてRISC-Vを使用するという選択肢 • 制御プロセッサの設計とメンテナンスに必要なコストを最小化する。 • 開発しているチップがプロセッサメインで性能が要求される場合 • 余力あればRISC-Vプロセッサを独自に開発するという選択肢がある • 特許に関する問題を解決することができれば。 いろんな手段はありますが 用量・用法を守ることが肝要です
  17. 31.

    31 まず何をしたい? とりあえず手持ちのプログラムを RISC-V向けにコンパイルして 実行してみたい。 riscv-toolsによる 開発環境の整備 riscv-isa-simによる シミュレーション QEMUによるLinux

    のブート RISC-VプロセッサのRTL シミュレーションをしてみたい Rocket-Chipの RTL立ち上げ BOOMの RTL立ち上げ RISC-Vチップを使ってプログラム をガリガリ書いてみたい。 RISC-Vについてもっと 詳しく理解したい。 RISC-Vシミュレータ を作ろう RISC-VチップHiFive1 を使ってみよう。
  18. 32.

    riscv-toolsリポジトリの中身 32 riscv-tools riscv-openocd riscv-fesvr riscv-gnu-toolchain riscv-isa-sim riscv-opcodes riscv-tests riscv-pk

    RISC-Vデバッグ用のOpenOCD実装 シミュレーション用のフロントエンドサーバ コンパイラやライブラリなど 命令セットシミュレータ RISC-Vテストパタン RISC-Vのプロキシカーネル RISC-Vのソフトウェア開発を行う際の最もBaseとなるツール群が 入っている。 全部ダウンロードするとかなりディスクを消費します(2GBくらい)。
  19. 33.

    RISC-Vのソフトウェア環境を用意する 33 $ git clone https://github.com/riscv/riscv-tools.git $ cd riscv-tools $

    export RISCV=/home/msyksphinz/riscv64 $ MAKEFLAGS=“-j8” ./build.sh ... $ cd ${RISCV}/ $ export PATH=${RISCV}/bin:${PATH} $ export LD_LIBRARY_PATH=${RISCV}/lib:${LD_LIBRARY_PATH} $ git clone https://github.com/riscv/riscv-tools.git $ cd riscv-tools $ export RISCV=/home/msyksphinz/riscv32 $ MAKEFLAGS=“-j8” ./build.sh ... $ cd ${RISCV}/ $ export PATH=${RISCV}/bin:${PATH} $ export LD_LIBRARY_PATH=${RISCV}/lib:${LD_LIBRARY_PATH} 64-bit版 RISC-Vツールチェイン 32-bit版 RISC-Vツールチェイン
  20. 34.

    GCCを使ってプログラムをコンパイル & シミュレーション 34 #include <stdio.h> int gcd (int a,

    int b) { int c; if (a < b) { int tmp; tmp = b; b = a; a = tmp; } while (b != 0) { c = a % b; a = b; b = c; } return a; } int main () { printf ("hello world¥nCalling GCD ...¥n"); printf ("GCD(273, 21) = %d¥n", gcd(273, 21)); printf ("GCD(411, 27117) = %d¥n", gcd(411, 27117)); return 0; } $ riscv64-unknown-elf-gcc gcd.c –o gcd $ riscv64-unknown-elf-objdump -D gcd > gcd.dmp $ spike pk gcd <<set terminal>> <<reset terminal>> hello world Calling GCD ... GCD(273, 21) = 21 GCD(411, 27117) = 3 <<reset terminal>> 命令セットシミュレータを実行
  21. 35.

    “spike gcd”って何をしているの? • SpikeはUCBが開発しているRISC-V命令セットシミュレータ • Linuxも起動することができる • 各種外部デバイスもサポートしている • タイマ

    • 割り込みなど • システムコールが呼び出されると pk(Proxy Kernel)を通じてホ ストのLinuxマシンに処理を依頼する • printf()や、ファイルシステムのアクセスも実現可能 35 x86 Host Linux pk (proxy kernel) Spike RISC-V Simulator dtb Device Tree Blob Target Program Elf Log Files
  22. 36.

    ベンチマークプログラムのコンパイル・ シミュレーション実行 • riscv-testsディレクトリ • 命令セットのテストパタンや、ベンチマークプログラムが格納されて いる。 • riscv-tools/riscv-tests/benchmarks 36

    $ spike ${RISCV}/riscv64-unknown-elf/share/riscv-tests/ ¥ benchmarks/dhrystone.riscv Microseconds for one run through Dhrystone: 396 Dhrystones per Second: 2525 mcycle = 198024 minstret = 198030 Dhrystoneの実行 $ cd freedom-u-sdk $ spike work/riscv-pk/bbl ... Welcome to Buildroot buildroot login: root root Password: sifive # echo hello echo hello hello # Linuxもブートできます
  23. 37.

    QEMUでLinuxを立ち上げる(1) 37 $ wget https://download.qemu.org/qemu-2.12.0.tar.xz $ tar Jxf qemu-2.12.0.tar.xz $

    cd qemu-2.12.0/ $ mkdir build $ cd build $ ../configure --target-list=riscv64-softmmu --prefix=${RISCV} TargetをRISC-Vに設定して QEMUをビルド $ wget https://fedorapeople.org/groups/risc-v/disk-images/vmlinux $ wget https://fedorapeople.org/groups/risc-v/disk-images/bbl $ wget https://fedorapeople.org/groups/risc-v/disk-images/stage4- disk.img.xz $ xzdec -d stage4-disk.img.xz > stage4-disk.img Linuxのイメージをダウンロード
  24. 38.

    QEMUでLinuxを立ち上げる(2) 38 qemu-system-riscv64 ¥ -nographic -machine virt -kernel bbl ¥

    -object rng-random,filename=/dev/urandom,id=rng0 ¥ -device virtio-rng-device,rng=rng0 -append "console=ttyS0 ro root=/dev/vda" ¥ -device virtio-blk-device,drive=hd0 -drive file=stage4-disk.img,format=raw,id=hd0 ¥ -device virtio-net-device,netdev=usernet -netdev user,id=usernet,hostfwd=tcp::10000-:22 QEMUの起動 Fedoraの起動
  25. 40.

    初の商用RISC-V評価ボード “HiFive1” • SiFive社から発売 • 日本だとボード1枚につき10,000円で入手可 • Raspberry-Pi3よりも高い… • 主な仕様

    • RV32IMAC • 32-bitモード • ハードウェア乗算器・除算器搭載 • Atomic命令搭載 • Compact命令(16-bit長命令)搭載 • 最大動作周波数: 320MHz • キャッシュ • L1IC : 16kB / L1DC : 16kB • SPIフラッシュ : 128Mbit
  26. 41.

    様々な開発環境を用意している • RISC-Vのアピールチップだと思えば 何ということはない • HiFive1を制御するアプローチはさまざま • Windows, Linux, MacOSどれでも可

    • GUI, CUIなど様々な環境が用意されている • Lチカ、ベンチマークプログラム動作 くらいなら一瞬で出来る • 立ち上げは超お手軽 • GUIでも開発できる • Freedom Studio • Windows • Linux • MacOS
  27. 42.

    HiFive1/Freedom SoCのための FreedomStudio • SiFiveが提供されるEclipseベースの開発環境 • Windows / Linux /

    MacOS に対応している • SiFiveの提供している各種プラットフォームに対応 • HiFive1 • Freedom E300 • Freedom U500 42
  28. 43.

    GUIが嫌いな人のための、”Freedom-SDK”開発環境 • https://github.com/sifive/freedom-e-sdk • HiFive1構成用riscv-tools、ベンチマークプログラム、サンプルプログラムなど 一通り揃う • printf、getc的な物も使える freedom-e-sdk bsp

    openocd riscv-gnu-toolchain software demo_gpio dhrystone welcome local_interrupt led_fade # software/demo_gpioをコンパイル $ make software PROGRAM=demo_gpio # software/demo_gpio を Hifive1にupload $ make upload PROGRAM=demo_gpio # HiFive1のコンソールを出力を取得 $ screen /dev/ttyUSB1 115200
  29. 44.

    HiFive1を使ってちょっと複雑なプログラムを実行してみた い • 最近流行りのニューラルネットワークをHiFive1に移植して動作させる • ターゲットアプリケーション: MNIST (数字文字認識) • 今回は推論の部分のみ

    • 学習フェーズはx86で実施 → パラメータを抽出 参考にした本: ゼロから学ぶDeep Learning 全部Pythonで書いてあるのでC言語に移植 ※ 発表者はディープラーニング初心者なので、あまり詳細な ことは知りません。 性能評価などもあまり突っ込んだことはしていません… 入力値 Batch_Size 28x28 重み W0 28x28 Hidden_size × Affine1 出力 Batch_Size Hidden_Size → 1. Affine1 Affine1 出力 Batch_Size Hidden_Size ReLU 出力 Batch_Size Hidden_Size → 2. ReLU Batch_Size 重み W1 Hidden_Size 10 × ReLU 出力 Batch_Size Hidden_Size → 3. Affine2 Batch_Size 10 Batch_Size → 4. Softmax Affine2 出力 10 Affine2 出力 10 Softmax 出力 重み b0 + 重み b1 + 図. 実装した主な演算
  30. 45.

    Freedom-E-SDK環境で MNISTを動かす • printf(), getc()なども使えるので デバッグもかなり楽 • freedom-e-sdk環境でコンパイルして HiFive1にアップロードで動かすことが できる。

    • HiFive1を使ってみてわかったこと • L1Dキャッシュが小さい & SPIフラッシュメモリへのアクセスが遅い • 学習済みパラメータの アクセスが異常に 遅くなってしまう。 • お金に余裕があるならば、 マルチコアが搭載されたRISC-V ボードはいかが freedom-e-sdk bsp openocd riscv-gnu-toolchain software demo_gpio dhrystone welcome local_interrupt led_fade mnist HiFive Unleashed
  31. 47.

    RISC-V Implementationの代表格「Rocket-Chip」 • UCBの開発したRISC-V Implementation • XilinxのFPGAボードならばサポート ZedBoard Zybo ZC706

    HiFive1の中身も実際は Rocket Chip(32-bit) Rocket-ChipのRTLシミュレーションと ソフトウェアデバッグの様子 無料 ソースコード公開 最新仕様に(かなり)追従 開発が活発 Chiselって何? どうやって動かすの? カスタマイズの方法が分からん
  32. 48.

    Rocket-Chipの実装言語 “Chisel” • Scalaをベースとしたハードウェア記述言語 • Rocket Chipはすべて”Chisel”で実装してある • 最終的にはVerilogに変換される •

    Chiselを使うことにより、合成用言語Verilogと分離する • Chisel→FIRRTL(中間言語)と変換することで、 VHDLなども出せる(一応) • 検証で有利 • Verilogシミュレータを走らせなくても Chisel(≒Scala)で検証パタンを書ける→高速 FIRRTL Verilog
  33. 49.

    Chiselによる実装は、 部品を取り付けたり外したりするイメージ class WithNBigCores(n: Int) extends Config((site, here, up) =>

    { case RocketTilesKey => { val big = RocketTileParams( core = RocketCoreParams(mulDiv = Some(MulDivParams( mulUnroll = 8, mulEarlyOut = true, divEarlyOut = true))), dcache = Some(DCacheParams( rowBits = site(SystemBusKey).beatBits, nMSHRs = 0, blockBytes = site(CacheBlockBytes))), icache = Some(ICacheParams( ... } }) class With1TinyCore extends Config((site, here, up) => { case XLen => 32 case RocketTilesKey => List(RocketTileParams( core = RocketCoreParams( useVM = false, fpu = None, mulDiv = Some(MulDivParams(mulUnroll = 8))), btb = None, dcache = Some(DCacheParams( rowBits = site(SystemBusKey).beatBits, nSets = 256, // 16Kb scratchpad nWays = 1, nTLBEntries = 4, nMSHRs = 0, blockBytes = site(CacheBlockBytes), scratch = Some(0x80000000L))), … blockBytes = site(CacheBlockBytes))))) }) class TinyConfig extends Config( new WithNMemoryChannels(0) ++ new WithIncoherentTiles ++ new With1TinyCore ++ new BaseConfig) Chiselを使って、コアの部品を簡単に着脱・ カスタマイズできる。 ベースのコンフィグレーションに対して、 カスタマイズを行っていく。 VM Support メインパイプライン FPU DIV I-cache 構成 D-cache 構成 I/F
  34. 50.

    Rocket-Chip Generator, Freedom SoCの構成方法 • 高いポータビリティ • Chisel(Scala拡張)によるモジュールの切り離し、コンフィグレーションの 構成変更が容易 •

    Xilinx ZYNQ FPGA, Arty, Virtex Ultrascaleなどに対応した構成を作成可能 Xilinx ARTY FPGA E300 Freedom SoC E3 Coreplex RV32E/IMACN ROM Debug AON UART SPIFlash SPI GPIO PWM I2C I-Cache 4kB D-Cache 16kB Custom Coprocessor Xilinx ZYNQ FPGA Rocket-Chip Generator RV64GC ROM Debug I-Cache 4kB D-Cache 16kB Custom Coprocessor AXI2TileLink ARM DRAM I/O class DefaultConfig extends Config( new WithNBigCores(1) ++ new BaseConfig) class TinyConfig extends Config( new WithNMemoryChannels(0) ++ new WithIncoherentTiles ++ new With1TinyCore ++ new BaseConfig) Chiselを使って、Rocketの 構成を簡単に変更できる
  35. 51.

    Rocket-Chipを使ってみよう • University of California Berkeleyの開発しているRISC-V実装 • 5-stageパイプライン • RISC-V

    Foundationに最も近い人たちが実装しているので信頼できる • Rocket-Chip + 周辺バスを含めてFPGAに実装できる • リポジトリ : https://github.com/freechipsproject/rocket-chip • https://github.com/freechipsproject/rocket-chip.gitで 丸ごとダウンロードできる 51
  36. 52.

    Rocket-Chipのダウンロードとビルド • ↑を実行するとツールチェインまで全部ダウンロードして時間 がかかるので 52 $ git clone https://github.com/freechipsproject/rocket-chip.git¥ --recurse-submodules

    $ git clone https://github.com/freechipsproject/rocket-chip.git $ cd rocket-chip $ git submodule init $ subpackages=`git submodule status | cut -d' ‘ –f3 | grep -v riscv-tools` $ git submodule update --init --recursive $subpackages riscv-toolsを既にインストールしている場合、 全てダウンロードする必要はない $ cd rocket-chip $ cd emulator # Verilatorを使う場合 $ cd vsim # Synopsys VCSを使う場合 $ make CONFIG=DefaultConfig # DefaultConfig構成でビルド(RTL作成)
  37. 53.

    Rocket-Chipでテストパタンを動かしてみる 53 $ make output/rv64ui-p-add.out ln -fs /home/msyksphinz/riscv64//riscv64-unknown-elf/share/riscv- tests/isa/rv64ui-p-add output/rv64ui-p-add

    ./emulator-freechips.rocketchip.system-DefaultConfig +max- cycles=100000000 +verbose output/rv64ui-p-add 3>&1 1>&2 2>&3 | /home/msyksphinz/riscv64/bin/spike-dasm > output/rv64ui-p- add.out && [ $PIPESTATUS -eq 0 ] <<set terminal>> <<reset terminal>> $ $ less output/rv64ui-p-add.out using random seed 1537717042 This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1. Listening on port 36423 C0: 0 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 1 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 2 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 3 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 4 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 5 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 6 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 7 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 8 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 9 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 10 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 11 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 12 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 13 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 14 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 15 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) C0: 16 [0] pc=[f629403494] W[r 0=0000000000000000][0] R[r15=e50f7b8dc1ff78b6] R[r31=7cf3faa98e59e7f7] inst=[0000ed10] sd a2, 24(a0) ...
  38. 54.

    [1]と出ているのが有効な命令 54 $ grep "¥[1¥] pc=" output/rv64ui-p-add.out C0: 53763 [1]

    pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[fe0408e3] beqz s0, pc - 16 C0: 53764 [1] pc=[0000000814] W[r 8=0000000000000000][1] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402473] csrr s0, mhartid C0: 53767 [1] pc=[0000000818] W[r 0=0000000000000100][0] R[r 0=0000000000000000] R[r 8=0000000000000000] inst=[10802023] sw s0, 256(zero) C0: 53773 [1] pc=[000000081c] W[r 0=0000000000000400][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu s0, 1024(s0) C0: 53781 [1] pc=[0000000820] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 3=0000000000000003] inst=[00347413] andi s0, s0, 3 C0: 53782 [1] pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[fe0408e3] beqz s0, pc - 16 C0: 53783 [1] pc=[0000000814] W[r 8=0000000000000000][1] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402473] csrr s0, mhartid C0: 53786 [1] pc=[0000000818] W[r 0=0000000000000100][0] R[r 0=0000000000000000] R[r 8=0000000000000000] inst=[10802023] sw s0, 256(zero) C0: 53792 [1] pc=[000000081c] W[r 0=0000000000000400][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu s0, 1024(s0) C0: 53800 [1] pc=[0000000820] W[r 8=0000000000000001][1] R[r 8=0000000000000001] R[r 3=0000000000000003] inst=[00347413] andi s0, s0, 3 C0: 53801 [1] pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000001] R[r 0=0000000000000000] inst=[fe0408e3] beqz s0, pc - 16 C0: 53805 [1] pc=[0000000828] W[r 8=0000000000000001][1] R[r 8=0000000000000001] R[r 1=0000000000000003] inst=[00147413] andi s0, s0, 1 C0: 53806 [1] pc=[000000082c] W[r 0=0000000000000000][0] R[r 8=0000000000000001] R[r 0=0000000000000000] inst=[00040863] beqz s0, pc + 16 C0: 53807 [1] pc=[0000000830] W[r 8=0000000080001008][1] R[r 0=0000000000000000] R[r18=0000000000000003] inst=[7b202473] csrr s0, dscratch C0: 53808 [1] pc=[0000000834] W[r 0=0000000000000104][0] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[10002223] sw zero, 260(zero) C0: 53809 [1] pc=[0000000838] W[r 0=000000000000083c][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[30000067] jalr zero, zero, 768 C0: 53828 [1] pc=[0000000300] W[r 0=0000000000000304][1] R[r 0=0000000000000000] R[r24=0000000000000003] inst=[0380006f] j pc + 0x38 命令hex RS2 RS1 Exec Cycle 命令ニーモニック Program Counter 書き込みレジスタ $ make output/dhrystone.riscv.out mkdir -p ./output ... <<set terminal>> Microseconds for one run through Dhrystone: 494 Dhrystones per Second: 2021 mcycle = 247478 minstret = 198773 <<reset terminal>> 次にDhrystoneを流してみましょう
  39. 55.

    具体的には何をやってんのさ? 55 $ make output/dhrystone.riscv.out mkdir -p ./output ln –fs

    ${RISCV}/riscv64-unknown-elf/share/riscv- tests/benchmarks/dhrystone.riscv output/dhrystone.riscv ./emulator-freechips.rocketchip.system-DefaultConfig +max-cycles=100000000 +verbose output/dhrystone.riscv 3>&1 1>&2 2>&3 | /home/msyksphinz/riscv64/bin/spike-dasm > output/dhrystone.riscv.out && [ $PIPESTATUS -eq 0 ] outputディレクトリを作成 ${RISCV}ディレクトリに存在する テストベンチをoutputディレクトリにリンク Verilatorでシミュレーションを実行 spike-dasmはRTLシミュレーションの生 成するログを読んで 逆アセンブルしたログを生成する
  40. 56.

    最初に出てきたDefaultConfigって何? 56 class DefaultConfig extends Config(new WithNBigCores(1) ++ new BaseConfig)

    ▪ main/scala/system/Configs.scala class WithNBigCores(n: Int) extends Config((site, here, up) => { case RocketTilesKey => { val big = RocketTileParams( core = RocketCoreParams(mulDiv = Some(MulDivParams( mulUnroll = 8, mulEarlyOut = true, divEarlyOut = true))), dcache = Some(DCacheParams( rowBits = site(SystemBusKey).beatBits, nMSHRs = 0, blockBytes = site(CacheBlockBytes))), icache = Some(ICacheParams( rowBits = site(SystemBusKey).beatBits, blockBytes = site(CacheBlockBytes)))) List.tabulate(n)(i => big.copy(hartId = i)) } }) class BaseConfig extends Config( new WithDefaultMemPort() ++ new WithDefaultMMIOPort() ++ new WithDefaultSlavePort() ++ new WithTimebase(BigInt(1000000)) ++ // 1 MHz new WithDTS("freechips,rocketchip-unknown", Nil) ++ new WithNExtTopInterrupts(2) ++ new BaseSubsystemConfig() )
  41. 57.

    ちょっと待って、Rocketは RTLでシミュレーションしてるの? • Rocket-ChipのシミュレーションはRTLが前提 • Chiselでシミュレーションできれば良いのだが、やり方が書いていな い。 • そのためRTLの生成に時間がかかる (Chisel→FIR→Verilog)

    • ちなみに、Chisel→VerilogのRTLは死ぬほど読みにくい。 57 wire _GEN_53; // @[Monitor.scala 64:14:freechips.rocketchip.system.DefaultConfig.fir@220419.10] wire _GEN_65; // @[Monitor.scala 73:14:freechips.rocketchip.system.DefaultConfig.fir@220475.10] wire _GEN_75; // @[Monitor.scala 81:14:freechips.rocketchip.system.DefaultConfig.fir@220523.10] wire _GEN_85; // @[Monitor.scala 89:14:freechips.rocketchip.system.DefaultConfig.fir@220573.10] wire _GEN_95; // @[Monitor.scala 97:14:freechips.rocketchip.system.DefaultConfig.fir@220621.10] wire _GEN_105; // @[Monitor.scala 105:14:freechips.rocketchip.system.DefaultConfig.fir@220669.10] plusarg_reader #(.FORMAT("tilelink_timeout=%d"), .DEFAULT(0)) plusarg_reader ( // @[PlusArg.scala 42:11:freechips.rocketchip.system.DefaultConfig.fir@221284.4] .out(plusarg_reader_out) ); assign _T_26 = io_in_a_bits_source <= 9'h12f; // @[Parameters.scala 55:20:freechips.rocketchip.system.DefaultConfig.fir@220175.6] assign _T_36 = 6'h7 << io_in_a_bits_size; // @[package.scala 185:77:freechips.rocketchip.system.DefaultConfig.fir@220181.6] assign _T_37 = _T_36[2:0]; // @[package.scala 185:82:freechips.rocketchip.system.DefaultConfig.fir@220182.6] assign _T_38 = ~ _T_37; // @[package.scala 185:46:freechips.rocketchip.system.DefaultConfig.fir@220183.6] assign _GEN_18 = {{14'd0}, _T_38}; // @[Edges.scala 21:16:freechips.rocketchip.system.DefaultConfig.fir@220184.6] assign _T_39 = io_in_a_bits_address & _GEN_18; // @[Edges.scala 21:16:freechips.rocketchip.system.DefaultConfig.fir@220184.6] assign _T_40 = _T_39 == 17'h0; // @[Edges.scala 21:24:freechips.rocketchip.system.DefaultConfig.fir@220185.6] assign _T_41 = {{1'd0}, io_in_a_bits_size}; // @[Misc.scala 203:34:freechips.rocketchip.system.DefaultConfig.fir@220186.6] assign _T_42 = _T_41[1:0]; // @[OneHot.scala 51:49:freechips.rocketchip.system.DefaultConfig.fir@220187.6] assign _T_43 = 4'h1 << _T_42; // @[OneHot.scala 52:12:freechips.rocketchip.system.DefaultConfig.fir@220188.6] assign _T_44 = _T_43[2:0]; // @[OneHot.scala 52:27:freechips.rocketchip.system.DefaultConfig.fir@220189.6] assign _T_45 = _T_44 | 3'h1; // @[Misc.scala 203:81:freechips.rocketchip.system.DefaultConfig.fir@220190.6] assign _T_46 = io_in_a_bits_size >= 2'h3; // @[Misc.scala 207:21:freechips.rocketchip.system.DefaultConfig.fir@220191.6] assign _T_47 = _T_45[2]; // @[Misc.scala 210:26:freechips.rocketchip.system.DefaultConfig.fir@220192.6] assign _T_48 = io_in_a_bits_address[2]; // @[Misc.scala 211:26:freechips.rocketchip.system.DefaultConfig.fir@220193.6] assign _T_49 = _T_48 == 1'h0; // @[Misc.scala 212:20:freechips.rocketchip.system.DefaultConfig.fir@220194.6] assign _T_51 = _T_47 & _T_49; // @[Misc.scala 216:38:freechips.rocketchip.system.DefaultConfig.fir@220196.6] assign _T_52 = _T_46 | _T_51; // @[Misc.scala 216:29:freechips.rocketchip.system.DefaultConfig.fir@220197.6] assign _T_54 = _T_47 & _T_48; // @[Misc.scala 216:38:freechips.rocketchip.system.DefaultConfig.fir@220199.6] assign _T_55 = _T_46 | _T_54; // @[Misc.scala 216:29:freechips.rocketchip.system.DefaultConfig.fir@220200.6] assign _T_56 = _T_45[1]; // @[Misc.scala 210:26:freechips.rocketchip.system.DefaultConfig.fir@220201.6] assign _T_57 = io_in_a_bits_address[1]; // @[Misc.scala 211:26:freechips.rocketchip.system.DefaultConfig.fir@220202.6] assign _T_58 = _T_57 == 1'h0; // @[Misc.scala 212:20:freechips.rocketchip.system.DefaultConfig.fir@220203.6] こんなの読めますか...? ってかECOとか どうするんだ...
  42. 58.

    BOOM (Berkeley Out-of-Order Machine) • アウトオブオーダのRISC-V実装 • UCBの学生が開発 • 2-way版と4-way版が存在する(ハズ)

    • BOOMv1 : サイクル性能重視 (v2に比べて) • BOOMv2 : 動作周波数重視(サイクル性能はv1に劣る?) 58 UCBの大学生が(1~2人で)書いた ちなみにかBOOMを設計した本人は RISC-Vベンチャーの Esperanto Technologiesに就職しました。 David Ditzel氏
  43. 59.

    BOOMのダウンロードとビルド • ↑を実行するとツールチェインまで全部ダウンロードして時間 がかかるので 59 $ git clone https://github.com/esperantotech/boom-template.git --recurse-submodules

    $ git clone https://github.com/ccelio/boom-template.git $ cd boom-template $ git submodule update --init --recursive boom torture $ git submodule update rocket-chip $ cd rocket-chip $ git submodule update --init --recursive chisel3 firrtl hardfloat torture $ cd boom-template $ cd verisim # Verilatorを使う場合 $ cd vsim # Synopsys VCSを使う場合 $ make riscv-toolsを既にインストールしている場合、 全てダウンロードする必要はない
  44. 60.

    BOOMでベンチマークプログラムを実行 60 $ make run-bmark-tests ... ./emulator-freechips.rocketchip.system-DefaultConfig +max-cycles=100000000 +verbose output/towers.riscv

    3>&1 1>&2 2>&3 | /home/msyksphinz/riscv64/bin/spike-dasm > output/towers.riscv.out && [ $PIPESTATUS -eq 0 ] <<set terminal>> mcycle = 6334 minstret = 6170 <<reset terminal>> ./emulator-freechips.rocketchip.system-DefaultConfig +max-cycles=100000000 +verbose output/vvadd.riscv 3>&1 1>&2 2>&3 | /home/msyksphinz/riscv64/bin/spike-dasm > output/vvadd.riscv.out && [ $PIPESTATUS -eq 0 ] <<set terminal>> mcycle = 2512 minstret = 2420 <<reset terminal>> ./emulator-freechips.rocketchip.system-DefaultConfig +max-cycles=100000000 +verbose output/mt-matmul.riscv 3>&1 1>&2 2>&3 | /home/msyksphinz/riscv64/bin/spike-dasm > output/mt-matmul.riscv.out && [ $PIPESTATUS -eq 0 ] <<set terminal>> matmul(cid, nc, 16, input1_data, input2_data, results_data); barrier(nc): 41033 cycles, 10.0 cycles/iter, 1.5 CPI <<reset terminal>>
  45. 61.

    FPGA への実装 • ZedBoard向けに論理合成→インプリメント • UCBのfpga-zynqリポジトリが便利 • (https://github.com/ucb-bar/fpga-zynq) • インプリメントの手順は非常に単純

    • cd zedboard; make • 合成後binファイル (.bin) • FSBL, U-Boot, BOOT.binなどZynqの起動に必要なもの • PS部(ARM)で動作させるPeta-Linuxのビルド • RISC-Vで動作させるLinuxのビルド • 全部自動でやってくれる! • このフレームワークはRISC-Vだけで使うのは もったいない • SDカードに書き込むファイル群が ディレクトリにまとめて生成させるので、 SDカードにコピーするだけ fpga-zynq rocket-chip zedboard zynq zc706 sub-repo 合成ディレクトリ 合成ディレクトリ 合成ディレクトリ
  46. 62.

    Rocket-Chipの拡張機能 RoCC • RoCC (Rocket Custom Coprocessor) • Rocket Coreとダイレクトに接続

    (L1DC, External MemoryIFに接 続) • RISC-Vのカスタム命令の仕様と直結 CMD RESP RESP CMD Rocket Core L1 D- cache Accelerato r CMD RESP External ここを自作するこ とで、オリジナル 命令を作成できる custom0 rd, rs1, rs2 ・rd, rs1, rs2のレジスタアドレス情報 ・rs1, rs2 のレジスタデータ ・デコード情報など
  47. 63.

    Dot Product Acceleratorを作って Rocket Coreに接続した × 2つの行列のアドレスと長さを指定して、 自動的にデータをフェッチ+MAD処理をするアクセラレータ = 要素1つ

    分計算 ハードウェアを使って、メモリ のフェッチ処理とデータの演算 処理をオーバラップさせること で高速化を狙う CMD RESP RESP CMD Rocket Core L1 D-cache Accelerator CMD RESP External H_addr MAD V_addr
  48. 64.

    性能評価 ◼ZedBoardで動作させた ◼ SW: ソフトウェアで実行 ◼ HW1: ハードウェアで実行 ◼ 行列積を「行」→「列」の順番で実行

    ◼ HW2: ハードウェアで実行 ◼ 行列積を「列」→「行」の順番で実行 ◼ 行列のサイズが大きくなると、約4倍の性能向上 ◼ 行列積の計算の順番で、キャッシュのヒット率が変わる? 0 20000 40000 60000 80000 100000 120000 140000 160000 180000 2 x 2 x 2 4 x 4 x 4 8 x 8 x 8 16 x16 x16 17 x23 x27 サイクル数 行列サイズ Dot Product Acceleratorを使った行列積 サイクル数 SW HW1 HW2 0.0 1.0 2.0 3.0 4.0 5.0 2 x 2 x 2 4 x 4 x 4 8 x 8 x 8 16 x16 x16 17 x23 x27 性能比率 行列サイズ ソフトウェア実行を1とした場合の、 ハードウェア実行の性能向上率 SW/SW SW HW1 HW2 2 x 2 x 2 221 145 178 4 x 4 x 4 1284 512 539 8 x 8 x 8 8336 2510 2590 16 x16 x16 66735 16099 16161 17 x23 x27 164199 39571 39877 表1. サイクル数 SW/SW HW1/SW HW2/SW 2 x 2 x 2 1.000 1.524 1.242 4 x 4 x 4 1.000 2.508 2.382 8 x 8 x 8 1.000 3.321 3.219 16 x16 x16 1.000 4.145 4.129 17 x23 x27 1.000 4.149 4.118 表2. 性能向上比率
  49. 65.

    オリジナルカスタマイズの例: RISC-V+ディープラーニング ◼ カスタム命令を追加する ◼ 不要な機能を削除してダイエット ◼ 自社のIPをアクセラレータとして接続する (RoCC :

    Rocket Custom Coprocessor) CMD RESP RESP CMD Rocket Core L1 D-cache Accelerator CMD RESP External H_addr MAD V_addr Chiselで記述 図. Rocket-Chip on RISC-V上でMNISTを実行 Acceleration無し Acceleration IP接続
  50. 66.

    Dot Product Accelerator Block Diagram 66 DotProductF16 Fix16Mul a_data_queue b_data_queue

    ResultRAM InputRAM WeightRAM io.cmd a_address b_address io.mem.req io.mem.resp 実機Debug用 Data Logger データがOoOで返ってくる ためシリアライズが必須
  51. 67.

    ChiselでDot Product Acceleratorを作ろう 67 // MEMORY REQUEST INTERFACE io.mem.req.valid :=

    (r_cmd_state === s_mem_fetch) io.mem.req.bits.addr := w_addr io.mem.req.bits.tag := r_tag io.mem.req.bits.cmd := M_XRD // perform a load (M_XWR for stores) io.mem.req.bits.typ := MT_W // D = 8 bytes, W = 4, H = 2, B = 1 io.mem.req.bits.data := Bits(0) // we're not performing any stores... io.mem.req.bits.phys := Bool(false) io.mem.invalidate_lr := Bool(false) val a_data_queue = Module (new ReorderQueue(UInt(width=32), n-1)) a_data_queue.io.enq.valid := io.mem.resp.fire() && !io.mem.resp.bits.tag(h_v_bit) a_data_queue.io.enq.bits.data := io.mem.resp.bits.data a_data_queue.io.enq.bits.tag := io.mem.resp.bits.tag a_data_queue.io.deq.tag := Cat(data_tag_counter(n-2, h_v_bit), UInt(0, width=1), data_tag_counter(h_v_bit-1, 0)) when (a_data_queue.io.deq.matches && b_data_queue.io.deq.matches) { a_data_queue.io.deq.valid := Bool(true) data_tag_counter := data_tag_counter + UInt(1) } .otherwise { a_data_queue.io.deq.valid := Bool(false) } data_queue controller io.mem requester
  52. 68.

    ChiselでDot Product Acceleratorを作ろう 68 // int32_t AC = A*C; //

    int32_t AD_CB = A*D + C*B; // uint32_t BD = B*D; val w_ah_bh = Reg(SInt(width=32)) val w_ah_bl_al_bh = Reg(SInt(width=32)) val w_al_bl = Reg(UInt(width=32)) w_ah_bh := w_a_hi * w_b_hi w_ah_bl_al_bh := w_a_hi * w_b_lo + w_a_lo * w_b_hi w_al_bl := w_a_lo * w_b_lo val product_hi = Wire(SInt(width=32)) product_hi := w_ah_bh + w_ah_bl_al_bh(31,16).asSInt() val product_lo = Wire(UInt(width=32)) product_lo := w_al_bl + Cat(w_ah_bl_al_bh, UInt(0,width=16)) val product_hi2 = Wire(SInt(width=32)) when (product_lo < w_al_bl) { product_hi2 := product_hi + SInt(1) } .otherwise { product_hi2 := product_hi } f16 multiplier
  53. 69.

    C言語側から Dot Product Acceleratorを制御する 69 #define N (18) #define M

    (24) #define K (28) int main() { uint64_t cycle; int32_t output_data[N*K]; // Allocate Largest Size printf (" HW2, HW1, SW¥n"); for (int size = 2; size <=16; size *= 2) { printf ("%2d x%2d x%2d : ", size, size, size); cycle = matrixmul_hw1 (output_data, input1_data, input2_data, size, size, size, 0); printf ("%ld, ", cycle); printf ("¥n"); } return 0; }
  54. 70.

    C言語側から Dot Product Acceleratorを制御する 70 #define XCUSTOM_MATRIXMUL32 0 #define k_MTRXMUL_SETM

    (0) #define k_MTRXMUL_SETK (1) #define k_MTRXMUL_DOCALC (2) #define matrixmul32_setM(y, len) ¥ ROCC_INSTRUCTION(XCUSTOM_MATRIXMUL32, y, len, 0, k_MTRXMUL_SETM); #define matrixmul32_setK(y, len) ¥ ROCC_INSTRUCTION(XCUSTOM_MATRIXMUL32, y, len, 0, k_MTRXMUL_SETK); #define matrixmul32(y, mem_addr0, mem_addr1) ¥ ROCC_INSTRUCTION(XCUSTOM_MATRIXMUL32, y, mem_addr0, mem_addr1, k_MTRXMUL_DOCALC);
  55. 71.

    C言語側から Dot Product Acceleratorを制御する 71 #define CUSTOMX(X, rd, rs1, rs2,

    funct) ¥ CUSTOMX_OPCODE(X) | ¥ (rd << (7)) | ¥ (0x7 << (7+5)) | ¥ (rs1 << (7+5+3)) | ¥ (rs2 << (7+5+3+5)) | ¥ (EXTRACT(funct, 7, 0) << (7+5+3+5+5)) // Standard macro that passes rd, rs1, and rs2 via registers #define ROCC_INSTRUCTION(X, rd, rs1, rs2, funct) ¥ ROCC_INSTRUCTION_R_R_R(X, rd, rs1, rs2, funct, 10, 11, 12) // rd, rs1, and rs2 are data // rd_n, rs_1, and rs2_n are the register numbers to use #define ROCC_INSTRUCTION_R_R_R(X, rd, rs1, rs2, funct, rd_n, rs1_n, rs2_n) { ¥ register uint64_t rd_ asm ("x" # rd_n); ¥ register uint64_t rs1_ asm ("x" # rs1_n) = (uint64_t) rs1; ¥ register uint64_t rs2_ asm ("x" # rs2_n) = (uint64_t) rs2; ¥ asm volatile ( ¥ ".word " STR(CUSTOMX(X, rd_n, rs1_n, rs2_n, funct)) "¥n¥t" ¥ : "=r" (rd_) ¥ : [_rs1] "r" (rs1_), [_rs2] "r" (rs2_)); ¥ rd = rd_; ¥ }
  56. 72.

    RTLでDot Product Acceleratorの 動作を確認 72 $ make CONFIG=DefaultConfig output/train_twolayernet.riscv.out ./emulator-freechips.rocketchip.system-DefaultConfig

    +max- cycles=100000000 +verbose output/train_twolayernet.riscv 3>&1 1>&2 2>&3 | /home/msyksphinz/riscv64/bin/spike-dasm > output/train_twolayernet.riscv.out && [ $PIPESTATUS -eq 0 ] === TestNetwork === === TestNetwork === === start === Correct = 0 Correct = 1 Correct = 2 Correct = 3 Correct = 4 Fail = 5 Correct = 5 Time = 0114d6ae - 003e0a7d = 00d6cc31
  57. 74.

    Linuxがブートする RISC-Vシミュレータを作る • RISC-VのISAをしっかり理解したい • マニュアルを読むだけでは何が何だか分からないことが多い。 RISC-Vシミュレータを 自作する 目標1. コンプライアンステストをPassさせる

    目標2. Linuxをブートさせる 使用したRISC-V Linux : Freedom-U-SDKで公開されているLinuxバイナリ buildrootで1つのバイナリにまとめられている。Kernel v4.15 https://github.com/sifive/freedom-u-sdk で公開されており、ビルドできます。 ※ 上記に限らず、RISC-V向けにビルドしたLinuxディストリビューションは各種公開されている。 RedHat, Debian, … 今回はディスクイメージが1つにまとめられているので上記を使用。 あるものを理解したいとき、フルスクラッチで自分で 作ってみるの、おすすめです。
  58. 75.

    RISC-Vの命令セットシミュレータを作った pk (proxy kernel) RISC-V Instruction Set Simulator dtb Device

    Tree Blob Target Program Elf Log Files x86 Host Linux ※ pk(proxy kernel) RISC-Vのプログラムを動かすにあたり、システムコールを代わりに処理してくれる仕組み。 printf()やら、ファイルアクセスなどを代行できる (Linuxの起動には使用しません)。 参考にしたもの RISC-V ISA Spec Manual RISC-V Privileged Manual riscv-isa-sim 実装!! マニュアル見て意味が分からなかっ たら実装を見るのがおすすめ RISC-Vの仕様を、C++の実装 でほぼ忠実に再現してある。 GitHub公開中 : http://github.com/msyksphinz/swimmer_riscv Rocket-Chipを含め、多くの RISC-V実装は最初に Device Tree を読み込む
  59. 76.

    RISC-Vシミュレータの命令定義 76 命令フェッチ 命令デコード ADD命令実行 SUB命令実行 LD命令実行 SW命令実行 レジスタ デコード

    レジスタ デコード レジスタ デコード レジスタ デコード レジスタ リード 演算実行 レジスタ ライト レジスタ リード 演算実行 レジスタ ライト レジスタ リード レジスタ リード メモリ アクセス 例外判定 レジスタ ライト メモリ アクセス 例外判定
  60. 78.

    Linuxをブートしながら学んだ RISC-Vのすごいところ(仕様編) • 命令デコードがシンプルだが、C命令(Compressed命令)の理解は必須 • デコーダの設計はかなりシンプルで自動化できる • RISC-Vの真の性能を発揮したいなら、C命令はサポートすべき • スーパバイザに権限を移譲する”Delegation(移譲)”

    • Machine Modeで処理するのが面倒な例外はSupervisor Modeに移譲して動かす • コンテキストスイッチ時にレジスタ退避を簡略化するための仕組み • XS / FSビットフィールドにより、レジスタの書き換え発生を記憶している • mstatusシステムレジスタは過去の実行モードを記憶することが可能 • 例外処理に入る→復帰の処理が割と容易 スーパバイザモード マシンモード 例外発生 移譲 例外処理 例外から戻る ユーザモード スーパバイザモード マシンモード 例外発生 例外受付 動作モード変更 例外処理 例外から戻る ユーザモード 割り込み・例外の移譲を使う場合 割り込み・例外の移譲を使わない場合 こちらも参考になります : https://www.sifive.com/blog/2017/10/23/all-aboard-part-7-entering-and-exiting-the-linux- kernel-on-risc-v/
  61. 79.

    Linuxをブートしながら学んだ RISC-Vのすごいところ(環境編) • ツールがすべて公開されているので、デバッグが容易 • https://github.com/riscv/riscv-tools を参照のこと • テストセットもすべて公開されている •

    ISAのテストパタン riscv-tests / riscv-torture • ~な高速化技法試してみようかな→ 一旦テストセットで全部リグレッションを動かして確認
  62. 81.

    Open-Hardwareの目指すところ • ハードウェア設計・CPUアーキテクチャをオープンに 議論できる環境を構築する • 例: Meltdown / Spectre •

    例: Memory Consistency Model of RISC-V • RISC-Vのメモリコンシステンシモデルのバグを大学が発見 • 2018年はハードウェアを含め、セキュリティ界隈の話が多い • RISC-Vをベースにオープンなセキュリティプラットフォームの 構築を目指すKeystone
  63. 82.

    実チップ?FPGA?いえいえ、AWS FireSim : RISC-V Implementation on AWS F1 instance 複数FPGAを使って最大1024コアまで動作。

    GitHubで公開されている (https://github.com/firesim) 大規模FPGAの購入にはかなりのコスト高。200~300万円 FPGAを常に手元に置いておく必要がない。 必要な時に必要な分だけコストがかかる。 → コストダウン・参入障壁を下げる一要因になることを期待 FPGA-Accelerated Cycle-Exact Scale-Out System Simulation in the Public Cloud http://iscaconf.org/isca2018/slides/1A3.pdf
  64. 83.

    AWSを使ってRISC-Vを動かし Linuxをブートする お値段 : f1.2xlarge (Rocket-ChipならばSingle-Core) : 1.65USD/h f1.16xlarge (Rocket-Chipならば8-Core)

    : 13.20USD/h Single使用なら 個人でも何とか… (ちょっと見えにくいけど) AWS F1上でRISC-V Linuxがブート RISC-Vと関係なく、とりあえずAWSインスタンスを 試したいということも可能: AWS FPGAリポジトリ : https://github.com/aws/aws-fpga
  65. 85.

    • RISC-Vを取り巻く最新動向についてご紹介しました。 • RISC-Vの開発環境の構築方法について簡単にご説明し ました。 • シミュレータを使ったアプリケーションの実行 • RTLシミュレータを使ったRISC-Vコアの動作 •

    FPGAを使ったRISC-V + アクセラレータの実現 • 自作命令セットシミュレータを使ったLinuxのブート • RISC-Vと、オープンハードウェアが向かう未来につい て、その一端をご紹介しました。 85