在現在的世界,如果要講到指令集架構(ISA),腦海中第一個想到的不是 x86 就是 ARM 或 者 MIPS,然而如果想要自己製作一個 CPU 來玩,如果不透過現有的指令集的話,要從 CPU 打造到編譯器的撰寫、Linux 的移植又會花費大量的時間,有沒有一個現成且不需要商業授 權的指令集可以直接套用呢?有,那就是 RISC-V。
RISC-V (發音為: risk-five) 是由 UC Berkeley 所發展的開源 ISA,具有大約 100 個 指令,並且提供 16、32、64、128 等多種記憶體定址方式,更酷的事情是,RISC-V 已經具 有 Linux、GCC、LLVM、Yocto 等軟體支援,也就是說,任何人都可以基於 RISC-V 製作屬 於自己的 CPU,並且可以快速移植 Linux 上去。
聽起來很棒,那麼效能如何呢? 為了確認 RISC-V 的效能,UC Berkeley 設計出了一顆名為 Rocket 的 CPU,並選用了和 ARM Cortex-A5 相同的製成,由官方 資訊 來看,RISC-V 除 了晶片面積較小以外,運算速度也比較快,更重要的事情是,功耗更低,由此可見 RISC-V 有挑戰行動領域的王者 ARM 的淺力。
下表為 RISC-V 官網上針對 Rocket 與 ARM Cortex-A5 進行的對照表:
ISA Implementation | ARM Cortex-A5 | RISC-V Rocket | R/A |
---|---|---|---|
ISA Register Width | 32 bits | 64 bits | 2 |
Frequency | >1 GHz | >1 GHz | 1 |
Dhrystone Performance | 1.57 DMIPS/MHz | 1.72 DMIPS/MHz | 1.1 |
Area excluding caches | 0.27 mm² | 0.14 mm² | 0.5 |
Area with 16KB caches | 0.53 mm² | 0.39 mm² | 0.7 |
Area Efficiency | 2.96 DMIPS/MHz/mm² | 4.41 DMIPS/MHz/mm² | 1.5 |
Dynamic Power | <0.08 mW/MHz | 0.034 mW/MHz | >= 0.4 |
聽起來很棒對不對,本文將簡單介紹如何初步認識 RISC-V 的軟體與環境。
環境建立與 toolchain 編譯
為了可以執行 RISC-V 環境,我們首先要安裝 riscv-tools
套件,裡面包含了開發用的
toolchain 以及模擬器等 repo,我們可以使用以下命令取得 riscv-tool 並編譯
git clone https://github.com/riscv/riscv-tools.git cd riscv-tools git submodule update --init --recursive export RISCV=/path/to/install/riscv/toolchain ./build.sh
在我的 Gentoo Linux 這個編譯是非常愉快的,如果你編譯失敗的話請參考 riscv-tools 的 README.md 文件。 而在 Mac OSX 下則是有已經預先編譯好的套件可以安裝,我們可以使用 homebrew 來安裝 riscv-tools
coldnew@osx ~ $ brew tap ucb-bar/riscv && brew install riscv-tools
安裝完成後,我們系統會大致上增加以下這些命令
coldnew@osx ~ $ ls ${RISCV}/bin elf2hex riscv64-unknown-elf-gconv fesvr-eth riscv64-unknown-elf-gprof fesvr-rs232 riscv64-unknown-elf-ld fesvr-zenboard riscv64-unknown-elf-ld.bfd riscv64-unknown-elf-addr2line riscv64-unknown-elf-nm riscv64-unknown-elf-ar riscv64-unknown-elf-nm riscv64-unknown-elf-as riscv64-unknown-elf-objcopy riscv64-unknown-elf-c++ riscv64-unknown-elf-objdump riscv64-unknown-elf-c++filt riscv64-unknown-elf-ranlib riscv64-unknown-elf-cpp riscv64-unknown-elf-readelf riscv64-unknown-elf-elfedit riscv64-unknown-elf-size riscv64-unknown-elf-g++ riscv64-unknown-elf-strings riscv64-unknown-elf-gcc riscv64-unknown-elf-strip riscv64-unknown-elf-gcc-4.9.2 spike riscv64-unknown-elf-gcc-ar spike-dasm riscv64-unknown-elf-gcc-nm termios-xspike riscv64-unknown-elf-gcc-ranlib xspike
使用 Spike 來模擬編譯出來的程式
當你的 toolchain 編譯/安裝完成後,就讓我們先從 Hello World 來開始玩吧,首先建立
名為 hello.c
的檔案
#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello RISC-V\n"); return 0; }
接著使用 riscv64-unknown-elf-gcc
對其進行編譯成 hello 這個執行檔
coldnew@osx ~ $ riscv64-unknown-elf-gcc -O2 -o hello hello.c
如果你想更深入的理解編譯出來的 hello 這個靜態編譯 (static-linked) 的執行檔內容是
什麼,你可以透過 readelf
或是 objdump
來觀察他:
coldnew@osx ~ $ riscv64-unknown-elf-readelf -a hello | less
coldnew@osx ~ $ riscv64-unknown-elf-objdump -d hello | less
在目前的版本中,RISC-V 尚未支援 qemu-user 的功能,那我們要怎樣執行剛剛編譯出來的 hello 執行檔呢? 我們可以使用 Spkie - ISA Simulator 搭配 riscv-pk 來作為 qemu-user 的替代,執行方式如下
coldnew@osx ~ $ spike pk hello Hello RISC-V
使用 ANGEL 來測試 RSIC-V
ANGEL 是一款 RISC-V 基於 javascript 線上模擬器,類似 jslinux 那樣,只是模擬的平 台為 RISC-V 架構而已,你可以點擊以下連結去測試 ANGEL。
如果你對 ANGEL 有興趣,可以到這裡去看看他的原始碼: https://github.com/riscv/riscv-angel
使用 Yocto 來編譯 RISC-V Linux 系統
目前 RISC-V 雖然尚未被併入 Yocto 當中,但是 RISC-V 官方有提供 riscv-poky 好方便 我們測試 RISC-V 在 Linux 下的狀況,我們可以使用以下命令取得:
coldnew@osx ~ $ git clone https://github.com/riscv/riscv-poky.git
接著進入該資料夾
coldnew@osx ~ $ cd riscv-poky
再接下來則是和 Yocto 一樣的使用方式,首先先取得編譯環境用的環境變數
coldnew@osx ~/riscv-poky $ source oe-init-build-env
接著修改一下目標平台,預設是 qemuriscv64
,但是在本文撰寫時似乎執行 QEMU 會有
問題,因此請將 MACHINE
改為 riscv64
,我們將使用 spike 來進行 riscv 的模擬
coldnew@osx ~/riscv-poky/build $ vim conf/local.conf MACHINE="riscv64"
接下來就是編譯我們想要的目標: core-image-riscv
,這邊由於包含下載程式碼以及編譯,會耗費許多時間
coldnew@osx ~/riscv-poky/build $ bitbake core-image-riscv
在本篇文章撰寫的時候,riscv-poky 有 bug 會造成執行 spike 時不正常,因此最好不要在 conf/local.conf 加上 INHERIT += "rm_work" ,不然在執行 runspike 命令時他會 抱怨說找不到 riscv-pk 編譯出來的檔案 bbl (Berkeley Boot Loader)。
針對這個問題我已經發了 patch 來修正,請參閱: https://github.com/riscv/riscv-poky/pull/5
編譯完成後,我們就可以使用 runspike
來執行我們的 RISC-V Linux 環境
coldnew@osx ~/riscv-poky/build $ runspike riscv64 Continuing with the following parameters: KERNEL: [/Yocto/riscv-poky/build/tmp/deploy/images/riscv64/vmlinux-riscv64.bin] ROOTFS: [/Yocto/riscv-poky/build/tmp/deploy/images/riscv64/core-image-riscv-riscv64-20150914130848.rootfs.ext2] FSTYPE: [ext2] SPIKE_BIN: [/Yocto/riscv-poky/build/tmp/sysroots/x86_64-linux/usr/bin/spike] BBL_PATH: [/Yocto/riscv-poky/build/tmp/work/riscv64-poky-linux/riscv-pk/1.0-r0/bbl] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv rr vvvvvvvvvvvvvvvvvvvvvv rr vvvvvvvvvvvvvvvvvvvvvvvv rr rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr ..... Poky (Yocto Project Reference Distro) 1.8+snapshot-20150914 riscv64 /dev/ttyHTIF0 riscv64 login: root root@riscv64:~# cat /proc/cpuinfo hart : 0 isa : RV64G