spinal.lib.bus.bmb.BmbInvalidateMonitor.scala Maven / Gradle / Ivy
package spinal.lib.bus.bmb
import spinal.core._
import spinal.lib._
object BmbInvalidateMonitor{
def outputAccessParameter(inputParameter : BmbAccessParameter) = inputParameter.sourcesTransform(s => s.copy(
contextWidth = 1 + inputParameter.contextWidth + inputParameter.addressWidth + s.lengthWidth,
canInvalidate = false,
canSync = false
))
def outputInvalidationParameter() = BmbInvalidationParameter()
}
case class BmbInvalidateMonitor(inputParameter : BmbParameter,
pendingInvMax : Int) extends Component{
val outputParameter = BmbInvalidateMonitor.outputAccessParameter(inputParameter.access)
val io = new Bundle {
val input = slave(Bmb(inputParameter))
val output = master(Bmb(outputParameter))
}
case class Context() extends Bundle{
val context = Bits(inputParameter.access.contextWidth bits)
val address = UInt(inputParameter.access.addressWidth bits)
val length = UInt(inputParameter.access.lengthWidth bits)
val write = Bool()
}
val cmdLogic = new Area {
val cmdContext = Context()
cmdContext.context := io.input.cmd.context
cmdContext.write := io.input.cmd.isWrite
cmdContext.address := io.input.cmd.address
cmdContext.length := io.input.cmd.length
io.output.cmd << io.input.cmd
io.output.cmd.context.removeAssignments().assignFromBits(B(cmdContext))
}
val rspLogic = new Area {
val rspContext = io.output.rsp.context.as(Context())
val (rspToRsp, rspToInv, rspToSync) = StreamFork3(io.output.rsp)
io.input.rsp << rspToRsp
io.input.rsp.context.removeAssignments() := rspContext.context
val rspToInvFiltred = rspToInv.takeWhen(rspContext.write)
io.input.inv.arbitrationFrom(rspToInvFiltred)
io.input.inv.address := rspContext.address
io.input.inv.length := rspContext.length
io.input.inv.source := rspToInvFiltred.source
io.input.inv.all := False
val rspToSyncFiltred = rspToSync.translateWith(rspToInv.source).takeWhen(rspContext.write)
}
val ackLogic = new Area{
val syncSource = rspLogic.rspToSyncFiltred.s2mPipe().queue(pendingInvMax)
syncSource.ready := io.input.ack.fire
io.input.sync.arbitrationFrom(io.input.ack)
io.input.sync.source := syncSource.payload
}
}