support streaming DMA in DMA frontend
This commit is contained in:
parent
dbe68056d9
commit
05b359d357
@ -8,7 +8,7 @@ import cde.Parameters
|
|||||||
|
|
||||||
trait HasClientDmaParameters extends HasCoreParameters with HasDmaParameters {
|
trait HasClientDmaParameters extends HasCoreParameters with HasDmaParameters {
|
||||||
val dmaAddrBits = coreMaxAddrBits
|
val dmaAddrBits = coreMaxAddrBits
|
||||||
val dmaSizeBits = coreMaxAddrBits
|
val dmaSegmentSizeBits = coreMaxAddrBits
|
||||||
val dmaSegmentBits = 24
|
val dmaSegmentBits = 24
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,10 +21,11 @@ class ClientDmaRequest(implicit p: Parameters) extends ClientDmaBundle()(p) {
|
|||||||
val cmd = UInt(width = DMA_CMD_SZ)
|
val cmd = UInt(width = DMA_CMD_SZ)
|
||||||
val src_start = UInt(width = dmaAddrBits)
|
val src_start = UInt(width = dmaAddrBits)
|
||||||
val dst_start = UInt(width = dmaAddrBits)
|
val dst_start = UInt(width = dmaAddrBits)
|
||||||
val src_stride = UInt(width = dmaSizeBits)
|
val src_stride = UInt(width = dmaSegmentSizeBits)
|
||||||
val dst_stride = UInt(width = dmaSizeBits)
|
val dst_stride = UInt(width = dmaSegmentSizeBits)
|
||||||
val segment_size = UInt(width = dmaSizeBits)
|
val segment_size = UInt(width = dmaSegmentSizeBits)
|
||||||
val nsegments = UInt(width = dmaSegmentBits)
|
val nsegments = UInt(width = dmaSegmentBits)
|
||||||
|
val word_size = UInt(width = dmaWordSizeBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
object ClientDmaRequest {
|
object ClientDmaRequest {
|
||||||
@ -34,7 +35,8 @@ object ClientDmaRequest {
|
|||||||
segment_size: UInt,
|
segment_size: UInt,
|
||||||
nsegments: UInt = UInt(1),
|
nsegments: UInt = UInt(1),
|
||||||
src_stride: UInt = UInt(0),
|
src_stride: UInt = UInt(0),
|
||||||
dst_stride: UInt = UInt(0))
|
dst_stride: UInt = UInt(0),
|
||||||
|
word_size: UInt = UInt(0))
|
||||||
(implicit p: Parameters) = {
|
(implicit p: Parameters) = {
|
||||||
val req = Wire(new ClientDmaRequest)
|
val req = Wire(new ClientDmaRequest)
|
||||||
req.cmd := cmd
|
req.cmd := cmd
|
||||||
@ -44,6 +46,7 @@ object ClientDmaRequest {
|
|||||||
req.dst_stride := dst_stride
|
req.dst_stride := dst_stride
|
||||||
req.segment_size := segment_size
|
req.segment_size := segment_size
|
||||||
req.nsegments := nsegments
|
req.nsegments := nsegments
|
||||||
|
req.word_size := word_size
|
||||||
req
|
req
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,10 +86,16 @@ class DmaFrontend(implicit val p: Parameters)
|
|||||||
val vm_enabled = io.ptw.status.vm(3) && priv <= UInt(PRV_S)
|
val vm_enabled = io.ptw.status.vm(3) && priv <= UInt(PRV_S)
|
||||||
|
|
||||||
val cmd = Reg(UInt(width = DMA_CMD_SZ))
|
val cmd = Reg(UInt(width = DMA_CMD_SZ))
|
||||||
|
val adv_ptr = MuxLookup(cmd, UInt("b11"), Seq(
|
||||||
|
DMA_CMD_PFR -> UInt("b10"),
|
||||||
|
DMA_CMD_PFW -> UInt("b10"),
|
||||||
|
DMA_CMD_SIN -> UInt("b10"),
|
||||||
|
DMA_CMD_SOUT -> UInt("b01")))
|
||||||
|
|
||||||
val segment_size = Reg(UInt(width = dmaSizeBits))
|
val segment_size = Reg(UInt(width = dmaSegmentSizeBits))
|
||||||
val bytes_left = Reg(UInt(width = dmaSizeBits))
|
val bytes_left = Reg(UInt(width = dmaSegmentSizeBits))
|
||||||
val segments_left = Reg(UInt(width = dmaSegmentBits))
|
val segments_left = Reg(UInt(width = dmaSegmentBits))
|
||||||
|
val word_size = Reg(UInt(width = dmaWordSizeBits))
|
||||||
|
|
||||||
val src_vaddr = Reg(UInt(width = dmaAddrBits))
|
val src_vaddr = Reg(UInt(width = dmaAddrBits))
|
||||||
val dst_vaddr = Reg(UInt(width = dmaAddrBits))
|
val dst_vaddr = Reg(UInt(width = dmaAddrBits))
|
||||||
@ -97,8 +106,8 @@ class DmaFrontend(implicit val p: Parameters)
|
|||||||
val src_pglen = UInt(pgSize) - src_idx
|
val src_pglen = UInt(pgSize) - src_idx
|
||||||
val dst_pglen = UInt(pgSize) - dst_idx
|
val dst_pglen = UInt(pgSize) - dst_idx
|
||||||
|
|
||||||
val src_stride = Reg(UInt(width = dmaSizeBits))
|
val src_stride = Reg(UInt(width = dmaSegmentSizeBits))
|
||||||
val dst_stride = Reg(UInt(width = dmaSizeBits))
|
val dst_stride = Reg(UInt(width = dmaSegmentSizeBits))
|
||||||
|
|
||||||
val src_ppn = Reg(UInt(width = ppnBits))
|
val src_ppn = Reg(UInt(width = ppnBits))
|
||||||
val dst_ppn = Reg(UInt(width = ppnBits))
|
val dst_ppn = Reg(UInt(width = ppnBits))
|
||||||
@ -145,8 +154,7 @@ class DmaFrontend(implicit val p: Parameters)
|
|||||||
to_translate := to_translate & ~recv_choice
|
to_translate := to_translate & ~recv_choice
|
||||||
|
|
||||||
// getting the src translation
|
// getting the src translation
|
||||||
// if this is a prefetch, dst_ppn and src_ppn should be equal
|
when (recv_choice(0)) {
|
||||||
when (recv_choice(0) || cmd(1)) {
|
|
||||||
src_ppn := io.ptw.resp.bits.pte.ppn
|
src_ppn := io.ptw.resp.bits.pte.ppn
|
||||||
} .otherwise {
|
} .otherwise {
|
||||||
dst_ppn := io.ptw.resp.bits.pte.ppn
|
dst_ppn := io.ptw.resp.bits.pte.ppn
|
||||||
@ -162,11 +170,13 @@ class DmaFrontend(implicit val p: Parameters)
|
|||||||
cmd = cmd,
|
cmd = cmd,
|
||||||
source = src_paddr,
|
source = src_paddr,
|
||||||
dest = dst_paddr,
|
dest = dst_paddr,
|
||||||
length = tx_len)
|
length = tx_len,
|
||||||
|
size = word_size)
|
||||||
io.dma.resp.ready := Bool(true)
|
io.dma.resp.ready := Bool(true)
|
||||||
|
|
||||||
when (io.cpu.req.fire()) {
|
when (io.cpu.req.fire()) {
|
||||||
val req = io.cpu.req.bits
|
val req = io.cpu.req.bits
|
||||||
|
val is_prefetch = req.cmd(2, 1) === UInt("b01")
|
||||||
cmd := req.cmd
|
cmd := req.cmd
|
||||||
src_vaddr := req.src_start
|
src_vaddr := req.src_start
|
||||||
dst_vaddr := req.dst_start
|
dst_vaddr := req.dst_start
|
||||||
@ -175,7 +185,8 @@ class DmaFrontend(implicit val p: Parameters)
|
|||||||
segment_size := req.segment_size
|
segment_size := req.segment_size
|
||||||
segments_left := req.nsegments - UInt(1)
|
segments_left := req.nsegments - UInt(1)
|
||||||
bytes_left := req.segment_size
|
bytes_left := req.segment_size
|
||||||
to_translate := Mux(req.cmd(1), UInt("b10"), UInt("b11"))
|
word_size := req.word_size
|
||||||
|
to_translate := Mux(is_prefetch, UInt("b10"), UInt("b11"))
|
||||||
ptw_sent := UInt(0)
|
ptw_sent := UInt(0)
|
||||||
state := Mux(vm_enabled, s_translate, s_dma_req)
|
state := Mux(vm_enabled, s_translate, s_dma_req)
|
||||||
}
|
}
|
||||||
@ -184,16 +195,20 @@ class DmaFrontend(implicit val p: Parameters)
|
|||||||
state := s_dma_req
|
state := s_dma_req
|
||||||
}
|
}
|
||||||
|
|
||||||
when (io.dma.req.fire()) {
|
def setBusyOnSend(req: DecoupledIO[DmaRequest]): UInt =
|
||||||
src_vaddr := src_vaddr + tx_len
|
Mux(req.fire(), UIntToOH(req.bits.client_xact_id), UInt(0))
|
||||||
dst_vaddr := dst_vaddr + tx_len
|
|
||||||
bytes_left := bytes_left - tx_len
|
|
||||||
dma_busy := dma_busy | UIntToOH(dma_xact_id)
|
|
||||||
state := s_dma_update
|
|
||||||
}
|
|
||||||
|
|
||||||
when (io.dma.resp.fire()) {
|
def clearBusyOnRecv(resp: DecoupledIO[DmaResponse]): UInt =
|
||||||
dma_busy := dma_busy & ~UIntToOH(io.dma.resp.bits.client_xact_id)
|
~Mux(resp.fire(), UIntToOH(resp.bits.client_xact_id), UInt(0))
|
||||||
|
|
||||||
|
dma_busy := (dma_busy | setBusyOnSend(io.dma.req)) &
|
||||||
|
clearBusyOnRecv(io.dma.resp)
|
||||||
|
|
||||||
|
when (io.dma.req.fire()) {
|
||||||
|
src_vaddr := src_vaddr + Mux(adv_ptr(0), tx_len, UInt(0))
|
||||||
|
dst_vaddr := dst_vaddr + Mux(adv_ptr(1), tx_len, UInt(0))
|
||||||
|
bytes_left := bytes_left - tx_len
|
||||||
|
state := s_dma_update
|
||||||
}
|
}
|
||||||
|
|
||||||
when (state === s_dma_update) {
|
when (state === s_dma_update) {
|
||||||
@ -211,16 +226,16 @@ class DmaFrontend(implicit val p: Parameters)
|
|||||||
state := Mux(vm_enabled, s_prepare, s_dma_req)
|
state := Mux(vm_enabled, s_prepare, s_dma_req)
|
||||||
}
|
}
|
||||||
} .otherwise {
|
} .otherwise {
|
||||||
to_translate := Cat(dst_idx === UInt(0), !cmd(1) && src_idx === UInt(0))
|
to_translate := adv_ptr & Cat(dst_idx === UInt(0), src_idx === UInt(0))
|
||||||
ptw_sent := UInt(0)
|
ptw_sent := UInt(0)
|
||||||
state := s_translate
|
state := s_translate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when (state === s_prepare) {
|
when (state === s_prepare) {
|
||||||
to_translate := Cat(
|
to_translate := adv_ptr & Cat(
|
||||||
dst_vpn =/= last_dst_vpn,
|
dst_vpn =/= last_dst_vpn,
|
||||||
src_vpn =/= last_src_vpn && !cmd(1))
|
src_vpn =/= last_src_vpn)
|
||||||
ptw_sent := UInt(0)
|
ptw_sent := UInt(0)
|
||||||
state := s_translate
|
state := s_translate
|
||||||
}
|
}
|
||||||
@ -235,35 +250,38 @@ object DmaCtrlRegNumbers {
|
|||||||
val DST_STRIDE = 1
|
val DST_STRIDE = 1
|
||||||
val SEGMENT_SIZE = 2
|
val SEGMENT_SIZE = 2
|
||||||
val NSEGMENTS = 3
|
val NSEGMENTS = 3
|
||||||
val RESP_STATUS = 4
|
val WORD_SIZE = 4
|
||||||
|
val RESP_STATUS = 5
|
||||||
}
|
}
|
||||||
import DmaCtrlRegNumbers._
|
import DmaCtrlRegNumbers._
|
||||||
|
|
||||||
class DmaCtrlRegFile(implicit p: Parameters) extends ClientDmaModule()(p) {
|
class DmaCtrlRegFile(implicit p: Parameters) extends ClientDmaModule()(p) {
|
||||||
private val nWriteRegs = 4
|
private val nWriteRegs = 5
|
||||||
private val nReadRegs = 1
|
private val nReadRegs = 1
|
||||||
private val nRegs = nWriteRegs + nReadRegs
|
private val nRegs = nWriteRegs + nReadRegs
|
||||||
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val wen = Bool(INPUT)
|
val wen = Bool(INPUT)
|
||||||
val addr = UInt(INPUT, log2Up(nRegs))
|
val addr = UInt(INPUT, log2Up(nRegs))
|
||||||
val wdata = UInt(INPUT, dmaSizeBits)
|
val wdata = UInt(INPUT, dmaSegmentSizeBits)
|
||||||
val rdata = UInt(OUTPUT, dmaSizeBits)
|
val rdata = UInt(OUTPUT, dmaSegmentSizeBits)
|
||||||
|
|
||||||
val src_stride = UInt(OUTPUT, dmaSizeBits)
|
val src_stride = UInt(OUTPUT, dmaSegmentSizeBits)
|
||||||
val dst_stride = UInt(OUTPUT, dmaSizeBits)
|
val dst_stride = UInt(OUTPUT, dmaSegmentSizeBits)
|
||||||
val segment_size = UInt(OUTPUT, dmaSizeBits)
|
val segment_size = UInt(OUTPUT, dmaSegmentSizeBits)
|
||||||
val nsegments = UInt(OUTPUT, dmaSegmentBits)
|
val nsegments = UInt(OUTPUT, dmaSegmentBits)
|
||||||
|
val word_size = UInt(OUTPUT, dmaWordSizeBits)
|
||||||
|
|
||||||
val status = UInt(INPUT, dmaStatusBits)
|
val status = UInt(INPUT, dmaStatusBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
val regs = Reg(Vec(nWriteRegs, UInt(width = dmaSizeBits)))
|
val regs = Reg(Vec(nWriteRegs, UInt(width = dmaSegmentSizeBits)))
|
||||||
|
|
||||||
io.src_stride := regs(SRC_STRIDE)
|
io.src_stride := regs(SRC_STRIDE)
|
||||||
io.dst_stride := regs(DST_STRIDE)
|
io.dst_stride := regs(DST_STRIDE)
|
||||||
io.segment_size := regs(SEGMENT_SIZE)
|
io.segment_size := regs(SEGMENT_SIZE)
|
||||||
io.nsegments := regs(NSEGMENTS)
|
io.nsegments := regs(NSEGMENTS)
|
||||||
|
io.word_size := regs(WORD_SIZE)
|
||||||
|
|
||||||
when (io.wen && io.addr < UInt(nWriteRegs)) {
|
when (io.wen && io.addr < UInt(nWriteRegs)) {
|
||||||
regs.write(io.addr, io.wdata)
|
regs.write(io.addr, io.wdata)
|
||||||
@ -283,9 +301,9 @@ class DmaController(implicit p: Parameters) extends RoCC()(p)
|
|||||||
|
|
||||||
val cmd = Queue(io.cmd)
|
val cmd = Queue(io.cmd)
|
||||||
val inst = cmd.bits.inst
|
val inst = cmd.bits.inst
|
||||||
val is_transfer = inst.funct < UInt(4)
|
val is_transfer = inst.funct < UInt(8)
|
||||||
val is_cr_write = inst.funct === UInt(4)
|
val is_cr_write = inst.funct === UInt(8)
|
||||||
val is_cr_read = inst.funct === UInt(5)
|
val is_cr_read = inst.funct === UInt(9)
|
||||||
val is_cr_access = is_cr_write || is_cr_read
|
val is_cr_access = is_cr_write || is_cr_read
|
||||||
|
|
||||||
val resp_rd = Reg(io.resp.bits.rd)
|
val resp_rd = Reg(io.resp.bits.rd)
|
||||||
@ -311,7 +329,8 @@ class DmaController(implicit p: Parameters) extends RoCC()(p)
|
|||||||
src_stride = crfile.io.src_stride,
|
src_stride = crfile.io.src_stride,
|
||||||
dst_stride = crfile.io.dst_stride,
|
dst_stride = crfile.io.dst_stride,
|
||||||
segment_size = crfile.io.segment_size,
|
segment_size = crfile.io.segment_size,
|
||||||
nsegments = crfile.io.nsegments)
|
nsegments = crfile.io.nsegments,
|
||||||
|
word_size = crfile.io.word_size)
|
||||||
|
|
||||||
cmd.ready := state === s_idle && (!is_transfer || frontend.io.cpu.req.ready)
|
cmd.ready := state === s_idle && (!is_transfer || frontend.io.cpu.req.ready)
|
||||||
io.resp.valid := state === s_resp
|
io.resp.valid := state === s_resp
|
||||||
|
Loading…
Reference in New Issue
Block a user