SRAMTemplate.scala 3.7 KB
Newer Older
1 2 3 4 5
package utils

import chisel3._
import chisel3.util._

6
class SRAMBundleA(val set: Int) extends Bundle {
7
  val setIdx = Output(UInt(log2Up(set).W))
8 9 10 11 12

  def apply(setIdx: UInt) = {
    this.setIdx := setIdx
    this
  }
13 14
}

15
class SRAMBundleAW[T <: Data](private val gen: T, set: Int, val way: Int = 1) extends SRAMBundleA(set) {
16
  val data = Output(gen)
17
  val waymask = if (way > 1) Some(Output(UInt(way.W))) else None
18 19 20 21 22 23 24

  def apply(data: T, setIdx: UInt, waymask: UInt) = {
    super.apply(setIdx)
    this.data := data
    this.waymask.map(_ := waymask)
    this
  }
25 26
}

27 28
class SRAMBundleR[T <: Data](private val gen: T, val way: Int = 1) extends Bundle {
  val data = Output(Vec(way, gen))
29 30
}

31
class SRAMReadBus[T <: Data](private val gen: T, val set: Int, val way: Int = 1) extends Bundle {
32
  val req = Decoupled(new SRAMBundleA(set))
33
  val resp = Flipped(new SRAMBundleR(gen, way))
34 35 36 37 38 39

  def apply(valid: Bool, setIdx: UInt) = {
    this.req.bits.apply(setIdx)
    this.req.valid := valid
    this
  }
40 41
}

42 43
class SRAMWriteBus[T <: Data](private val gen: T, val set: Int, val way: Int = 1) extends Bundle {
  val req = Decoupled(new SRAMBundleAW(gen, set, way))
44 45 46 47 48 49

  def apply(valid: Bool, data: T, setIdx: UInt, waymask: UInt) = {
    this.req.bits.apply(data = data, setIdx = setIdx, waymask = waymask)
    this.req.valid := valid
    this
  }
50 51
}

52
class SRAMTemplate[T <: Data](gen: T, set: Int, way: Int = 1,
53 54
  shouldReset: Boolean = false, holdRead: Boolean = false, singlePort: Boolean = false) extends Module {
  val io = IO(new Bundle {
55 56
    val r = Flipped(new SRAMReadBus(gen, set, way))
    val w = Flipped(new SRAMWriteBus(gen, set, way))
57 58 59
  })

  val wordType = UInt(gen.getWidth.W)
60 61
  val array = SyncReadMem(set, Vec(way, wordType))
  val (resetState, resetSet) = (WireInit(false.B), WireInit(0.U))
62 63 64

  if (shouldReset) {
    val _resetState = RegInit(true.B)
65
    val (_resetSet, resetFinish) = Counter(_resetState, set)
66 67 68
    when (resetFinish) { _resetState := false.B }

    resetState := _resetState
69
    resetSet := _resetSet
70 71
  }

72 73 74 75
  val (ren, wen) = (io.r.req.valid, io.w.req.valid || resetState)
  val realRen = (if (singlePort) ren && !wen else ren)

  val setIdx = Mux(resetState, resetSet, io.w.req.bits.setIdx)
76
  val wdataword = Mux(resetState, 0.U.asTypeOf(wordType), io.w.req.bits.data.asUInt)
77
  val waymask = Mux(resetState, Fill(way, "b1".U), io.w.req.bits.waymask.getOrElse("b1".U))
Z
Zihao Yu 已提交
78
  val wdata = VecInit(Seq.fill(way)(wdataword))
79
  when (wen) { array.write(setIdx, wdata, waymask.asBools) }
80

81 82 83
  val rdata = (if (holdRead) ReadAndHold(array, io.r.req.bits.setIdx, realRen)
               else array.read(io.r.req.bits.setIdx, realRen)).map(_.asTypeOf(gen))
  io.r.resp.data := VecInit(rdata)
Z
Zihao Yu 已提交
84

85 86
  io.r.req.ready := !resetState && (if (singlePort) !wen else true.B)
  io.w.req.ready := true.B
87

Y
Yinan Xu 已提交
88 89 90 91 92 93 94 95
  // Debug(false) {
  //   when (wen) {
  //     printf("%d: SRAMTemplate: write %x to idx = %d\n", GTimer(), wdata.asUInt, setIdx)
  //   }
  //   when (RegNext(realRen)) {
  //     printf("%d: SRAMTemplate: read %x at idx = %d\n", GTimer(), VecInit(rdata).asUInt, RegNext(io.r.req.bits.setIdx))
  //   }
  // }
96
}
97

98
class SRAMTemplateWithArbiter[T <: Data](nRead: Int, gen: T, set: Int, way: Int = 1,
99 100 101
  shouldReset: Boolean = false) extends Module {
  val io = IO(new Bundle {
    val r = Flipped(Vec(nRead, new SRAMReadBus(gen, set, way)))
102
    val w = Flipped(new SRAMWriteBus(gen, set, way))
103 104 105
  })

  val ram = Module(new SRAMTemplate(gen, set, way, shouldReset, holdRead = false, singlePort = true))
106
  ram.io.w <> io.w
107 108 109 110 111

  val readArb = Module(new Arbiter(chiselTypeOf(io.r(0).req.bits), nRead))
  readArb.io.in <> io.r.map(_.req)
  ram.io.r.req <> readArb.io.out

112
  // latch read results
113
  io.r.map{ case r => {
114
    r.resp.data := HoldUnless(ram.io.r.resp.data, RegNext(r.req.fire()))
115
  }}
116
}