Skip to content

Commit

Permalink
import treadle source code (ucb-bar#618)
Browse files Browse the repository at this point in the history
* import treadle source code

* add new deprecation warning to ignore

* import treadle source code

* rename treadle -> treadle2

* format treadle sources

* treadle: remove repl

* treadle: remove VCD reading and diffing

* fix treadle warnings

* add missing resources for tests

* fix bore spec to not generate a stray file in root directory

* remove bespoke treadle coverage

Standard firrtl coverage is still supported.

* treadle: remove expression renderer

* treadle: remove  WaveformValues

* treadle: remove RollBackBuffer support
  • Loading branch information
ekiwi authored Mar 2, 2023
1 parent fed4822 commit a6b1091
Show file tree
Hide file tree
Showing 161 changed files with 23,796 additions and 48 deletions.
33 changes: 26 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
java-version: ${{ matrix.jvm }}
cache: 'sbt'
- name: Test
run: sbt ++${{ matrix.scala }} "testOnly -- -l RequiresVcs -l RequiresVerilator -l Formal -l RequiresIcarus"
run: sbt ++${{ matrix.scala }} "testOnly chiseltest.** -- -l RequiresVcs -l RequiresVerilator -l Formal -l RequiresIcarus"

test-mac:
name: sbt test on mac
Expand All @@ -35,7 +35,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Test
run: sbt "testOnly -- -l RequiresVcs -l RequiresVerilator -l Formal -l RequiresIcarus"
run: sbt "testOnly chiseltest.** -- -l RequiresVcs -l RequiresVerilator -l Formal -l RequiresIcarus"

icarus:
name: icarus verilog
Expand All @@ -57,7 +57,7 @@ jobs:
brew install icarus-verilog
iverilog -v || true
- name: Test
run: sbt ++${{ matrix.scala }} "testOnly -- -n RequiresIcarus"
run: sbt ++${{ matrix.scala }} "testOnly chiseltest.** -- -n RequiresIcarus"

verilator:
name: verilator regressions
Expand Down Expand Up @@ -99,7 +99,7 @@ jobs:
sudo make install
verilator --version
- name: Test
run: sbt "testOnly -- -n RequiresVerilator"
run: sbt "testOnly chiseltest.** -- -n RequiresVerilator"

formal:
name: formal verification tests
Expand All @@ -121,7 +121,7 @@ jobs:
with:
osscadsuite-version: '2023-01-09'
- name: Test
run: sbt "testOnly -- -n Formal -Dformal_engine=${{ matrix.backend }}"
run: sbt "testOnly chiseltest.** -- -n Formal -Dformal_engine=${{ matrix.backend }}"

formal-mac:
name: formal verification tests on mac
Expand All @@ -134,7 +134,7 @@ jobs:
brew install z3
z3 --version
- name: Test
run: sbt "testOnly -- -n Formal -Dformal_engine=z3"
run: sbt "testOnly chiseltest.** -- -n Formal -Dformal_engine=z3"

doc:
name: Documentation and Formatting
Expand All @@ -160,6 +160,25 @@ jobs:
- name: Check for Warnings in Tests
run: sbt "set ThisBuild / scalacOptions ++= Seq(\"-Xfatal-warnings\") ; Test / compile"

test-treadle:
name: sbt test for treadle on ubuntu
runs-on: ubuntu-20.04
strategy:
matrix:
scala: [2.12.17, 2.13.10]
jvm: [8, 11]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Scala
uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: ${{ matrix.jvm }}
cache: 'sbt'
- name: Test
run: sbt ++${{ matrix.scala }} "testOnly treadle2.**"

# Sentinel job to simplify how we specify which checks need to pass in branch
# protection and in Mergify
#
Expand All @@ -175,7 +194,7 @@ jobs:
# separate from a Scala versions build matrix to avoid duplicate publishing
publish:
# note: we do not require a warning check for publishing!
needs: [test, doc, verilator, formal, formal-mac, icarus, test-mac]
needs: [test, doc, verilator, formal, formal-mac, icarus, test-mac, test-treadle]
runs-on: ubuntu-20.04
if: github.event_name == 'push'

Expand Down
2 changes: 0 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ publishTo := {
// Provide a managed dependency on X if -DXVersion="" is supplied on the command line.
val defaultVersions = Map(
"chisel3" -> "3.6-SNAPSHOT",
"treadle" -> "1.6-SNAPSHOT"
)

scalacOptions ++= Seq(
Expand Down Expand Up @@ -84,7 +83,6 @@ scalacOptions ++= Seq(

libraryDependencies ++= Seq(
"edu.berkeley.cs" %% "chisel3" % defaultVersions("chisel3"),
"edu.berkeley.cs" %% "treadle" % defaultVersions("treadle"),
"org.scalatest" %% "scalatest" % "3.2.15",
"com.lihaoyi" %% "utest" % "0.8.1",
"net.java.dev.jna" % "jna" % "5.13.0",
Expand Down
15 changes: 3 additions & 12 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ object chiseltest extends mill.Cross[chiseltestCrossModule]("2.13.10")

val defaultVersions = Map(
"chisel3" -> "3.6-SNAPSHOT",
"treadle" -> "1.6-SNAPSHOT"
)

def getVersion(dep: String, org: String = "edu.berkeley.cs") = {
Expand Down Expand Up @@ -40,14 +39,6 @@ class chiseltestCrossModule(val crossScalaVersion: String)
Agg(ivy"edu.berkeley.cs:::chisel3-plugin:${defaultVersions("chisel3")}")
} else Agg.empty[Dep]

def treadleModule: Option[PublishModule] = None

def treadleIvyDeps = if (treadleModule.isEmpty)
Agg(
getVersion("treadle")
)
else Agg.empty[Dep]

override def millSourcePath = super.millSourcePath / os.up

// 2.12.12 -> Array("2", "12", "12") -> "12" -> 12
Expand All @@ -74,7 +65,7 @@ class chiseltestCrossModule(val crossScalaVersion: String)
ivy"org.scalatest::scalatest:3.2.15",
ivy"com.lihaoyi::utest:0.8.1",
ivy"net.java.dev.jna:jna:5.13.0"
) ++ chisel3IvyDeps ++ treadleIvyDeps
) ++ chisel3IvyDeps
}

override def scalacPluginIvyDeps = T { chisel3PluginIvyDeps }
Expand All @@ -84,11 +75,11 @@ class chiseltestCrossModule(val crossScalaVersion: String)
}

object test_1 extends Tests with TestModule.ScalaTest with ScalafmtModule {
override def ivyDeps = T { chisel3IvyDeps ++ treadleIvyDeps }
override def ivyDeps = T { chisel3IvyDeps }
}

object test_2 extends Tests with TestModule.Utest with ScalafmtModule {
override def ivyDeps = T { chisel3IvyDeps ++ treadleIvyDeps }
override def ivyDeps = T { chisel3IvyDeps }
}

def pomSettings = T {
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/chiseltest/experimental/Async.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ package chiseltest.experimental
import chisel3._
import chisel3.experimental.{ExtModule, IntParam}
import firrtl.ir.{Param, Type}
import treadle.executable.{PositiveEdge, Transition}
import treadle.{ScalaBlackBox, ScalaBlackBoxFactory}
import treadle2.executable.{PositiveEdge, Transition}
import treadle2.{ScalaBlackBox, ScalaBlackBoxFactory}

/** Temporary and bleeding edge features with no guarantee of forwards compatibility
* This isn't in its own package object because that contributes to name mangling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Author: Kevin Laeufer <laeufer@cs.berkeley.edu>
package chiseltest.formal.backends

import treadle.vcd
import treadle2.vcd
import chiseltest.formal.backends.smt._
import firrtl.backends.experimental.smt._

Expand Down
13 changes: 6 additions & 7 deletions src/main/scala/chiseltest/simulator/TreadleSimulator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@ package chiseltest.simulator
import firrtl.annotations.Annotation
import firrtl.stage.FirrtlCircuitAnnotation
import firrtl.{AnnotationSeq, CircuitState}
import treadle.{ClockInfoAnnotation, TreadleTester, TreadleTesterAnnotation}
import treadle.executable.{ClockInfo, StopException}
import treadle.stage.TreadleTesterPhase
import treadle2.{ClockInfoAnnotation, TreadleTester, TreadleTesterAnnotation}
import treadle2.executable.{ClockInfo, StopException}
import treadle2.stage.TreadleTesterPhase

case object TreadleBackendAnnotation extends SimulatorAnnotation {
override def getSimulator: Simulator = TreadleSimulator
}

private object TreadleSimulator extends Simulator {
override def name: String = "treadle"
override def name: String = "treadle2"
override def isAvailable: Boolean = true
def findVersions(): Unit = {
println("treadle is available")
println(s"version: ${treadle.BuildInfo.version}")
}
override def waveformFormats = Seq(WriteVcdAnnotation)
override def supportsCoverage = true
Expand Down Expand Up @@ -48,8 +47,8 @@ private object TreadleSimulator extends Simulator {
}

private def translateAnnotation(a: Annotation): Annotation = a match {
case WriteVcdAnnotation => treadle.WriteVcdAnnotation
case PlusArgsAnnotation(args) => treadle.PlusArgsAnnotation(args)
case WriteVcdAnnotation => treadle2.WriteVcdAnnotation
case PlusArgsAnnotation(args) => treadle2.PlusArgsAnnotation(args)
case other => other
}

Expand Down
1 change: 1 addition & 0 deletions src/main/scala/treadle2/Driver.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

108 changes: 108 additions & 0 deletions src/main/scala/treadle2/ScalaBlackBox.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// SPDX-License-Identifier: Apache-2.0

package treadle2

import firrtl.ir.{Param, Type}
import treadle2.blackboxes.PlusArg
import treadle2.executable.Transition

import scala.collection.mutable

/** This is the template for writing Scala functions that implement the behaviour of a
* black box. Implementing classes should add internal
* variables to hold any state information.
*/
//TODO: Consider providing a VCD hook here, so internal state can be dumped
trait ScalaBlackBox {
def name: String
def completeName(componentName: String): String = s"$name.$componentName"

/** This method will be called for each input symbol of the black box.
* This method should be overridden
* @param name the name of the input to this black box
* @param value the latest value computed for this input. It may not be different than the current value
*/
def inputChanged(name: String, value: BigInt): Unit = {}

/** getOutput is called to determine the value for the named output at the
* current state of the system. The proper way to do this is to not use the inputValues.
* Instead use[[inputChanged]] to supply a black box with its inputs.
*
* @param inputValues This is a list of BigInt values that are in the same order
* as the outputDependencies lists them
* @param tpe The concrete type of this output
* @param outputName The name of this output
* @return Computed current concrete value for the name output
*/
def getOutput(inputValues: Seq[BigInt], tpe: Type, outputName: String = ""): BigInt

/** Called whenever the cycle command of the engine is called.
* @param transition, tells whether clock went up or down or didn't change.
* @param clockName name of the clock, only need if there are multiple clocks
*/
def clockChange(transition: Transition, clockName: String = ""): Unit = {}

/** returns a list of names of inputs that this output depends on.
* @note The order of this list will determine the order of the inputValues argument to the getOutput method
* @param outputName the output whose dependencies are being described
* @return
*/
def outputDependencies(outputName: String): Seq[String]

/** returns a list of dependencies between ports.
* @note There is one bit of hand-waving magic to make black boxes work when they have internal state.
* In order to satisfy the single pass assignment to every wire, black boxes with state must specify that
* their inputs depend on their outputs, in order to get the correct topological sort. See the AsyncResetBlackBox
* test to see an example of how this was done.
* @return
*/
def getDependencies: Seq[(String, Set[String])] = {
Seq.empty
}

/** Add any parameters to the black box implementation
*/
def setParams(params: Seq[Param]): Unit = {}

/** allows blackbox to see if any plus args on command line are targeted at it
*
* @param plusArgs list of args
*/
def setPlusArgs(plusArgs: Seq[PlusArg]): Unit = {}

/** Called by TreadleTester#finish
* override this method to perform any cleanup necessary
*/
def finish(): Unit = {}
}

/** For each instantiation of an ExtModule the engine needs a separate instance of
* a BlackBoxImplementation. This factory provides it.
* @example {{{
* class ExampleBBFactory extends BlackBoxFactory {
* override def createInstance(instanceName: String, blackBoxName: String): Option[BlackBoxImplementation] = {
* instanceName match {
* case "bb1" => Some(add(new BB1Impl))
* case "bb2" => Some(add(new BB2Impl))
* case "bb3" => Some(add(new BB3Impl))
* case _ => throw Exception(s"ExampleBBBFactory does not know how to create " + instanceName)
* }
* }
* }
* }}}
*/
abstract class ScalaBlackBoxFactory {
val boxes: mutable.HashMap[String, ScalaBlackBox] = new mutable.HashMap[String, ScalaBlackBox]

def add(blackBox: ScalaBlackBox): ScalaBlackBox = {
boxes(blackBox.name) = blackBox
blackBox
}

/** This function will be called during treadle compilation.
* @param instanceName The name of the specific instance being created
* @param blackBoxName The BlackBox implementation name
* @return
*/
def createInstance(instanceName: String, blackBoxName: String): Option[ScalaBlackBox]
}
Loading

0 comments on commit a6b1091

Please sign in to comment.