top of page

【RISC-V/Chisel】パイプラインのストールで躓いたところ


はじめに

「RISC-VとChiselで学ぶ はじめてのCPU自作」をやっていて少し躓いたところがあるのでまとめておきます。

自分は今までソフトウェア中心にやってきたので回路設計の考え方に慣れないところがあります、、、



概要

該当の箇所は、パイプラインを実装する際に、「EXステージでjmp命令を検出したらIF、IDステージをストールする」という処理です。



レジスタとワイヤ

まず混乱の最大の原因はChiselで使われる2つの変数(CPUで用いられる2つの要素)についての理解が曖昧だったことですね。

まずはここを整理しておきます。


レジスタ(RegInit):

  • 順序論理回路

  • クロックが進むと値が更新される

ワイヤ(Wire):

  • 組み合わせ論理回路

  • 入力が即座に反映される


また、

val pc_plu4 = reg_pc + 4.U(32.W)

のように、RegInitでもWireでもない変数も定義可能ですが、これは回路図では、配線の途中の信号状態に名前をつけたもの、と解釈しています。



詳細

で、実際僕が躓いたのは以下の部分です。

この本の設計では、IFステージとIDステージの無効化のために以下のような処理を入れています。

val id_reg_inst = RegInit(0.U(32.W))
val exe_jmp_flg = Wire(Bool())

//・・・

//IF statge
//・・・
id_reg_inst:= MuxCase(if_inst, Seq(
     exe_jmp_flg -> BUBBLE,
   )
)
//ID statge
val id_inst = Mux(exe_jmp_flg, BUBBLE, id_reg_inst)

id_reg_inst:IDステージにおいて、指令を格納するレジスタ

if_inst:IFステージでフェッチしてきた指令値

exe_jmp_flag:指令がjmpかどうかを表すフラグ。EXステージで確定。


1つ目の式でIFステージを無効化し、2つ目でIDステージを無効化しています。



疑問1:2つ目の式いる?

id_reg_instはレジスタだから、次のサイクルまで値は変わりません。

そのため、2つ目の式でid_instにBUBBLEが反映されるのはjmpが確定した時(サイクルXとする)の次のサイクルからになります。

その場合、サイクルXで処理した結果はEXステージに流れてしまいます。



疑問2:なぜサイクルXの結果も無効化できる?

上記のように考えた時、次に出てきた疑問がこれです。

それは2つ目の式を入れても同じでは?id_instをBUBBLEにできるのはexe_jmp_flagの値が確定した次のサイクルからでは?


これに対する答えは「exe_jmp_flagはワイヤだから」ですね。

レジスタとは違いワイヤは値が確定した途端反映されるので、サイクルXにおいてid_instを書き換えることができます。


上記の勘違いが発生したもう一つの原因は、「書いたコードが上から下に、1度だけ実行される」と勘違いしていたことですね。

今はプログラミング言語でコードを書いてはいますが、実際は回路の設計をしています。

回路の各部品では入力信号が常に評価されています。

Wireは文字通り回路の部品間が結線されていると考えます。

exe_jmp_flagの値が変われば、Mux()の出力も変わります。



最後に

特に今までソフトウェア中心にやってきた人間にとっては、「実際には回路を設計している」という意識が必要ですね。

慣れないうちは頭の中に回路図を思い浮かべながらコーディングしていくのがよさそうです。


最新記事

すべて表示

【Chisel/scala】class Module is abstract; cannot be instantiated

現象 以下のchiselのコードで掲題のコンパイルエラーが発生 val parts = new Module(new MyParts()) class Module is abstract; cannot be instantiated 原因と解決策 Module()にnewをつけているのが原因。 newをつけるとコンストラクタと解釈されるが、Moduleは抽象クラスなのでコンストラクタはない。そ

【Chisel/scala】Bundleのメンバにハードウェアの配列を追加する

やりたいこと 掲題の通りだが、chiselのハードウェアの配列をBundleのメンバにを追加したい。どのような状況かというと、同じ回路を複数用意して並列処理をさせるということをしたい。 UIntの配列ならば簡単なのだが、配列のメンバがハードウェアの場合にかなりてこずった。 前提 Scalaの型、chiselの型、chiselのハードウェアがある Int、SeqはScalaの型 UInt、Vecはc

【Chisel/scala】overloaded method apply with alternatives

はじめに chiselでコードを書いていると、掲題のコンパイルエラーに時折遭遇する。 これの意味がいまいち分からなかったので調べてみた。 詳細 下記のエラーを例にとって一行ずつ見ていく overloaded method apply with alternatives: [error] [T <: chisel3.Data](elt0: T, elts: T*): chisel3.Vec[T]

Comments


あなたの買い物をサポートする
アプリ Shop Plan

iphone6.5p2.png

​いつ何を買うかの計画を立てられるアプリです。

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

靴を大切にしよう!靴管理アプリ SHOES_KEEP

納品:iPhone6.5①.png

靴の履いた回数、お手入れ回数を管理するアプリです。

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

「後で読む」を忘れないアプリ ArticleReminder

気になった​Webサイトを登録し、指定時刻にリマインダを送れるアプリです

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png
bottom of page