Compare commits

..

3 Commits

@ -152,15 +152,6 @@ git pull # 拉取最新代码
所有的 make 指令均在 difftest 目录下执行,如 `make verilog``make lab1``make trace_lab1` 等
部分实验存在多个测例,此时 trace.fst 文件需手动生成,在 difftest 目录下使用以下命令手动生成 CPU 波形文件
```bash
make trace TESTBIN_DIR=<测例对应的bin文件的路径>
# 如在 difftest 目录下输入以下命令可生成CPU运行 am-tests/add.bin 测例的波形
make trace TESTBIN_DIR=./test/bin/am-tests/add.bin
```
## 📢 注意事项
- 编程位置位于 chisel 中

@ -1,54 +0,0 @@
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,35 +0,0 @@
package cpu
import chisel3._
import chisel3.util._
import defines._
import defines.Const._
import pipeline._
class Core extends Module {
val io = IO(new Bundle {
val interrupt = Input(new ExtInterrupt())
val instSram = new InstSram()
val dataSram = new DataSram()
val debug = new DEBUG()
})
val fetchUnit = Module(new FetchUnit()).io
val decodeStage = Module(new DecodeStage()).io
val decodeUnit = Module(new DecodeUnit()).io
val regfile = Module(new ARegFile()).io
val executeStage = Module(new ExecuteStage()).io
val executeUnit = Module(new ExecuteUnit()).io
val memoryStage = Module(new MemoryStage()).io
val memoryUnit = Module(new MemoryUnit()).io
val writeBackStage = Module(new WriteBackStage()).io
val writeBackUnit = Module(new WriteBackUnit()).io
// 取指单元
fetchUnit.instSram <> io.instSram
fetchUnit.decodeStage <> decodeStage.fetchUnit
// TODO: 完成Core模块的逻辑
// 在该模块中需要将各个模块连接起来形成一个完整的CPU核心
}

@ -1,16 +0,0 @@
package cpu
import chisel3.util._
import cpu.defines.Const._
case class CpuConfig(
// 指令集
val isRV32: Boolean = false, // 是否为RV32
val hasMExtension: Boolean = false, // 是否实现M扩展即乘除法指令
val hasZicsrExtension: Boolean = false, // 是否实现Zicsr扩展即CSR指令
val hasZifenceiExtension: Boolean = false, // 是否实现Zifencei扩展即FENCE.I指令
val hasAExtension: Boolean = false, // 是否实现A扩展即原子指令
// 特权模式
val hasSMode: Boolean = false, // 是否有S模式
val hasUMode: Boolean = false // 是否有U模式
)

@ -0,0 +1,68 @@
package gcd
import chisel3._
import chisel3.util.Decoupled
class GcdInputBundle(val w: Int) extends Bundle {
val value1 = UInt(w.W)
val value2 = UInt(w.W)
}
class GcdOutputBundle(val w: Int) extends Bundle {
val value1 = UInt(w.W)
val value2 = UInt(w.W)
val gcd = UInt(w.W)
}
/** Compute Gcd using subtraction method. Subtracts the smaller from the larger until register y is zero. value input
* register x is then the Gcd. Unless first input is zero then the Gcd is y. Can handle stalls on the producer or
* consumer side
*/
class DecoupledGcd(width: Int) extends Module {
val input = IO(Flipped(Decoupled(new GcdInputBundle(width))))
val output = IO(Decoupled(new GcdOutputBundle(width)))
val xInitial = Reg(UInt())
val yInitial = Reg(UInt())
val x = Reg(UInt())
val y = Reg(UInt())
val busy = RegInit(false.B)
val resultValid = RegInit(false.B)
input.ready := !busy
output.valid := resultValid
output.bits := DontCare
when(busy) {
when(x > y) {
x := x - y
}.otherwise {
y := y - x
}
when(x === 0.U || y === 0.U) {
when(x === 0.U) {
output.bits.gcd := y
}.otherwise {
output.bits.gcd := x
}
output.bits.value1 := xInitial
output.bits.value2 := yInitial
resultValid := true.B
when(output.ready && resultValid) {
busy := false.B
resultValid := false.B
}
}
}.otherwise {
when(input.valid) {
val bundle = input.deq()
x := bundle.value1
y := bundle.value2
xInitial := bundle.value1
yInitial := bundle.value2
busy := true.B
}
}
}

@ -1,9 +1,12 @@
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))
}
val firtoolOptions = Array(
"--lowering-options=" + List(
// make yosys happy
// see https://github.com/llvm/circt/blob/main/docs/VerilogGeneration.md
"disallowLocalVariables",
"disallowPackedArrays",
"locationInfoStyle=wrapInAtSquareBracket"
).reduce(_ + "," + _)
)
circt.stage.ChiselStage.emitSystemVerilogFile(new gcd.GCD(), args, firtoolOptions)
}

@ -0,0 +1,29 @@
package gcd
import chisel3._
/** Compute GCD using subtraction method. Subtracts the smaller from the larger until register y is zero. value in
* register x is then the GCD
*/
class GCD extends Module {
val io = IO(new Bundle {
val value1 = Input(UInt(16.W))
val value2 = Input(UInt(16.W))
val loadingValues = Input(Bool())
val outputGCD = Output(UInt(16.W))
val outputValid = Output(Bool())
})
val x = Reg(UInt())
val y = Reg(UInt())
when(x > y) { x := x - y }.otherwise { y := y - x }
when(io.loadingValues) {
x := io.value1
y := io.value2
}
io.outputGCD := x
io.outputValid := y === 0.U
}

@ -1,20 +0,0 @@
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
}

@ -1,59 +0,0 @@
package cpu.defines
import chisel3._
import chisel3.util._
import cpu.defines._
import cpu.defines.Const._
import cpu.CpuConfig
class ExtInterrupt extends Bundle {
val mei = Bool()
val mti = Bool()
val msi = Bool()
}
class SrcInfo extends Bundle {
val src1_data = UInt(XLEN.W)
val src2_data = UInt(XLEN.W)
}
class RdInfo extends Bundle {
val wdata = UInt(XLEN.W)
}
class Info extends Bundle {
val valid = Bool() // 用于标识当前流水级中的指令是否有效
val src1_raddr = UInt(REG_ADDR_WID.W)
val src2_raddr = UInt(REG_ADDR_WID.W)
val op = FuOpType()
val reg_wen = Bool()
val reg_waddr = UInt(REG_ADDR_WID.W)
}
class SrcReadSignal extends Bundle {
val ren = Bool()
val raddr = UInt(REG_ADDR_WID.W)
}
class InstSram extends Bundle {
val en = Output(Bool())
val addr = Output(UInt(SRAM_ADDR_WID.W))
val wdata = Output(UInt(INST_SRAM_DATA_WID.W))
val wen = Output(UInt(INST_SRAM_WEN_WID.W))
val rdata = Input(UInt(INST_SRAM_DATA_WID.W))
}
class DataSram extends Bundle {
val en = Output(Bool())
val addr = Output(UInt(SRAM_ADDR_WID.W))
val wdata = Output(UInt(DATA_SRAM_DATA_WID.W))
val wen = Output(UInt(DATA_SRAM_WEN_WID.W))
val rdata = Input(UInt(DATA_SRAM_DATA_WID.W))
}
class DEBUG extends Bundle {
val commit = Output(Bool()) // 写回阶段的commit信号仅在每条指令提交时置为true
val pc = Output(UInt(XLEN.W)) // 写回阶段的pc
val rf_wnum = Output(UInt(REG_ADDR_WID.W)) // 写回阶段的寄存器写地址
val rf_wdata = Output(UInt(XLEN.W)) // 写回阶段的寄存器写数据
}

@ -1,42 +0,0 @@
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
}

@ -1,29 +0,0 @@
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)
}

@ -1,36 +0,0 @@
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
// IRUJ类型的指令都需要写寄存器
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操作类型
}

@ -1,61 +0,0 @@
package cpu.defines
import chisel3._
import chisel3.util._
object RV32I_ALUInstr extends HasInstrType with CoreParameter {
def ADDI = BitPat("b????????????_?????_000_?????_0010011")
def SLLI = if (XLEN == 32) BitPat("b0000000?????_?????_001_?????_0010011")
else BitPat("b000000??????_?????_001_?????_0010011")
def SLTI = BitPat("b????????????_?????_010_?????_0010011")
def SLTIU = BitPat("b????????????_?????_011_?????_0010011")
def XORI = BitPat("b????????????_?????_100_?????_0010011")
def SRLI = if (XLEN == 32) BitPat("b0000000?????_?????_101_?????_0010011")
else BitPat("b000000??????_?????_101_?????_0010011")
def ORI = BitPat("b????????????_?????_110_?????_0010011")
def ANDI = BitPat("b????????????_?????_111_?????_0010011")
def SRAI = if (XLEN == 32) BitPat("b0100000?????_?????_101_?????_0010011")
else BitPat("b010000??????_?????_101_?????_0010011")
def ADD = BitPat("b0000000_?????_?????_000_?????_0110011")
def SLL = BitPat("b0000000_?????_?????_001_?????_0110011")
def SLT = BitPat("b0000000_?????_?????_010_?????_0110011")
def SLTU = BitPat("b0000000_?????_?????_011_?????_0110011")
def XOR = BitPat("b0000000_?????_?????_100_?????_0110011")
def SRL = BitPat("b0000000_?????_?????_101_?????_0110011")
def OR = BitPat("b0000000_?????_?????_110_?????_0110011")
def AND = BitPat("b0000000_?????_?????_111_?????_0110011")
def SUB = BitPat("b0100000_?????_?????_000_?????_0110011")
def SRA = BitPat("b0100000_?????_?????_101_?????_0110011")
def AUIPC = BitPat("b????????????????????_?????_0010111")
def LUI = BitPat("b????????????????????_?????_0110111")
// 在Decoder模块中搭配ListLookup函数使用
val table = Array(
// ADD指令将被解析为InstrR类型的指令功能单元类型为alu功能单元操作类型为add
ADD -> List(InstrR, FuType.alu, ALUOpType.add)
// TODO: 完成其他指令的解析
)
}
object RV64IInstr extends HasInstrType {
def ADDIW = BitPat("b???????_?????_?????_000_?????_0011011")
def SLLIW = BitPat("b0000000_?????_?????_001_?????_0011011")
def SRLIW = BitPat("b0000000_?????_?????_101_?????_0011011")
def SRAIW = BitPat("b0100000_?????_?????_101_?????_0011011")
def SLLW = BitPat("b0000000_?????_?????_001_?????_0111011")
def SRLW = BitPat("b0000000_?????_?????_101_?????_0111011")
def SRAW = BitPat("b0100000_?????_?????_101_?????_0111011")
def ADDW = BitPat("b0000000_?????_?????_000_?????_0111011")
def SUBW = BitPat("b0100000_?????_?????_000_?????_0111011")
val table = Array(
// TODO: 完成RV64I指令集的解析
)
}
object RVIInstr extends CoreParameter {
val table = RV32I_ALUInstr.table ++
(if (XLEN == 64) RV64IInstr.table else Array.empty)
}

@ -1,41 +0,0 @@
package cpu.pipeline
import chisel3._
import chisel3.util._
import cpu.defines._
import cpu.defines.Const._
import cpu.CpuConfig
class SrcRead extends Bundle {
val raddr = Output(UInt(REG_ADDR_WID.W))
val rdata = Input(UInt(XLEN.W))
}
class Src12Read extends Bundle {
val src1 = new SrcRead()
val src2 = new SrcRead()
}
class RegWrite extends Bundle {
val wen = Output(Bool())
val waddr = Output(UInt(REG_ADDR_WID.W))
val wdata = Output(UInt(XLEN.W))
}
class ARegFile extends Module {
val io = IO(new Bundle {
val read = Flipped(new Src12Read())
val write = Flipped(new RegWrite())
})
// 定义32个XLEN位寄存器
val regs = RegInit(VecInit(Seq.fill(AREG_NUM)(0.U(XLEN.W))))
// 写寄存器堆
// TODO:完成写寄存器堆逻辑
// 注意0号寄存器恒为0
// 读寄存器堆
// TODO:完成读寄存器堆逻辑
// 注意0号寄存器恒为0
}

@ -1,30 +0,0 @@
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
}

@ -1,38 +0,0 @@
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 :=
}

@ -1,36 +0,0 @@
package cpu.pipeline
import chisel3._
import chisel3.util._
import cpu.defines._
import cpu.defines.Const._
class Decoder extends Module with HasInstrType {
val io = IO(new Bundle {
// inputs
val in = Input(new Bundle {
val inst = UInt(XLEN.W)
})
// outputs
val out = Output(new Bundle {
val info = new Info()
})
})
val inst = io.in.inst
// 根据输入的指令inst从Instructions.DecodeTable中查找对应的指令类型功能单元类型和功能单元操作类型
// 如果找不到匹配的指令则使用Instructions.DecodeDefault作为默认值
// instrTypefuType和fuOpType分别被赋值为Instructions.DecodeTable中的对应值
val instrType :: fuType :: fuOpType :: Nil =
ListLookup(inst, Instructions.DecodeDefault, Instructions.DecodeTable)
val (rs, rt, rd) = (inst(19, 15), inst(24, 20), inst(11, 7))
// TODO: 完成Decoder模块的逻辑
// io.out.info.valid :=
// io.out.info.src1_raddr :=
// io.out.info.src2_raddr :=
// io.out.info.op :=
// io.out.info.reg_wen :=
// io.out.info.reg_waddr :=
}

@ -1,28 +0,0 @@
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模块的逻辑
}

@ -1,31 +0,0 @@
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 :=
}

@ -1,32 +0,0 @@
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
}

@ -1,15 +0,0 @@
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模块的逻辑
}

@ -1,41 +0,0 @@
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
}

@ -1,29 +0,0 @@
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模块的逻辑
}

@ -1,21 +0,0 @@
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
}

@ -1,27 +0,0 @@
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模块的逻辑
}

@ -1,19 +0,0 @@
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模块的逻辑
}

@ -1,9 +1,68 @@
// 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))
// }
// See README.md for license details.
package gcd
import chisel3._
import chisel3.experimental.BundleLiterals._
import chisel3.simulator.EphemeralSimulator._
import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.must.Matchers
/** This is a trivial example of how to run this Specification From within sbt use:
* {{{
* testOnly gcd.GCDSpec
* }}}
* From a terminal shell use:
* {{{
* sbt 'testOnly gcd.GCDSpec'
* }}}
* Testing from mill:
* {{{
* mill %NAME%.test.testOnly gcd.GCDSpec
* }}}
*/
class GCDSpec extends AnyFreeSpec with Matchers {
"Gcd should calculate proper greatest common denominator" in {
simulate(new DecoupledGcd(16)) { dut =>
val testValues = for {
x <- 0 to 10
y <- 0 to 10
} yield (x, y)
val inputSeq = testValues.map { case (x, y) => (new GcdInputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U) }
val resultSeq = testValues.map { case (x, y) =>
(new GcdOutputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U, _.gcd -> BigInt(x).gcd(BigInt(y)).U)
}
dut.reset.poke(true.B)
dut.clock.step()
dut.reset.poke(false.B)
dut.clock.step()
var sent, received, cycles: Int = 0
while (sent != 100 && received != 100) {
assert(cycles <= 1000, "timeout reached")
if (sent < 100) {
dut.input.valid.poke(true.B)
dut.input.bits.value1.poke(testValues(sent)._1.U)
dut.input.bits.value2.poke(testValues(sent)._2.U)
if (dut.input.ready.peek().litToBoolean) {
sent += 1
}
}
if (received < 100) {
dut.output.ready.poke(true.B)
if (dut.output.valid.peekValue().asBigInt == 1) {
dut.output.bits.gcd.expect(BigInt(testValues(received)._1).gcd(testValues(received)._2))
received += 1
}
}
// Step the simulation forward.
dut.clock.step()
cycles += 1
}
}
}
}

@ -1,7 +1,4 @@
*.vcd
obj_dir
core/*
!core/top_sram_wrapper.v
trace.*

@ -3,21 +3,21 @@ SRC_DIR := ./core
SRC_FILE := $(shell find $(SRC_DIR) -name '*.svh') $(shell find $(SRC_DIR) -name '*.h') $(shell find $(SRC_DIR) -name '*.v') $(shell find $(SRC_DIR) -name '*.sv')
CHISEL_DIR = ../chisel
BUILD_DIR = $(CHISEL_DIR)/build
TESTBIN_DIR = ./test/bin/am-tests/add.bin
.PHONY: clean
obj_dir/V$(TOP_NAME): src/* $(SRC_FILE)
verilator --cc -Wno-fatal --exe --trace-fst --trace-structs -LDFLAGS "-lpthread" --build src/sim_mycpu.cpp $(SRC_FILE) -I$(SRC_DIR) --top $(TOP_NAME) -j `nproc`
envtest:
$(call git_commit, "env test") # DO NOT REMOVE THIS LINE!!!
$(MAKE) -C $(CHISEL_DIR) verilog
$(MAKE) lab1
verilog:
$(MAKE) -C $(CHISEL_DIR) verilog
cp $(CHISEL_DIR)/build/PuaCpu.v $(SRC_DIR)
trace: obj_dir/V$(TOP_NAME)
$(call git_commit, "trace") # DO NOT REMOVE THIS LINE!!!
./obj_dir/V$(TOP_NAME) $(TESTBIN_DIR) -rvtest -trace 10000000 -pc
test:
$(MAKE) -C $(CHISEL_DIR) test
@ -103,7 +103,7 @@ trace_lab8: obj_dir/V$(TOP_NAME)
lab9: obj_dir/V$(TOP_NAME)
$(call git_commit, "test lab9") # DO NOT REMOVE THIS LINE!!!
count=0; \
for test in $$(find ./test/bin/riscv-test/ \( -name "*rv64ui-p-*" -o -name "*rv64um-p-*" -o -name "*rv64mi-p-*" \) | grep -vE "*rv64ui-p-fence_i|*rv64mi-p-access"); do \
for test in $$(find ./test/bin/riscv-test/ \( -name "rv64ui-p-*" -o -name "rv64um-p-*" -o -name "rv64mi-p-*" \) | grep -vE "rv64ui-p-fence_i|rv64mi-p-access"); do \
count=$$((count + 1)); \
echo "Running test $$count: $$test"; \
./obj_dir/V$(TOP_NAME) $$test -rvtest -pc; \
@ -113,7 +113,7 @@ lab9: obj_dir/V$(TOP_NAME)
trace_lab9: obj_dir/V$(TOP_NAME)
$(call git_commit, "trace lab9") # DO NOT REMOVE THIS LINE!!!
count=0; \
for test in $$(find ./test/bin/riscv-test/ \( -name "*rv64ui-p-*" -o -name "*rv64um-p-*" -o -name "*rv64mi-p-*" \) | grep -vE "*rv64ui-p-fence_i|*rv64mi-p-access"); do \
for test in $$(find ./test/bin/riscv-test/ \( -name "rv64ui-p-*" -o -name "rv64um-p-*" -o -name "rv64mi-p-*" \) | grep -vE "rv64ui-p-fence_i|rv64mi-p-access"); do \
count=$$((count + 1)); \
echo "Running test $$count: $$test"; \
./obj_dir/V$(TOP_NAME) $$test -rvtest -cpu_trace -writeappend; \

@ -27,7 +27,17 @@
- 在上述命令后继续增加参数:
- `-trace <记录波形时长>` 记录波形,并导出
- `-starttrace <开始记录波形的时刻>` 从指定时刻开始记录一段固定时长的波形
- `-pc` 报错时将额外输出最近的 PC 历史记录
- `-delay` 行为不一致时将继续运行一段时间再停止
- `-cpu_trace` 记录被测试的处理器的程序运行历史信息,生成 trace.txt
- 评测功能,下述信号互斥,只能选择一个:
- `-cpu_trace` 记录被测试的处理器的程序运行差分测试信号
- `-golden_trace` 记录模拟器的程序运行差分测试信号
- `-os` 运行操作系统测试目前支持Linux
- 在上述命令后继续增加参数:
- `-trace <记录波形时长>` 记录波形,并导出
- `-pc` 报错时将额外输出最近的 PC 历史记录
- `-delay` 行为不一致时将继续运行一段时间再停止
- `-nodiff` 不进行差分测试
- `-starttrace <开始记录波形的时刻>` 从指定时刻开始记录一段固定时长的波形
- `-emu` 使用模拟器进行测试

File diff suppressed because it is too large Load Diff

@ -412,7 +412,7 @@ int main(int argc, char **argv, char **env)
{
should_delay = true;
}
else if (strcmp(argv[i], "-cpu_trace") == 0) // 生成cpu trace
else if (strcmp(argv[i], "-cpu_trace") == 0) // 生成golden trace
{
run_mode = CPU_TRACE;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save