Для этого примера, важно иметь в виду разницу между зубила и Scala. Более конкретно, when
представляет собой конструкцию долота, которая сопоставляется с условными соединениями в Verilog, тогда как for
является конструкцией Scala, которую мы можем использовать для создания аппаратного обеспечения (аналогично generate
в Verilog).
Давайте раскатать этот цикл и посмотрим, что мы получаем:
when(io.bits_perf.valid){
when(io.bits_perf.bits(0)) { hit_bits := hit_bits + Bits(1) }
when(io.bits_perf.bits(1)) { hit_bits := hit_bits + Bits(1) }
when(io.bits_perf.bits(2)) { hit_bits := hit_bits + Bits(1) }
}
Обратите внимание, что все соединения являются такими же, когда io.bits_perf.valid
высока, и любой из битов в io.bits_perf.bits
высока, вы будете подключать hit_bits
- hit_bits + Bits(1)
. Это комбинационный цикл.
Теперь давайте выясним, как выразить то, что вы действительно пытаетесь сделать: как подключить hit_bits к числу единиц в io.bits_perf.bits
, когда io.bits_perf.valid
является высоким. Это также известно как popcount, для которого у долота просто так есть утилита. То, что вы должны сделать, это использовать, что:
val hit_bits = Bits()
hit_bits := Bits(0)
when(io.bits_perf.valid) {
hit_bits := PopCount(io.bits_perf.bits)
}
Однако код, который вы написали близко к правильному, так давайте сделаем это работать в любом случае. Мы хотим использовать цикл Scala для создания кода. Один из способов сделать это - использовать Scala var (который позволяет переназначить) как своего рода «указатель» на узлы долота, а не val, который допускает только одно назначение (и, следовательно, его нельзя изменить, чтобы указать на другой узел долота).
var hit_bits = Bits(0, 2) // We set the width because + does not expand width
when (io.bits_perf.valid) {
for (i <- 0 until 3) {
hit_bits = hit_bits + io.bits_perf.bits(i)
}
}
// Now hit_bits is equal to the popcount of io.bits_perf.bits (or 0 if not valid)
Обратите внимание, что я упал внутренний, когда условно, так как вы можете просто добавить немного напрямую, а не условно добавления 1. То, что происходит здесь в том, что hit_bits
является ссылкой на Зубило узлы, начиная с 0
. Затем для каждого индекса в цикле for мы меняем узел. Hit_bits означает узел Chizel, который является результатом добавления предыдущего узла hit_bits и бит io.bits_perf.bits
.