diff options
| author | Adam Izraelevitz | 2017-10-26 12:39:42 -0700 |
|---|---|---|
| committer | Jim Lawson | 2017-10-26 12:39:42 -0700 |
| commit | c313e137d4e562ef20195312501840ceab8cbc6a (patch) | |
| tree | 37e290d3c5af672624b9ac267ccb33421acca84e /chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala | |
| parent | 8168a8eea6c3465966081c5acd0347e09791361c (diff) | |
Invalidateapi (#645)
* Require explicit connection to DontCare to generate "is invalid".
* Add tests for RefNotInitializedException.
Currently, we fail the when ... otherwise ...
* Disable ScalaTest shrinking on error in ComplexAssignSpec.
* fix broken merge; still some binding issues
* cleanup DontCare connection checks; add missing directions to test module IOs
* Have library code inherit compileOptions from the enclosing Module (if it exists).
* work around current firrtl uninitialized references with Strict compile options and explicitInvalidate
* more CompileOptions cleanup; move test-specific defines to package object
* minimize differences with master
* set default CompileOptions.explicitInvalidate to false until we fix the FIRRTL when issue
* ignore the StrictCompiler property checks (until CompileOptions.explicitInvalidate is defaulted to true)
* Revert "more CompileOptions cleanup; move test-specific defines to package object"
This reverts commit e4486edcba990d150e76e08a2fc6abca033556e0.
* Revert "work around current firrtl uninitialized references with Strict compile options and explicitInvalidate"
This reverts commit 426faa430a62c3dac2dbdf33044d3386d4243157.
* remove unused code
* Convert to binding-based DontCare implementation
* comment cleanup to minimize differences with master
* Tentatively remove possibly redundant DefInvalid on module ports.
* Respond to code review change request.
- backout build.sbt change
- correct indentation
- handle bulk of DontCare semantics in elemConnect()
- have DontCare extend Element, not Data (eliminate most Object specific methods
- add comments indicating reason for explicit DontCare connections
* Initialize test elements without requiring a DontCare.
* Respond to review change requests.
- DontCare should work on left or right side in BiDirectional connections
- call bind() to set DontCare binding instead of messing with internal variables
- DontCares are only equivalent with DontCares
- clean up processWhens() definition
* Eliminate DontCare connection to inputs in MonoConnect().
* Pull aggregates apart for the purpose of DontCare connections.
* Restore the explicit (conditionally executed) ports DefInvalidin ImplicitModule()
* Don't add DontCare's to the module list of _ids.
* Add missing DefInvalid() to LegacyModule().
* Respond to review requests: add DontCare BiConnect Vec, remove null parent hack to avoid addId(), initialize singletons early in Builder
* Move DontCare out of chisel3.experimental.
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index f2b2b7e1..d056efba 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -2,10 +2,8 @@ package chisel3.core -import chisel3.internal.Builder import chisel3.internal.Builder.pushCommand -import chisel3.internal.firrtl.{Attach, Connect} -import chisel3.internal.throwException +import chisel3.internal.firrtl.{Connect, DefInvalid} import scala.language.experimental.macros import chisel3.internal.sourceinfo._ @@ -46,6 +44,8 @@ object BiConnect { BiConnectException(s": Left ($left) and Right ($right) have different types.") def AttachAlreadyBulkConnectedException(sourceInfo: SourceInfo) = BiConnectException(sourceInfo.makeMessage(": Analog previously bulk connected at " + _)) + def DontCareCantBeSink = + BiConnectException(": DontCare cannot be a connection sink (LHS)") /** This function is what recursively tries to connect a left and right together @@ -54,7 +54,7 @@ object BiConnect { * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. */ - def connect(sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Data, right: Data, context_mod: UserModule): Unit = + def connect(sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Data, right: Data, context_mod: UserModule): Unit = { (left, right) match { // Handle element case (root case) case (left_a: Analog, right_a: Analog) => @@ -69,9 +69,11 @@ object BiConnect { // TODO(twigg): Verify the element-level classes are connectable } // Handle Vec case - case (left_v: Vec[Data @unchecked], right_v: Vec[Data @unchecked]) => { - if(left_v.length != right_v.length) { throw MismatchedVecException } - for(idx <- 0 until left_v.length) { + case (left_v: Vec[Data@unchecked], right_v: Vec[Data@unchecked]) => { + if (left_v.length != right_v.length) { + throw MismatchedVecException + } + for (idx <- 0 until left_v.length) { try { implicit val compileOptions = connectCompileOptions connect(sourceInfo, connectCompileOptions, left_v(idx), right_v(idx), context_mod) @@ -80,6 +82,28 @@ object BiConnect { } } } + // Handle Vec connected to DontCare + case (left_v: Vec[Data@unchecked], DontCare) => { + for (idx <- 0 until left_v.length) { + try { + implicit val compileOptions = connectCompileOptions + connect(sourceInfo, connectCompileOptions, left_v(idx), right, context_mod) + } catch { + case BiConnectException(message) => throw BiConnectException(s"($idx)$message") + } + } + } + // Handle DontCare connected to Vec + case (DontCare, right_v: Vec[Data@unchecked]) => { + for (idx <- 0 until right_v.length) { + try { + implicit val compileOptions = connectCompileOptions + connect(sourceInfo, connectCompileOptions, left, right_v(idx), context_mod) + } catch { + case BiConnectException(message) => throw BiConnectException(s"($idx)$message") + } + } + } // Handle Records defined in Chisel._ code (change to NotStrict) case (left_r: Record, right_r: Record) => (left_r.compileOptions, right_r.compileOptions) match { case (ExplicitCompileOptions.NotStrict, _) => @@ -89,9 +113,40 @@ object BiConnect { case _ => recordConnect(sourceInfo, connectCompileOptions, left_r, right_r, context_mod) } + // Handle Records connected to DontCare (change to NotStrict) + case (left_r: Record, DontCare) => + left_r.compileOptions match { + case ExplicitCompileOptions.NotStrict => + left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions.NotStrict) + case _ => + // For each field in left, descend with right + for ((field, left_sub) <- left_r.elements) { + try { + connect(sourceInfo, connectCompileOptions, left_sub, right, context_mod) + } catch { + case BiConnectException(message) => throw BiConnectException(s".$field$message") + } + } + } + case (DontCare, right_r: Record) => + right_r.compileOptions match { + case ExplicitCompileOptions.NotStrict => + left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions.NotStrict) + case _ => + // For each field in left, descend with right + for ((field, right_sub) <- right_r.elements) { + try { + connect(sourceInfo, connectCompileOptions, left, right_sub, context_mod) + } catch { + case BiConnectException(message) => throw BiConnectException(s".$field$message") + } + } + } + // Left and right are different subtypes of Data so fail case (left, right) => throw MismatchedException(left.toString, right.toString) } + } // Do connection of two Records def recordConnect(sourceInfo: SourceInfo, @@ -128,11 +183,25 @@ object BiConnect { // These functions (finally) issue the connection operation // Issue with right as sink, left as source private def issueConnectL2R(left: Element, right: Element)(implicit sourceInfo: SourceInfo): Unit = { - pushCommand(Connect(sourceInfo, right.lref, left.ref)) + // Source and sink are ambiguous in the case of a Bi/Bulk Connect (<>). + // If either is a DontCareBinding, just issue a DefInvalid for the other, + // otherwise, issue a Connect. + (left.binding, right.binding) match { + case (lb: DontCareBinding, _) => pushCommand(DefInvalid(sourceInfo, right.lref)) + case (_, rb: DontCareBinding) => pushCommand(DefInvalid(sourceInfo, left.lref)) + case (_, _) => pushCommand(Connect(sourceInfo, right.lref, left.ref)) + } } // Issue with left as sink, right as source private def issueConnectR2L(left: Element, right: Element)(implicit sourceInfo: SourceInfo): Unit = { - pushCommand(Connect(sourceInfo, left.lref, right.ref)) + // Source and sink are ambiguous in the case of a Bi/Bulk Connect (<>). + // If either is a DontCareBinding, just issue a DefInvalid for the other, + // otherwise, issue a Connect. + (left.binding, right.binding) match { + case (lb: DontCareBinding, _) => pushCommand(DefInvalid(sourceInfo, right.lref)) + case (_, rb: DontCareBinding) => pushCommand(DefInvalid(sourceInfo, left.lref)) + case (_, _) => pushCommand(Connect(sourceInfo, left.lref, right.ref)) + } } // This function checks if element-level connection operation allowed. |
