Skip to content

Commit

Permalink
Bump to chisel3.6 (#247)
Browse files Browse the repository at this point in the history
* Bump breeze and spire versions

* Bump spire to 0.18.0
* Bump breeze to 2.1.0
* Override method 'reverse' in SignAlgebra due to both Order[A]
and CMonoid[A] now having 'reverse' methods each.
* Remove parameterless non-Unit method definitions and invocations

* Bump Chisel version to 3.6

* Bump dsptools version to 1.6
* Bump chiseltest version to 0.6
* Bump scalatest version to 3.2.15
* Bump fixedpoint to version supporting Chisel 3.6.0
* Apply fixedpoint.shadow.Mux to more places
* Add '-Xfatal-warnings' compiler option
* Remove Saturate as it uses firrtl transformations
* Add branch 1.6.x to CI workflow

* Update scalafmt settings

* Add sclaafmt sbt plugin
* Reformat source files according to scalafmt rules
* Add scalafmt step to CI

* Changed license from BSD to Apache-2.0 in README.md

---------

Co-authored-by: Aleksandar Kondić <[email protected]>
  • Loading branch information
milovanovic and konda-x1 authored Jul 30, 2023
1 parent 3fb6e60 commit 2fa039f
Show file tree
Hide file tree
Showing 43 changed files with 680 additions and 869 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
push:
branches:
- master
- 1.6.x
- 1.5.x
- 1.4.x
- 1.3.x
Expand All @@ -25,6 +26,9 @@ jobs:
uses: coursier/setup-action@v1
- name: Cache
uses: coursier/cache-action@v6
- name: Formatting check
id: scalafmt
run: sbt scalafmtCheckAll
- name: Documentation
id: doc
run: sbt doc
Expand Down
8 changes: 7 additions & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
version = 2.6.4

maxColumn = 120
align = most
continuationIndent.defnSite = 2
Expand All @@ -13,7 +15,11 @@ align.tokens.add = [
}
]

newlines.alwaysBeforeCurlyBraceLambdaParams
 = false
newlines.alwaysBeforeCurlyBraceLambdaParams = false
newlines.alwaysBeforeMultilineDef = false
newlines.implicitParamListModifierForce = [before]

verticalMultiline.atDefnSite = true

optIn.annotationNewlines = true

Expand Down
74 changes: 35 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ Some of the goals of dsptools are to enable:
2. Enhanced support for designing and testing DSP with generic types (i.e. switching between **DSPReal** for verifying functional correctness with double-precision floating point and **FixedPoint** for evaluating fixed-point design metrics by changing a single parameter).

3. More useful and universal testing platform for numeric types!
> Numbers are displayed in their correct formats instead of hex for peek, poke, and expect operations. Additionally, if your tester extends **DSPTester**, you can optionally dump your test sequence to a **Verilog testbench** that replays the test for functional verification on all simulation platforms (i.e. Xilinx, Altera, etc. instead of only VCS). The tolerance of comparisons with expected values can also be changed via `DSPTester.setTol(floTol = decimal_tolerance,
fixedTol = number_of_bits)`.
> Numbers are displayed in their correct formats instead of hex for peek, poke, and expect operations. Additionally, if your tester extends **DSPTester**, you can optionally dump your test sequence to a **Verilog testbench** that replays the test for functional verification on all simulation platforms (i.e. Xilinx, Altera, etc. instead of only VCS). The tolerance of comparisons with expected values can also be changed via `DSPTester.setTol(floTol = decimal_tolerance, fixedTol = number_of_bits)`.
4. **Miscellaneous additional features**
- Wide range of LUT modules for ease of generating lookup tables from pre-calculated constants (no intermediate representation)
- Memory modules that abstract out confusion associated with Chisel Mem
- Wide range of LUT modules for ease of generating lookup tables from pre-calculated constants (no intermediate representation).
- Memory modules that abstract out confusion associated with Chisel `Mem`.
- Generates useful helper files with each Verilog output (constraints, generator parameters used, etc.).
- Easier to rename modules & signals and have renaming actually succeed.
- Expanding Support for non-base-2 math.
Expand All @@ -50,46 +49,42 @@ See Github for the latest release.
Snapshots are also published on Sonatype, which are beneficial if you want to use the latest features.

Projects that dsptools depends on are:

- [FIRRTL](https://github.com/ucb-bar/firrtl)

- [FIRRTL Interpreter](https://github.com/ucb-bar/firrtl-interpreter)

- [Chisel3](https://github.com/ucb-bar/chisel3)

- [Chisel Testers](https://github.com/ucb-bar/chisel-testers)
* [FIRRTL](https://github.com/ucb-bar/firrtl)
* [FIRRTL Interpreter](https://github.com/ucb-bar/firrtl-interpreter)
* [Chisel3](https://github.com/ucb-bar/chisel3)
* [Chisel Testers](https://github.com/ucb-bar/chisel-testers)

----------

Numeric Typeclasses
===============
===================

This library defines a number of typeclasses for numeric types.
A brief explanation of how typeclasses work in scala can be found [here](http://typelevel.org/cats/typeclasses.html) and [here](http://blog.jaceklaskowski.pl/2015/05/15/ad-hoc-polymorphism-in-scala-with-type-classes.html).
A brief explanation of how typeclasses work in scala can be found [here](http://typelevel.org/cats/typeclasses.html).
Our DSP-specific typeclasses are built on top of [spire](https://github.com/non/spire).

The goal of these typeclasses is to make it easy to write chisel modules that treat the number representation as a parameter.
For example, using typeclasses you can write chisel that generates an FIR filter for both real and complex numbers.
You can also use typeclasses to write chisel that generates a circuit implementation using floating point (via Verilog's real type).
The goal of these typeclasses is to make it easy to write Chisel modules that treat the number representation as a parameter.
For example, using typeclasses you can write Chisel that generates an FIR filter for both real and complex numbers.
You can also use typeclasses to write Chisel that generates a circuit implementation using floating point (via Verilog's real type).
After testing that your circuit implementation works with floating point, you can use the same code to generate a fixed point version of the circuit suitable for synthesis.

**For a additional, more detailed description of the Numeric classes in dsptools: see [The Numbers ReadMe](https://github.com/ucb-bar/dsptools/blob/master/src/main/scala/dsptools/numbers/README.md)**


A generic function in scala is defined like so:
A generic function in Scala programming language is defined like so:

```def func[T](in: T): T```

This means that you can call `func(obj)` for an object of any type. If `obj` is of type `Q`, you can write `func[Q](obj)` to specify that we want the `Q` version of the generic function `func`, but this is only necessary if the scala compiler can't figure out what `Q` is supposed to be.
This means that you can call `func(obj)` for an object of any type. If `obj` is of type `Q`, you can write `func[Q](obj)` to specify that we want the `Q` version of the generic function `func`, but this is only necessary if the Scala compiler can't figure out what `Q` is supposed to be.

You can also write

```class SomeClass[T]```

and use `T` like it is a real type for any member functions of variables.
To write a generic chisel Module, we might try to write
To write a generic Chisel Module, we might try to write

```
```scala
class Passthrough[T](gen: T) extends Module {
val io = new IO(Bundle {
val in = Input(gen)
Expand All @@ -102,18 +97,18 @@ class Passthrough[T](gen: T) extends Module {
Here, `gen` is a parameter specifying the type you want to use for your IO's, so you could write `Module(new Passthrough(SInt(width=10)))` or `Module(new Passthrough(new Bundle { ... }))`.
Unfortunately, there's a problem with this.
`T` can be any type, and a lot of types don't make sense, like `String` or `()=>Unit`.
This will not compile, because `Input()`, `Output()`, and `:=` are functions defined on chisel types.
This will not compile, because `Input()`, `Output()`, and `:=` are functions defined on Chisel types.
We can fix this problem by writing

```class Passthrough[T<:Data](gen: T) extends Module```

This type constraint means that we have to choose `T` to be a subtype of the chisel type `Data`.
This type constraint means that we have to choose `T` to be a subtype of the Chisel type `Data`.
Things like `UInt`, `SInt`, and `Bundle` are subtypes of `Data`.
Now the example above should compile.
This example isn't very interesting, though.
`Data` lets you do basic things like assignment and make registers, but doesn't define any mathematical operations, so if we write

```
```scala
class Doubler[T<:Data](gen: T) extends Module {
val io = IO(new Bundle {
val in = Input(gen)
Expand All @@ -127,7 +122,7 @@ it won't compile.
This is where typeclasses come in.
This library defines a trait

```
```scala
trait Real[T] {
...
def plus(x: T, y: T): T
Expand All @@ -137,49 +132,50 @@ trait Real[T] {

as well as an implicit conversion so that `a+b` gets converted to `Real[T].plus(a,b)`.
`Real[T]` is a typeclass.
Typeclasses are a useful pattern in scala, so there is syntactic sugar to make using them easy:
Typeclasses are a useful pattern in Scala, so there is syntactic sugar to make using them easy:

```
```scala
import dsptools.numbers._
class Doubler[T<:Data:Real](gen: T) extends Module
```

Note: If you don't include the `:Real` at the end, the scala compiler will think `io.in + io.in` is string concatenation and you'll get a weird error saying
*Note*: If you don't include the `:Real` at the end, the Scala compiler will think `io.in + io.in` is string concatenation and you'll get a weird error saying

```
[error] found : T
[error] required: String
```

Some useful typeclasses:
- Ring
* Ring
- defines +, *, -, **, zero, one
- defined in [Spire](https://github.com/non/spire)
- Read: https://en.wikipedia.org/wiki/Ring_(mathematics)
- Note: We chose to restrict ourselves to `Ring` rather than `Field` because division is particularly expensive and nuanced in hardware. Rather than typing `a / b` we think it is better to require users to instantiate a module and think about what's going on.

- Eq
- defines === and =/= (returning chisel Bools!)
- PartialOrder
* Eq
- defines === and =/= (returning Chisel Bools!)
* PartialOrder
- extends Eq
- defines >, <, <=, >= (returning a `ValidIO[ComparisonBundle]` that has `valid` false if the objects are not comparable
- Order
* Order
- extends PartialOrder
- defines >, <, <=, >=, min, max
- Sign
* Sign
- defines abs, isSignZero, isSignPositive, isSignNegative, isSignNonZero, isSignNonPositive, isSignNonNegative
- Real
* Real
- extends Ring with Order with Sign
- defines ceil, round, floor, isWhole
- defines a bunch of conversion methods from ConvertableTo, e.g. fromDouble, fromInt
- Integer
* Integer
- extends Real
- defines mod

----------

Rocket-chip
===============
===========

Integration of dsptools with a rocket-chip based project:

The github project [Rocket Dsp Utils](https://github.com/chick/rocket-dsp-utils) contains useful tools
Expand All @@ -189,6 +185,6 @@ These tools formerly were contained in this repo under the `rocket` sub-director

----------

This code is maintained by [Chick](https://github.com/chick), [Angie](https://github.com/shunshou) and [Paul](https://github.com/grebe). Let us know if you have any questions/feedback!
This code was maintained by [Chick](https://github.com/chick), [Angie](https://github.com/shunshou) and [Paul](https://github.com/grebe). Let us know if you have any questions/feedback!

Copyright (c) 2015 - 2021 The Regents of the University of California. Released under the Modified (3-clause) BSD license.
Copyright (c) 2015 - 2022 The Regents of the University of California. Released under the Apache-2.0 license.
15 changes: 8 additions & 7 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ enablePlugins(SiteScaladocPlugin)
enablePlugins(GhpagesPlugin)

val defaultVersions = Map(
"chisel3" -> "3.5-SNAPSHOT",
"chiseltest" -> "0.5-SNAPSHOT"
"chisel3" -> "3.6-SNAPSHOT",
"chiseltest" -> "0.6-SNAPSHOT"
)

name := "dsptools"

val commonSettings = Seq(
organization := "edu.berkeley.cs",
version := "1.5-SNAPSHOT",
version := "1.6-SNAPSHOT",
git.remoteRepo := "[email protected]:ucb-bar/dsptools.git",
autoAPIMappings := true,
scalaVersion := "2.13.10",
Expand All @@ -23,6 +23,7 @@ val commonSettings = Seq(
"-deprecation",
"-feature",
"-language:reflectiveCalls",
"-Xfatal-warnings",
"-Ymacro-annotations"),
javacOptions ++= Seq("-source", "1.8", "-target", "1.8"),
pomExtra := (<url>http://chisel.eecs.berkeley.edu/</url>
Expand Down Expand Up @@ -78,15 +79,15 @@ val commonSettings = Seq(
val dsptoolsSettings = Seq(
name := "dsptools",
libraryDependencies ++= Seq(
"org.typelevel" %% "spire" % "0.17.0",
"org.scalanlp" %% "breeze" % "1.1",
"org.scalatest" %% "scalatest" % "3.2.+" % "test"
"org.typelevel" %% "spire" % "0.18.0",
"org.scalanlp" %% "breeze" % "2.1.0",
"org.scalatest" %% "scalatest" % "3.2.15" % "test"
),
)

val fixedpointSettings = Seq(
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "3.2.+" % "test",
"org.scalatest" %% "scalatest" % "3.2.15" % "test",
"org.scalatestplus" %% "scalacheck-1-14" % "3.2.2.0" % "test",
)
)
Expand Down
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ addSbtPlugin("com.eed3si9n" % "sbt-sriracha" % "0.1.0")

addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.4")

addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import chisel3._
object CounterWithReset {
def apply(cond: Bool, n: Int, reset: Bool): (UInt, Bool) = {
val c = chisel3.util.Counter(cond, n)
if (n > 1) { when (reset) { c._1 := 0.U } }
if (n > 1) { when(reset) { c._1 := 0.U } }
c
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ package dsptools.counters
import chisel3._
import chisel3.util.RegEnable

object ShiftRegisterWithReset
{
object ShiftRegisterWithReset {

/** Returns the n-cycle delayed version of the input signal.
*
* @param in input to delay
Expand All @@ -16,7 +16,7 @@ object ShiftRegisterWithReset
def apply[T <: Data](in: T, n: Int, reset: T, en: Bool = true.B): T = {
// The order of tests reflects the expected use cases.
if (n != 0) {
RegEnable(apply(in, n-1, reset, en), reset, en)
RegEnable(apply(in, n - 1, reset, en), reset, en)
} else {
in
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/dsptools/dspmath/ExtendedEuclid.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package dsptools.dspmath

object ExtendedEuclid {

/** Extended Euclidean Algorithm
* ax + by = gcd(a, b)
* Inputs: a, b
Expand All @@ -16,4 +17,4 @@ object ExtendedEuclid {
(gcd, x - (b / a) * y, y)
}
}
}
}
24 changes: 14 additions & 10 deletions src/main/scala/dsptools/dspmath/Factorization.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
package dsptools.dspmath

case class RadPow(rad: Int, pow: Int) {

/** `r ^ p` */
def get: Int = BigInt(rad).pow(pow).toInt

/** Factorize i.e. rad = 4, pow = 3 -> Seq(4, 4, 4) */
def factorize: Seq[Int] = Seq.fill(pow)(rad)
}

case class Factorization(supportedRadsUnsorted: Seq[Seq[Int]]) {

/** Supported radices, MSD First */
private val supportedRads = supportedRadsUnsorted.map(_.sorted.reverse)

Expand All @@ -22,17 +25,19 @@ case class Factorization(supportedRadsUnsorted: Seq[Seq[Int]]) {
// Test if n can be factored by each of the supported radices (mod = 0)
// Count # of times it can be factored
var unfactorized = n
val radPows = for (primeGroup <- supportedRads) yield { for (rad <- primeGroup) yield {
var (mod, pow) = (0, 0)
while (mod == 0) {
mod = unfactorized % rad
if (mod == 0) {
pow = pow + 1
unfactorized = unfactorized / rad
val radPows = for (primeGroup <- supportedRads) yield {
for (rad <- primeGroup) yield {
var (mod, pow) = (0, 0)
while (mod == 0) {
mod = unfactorized % rad
if (mod == 0) {
pow = pow + 1
unfactorized = unfactorized / rad
}
}
RadPow(rad, pow)
}
RadPow(rad, pow)
}}
}
// If n hasn't completely been factorized, then an unsupported radix is required
require(unfactorized == 1, s"$n is invalid for supportedRads.")
radPows
Expand Down Expand Up @@ -82,4 +87,3 @@ case class Factorization(supportedRadsUnsorted: Seq[Seq[Int]]) {
}

}

Loading

0 comments on commit 2fa039f

Please sign in to comment.