169 lines
4.2 KiB
Scala
169 lines
4.2 KiB
Scala
// See LICENSE.SiFive for license details.
|
|
// See LICENSE.Berkeley for license details.
|
|
|
|
package groundtest
|
|
|
|
import Chisel._
|
|
|
|
// ============
|
|
// LCG16 module
|
|
// ============
|
|
|
|
// A 16-bit psuedo-random generator based on a linear conguential
|
|
// generator (LCG). The state is stored in an unitialised register.
|
|
// When using the C++ backend, it is straigtforward to arrange a
|
|
// random initial value for each uninitialised register, effectively
|
|
// seeding each LCG16 instance with a different seed.
|
|
|
|
class LCG16 extends Module {
|
|
val io = new Bundle {
|
|
val out = UInt(OUTPUT, 16)
|
|
val inc = Bool(INPUT)
|
|
}
|
|
val state = Reg(UInt(width = 32))
|
|
when (io.inc) {
|
|
state := state * UInt(1103515245, 32) + UInt(12345, 32)
|
|
}
|
|
io.out := state(30, 15)
|
|
}
|
|
|
|
// ==========
|
|
// LCG module
|
|
// ==========
|
|
|
|
// An n-bit psuedo-random generator made from many instances of a
|
|
// 16-bit LCG. Parameter 'width' must be larger than 0.
|
|
|
|
class LCG(val w: Int) extends Module {
|
|
val io = new Bundle {
|
|
val out = UInt(OUTPUT, w)
|
|
val inc = Bool(INPUT)
|
|
}
|
|
require(w > 0)
|
|
val numLCG16s : Int = (w+15)/16
|
|
val outs = Seq.fill(numLCG16s) { LCG16(io.inc) }
|
|
io.out := Cat(outs)
|
|
}
|
|
|
|
object LCG16 {
|
|
def apply(inc: Bool = Bool(true)): UInt = {
|
|
val lcg = Module(new LCG16)
|
|
lcg.io.inc := inc
|
|
lcg.io.out
|
|
}
|
|
}
|
|
|
|
object LCG {
|
|
def apply(w: Int, inc: Bool = Bool(true)): UInt = {
|
|
val lcg = Module(new LCG(w))
|
|
lcg.io.inc := inc
|
|
lcg.io.out
|
|
}
|
|
}
|
|
|
|
// ======================
|
|
// Frequency distribution
|
|
// ======================
|
|
|
|
// 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
|
|
}
|
|
}
|
|
|
|
object ValidMux {
|
|
def apply[T <: Data](v1: ValidIO[T], v2: ValidIO[T]*): ValidIO[T] = {
|
|
apply(v1 +: v2.toSeq)
|
|
}
|
|
def apply[T <: Data](valids: Seq[ValidIO[T]]): ValidIO[T] = {
|
|
val out = Wire(Valid(valids.head.bits))
|
|
out.valid := valids.map(_.valid).reduce(_ || _)
|
|
out.bits := MuxCase(valids.head.bits,
|
|
valids.map(v => (v.valid -> v.bits)))
|
|
out
|
|
}
|
|
}
|
|
|
|
object DebugCombiner {
|
|
def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = {
|
|
val out = Wire(new GroundTestStatus)
|
|
out.finished := debugs.map(_.finished).reduce(_ && _)
|
|
out.timeout := ValidMux(debugs.map(_.timeout))
|
|
out.error := ValidMux(debugs.map(_.error))
|
|
out
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Takes in data on one decoupled interface and broadcasts it to
|
|
* N decoupled output interfaces
|
|
*/
|
|
class Broadcaster[T <: Data](typ: T, n: Int) extends Module {
|
|
val io = new Bundle {
|
|
val in = Decoupled(typ).flip
|
|
val out = Vec(n, Decoupled(typ))
|
|
}
|
|
|
|
require (n > 0)
|
|
|
|
if (n == 1) {
|
|
io.out.head <> io.in
|
|
} else {
|
|
val idx = Reg(init = UInt(0, log2Up(n)))
|
|
val save = Reg(typ)
|
|
|
|
io.out.head.valid := idx === UInt(0) && io.in.valid
|
|
io.out.head.bits := io.in.bits
|
|
for (i <- 1 until n) {
|
|
io.out(i).valid := idx === UInt(i)
|
|
io.out(i).bits := save
|
|
}
|
|
io.in.ready := io.out.head.ready && idx === UInt(0)
|
|
|
|
when (io.in.fire()) { save := io.in.bits }
|
|
|
|
when (io.out(idx).fire()) {
|
|
when (idx === UInt(n - 1)) { idx := UInt(0) }
|
|
.otherwise { idx := idx + UInt(1) }
|
|
}
|
|
}
|
|
}
|
|
|
|
object Broadcaster {
|
|
def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = {
|
|
val split = Module(new Broadcaster(in.bits, n))
|
|
split.io.in <> in
|
|
split.io.out
|
|
}
|
|
}
|