Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Fix bug in zero-width memory removal (bp #2153) #2155

Merged
merged 2 commits into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions src/main/scala/firrtl/passes/ZeroWidth.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,27 @@ object ZeroWidth extends Transform with DependencyAPIMigration {
case _ => false
}

private def makeEmptyMemBundle(name: String): Field =
Field(name, Flip, BundleType(Seq(
Field("addr", Default, UIntType(IntWidth(0))),
Field("en", Default, UIntType(IntWidth(0))),
Field("clk", Default, UIntType(IntWidth(0))),
Field("data", Flip, UIntType(IntWidth(0)))
)))
private def makeZero(tpe: ir.Type): ir.Type = tpe match {
case ClockType => UIntType(IntWidth(0))
case a: UIntType => a.copy(IntWidth(0))
case a: SIntType => a.copy(IntWidth(0))
case a: AggregateType => a.map(makeZero)
}

private def onEmptyMemStmt(s: Statement): Statement = s match {
case d @ DefMemory(info, name, tpe, _, _, _, rs, ws, rws, _) => removeZero(tpe) match {
case None =>
DefWire(info, name, BundleType(
rs.map(r => makeEmptyMemBundle(r)) ++
ws.map(w => makeEmptyMemBundle(w)) ++
rws.map(rw => makeEmptyMemBundle(rw))
))
case Some(_) => d
}
case sx => sx map onEmptyMemStmt
case d @ DefMemory(info, name, tpe, _, _, _, rs, ws, rws, _) =>
removeZero(tpe) match {
case None =>
DefWire(
info,
name,
MemPortUtils
.memType(d)
.map(makeZero)
)
case Some(_) => d
}
case sx => sx.map(onEmptyMemStmt)
}

private def onModuleEmptyMemStmt(m: DefModule): DefModule = {
Expand Down
63 changes: 63 additions & 0 deletions src/test/scala/firrtlTests/ZeroWidthTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,69 @@ class ZeroWidthTests extends FirrtlFlatSpec {
| z <= asUInt(y)""".stripMargin
(parse(exec(input))) should be(parse(check))
}

"Memories with zero-width data-type" should "be fully removed" in {
val input =
"""circuit Foo:
| module Foo:
| input clock: Clock
| input rAddr: UInt<4>
| input rEn: UInt<1>
| output rData: UInt<0>
| input wAddr: UInt<4>
| input wEn: UInt<1>
| input wMask: UInt<1>
| input wData: UInt<0>
| input rwEn: UInt<1>
| input rwMode: UInt<1>
| input rwAddr: UInt<1>
| input rwMask: UInt<1>
| input rwDataIn: UInt<0>
| output rwDataOut: UInt<0>
|
| mem memory:
| data-type => UInt<0>
| depth => 16
| reader => r
| writer => w
| readwriter => rw
| read-latency => 0
| write-latency => 1
| read-under-write => undefined
|
| memory.r.clk <= clock
| memory.r.en <= rEn
| memory.r.addr <= rAddr
| rData <= memory.r.data
| memory.w.clk <= clock
| memory.w.en <= wEn
| memory.w.addr <= wAddr
| memory.w.mask <= wMask
| memory.w.data <= wData
| memory.rw.clk <= clock
| memory.rw.en <= rwEn
| memory.rw.addr <= rwAddr
| memory.rw.wmode <= rwMode
| memory.rw.wmask <= rwMask
| memory.rw.wdata <= rwDataIn
| rwDataOut <= memory.rw.rdata""".stripMargin
val check =
s"""circuit Foo:
| module Foo:
| input clock: Clock
| input rAddr: UInt<4>
| input rEn: UInt<1>
| input wAddr: UInt<4>
| input wEn: UInt<1>
| input wMask: UInt<1>
| input rwEn: UInt<1>
| input rwMode: UInt<1>
| input rwAddr: UInt<1>
| input rwMask: UInt<1>
|
|${Seq.tabulate(17)(_ => " skip").mkString("\n")}""".stripMargin
parse(exec(input)) should be(parse(check))
}
}

class ZeroWidthVerilog extends FirrtlFlatSpec {
Expand Down