chipsalliance / chipsalliance/chisel

Result of operator ## cannot be assigned to

Open
#2,510 2 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 | feature request

**Impact**: API addition (no impact on existing code)

**Development Phase**: proposal

**What is the current behavior?**

Assume two kinds of Blackbox modules, `Slave` and `Master`. Let their interfaces be denoted by `SlaveIf` and `MasterIf`. Now, consider the case where you want to connect two `Master` instances to one of the `Slave` instances like in the following code:

```scala
class SlaveIf extends Bundle {
val inp = Input(UInt(4.W))
val outp = Output(UInt(4.W))
}

class MasterIf extends Bundle {
val inp = Output(UInt(2.W))
val outp = Input(UInt(2.W))
}

class Slave extends BlackBox {
val io = IO(new SlaveIf)
}

class Master extends BlackBox {
val io = IO(new MasterIf)
}

class Tlf extends Module {
val io = IO(new Bundle {
val fnord = Input(UInt(4.W))
})

val xbar = Module(new Slave)
val mst1 = Module(new Master)
val mst2 = Module(new Master)

xbar.io.inp <> (mst1.io.inp ## mst2.io.inp) // works
xbar.io.outp <> (mst1.io.outp ## mst1.io.outp) // !!!!not working!!!!
}
```

`xbar.io.inp <> (mst1.io.inp ## mst2.io.inp)` will roughly produce `assign xbar_inp = {mst1_inp,mst2_inp};` in the Verilog file, but the last line will produce the following runtime exception

```
Exception in thread "main" chisel3.internal.ChiselException: internal error: attempted to generate LHS ref to ReadOnlyBinding OpBinding(chisel_test.Tlf@1dbb650b,None)
at ... ()
at chisel_test.Tlf.(App.scala:38)
at chisel_test.App$.$anonfun$main$1(App.scala:46)
at ... ()
at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
```

Essentially it says that the result of a `##` operator is not writable.

This is overly conservative. Sure, the result of the `+` Operator on UInt cannot be written to, but the result of `##` can be.

**What is the expected behavior?**

The code should produce three module instances, some wires and the following two assignments

```
assign xbar_inp = {mst1_inp,mst2_inp};
assign {mst1_outp, mst2_outp} = xbar_outp
```

**Environment:**

- Chisel version: 3.5.2
- Latest macOS

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with the Slave, Master, and Tlf example in the report using Chisel 3.5.2, then trace how the ## result is classified during the <> connection. Done means the example elaborates without the ReadOnlyBinding exception and emits assignments equivalent to the two shown in the report.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
embedded-iot
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.