81 lines
2.8 KiB
Scala
81 lines
2.8 KiB
Scala
// See LICENSE for license details.
|
|
|
|
package uncore
|
|
import Chisel._
|
|
|
|
class BigMem[T <: Data](n: Int, preLatency: Int, postLatency: Int, leaf: Mem[UInt], noMask: Boolean = false)(gen: => T) extends Module
|
|
{
|
|
class Inputs extends Bundle {
|
|
val addr = UInt(INPUT, log2Up(n))
|
|
val rw = Bool(INPUT)
|
|
val wdata = gen.asInput
|
|
val wmask = gen.asInput
|
|
override def clone = new Inputs().asInstanceOf[this.type]
|
|
}
|
|
val io = new Bundle {
|
|
val in = Valid(new Inputs).flip
|
|
val rdata = gen.asOutput
|
|
}
|
|
val data = gen
|
|
val colMux = if (2*data.getWidth <= leaf.data.getWidth && n > leaf.n) 1 << math.floor(math.log(leaf.data.getWidth/data.getWidth)/math.log(2)).toInt else 1
|
|
val nWide = if (data.getWidth > leaf.data.getWidth) 1+(data.getWidth-1)/leaf.data.getWidth else 1
|
|
val nDeep = if (n > colMux*leaf.n) 1+(n-1)/(colMux*leaf.n) else 1
|
|
if (nDeep > 1 || colMux > 1)
|
|
require(isPow2(n) && isPow2(leaf.n))
|
|
|
|
val rdataDeep = Vec.fill(nDeep){Bits()}
|
|
val rdataSel = Vec.fill(nDeep){Bool()}
|
|
for (i <- 0 until nDeep) {
|
|
val in = Pipe(io.in.valid && (if (nDeep == 1) Bool(true) else UInt(i) === io.in.bits.addr(log2Up(n)-1, log2Up(n/nDeep))), io.in.bits, preLatency)
|
|
val idx = in.bits.addr(log2Up(n/nDeep/colMux)-1, 0)
|
|
val wdata = in.bits.wdata.toBits
|
|
val wmask = in.bits.wmask.toBits
|
|
val ren = in.valid && !in.bits.rw
|
|
val reg_ren = Reg(next=ren)
|
|
val rdata = Vec.fill(nWide){Bits()}
|
|
|
|
val r = Pipe(ren, in.bits.addr, postLatency)
|
|
|
|
for (j <- 0 until nWide) {
|
|
val mem = leaf.clone
|
|
var dout: Bits = null
|
|
val ridx = if (postLatency > 0) Reg(Bits()) else null
|
|
|
|
var wmask0 = Fill(colMux, wmask(math.min(wmask.getWidth, leaf.data.getWidth*(j+1))-1, leaf.data.getWidth*j))
|
|
if (colMux > 1)
|
|
wmask0 = wmask0 & FillInterleaved(gen.getWidth, UIntToOH(in.bits.addr(log2Up(n/nDeep)-1, log2Up(n/nDeep/colMux)), log2Up(colMux)))
|
|
val wdata0 = Fill(colMux, wdata(math.min(wdata.getWidth, leaf.data.getWidth*(j+1))-1, leaf.data.getWidth*j))
|
|
when (in.valid) {
|
|
when (in.bits.rw) {
|
|
if (noMask)
|
|
mem.write(idx, wdata0)
|
|
else
|
|
mem.write(idx, wdata0, wmask0)
|
|
}
|
|
.otherwise { if (postLatency > 0) ridx := idx }
|
|
}
|
|
|
|
if (postLatency == 0) {
|
|
dout = mem(idx)
|
|
} else if (postLatency == 1) {
|
|
dout = mem(ridx)
|
|
} else
|
|
dout = Pipe(reg_ren, mem(ridx), postLatency-1).bits
|
|
|
|
rdata(j) := dout
|
|
}
|
|
val rdataWide = rdata.reduceLeft((x, y) => Cat(y, x))
|
|
|
|
var colMuxOut = rdataWide
|
|
if (colMux > 1) {
|
|
val colMuxIn = Vec((0 until colMux).map(k => rdataWide(gen.getWidth*(k+1)-1, gen.getWidth*k)))
|
|
colMuxOut = colMuxIn(r.bits(log2Up(n/nDeep)-1, log2Up(n/nDeep/colMux)))
|
|
}
|
|
|
|
rdataDeep(i) := colMuxOut
|
|
rdataSel(i) := r.valid
|
|
}
|
|
|
|
io.rdata := Mux1H(rdataSel, rdataDeep)
|
|
}
|