提交 e46e877c 编写于 作者: L Lingrui98

utils: bump DataModuleTemplate to newest version and add default value to parentModule parameter

上级 2f12ee53
......@@ -19,7 +19,14 @@ package utils
import chisel3._
import chisel3.util._
class RawDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int, isSync: Boolean) extends Module {
class RawDataModuleTemplate[T <: Data](
gen: T,
numEntries: Int,
numRead: Int,
numWrite: Int,
isSync: Boolean,
optWrite: Seq[Int] = Seq()
) extends Module {
val io = IO(new Bundle {
val rvec = Vec(numRead, Input(UInt(numEntries.W)))
val rdata = Vec(numRead, Output(gen))
......@@ -30,6 +37,10 @@ class RawDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, nu
val data = Reg(Vec(numEntries, gen))
val wen = io.wen.zipWithIndex.map{ case (en, i) => if (optWrite.contains(i)) RegNext(en) else en }
val wvec = io.wvec.zipWithIndex.map{ case (v, i) => if (optWrite.contains(i)) RegEnable(v, io.wen(i)) else v }
val wdata = io.wdata.zipWithIndex.map{ case (d, i) => if (optWrite.contains(i)) RegEnable(d, io.wen(i)) else d }
// read ports
val rvec = if (isSync) RegNext(io.rvec) else io.rvec
for (i <- 0 until numRead) {
......@@ -37,55 +48,150 @@ class RawDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, nu
io.rdata(i) := Mux1H(rvec(i), data)
}
if (optWrite.nonEmpty) {
val data_next = WireInit(data)
val wbypass = io.wen.zip(io.wvec).zip(wdata).zipWithIndex.filter(x => optWrite.contains(x._2)).map(_._1)
for (i <- 0 until numEntries) {
val wbypass_en = wbypass.map(w => RegNext(w._1._1 && w._1._2(i)))
when (VecInit(wbypass_en).asUInt.orR) {
data_next(i) := Mux1H(wbypass_en, wbypass.map(_._2))
}
}
for (i <- 0 until numRead) {
io.rdata(i) := Mux1H(rvec(i), data_next)
}
}
// write ports
for (i <- 0 until numEntries) {
val w = VecInit((0 until numWrite).map(j => io.wen(j) && io.wvec(j)(i)))
val w = VecInit((0 until numWrite).map(j => wen(j) && wvec(j)(i)))
assert(PopCount(w) <= 1.U)
when (w.asUInt.orR) {
data(i) := Mux1H(w, io.wdata)
data(i) := Mux1H(w, wdata)
}
}
}
class SyncRawDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends RawDataModuleTemplate(gen, numEntries, numRead, numWrite, true)
class AsyncRawDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends RawDataModuleTemplate(gen, numEntries, numRead, numWrite, false)
class SyncRawDataModuleTemplate[T <: Data](
gen: T, numEntries: Int, numRead: Int, numWrite: Int, optWrite: Seq[Int] = Seq()
) extends RawDataModuleTemplate(gen, numEntries, numRead, numWrite, true, optWrite)
class AsyncRawDataModuleTemplate[T <: Data](
gen: T, numEntries: Int, numRead: Int, numWrite: Int, optWrite: Seq[Int] = Seq()
) extends RawDataModuleTemplate(gen, numEntries, numRead, numWrite, false, optWrite)
class SyncDataModuleTemplate[T <: Data](
gen: T,
numEntries: Int,
numRead: Int,
numWrite: Int,
parentModule: String = "",
concatData: Boolean = false,
perReadPortBypassEnable: Option[Seq[Boolean]] = None
) extends Module {
val io = IO(new Bundle {
val raddr = Vec(numRead, Input(UInt(log2Ceil(numEntries).W)))
val rdata = Vec(numRead, Output(gen))
val wen = Vec(numWrite, Input(Bool()))
val waddr = Vec(numWrite, Input(UInt(log2Ceil(numEntries).W)))
val wdata = Vec(numWrite, Input(gen))
})
override def desiredName: String = s"SyncDataModuleTemplate_${parentModule}_${numEntries}entry"
val dataType = if (concatData) UInt(gen.getWidth.W) else gen
val maxBankEntries = if (numEntries >= 2 * 64) 64 else 16
val numBanks = (numEntries + maxBankEntries - 1) / maxBankEntries
def bankOffset(address: UInt): UInt = {
if (numBanks > 1) address(log2Ceil(maxBankEntries) - 1, 0)
else address
}
def bankIndex(address: UInt): UInt = {
if (numBanks > 1) address(log2Ceil(numEntries) - 1, log2Ceil(maxBankEntries))
else 0.U
}
// if use bypassEnable to control bypass of each port,
// then we should have a separate bit for each read port
perReadPortBypassEnable.map(en_vec => require(en_vec.length == numRead))
val dataBanks = Seq.tabulate(numBanks)(i => {
val bankEntries = if (i < numBanks - 1) maxBankEntries else numEntries - (i * maxBankEntries)
val dataBank = Module(new NegedgeDataModuleTemplate(dataType, bankEntries, numRead, numWrite, parentModule, perReadPortBypassEnable))
// delay one clock
val raddr_dup = RegNext(io.raddr)
val wen_dup = RegNext(io.wen)
val waddr_dup = io.wen.zip(io.waddr).map(w => RegEnable(w._2, w._1))
// input
dataBank.io.raddr := raddr_dup.map(bankOffset)
dataBank.io.wen := wen_dup.zip(waddr_dup).map{ case (en, addr) => en && bankIndex(addr) === i.U }
dataBank.io.waddr := waddr_dup.map(bankOffset)
if (concatData) {
val wdata_dup = io.wen.zip(io.wdata).map(w => RegEnable(w._2.asTypeOf(dataType), w._1))
dataBank.io.wdata := wdata_dup
}
else {
dataBank.io.wdata := io.wen.zip(io.wdata).map(w => RegEnable(w._2, w._1))
}
dataBank
})
// output
val rdata = if (concatData) dataBanks.map(_.io.rdata.map(_.asTypeOf(gen))) else dataBanks.map(_.io.rdata)
for (j <- 0 until numRead) {
val raddr_dup = RegNext(io.raddr(j))
val index_dec = UIntToOH(bankIndex(raddr_dup), numBanks)
io.rdata(j) := Mux1H(index_dec, rdata.map(_(j)))
}
}
class DataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int, isSync: Boolean) extends Module {
class NegedgeDataModuleTemplate[T <: Data](
gen: T,
numEntries: Int,
numRead: Int,
numWrite: Int,
parentModule: String,
perReadPortBypassEnable: Option[Seq[Boolean]] = None
) extends Module {
val io = IO(new Bundle {
val raddr = Vec(numRead, Input(UInt(log2Up(numEntries).W)))
val raddr = Vec(numRead, Input(UInt(log2Ceil(numEntries).W)))
val rdata = Vec(numRead, Output(gen))
val wen = Vec(numWrite, Input(Bool()))
val waddr = Vec(numWrite, Input(UInt(log2Up(numEntries).W)))
val waddr = Vec(numWrite, Input(UInt(log2Ceil(numEntries).W)))
val wdata = Vec(numWrite, Input(gen))
})
val data = Mem(numEntries, gen)
override def desiredName: String = s"NegedgeDataModule_${parentModule}_${numEntries}entry"
val data = Reg(Vec(numEntries, gen))
// if use bypassEnable to control bypass of each port,
// then we should have a separate bit for each read port
perReadPortBypassEnable.map(en_vec => require(en_vec.length == numRead))
// read ports
val raddr = if (isSync) (RegNext(io.raddr)) else io.raddr
for (i <- 0 until numRead) {
io.rdata(i) := data(raddr(i))
}
// below is the write ports (with priorities)
for (i <- 0 until numWrite) {
when (io.wen(i)) {
data(io.waddr(i)) := io.wdata(i)
val bypass_en = perReadPortBypassEnable.map(_(i)).getOrElse(true)
val read_by = io.wen.zip(io.waddr).map(w => w._1 && w._2 === io.raddr(i) && bypass_en.B)
val addr_dec = UIntToOH(io.raddr(i), numEntries)
when (VecInit(read_by).asUInt.orR) {
io.rdata(i) := Mux1H(read_by, io.wdata)
} .otherwise {
io.rdata(i) := Mux1H(addr_dec, data)
}
}
// DataModuleTemplate should not be used when there're any write conflicts
for (i <- 0 until numWrite) {
for (j <- i+1 until numWrite) {
assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
// write ports
val waddr_dec = io.waddr.map(a => UIntToOH(a))
for (j <- 0 until numEntries) {
val write_wen = io.wen.zip(waddr_dec).map(w => w._1 && w._2(j))
when (VecInit(write_wen).asUInt.orR) {
data(j) := Mux1H(write_wen, io.wdata)
}
}
}
class SyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends DataModuleTemplate(gen, numEntries, numRead, numWrite, true)
class AsyncDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int) extends DataModuleTemplate(gen, numEntries, numRead, numWrite, false)
class Folded1WDataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int,
isSync: Boolean, width: Int, hasResetEn: Boolean = true) extends Module {
val io = IO(new Bundle {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册