All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spinal.lib.bus.tilelink.coherent.Misc.scala Maven / Gradle / Ivy

package spinal.lib.bus.tilelink.coherent

import spinal.core._
import spinal.lib._
import spinal.lib.bus.tilelink._
import spinal.lib.pipeline._


case class DataPayload(bytes : Int) extends Bundle {
  val mask = Bits(bytes bits)
  val data = Bits(bytes*8 bits)
}

class ChannelDataBuffer(entries: Int,
                        blockSize: Int,
                        dataBytes : Int) extends Area {
  val ram = Mem.fill(entries * blockSize / dataBytes)(DataPayload(dataBytes))
  val allocated = Reg(Bits(entries bits)) init (0)
  val set, clear = B(0, entries bits)
  val firstFree = OHToUInt(OHMasking.firstV2(~allocated))
  val full = allocated.andR
  val write = ram.writePort()
  allocated := (allocated | set) & ~clear

  def push(stage : Stage,
           CMD : Stageable[ChannelA],
           PAYLOAD : Stageable[DataPayload],
           LAST : Stageable[Bool]) = new Area {
    import stage._
    val withBeats = CMD.withBeats
    val hazard = withBeats && full
    haltIt(hazard)
    throwIt(!hazard && !LAST)


    for (i <- log2Up(dataBytes) until log2Up(blockSize)) CMD.addressNull(i) clearWhen (i < CMD.size)

    val locked = RegInit(False) setWhen (write.valid)
    val lockedValue = RegNextWhen(firstFree, !locked)
    val BUFFER_ID = insert(locked ? lockedValue | firstFree)
    write.valid := valid && withBeats && !hazard
    write.address := BUFFER_ID @@ CMD.address(log2Up(blockSize)-1 downto log2Up(dataBytes))
    write.data := PAYLOAD
    when(isFireing && LAST && withBeats) {
      set(BUFFER_ID) := True
      locked := False
    }
  }

  def push[T <: BusFragment](up : Stream[T]) = new Area {
    val withBeats = up.withBeats
    val hazard = withBeats && full
    val dataLess = up.translateWith(up.asNoData())
    val filtred = dataLess.throwWhen(!hazard && !up.isLast())
    val down = filtred.haltWhen(hazard)
    val locked = RegInit(False) setWhen (write.valid)
    val lockedValue = RegNextWhen(firstFree, !locked)
    val bufferId = locked ? lockedValue | firstFree

    for(i <- log2Up(dataBytes) until log2Up(blockSize)) down.addressNull(i) clearWhen(i < down.size)

    write.valid := up.valid && withBeats && !hazard
    write.address := bufferId @@ up.addressNull(log2Up(blockSize) - 1 downto log2Up(dataBytes))
    write.data.mask := up.maskNull
    write.data.data := up.data
    when(down.fire && up.isLast() && withBeats) {
      set(bufferId) := True
      locked := False
    }
  }
}






© 2015 - 2025 Weber Informatics LLC | Privacy Policy