diff --git a/.gitignore b/.gitignore index d3df29b..074d9a3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ generated-rtl/ target/ project/ verilog/ + +.metals/ +.scala-build/ +out/ +mill diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..29a0975 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "tools/dsptools"] + path = tools/dsptools + url = https://github.com/ucb-bar/dsptools.git +[submodule "tools/rocket-dsp-utils"] + path = tools/rocket-dsp-utils + url = https://github.com/ucb-bar/rocket-dsp-utils.git +[submodule "tools/cde"] + path = tools/cde + url = https://github.com/chipsalliance/cde.git +[submodule "generators/rocket-chip"] + path = generators/rocket-chip + url = https://github.com/chipsalliance/rocket-chip.git diff --git a/.mill-version b/.mill-version new file mode 100644 index 0000000..13ca94b --- /dev/null +++ b/.mill-version @@ -0,0 +1 @@ +0.11.6 \ No newline at end of file diff --git a/README.md b/README.md index cdb6e46..f62a8d3 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,28 @@ # SDF-FFT Design Generator -[![Build](https://github.com/milovanovic/sdf-fft/actions/workflows/test.yml/badge.svg)](https://github.com/milovanovic/sdf-fft/actions/workflows/test.yml) - The SDF-FFT Generator is a highly parametrizable Single-Path-Delay-Feedback (SDF) Fast Fourier Transform (FFT) hardware accelerator. ## Prerequisites The following software packages should be installed prior to running this project: -* [sbt](http://www.scala-sbt.org) +* [sbt](http://www.scala-sbt.org) or +* [mill](https://mill-build.com) * [Verilator](http://www.veripool.org/wiki/verilator) ## Setup Proposed design generator is intended to be used inside [chipyard](https://github.com/ucb-bar/chipyard) environment as one of the generators located inside `generators/dsp-blocks`. Anyhow, if you want to use this repository standalone then follow instructions below: -* Clone this repository. +* Clone this repository (with submodules). * Switch directory. -* Initialize all tools and submodules. * Compile code, generate verilog or run tests. ``` -git clone https://github.com/milovanovic/sdf-fft.git +git clone --recurse-submodules https://github.com/milovanovic/sdf-fft.git cd sdf-fft -./scripts/init_submodules_and_build_sbt.sh -sbt test +sbt test or ./mill sdf_fft.test ``` -#### Note -The shell script `init_submodules_and_build_sbt.sh`, initializes all tools and generators required to run this project. Besides that, it initializes `bulid.sbt` with all correctly defined dependencies. Versions of tools and generators correspond to chipyard 1.9.1 release. The user can replace versions by changing corresponding checkout commits inside the same script. -The shell script `remove_submodules.sh` runs commands that are the inverse of those in `init_submodules_and_build_sbt.sh`. - ## Documentation * doc/sdf_fft_generator.md - detailed documentation about design generator diff --git a/build.sbt.ignore b/build.sbt similarity index 97% rename from build.sbt.ignore rename to build.sbt index c93335c..f12ed70 100644 --- a/build.sbt.ignore +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val hardfloat = (project in rocketChipDir / "hardfloat") ) ) -lazy val rocketMacros = (project in rocketChipDir / "macros") +lazy val `rocket-macros` = (project in rocketChipDir / "macros") .settings(commonSettings) .settings( libraryDependencies ++= Seq( @@ -97,7 +97,7 @@ lazy val rocketMacros = (project in rocketChipDir / "macros") scalafmtOnCompile := true lazy val rocketchip = freshProject("rocketchip", rocketChipDir) - .dependsOn(hardfloat, rocketMacros, cde) + .dependsOn(hardfloat, `rocket-macros`, cde) .settings(commonSettings) .settings(chiselSettings) .settings( diff --git a/build.sc b/build.sc new file mode 100644 index 0000000..24e2aac --- /dev/null +++ b/build.sc @@ -0,0 +1,87 @@ +// import Mill dependency +import mill._ +import mill.define.Sources +import mill.modules.Util +import mill.scalalib.TestModule.ScalaTest +import scalalib._ +// support BSP +import mill.bsp._ +import os._ + +def scalaVersionString: String = "2.13.10" +def chiselVersionString: String = "3.5.6" + +trait SbtScalaModule extends SbtModule { + def millSourcePath = os.pwd + def scalaVersion = scalaVersionString + def scalacOptions = Seq( + "-language:reflectiveCalls", + "-deprecation", + "-feature", + "-Xcheckinit", + "-unchecked", + "-Ymacro-annotations" + ) + def ivyDeps = T{Agg( + ivy"org.scala-lang:scala-reflect:$scalaVersionString", + ivy"org.json4s::json4s-jackson:3.6.6", + ivy"org.scalatest::scalatest:3.2.0" +)} +} +trait ChiselScalaModule extends SbtScalaModule { m => + override def scalacOptions = super.scalacOptions() ++ Seq("-P:chiselplugin:genBundleElements") + override def ivyDeps = Agg( + ivy"edu.berkeley.cs::chisel3:$chiselVersionString", + ) + def scalacPluginIvyDeps = Agg( + ivy"edu.berkeley.cs:::chisel3-plugin:$chiselVersionString", + ) + object test extends SbtModuleTests with TestModule.ScalaTest { + def ivyDeps = m.ivyDeps() ++ Agg( + ivy"edu.berkeley.cs::chisel-iotesters:2.5.1" + ) + } +} +object sdf_fft extends ChiselScalaModule { + def moduleDeps = Seq( + rocketchip, + rocket_dsp_utils + ) +} + +object rocketchip extends SbtScalaModule { + override def millSourcePath = os.pwd / "generators" / "rocket-chip" + def moduleDeps = Seq( + hardfloat, rocketMacros, cde + ) + object rocketMacros extends SbtScalaModule { + override def millSourcePath = os.pwd / "generators" / "rocket-chip" / "macros" + } +} +object hardfloat extends ChiselScalaModule { + override def millSourcePath = os.pwd / "generators" / "rocket-chip" / "hardfloat" +} +object cde extends SbtScalaModule { + override def millSourcePath = os.pwd / "tools" / "cde" + def sources = T.sources{ + super.sources() ++ Seq(PathRef(millSourcePath / "cde" / "src" / "chipsalliance" / "rocketchip")) + } +} +object rocket_dsp_utils extends SbtScalaModule { + override def millSourcePath = os.pwd / "tools" / "rocket-dsp-utils" + def moduleDeps = Seq( + rocketchip, cde, dsptools + ) +} +object dsptools extends ChiselScalaModule { + override def millSourcePath = os.pwd / "tools" / "dsptools" + override def ivyDeps = Agg( + ivy"edu.berkeley.cs::chisel3:$chiselVersionString", + ivy"org.scalatest::scalatest:3.2.+", + ivy"org.typelevel::spire:0.17.0", + ivy"org.scalanlp::breeze:1.1", + ivy"junit:junit:4.13", + ivy"org.scalacheck::scalacheck:1.14.3", + ivy"edu.berkeley.cs::chisel-iotesters:2.5.1" + ) +} \ No newline at end of file diff --git a/generators/rocket-chip b/generators/rocket-chip new file mode 160000 index 0000000..25e2c63 --- /dev/null +++ b/generators/rocket-chip @@ -0,0 +1 @@ +Subproject commit 25e2c63567689ebe1fc5e60fdfe3375a8dba071c diff --git a/scripts/init_submodules_and_build_sbt.sh b/scripts/init_submodules_and_build_sbt.sh deleted file mode 100755 index 6b5c758..0000000 --- a/scripts/init_submodules_and_build_sbt.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -# exit script if any command fails -set -e -set -o pipefail - -CHIPYARD_VERSION="1.9.1" -DSPTOOLS_COMMIT=5b1e733 -ROCKET_COMMIT=25e2c63 -FIRESIM_COMMIT=3ae68ec -ROCKET_DSP_COMMIT=fe641d1 -CDE_COMMIT=384c06b - -git submodule add https://github.com/ucb-bar/dsptools.git tools/dsptools -cd tools/dsptools -git checkout $DSPTOOLS_COMMIT -cd ../.. -git submodule add https://github.com/ucb-bar/rocket-dsp-utils.git tools/rocket-dsp-utils -cd tools/rocket-dsp-utils -git checkout $ROCKET_DSP_COMMIT -cd ../.. - -git submodule add https://github.com/chipsalliance/cde.git tools/cde -cd tools/cde -git checkout $CDE_COMMIT -cd ../.. - -git submodule add https://github.com/chipsalliance/rocket-chip.git generators/rocket-chip -cd generators/rocket-chip -git checkout $ROCKET_COMMIT - -git submodule add https://github.com/firesim/firesim.git sims/firesim -cd sims/firesim -git checkout $FIRESIM_COMMIT -cd ../.. -git config --local submodule.sims/firesim.update none -git submodule update --init --recursive -git config --local --unset-all submodule.sims/firesim.update -git submodule update --init sims/firesim -cd ../.. -mv build.sbt.ignore build.sbt - -if [ -d project ]; then - echo "Directory project already exists" -else - mkdir project -fi - -# add plugins -echo -e 'addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")\naddSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.21")\naddSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.3")\naddSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")\naddSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3")' > ./project/plugins.sbt diff --git a/scripts/remove_submodules.sh b/scripts/remove_submodules.sh deleted file mode 100755 index cb0d729..0000000 --- a/scripts/remove_submodules.sh +++ /dev/null @@ -1,25 +0,0 @@ -git submodule deinit -f ./generators/rocket-chip/ -rm -rf .git/modules/generators/rocket-chip/ -git rm -f generators/rocket-chip/ - -git submodule deinit -f tools/rocket-dsp-utils/ -rm -rf .git/modules/tools/rocket-dsp-utils/ -git rm -f tools/rocket-dsp-utils/ - -git submodule deinit -f tools/dsptools/ -rm -rf .git/modules/tools/dsptools/ -git rm -f tools/dsptools/ - -git submodule deinit -f tools/cde/ -rm -rf .git/modules/tools/cde/ -git rm -f tools/cde/ - -#git submodule deinit -f sims/firesim -#rm -rf .git/modules/sims/firesim -#git rm -f sims/firesim - -git restore --staged .gitmodules -rm .gitmodules - -mv build.sbt build.sbt.ignore -rm project/plugins.sbt diff --git a/src/main/scala/SDFChainRadix2.scala b/src/main/scala/SDFChainRadix2.scala index dc3fae4..64a6d8c 100644 --- a/src/main/scala/SDFChainRadix2.scala +++ b/src/main/scala/SDFChainRadix2.scala @@ -5,7 +5,6 @@ package fft import chisel3._ import chisel3.util._ import chisel3.experimental.FixedPoint -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import dsptools._ import dsptools.numbers._ @@ -15,7 +14,7 @@ import scala.math.{pow, Pi} import dspblocks.CounterWithReset import craft.ShiftRegisterMem -class SDFChainRadix2[T <: Data: Real: BinaryRepresentation](val params: FFTParams[T]) extends Module with HasIO { +class SDFChainRadix2[T <: Data: Real: BinaryRepresentation](val params: FFTParams[T]) extends Module { params.checkNumPointsPow2() require(Seq(DITDecimType, DIFDecimType).contains(params.decimType), s"""Decimation type must either be dit or dif""") val io = IO(FFTIO(params)) @@ -150,8 +149,7 @@ class SDFChainRadix2[T <: Data: Real: BinaryRepresentation](val params: FFTParam case ((delayLog2, delay), ind) => { val stageparams = params.copy(protoIQ = params.protoIQstages(ind)) val useGrow = if (stageparams.expandLogic(ind) == 1) true else false - val stage = - Module(new SDFStageRadix2(stageparams, delay = delay, useGrow, params.keepMSBorLSB(ind), params.singlePortSRAM)) + val stage = Module(new SDFStageRadix2(stageparams, delay = delay, useGrow, params.keepMSBorLSB(ind))) if (params.keepMSBorLSBReg) { stage.io.scale.get := scaleBflyReg(ind) } @@ -182,8 +180,8 @@ class SDFChainRadix2[T <: Data: Real: BinaryRepresentation](val params: FFTParam enableVector(currStage) := stageEn //collects all enable signals cntr_wires(currStage) := stageCnt //collects all shifted counter values ( - ShiftRegisterWithReset(stageEn, outputLatency, false.B, state === sIdle, true.B), - ShiftRegisterWithReset(stageCnt, outputLatency, 0.U, state === sIdle, true.B) + ShiftRegisterWithReset(stageEn, outputLatency, resetData = false.B, reset = state === sIdle, en = true.B), + ShiftRegisterWithReset(stageCnt, outputLatency, resetData = 0.U, reset = state === sIdle, en = true.B) ) } } @@ -246,7 +244,13 @@ class SDFChainRadix2[T <: Data: Real: BinaryRepresentation](val params: FFTParam val output = if (params.decimType == DIFDecimType) outputWires.last else outputWires(regNumStages - 1.U) val latency = (params.numAddPipes + complexMulLatency) * log2Up(params.numPoints) - val outValid = ShiftRegisterWithReset(validOutBeforePipes, outputLatency, false.B, state === sIdle, true.B) + val outValid = ShiftRegisterWithReset( + validOutBeforePipes, + outputLatency, + resetData = false.B, + reset = state_next === sIdle, + en = true.B + ) val outQueue = Module( new Queue(chiselTypeOf(sdf_stages.last.io.out), entries = latency + 1, pipe = true, flow = true) @@ -257,12 +261,7 @@ class SDFChainRadix2[T <: Data: Real: BinaryRepresentation](val params: FFTParam val scalar = if (params.expandLogic.sum == 0 && !params.keepMSBorLSBReg) ConvertableTo[T].fromDouble(1.0) else ConvertableTo[T].fromDouble(1.0 / params.numPoints.toDouble) - io.in.ready := ShiftRegister( - (~initialOutDone), - outputLatency, - false.B, - true.B - ) || (io.out.ready && (state =/= sFlush)) + io.in.ready := (~initialInDone) || (io.out.ready && (state =/= sFlush)) if (latency == 0) { when(fftOrifft === true.B) { @@ -301,19 +300,16 @@ class SDFStageRadix2IO[T <: Data: Ring](params: FFTParams[T]) extends Bundle { // control signals val cntr = Input(UInt(log2Up(params.numPoints).W)) val en = Input(Bool()) - - //override def cloneType: this.type = SDFStageRadix2IO(params).asInstanceOf[this.type] } object SDFStageRadix2IO { def apply[T <: Data: Ring](params: FFTParams[T]): SDFStageRadix2IO[T] = new SDFStageRadix2IO(params) } class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( - val params: FFTParams[T], - val delay: Int, - val useGrow: Boolean, - val keepMSBOrLSB: Boolean, - val singlePortSRAM: Boolean = false) + val params: FFTParams[T], + val delay: Int, + val useGrow: Boolean, + val keepMSBOrLSB: Boolean) extends Module { params.checkNumPointsPow2() require(isPow2(delay) && delay >= 1, "delay must be a power of 2 greater than or equal to 1") @@ -331,7 +327,7 @@ class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( val totalDataWidth = params.protoIQ.real.getWidth * 2 val twiddles_rom = Wire(Vec(delay, params.protoTwiddle.cloneType)) val tw = - if (params.decimType == DIFDecimType) ShiftRegister(twiddles_rom(io.cntr), params.numAddPipes, true.B) + if (params.decimType == DIFDecimType) ShiftRegister(twiddles_rom(io.cntr), params.numAddPipes, en = true.B) else twiddles_rom(io.cntr) DspContext.withTrimType(Convergent) { @@ -365,8 +361,8 @@ class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( ) { io.in.context_*(tw) } inpOuttw := DspContext.withTrimType(params.trimType) { mulres.trimBinary(bpos) } } - inpOut := ShiftRegister(io.in, complexMulLatency, true.B) - when(ShiftRegister(io.cntr > delay, complexMulLatency, true.B)) { + inpOut := ShiftRegister(io.in, complexMulLatency, en = true.B) + when(ShiftRegister(io.cntr > delay, complexMulLatency, en = true.B)) { inp := inpOuttw }.otherwise { inp := inpOut @@ -374,7 +370,7 @@ class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( io.out := out } else { inp := io.in - val multipleSignal = ShiftRegister(io.cntr < delay.U && io.cntr =/= 0.U, params.numAddPipes, true.B) + val multipleSignal = ShiftRegister(io.cntr < delay.U && io.cntr =/= 0.U, params.numAddPipes, en = true.B) val ioOuttw = Wire(io.out.cloneType) val ioOut = Wire(io.out.cloneType) @@ -389,8 +385,8 @@ class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( ) { out.context_*(tw) } ioOuttw := DspContext.withTrimType(params.trimType) { mulres.trimBinary(bpos) } } - ioOut := ShiftRegister(out, complexMulLatency, true.B) - when(ShiftRegister(multipleSignal, complexMulLatency, true.B)) { + ioOut := ShiftRegister(out, complexMulLatency, en = true.B) + when(ShiftRegister(multipleSignal, complexMulLatency, en = true.B)) { io.out := ioOuttw }.otherwise { io.out := ioOut @@ -403,7 +399,7 @@ class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( if (params.decimType == DIFDecimType) { load_input := io.cntr < delay.U } else { - load_input := ShiftRegister(io.cntr < delay.U, complexMulLatency, false.B, true.B) + load_input := ShiftRegister(io.cntr < delay.U, complexMulLatency, resetData = false.B, en = true.B) } val shift_in = Wire(inp.cloneType) shift_in := Mux(load_input, inp, butterfly_outputs(1)) @@ -411,41 +407,25 @@ class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( if (params.decimType == DIFDecimType) { if (params.minSRAMdepth < delay) { - shift_out.real := ShiftRegisterMem( - shift_in.real, - delay, - io.en, - use_sp_mem = singlePortSRAM, - name = "SRAM" + "_depth_" + delay.toString + "_width_" + totalDataWidth.toString + s"_real" + s"_mem" - ) - shift_out.imag := ShiftRegisterMem( - shift_in.imag, + shift_out := ShiftRegisterMem( + shift_in, delay, - io.en, - use_sp_mem = singlePortSRAM, - name = "SRAM" + "_depth_" + delay.toString + "_width_" + totalDataWidth.toString + s"_imag" + s"_mem" + en = io.en, + name = "SRAM" + "_depth_" + delay.toString + "_width_" + totalDataWidth.toString + s"_mem" ) } else { - shift_out := ShiftRegister(shift_in, delay, io.en) + shift_out := ShiftRegister(shift_in, delay, en = io.en) } } else { if (params.minSRAMdepth < delay) { - shift_out.real := ShiftRegisterMem( - shift_in.real, + shift_out := ShiftRegisterMem( + shift_in, delay, - ShiftRegister(io.en, complexMulLatency, true.B), - use_sp_mem = singlePortSRAM, - name = "SRAM" + "_depth_" + delay.toString + "_width_" + totalDataWidth.toString + s"_real" + s"_mem" - ) - shift_out.imag := ShiftRegisterMem( - shift_in.imag, - delay, - ShiftRegister(io.en, complexMulLatency, true.B), - use_sp_mem = singlePortSRAM, - name = "SRAM" + "_depth_" + delay.toString + "_width_" + totalDataWidth.toString + s"_imag" + s"_mem" + en = ShiftRegister(io.en, complexMulLatency, true.B), + name = "SRAM" + "_depth_" + delay.toString + "_width_" + totalDataWidth.toString + s"_mem" ) } else { - shift_out := ShiftRegister(shift_in, delay, ShiftRegister(io.en, complexMulLatency, true.B)) + shift_out := ShiftRegister(shift_in, delay, en = ShiftRegister(io.en, complexMulLatency, true.B)) } } //val shift_out = if (params.decimType == DIFDecimType) ShiftRegisterMem(shift_in, delay, en = io.en) else ShiftRegisterMem(shift_in, delay, en = ShiftRegister(io.en, complexMulLatency, true.B)) @@ -495,20 +475,22 @@ class SDFStageRadix2[T <: Data: Real: BinaryRepresentation]( if (params.overflowReg) { io.overflow.get := overflow } - val feedback = ShiftRegister(shift_out, params.numAddPipes, true.B) - val butt_out_0 = ShiftRegister(butterfly_outputs(0), params.numAddPipes, true.B) + val feedback = ShiftRegister(shift_out, params.numAddPipes, en = true.B) + val butt_out_0 = ShiftRegister(butterfly_outputs(0), params.numAddPipes, en = true.B) val load_output = - if (params.decimType == DIFDecimType) ShiftRegister(load_input, params.numAddPipes, false.B, true.B) - else ShiftRegister(io.cntr < delay.U, params.numAddPipes + complexMulLatency, false.B, true.B) + if (params.decimType == DIFDecimType) + ShiftRegister(load_input, params.numAddPipes, resetData = false.B, en = true.B) + else ShiftRegister(io.cntr < delay.U, params.numAddPipes + complexMulLatency, resetData = false.B, en = true.B) out := Mux(load_output, feedback, butt_out_0) } -object SDFChainRadix2SimpleApp extends App { - val params = FFTParams.fixed( +/*object SDFChainRadix2SimpleApp extends App +{ + val params = FFTParams.fixed ( dataWidth = 16, twiddleWidth = 16, - numPoints = 8, + numPoints = 8 , decimType = DITDecimType, numAddPipes = 1, numMulPipes = 1, @@ -519,9 +501,5 @@ object SDFChainRadix2SimpleApp extends App { keepMSBorLSB = Array.fill(log2Up(8))(true), binPoint = 0 ) - - (new ChiselStage).execute( - Array("--target-dir", "verilog/SDFChainRadix2Simple"), - Seq(ChiselGeneratorAnnotation(() => new SDFChainRadix2(params))) - ) -} + chisel3.Driver.execute(args,()=>new SDFChainRadix2(params)) +}*/ diff --git a/tools/cde b/tools/cde new file mode 160000 index 0000000..384c06b --- /dev/null +++ b/tools/cde @@ -0,0 +1 @@ +Subproject commit 384c06b8d45c8184ca2f3fba2f8e78f79d2c1b51 diff --git a/tools/dsptools b/tools/dsptools new file mode 160000 index 0000000..5b1e733 --- /dev/null +++ b/tools/dsptools @@ -0,0 +1 @@ +Subproject commit 5b1e733596a39f6960bf9a7c1897d82912372766 diff --git a/tools/rocket-dsp-utils b/tools/rocket-dsp-utils new file mode 160000 index 0000000..fe641d1 --- /dev/null +++ b/tools/rocket-dsp-utils @@ -0,0 +1 @@ +Subproject commit fe641d1c346d5605f95d235e8c75d0baac7fa6d8