From 0cc643bfdbeef594e68bc7fb0c2a9e0f1cacf9e0 Mon Sep 17 00:00:00 2001 From: Paul Rigge Date: Thu, 30 Apr 2020 10:51:32 -0700 Subject: [PATCH] Switch FIR from UInt -> FixedPoint --- .../chipyard/src/main/scala/DigitalTop.scala | 2 ++ .../scala/example/dsptools/GenericFIR.scala | 26 +++++++++-------- tests/fir.c | 28 ++++++++++++++----- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/generators/chipyard/src/main/scala/DigitalTop.scala b/generators/chipyard/src/main/scala/DigitalTop.scala index c7b3d497..75262a99 100644 --- a/generators/chipyard/src/main/scala/DigitalTop.scala +++ b/generators/chipyard/src/main/scala/DigitalTop.scala @@ -22,6 +22,8 @@ class DigitalTop(implicit p: Parameters) extends System with icenet.CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for FireSim with chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget + with chipyard.example.CanHavePeripheryUIntTestFIR // Enables optionally adding the FIR example widget + with chipyard.example.CanHavePeripheryUIntStreamingPassthrough // Enables optionally adding the passthrough example widget { override lazy val module = new DigitalTopModule(this) } diff --git a/generators/chipyard/src/main/scala/example/dsptools/GenericFIR.scala b/generators/chipyard/src/main/scala/example/dsptools/GenericFIR.scala index 5335eb42..45093f9a 100644 --- a/generators/chipyard/src/main/scala/example/dsptools/GenericFIR.scala +++ b/generators/chipyard/src/main/scala/example/dsptools/GenericFIR.scala @@ -3,7 +3,7 @@ package chipyard.example import chisel3._ -import chisel3.{Bundle, Module} +import chisel3.experimental.FixedPoint import chisel3.util._ import dspblocks._ import dsptools.numbers._ @@ -80,9 +80,9 @@ class GenericFIR[T<:Data:Ring](genIn:T, genOut:T, coeffs: Seq[T]) extends Module // Connect adjacent cells // Note that .tail() returns a collection that consists of all // elements in the inital collection minus the first one. - // This means that we zip together directCells[0, n] and + // This means that we zip together directCells[0, n] and // directCells[1, n]. However, since zip ignores unmatched elements, - // the resulting zip is (directCells[0], directCells[1]) ... + // the resulting zip is (directCells[0], directCells[1]) ... // (directCells[n-1], directCells[n]) for ((current, next) <- directCells.zip(directCells.tail)) { next.in.bits := current.out.bits @@ -108,22 +108,22 @@ class GenericFIR[T<:Data:Ring](genIn:T, genOut:T, coeffs: Seq[T]) extends Module // // DOC include start: GenericFIRDirectCell chisel class GenericFIRDirectCell[T<:Data:Ring](genIn: T, genOut: T) extends Module { - val io = IO(GenericFIRCellIO(genIn, genOut)) - + val io = IO(GenericFIRCellIO(genIn, genOut)) + // Registers to delay the input and the valid to propagate with calculations val hasNewData = RegInit(0.U) val inputReg = Reg(genIn.cloneType) // Passthrough ready io.in.ready := io.out.ready - + // When a new transaction is ready on the input, we will have new data to output // next cycle. Take this data in when (io.in.fire()) { hasNewData := 1.U - inputReg := io.in.bits.data + inputReg := io.in.bits.data } - + // We should output data when our cell has new data to output and is ready to // recieve new data. This insures that every cell in the chain passes its data // on at the same time @@ -133,7 +133,7 @@ class GenericFIRDirectCell[T<:Data:Ring](genIn: T, genOut: T) extends Module { // Compute carry // This uses the ring implementation for + and *, i.e. // (a * b) maps to (Ring[T].prod(a, b)) for whicever T you use - io.out.bits.carry := inputReg * io.coeff + io.in.bits.carry + io.out.bits.carry := inputReg * io.coeff + io.in.bits.carry } // DOC include end: GenericFIRDirectCell chisel @@ -204,8 +204,12 @@ class TLGenericFIRChain[T<:Data:Ring] (genIn: T, genOut: T, coeffs: Seq[T], para trait CanHavePeripheryUIntTestFIR extends BaseSubsystem { val fir = p(GenericFIRKey) match { case Some(params) => { - val fir = LazyModule(new TLGenericFIRChain(UInt(8.W), UInt(12.W), Seq(1.U, 2.U, 3.U), params)) - + val fir = LazyModule(new TLGenericFIRChain( + genIn = FixedPoint(8.W, 3.BP), + genOut = FixedPoint(8.W, 3.BP), + coeffs = Seq(1.F(0.BP), 2.F(0.BP), 3.F(0.BP)), + params = params)) + pbus.toVariableWidthSlave(Some("firWrite")) { fir.writeQueue.mem.get } pbus.toVariableWidthSlave(Some("firRead")) { fir.readQueue.mem.get } } diff --git a/tests/fir.c b/tests/fir.c index 46313a35..be61534e 100644 --- a/tests/fir.c +++ b/tests/fir.c @@ -3,6 +3,9 @@ #define PASSTHROUGH_READ 0x2100 #define PASSTHROUGH_READ_COUNT 0x2108 +#define BP 3 +#define BP_SCALE ((double)(1 << BP)) + #include "mmio.h" #include @@ -10,14 +13,23 @@ #include #include +uint64_t roundi(double x) +{ + if (x < 0.0) { + return (uint64_t)(x - 0.5); + } else { + return (uint64_t)(x + 0.5); + } +} + int main(void) { - printf("Starting writing\n"); - uint32_t num_tests = 15; - uint32_t test_vector[15] = {1, 2, 3, 4, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 2}; + double test_vector[15] = {1.0, 2.0, 3.0, 4.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.5, 0.25, 0.125, 0.125}; + uint32_t num_tests = sizeof(test_vector) / sizeof(double); + printf("Starting writing %d inputs\n", num_tests); for (int i = 0; i < num_tests; i++) { - reg_write64(PASSTHROUGH_WRITE, test_vector[i]); + reg_write64(PASSTHROUGH_WRITE, roundi(test_vector[i] * BP_SCALE)); } printf("Done writing\n"); @@ -29,12 +41,14 @@ int main(void) if (rcnt != 0) { for (int i = 0; i < num_tests - 3; i++) { uint32_t res = reg_read32(PASSTHROUGH_READ); - uint32_t expected = 3*test_vector[i] + 2*test_vector[i+1] + test_vector[i+2]; + // double res = ((double)reg_read32(PASSTHROUGH_READ)) / BP_SCALE; + double expected_double = 3*test_vector[i] + 2*test_vector[i+1] + test_vector[i+2]; + uint32_t expected = ((uint32_t)(expected_double * BP_SCALE + 0.5)) & 0xFF; if (res == expected) { - printf("\n\nPass: Got %d Expected %d\n\n", res, expected); + printf("\n\nPass: Got %u Expected %u\n\n", res, expected); } else { failed = 1; - printf("\n\nFail: Got %d Expected %d\n\n", res, expected); + printf("\n\nFail: Got %u Expected %u\n\n", res, expected); } } } else {