Skip to content

Commit

Permalink
Support for Zicsr.
Browse files Browse the repository at this point in the history
  • Loading branch information
marko1616 committed Nov 11, 2024
1 parent 8a231e1 commit 0ea6dc8
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 125 deletions.
16 changes: 8 additions & 8 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,14 @@
</details>

<details>
<summary><strong> Zicsr Extension Instructions</strong></summary>

- [ ] csrrw
- [ ] csrrs
- [ ] csrrc
- [ ] csrrwi
- [ ] csrrsi
- [ ] csrrci
<summary><strong> Zicsr Extension Instructions</strong></summary>

- [x] csrrw
- [x] csrrs
- [x] csrrc
- [x] csrrwi
- [x] csrrsi
- [x] csrrci
</details>

<details>
Expand Down
9 changes: 5 additions & 4 deletions docs/update-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* ✅ Feat: Remove LSU state machine.
* ✅ Feat: Better build and compile implementation.
* ✅ Feat: Custom cpp & verilator based test workflow.
* ✅ Feat: Support for basic Zicsr.
* 📚 Docs: Added readme.

🎉 **Version 0.1 Released!** 🎉
Expand All @@ -17,8 +18,8 @@

📝 **Previously Unlogged Updates** 📝

* ✅ Feat: support for Immediate Instructions
* ✅ Feat: support for Register-Register Instructions
* ✅ Feat: support for Memory Instructions
* ✅ Feat: support for Flow Control Instructions
* ✅ Feat: Support for Immediate Instructions
* ✅ Feat: Support for Register-Register Instructions
* ✅ Feat: Support for Memory Instructions
* ✅ Feat: Support for Flow Control Instructions
* ✅ Feat: Implemented L1 Instruction Cache support
106 changes: 63 additions & 43 deletions src/main/scala/markorv/ControlStatusRegisters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ package markorv
import chisel3._
import chisel3.util._

class ControlStatusRegistersIO extends Bundle {
val read_addr = Input(UInt(12.W))
val write_addr = Input(UInt(12.W))
val write_en = Input(Bool())

val read_data = Output(UInt(64.W))
val write_data = Input(UInt(64.W))
}

class ControlStatusRegisters extends Module {
val io = IO(new Bundle {
val read_addr = Input(UInt(12.W))
val write_addr = Input(UInt(12.W))

val read_data = Output(UInt(64.W))
val write_data = Input(UInt(64.W))
val write_mask = Input(UInt(64.W))
val csrio = new ControlStatusRegistersIO
})
// While read write simultaneously shuould return old value.

// Machine custom register(MRW)
// For Zicsr test.
val MCUSTOMTST_ADDR = "h800".U(12.W)

// Machine infomations(MRO).
val MVENDORID_ADDR = "hf11".U(12.W)
val MARCHID_ADDR = "hf12".U(12.W)
Expand All @@ -30,6 +38,8 @@ class ControlStatusRegisters extends Module {
val MTVEC_ADDR = "h305".U(12.W)
val MCOUNTEREN_ADDR = "h306".U(12.W)

val mcustomtst = RegInit("h0000000000000000".U(64.W))

val mstatus = RegInit("h0000000000000000".U(64.W))
val misa = RegInit("h8000000000000100".U(64.W))
val medeleg = RegInit("h0000000000000000".U(64.W))
Expand All @@ -39,72 +49,82 @@ class ControlStatusRegisters extends Module {

val mcounteren = RegInit("h00000000".U(32.W))

io.read_data := 0.U
switch(io.read_addr) {
io.csrio.read_data := 0.U
switch(io.csrio.read_addr) {
is(MCUSTOMTST_ADDR) {
io.csrio.read_data := mcustomtst
}

is(MVENDORID_ADDR) {
// Non-commercial.
io.read_data := "h0000000000000000".U
io.csrio.read_data := "h0000000000000000".U
}
is(MARCHID_ADDR) {
// In development.
io.read_data := "h0000000000000000".U
io.csrio.read_data := "h0000000000000000".U
}
is(MIMPID_ADDR) {
// In development.
io.read_data := "h0000000000000000".U
io.csrio.read_data := "h0000000000000000".U
}
is(MHARTID_ADDR) {
// 0x0
io.read_data := "h0000000000000000".U
io.csrio.read_data := "h0000000000000000".U
}
is(MCONFIGPTR_ADDR) {
// TODO machine config
io.read_data := "h0000000000000000".U
io.csrio.read_data := "h0000000000000000".U
}

is(MSTATUS_ADDR) {
io.read_data := mstatus
io.csrio.read_data := mstatus
}
is(MISA_ADDR) {
// RV64I
io.read_data := misa
io.csrio.read_data := misa
}
is(MEDELEG_ADDR) {
io.read_data := medeleg
io.csrio.read_data := medeleg
}
is(MIDELEG_ADDR) {
io.read_data := mideleg
io.csrio.read_data := mideleg
}
is(MCOUNTEREN_ADDR) {
io.read_data := mcounteren
io.csrio.read_data := mcounteren
}
}

switch(io.write_addr) {
is(MSTATUS_ADDR) {
// write mask shown that which fields is implemented.
val write_mask = "h0000000000000000".U
mstatus := write_mask & io.write_data
}
is(MISA_ADDR) {
// Can't write this to switch func for now.
}
is(MEDELEG_ADDR) {
// TODO S mode
medeleg := io.write_data
}
is(MIDELEG_ADDR) {
// TODO S mode
mideleg := io.write_data
}
is(MTVEC_ADDR) {
// mtvec mode >= 2 is Reserved
val write_mask = "hfffffffffffffffd".U
mtvec := write_mask & io.write_data
}
is(MCOUNTEREN_ADDR) {
// TODO counter
mcounteren := io.write_data
when(io.csrio.write_en) {
switch(io.csrio.write_addr) {
is(MCUSTOMTST_ADDR) {
mcustomtst := io.csrio.write_data
}

is(MSTATUS_ADDR) {
// write mask shown that which fields is implemented.
val write_mask = "h0000000000000000".U
mstatus := write_mask & io.csrio.write_data
}
is(MISA_ADDR) {
// Can't write this to switch func for now.
}
is(MEDELEG_ADDR) {
// TODO S mode
medeleg := io.csrio.write_data
}
is(MIDELEG_ADDR) {
// TODO S mode
mideleg := io.csrio.write_data
}
is(MTVEC_ADDR) {
// mtvec mode >= 2 is Reserved
val write_mask = "hfffffffffffffffd".U
mtvec := write_mask & io.csrio.write_data
}
is(MCOUNTEREN_ADDR) {
// TODO counter
mcounteren := io.csrio.write_data
}
}
}
}
16 changes: 16 additions & 0 deletions src/main/scala/markorv/TopModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ class MarkoRvCore extends Module {
val load_store_unit = Module(new LoadStoreUnit)
val arithmetic_logic_unit = Module(new ArithmeticLogicUnit)
val branch_unit = Module(new BranchUnit)
val misc_unit = Module(new MiscUnit)

val register_file = Module(new RegFile)
val csr_file = Module(new ControlStatusRegisters)

val write_back = Module(new WriteBack)

data_cache_warpper.io.cache_write_req <> data_cache.io.write_req
Expand Down Expand Up @@ -98,6 +101,7 @@ class MarkoRvCore extends Module {
write_back.io.reg_write <> register_file.io.write_addr
write_back.io.write_data <> register_file.io.write_data

csr_file.io.csrio <> misc_unit.io.csrio
register_file.io.flush := branch_unit.io.flush

// Main pipeline.
Expand Down Expand Up @@ -127,6 +131,12 @@ class MarkoRvCore extends Module {
load_store_unit.io.outfire,
branch_unit.io.flush
)
PipelineConnect(
instr_issuer.io.misc_out,
misc_unit.io.misc_instr,
misc_unit.io.outfire,
branch_unit.io.flush
)
PipelineConnect(
instr_issuer.io.branch_out,
branch_unit.io.branch_instr,
Expand All @@ -153,6 +163,12 @@ class MarkoRvCore extends Module {
write_back.io.outfires(2),
branch_unit.io.flush
)
PipelineConnect(
misc_unit.io.write_back,
write_back.io.write_backs(3),
write_back.io.outfires(3),
branch_unit.io.flush
)
}

object MarkoRvCore extends App {
Expand Down
10 changes: 4 additions & 6 deletions src/main/scala/markorv/WriteBack.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import chisel3.util._

class WriteBack extends Module {
val io = IO(new Bundle {
val write_backs = Vec(
3,
Flipped(Decoupled(new Bundle {
val write_backs = Vec(4, Flipped(Decoupled(new Bundle {
val reg = UInt(5.W)
val data = UInt(64.W)
}))
Expand All @@ -16,10 +14,10 @@ class WriteBack extends Module {
val reg_write = Output(UInt(5.W))
val write_data = Output(UInt(64.W))

val outfires = Vec(3, Output(Bool()))
val outfires = Vec(4, Output(Bool()))
})

for (i <- 0 until 3) {
for (i <- 0 until 4) {
io.write_backs(i).ready := true.B
io.outfires(i) := true.B
}
Expand All @@ -28,7 +26,7 @@ class WriteBack extends Module {
io.write_data := 0.U

// Impossible to write back multiple times in one cycle.
for (i <- 0 until 3) {
for (i <- 0 until 4) {
when(io.write_backs(i).valid) {
io.reg_write := io.write_backs(i).bits.reg
io.write_data := io.write_backs(i).bits.data
Expand Down
67 changes: 62 additions & 5 deletions src/main/scala/markorv/backend/MiscUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ package markorv.backend
import chisel3._
import chisel3.util._

import markorv.ControlStatusRegistersIO
import markorv.frontend.DecoderOutParams

class MiscUnit extends Module {
val io = IO(new Bundle {
// misc_opcode encoding:
// Bit [4] AMO operate reserved.
// Bit [3] System operate(ecall ebrack etc) reserved.
// Bit [2] Fence operate(fence fence.i) reserved.
// Bit [1] Cache line operate(zicbox) reserved.
// Bit [0] CSR(zicsr) operate.
// Bit [2,0] == 4 AMO operate reserved.
// Bit [2,0] == 3 System operate(ecall ebrack etc) reserved.
// Bit [2,0] == 2 Fence operate(fence fence.i) reserved.
// Bit [2,0] == 1 Cache line operate(zicbox) reserved.
// Bit [2,0] == 0 CSR(zicsr) operate. Bit[3] = rs1 == x0 ? 1 : 0.
val misc_instr = Flipped(Decoupled(new Bundle {
val misc_opcode = UInt(5.W)
val params = new DecoderOutParams(64)
Expand All @@ -22,6 +23,62 @@ class MiscUnit extends Module {
val reg = Input(UInt(5.W))
val data = Input(UInt(64.W))
})

val csrio = Flipped(new ControlStatusRegistersIO)
val outfire = Output(Bool())
})
// M mode when reset.
val privilege_reg = RegInit(3.U(2.W))
val opcode = io.misc_instr.bits.misc_opcode
val params = io.misc_instr.bits.params

// Immediate shall handle by decoder.
val CSRRW = "b01".U
val CSRRS = "b10".U
val CSRRC = "b11".U
io.csrio.write_en := false.B
io.csrio.read_addr := 0.U
io.csrio.write_addr := 0.U
io.csrio.write_data := 0.U

io.outfire := true.B
io.misc_instr.ready := true.B
io.write_back.valid := false.B
io.write_back.bits.reg := 0.U
io.write_back.bits.data := 0.U

when(io.misc_instr.valid) {
when(opcode(2,0) === 0.U) {
val csr_src1 = params.source1
val csr_addr = params.source2
val csr_func = params.immediate
// If rs1 == x0 csrrc and csrrs shall not cause any side effect like illegal instruction exceptions.
val csr_ro = opcode(3) && csr_func =/= CSRRW

// Reserved for illegal instruction exceptions.
val is_csr_read_only = csr_addr(11, 10) === 3.U
val has_privilege = privilege_reg > csr_addr(9, 8)

io.csrio.read_addr := csr_addr
val csr_data = io.csrio.read_data

io.csrio.write_en := ~csr_ro
io.csrio.write_addr := csr_addr
switch(csr_func(1, 0)) {
is(CSRRW) {
io.csrio.write_data := csr_src1
}
is(CSRRS) {
io.csrio.write_data := csr_data | csr_src1
}
is(CSRRC) {
io.csrio.write_data := csr_data & ~csr_src1
}
}

io.write_back.valid := true.B
io.write_back.bits.reg := params.rd
io.write_back.bits.data := csr_data
}
}
}
Loading

0 comments on commit 0ea6dc8

Please sign in to comment.