perilus

git clone https://git.bradleygannon.com/perilus.git
Log | Files | Refs | Submodules | README

commit ed4fa0d20b16ab0b623fac80a43d2d24fd6acb9b
parent 19e57583faaf31adaec537c7c56993ca7d82c285
Author: mbbutler <m.brady.butler@gmail.com>
Date:   Fri,  2 Jan 2026 16:08:37 -0500

beq test not working. need to check imm extender

Diffstat:
Aassets/mem-beq-64x32.hex | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aassets/reg-beq-x32.hex | 32++++++++++++++++++++++++++++++++
Msrc/main/scala/alu.scala | 1+
Msrc/main/scala/controlUnit.scala | 1+
Msrc/main/scala/main.scala | 10++++++++++
Msrc/test/scala/perilus/main.scala | 160+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
6 files changed, 211 insertions(+), 57 deletions(-)

diff --git a/assets/mem-beq-64x32.hex b/assets/mem-beq-64x32.hex @@ -0,0 +1,64 @@ +02618563 +00930863 +5ee7809a +947924f4 +fc24525a +6c858974 +4996dd8c +50415755 +b329e2c1 +99a84ca8 +ca029ae4 +a57954e9 +a7b0a4b1 +5f1c57ea +bab5ee54 +e63aec6d +7afaad60 +334c7d51 +bc83bea3 +63b83aab +e1940fda +4812b9fa +7c224e0a +305c08cc +85e21635 +6e0cd50c +d976069b +f7f1ab0f +24d8e524 +0f15069c +1fa3eed3 +f73d90fa +bd46aca5 +a519ad77 +70cd4ed3 +a722ba58 +cec41109 +9955f8a8 +ba5eb4f8 +cb32fd9d +4f3fc791 +43bcbe26 +c1600d35 +0b5fc381 +dddfa0c3 +0331db73 +1e088fee +9a0cdee4 +29580f62 +043925f7 +653647af +d5e9eb13 +3e559887 +f098fa6f +0f3f9400 +07163d81 +b37a3f8e +0c11b791 +b3fa9fcf +9d6ae141 +a34ef0d5 +3e850e1a +2a410325 +8fce4057 diff --git a/assets/reg-beq-x32.hex b/assets/reg-beq-x32.hex @@ -0,0 +1,32 @@ +00000000 +00000000 +00000000 +abcdef01 +00000000 +00000000 +abcde012 +00000000 +00000000 +abcde012 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 diff --git a/src/main/scala/alu.scala b/src/main/scala/alu.scala @@ -15,6 +15,7 @@ class Alu extends Module { switch(io.aluControl) { is(AluControl.add) { + printf(cf"srcA = ${io.srcA}, srcB = ${io.srcB}\n") io.aluResult := io.srcA + io.srcB } is(AluControl.sub) { diff --git a/src/main/scala/controlUnit.scala b/src/main/scala/controlUnit.scala @@ -46,6 +46,7 @@ class ControlUnit(withDebug: Boolean = false) extends Module { io.resultSrc := ResultSrc.aluOutBuf // Main FSM (Figure 7.45, page 436) + printf(cf"state = $state\n") switch(state) { is(ControlUnitState.fetch) { io.adrSrc := false.B diff --git a/src/main/scala/main.scala b/src/main/scala/main.scala @@ -32,6 +32,7 @@ class Perilus( val io = IO(new Bundle { val memory = Module(new Memory(memorySizeWords, width, initMem, withDebug)) val registerFile = Module(new RegisterFile(width, initRegs, withDebug)) + val pc = Output(UInt(width)) val debug = if (withDebug) Some(new Bundle { val reg = Input(UInt(5.W)) @@ -69,6 +70,8 @@ class Perilus( pc := pcNext } + io.pc := pc + val oldPc = RegInit(0.U(width)) when(controlUnit.io.irWrite) { oldPc := pc @@ -90,7 +93,10 @@ class Perilus( val aluOutBuf = RegInit(0.U(width)) aluOutBuf := alu.io.aluResult + printf(cf"aluOutBuf = $aluOutBuf\n") + val result = WireDefault(0.U(width)) + pcNext := result switch(controlUnit.io.resultSrc) { is(ResultSrc.aluOutBuf) { result := aluOutBuf @@ -151,6 +157,10 @@ class Perilus( io.registerFile.io.a3 := instr(11, 7) io.registerFile.io.writeData3 := result io.registerFile.io.writeEnable3 := controlUnit.io.regWrite + + printf("----\n") + printf(cf"pcNext = $pcNext\n") + printf(cf"pc = $pc\n") } object Perilus extends App { diff --git a/src/test/scala/perilus/main.scala b/src/test/scala/perilus/main.scala @@ -7,84 +7,130 @@ import com.rinthyAi.perilus.main._ class PerilusTests extends AnyFunSpec with ChiselSim { describe("Perilus") { - it("executes lw") { - simulate( - new Perilus( - initRegs = System.getProperty("user.dir") + "/assets/reg-lw-x32.hex", - initMem = System.getProperty("user.dir") + "/assets/mem-lw-64x32.hex", - withDebug = true - ) - ) { perilus => - { - val perilusDebug = perilus.io.debug.get + // it("executes lw") { + // simulate( + // new Perilus( + // initRegs = System.getProperty("user.dir") + "/assets/reg-lw-x32.hex", + // initMem = System.getProperty("user.dir") + "/assets/mem-lw-64x32.hex", + // withDebug = true + // ) + // ) { perilus => + // { + // val perilusDebug = perilus.io.debug.get - // lw x21, 0x2a(x11) - val rd = 21 - val rs1 = 11 - val base = 0xc - val imm = 0x2a - val memAddr = (base + imm).U - val memData = 0x0f3f9400 + // // lw x21, 0x2a(x11) + // val rd = 21 + // val rs1 = 11 + // val base = 0xc + // val imm = 0x2a + // val memAddr = (base + imm).U + // val memData = 0x0f3f9400 - // rs1 contains the base pointer - perilusDebug.reg.poke(rs1) - perilusDebug.regData.expect(base) + // // rs1 contains the base pointer + // perilusDebug.reg.poke(rs1) + // perilusDebug.regData.expect(base) - // rd is empty - perilusDebug.reg.poke(rd) - perilusDebug.regData.expect(0.U) + // // rd is empty + // perilusDebug.reg.poke(rd) + // perilusDebug.regData.expect(0.U) - // memAddr contains memData - perilusDebug.memAddr.poke(memAddr) - perilusDebug.memData.expect(memData) + // // memAddr contains memData + // perilusDebug.memAddr.poke(memAddr) + // perilusDebug.memData.expect(memData) - // execute the instruction - perilus.clock.step(6) + // // execute the instruction + // perilus.clock.step(6) - // rd contains memData - perilusDebug.reg.poke(rd) - perilusDebug.regData.expect(memData) + // // rd contains memData + // perilusDebug.reg.poke(rd) + // perilusDebug.regData.expect(memData) - // contents of memAddr have not changed - perilusDebug.memAddr.poke(memAddr) - perilusDebug.memData.expect(memData) - } - } - } - it("executes sw") { + // // contents of memAddr have not changed + // perilusDebug.memAddr.poke(memAddr) + // perilusDebug.memData.expect(memData) + // } + // } + // } + // it("executes sw") { + // simulate( + // new Perilus( + // initRegs = System.getProperty("user.dir") + "/assets/reg-sw-x32.hex", + // initMem = System.getProperty("user.dir") + "/assets/mem-sw-64x32.hex", + // withDebug = true + // ) + // ) { perilus => + // { + // val perilusDebug = perilus.io.debug.get + + // // sw x6, -4(x9) + // // sw rs2, imm(rs1) + // val rs2 = 6 + // val rs1 = 9 + // val base = 0x3a + // val imm = -4 + // val memAddr = (base + imm).U + // val memData = 0x01830169 + + // // rs1 contains the base pointer + // perilusDebug.reg.poke(rs1) + // perilusDebug.regData.expect(base) + + // // rs2 contains data to be stored + // perilusDebug.reg.poke(rs2) + // perilusDebug.regData.expect(memData) + + // // execute the instruction + // perilus.clock.step(5) + + // // contents of memAddr have not changed + // perilusDebug.memAddr.poke(memAddr) + // perilusDebug.memData.expect(memData) + // } + // } + // } + it("executes beq") { simulate( new Perilus( - initRegs = System.getProperty("user.dir") + "/assets/reg-sw-x32.hex", - initMem = System.getProperty("user.dir") + "/assets/mem-sw-64x32.hex", + initRegs = System.getProperty("user.dir") + "/assets/reg-beq-x32.hex", + initMem = System.getProperty("user.dir") + "/assets/mem-beq-64x32.hex", withDebug = true ) ) { perilus => { val perilusDebug = perilus.io.debug.get - // sw x6, -4(x9) - // sw rs2, imm(rs1) + val rs1 = 3 val rs2 = 6 - val rs1 = 9 - val base = 0x3a - val imm = -4 - val memAddr = (base + imm).U - val memData = 0x01830169 + val rs3 = 9 + val offset = 16.U - // rs1 contains the base pointer + // Verify that registers are/aren't equal as expected perilusDebug.reg.poke(rs1) - perilusDebug.regData.expect(base) - - // rs2 contains data to be stored + val rs1_t = perilusDebug.regData.peek() perilusDebug.reg.poke(rs2) - perilusDebug.regData.expect(memData) + val rs2_t = perilusDebug.regData.peek() + perilusDebug.reg.poke(rs3) + val rs3_t = perilusDebug.regData.peek() + assert(rs1_t.litValue != rs2_t.litValue) + assert(rs2_t.litValue == rs3_t.litValue) + + var pc_t = perilus.io.pc.peek() + // execute the first beq instruction:fe64ae23 + // beq x3, x6, 0x4 + perilus.clock.step(4) + + // pc should be at address 1 because x3 != x6 + val expected_1 = pc_t.litValue + 4 + // perilus.io.pc.expect(expected_1.U) + pc_t = perilus.io.pc.peek() - // execute the instruction - perilus.clock.step(5) + // execute the second beq instruction: + // beq x6, x9, 0x4 + perilus.clock.step(4) - // contents of memAddr have not changed - perilusDebug.memAddr.poke(memAddr) - perilusDebug.memData.expect(memData) + // pc should be at address 5 because x6 == x9 + val expected_2 = pc_t.litValue + offset.litValue + // perilus.io.pc.expect(expected_2.U) } } }