Skip to content

Commit

Permalink
Utils: add source locators (#2496)
Browse files Browse the repository at this point in the history
* Cat: add source locators

* make test handle both cases

* test that the wrong source locator is not included for Cat

* Add source locators to FillInterleaved and test

* Add Bitwise Spec

* add FillSpec

* Reverse Spec

* Checkpoint -- doesn't compile

* Make source locators more correct with do_apply methods

* add source locators to Reg.scala

* RegEnable source locator tests

* ShiftRegisters source locators unit tests

* scalafmt

* clean up spacing and final defs

* scalafmt

* scaladoc groups
  • Loading branch information
mwachs5 authored Apr 29, 2022
1 parent 2f80a9e commit b24f09c
Show file tree
Hide file tree
Showing 8 changed files with 496 additions and 34 deletions.
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/Mem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ sealed class SyncReadMem[T <: Data] private[chisel3] (t: T, n: BigInt, val readU
def do_read(idx: UInt, en: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
_read_impl(idx, en, Builder.forcedClock, true)

def read(idx: UInt, en: Bool, clock: Clock): T = macro SourceInfoTransform.xyzArg
def read(idx: UInt, en: Bool, clock: Clock): T = macro SourceInfoTransform.idxEnClockArg

/** @group SourceInfoTransformMacro */
def do_read(idx: UInt, en: Bool, clock: Clock)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,58 @@ class SourceInfoTransform(val c: Context) extends AutoSourceTransform {
q"$thisObj.$doFuncTerm($x, $y)($implicitSourceInfo, $implicitCompileOptions)"
}

def xyzArg(idx: c.Tree, en: c.Tree, clock: c.Tree): c.Tree = {
def nxArg(n: c.Tree, x: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($n, $x)($implicitSourceInfo, $implicitCompileOptions)"
}

def idxEnClockArg(idx: c.Tree, en: c.Tree, clock: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($idx, $en, $clock)($implicitSourceInfo, $implicitCompileOptions)"
}

def xEnArg(x: c.Tree, en: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($x, $en)($implicitSourceInfo, $implicitCompileOptions)"
}

def arArg(a: c.Tree, r: c.Tree*): c.Tree = {
q"$thisObj.$doFuncTerm($a, ..$r)($implicitSourceInfo, $implicitCompileOptions)"
}

def rArg(r: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($r)($implicitSourceInfo, $implicitCompileOptions)"
}

def nInArg(n: c.Tree, in: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($n, $in)($implicitSourceInfo, $implicitCompileOptions)"
}

def nextEnableArg(next: c.Tree, enable: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($next, $enable)($implicitSourceInfo, $implicitCompileOptions)"
}

def nextInitEnableArg(next: c.Tree, init: c.Tree, enable: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($next, $init, $enable)($implicitSourceInfo, $implicitCompileOptions)"
}

def inNArg(in: c.Tree, n: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($in, $n)($implicitSourceInfo, $implicitCompileOptions)"
}

def inNEnArg(in: c.Tree, n: c.Tree, en: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($in, $n, $en)($implicitSourceInfo, $implicitCompileOptions)"
}

def inNResetEnArg(in: c.Tree, n: c.Tree, reset: c.Tree, en: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($in, $n, $reset, $en)($implicitSourceInfo, $implicitCompileOptions)"
}

def inNResetDataArg(in: c.Tree, n: c.Tree, resetData: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($in, $n, $resetData)($implicitSourceInfo, $implicitCompileOptions)"
}

def inNResetDataEnArg(in: c.Tree, n: c.Tree, resetData: c.Tree, en: c.Tree): c.Tree = {
q"$thisObj.$doFuncTerm($in, $n, $resetData, $en)($implicitSourceInfo, $implicitCompileOptions)"
}

}

// Workaround for https://github.com/sbt/sbt/issues/3966
Expand Down
88 changes: 64 additions & 24 deletions src/main/scala/chisel3/util/Bitwise.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package chisel3.util

import chisel3._
import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform}
import scala.language.experimental.macros

/** Creates repetitions of each bit of the input in order.
*
Expand All @@ -24,13 +26,29 @@ object FillInterleaved {
*
* Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times)
*/
def apply(n: Int, in: UInt): UInt = apply(n, in.asBools)
def apply(n: Int, in: UInt): UInt = macro SourceInfoTransform.nInArg

/** @group SourceInfoTransformMacro */
def do_apply(n: Int, in: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
_apply_impl(n, in.asBools)

/** Creates n repetitions of each bit of x in order.
*
* Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times)
*/
def apply(n: Int, in: Seq[Bool]): UInt = Cat(in.map(Fill(n, _)).reverse)
def apply(n: Int, in: Seq[Bool]): UInt = macro SourceInfoTransform.nInArg

/** @group SourceInfoTransformMacro */
def do_apply(n: Int, in: Seq[Bool])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
_apply_impl(n, in)

private def _apply_impl(
n: Int,
in: Seq[Bool]
)(
implicit sourceInfo: SourceInfo,
compileOptions: CompileOptions
): UInt = Cat(in.map(Fill(n, _)).reverse)
}

/** Returns the number of bits set (value is 1 or true) in the input signal.
Expand All @@ -45,9 +63,23 @@ object FillInterleaved {
* }}}
*/
object PopCount {
def apply(in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq)

def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_)))
def apply(in: Iterable[Bool]): UInt = macro SourceInfoTransform.inArg

/** @group SourceInfoTransformMacro */
def do_apply(in: Iterable[Bool])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = _apply_impl(
in.toSeq
)

def apply(in: Bits): UInt = macro SourceInfoTransform.inArg

/** @group SourceInfoTransformMacro */
def do_apply(in: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = _apply_impl(
(0 until in.getWidth).map(in(_))
)

private def _apply_impl(in: Iterable[Bool])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
SeqUtils.count(in.toSeq)
}

/** Create repetitions of the input using a tree fanout topology.
Expand All @@ -65,7 +97,10 @@ object Fill {
* Output data-equivalent to x ## x ## ... ## x (n repetitions).
* @throws java.lang.IllegalArgumentException if `n` is less than zero
*/
def apply(n: Int, x: UInt): UInt = {
def apply(n: Int, x: UInt): UInt = macro SourceInfoTransform.nxArg

/** @group SourceInfoTransformMacro */
def do_apply(n: Int, x: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = {
n match {
case _ if n < 0 => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.")
case 0 => UInt(0.W)
Expand All @@ -92,24 +127,29 @@ object Fill {
* }}}
*/
object Reverse {
private def doit(in: UInt, length: Int): UInt = length match {
case _ if length < 0 => throw new IllegalArgumentException(s"length (=$length) must be nonnegative integer.")
case _ if length <= 1 => in
case _ if isPow2(length) && length >= 8 && length <= 64 =>
// This esoterica improves simulation performance
var res = in
var shift = length >> 1
var mask = ((BigInt(1) << length) - 1).asUInt(length.W)
do {
mask = mask ^ (mask(length - shift - 1, 0) << shift)
res = ((res >> shift) & mask) | ((res(length - shift - 1, 0) << shift) & ~mask)
shift = shift >> 1
} while (shift > 0)
res
case _ =>
val half = (1 << log2Ceil(length)) / 2
Cat(doit(in(half - 1, 0), half), doit(in(length - 1, half), length - half))
}

def apply(in: UInt): UInt = doit(in, in.getWidth)
private def doit(in: UInt, length: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
length match {
case _ if length < 0 => throw new IllegalArgumentException(s"length (=$length) must be nonnegative integer.")
case _ if length <= 1 => in
case _ if isPow2(length) && length >= 8 && length <= 64 =>
// This esoterica improves simulation performance
var res = in
var shift = length >> 1
var mask = ((BigInt(1) << length) - 1).asUInt(length.W)
do {
mask = mask ^ (mask(length - shift - 1, 0) << shift)
res = ((res >> shift) & mask) | ((res(length - shift - 1, 0) << shift) & ~mask)
shift = shift >> 1
} while (shift > 0)
res
case _ =>
val half = (1 << log2Ceil(length)) / 2
Cat(doit(in(half - 1, 0), half), doit(in(length - 1, half), length - half))
}

def apply(in: UInt): UInt = macro SourceInfoTransform.inArg

/** @group SourceInfoTransformMacro */
def do_apply(in: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = doit(in, in.getWidth)
}
18 changes: 16 additions & 2 deletions src/main/scala/chisel3/util/Cat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

package chisel3.util

import scala.language.experimental.macros

import chisel3._
import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform}

/** Concatenates elements of the input, in order, together.
*
Expand All @@ -19,7 +22,11 @@ object Cat {
/** Concatenates the argument data elements, in argument order, together. The first argument
* forms the most significant bits, while the last argument forms the least significant bits.
*/
def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList)
def apply[T <: Bits](a: T, r: T*): UInt = macro SourceInfoTransform.arArg

/** @group SourceInfoTransformMacro */
def do_apply[T <: Bits](a: T, r: T*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
_apply_impl(a :: r.toList)

/** Concatenates the data elements of the input sequence, in reverse sequence order, together.
* The first element of the sequence forms the most significant bits, while the last element
Expand All @@ -28,5 +35,12 @@ object Cat {
* Equivalent to r(0) ## r(1) ## ... ## r(n-1).
* @note This returns a `0.U` if applied to a zero-element `Vec`.
*/
def apply[T <: Bits](r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse)
def apply[T <: Bits](r: Seq[T]): UInt = macro SourceInfoTransform.rArg

/** @group SourceInfoTransformMacro */
def do_apply[T <: Bits](r: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
_apply_impl(r)

private def _apply_impl[T <: Bits](r: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
SeqUtils.asUInt(r.reverse)
}
Loading

0 comments on commit b24f09c

Please sign in to comment.