Skip to content

Commit

Permalink
add set cache
Browse files Browse the repository at this point in the history
  • Loading branch information
LoveLonelyTime committed Jan 31, 2024
1 parent f2cfcb2 commit f3424b5
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 23 deletions.
7 changes: 6 additions & 1 deletion src/main/scala/lltriscv/bus/AXI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,33 @@ object AXISpec {
val dataWidth = 32
}

class AXIManagerIO extends Bundle {
class AXIMasterIO extends Bundle {
// Write request channel (AW)
val AWVALID = Output(Bool())
val AWREADY = Input(Bool())
val AWADDR = Output(UInt(AXISpec.addressWidth.W))
val AWPORT = Output(UInt(3.W))

// Write data channel (W)
val WVALID = Output(Bool())
val WREADY = Input(Bool())
val WDATA = Output(UInt(AXISpec.dataWidth.W))
val WSTRB = Output(UInt((AXISpec.dataWidth / 8).W))

// Write response channel (B)
val BVALID = Input(Bool())
val BREADY = Output(Bool())
val BRESP = Input(UInt(2.W))

// Read request channel (AR)
val ARVALID = Output(Bool())
val ARREADY = Input(Bool())
val ARADDR = Output(UInt(AXISpec.addressWidth.W))
val ARPORT = Output(UInt(3.W))

// Read data channel (R)
val RVALID = Input(Bool())
val RREADY = Output(Bool())
val RDATA = Input(UInt(AXISpec.dataWidth.W))
val RRESP = Input(UInt(2.W))
}
141 changes: 141 additions & 0 deletions src/main/scala/lltriscv/bus/AXIMaster.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package lltriscv.bus

import chisel3._
import chisel3.util._

import lltriscv.core.execute.MemoryAccessLength

/** Core M/MMIO aggregation interface
*
* Provide conversion from a set of SMA buses to AXI bus
*
* Misaligned address access not supported
*/
class AXIMaster extends Module {
val io = IO(new Bundle {
val smaReader = Flipped(new SMAReaderIO())
val smaWriter = Flipped(new SMAWriterIO())

val axi = new AXIMasterIO()
})

private object AXIStatus extends ChiselEnum {
val idle, address, data, response = Value;
}

// Reader logic
private val readerStatusReg = RegInit(AXIStatus.idle)

when(readerStatusReg === AXIStatus.idle) {
when(io.smaReader.valid) {
readerStatusReg := AXIStatus.address
}
}

when(readerStatusReg === AXIStatus.address) {
// 32-bit address alignment
io.axi.ARADDR := io.smaReader.address(31, 2) ## 0.U(2.W)
io.axi.ARPORT := 0.U
io.axi.ARVALID := true.B
when(io.axi.ARREADY) {
readerStatusReg := AXIStatus.response
}
}

when(readerStatusReg === AXIStatus.response) {
io.axi.RREADY := true.B

when(io.axi.RVALID) {
switch(io.smaReader.readType) {
is(MemoryAccessLength.byte) {
io.smaReader.data := MuxLookup(io.smaReader.address(1, 0), 0.U)(
Seq(
"b00".U -> io.axi.RDATA(7, 0),
"b01".U -> io.axi.RDATA(15, 8),
"b10".U -> io.axi.RDATA(23, 16),
"b11".U -> io.axi.RDATA(31, 24)
)
)
}
is(MemoryAccessLength.half) {
io.smaReader.data := Mux(io.smaReader.address(1), io.axi.RDATA(31, 16), io.axi.RDATA(15, 0))
}
is(MemoryAccessLength.word) {
io.smaReader.data := io.axi.RDATA
}
}

io.smaReader.error := false.B
io.smaReader.ready := true.B

readerStatusReg := AXIStatus.idle
}
}

// Writer logic
private val writerStatusReg = RegInit(AXIStatus.idle)

when(writerStatusReg === AXIStatus.idle) {
when(io.smaWriter.valid) {
writerStatusReg := AXIStatus.address
}
}

when(writerStatusReg === AXIStatus.address) {
// 32-bit address alignment
io.axi.AWADDR := io.smaWriter.address(31, 2) ## 0.U(2.W)
io.axi.AWPORT := 0.U
io.axi.AWVALID := true.B
when(io.axi.AWREADY) {
writerStatusReg := AXIStatus.data
}
}

when(writerStatusReg === AXIStatus.data) {
switch(io.smaWriter.writeType) {
is(MemoryAccessLength.byte) {
io.axi.WDATA := MuxLookup(io.smaWriter.address(1, 0), 0.U)(
Seq(
"b00".U -> io.smaWriter.data(7, 0),
"b01".U -> io.smaWriter.data(7, 0) ## 0.U(8.W),
"b10".U -> io.smaWriter.data(7, 0) ## 0.U(16.W),
"b11".U -> io.smaWriter.data(7, 0) ## 0.U(24.W)
)
)

io.axi.WSTRB := MuxLookup(io.smaWriter.address(1, 0), 0.U)(
Seq(
"b00".U -> "b0001".U,
"b01".U -> "b0010".U,
"b10".U -> "b0100".U,
"b11".U -> "b1000".U
)
)
}

is(MemoryAccessLength.half) {
io.axi.WDATA := Mux(io.smaWriter.address(1), io.smaWriter.data(15, 0) ## 0.U(16.W), io.smaWriter.data(15, 0))
io.axi.WSTRB := Mux(io.smaWriter.address(1), "b1100".U, "b0011".U)
}

is(MemoryAccessLength.word) {
io.axi.WDATA := io.smaWriter.data
io.axi.WSTRB := "b1111".U
}
}

io.axi.WVALID := true.B
when(io.axi.WREADY) {
writerStatusReg := AXIStatus.response
}
}

when(writerStatusReg === AXIStatus.response) {
io.axi.BREADY := true.B
when(io.axi.BVALID) {
io.smaWriter.ready := true.B
io.smaWriter.error := 0.U
writerStatusReg := AXIStatus.idle
}
}
}
149 changes: 133 additions & 16 deletions src/main/scala/lltriscv/cache/Cache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,40 +34,46 @@ class TrivialDCache extends Module {
io.flush.empty := true.B
}

//! TestCode
class TrivialICache(depth: Int) extends Module {
/** Cache line request to SMA
*
* Conversion of cache line requests to SMA interface with 32-bit bandwidth.
* @param cacheLineDepth
* Require 32-bit aligned cache line depth
*/
class CacheLineRequest2SMA(cacheLineDepth: Int) {
val io = IO(new Bundle {
val request = Flipped(new ICacheLineRequestIO(depth))
val downReader = new SMAReaderIO()

val flush = Flipped(new FlushCacheIO())
val request = Flipped(new CacheLineRequestIO(cacheLineDepth))
val smaReader = new SMAReaderIO()
})

private object Status extends ChiselEnum {
val idle, working, finish = Value
}

private val statusReg = RegInit(Status.idle)
private val incr = WireInit(false.B)
private val (counterReg, nextValue) = CoreUtils.pointer(depth, incr)
private val dataReg = RegInit(Vec(depth, UInt(16.W)).zero)
private val (counterReg, nextValue) = CoreUtils.pointer(cacheLineDepth / 2, incr)
private val dataReg = RegInit(Vec(cacheLineDepth, UInt(16.W)).zero)

when(statusReg === Status.idle) {
when(io.request.valid) {
statusReg := Status.working
}
}

io.downReader.valid := false.B
io.downReader.readType := MemoryAccessLength.half
io.downReader.address := io.request.address(31, log2Ceil(depth) + 1) ## counterReg ## 0.U
io.smaReader.valid := false.B
io.smaReader.readType := MemoryAccessLength.word
io.smaReader.address := io.request.address(31, log2Ceil(cacheLineDepth) + 1) ## counterReg ## 0.U(2.W)

when(statusReg === Status.working) {
io.downReader.valid := true.B
io.smaReader.valid := true.B

when(io.downReader.ready) {
when(io.smaReader.ready) {
incr := true.B
dataReg(counterReg) := io.downReader.data
dataReg(counterReg ## 1.U) := io.smaReader.data(31, 16)
dataReg(counterReg ## 0.U) := io.smaReader.data(15, 0)

when(counterReg === (depth - 1).U) {
when(counterReg === (cacheLineDepth / 2 - 1).U) {
statusReg := Status.finish
}
}
Expand All @@ -84,6 +90,117 @@ class TrivialICache(depth: Int) extends Module {
statusReg := Status.idle
}
}
}

io.flush.empty := true.B
/** Set Cache (Write-Through)
*
* @param cacheLineDepth
*/
class SetCache(tagDepth: Int, wayDepth: Int, cacheLineDepth: Int) {
val io = IO(new Bundle {
// In
val inWriter = Flipped(new SMAWriterIO())
val inReader = Flipped(new CacheLineRequestIO(cacheLineDepth))

// Out
val outWriter = new SMAWriterIO()
val outReader = new CacheLineRequestIO(cacheLineDepth)
})

private class TagEntry extends Bundle {
val address = UInt(31.W)
val valid = Bool()
}

private val tagMem = Seq.fill(wayDepth)(SyncReadMem(log2Ceil(tagDepth), new TagEntry()))
private val dataMem = Seq.fill(wayDepth)(SyncReadMem(log2Ceil(tagDepth), Vec(cacheLineDepth, UInt(16.W))))

private val victimIncr = WireInit(false.B)
private val (victimReg, _) = CoreUtils.pointer(wayDepth, victimIncr)

private object Status extends ChiselEnum {
val idle, lookup, read, write = Value;
}
private val statusReg = RegInit(Status.idle)
private val responseReadReg = RegInit(false.B)

private def getTag(address: UInt) = address(31, 32 - log2Ceil(tagDepth))
private def getCacheAddress(address: UInt) = address(31, log2Ceil(cacheLineDepth) + 1)

when(statusReg === Status.idle) {
val address = Mux(responseReadReg, io.inReader.address, io.inWriter.address)
tagMem.zip(dataMem).foreach { case (tagWay, dataWay) =>
tagWay.read(getTag(address))
dataWay.read(getTag(address))
}

when(io.inReader.valid) {
responseReadReg := true.B
statusReg := Status.lookup
}.elsewhen(io.inWriter.valid) {
responseReadReg := false.B
statusReg := Status.lookup
}
}

when(statusReg === Status.lookup) {
val address = Mux(responseReadReg, io.inReader.address, io.inWriter.address)
val hit = WireInit(false.B)

tagMem.zip(dataMem).foreach { case (tagWay, dataWay) =>
val tagCell = tagWay.read(getTag(address))
val dataCell = dataWay.read(getTag(address))
when(tagCell.valid && tagCell.address === getCacheAddress(address)) { // Hit
hit := true.B
when(responseReadReg) { // Hit read
io.inReader.error := false.B
io.inReader.data := dataCell
io.inReader.ready := true.B

statusReg := Status.idle
}.otherwise { // Hit write
val newData = Wire(Vec(cacheLineDepth, UInt(16.W)))
// TODO: Write
dataWay.write(getTag(address), newData)
}
}
}

when(responseReadReg && !hit) {
statusReg := Status.read
}.elsewhen(!responseReadReg) {
statusReg := Status.write
}
}

when(statusReg === Status.read) {
val address = io.inReader.address
io.outReader.address := getCacheAddress(address)
io.outReader.valid := true.B

when(io.outReader.ready) {
tagMem.zip(dataMem).zipWithIndex.foreach { case ((tagWay, dataWay), way) =>
when(way.U === victimReg) {
val entry = Wire(new TagEntry())
entry.address := getCacheAddress(address)
entry.valid := true.B
tagWay.write(getTag(address), entry)
dataWay.write(getTag(address), io.outReader.data)
}
}
victimIncr := true.B

io.inReader.error := false.B
io.inReader.data := io.outReader.data
io.inReader.ready := true.B
statusReg := Status.idle
}
}

when(statusReg === Status.write) {
io.inWriter <> io.outWriter
when(io.outWriter.ready) {
statusReg := Status.idle
}
}
}
2 changes: 1 addition & 1 deletion src/main/scala/lltriscv/cache/CacheEntry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class FlushCacheIO extends Bundle {
* @param cacheLineDepth
* Size(bits) = 16 * Cache line depth
*/
class ICacheLineRequestIO(cacheLineDepth: Int) extends Bundle {
class CacheLineRequestIO(cacheLineDepth: Int) extends Bundle {
val address = Output(DataType.address) // Aligned cache line address
val data = Input(Vec(cacheLineDepth, UInt(16.W))) // Group data
val error = Input(Bool()) // Memory error
Expand Down
Loading

0 comments on commit f3424b5

Please sign in to comment.