chipsalliance / chipsalliance/chisel
Confusing bundle connection behavior with SRAM API
- Dominant language
- Scala
- Stars
- 4.8k
- Forks
- 658
- Avg merge
- 18h 59m
- Merged PRs (30d)
- 14
Description
**Type of issue**: Bug Report
**Please provide the steps to reproduce the problem:**
The scala-cli snippet below gives a few different errors that you can cause:
- Set `readerUnintError` to `true`
- Set `writerUnintError` to `true`
- Comment out the existing `myMem.writePorts` connection, and use one of the other commented-out options
```scala
//> using scala 2.13.16
//> using repository https://s01.oss.sonatype.org/content/repositories/snapshots
//> using dep org.chipsalliance::chisel:7.0.0-RC1+28-2f256a83-SNAPSHOT
//> using plugin org.chipsalliance:::chisel-plugin:7.0.0-RC1+28-2f256a83-SNAPSHOT
//> using options -unchecked -deprecation -language:reflectiveCalls -feature -Xcheckinit -Xfatal-warnings -Ywarn-dead-code -Ywarn-unused -Ymacro-annotations
import chisel3._
import chisel3.util._
class Reader(readPort: MemoryReadPort[UInt], uninitError: Boolean = false) extends Module {
// `Flipped` because default `MemoryReadPort` alignment is `Input`
val port = IO(Flipped(readPort))
if (uninitError) {
port :<= DontCare
} else {
port.address :<= DontCare
port.enable :<= DontCare
}
}
class Writer(writePort: MemoryWritePort[UInt], uninitError: Boolean = false) extends Module {
// `Flipped` because default `MemoryWritePort` alignment is `Input`
val port = IO(Flipped(writePort))
if (uninitError) {
port :<= DontCare
} else {
port.address :<= DontCare
port.data :<= DontCare
port.enable :<= DontCare
}
}
class Foo extends Module {
val myMem = SRAM(8, UInt(5.W), 1, 1, 0)
val readPort = chiselTypeOf(myMem.readPorts.head)
val writePort = chiselTypeOf(myMem.writePorts.head)
// If set to `true`, firtool error: sink * not fully initialized in "Reader"
val readerUnintError = false
// If set to `true`, firtool error: sink * not fully initialized in "Writer"
val writerUnintError = false
val reader = Module(new Reader(readPort, readerUnintError))
val writer = Module(new Writer(writePort, writerUnintError))
// This works
reader.port :<>= myMem.readPorts.head
// firtool error: sink * not fully initialized in "Foo"
// myMem.writePorts.head :<= writer.port
// Chisel error: port.* in Writer cannot be written from module Foo.
// myMem.writePorts.head :<>= writer.port
// This works, but the LHS-vs-RHS isn't intuitive.
// writer.port :>= myMem.writePorts.head
// This works, has the LHS-vs-RHS I would expect, but is inconvenient due to enumerating each bundle element
myMem.writePorts.head.address :<= writer.port.address
myMem.writePorts.head.data :<= writer.port.data
myMem.writePorts.head.enable :<= writer.port.enable
}
object Main extends App {
import _root_.circt.stage.ChiselStage
println(
ChiselStage.emitSystemVerilog(
new Foo,
firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info", "-default-layer-specialization=enable")
)
)
}
```
**What is the current behavior?**
I'm unable to make connections to the `Memory*Port` bundles that I would expect, perhaps due to their default alignment being `Input` rather than `Output`: https://github.com/chipsalliance/chisel/blob/2f256a835c4f02f53b62f9026f66355216cd6a85/src/main/scala-2/chisel3/util/SRAM.scala#L23-L82
Rather than being able to make connections like `port :<= DontCare`, I either need to break out the fields of `port` and connect to them individually (`port.address :<= DontCare; port.enable :<= DontCare; ...`), or I need to use an unintuitive LHS-vs-RHS style: `DontCare :>= port`. Is this the intended behavior, or is this just an annoying edge case in the `Connectable` (or SRAM) API?
**What is the expected behavior?**
I should be able to connect bundles with matching alignment, and put the producer and consumer on the sides of the Connectable operator that I would expect.
**Please tell us about your environment:**
- version: `7.0.0-RC1+28-2f256a83-SNAPSHOT`
- OS: macOS 15.5
**Other Information**
**What is the use case for changing the behavior?**
Making the Connectable API more convenient for users.
Contributor guide
Research direction
Start with the linked src/main/scala-2/chisel3/util/SRAM.scala section around lines 23-82, then reproduce the scala-cli snippet and inspect the Connectable behavior for MemoryReadPort and MemoryWritePort bundles. Determine whether matching aligned bundles should support the expected connection direction; done means the intended behavior is resolved and the reported connection cases are addressed or clearly documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- developer-experience
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100