Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetchモジュール #16

Merged
merged 10 commits into from
May 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ lazy val root = (project in file("."))
name := "B4-processor"
)

// build.sbt
scalacOptions ++= Seq(
"-language:reflectiveCalls",
"-deprecation",
"-feature",
"-Xcheckinit",
"-P:chiselplugin:genBundleElements",
)

scalaVersion := "2.13.8"
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.5.3" cross CrossVersion.full)
libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.5.3"
Expand Down
17 changes: 17 additions & 0 deletions riscv-sample-programs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export CC := riscv64-elf-gcc
export OBJCOPY := riscv64-elf-objcopy
export CFLAGS := -nodefaultlibs -nostdlib -march=rv64i -mabi=lp64 -no-pie -static

SUBDIRS := branch

.PHONY: all, branch
all: $(SUBDIRS)

$(SUBDIRS):
$(MAKE) -C $@

SUBDIRS_CLEAN = $(addsuffix .clean, $(SUBDIRS))
$(SUBDIRS_CLEAN):
$(MAKE) -C $(basename $@) clean

clean: $(SUBDIRS_CLEAN)
20 changes: 20 additions & 0 deletions riscv-sample-programs/branch/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CFLAGS += -T ../linker.ld

.PHONY:clean
all: branch.8.hex branch.32.hex branch.o

branch.o: branch.S
@echo $(CC) $(CFLAGS)
$(CC) $(CFLAGS) $< -o $@

branch.binary: branch.o
$(OBJCOPY) -O binary -j .text $< $@

branch.8.hex: branch.binary
od -An -t x1 $< -w1 -v | tr -d " " > $@

branch.32.hex: branch.binary
od -An -t x4 $< -w4 -v | tr -d " " > $@

clean:
$(RM) *.hex *.binary *.o
7 changes: 7 additions & 0 deletions riscv-sample-programs/branch/branch.32.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
00200513
00300593
00a58633
00061663
00a00693
00000463
01400693
28 changes: 28 additions & 0 deletions riscv-sample-programs/branch/branch.8.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
13
05
20
00
93
05
30
00
33
86
a5
00
63
16
06
00
93
06
a0
00
63
04
00
00
93
06
40
01
12 changes: 12 additions & 0 deletions riscv-sample-programs/branch/branch.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.section .text.init
.global _start
_start:
li a0,2
li a1,3
add a2,a1,a0
bne a2,x0,LABEL
li a3,10
beq zero,zero,END
LABEL:
li a3,20
END:
Binary file added riscv-sample-programs/branch/branch.binary
Binary file not shown.
Binary file added riscv-sample-programs/branch/branch.o
Binary file not shown.
14 changes: 14 additions & 0 deletions riscv-sample-programs/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ENTRY(_start)

MEMORY{
ROM (rx) : ORIGIN = 0, LENGTH = 4k
}

SECTIONS{
.text :
{
*(.text.init)
*(.text*)
} > ROM
.data : { *(.data) } > ROM
}
8 changes: 7 additions & 1 deletion src/main/scala/b4processor/Parameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ package b4processor
* @param numberOfALUs ALUの数
* @param maxRegisterFileCommitCount リオーダバッファからレジスタファイルに1クロックでコミットする命令の数(Max)
* @param debug デバッグ機能を使う
* @param fetchWidth 命令フェッチ時にメモリから取出す命令数
* @param branchPredictionWidth 分岐予測で使う下位ビット数
* @param pcInit プログラムカウンタの初期値
*/
case class Parameters(tagWidth: Int = 6,
numberOfDecoders: Int = 2,
numberOfALUs: Int = 2,
maxRegisterFileCommitCount: Int = 4,
debug: Boolean = false)
fetchWidth: Int = 2,
branchPredictionWidth: Int = 4,
pcInit: Int = 0x0,
debug: Boolean = false)
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class Decoder2ReorderBuffer(implicit params: Parameters) extends Bundle {
val source1 = new SourceRegister()
val source2 = new SourceRegister()
val destination = new DestinationRegister()
val programCounter = Output(UInt(64.W))
val isPrediction = Output(Bool())
val programCounter = Output(SInt(64.W))
// 全体をDecoupledにするとsource1などがすべてOutputにってしまって、間違っているのでこちらに書く
val ready = Input(Bool())
val valid = Output(Bool())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ package b4processor.connections

import b4processor.Parameters
import chisel3._
import chisel3.util.ReadyValidIO

/**
* ALUからデコーダへバイパスされたデータを送る
*
* @param params パラメータ
*/
class ExecutionRegisterBypass(implicit val params: Parameters) extends Bundle {
class ExecutionRegisterBypass(implicit params: Parameters) extends Bundle {
val destinationTag = Output(UInt(params.tagWidth.W))
val value = Output(UInt(64.W))
val valid = Output(Bool())
Expand Down
15 changes: 15 additions & 0 deletions src/main/scala/b4processor/connections/ExecutorBranchResult.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package b4processor.connections

import chisel3._
import chisel3.experimental.BundleLiterals._

class ExecutorBranchResult extends Bundle {
val valid = Bool()
val branchAddress = SInt(64.W)
}

object ExecutorBranchResult {
def noResult(): ExecutorBranchResult = (new ExecutorBranchResult).Lit(_.valid -> false.B, _.branchAddress -> 0.S)

def branch(address: SInt): ExecutorBranchResult = (new ExecutorBranchResult).Lit(_.valid -> true.B, _.branchAddress -> address)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package b4processor.connections

import b4processor.Parameters
import chisel3._

class Fetch2BranchPrediction(implicit params: Parameters) extends Bundle {
val addressLowerBits = Output(UInt(params.branchPredictionWidth.W))
val isBranch = Output(Bool())
val prediction = Input(Bool())
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import chisel3.util.ReadyValidIO
/**
* 命令とデコーダをつなぐ
*/
class IMem2Decoder extends ReadyValidIO(new Bundle {
class Fetch2Decoder extends ReadyValidIO(new Bundle {
val instruction = UInt(64.W)
val programCounter = UInt(64.W)
val isPrediction = Bool()
val programCounter = SInt(64.W)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package b4processor.connections

import chisel3._
import chisel3.util._

class InstructionCache2Fetch extends Bundle {
val address = Input(SInt(64.W))
val output = Valid(UInt(32.W))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package b4processor.connections

import b4processor.Parameters
import chisel3._

class InstructionMemory2Cache(implicit params: Parameters) extends Bundle {
val address = Input(SInt(64.W))
val output = Output(Vec(params.fetchWidth, UInt(32.W)))
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ class ReservationStation2Executor(implicit params: Parameters) extends ReadyVali
val function3 = UInt(3.W)
val immediateOrFunction7 = UInt(12.W)
val opcode = UInt(7.W)
val programCounter = UInt(64.W)
val programCounter = SInt(64.W)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package b4processor.modules.branchprediction

import b4processor.Parameters
import b4processor.connections.Fetch2BranchPrediction
import chisel3._

/** 分岐予測モジュール */
class BranchPrediction(implicit params: Parameters) extends Module {
val io = IO(new Bundle {
val fetch = new Fetch2BranchPrediction
})
io.fetch.prediction := false.B
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package b4processor.modules.cache

import b4processor.Parameters
import b4processor.connections.{InstructionCache2Fetch, InstructionMemory2Cache}
import chisel3._
import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
import chisel3.stage.ChiselStage
import chisel3.util._

/** 命令キャッシュモジュール
*
* このモジュールは正確にはキャッシュとしては機能していないが、命令メモリとフェッチの間を取り持つ役割を持つ
* */
class InstructionMemoryCache(implicit params: Parameters) extends Module {
val io = IO(new Bundle {
/** フェッチ */
val fetch = Vec(params.numberOfDecoders, new InstructionCache2Fetch)
/** 命令メモリ */
val memory = Flipped(new InstructionMemory2Cache)
})

/** フェッチから要求された最初のアドレス */
val baseAddress = io.fetch(0).address

io.memory.address := baseAddress
io.fetch(0).output.bits := io.memory.output(0)
io.fetch(0).output.valid := true.B

for (i <- 1 until params.numberOfDecoders) {
// 命令メモリから取得した幅の中に要求したアドレスがあれば渡す
io.fetch(i).output := MuxCase(Valid(UInt(32.W)).Lit(_.valid -> false.B, _.bits -> 0.U),
io.memory.output.zipWithIndex.map { case (m, index) =>
(io.fetch(i).address === baseAddress + (4 * index).S) -> {
val w = Wire(Valid(UInt(32.W)))
w.valid := true.B
w.bits := m
w
}
}
)
}
}

object InstructionMemoryCache extends App {
implicit val params = Parameters()
(new ChiselStage).emitVerilog(new InstructionMemoryCache(), args = Array("--emission-options=disableMemRandomization,disableRegisterRandomization"))
}
44 changes: 21 additions & 23 deletions src/main/scala/b4processor/modules/decoder/Decoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import chisel3.util._
*/
class Decoder(instructionOffset: Int)(implicit params: Parameters) extends Module {
val io = IO(new Bundle {
val imem = Flipped(new IMem2Decoder())
val instructionFetch = Flipped(new Fetch2Decoder())
val reorderBuffer = new Decoder2ReorderBuffer
val alu = Vec(params.numberOfALUs, Flipped(new ExecutionRegisterBypass))
val registerFile = new Decoder2RegisterFile()
Expand All @@ -28,22 +28,22 @@ class Decoder(instructionOffset: Int)(implicit params: Parameters) extends Modul
})

// 命令からそれぞれの昨日のブロックを取り出す
val instRd = io.imem.bits.instruction(11, 7)
val instRs1 = io.imem.bits.instruction(19, 15)
val instRs2 = io.imem.bits.instruction(24, 20)
val instFunct3 = io.imem.bits.instruction(14, 12)
val instFunct7 = io.imem.bits.instruction(31, 25)
val instOp = io.imem.bits.instruction(6, 0)
val instImmI = io.imem.bits.instruction(31, 20)
val instImmS = Cat(io.imem.bits.instruction(31, 25), io.imem.bits.instruction(11, 7))
val instImmB = Cat(io.imem.bits.instruction(31), io.imem.bits.instruction(7), io.imem.bits.instruction(30, 25), io.imem.bits.instruction(11, 8))
val instImmU = io.imem.bits.instruction(31, 12)
val instImmJ = Cat(io.imem.bits.instruction(31), io.imem.bits.instruction(19, 12), io.imem.bits.instruction(20), io.imem.bits.instruction(30, 21))
val instRd = io.instructionFetch.bits.instruction(11, 7)
val instRs1 = io.instructionFetch.bits.instruction(19, 15)
val instRs2 = io.instructionFetch.bits.instruction(24, 20)
val instFunct3 = io.instructionFetch.bits.instruction(14, 12)
val instFunct7 = io.instructionFetch.bits.instruction(31, 25)
val instOp = io.instructionFetch.bits.instruction(6, 0)
val instImmI = io.instructionFetch.bits.instruction(31, 20)
val instImmS = Cat(io.instructionFetch.bits.instruction(31, 25), io.instructionFetch.bits.instruction(11, 7))
val instImmB = Cat(io.instructionFetch.bits.instruction(31), io.instructionFetch.bits.instruction(7), io.instructionFetch.bits.instruction(30, 25), io.instructionFetch.bits.instruction(11, 8))
val instImmU = io.instructionFetch.bits.instruction(31, 12)
val instImmJ = Cat(io.instructionFetch.bits.instruction(31), io.instructionFetch.bits.instruction(19, 12), io.instructionFetch.bits.instruction(20), io.instructionFetch.bits.instruction(30, 21))

// 即値を64bitに符号拡張
val immIExtended = Mux(instImmI(11), (!0.U(64.W)) & instImmI, 0.U(64.W) | instImmI)
val immUExtended = Cat(instImmU, 0.U(12.W))
val immJExtended = Mux(instImmU(19), (!0.U(64.W)) & Cat(instImmJ, 0.U(1.W)), 0.U(64.W) | Cat(instImmJ, 0.U(1.W)))
val immIExtended = instImmI.asSInt
val immUExtended = Cat(instImmU, 0.U(12.W)).asSInt
val immJExtended = Cat(instImmJ, 0.U(1.W)).asSInt

// オペコードが何形式かを調べるモジュール
val opcodeFormatChecker = Module(new OpcodeFormatChecker)
Expand All @@ -67,7 +67,7 @@ class Decoder(instructionOffset: Int)(implicit params: Parameters) extends Modul
opcodeFormatChecker.io.format === B

// リオーダバッファへの入力
io.reorderBuffer.programCounter := io.imem.bits.programCounter
io.reorderBuffer.programCounter := io.instructionFetch.bits.programCounter
io.reorderBuffer.source1.sourceRegister := Mux(source1IsValid,
instRs1,
0.U)
Expand All @@ -77,8 +77,6 @@ class Decoder(instructionOffset: Int)(implicit params: Parameters) extends Modul
io.reorderBuffer.destination.destinationRegister := Mux(destinationIsValid,
instRd,
0.U)
io.reorderBuffer.isPrediction := io.imem.bits.isPrediction


// レジスタファイルへの入力
io.registerFile.sourceRegister1 := instRs1
Expand Down Expand Up @@ -123,7 +121,7 @@ class Decoder(instructionOffset: Int)(implicit params: Parameters) extends Modul
valueSelector2.io.sourceTag <> sourceTag2
valueSelector2.io.reorderBufferValue <> io.reorderBuffer.source2.value
valueSelector2.io.registerFileValue := io.registerFile.value2
valueSelector2.io.immediateValue := MuxLookup(opcodeFormatChecker.io.format.asUInt, 0.U, Seq(
valueSelector2.io.immediateValue := MuxLookup(opcodeFormatChecker.io.format.asUInt, 0.S, Seq(
I.asUInt -> immIExtended,
U.asUInt -> immUExtended,
J.asUInt -> immJExtended
Expand Down Expand Up @@ -155,10 +153,10 @@ class Decoder(instructionOffset: Int)(implicit params: Parameters) extends Modul
io.reorderBuffer.source2.value.ready := true.B

// 命令をデコードするのはリオーダバッファにエントリの空きがあり、リザベーションステーションにも空きがあるとき
io.imem.ready := io.reservationStation.ready && io.reorderBuffer.ready
io.instructionFetch.ready := io.reservationStation.ready && io.reorderBuffer.ready
// リオーダバッファやリザベーションステーションに新しいエントリを追加するのは命令がある時
io.reorderBuffer.valid := io.imem.valid
io.reservationStation.entry.valid := io.imem.valid
io.reorderBuffer.valid := io.instructionFetch.valid
io.reservationStation.entry.valid := io.instructionFetch.valid

// RSへの出力を埋める
val rs = io.reservationStation.entry
Expand All @@ -176,7 +174,7 @@ class Decoder(instructionOffset: Int)(implicit params: Parameters) extends Modul
rs.ready2 := valueSelector2.io.value.valid
rs.value1 := valueSelector1.io.value.bits
rs.value2 := valueSelector2.io.value.bits
rs.programCounter := io.imem.bits.programCounter
rs.programCounter := io.instructionFetch.bits.programCounter
}

object Decoder extends App {
Expand Down
Loading