Skip to content

Commit

Permalink
Merge branch '1.2.x' into 1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ucbjrl committed Apr 10, 2018
2 parents 57a7d2e + a1ce3f5 commit 55ecb28
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 34 deletions.
8 changes: 4 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def javacOptionsVersion(scalaVersion: String): Seq[String] = {
}

organization := "edu.berkeley.cs"
version := "1.2.0-RC1"
version := "1.2.0-RC2"
name := "Chisel.iotesters"

scalaVersion := "2.11.12"
Expand All @@ -45,9 +45,9 @@ crossScalaVersions := Seq("2.11.12", "2.12.4")
// Provide a managed dependency on X if -DXVersion="" is supplied on the command line.
// The following are the release versions, not the default development versions.
val defaultVersions = Map(
"chisel3" -> "3.1.0-RC1",
"firrtl" -> "1.1.0-RC1",
"firrtl-interpreter" -> "1.1.0-RC1"
"chisel3" -> "3.1.0-RC2",
"firrtl" -> "1.1.0-RC2",
"firrtl-interpreter" -> "1.1.0-RC2"
)

libraryDependencies ++= Seq("chisel3","firrtl","firrtl-interpreter").map { dep: String =>
Expand Down
17 changes: 9 additions & 8 deletions src/main/scala/chisel3/iotesters/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package chisel3.iotesters

import chisel3._
import chisel3.experimental.MultiIOModule
import java.io.File

import firrtl.{ExecutionOptionsManager, HasFirrtlOptions}
Expand All @@ -27,7 +28,7 @@ object Driver {
* @param testerGen A peek poke tester with tests for the dut
* @return Returns true if all tests in testerGen pass
*/
def execute[T <: Module](
def execute[T <: MultiIOModule](
dutGenerator: () => T,
optionsManager: TesterOptionsManager
)
Expand Down Expand Up @@ -84,7 +85,7 @@ object Driver {
* @param testerGen A peek-poke tester with test for the dey
* @return Returns true if all tests in testerGen pass
*/
def execute[T <: Module](args: Array[String], dut: () => T)(
def execute[T <: MultiIOModule](args: Array[String], dut: () => T)(
testerGen: T => PeekPokeTester[T]
): Boolean = {
val optionsManager = new TesterOptionsManager
Expand Down Expand Up @@ -116,7 +117,7 @@ object Driver {
* @param optionsManager options
* @return
*/
def executeFirrtlRepl[T <: Module](
def executeFirrtlRepl[T <: MultiIOModule](
dutGenerator: () => T,
optionsManager: ReplOptionsManager = new ReplOptionsManager): Boolean = {

Expand Down Expand Up @@ -162,7 +163,7 @@ object Driver {
* @param args options from the command line
* @return
*/
def executeFirrtlRepl[T <: Module](
def executeFirrtlRepl[T <: MultiIOModule](
args: Array[String],
dutGenerator: () => T
): Boolean = {
Expand Down Expand Up @@ -214,7 +215,7 @@ object Driver {
* @param testerGen This is a test harness subclassing PeekPokeTester for dutGen,
* @return This will be true if all tests in the testerGen pass
*/
def apply[T <: Module](
def apply[T <: MultiIOModule](
dutGen: () => T,
backendType: String = "firrtl",
verbose: Boolean = false,
Expand All @@ -232,7 +233,7 @@ object Driver {
* Runs the ClassicTester using the verilator backend without doing Verilator compilation and returns a Boolean indicating success or failure
* Requires the caller to supply path the already compile Verilator binary
*/
def run[T <: Module](dutGen: () => T, cmd: Seq[String])
def run[T <: MultiIOModule](dutGen: () => T, cmd: Seq[String])
(testerGen: T => PeekPokeTester[T]): Boolean = {
val circuit = chisel3.Driver.elaborate(dutGen)
val dut = getTopModule(circuit).asInstanceOf[T]
Expand All @@ -253,11 +254,11 @@ object Driver {
}
}

def run[T <: Module](dutGen: () => T, binary: String, args: String*)
def run[T <: MultiIOModule](dutGen: () => T, binary: String, args: String*)
(testerGen: T => PeekPokeTester[T]): Boolean =
run(dutGen, binary +: args.toSeq)(testerGen)

def run[T <: Module](dutGen: () => T, binary: File, waveform: Option[File] = None)
def run[T <: MultiIOModule](dutGen: () => T, binary: File, waveform: Option[File] = None)
(testerGen: T => PeekPokeTester[T]): Boolean = {
val args = waveform match {
case None => Nil
Expand Down
10 changes: 7 additions & 3 deletions src/main/scala/chisel3/iotesters/FirrtlTerpBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@
package chisel3.iotesters

import chisel3._
import chisel3.experimental.MultiIOModule
import chisel3.internal.InstanceId
import firrtl.{FirrtlExecutionFailure, FirrtlExecutionSuccess}
import firrtl_interpreter._

private[iotesters] class FirrtlTerpBackend(
dut: Module,
dut: MultiIOModule,
firrtlIR: String,
optionsManager: TesterOptionsManager with HasInterpreterSuite = new TesterOptionsManager)
extends Backend(_seed = System.currentTimeMillis()) {
val interpretiveTester = new InterpretiveTester(firrtlIR, optionsManager)
reset(5) // reset firrtl interpreter on construction

private val portNames = getDataNames("io", dut.io).toMap
private val portNames = dut.getPorts.flatMap { case chisel3.internal.firrtl.Port(id, dir) =>
val pathName = id.pathName
getDataNames(pathName.drop(pathName.indexOf('.') + 1), id)
}.toMap

def poke(signal: InstanceId, value: BigInt, off: Option[Int])
(implicit logger: TestErrorLog, verbose: Boolean, base: Int): Unit = {
Expand Down Expand Up @@ -113,7 +117,7 @@ private[iotesters] class FirrtlTerpBackend(
}

private[iotesters] object setupFirrtlTerpBackend {
def apply[T <: chisel3.Module](
def apply[T <: MultiIOModule](
dutGen: () => T,
optionsManager: TesterOptionsManager = new TesterOptionsManager): (T, Backend) = {

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/chisel3/iotesters/PeekPokeTester.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.io.File
import chisel3._
import chisel3.core.{Aggregate, Element}
import PeekPokeTester.extractElementBits
import chisel3.experimental.FixedPoint
import chisel3.experimental.{FixedPoint, MultiIOModule}
import chisel3.internal.firrtl.KnownBinaryPoint

import scala.collection.immutable.ListMap
Expand Down Expand Up @@ -51,7 +51,7 @@ object PeekPokeTester {
}
}

abstract class PeekPokeTester[+T <: Module](
abstract class PeekPokeTester[+T <: MultiIOModule](
val dut: T,
base: Int = 16,
logFile: Option[File] = None) {
Expand Down
9 changes: 6 additions & 3 deletions src/main/scala/chisel3/iotesters/PeekPokeTesterUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ private[iotesters] object getDataNames {
case b: Record => b.elements.toSeq flatMap {case (n, e) => apply(s"${name}_$n", e)}
case v: Vec[_] => v.zipWithIndex flatMap {case (e, i) => apply(s"${name}_$i", e)}
}
def apply(dut: Module, separator: String = "."): Seq[(Element, String)] =
apply(dut.io.pathName replace (".", separator), dut.io)
def apply(dut: MultiIOModule, separator: String = "."): Seq[(Element, String)] =
dut.getPorts.flatMap { case chisel3.internal.firrtl.Port(data, _) =>
apply(data.pathName replace (".", separator), data)
}

}

private[iotesters] object getPorts {
def apply(dut: Module, separator: String = "."): (Seq[(Element, String)], Seq[(Element, String)]) =
def apply(dut: MultiIOModule, separator: String = "."): (Seq[(Element, String)], Seq[(Element, String)]) =
getDataNames(dut, separator) partition { case (e, _) => DataMirror.directionOf(e) == ActualDirection.Input }
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/chisel3/iotesters/SimApiInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package chisel3.iotesters


import chisel3._
import chisel3.experimental.MultiIOModule

import scala.collection.mutable.{ArrayBuffer, HashMap}
import scala.collection.immutable.ListMap
Expand All @@ -12,7 +13,7 @@ import scala.sys.process.{Process, ProcessLogger}
import java.io.{File, PrintStream}
import java.nio.channels.FileChannel

private[iotesters] class SimApiInterface(dut: Module, cmd: Seq[String]) {
private[iotesters] class SimApiInterface(dut: MultiIOModule, cmd: Seq[String]) {
val (inputsNameToChunkSizeMap, outputsNameToChunkSizeMap) = {
val (inputs, outputs) = getPorts(dut)
def genChunk(args: (Data, String)) = args match {
Expand Down
26 changes: 17 additions & 9 deletions src/main/scala/chisel3/iotesters/VCSBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import java.io.{File, FileWriter, IOException, Writer}
import java.nio.file.{FileAlreadyExistsException, Files, Paths}
import java.nio.file.StandardCopyOption.REPLACE_EXISTING

import chisel3.core.{ActualDirection, DataMirror}
import chisel3.{ChiselExecutionFailure, ChiselExecutionSuccess}
import chisel3.{ChiselExecutionFailure, ChiselExecutionSuccess, Element}
import chisel3.experimental.MultiIOModule
import firrtl.{ChirrtlForm, CircuitState}
import firrtl.annotations.CircuitName
import firrtl.transforms.{BlackBoxSourceHelper, BlackBoxTargetDirAnno}
import firrtl.transforms.BlackBoxTargetDirAnno

/**
* Copies the necessary header files used for verilator compilation to the specified destination folder
Expand Down Expand Up @@ -44,11 +43,20 @@ object copyVpiFiles {
* Generates the Module specific verilator harness cpp file for verilator compilation
*/
object genVCSVerilogHarness {
def apply(dut: chisel3.Module, writer: Writer, vpdFilePath: String, isGateLevel: Boolean = false) {
def apply(dut: MultiIOModule, writer: Writer, vpdFilePath: String, isGateLevel: Boolean = false) {
val dutName = dut.name
val (inputs, outputs) = getDataNames("io", dut.io).partition {
case (e, _) => DataMirror.directionOf(e) == ActualDirection.Input
// getPorts() is going to return names prefixed with the dut name.
// These don't correspond to code currently generated for verilog modules,
// so we have to strip the dut name prefix (and the delimiter) from the name.
// We tell getPorts() to use "_" as the delimiter to simplify the replacement regexp.
def fixnames(portSeq: (Seq[(Element, String)], Seq[(Element, String)])): (Seq[(Element, String)], Seq[(Element, String)]) = {
val replaceRegexp = ("^" + dutName + "_").r
(
portSeq._1 map { case (e: Element, s: String) => (e, replaceRegexp.replaceFirstIn(s, ""))},
portSeq._2 map { case (e: Element, s: String) => (e, replaceRegexp.replaceFirstIn(s, ""))}
)
}
val (inputs, outputs) = fixnames(getPorts(dut, "_"))

writer write "module test;\n"
writer write " reg clock = 1;\n"
Expand Down Expand Up @@ -118,7 +126,7 @@ object genVCSVerilogHarness {
}

private[iotesters] object setupVCSBackend {
def apply[T <: chisel3.Module](dutGen: () => T, optionsManager: TesterOptionsManager): (T, Backend) = {
def apply[T <: MultiIOModule](dutGen: () => T, optionsManager: TesterOptionsManager): (T, Backend) = {
optionsManager.makeTargetDir()
optionsManager.chiselOptions = optionsManager.chiselOptions.copy(
runFirrtlCompiler = false
Expand Down Expand Up @@ -180,7 +188,7 @@ private[iotesters] object setupVCSBackend {
}
}

private[iotesters] class VCSBackend(dut: chisel3.Module,
private[iotesters] class VCSBackend(dut: MultiIOModule,
cmd: Seq[String],
_seed: Long = System.currentTimeMillis)
extends VerilatorBackend(dut, cmd, _seed)
8 changes: 4 additions & 4 deletions src/main/scala/chisel3/iotesters/VerilatorBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import java.nio.file.StandardCopyOption.REPLACE_EXISTING
import java.nio.file.{FileAlreadyExistsException, Files, Paths}

import chisel3._
import chisel3.experimental.FixedPoint
import chisel3.experimental.{FixedPoint, MultiIOModule}
import chisel3.internal.InstanceId
import firrtl._
import firrtl.annotations.CircuitName
Expand Down Expand Up @@ -38,7 +38,7 @@ object copyVerilatorHeaderFiles {
* Generates the Module specific verilator harness cpp file for verilator compilation
*/
object VerilatorCppHarnessGenerator {
def codeGen(dut: chisel3.Module, state: CircuitState, vcdFilePath: String): String = {
def codeGen(dut: MultiIOModule, state: CircuitState, vcdFilePath: String): String = {
val codeBuffer = new StringBuilder

def pushBack(vector: String, pathName: String, width: BigInt) {
Expand Down Expand Up @@ -191,7 +191,7 @@ object VerilatorCppHarnessGenerator {
}

private[iotesters] object setupVerilatorBackend {
def apply[T <: chisel3.Module](dutGen: () => T, optionsManager: TesterOptionsManager): (T, Backend) = {
def apply[T <: MultiIOModule](dutGen: () => T, optionsManager: TesterOptionsManager): (T, Backend) = {
import firrtl.{ChirrtlForm, CircuitState}

optionsManager.makeTargetDir()
Expand Down Expand Up @@ -269,7 +269,7 @@ private[iotesters] object setupVerilatorBackend {
}
}

private[iotesters] class VerilatorBackend(dut: Module,
private[iotesters] class VerilatorBackend(dut: MultiIOModule,
cmd: Seq[String],
_seed: Long = System.currentTimeMillis) extends Backend(_seed) {

Expand Down
46 changes: 46 additions & 0 deletions src/test/scala/examples/MultiIOModule.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// See LICENSE for license details.

package examples

import chisel3._
import chisel3.experimental.MultiIOModule
import chisel3.util._
import chisel3.iotesters._
import org.scalatest.{Matchers, FlatSpec}


class MultiIOAdder extends MultiIOModule {
val a = IO(Input(UInt(4.W)))
val b = IO(Input(UInt(4.W)))
val c = IO(Output(UInt(5.W)))

c := a +& b
}

class MultiIOAdderTester(c: MultiIOAdder) extends PeekPokeTester(c) {
for {
i <- 0 until 15
j <- 0 until 15
} {
poke(c.a, i)
poke(c.b, j)
expect(c.c, i + j)
}
}

class MultiIOModuleSpec extends FlatSpec with Matchers {
behavior of "MuiltiIOAdder"

it should "test correctly for every i/o combination with verilator" in {
val args = Array("--backend-name", "verilator")
iotesters.Driver.execute(args, () => new MultiIOAdder) { c =>
new MultiIOAdderTester(c)
} should be (true)
}
it should "test correctly for every i/o combination with firrtl" in {
val args = Array("--backend-name", "firrtl")
iotesters.Driver.execute(args, () => new MultiIOAdder) { c =>
new MultiIOAdderTester(c)
} should be (true)
}
}

0 comments on commit 55ecb28

Please sign in to comment.