Lab3 pipelined CPU renewed

- added tutorial
- fix ID reg addr invalid in certain types of instructions
- renamed some variables for better understanding
This commit is contained in:
PurplePower
2025-08-14 16:55:53 +08:00
parent 110132ff95
commit b9865cd612
33 changed files with 494 additions and 98 deletions

View File

@@ -71,3 +71,4 @@ class FiveStageCPUForwardTest extends AnyFlatSpec with ChiselScalatestTester {
}
}
}

View File

@@ -17,6 +17,8 @@ package riscv
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import scala.util.Random
import riscv.core.fivestage_stall._
class FiveStageCPUStallTest extends AnyFlatSpec with ChiselScalatestTester {
@@ -71,3 +73,86 @@ class FiveStageCPUStallTest extends AnyFlatSpec with ChiselScalatestTester {
}
}
}
class DecoderStallTest extends AnyFlatSpec with ChiselScalatestTester {
behavior of "ID of Five-stage Pipelined CPU with Stalling"
def concatBits(values: (Int, Int)*): Int = {
values.foldLeft(0) { case (result, (value, bits)) =>
val mask = (1 << bits) - 1 // Create mask for the specified bit width
val maskedValue = value & mask // Ensure value fits in specified bits
(result << bits) | maskedValue
}
}
it should "generate correct reg addr" in {
test(new InstructionDecode).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 0 to 100) {
val rs1 = Random.nextInt(32)
val rs2 = Random.nextInt(32)
val rd = Random.nextInt(32)
// for R-type instructions, rs2, rs1 and rd should be valid
// val instR = 0.U(7.W) ## rs2 ## rs1 ## 1.U(3.W) ## rd ## InstructionTypes.RM
val instR = concatBits(
(0, 7), (rs2, 5), (rs1, 5), (1, 3), (rd, 5), (InstructionTypes.RM.litValue.toInt, 7)
)
c.io.instruction.poke(instR)
c.io.regs_reg1_read_address.expect(rs1)
c.io.regs_reg2_read_address.expect(rs2)
c.io.ex_reg_write_address.expect(rd)
c.io.ex_reg_write_enable.expect(true.B)
c.clock.step()
// for I-type instructions, rs1 and rd should be valid
val instI = concatBits((0, 12), (rs1, 5), (1, 3), (rd, 5), (InstructionTypes.I.litValue.toInt, 7))
c.io.instruction.poke(instI)
c.io.regs_reg1_read_address.expect(rs1)
c.io.regs_reg2_read_address.expect(0.U)
c.io.ex_reg_write_address.expect(rd)
c.io.ex_reg_write_enable.expect(true.B)
c.clock.step()
// for S-type instructions, rs2 and rs1 should be valid
val instS = concatBits((0, 7), (rs2, 5), (rs1, 5), (1, 3), (2, 5), (InstructionTypes.S.litValue.toInt, 7))
c.io.instruction.poke(instS)
c.io.regs_reg1_read_address.expect(rs1)
c.io.regs_reg2_read_address.expect(rs2)
c.io.ex_reg_write_address.expect(0.U)
c.io.ex_reg_write_enable.expect(false.B)
c.clock.step()
// for B-type instructions, rs2 and rs1 should be valid
val instB = concatBits((0, 7), (rs2, 5), (rs1, 5), (1, 3), (2, 5), (InstructionTypes.B.litValue.toInt, 7))
c.io.instruction.poke(instB)
c.io.regs_reg1_read_address.expect(rs1)
c.io.regs_reg2_read_address.expect(rs2)
c.io.ex_reg_write_address.expect(0.U)
c.io.ex_reg_write_enable.expect(false.B)
c.clock.step()
// for U-type instructions, rd should be valid
val instU = concatBits((0, 20), (rd, 5), (Instructions.lui.litValue.toInt, 7))
c.io.instruction.poke(instU)
c.io.regs_reg1_read_address.expect(0.U)
c.io.regs_reg2_read_address.expect(0.U)
c.io.ex_reg_write_address.expect(rd)
c.io.ex_reg_write_enable.expect(true.B)
c.clock.step()
// for J-type instructions, rd should be valid
val instJ = concatBits((0, 20), (rd, 5), (Instructions.jal.litValue.toInt, 7))
c.io.instruction.poke(instJ)
c.io.regs_reg1_read_address.expect(0.U)
c.io.regs_reg2_read_address.expect(0.U)
c.io.ex_reg_write_address.expect(rd)
c.io.ex_reg_write_enable.expect(true.B)
c.clock.step()
}
}
}
}