summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Koenig2016-12-21 14:33:07 -0800
committerJack Koenig2017-02-08 18:00:32 -0800
commit66a72ff64c46d8a9fdade77223de62b4dcfe2825 (patch)
tree8ff97057072ed7ec1e1c64b3f1db774e2c09f99e
parent132b80edee2fb8e730d3b6f5eb5f36051a819525 (diff)
Add Analog type
Used for stitching Verilog inout through Chisel Modules (from BlackBox to BlackBox)
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Attach.scala45
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala32
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Bits.scala49
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala1
-rw-r--r--src/main/scala/chisel3/internal/firrtl/Emitter.scala1
-rw-r--r--src/main/scala/chisel3/package.scala4
-rw-r--r--src/test/resources/AnalogBlackBox.v27
-rw-r--r--src/test/scala/chiselTests/AnalogIntegrationSpec.scala128
-rw-r--r--src/test/scala/chiselTests/AnalogSpec.scala211
9 files changed, 497 insertions, 1 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Attach.scala b/chiselFrontend/src/main/scala/chisel3/core/Attach.scala
new file mode 100644
index 00000000..5e767b84
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Attach.scala
@@ -0,0 +1,45 @@
+// See LICENSE for license details.
+
+package chisel3.core
+
+import chisel3.internal._
+import chisel3.internal.Builder.pushCommand
+import chisel3.internal.firrtl._
+import chisel3.internal.sourceinfo.{SourceInfo}
+
+object attach { // scalastyle:ignore object.name
+ // Exceptions that can be generated by attach
+ case class AttachException(message: String) extends Exception(message)
+ def ConditionalAttachException =
+ AttachException(": Conditional attach is not allowed!")
+
+ // Actual implementation
+ private[core] def impl(elts: Seq[Analog], contextModule: Module)(implicit sourceInfo: SourceInfo): Unit = {
+ if (Builder.whenDepth != 0) throw ConditionalAttachException
+
+ // TODO Check that references are valid and can be attached
+
+ pushCommand(Attach(sourceInfo, elts.map(_.lref)))
+ }
+
+ /** Create an electrical connection between [[Analog]] components
+ *
+ * @param elts The components to attach
+ *
+ * @example
+ * {{{
+ * val a1 = Wire(Analog(32.W))
+ * val a2 = Wire(Analog(32.W))
+ * attach(a1, a2)
+ * }}}
+ */
+ def apply(elts: Analog*)(implicit sourceInfo: SourceInfo): Unit = {
+ try {
+ impl(elts, Builder.forcedModule)
+ } catch {
+ case AttachException(message) =>
+ throwException(elts.mkString("Attaching (", ", ", s") failed @$message"))
+ }
+ }
+}
+
diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
index b17239e7..825dbad7 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
@@ -2,8 +2,10 @@
package chisel3.core
+import chisel3.internal.Builder
import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl.Connect
+import chisel3.internal.firrtl.{Attach, Connect}
+import chisel3.internal.throwException
import scala.language.experimental.macros
import chisel3.internal.sourceinfo._
@@ -42,6 +44,9 @@ object BiConnect {
BiConnectException(s": Right Record missing field ($field).")
def MismatchedException(left: String, right: String) =
BiConnectException(s": Left ($left) and Right ($right) have different types.")
+ def AttachAlreadyBulkConnectedException(sourceInfo: SourceInfo) =
+ BiConnectException(sourceInfo.makeMessage(": Analog previously bulk connected at " + _))
+
/** This function is what recursively tries to connect a left and right together
*
@@ -52,6 +57,13 @@ object BiConnect {
def connect(sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Data, right: Data, context_mod: Module): Unit =
(left, right) match {
// Handle element case (root case)
+ case (left_a: Analog, right_a: Analog) =>
+ try {
+ analogAttach(sourceInfo, left_a, right_a, context_mod)
+ } catch {
+ // If attach fails, convert to BiConnectException
+ case attach.AttachException(message) => throw BiConnectException(message)
+ }
case (left_e: Element, right_e: Element) => {
elemConnect(sourceInfo, connectCompileOptions, left_e, right_e, context_mod)
// TODO(twigg): Verify the element-level classes are connectable
@@ -235,4 +247,22 @@ object BiConnect {
// so just error out
else throw UnknownRelationException
}
+
+ // This function checks if analog element-level attaching is allowed
+ // Then it either issues it or throws the appropriate exception.
+ def analogAttach(implicit sourceInfo: SourceInfo, left: Analog, right: Analog, contextModule: Module): Unit = {
+ // Error if left or right is BICONNECTED in the current module already
+ for (elt <- left :: right :: Nil) {
+ elt.biConnectLocs.get(contextModule) match {
+ case Some(sl) => throw AttachAlreadyBulkConnectedException(sl)
+ case None => // Do nothing
+ }
+ }
+
+ // Do the attachment
+ attach.impl(Seq(left, right), contextModule)
+ // Mark bulk connected
+ left.biConnectLocs(contextModule) = sourceInfo
+ right.biConnectLocs(contextModule) = sourceInfo
+ }
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
index 96ea137f..bf134771 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
@@ -3,6 +3,7 @@
package chisel3.core
import scala.language.experimental.macros
+import collection.mutable
import chisel3.internal._
import chisel3.internal.Builder.{pushCommand, pushOp}
@@ -1020,3 +1021,51 @@ object FixedPoint {
}
}
+
+/** Data type for representing bidirectional bitvectors of a given width
+ *
+ * Analog support is limited to allowing wiring up of Verilog BlackBoxes with bidirectional (inout)
+ * pins. There is currently no support for reading or writing of Analog types within Chisel code.
+ *
+ * Given that Analog is bidirectional, it is illegal to assign a direction to any Analog type. It
+ * is legal to "flip" the direction (since Analog can be a member of aggregate types) which has no
+ * effect.
+ *
+ * Analog types are generally connected using the bidirectional [[attach]] mechanism, but also
+ * support limited bulkconnect `<>`. Analog types are only allowed to be bulk connected *once* in a
+ * given module. This is to prevent any surprising consequences of last connect semantics.
+ *
+ * @note This API is experimental and subject to change
+ */
+final class Analog private (width: Width) extends Element(width) {
+ require(width.known, "Since Analog is only for use in BlackBoxes, width must be known")
+
+ // Used to enforce single bulk connect of Analog types, multi-attach is still okay
+ // Note that this really means 1 bulk connect per Module because a port can
+ // be connected in the parent module as well
+ private[core] val biConnectLocs = mutable.Map.empty[Module, SourceInfo]
+
+ // Define setter/getter pairing
+ // Analog can only be bound to Ports and Wires (and Unbound)
+ private[core] override def binding_=(target: Binding): Unit = target match {
+ case (_: UnboundBinding | _: WireBinding | PortBinding(_, None)) => super.binding_=(target)
+ case _ => throwException("Only Wires and Ports can be of type Analog")
+ }
+ private[core] override def cloneTypeWidth(w: Width): this.type =
+ new Analog(w).asInstanceOf[this.type]
+ private[chisel3] def toType = s"Analog$width"
+ def cloneType: this.type = cloneTypeWidth(width)
+ // What do flatten and fromBits mean?
+ private[chisel3] def flatten: IndexedSeq[Bits] =
+ throwException("Chisel Internal Error: Analog cannot be flattened into Bits")
+ def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type =
+ throwException("Analog does not support fromBits")
+ final def toPrintable: Printable = PString("Analog")
+}
+/** Object that provides factory methods for [[Analog]] objects
+ *
+ * @note This API is experimental and subject to change
+ */
+object Analog {
+ def apply(width: Width): Analog = new Analog(width)
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
index 50400034..bee72817 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
@@ -263,6 +263,7 @@ case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command
case class WhenEnd(sourceInfo: SourceInfo) extends Command
case class Connect(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
case class BulkConnect(sourceInfo: SourceInfo, loc1: Node, loc2: Node) extends Command
+case class Attach(sourceInfo: SourceInfo, locs: Seq[Node]) extends Command
case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
case class Stop(sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Command
case class Port(id: Data, dir: Direction)
diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
index 42bc6c30..eb00e333 100644
--- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala
+++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
@@ -25,6 +25,7 @@ private class Emitter(circuit: Circuit) {
case e: DefMemPort[_] => s"${e.dir} mport ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}], ${e.clock.fullName(ctx)}"
case e: Connect => s"${e.loc.fullName(ctx)} <= ${e.exp.fullName(ctx)}"
case e: BulkConnect => s"${e.loc1.fullName(ctx)} <- ${e.loc2.fullName(ctx)}"
+ case e: Attach => e.locs.map(_.fullName(ctx)).mkString("attach (", ", ", ")")
case e: Stop => s"stop(${e.clock.fullName(ctx)}, UInt<1>(1), ${e.ret})"
case e: Printf =>
val (fmt, args) = e.pable.unpack(ctx)
diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala
index a5d782ea..a236d3da 100644
--- a/src/main/scala/chisel3/package.scala
+++ b/src/main/scala/chisel3/package.scala
@@ -264,6 +264,10 @@ package object chisel3 { // scalastyle:ignore package.object.name
type RawParam = chisel3.core.RawParam
val RawParam = chisel3.core.RawParam
+ type Analog = chisel3.core.Analog
+ val Analog = chisel3.core.Analog
+ val attach = chisel3.core.attach
+
// Implicit conversions for BlackBox Parameters
implicit def fromIntToIntParam(x: Int): IntParam = IntParam(BigInt(x))
implicit def fromLongToIntParam(x: Long): IntParam = IntParam(BigInt(x))
diff --git a/src/test/resources/AnalogBlackBox.v b/src/test/resources/AnalogBlackBox.v
new file mode 100644
index 00000000..79e74a13
--- /dev/null
+++ b/src/test/resources/AnalogBlackBox.v
@@ -0,0 +1,27 @@
+
+module AnalogReaderBlackBox(
+ inout [31:0] bus,
+ output [31:0] out
+);
+ assign bus = 32'dz;
+ assign out = bus;
+endmodule
+
+module AnalogWriterBlackBox(
+ inout [31:0] bus,
+ input [31:0] in
+);
+ assign bus = in;
+endmodule
+
+module AnalogBlackBox #(
+ parameter index=0
+) (
+ inout [31:0] bus,
+ input port_0_in_valid,
+ input [31:0] port_0_in_bits,
+ output [31:0] port_0_out
+);
+ assign port_0_out = bus;
+ assign bus = (port_0_in_valid)? port_0_in_bits + index : 32'dZ;
+endmodule
diff --git a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala
new file mode 100644
index 00000000..92f89e06
--- /dev/null
+++ b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala
@@ -0,0 +1,128 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import chisel3._
+import chisel3.util._
+import chisel3.testers.BasicTester
+import chisel3.experimental._
+
+/* This test is different from AnalogSpec in that it uses more complicated black boxes that can each
+ * drive the bidirectional bus. It was created to evaluate Analog with synthesis tools since the
+ * simple tests in AnalogSpec don't anything interesting in them to synthesize.
+ */
+
+class AnalogBlackBoxPort extends Bundle {
+ val in = Input(Valid(UInt(32.W)))
+ val out = Output(UInt(32.W))
+}
+
+// This IO can be used for a single BlackBox or to group multiple
+// Has multiple ports for driving and checking but only one shared bus
+class AnalogBlackBoxIO(n: Int) extends Bundle {
+ require(n > 0)
+ val bus = Analog(32.W)
+ val port = Vec(n, new AnalogBlackBoxPort)
+}
+
+// Assigns bus to out
+// Assigns in.bits + index to bus when in.valid
+class AnalogBlackBox(index: Int) extends BlackBox(Map("index" -> index)) {
+ val io = IO(new AnalogBlackBoxIO(1))
+}
+
+// Wraps up n blackboxes, connecing their buses and simply forwarding their ports up
+class AnalogBlackBoxWrapper(n: Int, idxs: Seq[Int]) extends Module {
+ require(n > 0)
+ val io = IO(new AnalogBlackBoxIO(n))
+ val bbs = idxs.map(i => Module(new AnalogBlackBox(i)))
+ io.bus <> bbs.head.io.bus // Always bulk connect io.bus to first bus
+ io.port <> bbs.flatMap(_.io.port) // Connect ports
+ attach(bbs.map(_.io.bus):_*) // Attach all the buses
+}
+
+// Common superclass for AnalogDUT and AnalogSmallDUT
+abstract class AnalogDUTModule(numBlackBoxes: Int) extends Module {
+ require(numBlackBoxes > 0)
+ val io = IO(new Bundle {
+ val ports = Vec(numBlackBoxes, new AnalogBlackBoxPort)
+ })
+}
+
+/** Single test case for lots of things
+ *
+ * $ - Wire at top connecting child inouts (Done in AnalogDUT)
+ * $ - Port inout connected to 1 or more children inouts (AnalogBackBoxWrapper)
+ * $ - Multiple port inouts connected (AnalogConnector)
+ */
+class AnalogDUT extends AnalogDUTModule(5) { // 5 BlackBoxes
+ val mods = Seq(
+ Module(new AnalogBlackBoxWrapper(1, Seq(0))),
+ Module(new AnalogBlackBox(1)),
+ Module(new AnalogBlackBoxWrapper(2, Seq(2, 3))), // 2 blackboxes
+ Module(new AnalogBlackBox(4))
+ )
+ // Connect all ports to top
+ io.ports <> mods.flatMap(_.io.port)
+ // Attach first 3 Modules
+ attach(mods.take(3).map(_.io.bus):_*)
+ // Attach last module to 1st through AnalogConnector
+ val con = Module(new AnalogConnector)
+ attach(con.io.bus1, mods.head.io.bus)
+ attach(con.io.bus2, mods.last.io.bus)
+}
+
+/** Same as [[AnalogDUT]] except it omits [[AnalogConnector]] because that is currently not
+ * supported by Verilator
+ * @todo Delete once Verilator can handle [[AnalogDUT]]
+ */
+class AnalogSmallDUT extends AnalogDUTModule(4) { // 4 BlackBoxes
+ val mods = Seq(
+ Module(new AnalogBlackBoxWrapper(1, Seq(0))),
+ Module(new AnalogBlackBox(1)),
+ Module(new AnalogBlackBoxWrapper(2, Seq(2, 3))) // 2 BlackBoxes
+ )
+ // Connect all ports to top
+ io.ports <> mods.flatMap(_.io.port)
+ // Attach first 3 Modules
+ attach(mods.take(3).map(_.io.bus):_*)
+}
+
+
+// This tester is primarily intended to be able to pass the dut to synthesis
+class AnalogIntegrationTester(mod: => AnalogDUTModule) extends BasicTester {
+ val BusValue = 2.U(32.W) // arbitrary
+
+ val dut = Module(mod)
+
+ val expectedValue = Wire(UInt(32.W))
+ expectedValue := BusValue // Overridden each cycle
+
+ val (cycle, done) = Counter(true.B, dut.io.ports.size)
+ for ((dut, idx) <- dut.io.ports.zipWithIndex) {
+ printf(p"@$cycle: BlackBox #$idx: $dut\n")
+ // Defaults
+ dut.in.valid := false.B
+ dut.in.bits := BusValue
+ // Error checking
+ assert(dut.out === expectedValue)
+
+ when (cycle === idx.U) {
+ expectedValue := BusValue + idx.U
+ dut.in.valid := true.B
+
+ }
+ }
+ when (done) { stop() }
+}
+
+class AnalogIntegrationSpec extends ChiselFlatSpec {
+ behavior of "Verilator"
+ it should "support simple bidirectional wires" in {
+ assertTesterPasses(new AnalogIntegrationTester(new AnalogSmallDUT), Seq("/AnalogBlackBox.v"))
+ }
+ // Use this test once Verilator supports alias
+ ignore should "support arbitrary bidirectional wires" in {
+ assertTesterPasses(new AnalogIntegrationTester(new AnalogDUT), Seq("/AnalogBlackBox.v"))
+ }
+}
diff --git a/src/test/scala/chiselTests/AnalogSpec.scala b/src/test/scala/chiselTests/AnalogSpec.scala
new file mode 100644
index 00000000..576a5a1f
--- /dev/null
+++ b/src/test/scala/chiselTests/AnalogSpec.scala
@@ -0,0 +1,211 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import chisel3._
+import chisel3.util._
+import chisel3.testers.BasicTester
+import chisel3.experimental.{Analog, attach}
+
+// IO for Modules that just connect bus to out
+class AnalogReaderIO extends Bundle {
+ val bus = Analog(32.W)
+ val out = Output(UInt(32.W))
+}
+// IO for Modules that drive bus from in (there should be only 1)
+class AnalogWriterIO extends Bundle {
+ val bus = Analog(32.W)
+ val in = Input(UInt(32.W))
+}
+
+trait AnalogReader {
+ self: Module =>
+ final val io = self.IO(new AnalogReaderIO)
+}
+
+class AnalogReaderBlackBox extends BlackBox with AnalogReader
+
+class AnalogReaderWrapper extends Module with AnalogReader {
+ val mod = Module(new AnalogReaderBlackBox)
+ io <> mod.io
+}
+class AnalogWriterBlackBox extends BlackBox {
+ val io = IO(new AnalogWriterIO)
+}
+// Connects two Analog ports
+class AnalogConnector extends Module {
+ val io = IO(new Bundle {
+ val bus1 = Analog(32.W)
+ val bus2 = Analog(32.W)
+ })
+ io.bus1 <> io.bus2
+}
+
+// Parent class for tests connecing up AnalogReaders and AnalogWriters
+abstract class AnalogTester extends BasicTester {
+ final val BusValue = "hdeadbeef".U
+
+ final val (cycle, done) = Counter(true.B, 2)
+ when (done) { stop() }
+
+ final val writer = Module(new AnalogWriterBlackBox)
+ writer.io.in := BusValue
+
+ final def check(reader: Module with AnalogReader): Unit =
+ assert(reader.io.out === BusValue)
+}
+
+class AnalogSpec extends ChiselFlatSpec {
+ behavior of "Analog"
+
+ it should "NOT be bindable to registers" in {
+ a [ChiselException] should be thrownBy {
+ elaborate { new Module {
+ val io = IO(new Bundle {})
+ val reg = Reg(Analog(32.W))
+ }}
+ }
+ }
+
+ it should "NOT be bindable to a direction" in {
+ a [ChiselException] should be thrownBy {
+ elaborate { new Module {
+ val io = IO(new Bundle {
+ val a = Input(Analog(32.W))
+ })
+ }}
+ }
+ a [ChiselException] should be thrownBy {
+ elaborate { new Module {
+ val io = IO(new Bundle {
+ val a = Output(Analog(32.W))
+ })
+ }}
+ }
+ }
+
+ it should "be flippable" in {
+ elaborate { new Module {
+ val io = IO(new Bundle {
+ val a = Flipped(Analog(32.W))
+ })
+ }}
+ }
+
+ // There is no binding on the type of a memory
+ // Should this be an error?
+ ignore should "NOT be a legal type for Mem" in {
+ a [ChiselException] should be thrownBy {
+ elaborate { new Module {
+ val io = IO(new Bundle {})
+ val mem = Mem(16, Analog(32.W))
+ }}
+ }
+ }
+
+ it should "NOT be bindable to Mem ports" in {
+ a [ChiselException] should be thrownBy {
+ elaborate { new Module {
+ val io = IO(new Bundle {})
+ val mem = Mem(16, Analog(32.W))
+ val port = mem(5.U)
+ }}
+ }
+ }
+
+ // TODO This should probably be caught in Chisel
+ // Also note this relies on executing Firrtl from Chisel directly
+ it should "NOT be connectable to UInts" in {
+ a [Exception] should be thrownBy {
+ runTester { new BasicTester {
+ val uint = Wire(init = 0.U(32.W))
+ val sint = Wire(Analog(32.W))
+ sint := uint
+ }}
+ }
+ }
+
+ it should "work with 2 blackboxes bulk connected" in {
+ assertTesterPasses(new AnalogTester {
+ val mod = Module(new AnalogReaderBlackBox)
+ mod.io.bus <> writer.io.bus
+ check(mod)
+ }, Seq("/AnalogBlackBox.v"))
+ }
+
+ it should "error if any bulk connected more than once" in {
+ a [ChiselException] should be thrownBy {
+ elaborate(new Module {
+ val io = IO(new Bundle {})
+ val wires = List.fill(3)(Wire(Analog(32.W)))
+ wires(0) <> wires(1)
+ wires(0) <> wires(2)
+ })
+ }
+ }
+
+ it should "work with 3 blackboxes attached" in {
+ assertTesterPasses(new AnalogTester {
+ val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox))
+ attach(writer.io.bus, mods(0).io.bus, mods(1).io.bus)
+ mods.foreach(check(_))
+ }, Seq("/AnalogBlackBox.v"))
+ }
+
+ it should "work with 3 blackboxes separately attached via a wire" in {
+ assertTesterPasses(new AnalogTester {
+ val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox))
+ val busWire = Wire(Analog(32.W))
+ attach(busWire, writer.io.bus)
+ attach(busWire, mods(0).io.bus)
+ attach(mods(1).io.bus, busWire)
+ mods.foreach(check(_))
+ }, Seq("/AnalogBlackBox.v"))
+ }
+
+ // This does not currently work in Verilator unless Firrtl does constant prop and dead code
+ // elimination on these wires
+ ignore should "work with intermediate wires attached to each other" in {
+ assertTesterPasses(new AnalogTester {
+ val mod = Module(new AnalogReaderBlackBox)
+ val busWire = Seq.fill(2)(Wire(Analog(32.W)))
+ attach(busWire(0), writer.io.bus)
+ attach(busWire(1), mod.io.bus)
+ attach(busWire(0), busWire(1))
+ check(mod)
+ }, Seq("/AnalogBlackBox.v"))
+ }
+
+ it should "work with blackboxes at different levels of the module hierarchy" in {
+ assertTesterPasses(new AnalogTester {
+ val mods = Seq(Module(new AnalogReaderBlackBox), Module(new AnalogReaderWrapper))
+ val busWire = Wire(writer.io.bus)
+ attach(writer.io.bus, mods(0).io.bus, mods(1).io.bus)
+ mods.foreach(check(_))
+ }, Seq("/AnalogBlackBox.v"))
+ }
+
+ // This does not currently work in Verilator, but does work in VCS
+ ignore should "support two analog ports in the same module" in {
+ assertTesterPasses(new AnalogTester {
+ val reader = Module(new AnalogReaderBlackBox)
+ val connector = Module(new AnalogConnector)
+ connector.io.bus1 <> writer.io.bus
+ reader.io.bus <> connector.io.bus2
+ check(reader)
+ }, Seq("/AnalogBlackBox.v"))
+ }
+
+ it should "NOT support conditional connection of analog types" in {
+ a [ChiselException] should be thrownBy {
+ assertTesterPasses(new AnalogTester {
+ val mod = Module(new AnalogReaderBlackBox)
+ when (cycle > 3.U) {
+ mod.io.bus <> writer.io.bus
+ }
+ check(mod)
+ }, Seq("/AnalogBlackBox.v"))
+ }
+ }
+}
+