Skip to content

SRAM.masked broken when the mask is a constant of all 1s #5243

Description

@elipsitz

Type of issue: Bug Report

Please provide the steps to reproduce the problem:

I'm instantiating an SRAM with 2 read-write ports. I need byte-masking on one of the ports, but not the other:

val mem = SRAM.masked(16 * 1024, Vec(4, UInt(8.W)), numReadPorts = 0, numWritePorts = 0, numReadwritePorts = 2)
val memHostPort = mem.readwritePorts(0)
val memDevicePort = mem.readwritePorts(1)

memDevicePort is linked up with another submodule that uses the byte-mask. memHostPort connects to the Module's IO ports.

Then, I have this, to set the writeMask to 1111 for this port:

val writeMask = Wire(Vec(4, Bool()))
writeMask := VecInit(true.B, true.B, true.B, true.B)
memHostPort.mask.get := writeMask

What is the current behavior?

When producing SystemVerilog output, Chisel/CIRCT ends up producing a module mem_mem_sram_16384x32 for the SRAM, and in my parent Module, passes it (SystemVerilog)

mem_mem_sram_16384x32 mem_mem_sram_ext (
  .RW0_wmask ({_GEN_3, _GEN_4, _GEN_5, _GEN_6}),
  ...
  .RW1_wmask (4'h1)
);

which is, of course, the wrong mask for port 1. The mask for port 0 is correct. This is generated with:

ChiselStage.emitSystemVerilogFile(
    new MyModule(),
    argRest.toArray,
    firtoolOpts = Array(
      "--preserve-aggregate=1d-vec",
    )
)

without --preserve-aggregate=1d-vec, the output is even worse. In the mem_mem_sram_16384x32 module definition, RW0_wmask and RW1_wmask both disappear! So now, there's no masking at all.

What is the expected behavior?

.RW1_wmask (4'hF), to pass all 1s.

Please tell us about your environment:

Version: 7.9.0
OS: macOS Sequoia 15.7.1 (also verified on an Ubuntu 20.04 system).

Other Information
I was previously using Version 6.6.0, which did not have this problem.

I have found a workaround. Wrap the writeMask with dontTouch:

val writeMask = dontTouch(Wire(Vec(4, Bool())))
writeMask := VecInit(true.B, true.B, true.B, true.B)

This produces:

wire [3:0]      mem_writeMask = '{1'h1, 1'h1, 1'h1, 1'h1};

mem_mem_sram_16384x32 mem_mem_sram_ext (
  .RW0_wmask ({_GEN_3, _GEN_4, _GEN_5, _GEN_6}),
  ...
  .RW1_wmask (mem_writeMask)
);

and without --preserve-aggregate=1d-vec, the masks are still there and correct.

    .RW0_wmask
      ({mem_mem_sram_RW1_wmask_3,
        mem_mem_sram_RW1_wmask_2,
        mem_mem_sram_RW1_wmask_1,
        mem_mem_sram_RW1_wmask_0}),
    ...
    .RW1_wmask ({mem_writeMask_3, mem_writeMask_2, mem_writeMask_1, mem_writeMask_0})

I'll also note that, weirdly enough, other constant values (other than b1111) work. e.g.:

    val writeMask = Wire(Vec(4, Bool()))
    writeMask := VecInit(true.B, true.B, true.B, false.B)

generates:

.RW1_wmask (4'h7)

and every other combination I've tried also works, except for 1111.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions