diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh
index bfb63a33..2ff81ef1 100755
--- a/.circleci/defaults.sh
+++ b/.circleci/defaults.sh
@@ -49,7 +49,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
# key value store to get the build groups
declare -A grouping
-grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad"
+grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad chipyard-fftgenerator"
grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif"
grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
grouping["group-tracegen"]="tracegen tracegen-boom"
@@ -81,6 +81,7 @@ mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig"
mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig"
mapping["chipyard-multiclock-rocket"]=" CONFIG=MulticlockRocketConfig"
mapping["chipyard-nomem-scratchpad"]=" CONFIG=MMIOScratchpadOnlyRocketConfig"
+mapping["chipyard-fftgenerator"]=" CONFIG=FFTRocketConfig"
mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests"
mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests"
diff --git a/.github/scripts/defaults.sh b/.github/scripts/defaults.sh
index 5d33cbf7..25bffb6a 100755
--- a/.github/scripts/defaults.sh
+++ b/.github/scripts/defaults.sh
@@ -39,7 +39,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
declare -A grouping
grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad"
grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif"
-grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
+grouping["group-accels"]="chipyard-fftgenerator chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
grouping["group-tracegen"]="tracegen tracegen-boom"
grouping["group-other"]="icenet testchipip"
grouping["group-fpga"]="arty vcu118"
@@ -69,6 +69,7 @@ mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig"
mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig"
mapping["chipyard-multiclock-rocket"]=" CONFIG=MulticlockRocketConfig"
mapping["chipyard-nomem-scratchpad"]=" CONFIG=MMIOScratchpadOnlyRocketConfig"
+mapping["chipyard-fftgenerator"]=" CONFIG=FFTRocketConfig"
mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests"
mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests"
diff --git a/.github/scripts/run-tests.sh b/.github/scripts/run-tests.sh
index e5bdf99c..bc344c1a 100755
--- a/.github/scripts/run-tests.sh
+++ b/.github/scripts/run-tests.sh
@@ -111,6 +111,10 @@ case $1 in
make -C $LOCAL_CHIPYARD_DIR/tests
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} BINARY=$LOCAL_CHIPYARD_DIR/tests/nvdla.riscv run-binary-fast
;;
+ chipyard-fftgenerator)
+ make -C $LOCAL_CHIPYARD_DIR/tests
+ make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} BINARY=$LOCAL_CHIPYARD_DIR/tests/fft.riscv run-binary-fast
+ ;;
icenet)
make run-binary-fast BINARY=none -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]}
;;
diff --git a/.github/workflows/chipyard-run-tests.yml b/.github/workflows/chipyard-run-tests.yml
index 560cd142..245bfd74 100644
--- a/.github/workflows/chipyard-run-tests.yml
+++ b/.github/workflows/chipyard-run-tests.yml
@@ -375,6 +375,26 @@ jobs:
project-key: "chipyard-sodor"
- uses: ./.github/actions/job-end
+ chipyard-fftgenerator-run-tests:
+ name: chipyard-fftgenerator-run-tests
+ needs: prepare-chipyard-accels
+ runs-on: ubuntu-latest
+ container:
+ image: ucbbar/chipyard-ci-image:554b436
+ options: --entrypoint /bin/bash
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - uses: ./.github/actions/job-start
+ id: job-start
+ - name: Run tests
+ if: steps.job-start.outputs.run_result != 'success'
+ uses: ./.github/actions/run-tests
+ with:
+ group-key: "group-accels"
+ project-key: "chipyard-fftgenerator"
+ - uses: ./.github/actions/job-end
+
chipyard-dmirocket-run-tests:
name: chipyard-dmirocket-run-tests
needs: prepare-chipyard-peripherals
@@ -717,7 +737,7 @@ jobs:
name: "all tests passed"
needs: [commit-on-master-check, tutorial-setup-check, documentation-check,
chipyard-rocket-run-tests, chipyard-hetero-run-tests, chipyard-boom-run-tests, chipyard-cva6-run-tests, chipyard-ibex-run-tests,
- chipyard-sodor-run-tests, chipyard-dmirocket-run-tests, chipyard-spiflashwrite-run-tests,
+ chipyard-sodor-run-tests, chipyard-dmirocket-run-tests, chipyard-spiflashwrite-run-tests, chipyard-fftgenerator-run-tests,
chipyard-spiflashread-run-tests, chipyard-lbwif-run-tests, chipyard-sha3-run-tests,
chipyard-streaming-fir-run-tests, chipyard-streaming-passthrough-run-tests, chipyard-hwacha-run-tests,
chipyard-gemmini-run-tests, chipyard-nvdla-run-tests,
diff --git a/.gitmodules b/.gitmodules
index 76e9f804..11ca0d5a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -131,3 +131,6 @@
[submodule "generators/ibex"]
path = generators/ibex
url = https://github.com/ucb-bar/ibex-wrapper
+[submodule "generators/fft-generator"]
+ path = generators/fft-generator
+ url = https://github.com/ucb-bar/FFTGenerator.git
diff --git a/build.sbt b/build.sbt
index 5d590717..fc144862 100644
--- a/build.sbt
+++ b/build.sbt
@@ -145,7 +145,12 @@ lazy val chipyard = (project in file("generators/chipyard"))
.dependsOn(testchipip, rocketchip, boom, hwacha, sifive_blocks, sifive_cache, iocell,
sha3, // On separate line to allow for cleaner tutorial-setup patches
dsptools, `rocket-dsp-utils`,
- gemmini, icenet, tracegen, cva6, nvdla, sodor, ibex)
+ gemmini, icenet, tracegen, cva6, nvdla, sodor, ibex, fft_generator)
+ .settings(libraryDependencies ++= rocketLibDeps.value)
+ .settings(commonSettings)
+
+lazy val fft_generator = (project in file("generators/fft-generator"))
+ .dependsOn(rocketchip, `rocket-dsp-utils`)
.settings(libraryDependencies ++= rocketLibDeps.value)
.settings(chiselSettings)
.settings(commonSettings)
diff --git a/docs/Generators/fft.rst b/docs/Generators/fft.rst
new file mode 100644
index 00000000..4ced93df
--- /dev/null
+++ b/docs/Generators/fft.rst
@@ -0,0 +1,63 @@
+FFT Generator
+====================================
+
+The FFT generator is a parameterizable fft accelerator.
+
+Configuration
+--------------------------
+The following configuration creates an 8-point FFT:
+
+.. literalinclude:: ../../generators/chipyard/src/main/scala/config/RocketConfigs.scala
+ :language: scala
+ :start-after: DOC include start: FFTRocketConfig
+ :end-before: DOC include end: FFTRocketConfig
+
+:code:`baseAddress` specifies the starting address of the FFT's read and write lanes. The FFT write lane is always located at :code:`baseAddress`. There is 1 read lane per output point; since this config specifies an 8-point FFT, there will be 8 read lanes. Read lane :code:`i` (which can be loaded from to retrieve output point :code:`i`) will be located at :code:`baseAddr + 64bits (assuming 64bit system) + (i * 8)`. :code:`baseAddress` should be 64-bit aligned
+
+:code:`width` is the size of input points in binary. A width of :code:`w` means that each point will have :code:`w` bits for the real component and :code:`w` bits for the imaginary component, yielding a total of `2w` bits per point. :code:`decPt` is the location of the decimal point in the fixed-precision representation of each point's real and imaginary value. In the Config above, each point is `32` bits wide, with `16` bits used to represent the real component and `16` bits used to represent the imaginary component. Within the `16` bits for each component, the `8` LSB are used to represent the decimal component of the value and the remaining (8) MSB are used to represent the integer component. Both the real and imaginary components use a fixed-precision representation.
+
+To build a simulation of this example Chipyard config, run the following commands:
+
+.. code-block:: shell
+
+ cd sims/verilator # or "cd sims/vcs"
+ make CONFIG=FFTRocketConfig
+
+Usage and Testing
+--------------------------
+
+Points are passed into the FFT via the single write lane. In C pseudocode, this might look like:
+
+.. code-block:: C
+
+ for (int i = 0; i < num_points; i++) {
+ // FFT_WRITE_LANE = baseAddress
+ uint32_t write_val = points[i];
+ volatile uint32_t* ptr = (volatile uint32_t*) FFT_WRITE_LANE;
+ *ptr = write_val;
+ }
+
+Once the correct number of inputs are passed in (in the config above, 8 values would be passed in), the read lanes can be read from (again in C pseudocode):
+
+.. code-block:: C
+
+ for (int i = 0; i < num_points; i++) {
+ // FFT_RD_LANE_BASE = baseAddress + 64bits (for write lane)
+ volatile uint32_t* ptr_0 = (volatile uint32_t*) (FFT_RD_LANE_BASE + (i * 8));
+ uint32_t read_val = *ptr_0;
+ }
+
+The :code:`fft.c` test file in the :code:`tests/` directory can be used to verify the fft's functionality on an SoC built with :code:`FFTRocketConfig`.
+
+Acknowledgements
+--------------------------
+The code for the FFT Generator was adapted from the ADEPT Lab at UC Berkeley's `Hydra Spine `_ project.
+
+Authors for the original project (in no particular order):
+
+* James Dunn, UC Berkeley (dunn [at] eecs [dot] berkeley [dot] edu)
+ * :code:`Deserialize.scala`
+ * :code:`Tail.scala`
+ * :code:`Unscramble.scala`
+* Stevo Bailey (stevo.bailey [at] berkeley [dot] edu)
+ * :code:`FFT.scala`
diff --git a/docs/Generators/index.rst b/docs/Generators/index.rst
index 22d7ad40..27e18e77 100644
--- a/docs/Generators/index.rst
+++ b/docs/Generators/index.rst
@@ -29,6 +29,7 @@ so changes to the generators themselves will automatically be used when building
SHA3
CVA6
Ibex
+ fft
NVDLA
Sodor
diff --git a/generators/chipyard/src/main/scala/DigitalTop.scala b/generators/chipyard/src/main/scala/DigitalTop.scala
index ba094163..0d751969 100644
--- a/generators/chipyard/src/main/scala/DigitalTop.scala
+++ b/generators/chipyard/src/main/scala/DigitalTop.scala
@@ -32,6 +32,7 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
with chipyard.example.CanHavePeripheryStreamingPassthrough // Enables optionally adding the DSPTools streaming-passthrough example widget
with nvidia.blocks.dla.CanHavePeripheryNVDLA // Enables optionally having an NVDLA
with chipyard.clocking.HasChipyardPRCI // Use Chipyard reset/clock distribution
+ with fftgenerator.CanHavePeripheryFFT // Enables optionally having an MMIO-based FFT block
{
override lazy val module = new DigitalTopModule(this)
}
diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala
index 3b3bb597..b1719773 100644
--- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala
+++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala
@@ -21,6 +21,13 @@ class TinyRocketConfig extends Config(
new freechips.rocketchip.subsystem.With1TinyCore ++ // single tiny rocket-core
new chipyard.config.AbstractConfig)
+// DOC include start: FFTRocketConfig
+class FFTRocketConfig extends Config(
+ new fftgenerator.WithFFTGenerator(baseAddr=0x2000, numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at 0x2000 with 16bit fixed-point numbers.
+ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
+ new chipyard.config.AbstractConfig)
+// DOC include end: FFTRocketConfig
+
class HwachaRocketConfig extends Config(
new chipyard.config.WithHwachaTest ++
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
diff --git a/generators/fft-generator b/generators/fft-generator
new file mode 160000
index 00000000..b9f1c085
--- /dev/null
+++ b/generators/fft-generator
@@ -0,0 +1 @@
+Subproject commit b9f1c085afa25e1688d5acbd3f252882d511b90e
diff --git a/tests/Makefile b/tests/Makefile
index ca8268ea..556c6fd3 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -6,7 +6,7 @@ LDFLAGS= -static
include libgloss.mk
PROGRAMS = pwm blkdev accum charcount nic-loopback big-blkdev pingd \
- streaming-passthrough streaming-fir nvdla spiflashread spiflashwrite
+ streaming-passthrough streaming-fir nvdla spiflashread spiflashwrite fft
spiflash.img: spiflash.py
python3 $<
diff --git a/tests/fft.c b/tests/fft.c
new file mode 100644
index 00000000..cddfa6db
--- /dev/null
+++ b/tests/fft.c
@@ -0,0 +1,71 @@
+/* This Test should be used with the fft generator config -- FFTRocketConfig. */
+
+#include
+#include
+#include
+
+#define FFT_WRITE_LANE 0x2000
+#define FFT_RD_LANE_BASE 0x2008
+// addr of read lane i is FFT_RD_LANE_BASE + i * 8
+
+// from generators/fft-generator/test_pts.py (in the fft-generator repo)
+// point size (and therefore integer width/uint32_t) determined by IOWidth from Tail.scala
+// point size is 2 * IOWidth since both real and imaginary components get IOWidth bits
+const uint32_t points[8] = {
+ 0b00000000101101011111111101001011, // 00B5FF4B
+ 0b00000000000000001111111100000000, // 0000FF00
+ 0b11111111010010111111111101001011, // FF4BFF4B
+ 0b11111111000000000000000000000000, // FF000000
+ 0b11111111010010110000000010110101, // FF4B00B5
+ 0b00000000000000000000000100000000, // 00000100
+ 0b00000000101101010000000010110101, // 00B500B5
+ 0b00000001000000000000000000000000 // 01000000
+};
+
+const uint32_t expected_outputs[8] = {
+ 0x00000000, // read 0
+ 0x00000000, // read 1
+ 0x00000000, // read 2
+ 0xffff0000, // read 3 -- real portion is 0xff (very small negative number)
+ 0x00000000, // read 4
+ 0x00000000, // read 5
+ 0x00000000, // read 6
+ 0x05a8fa57, // read 7 -- real: ~5.656 imaginary: ~-5.656
+};
+
+int main(void) {
+ int num_points = 8;
+
+ // write points to fft
+ for (int i = 0; i < num_points; i++) {
+ uint32_t write_val = points[i];
+ volatile uint32_t* ptr = (volatile uint32_t*) FFT_WRITE_LANE;
+ *ptr = write_val;
+ }
+
+ for (int i = 0; i < num_points; i++) {
+ volatile uint32_t* ptr_0 = (volatile uint32_t*) (FFT_RD_LANE_BASE + (i * 8));
+ uint32_t read_val = *ptr_0;
+
+ /* To convert binary to floating point
+ * However, RISC-V compiler can't print floats. You can use this by copy-pasting it into an online
+ * C compiler. The printf at the bottom of this for loop will print out the values of real_part_bin
+ * and imag_part_bin
+ *
+ * Code is commented out because default risc-v compiler doesn't support pow
+ */
+ // uint16_t real_part_bin = read_val >> 16;
+ // uint16_t imag_part_bin = read_val & 0xFFFF;
+ // int bp = 8; // from tail.scala
+ // float real_comp = ((int16_t) real_part_bin) * pow(2, bp);
+ // float imag_comp = ((int16_t) imag_part_bin) * pow(2, bp);
+
+ if (read_val != expected_outputs[i]) {
+ printf("FAIL: Expected and real differed: %x %x", read_val, expected_outputs[i]);
+ return -1;
+ }
+ }
+
+ printf("PASS: FFT Test Passed\n");
+ return 0;
+}
\ No newline at end of file