chipsalliance / chipsalliance/chisel

Confusing bundle connection behavior with SRAM API

Open
#4,945 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.