Что означает, что «Q должен быть готов быстрее, чем ответ» для утверждения Янкера пользователя AXI4?
Я пытаюсь выполнить DMA, в котором мастер AXI получает выборку из подчиненного устройства AXI. Для простоты я решил подключить эту систему через переднюю шину TL и системную шину, а не напрямую друг с другом, поскольку другим мастерам может потребоваться доступ к ведомому устройству AXI. Я использую порт MMIO по умолчанию для Rocket Chip. Я вызвал его с помощью следующих MasterPortParams.
class WithMMIOPort extends Config((site, here, up) => {
case ExtBus => Some(MasterPortParams(
base = x"4000_0000",
size = x"2000_0000",
beatBytes = site(MemoryBusKey).beatBytes,
idBits = 4))
})
Вот порт MMIO для справки.
trait CanHaveMasterAXI4MMIOPort { this: BaseSubsystem =>
private val mmioPortParamsOpt = p(ExtBus)
private val portName = "mmio_port_axi4"
private val device = new SimpleBus(portName.kebab, Nil)
val mmioAXI4Node = AXI4SlaveNode(
mmioPortParamsOpt.map(params =>
AXI4SlavePortParameters(
slaves = Seq(AXI4SlaveParameters(
address = AddressSet.misaligned(params.base, params.size),
resources = device.ranges,
executable = params.executable,
supportsWrite = TransferSizes(1, params.maxXferBytes),
supportsRead = TransferSizes(1, params.maxXferBytes))),
beatBytes = params.beatBytes)).toSeq)
mmioPortParamsOpt.map { params =>
sbus.coupleTo(s"port_named_$portName") {
(mmioAXI4Node
:= AXI4Buffer()
:= AXI4UserYanker()
:= AXI4Deinterleaver(sbus.blockBytes)
:= AXI4IdIndexer(params.idBits)
:= TLToAXI4()
:= TLWidthWidget(sbus.beatBytes)
:= _)
}
}
А вот главный узел, который пытается выполнить запись.
(dmaHstNode
:= TLBuffer(BufferParams.default)
// := TLFIFOFixer(TLFIFOFixer.all)
:= TLWidthWidget(8)
:= AXI4ToTL()
:= AXI4UserYanker(capMaxFlight=Some(16))
:= AXI4Fragmenter()
:= AXI4IdIndexer(idBits=3)
:= AXI4Buffer()
:= dmaTop.hstMaster)
// }
Он начинает выдавать запись, но затем я сталкиваюсь с ошибкой утверждения
assert (!out.b.valid || b_valid) // Q must be ready faster than the response
Я пытаюсь понять, о чем говорит это утверждение. Это исходит от UserYanker. Вот это в контексте
val bid = out.b.bits.id
val b_valid = Vec(wqueues.map(_.deq.valid))(bid)
val b_bits = Vec(wqueues.map(_.deq.bits))(bid)
assert (!out.b.valid || b_valid) // Q must be ready faster than the response
in.b :<> out.b
in.b.bits.echo :<= b_bits
B_bits извлекаются из очереди, и перед установкой битов канала in b мы проверяем это утверждение. Я до сих пор не совсем понимаю, что это значит. Мое лучшее предположение: b.valid становится высоким до того, как у UserYanker появится место в очереди? Означает ли это, что мне нужны очереди большего размера? Если это так, какой параметр увеличит размер очереди UserYanker? Будет ли это maxFlight? Это какая-то проблема с трансляцией протокола с Tilelink на axi4? Я не знаком с их спецификой, но, может быть, в этом случае следует пропустить преобразование в Tilelink?