44 lines
1.1 KiB
Scala
44 lines
1.1 KiB
Scala
|
// See LICENSE.SiFive for license details.
|
||
|
// See LICENSE.Berkeley for license details.
|
||
|
|
||
|
package freechips.rocketchip.util
|
||
|
|
||
|
import Chisel._
|
||
|
|
||
|
/** Given a list of (frequency, value) pairs, return a random value
|
||
|
* according to the frequency distribution. The sum of the
|
||
|
* frequencies in the distribution must be a power of two.
|
||
|
*/
|
||
|
object Frequency {
|
||
|
def apply(dist : List[(Int, Bits)]) : Bits = {
|
||
|
// Distribution must be non-empty
|
||
|
require(dist.length > 0)
|
||
|
|
||
|
// Require that the frequencies sum to a power of two
|
||
|
val (freqs, vals) = dist.unzip
|
||
|
val total = freqs.sum
|
||
|
require(isPow2(total))
|
||
|
|
||
|
// First item in the distribution
|
||
|
val (firstFreq, firstVal) = dist.head
|
||
|
|
||
|
// Result wire
|
||
|
val result = Wire(Bits(width = firstVal.getWidth))
|
||
|
result := UInt(0)
|
||
|
|
||
|
// Random value
|
||
|
val randVal = LCG(log2Up(total))
|
||
|
|
||
|
// Pick return value
|
||
|
var count = firstFreq
|
||
|
var select = when (randVal < UInt(firstFreq)) { result := firstVal }
|
||
|
for (p <- dist.drop(1)) {
|
||
|
count = count + p._1
|
||
|
select = select.elsewhen(randVal < UInt(count)) { result := p._2 }
|
||
|
}
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
}
|
||
|
|