Compare commits
1 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
c8144787b0 | 4 months ago |
@ -0,0 +1,36 @@
|
||||
version = 2.6.4
|
||||
|
||||
maxColumn = 120
|
||||
align = most
|
||||
continuationIndent.defnSite = 2
|
||||
assumeStandardLibraryStripMargin = true
|
||||
docstrings = ScalaDoc
|
||||
lineEndings = preserve
|
||||
includeCurlyBraceInSelectChains = false
|
||||
danglingParentheses = true
|
||||
|
||||
align.tokens.add = [
|
||||
{
|
||||
code = ":"
|
||||
},
|
||||
{
|
||||
code = ":="
|
||||
},
|
||||
{
|
||||
code = "="
|
||||
},
|
||||
{
|
||||
code = "->"
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
newlines.alwaysBeforeCurlyBraceLambdaParams = false
|
||||
newlines.alwaysBeforeMultilineDef = false
|
||||
newlines.implicitParamListModifierForce = [before]
|
||||
|
||||
verticalMultiline.atDefnSite = true
|
||||
|
||||
optIn.annotationNewlines = true
|
||||
|
||||
rewrite.rules = [SortImports, PreferCurlyFors, AvoidInfix]
|
||||
@ -0,0 +1,46 @@
|
||||
BUILD_DIR = ./build
|
||||
DIFF_DIR = ../difftest/core
|
||||
DIFF_WORK_DIR = ../difftest
|
||||
|
||||
export PATH := $(PATH):$(abspath ./utils)
|
||||
|
||||
verilog:
|
||||
$(call git_commit, "generate verilog") # DO NOT REMOVE THIS LINE!!!
|
||||
$(MAKE) clean
|
||||
mkdir -p $(BUILD_DIR)
|
||||
mill -i __.test.runMain Elaborate -td $(BUILD_DIR)
|
||||
|
||||
test:
|
||||
@echo "make test"
|
||||
$(call git_commit, "test chisel module") # DO NOT REMOVE THIS LINE!!!
|
||||
$(MAKE) clean
|
||||
mkdir -p $(BUILD_DIR)
|
||||
mill -i __.test.runMain TestMain -td $(BUILD_DIR)
|
||||
|
||||
count:
|
||||
find ./playground/ -name "*.scala" | xargs wc -l
|
||||
|
||||
help:
|
||||
mill -i __.test.runMain Elaborate --help
|
||||
|
||||
compile:
|
||||
mill -i __.compile
|
||||
|
||||
bsp:
|
||||
mill -i mill.bsp.BSP/install
|
||||
|
||||
reformat:
|
||||
mill -i __.reformat
|
||||
|
||||
checkformat:
|
||||
mill -i __.checkFormat
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILD_DIR)
|
||||
|
||||
.PHONY: test verilog help compile bsp reformat checkformat clean
|
||||
|
||||
sim:
|
||||
@echo "Write this Makefile by yourself."
|
||||
|
||||
-include ../Makefile
|
||||
@ -0,0 +1,38 @@
|
||||
# Chisel Project Template
|
||||
|
||||
Another version of the [Chisel template](https://github.com/ucb-bar/chisel-template) supporting mill.
|
||||
mill is another Scala/Java build tool without obscure DSL like SBT. It is much faster than SBT.
|
||||
|
||||
Contents at a glance:
|
||||
|
||||
- `.gitignore` - helps Git ignore junk like generated files, build products, and temporary files.
|
||||
- `build.sc` - instructs mill to build the Chisel project
|
||||
- `Makefile` - rules to call mill
|
||||
- `playground/src/GCD.scala` - GCD source file
|
||||
- `playground/src/DecoupledGCD.scala` - another GCD source file
|
||||
- `playground/src/Elaborate.scala` - wrapper file to call chisel command with the GCD module
|
||||
- `playground/test/src/GCDSpec.scala` - GCD tester
|
||||
|
||||
Feel free to rename or delete files under `playground/` or use them as a reference/template.
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, install mill by referring to the documentation [here](https://com-lihaoyi.github.io/mill).
|
||||
|
||||
To run all tests in this design (recommended for test-driven development):
|
||||
|
||||
```bash
|
||||
make test
|
||||
```
|
||||
|
||||
To generate Verilog:
|
||||
|
||||
```bash
|
||||
make verilog
|
||||
```
|
||||
|
||||
## Change FIRRTL Compiler
|
||||
|
||||
You can change the FIRRTL compiler between SFC (Scala-based FIRRTL compiler) and
|
||||
MFC (MLIR-based FIRRTL compiler) by modifying the `useMFC` variable in `playground/src/Elaborate.scala`.
|
||||
The latter one requires `firtool`, which is included under `utils/`.
|
||||
@ -0,0 +1,45 @@
|
||||
// import Mill dependency
|
||||
import mill._
|
||||
import mill.scalalib._
|
||||
import mill.scalalib.scalafmt.ScalafmtModule
|
||||
import mill.scalalib.TestModule.ScalaTest
|
||||
// support BSP
|
||||
import mill.bsp._
|
||||
|
||||
object playground extends ScalaModule with ScalafmtModule { m =>
|
||||
val useChisel5 = false
|
||||
val useChisel6 = true
|
||||
override def scalaVersion = "2.13.10"
|
||||
override def scalacOptions = Seq(
|
||||
"-language:reflectiveCalls",
|
||||
"-deprecation",
|
||||
"-feature",
|
||||
"-Xcheckinit"
|
||||
)
|
||||
override def ivyDeps = Agg(
|
||||
if (useChisel5) ivy"org.chipsalliance::chisel:5.0.0"
|
||||
else if (useChisel6) ivy"org.chipsalliance::chisel:6.1.0"
|
||||
else
|
||||
ivy"edu.berkeley.cs::chisel3:3.6.0"
|
||||
)
|
||||
override def scalacPluginIvyDeps = Agg(
|
||||
if (useChisel5) ivy"org.chipsalliance:::chisel-plugin:5.0.0"
|
||||
else if (useChisel6) ivy"org.chipsalliance:::chisel-plugin:6.1.0"
|
||||
else
|
||||
ivy"edu.berkeley.cs:::chisel3-plugin:3.6.0"
|
||||
)
|
||||
object test extends ScalaTests with ScalaTest {
|
||||
override def ivyDeps = m.ivyDeps() ++ Agg(
|
||||
ivy"com.lihaoyi::utest:0.8.1",
|
||||
if (useChisel5 || useChisel6) ivy"edu.berkeley.cs::chiseltest:5.0.0"
|
||||
else
|
||||
ivy"edu.berkeley.cs::chiseltest:0.6.0"
|
||||
)
|
||||
}
|
||||
def repositoriesTask = T.task {
|
||||
Seq(
|
||||
coursier.MavenRepository("https://maven.aliyun.com/repository/central"),
|
||||
coursier.MavenRepository("https://repo.scala-sbt.org/scalasbt/maven-releases")
|
||||
) ++ super.repositoriesTask()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
module top(
|
||||
input clock,
|
||||
input reset,
|
||||
// Interrupts
|
||||
input mei, // to PLIC
|
||||
input msi, // to CLINT
|
||||
input mti, // to CLINT
|
||||
input sei, // to PLIC
|
||||
// inst sram interface
|
||||
output inst_sram_en,
|
||||
output [ 3:0] inst_sram_wen,
|
||||
output [31:0] inst_sram_addr,
|
||||
output [31:0] inst_sram_wdata,
|
||||
input [31:0] inst_sram_rdata,
|
||||
// data sram interface
|
||||
output data_sram_en,
|
||||
output [ 7:0] data_sram_wen,
|
||||
output [31:0] data_sram_addr,
|
||||
output [63:0] data_sram_wdata,
|
||||
input [63:0] data_sram_rdata,
|
||||
// trace debug interface
|
||||
output debug_commit,
|
||||
output [63:0] debug_pc,
|
||||
output [4:0 ] debug_rf_wnum,
|
||||
output [63:0] debug_rf_wdata
|
||||
);
|
||||
|
||||
PuaCpu core(
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
// interrupts
|
||||
.io_ext_int_mei (mei),
|
||||
.io_ext_int_mti (mti),
|
||||
.io_ext_int_msi (msi),
|
||||
// inst sram interface
|
||||
.io_inst_sram_en (inst_sram_en),
|
||||
.io_inst_sram_wen (inst_sram_wen),
|
||||
.io_inst_sram_addr (inst_sram_addr),
|
||||
.io_inst_sram_wdata (inst_sram_wdata),
|
||||
.io_inst_sram_rdata (inst_sram_rdata),
|
||||
// data sram interface
|
||||
.io_data_sram_en (data_sram_en),
|
||||
.io_data_sram_wen (data_sram_wen),
|
||||
.io_data_sram_addr (data_sram_addr),
|
||||
.io_data_sram_wdata (data_sram_wdata),
|
||||
.io_data_sram_rdata (data_sram_rdata),
|
||||
// debug
|
||||
.io_debug_pc (debug_pc),
|
||||
.io_debug_commit (debug_commit),
|
||||
.io_debug_rf_wnum (debug_rf_wnum),
|
||||
.io_debug_rf_wdata (debug_rf_wdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
@ -0,0 +1,9 @@
|
||||
import cpu._
|
||||
import circt.stage._
|
||||
|
||||
object Elaborate extends App {
|
||||
implicit val cpuConfig = new CpuConfig()
|
||||
def top = new PuaCpu()
|
||||
val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top))
|
||||
(new ChiselStage).execute(args, generator :+ CIRCTTargetAnnotation(CIRCTTarget.Verilog))
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu._
|
||||
import cpu.defines._
|
||||
|
||||
class PuaCpu extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val ext_int = Input(new ExtInterrupt())
|
||||
val inst_sram = new InstSram()
|
||||
val data_sram = new DataSram()
|
||||
val debug = new DEBUG()
|
||||
})
|
||||
|
||||
val core = Module(new Core())
|
||||
|
||||
io.ext_int <> core.io.interrupt
|
||||
io.inst_sram <> core.io.instSram
|
||||
io.data_sram <> core.io.dataSram
|
||||
io.debug <> core.io.debug
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package cpu.defines
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.CpuConfig
|
||||
|
||||
trait CoreParameter {
|
||||
def cpuConfig = new CpuConfig
|
||||
val XLEN = if (cpuConfig.isRV32) 32 else 64
|
||||
val VADDR_WID = if (cpuConfig.isRV32) 32 else 39
|
||||
val PADDR_WID = 32
|
||||
}
|
||||
|
||||
trait Constants extends CoreParameter {
|
||||
// 全局
|
||||
val PC_INIT = "h80000000".U(XLEN.W)
|
||||
|
||||
val INT_WID = 12
|
||||
val EXC_WID = 16
|
||||
|
||||
// inst rom
|
||||
val INST_WID = 32
|
||||
|
||||
// GPR RegFile
|
||||
val AREG_NUM = 32
|
||||
val REG_ADDR_WID = 5
|
||||
}
|
||||
|
||||
trait SRAMConst extends Constants {
|
||||
val SRAM_ADDR_WID = PADDR_WID // 32
|
||||
val DATA_SRAM_DATA_WID = XLEN
|
||||
val DATA_SRAM_WEN_WID = XLEN / 8
|
||||
val INST_SRAM_DATA_WID = INST_WID
|
||||
val INST_SRAM_WEN_WID = INST_WID / 8
|
||||
}
|
||||
object Const extends Constants with SRAMConst
|
||||
|
||||
object Instructions extends HasInstrType with CoreParameter {
|
||||
def NOP = 0x00000013.U
|
||||
val DecodeDefault = List(InstrN, FuType.alu, ALUOpType.add)
|
||||
def DecodeTable = RVIInstr.table
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cpu.defines
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
object SignedExtend {
|
||||
def apply(a: UInt, len: Int) = {
|
||||
val aLen = a.getWidth
|
||||
val signBit = a(aLen - 1)
|
||||
if (aLen >= len) a(len - 1, 0) else Cat(Fill(len - aLen, signBit), a)
|
||||
}
|
||||
}
|
||||
|
||||
object ZeroExtend {
|
||||
def apply(a: UInt, len: Int) = {
|
||||
val aLen = a.getWidth
|
||||
if (aLen >= len) a(len - 1, 0) else Cat(0.U((len - aLen).W), a)
|
||||
}
|
||||
}
|
||||
|
||||
object LookupTree {
|
||||
def apply[T <: Data](key: UInt, mapping: Iterable[(UInt, T)]): T =
|
||||
Mux1H(mapping.map(p => (p._1 === key, p._2)))
|
||||
}
|
||||
|
||||
object LookupTreeDefault {
|
||||
def apply[T <: Data](key: UInt, default: T, mapping: Iterable[(UInt, T)]): T =
|
||||
MuxLookup(key, default)(mapping.toSeq)
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package cpu.defines
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
// 指令类型
|
||||
trait HasInstrType {
|
||||
def InstrN = "b000".U
|
||||
def InstrI = "b100".U
|
||||
def InstrR = "b101".U
|
||||
def InstrS = "b010".U
|
||||
def InstrB = "b001".U
|
||||
def InstrU = "b110".U
|
||||
def InstrJ = "b111".U
|
||||
|
||||
// I、R、U、J类型的指令都需要写寄存器
|
||||
def isRegWen(instrType: UInt): Bool = instrType(2)
|
||||
}
|
||||
|
||||
// 功能单元类型 Function Unit Type
|
||||
object FuType {
|
||||
def num = 1
|
||||
def alu = 0.U // arithmetic logic unit
|
||||
def apply() = UInt(log2Up(num).W)
|
||||
}
|
||||
|
||||
// 功能单元操作类型 Function Unit Operation Type
|
||||
object FuOpType {
|
||||
def apply() = UInt(5.W) // 宽度与最大的功能单元操作类型宽度一致
|
||||
}
|
||||
|
||||
// 算术逻辑单元操作类型 Arithmetic Logic Unit Operation Type
|
||||
object ALUOpType {
|
||||
def add = "b00000".U
|
||||
// TODO: 定义更多的ALU操作类型
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class IfIdData extends Bundle {
|
||||
val inst = UInt(XLEN.W)
|
||||
val valid = Bool()
|
||||
val pc = UInt(XLEN.W)
|
||||
}
|
||||
|
||||
class FetchUnitDecodeUnit extends Bundle {
|
||||
val data = Output(new IfIdData())
|
||||
}
|
||||
|
||||
class DecodeStage extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val fetchUnit = Flipped(new FetchUnitDecodeUnit())
|
||||
val decodeUnit = new FetchUnitDecodeUnit()
|
||||
})
|
||||
|
||||
val data = RegInit(0.U.asTypeOf(new IfIdData()))
|
||||
|
||||
data := io.fetchUnit.data
|
||||
|
||||
io.decodeUnit.data := data
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
|
||||
class DecodeUnit extends Module {
|
||||
val io = IO(new Bundle {
|
||||
// 输入
|
||||
val decodeStage = Flipped(new FetchUnitDecodeUnit())
|
||||
val regfile = new Src12Read()
|
||||
// 输出
|
||||
val executeStage = Output(new DecodeUnitExecuteUnit())
|
||||
})
|
||||
|
||||
// 译码阶段完成指令的译码操作以及源操作数的准备
|
||||
|
||||
val decoder = Module(new Decoder()).io
|
||||
decoder.in.inst := io.decodeStage.data.inst
|
||||
|
||||
val pc = io.decodeStage.data.pc
|
||||
val info = Wire(new Info())
|
||||
|
||||
info := decoder.out.info
|
||||
info.valid := io.decodeStage.data.valid
|
||||
|
||||
// TODO:完成寄存器堆的读取
|
||||
// io.regfile.src1.raddr :=
|
||||
// io.regfile.src2.raddr :=
|
||||
|
||||
// TODO: 完成DecodeUnit模块的逻辑
|
||||
// io.executeStage.data.pc :=
|
||||
// io.executeStage.data.info :=
|
||||
// io.executeStage.data.src_info.src1_data :=
|
||||
// io.executeStage.data.src_info.src2_data :=
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class IdExeData extends Bundle {
|
||||
val pc = UInt(XLEN.W)
|
||||
val info = new Info()
|
||||
val src_info = new SrcInfo()
|
||||
}
|
||||
|
||||
class DecodeUnitExecuteUnit extends Bundle {
|
||||
val data = new IdExeData()
|
||||
}
|
||||
|
||||
class ExecuteStage extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val decodeUnit = Input(new DecodeUnitExecuteUnit())
|
||||
val executeUnit = Output(new DecodeUnitExecuteUnit())
|
||||
})
|
||||
|
||||
val data = RegInit(0.U.asTypeOf(new IdExeData()))
|
||||
|
||||
// TODO: 完成ExecuteStage模块的逻辑
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.CpuConfig
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import chisel3.util.experimental.BoringUtils
|
||||
|
||||
class ExecuteUnit extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val executeStage = Input(new DecodeUnitExecuteUnit())
|
||||
val memoryStage = Output(new ExecuteUnitMemoryUnit())
|
||||
val dataSram = new DataSram()
|
||||
})
|
||||
|
||||
// 执行阶段完成指令的执行操作
|
||||
|
||||
val fu = Module(new Fu()).io
|
||||
fu.data.pc := io.executeStage.data.pc
|
||||
fu.data.info := io.executeStage.data.info
|
||||
fu.data.src_info := io.executeStage.data.src_info
|
||||
|
||||
io.dataSram <> fu.dataSram
|
||||
|
||||
// TODO: 完成ExecuteUnit模块的逻辑
|
||||
// io.memoryStage.data.pc :=
|
||||
// io.memoryStage.data.info :=
|
||||
// io.memoryStage.data.src_info :=
|
||||
// io.memoryStage.data.rd_info :=
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class Fu extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val data = new Bundle {
|
||||
val pc = Input(UInt(XLEN.W))
|
||||
val info = Input(new Info())
|
||||
val src_info = Input(new SrcInfo())
|
||||
val rd_info = Output(new RdInfo())
|
||||
}
|
||||
|
||||
val dataSram = new DataSram()
|
||||
})
|
||||
|
||||
val alu = Module(new Alu()).io
|
||||
|
||||
io.dataSram.en := false.B
|
||||
io.dataSram.addr := DontCare
|
||||
io.dataSram.wdata := DontCare
|
||||
io.dataSram.wen := 0.U
|
||||
|
||||
alu.info := io.data.info
|
||||
alu.src_info := io.data.src_info
|
||||
|
||||
io.data.rd_info.wdata := alu.result
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
|
||||
class Alu extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val info = Input(new Info())
|
||||
val src_info = Input(new SrcInfo())
|
||||
val result = Output(UInt(XLEN.W))
|
||||
})
|
||||
// TODO: 完成ALU模块的逻辑
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
import cpu.defines._
|
||||
|
||||
class FetchUnit extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val decodeStage = new FetchUnitDecodeUnit()
|
||||
val instSram = new InstSram()
|
||||
})
|
||||
|
||||
val boot :: send :: receive :: Nil = Enum(3)
|
||||
val state = RegInit(boot)
|
||||
|
||||
switch(state) {
|
||||
is(boot) {
|
||||
state := send
|
||||
}
|
||||
is(send) {
|
||||
state := receive
|
||||
}
|
||||
is(receive) {}
|
||||
}
|
||||
|
||||
// 取指阶段完成指令的取指操作
|
||||
|
||||
val pc = RegEnable(io.instSram.addr, (PC_INIT - 4.U), state =/= boot)
|
||||
|
||||
io.instSram.addr := pc + 4.U
|
||||
|
||||
io.decodeStage.data.valid := state === receive
|
||||
io.decodeStage.data.pc := pc
|
||||
io.decodeStage.data.inst := io.instSram.rdata
|
||||
|
||||
io.instSram.en := !reset.asBool
|
||||
io.instSram.wen := 0.U
|
||||
io.instSram.wdata := 0.U
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class ExeMemData extends Bundle {
|
||||
val pc = UInt(XLEN.W)
|
||||
val info = new Info()
|
||||
val rd_info = new RdInfo()
|
||||
val src_info = new SrcInfo()
|
||||
}
|
||||
|
||||
class ExecuteUnitMemoryUnit extends Bundle {
|
||||
val data = new ExeMemData()
|
||||
}
|
||||
|
||||
class MemoryStage extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val executeUnit = Input(new ExecuteUnitMemoryUnit())
|
||||
val memoryUnit = Output(new ExecuteUnitMemoryUnit())
|
||||
})
|
||||
|
||||
val data = RegInit(0.U.asTypeOf(new ExeMemData()))
|
||||
|
||||
// TODO: 完成MemoryStage模块的逻辑
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.util.experimental.BoringUtils
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class MemoryUnit extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val memoryStage = Input(new ExecuteUnitMemoryUnit())
|
||||
val writeBackStage = Output(new MemoryUnitWriteBackUnit())
|
||||
})
|
||||
|
||||
// 访存阶段完成指令的访存操作
|
||||
|
||||
io.writeBackStage.data.pc := io.memoryStage.data.pc
|
||||
io.writeBackStage.data.info := io.memoryStage.data.info
|
||||
io.writeBackStage.data.rd_info.wdata := io.memoryStage.data.rd_info.wdata
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class MemWbData extends Bundle {
|
||||
val pc = UInt(XLEN.W)
|
||||
val info = new Info()
|
||||
val rd_info = new RdInfo()
|
||||
}
|
||||
|
||||
class MemoryUnitWriteBackUnit extends Bundle {
|
||||
val data = new MemWbData()
|
||||
}
|
||||
class WriteBackStage extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val memoryUnit = Input(new MemoryUnitWriteBackUnit())
|
||||
val writeBackUnit = Output(new MemoryUnitWriteBackUnit())
|
||||
})
|
||||
|
||||
val data = RegInit(0.U.asTypeOf(new MemWbData()))
|
||||
|
||||
// TODO: 完成WriteBackStage模块的逻辑
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package cpu.pipeline
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class WriteBackUnit extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val writeBackStage = Input(new MemoryUnitWriteBackUnit())
|
||||
val regfile = Output(new RegWrite())
|
||||
val debug = new DEBUG()
|
||||
})
|
||||
|
||||
// 写回阶段完成数据的写回操作
|
||||
// 同时该阶段还负责差分测试的比对工作
|
||||
// TODO: 完成WriteBackUnit模块的逻辑
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// import cpu._
|
||||
// import circt.stage._
|
||||
|
||||
// object TestMain extends App {
|
||||
// implicit val cpuConfig = new CpuConfig()
|
||||
// def top = new Top()
|
||||
// val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top))
|
||||
// (new ChiselStage).execute(args, generator :+ CIRCTTargetAnnotation(CIRCTTarget.Verilog))
|
||||
// }
|
||||
@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
firtool.elf.strip --lowering-options=disallowLocalVariables,disallowPackedArrays,locationInfoStyle=wrapInAtSquareBracket $@
|
||||
Binary file not shown.
@ -0,0 +1,54 @@
|
||||
module top(
|
||||
input clock,
|
||||
input reset,
|
||||
// Interrupts
|
||||
input mei, // to PLIC
|
||||
input msi, // to CLINT
|
||||
input mti, // to CLINT
|
||||
input sei, // to PLIC
|
||||
// inst sram interface
|
||||
output inst_sram_en,
|
||||
output [ 3:0] inst_sram_wen,
|
||||
output [31:0] inst_sram_addr,
|
||||
output [31:0] inst_sram_wdata,
|
||||
input [31:0] inst_sram_rdata,
|
||||
// data sram interface
|
||||
output data_sram_en,
|
||||
output [ 7:0] data_sram_wen,
|
||||
output [31:0] data_sram_addr,
|
||||
output [63:0] data_sram_wdata,
|
||||
input [63:0] data_sram_rdata,
|
||||
// trace debug interface
|
||||
output debug_commit,
|
||||
output [63:0] debug_pc,
|
||||
output [4:0 ] debug_rf_wnum,
|
||||
output [63:0] debug_rf_wdata
|
||||
);
|
||||
|
||||
PuaCpu core(
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
// interrupts
|
||||
.io_ext_int_mei (mei),
|
||||
.io_ext_int_mti (mti),
|
||||
.io_ext_int_msi (msi),
|
||||
// inst sram interface
|
||||
.io_inst_sram_en (inst_sram_en),
|
||||
.io_inst_sram_wen (inst_sram_wen),
|
||||
.io_inst_sram_addr (inst_sram_addr),
|
||||
.io_inst_sram_wdata (inst_sram_wdata),
|
||||
.io_inst_sram_rdata (inst_sram_rdata),
|
||||
// data sram interface
|
||||
.io_data_sram_en (data_sram_en),
|
||||
.io_data_sram_wen (data_sram_wen),
|
||||
.io_data_sram_addr (data_sram_addr),
|
||||
.io_data_sram_wdata (data_sram_wdata),
|
||||
.io_data_sram_rdata (data_sram_rdata),
|
||||
// debug
|
||||
.io_debug_pc (debug_pc),
|
||||
.io_debug_commit (debug_commit),
|
||||
.io_debug_rf_wnum (debug_rf_wnum),
|
||||
.io_debug_rf_wdata (debug_rf_wdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
@ -1,17 +0,0 @@
|
||||
`ifndef MYCPU_H
|
||||
`define MYCPU_H
|
||||
`define XLEN 64
|
||||
// IF_ID_WID = valid + pc + inst = 1 + 64 + 64 = 129
|
||||
`define IF_ID_WID 129
|
||||
`define FU_OP_TYPE_WID 5
|
||||
// INFO_WID = src1_addr + src2_addr + reg_wen + reg_waddr + op
|
||||
// = 5 + 5 + 1 + 5 + `FU_OP_TYPE_WID = 16 + `FU_OP_TYPE_WID
|
||||
`define INFO_WID (16 +`FU_OP_TYPE_WID)
|
||||
// ID_EXE_WID = valid + pc + op + reg_wen + reg_waddr + src1_rdata + src2_rdata
|
||||
// = 1 + 64 + `FU_OP_TYPE_WID + 1 + 5 + 64 + 64 = 199 + `FU_OP_TYPE_WID
|
||||
`define ID_EXE_WID (199 + `FU_OP_TYPE_WID)
|
||||
// EXE_MEM_WID = valid + pc + reg_wen + reg_waddr + reg_wdata
|
||||
// = 1 + 64 + 1 + 5 + 64 = 135
|
||||
`define EXE_MEM_WID 135
|
||||
`define MEM_WB_WID 135
|
||||
`endif
|
||||
@ -1,41 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module DecodeUnit(
|
||||
// 来自DecodeStage的输入
|
||||
input [`IF_ID_WID - 1: 0] decodeStage,
|
||||
// 与ARegfile的接口
|
||||
output [4: 0] src1_raddr,
|
||||
input [`XLEN - 1: 0] src1_rdata,
|
||||
output [4: 0] src2_raddr,
|
||||
input [`XLEN - 1: 0] src2_rdata,
|
||||
// 输出至ExecuteStage的接口
|
||||
output [`ID_EXE_WID - 1: 0] executeStage
|
||||
);
|
||||
|
||||
wire valid;
|
||||
wire [`XLEN - 1: 0] pc;
|
||||
wire [`XLEN - 1: 0] inst;
|
||||
assign {valid, pc, inst} = decodeStage;
|
||||
|
||||
// outports wire
|
||||
wire [`INFO_WID - 1: 0] info;
|
||||
|
||||
// TODO: 完成译码器的实例化
|
||||
|
||||
wire [`FU_OP_TYPE_WID - 1: 0] op;
|
||||
wire reg_wen;
|
||||
wire [4: 0] reg_waddr;
|
||||
|
||||
assign {src1_raddr, src2_raddr, op, reg_wen, reg_waddr} = info;
|
||||
|
||||
assign executeStage = {
|
||||
valid,
|
||||
pc,
|
||||
op,
|
||||
reg_wen,
|
||||
reg_waddr,
|
||||
src1_rdata,
|
||||
src2_rdata
|
||||
};
|
||||
|
||||
endmodule
|
||||
@ -1,45 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module Decoder(
|
||||
input [`XLEN - 1: 0] inst,
|
||||
output [`INFO_WID - 1: 0] info
|
||||
);
|
||||
|
||||
// TODO: 完成译码器逻辑
|
||||
wire [6: 0] opcode = inst[6: 0];
|
||||
// wire [2: 0] funct3 =
|
||||
// wire [6: 0] funct7 =
|
||||
// wire [4: 0] rs =
|
||||
// wire [4: 0] rt =
|
||||
// wire [4: 0] rd =
|
||||
|
||||
wire inst_add = (opcode == 7'b0110011) && (funct3 == 3'b000) && (funct7 == 7'b0000000);
|
||||
// wire inst_sub =
|
||||
// wire inst_sll =
|
||||
// wire inst_slt =
|
||||
// wire inst_sltu =
|
||||
// wire inst_xor =
|
||||
// wire inst_srl =
|
||||
// wire inst_sra =
|
||||
// wire inst_or =
|
||||
// wire inst_and =
|
||||
// wire inst_addw =
|
||||
// wire inst_subw =
|
||||
// wire inst_sllw =
|
||||
// wire inst_srlw =
|
||||
// wire inst_sraw =
|
||||
|
||||
wire [4: 0] src1_raddr = rs;
|
||||
wire [4: 0] src2_raddr = rt;
|
||||
// wire [`FU_OP_TYPE_WID - 1: 0] op =
|
||||
// wire reg_wen =
|
||||
// wire [4: 0] reg_waddr =
|
||||
|
||||
assign info = {
|
||||
src1_raddr,
|
||||
src2_raddr,
|
||||
op,
|
||||
reg_wen,
|
||||
reg_waddr
|
||||
};
|
||||
endmodule
|
||||
@ -1,26 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module DecoderStage(
|
||||
input clock,
|
||||
input reset,
|
||||
input [`IF_ID_WID - 1: 0] fetchUnit,
|
||||
output [`IF_ID_WID - 1: 0] decodeUnit
|
||||
);
|
||||
|
||||
reg [`IF_ID_WID - 1: 0] data;
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
data <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
data <= fetchUnit;
|
||||
end
|
||||
end
|
||||
|
||||
assign decodeUnit = data;
|
||||
|
||||
endmodule
|
||||
@ -1,12 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module Alu(
|
||||
input [`FU_OP_TYPE_WID - 1: 0] op,
|
||||
input [`XLEN - 1: 0] src1_data,
|
||||
input [`XLEN - 1: 0] src2_data,
|
||||
output [`XLEN - 1: 0] result
|
||||
);
|
||||
|
||||
// TODO: 完成ALU模块的逻辑
|
||||
|
||||
endmodule
|
||||
@ -1,12 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module ExecuteStage(
|
||||
input clock,
|
||||
input reset,
|
||||
input [`ID_EXE_WID - 1: 0] decodeUnit,
|
||||
output [`ID_EXE_WID - 1: 0] executeUnit
|
||||
);
|
||||
|
||||
// TODO: 完成ExcuteStage逻辑
|
||||
|
||||
endmodule
|
||||
@ -1,41 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module ExecuteUnit(
|
||||
// 来自ExecuteStage的输入
|
||||
input [`ID_EXE_WID - 1: 0] executeStage,
|
||||
// 送往MemoryStage的输出
|
||||
output [`EXE_MEM_WID - 1: 0] memoryStage,
|
||||
// 与memory sram的接口
|
||||
output data_sram_en,
|
||||
output [7: 0] data_sram_wen,
|
||||
output [31: 0] data_sram_addr,
|
||||
output [63: 0] data_sram_wdata
|
||||
);
|
||||
|
||||
wire valid;
|
||||
wire [`XLEN - 1: 0] pc;
|
||||
wire [`FU_OP_TYPE_WID - 1: 0] op;
|
||||
wire reg_wen;
|
||||
wire [4: 0] reg_waddr;
|
||||
wire [`XLEN - 1: 0] src1_data;
|
||||
wire [`XLEN - 1: 0] src2_data;
|
||||
assign {valid, pc, op, reg_wen, reg_waddr, src1_data, src2_data} = executeStage;
|
||||
|
||||
wire [`XLEN - 1: 0] reg_wdata;
|
||||
Alu u_Alu(
|
||||
.op ( op ),
|
||||
.src1_data ( src1_data ),
|
||||
.src2_data ( src2_data ),
|
||||
.result ( reg_wdata )
|
||||
);
|
||||
|
||||
|
||||
assign data_sram_en = 1'b0;
|
||||
assign data_sram_wen = 8'b0;
|
||||
assign data_sram_addr = 32'b0;
|
||||
assign data_sram_wdata = 64'b0;
|
||||
|
||||
// TODO:定义和MemoryStage的连接
|
||||
// assign memoryStage =
|
||||
|
||||
endmodule
|
||||
@ -1,66 +0,0 @@
|
||||
|
||||
`include "mycpu.h"
|
||||
module FetchUnit(
|
||||
input clock,
|
||||
input reset,
|
||||
output [`IF_ID_WID - 1: 0] decodeStage,
|
||||
// inst sram interface
|
||||
output inst_sram_en,
|
||||
output [ 3: 0] inst_sram_wen,
|
||||
output [31: 0] inst_sram_addr,
|
||||
output [31: 0] inst_sram_wdata,
|
||||
input [31: 0] inst_sram_rdata
|
||||
);
|
||||
|
||||
reg [1: 0] state;
|
||||
parameter boot = 0;
|
||||
parameter send = 1;
|
||||
parameter receive = 2;
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
state <= boot;
|
||||
end
|
||||
else
|
||||
begin
|
||||
case (state)
|
||||
boot:
|
||||
state <= send;
|
||||
send:
|
||||
state <= receive;
|
||||
receive:
|
||||
;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
reg [`XLEN - 1: 0] pc;
|
||||
wire [`XLEN - 1: 0] pc_next = pc + 4;
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
pc <= 64'h80000000 - 4;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (state != boot)
|
||||
pc <= pc_next;
|
||||
end
|
||||
end
|
||||
|
||||
assign inst_sram_en = !reset;
|
||||
assign inst_sram_wen = 0;
|
||||
assign inst_sram_wdata = 0;
|
||||
assign inst_sram_addr = pc_next[31: 0];
|
||||
|
||||
assign decodeStage = {
|
||||
state == receive, // decodeStage.valid
|
||||
pc, // decodeStage.pc
|
||||
{32'b0, inst_sram_rdata} // decodeStage.inst
|
||||
};
|
||||
|
||||
endmodule
|
||||
@ -1,12 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module MemoryStage(
|
||||
input clock,
|
||||
input reset,
|
||||
input [`EXE_MEM_WID - 1: 0] executeUnit,
|
||||
output [`EXE_MEM_WID - 1: 0] memoryUnit
|
||||
);
|
||||
|
||||
// TODO: 完成MemoryStage逻辑
|
||||
|
||||
endmodule
|
||||
@ -1,14 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module MemoryUnit(
|
||||
// 来自MemoryStage的输入
|
||||
input [`EXE_MEM_WID - 1: 0] memoryStage,
|
||||
// 送往WriteBackStage的输出
|
||||
output [`MEM_WB_WID - 1: 0] writeBackStage,
|
||||
// 与memory sram的接口
|
||||
input [`XLEN - 1: 0] data_sram_rdata
|
||||
);
|
||||
|
||||
// TODO: 完成MemoryUnit逻辑
|
||||
|
||||
endmodule
|
||||
@ -1,12 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module WriteBackStage(
|
||||
input clock,
|
||||
input reset,
|
||||
input [`MEM_WB_WID - 1: 0] memoryUnit,
|
||||
output [`MEM_WB_WID - 1: 0] writeBackUnit
|
||||
);
|
||||
|
||||
// TODO: 完成WriteBackStage逻辑
|
||||
|
||||
endmodule
|
||||
@ -1,20 +0,0 @@
|
||||
`include "mycpu.h"
|
||||
|
||||
module WriteBackUnit(
|
||||
input [`MEM_WB_WID - 1: 0] writeBackStage,
|
||||
// 输出至ARegfile
|
||||
output reg_wen,
|
||||
output [4: 0] reg_waddr,
|
||||
output [`XLEN - 1: 0] reg_wdata,
|
||||
// debug
|
||||
output debug_commit,
|
||||
output [63: 0] debug_pc,
|
||||
output [4: 0] debug_rf_wnum,
|
||||
output [63: 0] debug_rf_wdata
|
||||
);
|
||||
|
||||
// 写回阶段完成数据的写回操作
|
||||
// 同时该阶段还负责差分测试的比对工作
|
||||
// TODO: 完成WriteBackUnit模块的逻辑
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in new issue