2016-04-29 23:10:44 +02:00
|
|
|
package uncore
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import cde.{Parameters, Field}
|
2016-05-02 22:58:41 +02:00
|
|
|
import junctions._
|
2016-05-24 22:26:26 +02:00
|
|
|
import HastiConstants._
|
2016-04-29 23:10:44 +02:00
|
|
|
|
|
|
|
class BRAMSlave(depth: Int)(implicit val p: Parameters) extends Module
|
|
|
|
with HasTileLinkParameters {
|
|
|
|
val io = new ClientUncachedTileLinkIO().flip
|
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
val bram = SeqMem(depth, Vec(tlDataBytes, UInt(width = 8)))
|
2016-04-29 23:10:44 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
val s_idle :: s_getblk :: s_putblk :: s_resp :: Nil = Enum(Bits(), 4)
|
|
|
|
val state = Reg(init = s_idle)
|
|
|
|
|
|
|
|
val acq = io.acquire.bits
|
|
|
|
val r_acq = Reg(new AcquireMetadata)
|
|
|
|
|
|
|
|
val (is_get :: is_getblk :: is_put :: is_putblk :: Nil) = Seq(
|
2016-04-29 23:10:44 +02:00
|
|
|
Acquire.getType, Acquire.getBlockType, Acquire.putType, Acquire.putBlockType
|
2016-06-16 05:06:13 +02:00
|
|
|
).map(acq.isBuiltInType _)
|
2016-04-29 23:10:44 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
val beats = Reg(UInt(width = tlBeatAddrBits))
|
2016-04-29 23:10:44 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
when (io.acquire.fire()) {
|
|
|
|
r_acq := acq
|
|
|
|
when (is_get || is_put || acq.isPrefetch()) {
|
|
|
|
state := s_resp
|
|
|
|
}
|
|
|
|
when (is_getblk) {
|
|
|
|
beats := UInt(tlDataBeats - 1)
|
|
|
|
state := s_getblk
|
|
|
|
}
|
|
|
|
/** Need to collect the rest of the beats.
|
|
|
|
* Beat 0 has already been accepted. */
|
|
|
|
when (is_putblk) {
|
|
|
|
beats := UInt(tlDataBeats - 2)
|
|
|
|
state := s_putblk
|
|
|
|
}
|
2016-04-29 23:10:44 +02:00
|
|
|
}
|
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
when (state === s_getblk && io.grant.ready) {
|
|
|
|
r_acq.addr_beat := r_acq.addr_beat + UInt(1)
|
|
|
|
beats := beats - UInt(1)
|
|
|
|
when (beats === UInt(0)) { state := s_idle }
|
|
|
|
}
|
2016-06-09 00:13:39 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
when (state === s_putblk && io.acquire.valid) {
|
|
|
|
beats := beats - UInt(1)
|
|
|
|
when (beats === UInt(0)) { state := s_resp }
|
|
|
|
}
|
2016-04-29 23:10:44 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
when (state === s_resp && io.grant.ready) { state := s_idle }
|
2016-04-29 23:10:44 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
val acq_addr = Cat(acq.addr_block, acq.addr_beat)
|
|
|
|
val r_acq_addr = Cat(r_acq.addr_block, r_acq.addr_beat)
|
2016-04-29 23:10:44 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
val ren = (io.acquire.fire() && (is_get || is_getblk)) ||
|
|
|
|
(state === s_getblk && io.grant.ready)
|
|
|
|
val raddr = Mux(state === s_idle, acq_addr,
|
|
|
|
Mux(io.grant.ready, r_acq_addr + UInt(1), r_acq_addr))
|
2016-04-29 23:10:44 +02:00
|
|
|
val rdata = bram.read(raddr, ren)
|
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
val wen = (io.acquire.fire() && (is_put || is_putblk))
|
|
|
|
val wdata = Vec.tabulate(tlDataBytes) { i => acq.data((i+1)*8-1, i*8) }
|
|
|
|
val wmask = Vec.tabulate(tlWriteMaskBits) { i => acq.wmask()(i) }
|
|
|
|
|
|
|
|
when (wen) { bram.write(acq_addr, wdata, wmask) }
|
2016-04-29 23:10:44 +02:00
|
|
|
|
2016-06-16 05:06:13 +02:00
|
|
|
io.grant.valid := (state === s_resp) || (state === s_getblk)
|
2016-04-29 23:10:44 +02:00
|
|
|
io.grant.bits := Grant(
|
|
|
|
is_builtin_type = Bool(true),
|
2016-06-16 05:06:13 +02:00
|
|
|
g_type = r_acq.getBuiltInGrantType(),
|
|
|
|
client_xact_id = r_acq.client_xact_id,
|
2016-04-29 23:10:44 +02:00
|
|
|
manager_xact_id = UInt(0),
|
2016-06-16 05:06:13 +02:00
|
|
|
addr_beat = r_acq.addr_beat,
|
|
|
|
data = rdata.toBits)
|
|
|
|
io.acquire.ready := (state === s_idle) || (state === s_putblk)
|
2016-04-29 23:10:44 +02:00
|
|
|
}
|
2016-05-02 22:58:41 +02:00
|
|
|
|
|
|
|
class HastiRAM(depth: Int)(implicit p: Parameters) extends HastiModule()(p) {
|
|
|
|
val io = new HastiSlaveIO
|
|
|
|
|
|
|
|
val wdata = Vec.tabulate(hastiDataBytes)(i => io.hwdata(8*(i+1)-1,8*i))
|
|
|
|
val waddr = Reg(UInt(width = hastiAddrBits))
|
|
|
|
val wvalid = Reg(init = Bool(false))
|
|
|
|
val wsize = Reg(UInt(width = SZ_HSIZE))
|
|
|
|
val ram = SeqMem(depth, Vec(hastiDataBytes, Bits(width = 8)))
|
|
|
|
|
2016-06-02 18:04:30 +02:00
|
|
|
val max_size = log2Ceil(hastiDataBytes)
|
2016-05-02 22:58:41 +02:00
|
|
|
val wmask_lut = MuxLookup(wsize, SInt(-1, hastiDataBytes).asUInt,
|
2016-06-02 18:04:30 +02:00
|
|
|
(0 until max_size).map(sz => (UInt(sz) -> UInt((1 << (1 << sz)) - 1))))
|
|
|
|
val wmask = (wmask_lut << waddr(max_size - 1, 0))(hastiDataBytes - 1, 0)
|
2016-05-02 22:58:41 +02:00
|
|
|
|
|
|
|
val is_trans = io.hsel && (io.htrans === HTRANS_NONSEQ || io.htrans === HTRANS_SEQ)
|
2016-06-02 18:04:30 +02:00
|
|
|
val raddr = io.haddr >> UInt(max_size)
|
2016-05-02 22:58:41 +02:00
|
|
|
val ren = is_trans && !io.hwrite
|
|
|
|
val bypass = Reg(init = Bool(false))
|
|
|
|
|
|
|
|
when (is_trans && io.hwrite) {
|
|
|
|
waddr := io.haddr
|
|
|
|
wsize := io.hsize
|
|
|
|
wvalid := Bool(true)
|
|
|
|
} .otherwise { wvalid := Bool(false) }
|
|
|
|
|
2016-06-02 18:04:30 +02:00
|
|
|
when (ren) { bypass := wvalid && (waddr >> UInt(max_size)) === raddr }
|
2016-05-02 22:58:41 +02:00
|
|
|
|
|
|
|
when (wvalid) {
|
2016-06-02 18:04:30 +02:00
|
|
|
ram.write(waddr >> UInt(max_size), wdata, wmask.toBools)
|
2016-05-02 22:58:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
val rdata = ram.read(raddr, ren)
|
|
|
|
io.hrdata := Cat(rdata.zip(wmask.toBools).zip(wdata).map {
|
|
|
|
case ((rbyte, wsel), wbyte) => Mux(wsel && bypass, wbyte, rbyte)
|
|
|
|
}.reverse)
|
|
|
|
|
2016-05-24 22:26:26 +02:00
|
|
|
io.hready := Bool(true)
|
2016-05-02 22:58:41 +02:00
|
|
|
io.hresp := HRESP_OKAY
|
|
|
|
}
|