Move a bunch more things into util package
A lot of utility code was just being imported willy-nilly from one package to another. This moves the common code into util to make things more sensible. The code moved were * The AsyncQueue and AsyncDecoupledCrossing from junctions. * All of the code in rocket's util.scala * The BlackBox asynchronous reset registers from uncore.tilelink2 * The implicit definitions from uncore.util
This commit is contained in:
100
src/main/scala/util/AsyncQueue.scala
Normal file
100
src/main/scala/util/AsyncQueue.scala
Normal file
@ -0,0 +1,100 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package util
|
||||
import Chisel._
|
||||
|
||||
object GrayCounter {
|
||||
def apply(bits: Int, increment: Bool = Bool(true)): UInt = {
|
||||
val incremented = Wire(UInt(width=bits))
|
||||
val binary = AsyncResetReg(incremented, 0)
|
||||
incremented := binary + increment.asUInt()
|
||||
incremented ^ (incremented >> UInt(1))
|
||||
}
|
||||
}
|
||||
|
||||
object AsyncGrayCounter {
|
||||
def apply(in: UInt, sync: Int): UInt = {
|
||||
val syncv = List.fill(sync)(Module (new AsyncResetRegVec(w = in.getWidth, 0)))
|
||||
syncv.last.io.d := in
|
||||
syncv.last.io.en := Bool(true)
|
||||
(syncv.init zip syncv.tail).foreach { case (sink, source) =>
|
||||
sink.io.d := source.io.q
|
||||
sink.io.en := Bool(true)
|
||||
}
|
||||
syncv(0).io.d
|
||||
}
|
||||
}
|
||||
|
||||
class AsyncQueueSource[T <: Data](gen: T, depth: Int, sync: Int, clockIn: Clock, resetIn: Bool)
|
||||
extends Module(_clock = clockIn, _reset = resetIn) {
|
||||
val bits = log2Ceil(depth)
|
||||
val io = new Bundle {
|
||||
// These come from the source domain
|
||||
val enq = Decoupled(gen).flip()
|
||||
// These cross to the sink clock domain
|
||||
val ridx = UInt(INPUT, width = bits+1)
|
||||
val widx = UInt(OUTPUT, width = bits+1)
|
||||
val mem = Vec(depth, gen).asOutput
|
||||
}
|
||||
|
||||
val mem = Reg(Vec(depth, gen)) //This does NOT need to be asynchronously reset.
|
||||
val widx = GrayCounter(bits+1, io.enq.fire())
|
||||
val ridx = AsyncGrayCounter(io.ridx, sync)
|
||||
val ready = widx =/= (ridx ^ UInt(depth | depth >> 1))
|
||||
|
||||
val index = if (depth == 1) UInt(0) else io.widx(bits-1, 0) ^ (io.widx(bits, bits) << (bits-1))
|
||||
when (io.enq.fire() && !reset) { mem(index) := io.enq.bits }
|
||||
val ready_reg = AsyncResetReg(ready, 0)
|
||||
io.enq.ready := ready_reg
|
||||
|
||||
val widx_reg = AsyncResetReg(widx, 0)
|
||||
io.widx := widx_reg
|
||||
|
||||
io.mem := mem
|
||||
}
|
||||
|
||||
class AsyncQueueSink[T <: Data](gen: T, depth: Int, sync: Int, clockIn: Clock, resetIn: Bool)
|
||||
extends Module(_clock = clockIn, _reset = resetIn) {
|
||||
val bits = log2Ceil(depth)
|
||||
val io = new Bundle {
|
||||
// These come from the sink domain
|
||||
val deq = Decoupled(gen)
|
||||
// These cross to the source clock domain
|
||||
val ridx = UInt(OUTPUT, width = bits+1)
|
||||
val widx = UInt(INPUT, width = bits+1)
|
||||
val mem = Vec(depth, gen).asInput
|
||||
}
|
||||
|
||||
val ridx = GrayCounter(bits+1, io.deq.fire())
|
||||
val widx = AsyncGrayCounter(io.widx, sync)
|
||||
val valid = ridx =/= widx
|
||||
|
||||
// The mux is safe because timing analysis ensures ridx has reached the register
|
||||
// On an ASIC, changes to the unread location cannot affect the selected value
|
||||
// On an FPGA, only one input changes at a time => mem updates don't cause glitches
|
||||
// The register only latches when the selected valued is not being written
|
||||
val index = if (depth == 1) UInt(0) else ridx(bits-1, 0) ^ (ridx(bits, bits) << (bits-1))
|
||||
// This register does not NEED to be reset, as its contents will not
|
||||
// be considered unless the asynchronously reset deq valid register is set.
|
||||
io.deq.bits := RegEnable(io.mem(index), valid)
|
||||
|
||||
io.deq.valid := AsyncResetReg(valid, 0)
|
||||
|
||||
io.ridx := AsyncResetReg(ridx, 0)
|
||||
}
|
||||
|
||||
class AsyncQueue[T <: Data](gen: T, depth: Int = 8, sync: Int = 3) extends Crossing[T] {
|
||||
require (sync >= 2)
|
||||
require (depth > 0 && isPow2(depth))
|
||||
|
||||
val io = new CrossingIO(gen)
|
||||
val source = Module(new AsyncQueueSource(gen, depth, sync, io.enq_clock, io.enq_reset))
|
||||
val sink = Module(new AsyncQueueSink (gen, depth, sync, io.deq_clock, io.deq_reset))
|
||||
|
||||
source.io.enq <> io.enq
|
||||
io.deq <> sink.io.deq
|
||||
|
||||
sink.io.mem := source.io.mem
|
||||
sink.io.widx := source.io.widx
|
||||
source.io.ridx := sink.io.ridx
|
||||
}
|
110
src/main/scala/util/BlackBoxRegs.scala
Normal file
110
src/main/scala/util/BlackBoxRegs.scala
Normal file
@ -0,0 +1,110 @@
|
||||
package util
|
||||
|
||||
import Chisel._
|
||||
|
||||
import cde.{Parameters}
|
||||
|
||||
/** This black-boxes an Async Reset
|
||||
* (or Set)
|
||||
* Register.
|
||||
*
|
||||
* Because Chisel doesn't support
|
||||
* parameterized black boxes,
|
||||
* we unfortunately have to
|
||||
* instantiate a number of these.
|
||||
*
|
||||
* We also have to hard-code the set/
|
||||
* reset behavior.
|
||||
*
|
||||
* Do not confuse an asynchronous
|
||||
* reset signal with an asynchronously
|
||||
* reset reg. You should still
|
||||
* properly synchronize your reset
|
||||
* deassertion.
|
||||
*
|
||||
* @param d Data input
|
||||
* @param q Data Output
|
||||
* @param clk Clock Input
|
||||
* @param rst Reset Input
|
||||
* @param en Write Enable Input
|
||||
*
|
||||
*/
|
||||
|
||||
abstract class AbstractBBReg extends BlackBox {
|
||||
|
||||
val io = new Bundle {
|
||||
val d = Bool(INPUT)
|
||||
val q = Bool(OUTPUT)
|
||||
val en = Bool(INPUT)
|
||||
|
||||
val clk = Clock(INPUT)
|
||||
val rst = Bool(INPUT)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AsyncResetReg extends AbstractBBReg
|
||||
class AsyncSetReg extends AbstractBBReg
|
||||
|
||||
class SimpleRegIO(val w: Int) extends Bundle{
|
||||
|
||||
val d = UInt(INPUT, width = w)
|
||||
val q = UInt(OUTPUT, width = w)
|
||||
|
||||
val en = Bool(INPUT)
|
||||
|
||||
}
|
||||
|
||||
class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module {
|
||||
|
||||
val io = new SimpleRegIO(w)
|
||||
|
||||
val bb_d = Mux(io.en, io.d, io.q)
|
||||
|
||||
val async_regs: List[AbstractBBReg] = List.tabulate(w)(
|
||||
i => Module (
|
||||
if (((init >> i) % 2) > 0)
|
||||
new AsyncSetReg
|
||||
else
|
||||
new AsyncResetReg)
|
||||
)
|
||||
|
||||
io.q := async_regs.map(_.io.q).asUInt
|
||||
|
||||
for ((reg, idx) <- async_regs.zipWithIndex) {
|
||||
reg.io.clk := clock
|
||||
reg.io.rst := reset
|
||||
reg.io.d := bb_d(idx)
|
||||
reg.io.en := io.en
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object AsyncResetReg {
|
||||
def apply(d: Bool, clk: Clock, rst: Bool, init: Boolean): Bool = {
|
||||
val reg: AbstractBBReg =
|
||||
if (init) Module (new AsyncSetReg)
|
||||
else Module(new AsyncResetReg)
|
||||
reg.io.d := d
|
||||
reg.io.clk := clk
|
||||
reg.io.rst := rst
|
||||
reg.io.en := Bool(true)
|
||||
reg.io.q
|
||||
}
|
||||
|
||||
def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, false)
|
||||
|
||||
def apply(updateData: UInt, resetData: BigInt, enable: Bool): UInt = {
|
||||
val w = updateData.getWidth max resetData.bitLength
|
||||
val reg = Module(new AsyncResetRegVec(w, resetData))
|
||||
reg.io.d := updateData
|
||||
reg.io.en := enable
|
||||
reg.io.q
|
||||
}
|
||||
|
||||
def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, enable=Bool(true))
|
||||
|
||||
def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, resetData=BigInt(0), enable)
|
||||
|
||||
def apply(updateData: UInt): UInt = apply(updateData, resetData=BigInt(0), enable=Bool(true))
|
||||
}
|
@ -2,6 +2,7 @@ package util
|
||||
|
||||
import Chisel._
|
||||
import cde.Parameters
|
||||
import scala.math.max
|
||||
|
||||
// Produces 0-width value when counting to 1
|
||||
class ZCounter(val n: Int) {
|
||||
@ -34,3 +35,33 @@ object TwoWayCounter {
|
||||
cnt
|
||||
}
|
||||
}
|
||||
|
||||
// a counter that clock gates most of its MSBs using the LSB carry-out
|
||||
case class WideCounter(width: Int, inc: UInt = UInt(1), reset: Boolean = true)
|
||||
{
|
||||
private val isWide = width > 2*inc.getWidth
|
||||
private val smallWidth = if (isWide) inc.getWidth max log2Up(width) else width
|
||||
private val small = if (reset) Reg(init=UInt(0, smallWidth)) else Reg(UInt(width = smallWidth))
|
||||
private val nextSmall = small +& inc
|
||||
small := nextSmall
|
||||
|
||||
private val large = if (isWide) {
|
||||
val r = if (reset) Reg(init=UInt(0, width - smallWidth)) else Reg(UInt(width = width - smallWidth))
|
||||
when (nextSmall(smallWidth)) { r := r +& UInt(1) }
|
||||
r
|
||||
} else null
|
||||
|
||||
val value = if (isWide) Cat(large, small) else small
|
||||
lazy val carryOut = {
|
||||
val lo = (small ^ nextSmall) >> 1
|
||||
if (!isWide) lo else {
|
||||
val hi = Mux(nextSmall(smallWidth), large ^ (large +& UInt(1)), UInt(0)) >> 1
|
||||
Cat(hi, lo)
|
||||
}
|
||||
}
|
||||
|
||||
def := (x: UInt) = {
|
||||
small := x
|
||||
if (isWide) large := x >> smallWidth
|
||||
}
|
||||
}
|
||||
|
134
src/main/scala/util/Crossing.scala
Normal file
134
src/main/scala/util/Crossing.scala
Normal file
@ -0,0 +1,134 @@
|
||||
package util
|
||||
|
||||
import Chisel._
|
||||
import chisel3.util.{DecoupledIO, Decoupled, Irrevocable, IrrevocableIO, ReadyValidIO}
|
||||
|
||||
class CrossingIO[T <: Data](gen: T) extends Bundle {
|
||||
// Enqueue clock domain
|
||||
val enq_clock = Clock(INPUT)
|
||||
val enq_reset = Bool(INPUT) // synchronously deasserted wrt. enq_clock
|
||||
val enq = Decoupled(gen).flip()
|
||||
// Dequeue clock domain
|
||||
val deq_clock = Clock(INPUT)
|
||||
val deq_reset = Bool(INPUT) // synchronously deasserted wrt. deq_clock
|
||||
val deq = Decoupled(gen)
|
||||
}
|
||||
|
||||
abstract class Crossing[T <: Data] extends Module {
|
||||
val io: CrossingIO[T]
|
||||
}
|
||||
|
||||
class AsyncScope extends Module { val io = new Bundle }
|
||||
object AsyncScope { def apply() = Module(new AsyncScope) }
|
||||
|
||||
object AsyncDecoupledCrossing
|
||||
{
|
||||
// takes from_source from the 'from' clock domain and puts it into the 'to' clock domain
|
||||
def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
|
||||
val crossing = Module(new AsyncQueue(from_source.bits, depth, sync)).io
|
||||
crossing.enq_clock := from_clock
|
||||
crossing.enq_reset := from_reset
|
||||
crossing.enq <> from_source
|
||||
crossing.deq_clock := to_clock
|
||||
crossing.deq_reset := to_reset
|
||||
crossing.deq
|
||||
}
|
||||
}
|
||||
|
||||
object AsyncDecoupledTo
|
||||
{
|
||||
// takes source from your clock domain and puts it into the 'to' clock domain
|
||||
def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
|
||||
val scope = AsyncScope()
|
||||
AsyncDecoupledCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync)
|
||||
}
|
||||
}
|
||||
|
||||
object AsyncDecoupledFrom
|
||||
{
|
||||
// takes from_source from the 'from' clock domain and puts it into your clock domain
|
||||
def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
|
||||
val scope = AsyncScope()
|
||||
AsyncDecoupledCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync)
|
||||
}
|
||||
}
|
||||
|
||||
object PostQueueIrrevocablize
|
||||
{
|
||||
def apply[T <: Data](deq: DecoupledIO[T]): IrrevocableIO[T] = {
|
||||
val irr = Wire(new IrrevocableIO(deq.bits))
|
||||
irr.bits := deq.bits
|
||||
irr.valid := deq.valid
|
||||
deq.ready := irr.ready
|
||||
irr
|
||||
}
|
||||
}
|
||||
|
||||
object AsyncIrrevocableCrossing {
|
||||
def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3): IrrevocableIO[T] = {
|
||||
PostQueueIrrevocablize(AsyncDecoupledCrossing(from_clock, from_reset, from_source, to_clock, to_reset, depth, sync))
|
||||
}
|
||||
}
|
||||
|
||||
object AsyncIrrevocableTo
|
||||
{
|
||||
// takes source from your clock domain and puts it into the 'to' clock domain
|
||||
def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): IrrevocableIO[T] = {
|
||||
PostQueueIrrevocablize(AsyncDecoupledTo(to_clock, to_reset, source, depth, sync))
|
||||
}
|
||||
}
|
||||
|
||||
object AsyncIrrevocableFrom
|
||||
{
|
||||
// takes from_source from the 'from' clock domain and puts it into your clock domain
|
||||
def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): IrrevocableIO[T] = {
|
||||
PostQueueIrrevocablize(AsyncDecoupledFrom(from_clock, from_reset, from_source, depth, sync))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper object synchronizes a level-sensitive signal from one
|
||||
* clock domain to another.
|
||||
*/
|
||||
object LevelSyncCrossing {
|
||||
class SynchronizerBackend(sync: Int, _clock: Clock) extends Module(Some(_clock)) {
|
||||
val io = new Bundle {
|
||||
val in = Bool(INPUT)
|
||||
val out = Bool(OUTPUT)
|
||||
}
|
||||
|
||||
io.out := ShiftRegister(io.in, sync)
|
||||
}
|
||||
|
||||
class SynchronizerFrontend(_clock: Clock) extends Module(Some(_clock)) {
|
||||
val io = new Bundle {
|
||||
val in = Bool(INPUT)
|
||||
val out = Bool(OUTPUT)
|
||||
}
|
||||
|
||||
io.out := RegNext(io.in)
|
||||
}
|
||||
|
||||
def apply(from_clock: Clock, to_clock: Clock, in: Bool, sync: Int = 2): Bool = {
|
||||
val front = Module(new SynchronizerFrontend(from_clock))
|
||||
val back = Module(new SynchronizerBackend(sync, to_clock))
|
||||
|
||||
front.io.in := in
|
||||
back.io.in := front.io.out
|
||||
back.io.out
|
||||
}
|
||||
}
|
||||
|
||||
object LevelSyncTo {
|
||||
def apply(to_clock: Clock, in: Bool, sync: Int = 2): Bool = {
|
||||
val scope = AsyncScope()
|
||||
LevelSyncCrossing(scope.clock, to_clock, in, sync)
|
||||
}
|
||||
}
|
||||
|
||||
object LevelSyncFrom {
|
||||
def apply(from_clock: Clock, in: Bool, sync: Int = 2): Bool = {
|
||||
val scope = AsyncScope()
|
||||
LevelSyncCrossing(from_clock, scope.clock, in, sync)
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package util
|
||||
|
||||
import Chisel._
|
||||
import cde.Parameters
|
||||
import scala.math._
|
||||
|
||||
class ParameterizedBundle(implicit p: Parameters) extends Bundle {
|
||||
override def cloneType = {
|
||||
@ -26,3 +27,113 @@ class DecoupledHelper(val rvs: Seq[Bool]) {
|
||||
(rvs.filter(_ ne exclude) ++ includes).reduce(_ && _)
|
||||
}
|
||||
}
|
||||
|
||||
object MuxT {
|
||||
def apply[T <: Data, U <: Data](cond: Bool, con: (T, U), alt: (T, U)): (T, U) =
|
||||
(Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2))
|
||||
|
||||
def apply[T <: Data, U <: Data, W <: Data](cond: Bool, con: (T, U, W), alt: (T, U, W)): (T, U, W) =
|
||||
(Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2), Mux(cond, con._3, alt._3))
|
||||
}
|
||||
|
||||
object Str
|
||||
{
|
||||
def apply(s: String): UInt = {
|
||||
var i = BigInt(0)
|
||||
require(s.forall(validChar _))
|
||||
for (c <- s)
|
||||
i = (i << 8) | c
|
||||
UInt(i, s.length*8)
|
||||
}
|
||||
def apply(x: Char): UInt = {
|
||||
require(validChar(x))
|
||||
UInt(x.toInt, 8)
|
||||
}
|
||||
def apply(x: UInt): UInt = apply(x, 10)
|
||||
def apply(x: UInt, radix: Int): UInt = {
|
||||
val rad = UInt(radix)
|
||||
val w = x.getWidth
|
||||
require(w > 0)
|
||||
|
||||
var q = x
|
||||
var s = digit(q % rad)
|
||||
for (i <- 1 until ceil(log(2)/log(radix)*w).toInt) {
|
||||
q = q / rad
|
||||
s = Cat(Mux(Bool(radix == 10) && q === UInt(0), Str(' '), digit(q % rad)), s)
|
||||
}
|
||||
s
|
||||
}
|
||||
def apply(x: SInt): UInt = apply(x, 10)
|
||||
def apply(x: SInt, radix: Int): UInt = {
|
||||
val neg = x < SInt(0)
|
||||
val abs = x.abs
|
||||
if (radix != 10) {
|
||||
Cat(Mux(neg, Str('-'), Str(' ')), Str(abs, radix))
|
||||
} else {
|
||||
val rad = UInt(radix)
|
||||
val w = abs.getWidth
|
||||
require(w > 0)
|
||||
|
||||
var q = abs
|
||||
var s = digit(q % rad)
|
||||
var needSign = neg
|
||||
for (i <- 1 until ceil(log(2)/log(radix)*w).toInt) {
|
||||
q = q / rad
|
||||
val placeSpace = q === UInt(0)
|
||||
val space = Mux(needSign, Str('-'), Str(' '))
|
||||
needSign = needSign && !placeSpace
|
||||
s = Cat(Mux(placeSpace, space, digit(q % rad)), s)
|
||||
}
|
||||
Cat(Mux(needSign, Str('-'), Str(' ')), s)
|
||||
}
|
||||
}
|
||||
|
||||
private def digit(d: UInt): UInt = Mux(d < UInt(10), Str('0')+d, Str(('a'-10).toChar)+d)(7,0)
|
||||
private def validChar(x: Char) = x == (x & 0xFF)
|
||||
}
|
||||
|
||||
object Split
|
||||
{
|
||||
// is there a better way to do do this?
|
||||
def apply(x: Bits, n0: Int) = {
|
||||
val w = checkWidth(x, n0)
|
||||
(x(w-1,n0), x(n0-1,0))
|
||||
}
|
||||
def apply(x: Bits, n1: Int, n0: Int) = {
|
||||
val w = checkWidth(x, n1, n0)
|
||||
(x(w-1,n1), x(n1-1,n0), x(n0-1,0))
|
||||
}
|
||||
def apply(x: Bits, n2: Int, n1: Int, n0: Int) = {
|
||||
val w = checkWidth(x, n2, n1, n0)
|
||||
(x(w-1,n2), x(n2-1,n1), x(n1-1,n0), x(n0-1,0))
|
||||
}
|
||||
|
||||
private def checkWidth(x: Bits, n: Int*) = {
|
||||
val w = x.getWidth
|
||||
def decreasing(x: Seq[Int]): Boolean =
|
||||
if (x.tail.isEmpty) true
|
||||
else x.head >= x.tail.head && decreasing(x.tail)
|
||||
require(decreasing(w :: n.toList))
|
||||
w
|
||||
}
|
||||
}
|
||||
|
||||
object Random
|
||||
{
|
||||
def apply(mod: Int, random: UInt): UInt = {
|
||||
if (isPow2(mod)) random(log2Up(mod)-1,0)
|
||||
else PriorityEncoder(partition(apply(1 << log2Up(mod*8), random), mod))
|
||||
}
|
||||
def apply(mod: Int): UInt = apply(mod, randomizer)
|
||||
def oneHot(mod: Int, random: UInt): UInt = {
|
||||
if (isPow2(mod)) UIntToOH(random(log2Up(mod)-1,0))
|
||||
else PriorityEncoderOH(partition(apply(1 << log2Up(mod*8), random), mod)).asUInt
|
||||
}
|
||||
def oneHot(mod: Int): UInt = oneHot(mod, randomizer)
|
||||
|
||||
private def randomizer = LFSR16()
|
||||
private def round(x: Double): Int =
|
||||
if (x.toInt.toDouble == x) x.toInt else (x.toInt + 1) & -2
|
||||
private def partition(value: UInt, slices: Int) =
|
||||
Seq.tabulate(slices)(i => value < round((i << value.getWidth).toDouble / slices))
|
||||
}
|
||||
|
48
src/main/scala/util/Package.scala
Normal file
48
src/main/scala/util/Package.scala
Normal file
@ -0,0 +1,48 @@
|
||||
import Chisel._
|
||||
|
||||
package object util {
|
||||
implicit class UIntIsOneOf(val x: UInt) extends AnyVal {
|
||||
def isOneOf(s: Seq[UInt]): Bool = s.map(x === _).reduce(_||_)
|
||||
|
||||
def isOneOf(u1: UInt, u2: UInt*): Bool = isOneOf(u1 +: u2.toSeq)
|
||||
}
|
||||
|
||||
implicit class SeqToAugmentedSeq[T <: Data](val x: Seq[T]) extends AnyVal {
|
||||
def apply(idx: UInt): T = {
|
||||
if (x.size == 1) {
|
||||
x.head
|
||||
} else {
|
||||
val half = 1 << (log2Ceil(x.size) - 1)
|
||||
val newIdx = idx & UInt(half - 1)
|
||||
Mux(idx >= UInt(half), x.drop(half)(newIdx), x.take(half)(newIdx))
|
||||
}
|
||||
}
|
||||
|
||||
def asUInt(): UInt = Cat(x.map(_.asUInt).reverse)
|
||||
}
|
||||
|
||||
implicit def uintToBitPat(x: UInt): BitPat = BitPat(x)
|
||||
implicit def intToUInt(x: Int): UInt = UInt(x)
|
||||
implicit def bigIntToUInt(x: BigInt): UInt = UInt(x)
|
||||
implicit def booleanToBool(x: Boolean): Bits = Bool(x)
|
||||
implicit def intSeqToUIntSeq(x: Seq[Int]): Seq[UInt] = x.map(UInt(_))
|
||||
implicit def wcToUInt(c: WideCounter): UInt = c.value
|
||||
|
||||
implicit class UIntToAugmentedUInt(val x: UInt) extends AnyVal {
|
||||
def sextTo(n: Int): UInt =
|
||||
if (x.getWidth == n) x
|
||||
else Cat(Fill(n - x.getWidth, x(x.getWidth-1)), x)
|
||||
|
||||
def extract(hi: Int, lo: Int): UInt = {
|
||||
if (hi == lo-1) UInt(0)
|
||||
else x(hi, lo)
|
||||
}
|
||||
}
|
||||
|
||||
implicit class BooleanToAugmentedBoolean(val x: Boolean) extends AnyVal {
|
||||
def toInt: Int = if (x) 1 else 0
|
||||
|
||||
// this one's snagged from scalaz
|
||||
def option[T](z: => T): Option[T] = if (x) Some(z) else None
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user