增加chisel框架
This commit is contained in:
parent
68a30caea2
commit
37c144d66d
|
@ -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/
|
|
@ -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]
|
|
@ -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
|
|
@ -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/`.
|
|
@ -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() }
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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))
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue