ひまわり

はやく人間になりたい

RISC-V systemからメモリマップがほしい

はじめに

lowRISC(RISC-Vの実装のRocket coreを含むシステム)のboot時のメモリマップの取得方法がわからなかったので調べた。

RISC-V Linux

riscv-linuxで検索してみると github.com sbi_query_memory と言う関数を呼び出しているらしく 更にその定義は,

arch/riscv/include/asm/sbi.h

...
unsigned long sbi_query_memory(unsigned long id, memory_block_info *p);
...

arch/riscv/kernel/sbi.S

.global sbi_query_memory; sbi_query_memory = -2016;
...

らしい

SBI

sbiとは一体なんなのか、それはriscv-privileged-v1.9のChapter 9に Supervisor Binary Interface (SBI)とある。 これは、仮想メモリ空間の上位2KiBに配置され、x0をbase registerとしてjalr命令で呼び出されるらしい。 (x0はzero registerだから常にリニアアドレス?) というか、RISC-Vとして定義されていることに驚いた。

sbi_query_memory

しかし、ここにはPreliminary list しか乗っておらず、sbi_query_memoryは見当たらない。

どうにかmemory mapの提供については、riscv sw dev メーリスでいくつか見ることができた。

特に二つ目で、議論されていたがまだ読み切れていないので、何かわかったら追記していきたい。
とりあえず今は、あるべきか、否かがまだ確定していないので、仕様として乗っていないのであろう。

少なくとも、Spike*1の現状の実装は、sbi_query_memoryは存在して、riscv-linux*2と、FreeBSD/RISC-V port*3はこれを使っている。

まとめ

現状仕様としては確率していないが、riscv linuxを含むいくつかの実装がこれに依存しているので環境によっては使える。 個人で何か作って、spikeやlowRISCで動かす分にはこれを使って、今後変更が有った際は、riscv linuxの実装読みに行くか、 Privileged ISA Specificationを読めばいいだろう。

まったく関係ない話

[llvm-dev] [RFC] RISC-V backend これもどうなったか調べたい

参照

おわり

ChiselでQuartusのRAM推論に引っかかる方法

自分の手元にあるDE0-Nano-SoCなどに乗っているCyclon V FPGAなどには
Logic Elementsとは別にメモリ用のブロックが内蔵されていて、Logic Elementの一部をメモリとして使うよりは
効率が良いのでできるだけ使っていきたい。

そしてQuartusはverilogのコードからメモリっぽいところを見つけ出して勝手に割り当ててくれる(手動で割り当てる方法もある)。

しかし、Chiselに組み込まれているMemをそのまま使いVerilogを生成すると
認識してくれないのでひと手間が必要になる。 そのひと手間が以下のコード。

gist06d941328baad1c607a87b46b03f4029

なにをしているのかというと、Memからの読み込みの際にRegisterを経由するのと、

when(Bool(true) {
...
}

ところで、なにも考えないとこれは意味ないのではとなるが。
この行により、同期回路として扱うことができ、そしてそうすることでRamやRomであろうと認識されて、割当がされる。

summaryは以下の通り

gist11d71c8654562e3ec3be044b93b85e97
Total Memory bitsが512となっている。

やったぜ。

ChiselでAXI書いた。

以下がリポジトリgithub.com

書いたと言ったが一部だけだし完全ではない、とりあえず動く程度。

scalaがいまいちよくわかってないのと、chiselもまだまだなので、今後綺麗にしたりしていきたい。 テストも書いてCIとか回していけたら捗るかな。

早いうちに、AXIについて説明をここに入れたい

Untethered lowRISC(RISC-V)について

Untetheredとは簡単にいうと、”他のメインのプロセッサの支援を得ずに直にI/O使うことができる実装”のことである。
この理解についてはIRCで説明が流れていたので間違っていないはず。

これだけだと分かりづらいので、
まずlowRISCにおけるtetheredについてを説明する。

Tethered とは?

lowRISCは初期段階としてzedboardの上で実装された。
これがRelease version 0.1(tagged memory)である。

tagged memoryが何なのかはもう少し理解が進んだらまとめようと思う。

このversion 0.1がtetheredな実装で、zedboardはAll Programable SoC(AP SoC)(AlteraではSoC FPGA?)と呼ばれるZynq7000 AP SoCを搭載し、
これは、以下のようにARMコアを持つPS(Processing system)部とPE(Programable Logic)部に分かれている
PS部とPL部との接続にAXIが使われている(lowRISCはNASTI)。

Zynq-7000 All Programmable SoC Overviewより抜粋 f:id:himaaaatti:20160826203821p:plain

分かりづらいが上の大部分を占めているのがProcessing System。

RocketChip(lowRISC Chip)からとの関係の図をlowRISCより
zynq_struct

lowRISCのコアは、PL部に実装されI/O(メモリ、SDなど)はPS部経由でアクセスしている。
この利点は、
自前のメモリやI/Oのコントローラを実装しなくとも、AXIのバスを通じてアクセスができることや、 メモリを共有*1するため、lowRISCが起動する前に、BIOSに当たる処理*2を行うことができることで、 システムを一旦動かすことができるのでこの方法を選択したのだと思う。

そして、
このPS部に実装の一部を担わせるシステムの事を"tethered"と言うのだと自分は理解している。 

Untetheredとは?

以上のことより、
一旦の実装のTetheredから、メモリ、I/Oコントローラーを実装しプロセッサシステムとして独立したものを"Untethered"と呼んでいる。

この文章は間違いを含んでいる可能性があるので、コメントなどで訂正をもらえると嬉しいです。

*1:lowRISCからは後半の256MBしか見えないようだが、どこでこれを実現しているのかわからない。

*2:riscv-fesvr