summaryrefslogtreecommitdiff
path: root/src/test/scala/examples
diff options
context:
space:
mode:
authorAditya Naik2023-11-23 03:11:56 -0800
committerAditya Naik2023-11-23 03:11:56 -0800
commitaf415532cf160e63e971ceb301833b8433c18a50 (patch)
tree1fef70139846f57298c8e24a590490a74249f7dd /src/test/scala/examples
parent8200c0cdf1d471453946d5ae24bc99757b2ef02d (diff)
cleanup
Diffstat (limited to 'src/test/scala/examples')
-rw-r--r--src/test/scala/examples/ImplicitStateVendingMachine.scala31
-rw-r--r--src/test/scala/examples/SimpleVendingMachine.scala98
-rw-r--r--src/test/scala/examples/VendingMachineGenerator.scala130
-rw-r--r--src/test/scala/examples/VendingMachineUtils.scala39
4 files changed, 0 insertions, 298 deletions
diff --git a/src/test/scala/examples/ImplicitStateVendingMachine.scala b/src/test/scala/examples/ImplicitStateVendingMachine.scala
deleted file mode 100644
index 36ac82ab..00000000
--- a/src/test/scala/examples/ImplicitStateVendingMachine.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package examples
-
-import chiselTests.ChiselFlatSpec
-import chisel3._
-
-// Vending machine implemented with an implicit state machine
-class ImplicitStateVendingMachine extends SimpleVendingMachine {
- // We let the value of nickel be 1 and dime be 2 for efficiency reasons
- val value = RegInit(0.asUInt(3.W))
- val incValue = WireDefault(0.asUInt(3.W))
- val doDispense = value >= 4.U // 4 * nickel as 1 == $0.20
-
- when(doDispense) {
- value := 0.U // No change given
- }.otherwise {
- value := value + incValue
- }
-
- when(io.nickel) { incValue := 1.U }
- when(io.dime) { incValue := 2.U }
-
- io.dispense := doDispense
-}
-
-class ImplicitStateVendingMachineSpec extends ChiselFlatSpec {
- "An vending machine implemented with implicit state" should "work" in {
- assertTesterPasses { new SimpleVendingMachineTester(new ImplicitStateVendingMachine) }
- }
-}
diff --git a/src/test/scala/examples/SimpleVendingMachine.scala b/src/test/scala/examples/SimpleVendingMachine.scala
deleted file mode 100644
index 819669a3..00000000
--- a/src/test/scala/examples/SimpleVendingMachine.scala
+++ /dev/null
@@ -1,98 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package examples
-
-import chiselTests.ChiselFlatSpec
-import chisel3.testers.{BasicTester, TesterDriver}
-import chisel3._
-import chisel3.util._
-
-class SimpleVendingMachineIO extends Bundle {
- val nickel = Input(Bool())
- val dime = Input(Bool())
- val dispense = Output(Bool())
-}
-
-// Superclass for vending machines with very simple IO
-abstract class SimpleVendingMachine extends Module {
- val io = IO(new SimpleVendingMachineIO)
- assert(!(io.nickel && io.dime), "Only one of nickel or dime can be input at a time!")
-}
-
-// Vending machine implemented with a Finite State Machine
-class FSMVendingMachine extends SimpleVendingMachine {
- val sIdle :: s5 :: s10 :: s15 :: sOk :: Nil = Enum(5)
- val state = RegInit(sIdle)
-
- switch(state) {
- is(sIdle) {
- when(io.nickel) { state := s5 }
- when(io.dime) { state := s10 }
- }
- is(s5) {
- when(io.nickel) { state := s10 }
- when(io.dime) { state := s15 }
- }
- is(s10) {
- when(io.nickel) { state := s15 }
- when(io.dime) { state := sOk }
- }
- is(s15) {
- when(io.nickel) { state := sOk }
- when(io.dime) { state := sOk }
- }
- is(sOk) {
- state := sIdle
- }
- }
- io.dispense := (state === sOk)
-}
-
-class VerilogVendingMachine extends BlackBox {
- // Because this is a blackbox, we must explicitly add clock and reset
- val io = IO(new SimpleVendingMachineIO {
- val clock = Input(Clock())
- val reset = Input(Reset())
- })
-}
-
-// Shim because Blackbox io is slightly different than normal Chisel Modules
-class VerilogVendingMachineWrapper extends SimpleVendingMachine {
- val impl = Module(new VerilogVendingMachine)
- impl.io.clock := clock
- impl.io.reset := reset
- impl.io.nickel := io.nickel
- impl.io.dime := io.dime
- io.dispense := impl.io.dispense
-}
-
-// Accept a reference to a SimpleVendingMachine so it can be constructed inside
-// the tester (in a call to Module.apply as required by Chisel
-class SimpleVendingMachineTester(mod: => SimpleVendingMachine) extends BasicTester {
-
- val dut = Module(mod)
-
- val (cycle, done) = Counter(true.B, 10)
- when(done) { stop(); stop() } // Stop twice because of Verilator
-
- val nickelInputs = VecInit(true.B, true.B, true.B, true.B, true.B, false.B, false.B, false.B, true.B, false.B)
- val dimeInputs = VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B)
- val expected = VecInit(false.B, false.B, false.B, false.B, true.B, false.B, false.B, true.B, false.B, false.B)
-
- dut.io.nickel := nickelInputs(cycle)
- dut.io.dime := dimeInputs(cycle)
- assert(dut.io.dispense === expected(cycle))
-}
-
-class SimpleVendingMachineSpec extends ChiselFlatSpec {
- "An FSM implementation of a vending machine" should "work" in {
- assertTesterPasses { new SimpleVendingMachineTester(new FSMVendingMachine) }
- }
- "An Verilog implementation of a vending machine" should "work" in {
- assertTesterPasses(
- new SimpleVendingMachineTester(new VerilogVendingMachineWrapper),
- List("/chisel3/VerilogVendingMachine.v"),
- annotations = TesterDriver.verilatorOnly
- )
- }
-}
diff --git a/src/test/scala/examples/VendingMachineGenerator.scala b/src/test/scala/examples/VendingMachineGenerator.scala
deleted file mode 100644
index 4adae987..00000000
--- a/src/test/scala/examples/VendingMachineGenerator.scala
+++ /dev/null
@@ -1,130 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package examples
-
-import chiselTests.ChiselFlatSpec
-import chisel3.testers.BasicTester
-import chisel3._
-import chisel3.util._
-
-import VendingMachineUtils._
-
-class VendingMachineIO(val legalCoins: Seq[Coin]) extends Bundle {
- require(legalCoins.size >= 1, "The vending machine must accept at least 1 coin!")
- // Order of coins by value
- val coins: Seq[Coin] = legalCoins.sortBy(_.value)
- // Map of coin names to their relative position in value (ie. index in inputs)
- val indexMap: Map[String, Int] = coins.map(_.name).zipWithIndex.toMap
-
- require(
- coins.map(_.value % coins.head.value == 0).reduce(_ && _),
- "All coins must be a multiple of the lowest value coin!"
- )
-
- val inputs = Input(Vec(legalCoins.size, Bool()))
- val dispense = Output(Bool())
-
- def apply(coin: String): Unit = {
- val idx = indexMap(coin)
- inputs(idx) := true.B
- }
-}
-
-// Superclass for parameterized vending machines
-abstract class ParameterizedVendingMachine(legalCoins: Seq[Coin], val sodaCost: Int) extends Module {
- val io = IO(new VendingMachineIO(legalCoins))
- // Enforce one hot
- if (io.inputs.size > 1) {
- for (input <- io.inputs) {
- when(input) {
- assert(io.inputs.filterNot(_ == input).map(!_).reduce(_ && _), "Only 1 coin can be input in a given cycle!")
- }
- }
- }
-}
-
-class VendingMachineGenerator(
- legalCoins: Seq[Coin],
- sodaCost: Int)
- extends ParameterizedVendingMachine(legalCoins, sodaCost) {
- require(sodaCost > 0, "Sodas must actually cost something!")
-
- // All coin values are normalized to a multiple of the minimum coin value
- val minCoin = io.coins.head.value
- val maxCoin = io.coins.last.value
- val maxValue = (sodaCost + maxCoin - minCoin) / minCoin // normalize to minimum value
-
- val width = log2Ceil(maxValue + 1).W
- val value = RegInit(0.asUInt(width))
- val incValue = WireDefault(0.asUInt(width))
- val doDispense = value >= (sodaCost / minCoin).U
-
- when(doDispense) {
- value := 0.U // No change given
- }.otherwise {
- value := value + incValue
- }
-
- for ((coin, index) <- io.coins.zipWithIndex) {
- when(io.inputs(index)) { incValue := (coin.value / minCoin).U }
- }
- io.dispense := doDispense
-}
-
-class ParameterizedVendingMachineTester(
- mod: => ParameterizedVendingMachine,
- testLength: Int)
- extends BasicTester {
- require(testLength > 0, "Test length must be positive!")
-
- // Construct the module
- val dut = Module(mod)
- val coins = dut.io.coins
-
- // Inputs and expected results
- // Do random testing
- private val _rand = scala.util.Random
- val inputs: Seq[Option[Coin]] = Seq.fill(testLength)(coins.lift(_rand.nextInt(coins.size + 1)))
- val expected: Seq[Boolean] = getExpectedResults(inputs, dut.sodaCost)
-
- val inputVec: Vec[UInt] = VecInit(inputs.map {
- case Some(coin) => (1 << dut.io.indexMap(coin.name)).asUInt(coins.size.W)
- case None => 0.asUInt(coins.size.W)
- })
- val expectedVec: Vec[Bool] = VecInit(expected.map(_.B))
-
- val (idx, done) = Counter(true.B, testLength + 1)
- when(done) { stop(); stop() } // Two stops for Verilator
-
- dut.io.inputs := inputVec(idx).asBools
- assert(dut.io.dispense === expectedVec(idx))
-}
-
-class VendingMachineGeneratorSpec extends ChiselFlatSpec {
- behavior.of("The vending machine generator")
-
- it should "generate a vending machine that accepts only nickels and dimes and costs $0.20" in {
- val coins = Seq(Nickel, Dime)
- assertTesterPasses {
- new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, 20), 100)
- }
- }
- it should "generate a vending machine that only accepts one kind of coin" in {
- val coins = Seq(Nickel)
- assertTesterPasses {
- new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, 30), 100)
- }
- }
- it should "generate a more realistic vending machine that costs $1.50" in {
- val coins = Seq(Penny, Nickel, Dime, Quarter)
- assertTesterPasses {
- new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, 150), 100)
- }
- }
- it should "generate a Harry Potter themed vending machine" in {
- val coins = Seq(Knut, Sickle) // Galleons are worth too much
- assertTesterPasses {
- new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, Galleon.value), 100)
- }
- }
-}
diff --git a/src/test/scala/examples/VendingMachineUtils.scala b/src/test/scala/examples/VendingMachineUtils.scala
deleted file mode 100644
index 8d5aea57..00000000
--- a/src/test/scala/examples/VendingMachineUtils.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package examples
-
-import scala.collection.mutable
-
-/* Useful utilities for testing vending machines */
-object VendingMachineUtils {
- abstract class Coin(val name: String, val value: Int)
- // US Coins
- case object Penny extends Coin("penny", 1)
- case object Nickel extends Coin("nickel", 5)
- case object Dime extends Coin("dime", 10)
- case object Quarter extends Coin("quarter", 25)
-
- // Harry Potter Coins
- case object Knut extends Coin("knut", Penny.value * 2) // Assuming 1 Knut is worth $0.02
- case object Sickle extends Coin("sickle", Knut.value * 29)
- case object Galleon extends Coin("galleon", Sickle.value * 17)
-
- def getExpectedResults(inputs: Seq[Option[Coin]], sodaCost: Int): Seq[Boolean] = {
- var value = 0
- val outputs = mutable.ArrayBuffer.empty[Boolean]
- for (input <- inputs) {
- val incValue = input match {
- case Some(coin) => coin.value
- case None => 0
- }
- if (value >= sodaCost) {
- outputs.append(true)
- value = 0
- } else {
- outputs.append(false)
- value += incValue
- }
- }
- outputs.toSeq
- }
-}