1
0

Refactor package hierarchy and remove legacy bus protocol implementations (#845)

* Refactors package hierarchy.

Additionally:
  - Removes legacy ground tests and configs
  - Removes legacy bus protocol implementations
  - Removes NTiles
  - Adds devices package
  - Adds more functions to util package
This commit is contained in:
Henry Cook
2017-07-07 10:48:16 -07:00
committed by GitHub
parent c28c23150d
commit 4c595d175c
238 changed files with 1347 additions and 10978 deletions

View File

@ -1,8 +1,9 @@
// See LICENSE.Berkeley for license details.
package util
package freechips.rocketchip.util
import Chisel._
import config._
import freechips.rocketchip.config.Parameters
/** A generalized locking RR arbiter that addresses the limitations of the
* version in the Chisel standard library */
@ -93,3 +94,52 @@ class HellaCountingArbiter[T <: Data](
}
}
}
/** This arbiter preserves the order of responses */
class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int)
(implicit p: Parameters) extends Module {
val io = new Bundle {
val in_req = Vec(n, Decoupled(reqTyp)).flip
val in_resp = Vec(n, Decoupled(respTyp))
val out_req = Decoupled(reqTyp)
val out_resp = Decoupled(respTyp).flip
}
if (n > 1) {
val route_q = Module(new Queue(UInt(width = log2Up(n)), 2))
val req_arb = Module(new RRArbiter(reqTyp, n))
req_arb.io.in <> io.in_req
val req_helper = DecoupledHelper(
req_arb.io.out.valid,
route_q.io.enq.ready,
io.out_req.ready)
io.out_req.bits := req_arb.io.out.bits
io.out_req.valid := req_helper.fire(io.out_req.ready)
route_q.io.enq.bits := req_arb.io.chosen
route_q.io.enq.valid := req_helper.fire(route_q.io.enq.ready)
req_arb.io.out.ready := req_helper.fire(req_arb.io.out.valid)
val resp_sel = route_q.io.deq.bits
val resp_ready = io.in_resp(resp_sel).ready
val resp_helper = DecoupledHelper(
resp_ready,
route_q.io.deq.valid,
io.out_resp.valid)
val resp_valid = resp_helper.fire(resp_ready)
for (i <- 0 until n) {
io.in_resp(i).bits := io.out_resp.bits
io.in_resp(i).valid := resp_valid && resp_sel === UInt(i)
}
route_q.io.deq.ready := resp_helper.fire(route_q.io.deq.valid)
io.out_resp.ready := resp_helper.fire(io.out_resp.valid)
} else {
io.out_req <> io.in_req.head
io.in_resp.head <> io.out_resp
}
}

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
import chisel3.util.{ReadyValidIO}

View File

@ -1,6 +1,7 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
object GrayCounter {

View File

@ -1,11 +1,9 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
import config._
/** This black-boxes an Async Reset
* (or Set)
* Register.

View File

@ -0,0 +1,48 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package freechips.rocketchip.util
import Chisel._
/** 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
}
}

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,6 +1,6 @@
// See LICENSE.Berkeley for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,10 +1,9 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
import config._
import scala.math.max
// Produces 0-width value when counting to 1

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
import chisel3.util.{DecoupledIO, Decoupled, Irrevocable, IrrevocableIO, ReadyValidIO}

View File

@ -0,0 +1,160 @@
// See LICENSE.Berkeley for license details.
package freechips.rocketchip.util
import Chisel._
abstract class Decoding
{
def uncorrected: UInt
def corrected: UInt
def correctable: Bool
def uncorrectable: Bool // If true, correctable should be ignored
def error = correctable || uncorrectable
}
abstract class Code
{
def width(w0: Int): Int
def encode(x: UInt): UInt
def decode(x: UInt): Decoding
/** Copy the bits in x to the right bit positions in an encoded word,
* so that x === decode(swizzle(x)).uncorrected; but don't generate
* the other code bits, so decode(swizzle(x)).error might be true.
* For codes for which this operation is not trivial, throw an
* UnsupportedOperationException. */
def swizzle(x: UInt): UInt
}
class IdentityCode extends Code
{
def width(w0: Int) = w0
def encode(x: UInt) = x
def swizzle(x: UInt) = x
def decode(y: UInt) = new Decoding {
def uncorrected = y
def corrected = y
def correctable = Bool(false)
def uncorrectable = Bool(false)
}
}
class ParityCode extends Code
{
def width(w0: Int) = w0+1
def encode(x: UInt) = Cat(x.xorR, x)
def swizzle(x: UInt) = Cat(false.B, x)
def decode(y: UInt) = new Decoding {
val uncorrected = y(y.getWidth-2,0)
val corrected = uncorrected
val correctable = Bool(false)
val uncorrectable = y.xorR
}
}
class SECCode extends Code
{
def width(k: Int) = {
val m = log2Floor(k) + 1
k + m + (if((1 << m) < m+k+1) 1 else 0)
}
def encode(x: UInt) = {
val k = x.getWidth
require(k > 0)
val n = width(k)
val y = for (i <- 1 to n) yield {
if (isPow2(i)) {
val r = for (j <- 1 to n; if j != i && (j & i) != 0)
yield x(mapping(j))
r reduce (_^_)
} else
x(mapping(i))
}
y.asUInt
}
def swizzle(x: UInt) = {
val y = for (i <- 1 to width(x.getWidth))
yield (if (isPow2(i)) false.B else x(mapping(i)))
y.asUInt
}
def decode(y: UInt) = new Decoding {
val n = y.getWidth
require(n > 0 && !isPow2(n))
val p2 = for (i <- 0 until log2Up(n)) yield 1 << i
val syndrome = (p2 map { i =>
val r = for (j <- 1 to n; if (j & i) != 0)
yield y(j-1)
r reduce (_^_)
}).asUInt
private def swizzle(z: UInt) = (1 to n).filter(i => !isPow2(i)).map(i => z(i-1)).asUInt
val uncorrected = swizzle(y)
val corrected = swizzle(((y << 1) ^ UIntToOH(syndrome)) >> 1)
val correctable = syndrome.orR
val uncorrectable = syndrome > UInt(n)
}
private def mapping(i: Int) = i-1-log2Up(i)
}
class SECDEDCode extends Code
{
private val sec = new SECCode
private val par = new ParityCode
def width(k: Int) = sec.width(k)+1
def encode(x: UInt) = par.encode(sec.encode(x))
def swizzle(x: UInt) = par.swizzle(sec.swizzle(x))
def decode(x: UInt) = new Decoding {
val secdec = sec.decode(x(x.getWidth-2,0))
val pardec = par.decode(x)
val uncorrected = secdec.uncorrected
val corrected = secdec.corrected
val correctable = pardec.uncorrectable
val uncorrectable = !pardec.uncorrectable && secdec.correctable
}
}
object ErrGen
{
// generate a 1-bit error with approximate probability 2^-f
def apply(width: Int, f: Int): UInt = {
require(width > 0 && f >= 0 && log2Up(width) + f <= 16)
UIntToOH(LFSR16()(log2Up(width)+f-1,0))(width-1,0)
}
def apply(x: UInt, f: Int): UInt = x ^ apply(x.getWidth, f)
}
class SECDEDTest extends Module
{
val code = new SECDEDCode
val k = 4
val n = code.width(k)
val io = new Bundle {
val original = Bits(OUTPUT, k)
val encoded = Bits(OUTPUT, n)
val injected = Bits(OUTPUT, n)
val uncorrected = Bits(OUTPUT, k)
val corrected = Bits(OUTPUT, k)
val correctable = Bool(OUTPUT)
val uncorrectable = Bool(OUTPUT)
}
val c = Counter(Bool(true), 1 << k)
val numErrors = Counter(c._2, 3)._1
val e = code.encode(c._1)
val i = e ^ Mux(numErrors < UInt(1), UInt(0), ErrGen(n, 1)) ^ Mux(numErrors < UInt(2), UInt(0), ErrGen(n, 1))
val d = code.decode(i)
io.original := c._1
io.encoded := e
io.injected := i
io.uncorrected := d.uncorrected
io.corrected := d.corrected
io.correctable := d.correctable
io.uncorrectable := d.uncorrectable
}

View File

@ -0,0 +1,43 @@
// 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
}
}

View File

@ -1,11 +1,14 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
import chisel3.internal.firrtl.Circuit
import chisel3.experimental.{RawModule}
import config._
import diplomacy.LazyModule
// TODO: better job of Makefrag generation for non-RocketChip testing platforms
import freechips.rocketchip.chip.{TestGeneration, DefaultTestSuites}
import freechips.rocketchip.config._
import freechips.rocketchip.diplomacy.LazyModule
import java.io.{File, FileWriter}
/** Representation of the information this Generator needs to collect from external sources. */
@ -40,7 +43,6 @@ trait HasGeneratorUtilities {
def getParameters(config: Config): Parameters = Parameters.root(config.toInstance)
import chisel3.internal.firrtl.Circuit
def elaborate(names: ParsedInputNames, params: Parameters): Circuit = {
val gen = () =>
Class.forName(names.fullTopModuleClass)
@ -92,13 +94,10 @@ trait GeneratorApp extends App with HasGeneratorUtilities {
/** Output software test Makefrags, which provide targets for integration testing. */
def generateTestSuiteMakefrags {
addTestSuites
writeOutputFile(td, s"$longName.d", rocketchip.TestGeneration.generateMakefrag) // Coreplex-specific test suites
writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites
}
def addTestSuites {
// TODO: better job of Makefrag generation
// for non-RocketChip testing platforms
import rocketchip.{DefaultTestSuites, TestGeneration}
TestGeneration.addSuite(DefaultTestSuites.groundtest64("p"))
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
TestGeneration.addSuite(DefaultTestSuites.singleRegression)

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,9 +1,8 @@
// See LICENSE.Berkeley for license details.
package util
package freechips.rocketchip.util
import Chisel._
import config._
class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module {
val io = new QueueIO(data, entries)

View File

@ -1,4 +1,6 @@
package util
// See LICENSE.SiFive for license details.
package freechips.rocketchip.util
import Chisel._
import chisel3.core.Record

View File

@ -0,0 +1,55 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package freechips.rocketchip.util
import Chisel._
/** 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)
}
/** 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
}
}

View File

@ -1,6 +1,6 @@
// See LICENSE.Berkeley for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,10 +1,10 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
import config._
import freechips.rocketchip.config.Parameters
import scala.math._
class ParameterizedBundle(implicit p: Parameters) extends Bundle {
@ -59,6 +59,19 @@ object MuxTLookup {
}
}
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 Str
{
def apply(s: String): UInt = {
@ -172,3 +185,53 @@ object Majority {
def apply(in: UInt): Bool = apply(in.toBools.toSet)
}
object PopCountAtLeast {
private def two(x: UInt): (Bool, Bool) = x.getWidth match {
case 1 => (x.toBool, Bool(false))
case n =>
val half = x.getWidth / 2
val (leftOne, leftTwo) = two(x(half - 1, 0))
val (rightOne, rightTwo) = two(x(x.getWidth - 1, half))
(leftOne || rightOne, leftTwo || rightTwo || (leftOne && rightOne))
}
def apply(x: UInt, n: Int): Bool = n match {
case 0 => Bool(true)
case 1 => x.orR
case 2 => two(x)._2
case 3 => PopCount(x) >= UInt(n)
}
}
// This gets used everywhere, so make the smallest circuit possible ...
// Given an address and size, create a mask of beatBytes size
// eg: (0x3, 0, 4) => 0001, (0x3, 1, 4) => 0011, (0x3, 2, 4) => 1111
// groupBy applies an interleaved OR reduction; groupBy=2 take 0010 => 01
object MaskGen {
def apply(addr_lo: UInt, lgSize: UInt, beatBytes: Int, groupBy: Int = 1): UInt = {
require (groupBy >= 1 && beatBytes >= groupBy)
require (isPow2(beatBytes) && isPow2(groupBy))
val lgBytes = log2Ceil(beatBytes)
val sizeOH = UIntToOH(lgSize, log2Up(beatBytes)) | UInt(groupBy*2 - 1)
def helper(i: Int): Seq[(Bool, Bool)] = {
if (i == 0) {
Seq((lgSize >= UInt(lgBytes), Bool(true)))
} else {
val sub = helper(i-1)
val size = sizeOH(lgBytes - i)
val bit = addr_lo(lgBytes - i)
val nbit = !bit
Seq.tabulate (1 << i) { j =>
val (sub_acc, sub_eq) = sub(j/2)
val eq = sub_eq && (if (j % 2 == 1) bit else nbit)
val acc = sub_acc || (size && eq)
(acc, eq)
}
}
}
if (groupBy == beatBytes) UInt(1) else
Cat(helper(lgBytes-log2Ceil(groupBy)).map(_._1).reverse)
}
}

View File

@ -0,0 +1,160 @@
// See LICENSE.Berkeley for license details.
package freechips.rocketchip.util
import Chisel._
import freechips.rocketchip.unittest.UnitTest
class MultiWidthFifo(inW: Int, outW: Int, n: Int) extends Module {
val io = new Bundle {
val in = Decoupled(Bits(width = inW)).flip
val out = Decoupled(Bits(width = outW))
val count = UInt(OUTPUT, log2Up(n + 1))
}
if (inW == outW) {
val q = Module(new Queue(Bits(width = inW), n))
q.io.enq <> io.in
io.out <> q.io.deq
io.count := q.io.count
} else if (inW > outW) {
val nBeats = inW / outW
require(inW % outW == 0, s"MultiWidthFifo: in: $inW not divisible by out: $outW")
require(n % nBeats == 0, s"Cannot store $n output words when output beats is $nBeats")
val wdata = Reg(Vec(n / nBeats, Bits(width = inW)))
val rdata = Vec(wdata.flatMap { indat =>
(0 until nBeats).map(i => indat(outW * (i + 1) - 1, outW * i)) })
val head = Reg(init = UInt(0, log2Up(n / nBeats)))
val tail = Reg(init = UInt(0, log2Up(n)))
val size = Reg(init = UInt(0, log2Up(n + 1)))
when (io.in.fire()) {
wdata(head) := io.in.bits
head := head + UInt(1)
}
when (io.out.fire()) { tail := tail + UInt(1) }
size := MuxCase(size, Seq(
(io.in.fire() && io.out.fire()) -> (size + UInt(nBeats - 1)),
io.in.fire() -> (size + UInt(nBeats)),
io.out.fire() -> (size - UInt(1))))
io.out.valid := size > UInt(0)
io.out.bits := rdata(tail)
io.in.ready := size < UInt(n)
io.count := size
} else {
val nBeats = outW / inW
require(outW % inW == 0, s"MultiWidthFifo: out: $outW not divisible by in: $inW")
val wdata = Reg(Vec(n * nBeats, Bits(width = inW)))
val rdata = Vec.tabulate(n) { i =>
Cat(wdata.slice(i * nBeats, (i + 1) * nBeats).reverse)}
val head = Reg(init = UInt(0, log2Up(n * nBeats)))
val tail = Reg(init = UInt(0, log2Up(n)))
val size = Reg(init = UInt(0, log2Up(n * nBeats + 1)))
when (io.in.fire()) {
wdata(head) := io.in.bits
head := head + UInt(1)
}
when (io.out.fire()) { tail := tail + UInt(1) }
size := MuxCase(size, Seq(
(io.in.fire() && io.out.fire()) -> (size - UInt(nBeats - 1)),
io.in.fire() -> (size + UInt(1)),
io.out.fire() -> (size - UInt(nBeats))))
io.count := size >> UInt(log2Up(nBeats))
io.out.valid := io.count > UInt(0)
io.out.bits := rdata(tail)
io.in.ready := size < UInt(n * nBeats)
}
}
class MultiWidthFifoTest extends UnitTest {
val big2little = Module(new MultiWidthFifo(16, 8, 8))
val little2big = Module(new MultiWidthFifo(8, 16, 4))
val bl_send = Reg(init = Bool(false))
val lb_send = Reg(init = Bool(false))
val bl_recv = Reg(init = Bool(false))
val lb_recv = Reg(init = Bool(false))
val bl_finished = Reg(init = Bool(false))
val lb_finished = Reg(init = Bool(false))
val bl_data = Vec.tabulate(4){i => UInt((2 * i + 1) * 256 + 2 * i, 16)}
val lb_data = Vec.tabulate(8){i => UInt(i, 8)}
val (bl_send_cnt, bl_send_done) = Counter(big2little.io.in.fire(), 4)
val (lb_send_cnt, lb_send_done) = Counter(little2big.io.in.fire(), 8)
val (bl_recv_cnt, bl_recv_done) = Counter(big2little.io.out.fire(), 8)
val (lb_recv_cnt, lb_recv_done) = Counter(little2big.io.out.fire(), 4)
big2little.io.in.valid := bl_send
big2little.io.in.bits := bl_data(bl_send_cnt)
big2little.io.out.ready := bl_recv
little2big.io.in.valid := lb_send
little2big.io.in.bits := lb_data(lb_send_cnt)
little2big.io.out.ready := lb_recv
val bl_recv_data_idx = bl_recv_cnt >> UInt(1)
val bl_recv_data = Mux(bl_recv_cnt(0),
bl_data(bl_recv_data_idx)(15, 8),
bl_data(bl_recv_data_idx)(7, 0))
val lb_recv_data = Cat(
lb_data(Cat(lb_recv_cnt, UInt(1, 1))),
lb_data(Cat(lb_recv_cnt, UInt(0, 1))))
when (io.start) {
bl_send := Bool(true)
lb_send := Bool(true)
}
when (bl_send_done) {
bl_send := Bool(false)
bl_recv := Bool(true)
}
when (lb_send_done) {
lb_send := Bool(false)
lb_recv := Bool(true)
}
when (bl_recv_done) {
bl_recv := Bool(false)
bl_finished := Bool(true)
}
when (lb_recv_done) {
lb_recv := Bool(false)
lb_finished := Bool(true)
}
io.finished := bl_finished && lb_finished
val bl_start_recv = Reg(next = bl_send_done)
val lb_start_recv = Reg(next = lb_send_done)
assert(!little2big.io.out.valid || little2big.io.out.bits === lb_recv_data,
"Little to Big data mismatch")
assert(!big2little.io.out.valid || big2little.io.out.bits === bl_recv_data,
"Bit to Little data mismatch")
assert(!lb_start_recv || little2big.io.count === UInt(4),
"Little to Big count incorrect")
assert(!bl_start_recv || big2little.io.count === UInt(8),
"Big to Little count incorrect")
}

View File

@ -1,6 +1,7 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
class plusarg_reader(val format: String, val default: Int, val docstring: String) extends BlackBox(Map(

View File

@ -1,6 +1,7 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
case class PositionalMultiQueueParameters[T <: Data](gen: T, positions: Int, ways: Int)

View File

@ -1,12 +1,13 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip.util
import Chisel._
// If you know two clocks are related with an N:M relationship, you
// can cross the clock domains with lower latency than an AsyncQueue.
// This crossing adds 1 cycle in the target clock domain.
package util
import Chisel._
// A rational crossing must put registers on the slow side.
// This trait covers the options of how/where to put the registers.
// BEWARE: the source+sink must agree on the direction!

View File

@ -1,6 +1,7 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._
object ReduceOthers {

View File

@ -1,10 +1,9 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package util
package freechips.rocketchip.util
import Chisel._
import config._
class ReorderQueueWrite[T <: Data](dType: T, tagWidth: Int) extends Bundle {
val data = dType.cloneType

View File

@ -0,0 +1,39 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip.util
import Chisel._
// A Repeater passes it's input to it's output, unless repeat is asserted.
// When repeat is asserted, the Repeater copies the input and repeats it next cycle.
class Repeater[T <: Data](gen: T) extends Module
{
val io = new Bundle {
val repeat = Bool(INPUT)
val full = Bool(OUTPUT)
val enq = Decoupled(gen).flip
val deq = Decoupled(gen)
}
val full = RegInit(Bool(false))
val saved = Reg(gen)
// When !full, a repeater is pass-through
io.deq.valid := io.enq.valid || full
io.enq.ready := io.deq.ready && !full
io.deq.bits := Mux(full, saved, io.enq.bits)
io.full := full
when (io.enq.fire() && io.repeat) { full := Bool(true); saved := io.enq.bits }
when (io.deq.fire() && !io.repeat) { full := Bool(false) }
}
object Repeater
{
def apply[T <: Data](enq: DecoupledIO[T], repeat: Bool): DecoupledIO[T] = {
val repeater = Module(new Repeater(enq.bits))
repeater.io.repeat := repeat
repeater.io.enq := enq
repeater.io.deq
}
}

View File

@ -1,7 +1,7 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,5 +1,6 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,6 +1,6 @@
// See LICENSE.SiFive for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,7 +1,7 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package util
package freechips.rocketchip.util
import Chisel._

View File

@ -1,6 +1,9 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip
import Chisel._
import scala.math.min
package object util {
implicit class UIntIsOneOf(val x: UInt) extends AnyVal {
@ -70,20 +73,27 @@ package object util {
def option[T](z: => T): Option[T] = if (x) Some(z) else None
}
object PopCountAtLeast {
private def two(x: UInt): (Bool, Bool) = x.getWidth match {
case 1 => (x.toBool, Bool(false))
case n =>
val half = x.getWidth / 2
val (leftOne, leftTwo) = two(x(half - 1, 0))
val (rightOne, rightTwo) = two(x(x.getWidth - 1, half))
(leftOne || rightOne, leftTwo || rightTwo || (leftOne && rightOne))
}
def apply(x: UInt, n: Int): Bool = n match {
case 0 => Bool(true)
case 1 => x.orR
case 2 => two(x)._2
case 3 => PopCount(x) >= UInt(n)
}
def OH1ToOH(x: UInt): UInt = (x << 1 | UInt(1)) & ~Cat(UInt(0, width=1), x)
def OH1ToUInt(x: UInt): UInt = OHToUInt(OH1ToOH(x))
def UIntToOH1(x: UInt, width: Int): UInt = ~(SInt(-1, width=width).asUInt << x)(width-1, 0)
def trailingZeros(x: Int): Option[Int] = if (x > 0) Some(log2Ceil(x & -x)) else None
// Fill 1s from low bits to high bits
def leftOR(x: UInt): UInt = leftOR(x, x.getWidth, x.getWidth)
def leftOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = {
val stop = min(width, cap)
def helper(s: Int, x: UInt): UInt =
if (s >= stop) x else helper(s+s, x | (x << s)(width-1,0))
helper(1, x)(width-1, 0)
}
// Fill 1s form high bits to low bits
def rightOR(x: UInt): UInt = rightOR(x, x.getWidth, x.getWidth)
def rightOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = {
val stop = min(width, cap)
def helper(s: Int, x: UInt): UInt =
if (s >= stop) x else helper(s+s, x | (x >> s))
helper(1, x)(width-1, 0)
}
}