Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Analog DontCare bulk-connect #1056

Merged
merged 10 commits into from
Jul 19, 2019
35 changes: 18 additions & 17 deletions chiselFrontend/src/main/scala/chisel3/internal/BiConnect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,20 @@ private[chisel3] object BiConnect {
// 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
markAnalogConnected(sourceInfo, left_a, context_mod)
markAnalogConnected(sourceInfo, right_a, context_mod)
} catch { // convert attach exceptions to BiConnectExceptions
case attach.AttachException(message) => throw BiConnectException(message)
}
attach.impl(Seq(left_a, right_a), context_mod)(sourceInfo)
case (left_a: Analog, DontCare) =>
try {
markAnalogConnected(sourceInfo, left_a, context_mod)
} catch { // convert attach exceptions to BiConnectExceptions
case attach.AttachException(message) => throw BiConnectException(message)
}
pushCommand(DefInvalid(sourceInfo, left_a.lref))
case (DontCare, right_a: Analog) => connect(sourceInfo, connectCompileOptions, right, left, context_mod)
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
Expand Down Expand Up @@ -312,21 +321,13 @@ private[chisel3] object BiConnect {
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: RawModule): 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
}
// This function checks if analog element-level attaching is allowed, then marks the Analog as connected
def markAnalogConnected(implicit sourceInfo: SourceInfo, analog: Analog, contextModule: RawModule): Unit = {
analog.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
analog.biConnectLocs(contextModule) = sourceInfo
}
}
14 changes: 13 additions & 1 deletion chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
package chisel3.internal

import chisel3._
import chisel3.experimental.{BaseModule, EnumType, FixedPoint, RawModule, UnsafeEnum}
import chisel3.experimental.{Analog, BaseModule, EnumType, FixedPoint, RawModule, UnsafeEnum}
import chisel3.internal.Builder.pushCommand
import chisel3.internal.firrtl.{Connect, DefInvalid}
import scala.language.experimental.macros
Expand Down Expand Up @@ -52,6 +52,12 @@ private[chisel3] object MonoConnect {
MonoConnectException(s": Sink ($sink) and Source ($source) have different types.")
def DontCareCantBeSink =
MonoConnectException(": DontCare cannot be a connection sink (LHS)")
def AnalogCantBeMonoSink =
MonoConnectException(": Analog cannot participate in a mono connection (sink - LHS)")
def AnalogCantBeMonoSource =
MonoConnectException(": Analog cannot participate in a mono connection (source - RHS)")
def AnalogMonoConnectionException =
MonoConnectException(": Analog cannot participate in a mono connection (source and sink)")
// scalastyle:on method.name public.methods.have.type

/** This function is what recursively tries to connect a sink and source together
Expand Down Expand Up @@ -142,6 +148,12 @@ private[chisel3] object MonoConnect {
case (sink, DontCare) => pushCommand(DefInvalid(sourceInfo, sink.lref))
// DontCare as a sink is illegal.
case (DontCare, _) => throw DontCareCantBeSink
// Analog is illegal in mono connections.
case (_: Analog, _:Analog) => throw AnalogMonoConnectionException
// Analog is illegal in mono connections.
case (_: Analog, _) => throw AnalogCantBeMonoSink
// Analog is illegal in mono connections.
case (_, _: Analog) => throw AnalogCantBeMonoSource
// Sink and source are different subtypes of data so fail
case (sink, source) => throw MismatchedException(sink.toString, source.toString)
}
Expand Down
23 changes: 23 additions & 0 deletions src/test/scala/chiselTests/AnalogSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,29 @@ class AnalogSpec extends ChiselFlatSpec {
wires(0) <> wires(2)
})
}
a [ChiselException] should be thrownBy {
elaborate(new Module {
val io = IO(new Bundle {})
val wires = List.fill(2)(Wire(Analog(32.W)))
wires(0) <> DontCare
wires(0) <> wires(1)
})
}
}

it should "allow DontCare connection" in {
elaborate(new Module {
val io = IO(new Bundle {
val a = Analog(1.W)
})
io.a := DontCare
})
elaborate(new Module {
val io = IO(new Bundle {
val a = Analog(1.W)
})
io.a <> DontCare
})
}

it should "work with 3 blackboxes attached" in {
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/chiselTests/ChiselSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class ChiselTestUtilitiesSpec extends ChiselFlatSpec {
class ChiselPropSpec extends PropSpec with ChiselRunners with PropertyChecks with Matchers {

// Constrain the default number of instances generated for every use of forAll.
implicit override val generatorDrivenConfig =
implicit override val generatorDrivenConfig: PropertyCheckConfiguration =
PropertyCheckConfiguration(minSuccessful = 8, minSize = 1, sizeRange = 3)

// Generator for small positive integers.
Expand Down