diff options
| author | Aditya Naik | 2023-11-23 03:11:56 -0800 |
|---|---|---|
| committer | Aditya Naik | 2023-11-23 03:11:56 -0800 |
| commit | af415532cf160e63e971ceb301833b8433c18a50 (patch) | |
| tree | 1fef70139846f57298c8e24a590490a74249f7dd /src/test/scala/chiselTests/ChiselSpec.scala | |
| parent | 8200c0cdf1d471453946d5ae24bc99757b2ef02d (diff) | |
cleanup
Diffstat (limited to 'src/test/scala/chiselTests/ChiselSpec.scala')
| -rw-r--r-- | src/test/scala/chiselTests/ChiselSpec.scala | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala deleted file mode 100644 index e00afcf6..00000000 --- a/src/test/scala/chiselTests/ChiselSpec.scala +++ /dev/null @@ -1,368 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.aop.Aspect -import chisel3.stage.{ - ChiselGeneratorAnnotation, - ChiselStage, - NoRunFirrtlCompilerAnnotation, - PrintFullStackTraceAnnotation -} -import chisel3.testers._ -import firrtl.annotations.Annotation -import firrtl.ir.Circuit -import firrtl.util.BackendCompilationUtilities -import firrtl.{AnnotationSeq, EmittedVerilogCircuitAnnotation} -import _root_.logger.Logger -import firrtl.stage.FirrtlCircuitAnnotation -import org.scalacheck._ -import org.scalatest._ -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.funspec.AnyFunSpec -import org.scalatest.propspec.AnyPropSpec -import org.scalatest.matchers.should.Matchers -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks - -import java.io.{ByteArrayOutputStream, PrintStream} -import java.security.Permission -import scala.reflect.ClassTag - -/** Common utility functions for Chisel unit tests. */ -trait ChiselRunners extends Assertions with BackendCompilationUtilities { - def runTester( - t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq() - ): Boolean = { - // Change this to enable Treadle as a backend - val defaultBackend = { - val useTreadle = sys.env.get("CHISEL3_CI_USE_TREADLE").isDefined - if (useTreadle) chisel3.testers.TreadleBackend else chisel3.testers.TesterDriver.defaultBackend - } - val hasBackend = TestUtils.containsBackend(annotations) - val annos: Seq[Annotation] = if (hasBackend) annotations else defaultBackend +: annotations - TesterDriver.execute(() => t, additionalVResources, annos) - } - def assertTesterPasses( - t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq() - ): Unit = { - assert(runTester(t, additionalVResources, annotations)) - } - def assertTesterFails( - t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: Seq[chisel3.aop.Aspect[_]] = Seq() - ): Unit = { - assert(!runTester(t, additionalVResources, annotations)) - } - - def assertKnownWidth(expected: Int)(gen: => Data): Unit = { - assertTesterPasses(new BasicTester { - val x = gen - assert(x.getWidth === expected) - // Sanity check that firrtl doesn't change the width - x := 0.U.asTypeOf(chiselTypeOf(x)) - val (_, done) = chisel3.util.Counter(true.B, 2) - when(done) { - chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt) - stop() - } - }) - } - - def assertInferredWidth(expected: Int)(gen: => Data): Unit = { - assertTesterPasses(new BasicTester { - val x = gen - assert(!x.isWidthKnown, s"Asserting that width should be inferred yet width is known to Chisel!") - x := 0.U.asTypeOf(chiselTypeOf(x)) - val (_, done) = chisel3.util.Counter(true.B, 2) - when(done) { - chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt) - stop() - } - }) - } - - /** Compiles a Chisel Module to Verilog - * NOTE: This uses the "test_run_dir" as the default directory for generated code. - * @param t the generator for the module - * @return the Verilog code as a string. - */ - def compile(t: => RawModule): String = { - (new ChiselStage) - .execute( - Array("--target-dir", createTestDirectory(this.getClass.getSimpleName).toString), - Seq(ChiselGeneratorAnnotation(() => t)) - ) - .collectFirst { - case EmittedVerilogCircuitAnnotation(a) => a.value - } - .getOrElse(fail("No Verilog circuit was emitted by the FIRRTL compiler!")) - } - - def elaborateAndGetModule[A <: RawModule](t: => A): A = { - var res: Any = null - ChiselStage.elaborate { - res = t - res.asInstanceOf[A] - } - res.asInstanceOf[A] - } - - /** Compiles a Chisel Module to FIRRTL - * NOTE: This uses the "test_run_dir" as the default directory for generated code. - * @param t the generator for the module - * @return The FIRRTL Circuit and Annotations _before_ FIRRTL compilation - */ - def getFirrtlAndAnnos(t: => RawModule, providedAnnotations: Seq[Annotation] = Nil): (Circuit, Seq[Annotation]) = { - val args = Array( - "--target-dir", - createTestDirectory(this.getClass.getSimpleName).toString, - "--no-run-firrtl", - "--full-stacktrace" - ) - val annos = (new ChiselStage).execute(args, Seq(ChiselGeneratorAnnotation(() => t)) ++ providedAnnotations) - val circuit = annos.collectFirst { - case FirrtlCircuitAnnotation(c) => c - }.getOrElse(fail("No FIRRTL Circuit found!!")) - (circuit, annos) - } -} - -/** Spec base class for BDD-style testers. */ -abstract class ChiselFlatSpec extends AnyFlatSpec with ChiselRunners with Matchers - -/** Spec base class for BDD-style testers. */ -abstract class ChiselFreeSpec extends AnyFreeSpec with ChiselRunners with Matchers - -/** Spec base class for BDD-style testers. */ -abstract class ChiselFunSpec extends AnyFunSpec with ChiselRunners with Matchers - -/** Spec base class for property-based testers. */ -abstract class ChiselPropSpec extends AnyPropSpec with ChiselRunners with ScalaCheckPropertyChecks with Matchers { - - // Constrain the default number of instances generated for every use of forAll. - implicit override val generatorDrivenConfig: PropertyCheckConfiguration = - PropertyCheckConfiguration(minSuccessful = 8, minSize = 1, sizeRange = 3) - - // Generator for small positive integers. - val smallPosInts = Gen.choose(1, 4) - - // Generator for positive (ascending or descending) ranges. - def posRange: Gen[Range] = for { - dir <- Gen.oneOf(true, false) - step <- Gen.choose(1, 3) - m <- Gen.choose(1, 10) - n <- Gen.choose(1, 10) - } yield { - if (dir) { - Range(m, (m + n) * step, step) - } else { - Range((m + n) * step, m, -step) - } - } - - // Generator for widths considered "safe". - val safeUIntWidth = Gen.choose(1, 30) - - // Generators for integers that fit within "safe" widths. - val safeUInts = Gen.choose(0, (1 << 30)) - - // Generators for vector sizes. - val vecSizes = Gen.choose(0, 4) - - // Generator for string representing an arbitrary integer. - val binaryString = for (i <- Arbitrary.arbitrary[Int]) yield "b" + i.toBinaryString - - // Generator for a sequence of Booleans of size n. - def enSequence(n: Int): Gen[List[Boolean]] = Gen.containerOfN[List, Boolean](n, Gen.oneOf(true, false)) - - // Generator which gives a width w and a list (of size n) of numbers up to w bits. - def safeUIntN(n: Int): Gen[(Int, List[Int])] = for { - w <- smallPosInts - i <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) - } yield (w, i) - - // Generator which gives a width w and a numbers up to w bits. - val safeUInt = for { - w <- smallPosInts - i <- Gen.choose(0, (1 << w) - 1) - } yield (w, i) - - // Generator which gives a width w and a list (of size n) of a pair of numbers up to w bits. - def safeUIntPairN(n: Int): Gen[(Int, List[(Int, Int)])] = for { - w <- smallPosInts - i <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) - j <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) - } yield (w, i.zip(j)) - - // Generator which gives a width w and a pair of numbers up to w bits. - val safeUIntPair = for { - w <- smallPosInts - i <- Gen.choose(0, (1 << w) - 1) - j <- Gen.choose(0, (1 << w) - 1) - } yield (w, i, j) -} - -trait Utils { - - /** Run some Scala thunk and return STDOUT and STDERR as strings. - * @param thunk some Scala code - * @return a tuple containing STDOUT, STDERR, and what the thunk returns - */ - def grabStdOutErr[T](thunk: => T): (String, String, T) = { - val stdout, stderr = new ByteArrayOutputStream() - val ret = scala.Console.withOut(stdout) { scala.Console.withErr(stderr) { thunk } } - (stdout.toString, stderr.toString, ret) - } - - /** Run some Scala thunk and return all logged messages as Strings - * @param thunk some Scala code - * @return a tuple containing LOGGED, and what the thunk returns - */ - def grabLog[T](thunk: => T): (String, T) = { - val baos = new ByteArrayOutputStream() - val stream = new PrintStream(baos, true, "utf-8") - val ret = Logger.makeScope(Nil) { - Logger.setOutput(stream) - thunk - } - (baos.toString, ret) - } - - /** Encodes a System.exit exit code - * @param status the exit code - */ - private case class ExitException(status: Int) extends SecurityException(s"Found a sys.exit with code $status") - - /** A security manager that converts calls to System.exit into [[ExitException]]s by explicitly disabling the ability of - * a thread to actually exit. For more information, see: - * - https://docs.oracle.com/javase/tutorial/essential/environment/security.html - */ - private class ExceptOnExit extends SecurityManager { - override def checkPermission(perm: Permission): Unit = {} - override def checkPermission(perm: Permission, context: Object): Unit = {} - override def checkExit(status: Int): Unit = { - super.checkExit(status) - throw ExitException(status) - } - } - - /** Encodes a file that some code tries to write to - * @param the file name - */ - private case class WriteException(file: String) extends SecurityException(s"Tried to write to file $file") - - /** A security manager that converts writes to any file into [[WriteException]]s. - */ - private class ExceptOnWrite extends SecurityManager { - override def checkPermission(perm: Permission): Unit = {} - override def checkPermission(perm: Permission, context: Object): Unit = {} - override def checkWrite(file: String): Unit = { - super.checkWrite(file) - throw WriteException(file) - } - } - - /** Run some Scala code (a thunk) in an environment where all System.exit are caught and returned. This avoids a - * situation where a test results in something actually exiting and killing the entire test. This is necessary if you - * want to test a command line program, e.g., the `main` method of [[firrtl.options.Stage Stage]]. - * - * NOTE: THIS WILL NOT WORK IN SITUATIONS WHERE THE THUNK IS CATCHING ALL [[Exception]]s OR [[Throwable]]s, E.G., - * SCOPT. IF THIS IS HAPPENING THIS WILL NOT WORK. REPEAT THIS WILL NOT WORK. - * @param thunk some Scala code - * @return either the output of the thunk (`Right[T]`) or an exit code (`Left[Int]`) - */ - def catchStatus[T](thunk: => T): Either[Int, T] = { - try { - System.setSecurityManager(new ExceptOnExit()) - Right(thunk) - } catch { - case ExitException(a) => Left(a) - } finally { - System.setSecurityManager(null) - } - } - - /** Run some Scala code (a thunk) in an environment where file writes are caught and the file that a program tries to - * write to is returned. This is useful if you want to test that some thunk either tries to write to a specific file - * or doesn't try to write at all. - */ - def catchWrites[T](thunk: => T): Either[String, T] = { - throw new Exception("Do not use, not thread-safe") - try { - System.setSecurityManager(new ExceptOnWrite()) - Right(thunk) - } catch { - case WriteException(a) => Left(a) - } finally { - System.setSecurityManager(null) - } - } - - /** A tester which runs generator and uses an aspect to check the returned object - * @param gen function to generate a Chisel module - * @param f a function to check the Chisel module - * @tparam T the Chisel module class - */ - def aspectTest[T <: RawModule](gen: () => T)(f: T => Unit)(implicit scalaMajorVersion: Int): Unit = { - // Runs chisel stage - def run[T <: RawModule](gen: () => T, annotations: AnnotationSeq): AnnotationSeq = { - new ChiselStage().run( - Seq(ChiselGeneratorAnnotation(gen), NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation) ++ annotations - ) - } - // Creates a wrapping aspect to contain checking function - case object BuiltAspect extends Aspect[T] { - override def toAnnotation(top: T): AnnotationSeq = { f(top); Nil } - } - val currentMajorVersion = scala.util.Properties.versionNumberString.split('.')(1).toInt - if (currentMajorVersion >= scalaMajorVersion) { - run(gen, Seq(BuiltAspect)) - } - } - - /** Run some code and rethrow an exception with a specific type if an exception of that type occurs anywhere in the - * stack trace. - * - * This is useful for "extracting" one exception that may be wrapped by other exceptions. - * - * Example usage: - * {{{ - * a [ChiselException] should be thrownBy extractCause[ChiselException] { /* ... */ } - * }}} - * - * @param thunk some code to run - * @tparam A the type of the exception to extract - * @return nothing - */ - def extractCause[A <: Throwable: ClassTag](thunk: => Any): Unit = { - def unrollCauses(a: Throwable): Seq[Throwable] = a match { - case null => Seq.empty - case _ => a +: unrollCauses(a.getCause) - } - - val exceptions: Seq[_ <: Throwable] = - try { - thunk - Seq.empty - } catch { - case a: Throwable => unrollCauses(a) - } - - exceptions.collectFirst { case a: A => a } match { - case Some(a) => throw a - case None => - exceptions match { - case Nil => () - case h :: t => throw h - } - } - - } -} |
