增加chisel框架

This commit is contained in:
Liphen 2023-11-07 13:41:15 +08:00
parent 68a30caea2
commit 37c144d66d
9 changed files with 319 additions and 0 deletions

22
chisel/.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
*.*
*
!*/
!Makefile
!*.mk
!*.scala
!*.[cSh]
!*.v
!*.cpp
!*.cc
!.gitignore
!.scalafmt.conf
!build.sc
!README.md
build/
# mill
out/
.bsp/
.idea/
.idea_modules/
test_run_dir/

33
chisel/.scalafmt.conf Normal file
View File

@ -0,0 +1,33 @@
version = 2.6.4
maxColumn = 120
align = most
continuationIndent.defnSite = 2
assumeStandardLibraryStripMargin = true
docstrings = ScalaDoc
lineEndings = preserve
includeCurlyBraceInSelectChains = false
danglingParentheses = true
align.tokens.add = [
{
code = ":"
},
{
code = ":="
},
{
code = "="
}
]
newlines.alwaysBeforeCurlyBraceLambdaParams = false
newlines.alwaysBeforeMultilineDef = false
newlines.implicitParamListModifierForce = [before]
verticalMultiline.atDefnSite = true
optIn.annotationNewlines = true
rewrite.rules = [SortImports, PreferCurlyFors, AvoidInfix]

37
chisel/Makefile Normal file
View File

@ -0,0 +1,37 @@
BUILD_DIR = ./build
export PATH := $(PATH):$(abspath ./utils)
test:
mill -i __.test
verilog:
$(call git_commit, "generate verilog")
mkdir -p $(BUILD_DIR)
mill -i __.test.runMain Elaborate -td $(BUILD_DIR)
help:
mill -i __.test.runMain Elaborate --help
compile:
mill -i __.compile
bsp:
mill -i mill.bsp.BSP/install
reformat:
mill -i __.reformat
checkformat:
mill -i __.checkFormat
clean:
-rm -rf $(BUILD_DIR)
.PHONY: test verilog help compile bsp reformat checkformat clean
sim:
$(call git_commit, "sim RTL") # DO NOT REMOVE THIS LINE!!!
@echo "Write this Makefile by yourself."
-include ../Makefile

37
chisel/README.md Normal file
View File

@ -0,0 +1,37 @@
Chisel Project Template
=======================
Another version of the [Chisel template](https://github.com/ucb-bar/chisel-template) supporting mill.
mill is another Scala/Java build tool without obscure DSL like SBT. It is much faster than SBT.
Contents at a glance:
* `.gitignore` - helps Git ignore junk like generated files, build products, and temporary files.
* `build.sc` - instructs mill to build the Chisel project
* `Makefile` - rules to call mill
* `playground/src/GCD.scala` - GCD source file
* `playground/src/DecoupledGCD.scala` - another GCD source file
* `playground/src/Elaborate.scala` - wrapper file to call chisel command with the GCD module
* `playground/test/src/GCDSpec.scala` - GCD tester
Feel free to rename or delete files under `playground/` or use them as a reference/template.
## Getting Started
First, install mill by referring to the documentation [here](https://com-lihaoyi.github.io/mill).
To run all tests in this design (recommended for test-driven development):
```bash
make test
```
To generate Verilog:
```bash
make verilog
```
## Change FIRRTL Compiler
You can change the FIRRTL compiler between SFC (Scala-based FIRRTL compiler) and
MFC (MLIR-based FIRRTL compiler) by modifying the `useMFC` variable in `playground/src/Elaborate.scala`.
The latter one requires `firtool`, which is included under `utils/`.

37
chisel/build.sc Normal file
View File

@ -0,0 +1,37 @@
// import Mill dependency
import mill._
import mill.scalalib._
import mill.scalalib.scalafmt.ScalafmtModule
import mill.scalalib.TestModule.ScalaTest
// support BSP
import mill.bsp._
object playground extends ScalaModule with ScalafmtModule { m =>
val useChisel5 = true
override def scalaVersion = "2.13.10"
override def scalacOptions = Seq(
"-language:reflectiveCalls",
"-deprecation",
"-feature",
"-Xcheckinit"
)
override def ivyDeps = Agg(
if (useChisel5) ivy"org.chipsalliance::chisel:5.0.0" else
ivy"edu.berkeley.cs::chisel3:3.6.0",
)
override def scalacPluginIvyDeps = Agg(
if (useChisel5) ivy"org.chipsalliance:::chisel-plugin:5.0.0" else
ivy"edu.berkeley.cs:::chisel3-plugin:3.6.0",
)
object test extends ScalaTests with ScalaTest {
override def ivyDeps = m.ivyDeps() ++ Agg(
ivy"com.lihaoyi::utest:0.8.1",
if (useChisel5) ivy"edu.berkeley.cs::chiseltest:5.0.0" else
ivy"edu.berkeley.cs::chiseltest:0.6.0",
)
}
def repositoriesTask = T.task { Seq(
coursier.MavenRepository("https://maven.aliyun.com/repository/central"),
coursier.MavenRepository("https://repo.scala-sbt.org/scalasbt/maven-releases"),
) ++ super.repositoriesTask() }
}

View File

@ -0,0 +1,69 @@
import chisel3._
import chisel3.util.Decoupled
class GcdInputBundle(val w: Int) extends Bundle {
val value1 = UInt(w.W)
val value2 = UInt(w.W)
}
class GcdOutputBundle(val w: Int) extends Bundle {
val value1 = UInt(w.W)
val value2 = UInt(w.W)
val gcd = UInt(w.W)
}
/**
* Compute Gcd using subtraction method.
* Subtracts the smaller from the larger until register y is zero.
* value input register x is then the Gcd.
* Unless first input is zero then the Gcd is y.
* Can handle stalls on the producer or consumer side
*/
class DecoupledGcd(width: Int) extends Module {
val input = IO(Flipped(Decoupled(new GcdInputBundle(width))))
val output = IO(Decoupled(new GcdOutputBundle(width)))
val xInitial = Reg(UInt())
val yInitial = Reg(UInt())
val x = Reg(UInt())
val y = Reg(UInt())
val busy = RegInit(false.B)
val resultValid = RegInit(false.B)
input.ready := !busy
output.valid := resultValid
output.bits := DontCare
when(busy) {
when(x > y) {
x := x - y
}.otherwise {
y := y - x
}
when(x === 0.U || y === 0.U) {
when(x === 0.U) {
output.bits.gcd := y
}.otherwise {
output.bits.gcd := x
}
output.bits.value1 := xInitial
output.bits.value2 := yInitial
resultValid := true.B
when(output.ready && resultValid) {
busy := false.B
resultValid := false.B
}
}
}.otherwise {
when(input.valid) {
val bundle = input.deq()
x := bundle.value1
y := bundle.value2
xInitial := bundle.value1
yInitial := bundle.value2
busy := true.B
}
}
}

View File

@ -0,0 +1,7 @@
import circt.stage._
object Elaborate extends App {
def top = new GCD()
val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top))
(new ChiselStage).execute(args, generator :+ CIRCTTargetAnnotation(CIRCTTarget.Verilog))
}

View File

@ -0,0 +1,29 @@
import chisel3._
/**
* Compute GCD using subtraction method.
* Subtracts the smaller from the larger until register y is zero.
* value in register x is then the GCD
*/
class GCD extends Module {
val io = IO(new Bundle {
val value1 = Input(UInt(16.W))
val value2 = Input(UInt(16.W))
val loadingValues = Input(Bool())
val outputGCD = Output(UInt(16.W))
val outputValid = Output(Bool())
})
val x = Reg(UInt())
val y = Reg(UInt())
when(x > y) { x := x - y }.otherwise { y := y - x }
when(io.loadingValues) {
x := io.value1
y := io.value2
}
io.outputGCD := x
io.outputValid := y === 0.U
}

View File

@ -0,0 +1,48 @@
import chisel3._
import chiseltest._
import chisel3.experimental.BundleLiterals._
import utest._
/**
* This is a trivial example of how to run this Specification
* From within sbt use:
* {{{
* testOnly gcd.GcdDecoupledTester
* }}}
* From a terminal shell use:
* {{{
* sbt 'testOnly gcd.GcdDecoupledTester'
* }}}
*/
object GCDSpec extends ChiselUtestTester {
val tests = Tests {
test("GCD") {
testCircuit(new DecoupledGcd(16)) {
dut =>
dut.input.initSource()
dut.input.setSourceClock(dut.clock)
dut.output.initSink()
dut.output.setSinkClock(dut.clock)
val testValues = for {x <- 0 to 10; y <- 0 to 10} yield (x, y)
val inputSeq = testValues.map { case (x, y) => (new GcdInputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U) }
val resultSeq = testValues.map { case (x, y) =>
(new GcdOutputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U, _.gcd -> BigInt(x).gcd(BigInt(y)).U)
}
fork {
// push inputs into the calculator, stall for 11 cycles one third of the way
val (seq1, seq2) = inputSeq.splitAt(resultSeq.length / 3)
dut.input.enqueueSeq(seq1)
dut.clock.step(11)
dut.input.enqueueSeq(seq2)
}.fork {
// retrieve computations from the calculator, stall for 10 cycles one half of the way
val (seq1, seq2) = resultSeq.splitAt(resultSeq.length / 2)
dut.output.expectDequeueSeq(seq1)
dut.clock.step(10)
dut.output.expectDequeueSeq(seq2)
}.join()
}
}
}
}