mirror of https://github.com/llvm/circt.git
295 lines
20 KiB
MLIR
295 lines
20 KiB
MLIR
// RUN: circt-opt -firrtl-lower-memory %s | FileCheck %s
|
|
|
|
// Test basic lowering of the three port types.
|
|
// CHECK-LABEL: firrtl.circuit "ReadWrite" {
|
|
firrtl.circuit "ReadWrite" {
|
|
// CHECK: firrtl.module private @MReadWrite
|
|
// CHECK: firrtl.instance MReadWrite_ext @MReadWrite_ext
|
|
// CHECK: firrtl.matchingconnect %MReadWrite_ext_RW0_addr, %RW0_addr
|
|
// CHECK: firrtl.matchingconnect %RW0_rdata, %MReadWrite_ext_RW0_rdata
|
|
// CHECK: }
|
|
firrtl.module @ReadWrite() {
|
|
%MReadWrite_readwrite = firrtl.mem Undefined {depth = 12 : i64, name = "MReadWrite", portNames = ["readwrite"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, rdata flip: uint<42>, wmode: uint<1>, wdata: uint<42>, wmask: uint<1>>
|
|
// CHECK: firrtl.instance MReadWrite @MReadWrite(in RW0_addr: !firrtl.uint<4>, in RW0_en: !firrtl.uint<1>, in RW0_clk: !firrtl.clock, in RW0_wmode: !firrtl.uint<1>, in RW0_wdata: !firrtl.uint<42>, out RW0_rdata: !firrtl.uint<42>)
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: firrtl.circuit "Write"
|
|
firrtl.circuit "Write" {
|
|
firrtl.module @Write() {
|
|
%MWrite_write = firrtl.mem Undefined {depth = 12 : i64, name = "MWrite", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance MWrite @MWrite(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>)
|
|
}
|
|
}
|
|
|
|
// SeqMems need at least 1 write port, but this is primarily testing the Read
|
|
// port.
|
|
firrtl.circuit "Read" {
|
|
// CHECK: firrtl.memmodule private @MRead_ext
|
|
// CHECK-SAME: {dataWidth = 42 : ui32, depth = 12 : ui64, extraPorts = [], maskBits = 1 : ui32, numReadPorts = 1 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 1 : ui32, readLatency = 1 : ui32, writeLatency = 1 : ui32}
|
|
firrtl.module @Read() {
|
|
%MRead_read, %MRead_write = firrtl.mem Undefined {depth = 12 : i64, name = "MRead", portNames = ["read", "write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<42>>, !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance MRead @MRead(in R0_addr: !firrtl.uint<4>, in R0_en: !firrtl.uint<1>, in R0_clk: !firrtl.clock, out R0_data: !firrtl.uint<42>, in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>)
|
|
}
|
|
}
|
|
|
|
// Test that the memory wrapper module is renamed when there is a collision.
|
|
// CHECK-LABEL: firrtl.circuit "Collision0"
|
|
firrtl.circuit "Collision0" {
|
|
// @test collides with the name of the wrapper module.
|
|
firrtl.extmodule @test()
|
|
// CHECK: firrtl.module private @test_0
|
|
// CHECK-NEXT: firrtl.instance test_ext @test_ext
|
|
firrtl.module @Collision0() {
|
|
%MWrite_write = firrtl.mem Undefined {depth = 12 : i64, name = "test", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance test @test_0
|
|
}
|
|
}
|
|
|
|
// Test that the memory module is renamed when there is a collision.
|
|
// CHECK-LABEL: firrtl.circuit "Collision1"
|
|
firrtl.circuit "Collision1" {
|
|
// @test_ext collides with the name of the external memory module.
|
|
firrtl.extmodule @test_ext()
|
|
// CHECK: firrtl.module private @test
|
|
// CHECK-NEXT: firrtl.instance test_0_ext @test_0_ext
|
|
// CHECK: firrtl.memmodule private @test_0_ext
|
|
firrtl.module @Collision1() {
|
|
%MWrite_write = firrtl.mem Undefined {depth = 12 : i64, name = "test", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance test @test
|
|
}
|
|
}
|
|
|
|
// Test that the memory modules are deduplicated.
|
|
// CHECK-LABEL: firrtl.circuit "Dedup"
|
|
firrtl.circuit "Dedup" {
|
|
// CHECK: firrtl.module private @mem0
|
|
// CHECK-NEXT: firrtl.instance mem0_ext @mem0_ext
|
|
|
|
// CHECK: firrtl.memmodule private @mem0_ext
|
|
|
|
// CHECK: firrtl.module private @mem1
|
|
// CHECK-NEXT: firrtl.instance mem0_ext @mem0_ext
|
|
firrtl.module @Dedup() {
|
|
%mem0_write = firrtl.mem Undefined {depth = 12 : i64, name = "mem0", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
%mem1_write = firrtl.mem Undefined {depth = 12 : i64, name = "mem1", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance mem0 @mem0(
|
|
// CHECK: firrtl.instance mem1 @mem1(
|
|
}
|
|
}
|
|
|
|
// Test that memories in the testharness are not deduped with other memories in
|
|
// the test harness.
|
|
// CHECK-LABEL: firrtl.circuit "NoTestharnessDedup0"
|
|
firrtl.circuit "NoTestharnessDedup0" {
|
|
// CHECK: firrtl.module private @mem0
|
|
// CHECK-NEXT: firrtl.instance mem0_ext @mem0_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>)
|
|
|
|
// CHECK: firrtl.memmodule private @mem0_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) attributes {dataWidth = 42 : ui32, depth = 12 : ui64, extraPorts = [], maskBits = 1 : ui32, numReadPorts = 0 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 1 : ui32, readLatency = 1 : ui32, writeLatency = 1 : ui32}
|
|
|
|
// CHECK: firrtl.module private @mem1
|
|
// CHECK-NEXT: firrtl.instance mem1_ext @mem1_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>)
|
|
|
|
// CHECK: firrtl.memmodule private @mem1_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) attributes {dataWidth = 42 : ui32, depth = 12 : ui64, extraPorts = [], maskBits = 1 : ui32, numReadPorts = 0 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 1 : ui32, readLatency = 1 : ui32, writeLatency = 1 : ui32}
|
|
firrtl.module @NoTestharnessDedup0() {
|
|
%mem0_write = firrtl.mem Undefined {depth = 12 : i64, name = "mem0", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance mem0 @mem0
|
|
%mem1_write = firrtl.mem Undefined {depth = 12 :i64, name = "mem1", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance mem1 @mem1
|
|
firrtl.instance dut @DUT()
|
|
}
|
|
firrtl.module @DUT() attributes {annotations = [{class = "sifive.enterprise.firrtl.MarkDUTAnnotation"}]} { }
|
|
}
|
|
|
|
// Test that memories in the testharness are not deduped with other memories in the DUT.
|
|
// CHECK-LABEL: firrtl.circuit "NoTestharnessDedup1"
|
|
firrtl.circuit "NoTestharnessDedup1" {
|
|
// CHECK: firrtl.module private @mem0
|
|
// CHECK-NEXT: firrtl.instance mem0_ext @mem0_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>)
|
|
|
|
// CHECK: firrtl.memmodule private @mem0_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) attributes {dataWidth = 42 : ui32, depth = 12 : ui64, extraPorts = [], maskBits = 1 : ui32, numReadPorts = 0 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 1 : ui32, readLatency = 1 : ui32, writeLatency = 1 : ui32}
|
|
firrtl.module @NoTestharnessDedup1() {
|
|
%mem0_write = firrtl.mem Undefined {depth = 12 : i64, name = "mem0", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance mem0 @mem0
|
|
firrtl.instance dut @DUT()
|
|
}
|
|
// CHECK: firrtl.module private @mem1
|
|
// CHECK-NEXT: firrtl.instance mem1_ext @mem1_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>)
|
|
|
|
// CHECK: firrtl.memmodule private @mem1_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) attributes {dataWidth = 42 : ui32, depth = 12 : ui64, extraPorts = [], maskBits = 1 : ui32, numReadPorts = 0 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 1 : ui32, readLatency = 1 : ui32, writeLatency = 1 : ui32}
|
|
firrtl.module @DUT() attributes {annotations = [{class = "sifive.enterprise.firrtl.MarkDUTAnnotation"}]} {
|
|
%mem1_write = firrtl.mem Undefined {depth = 12 :i64, name = "mem1", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
// CHECK: firrtl.instance mem1 @mem1
|
|
}
|
|
}
|
|
|
|
// Check that when the mask is 1-bit, it is removed from the memory and the
|
|
// enable signal is and'd with the mask signal.
|
|
// CHECK-LABEL: firrtl.circuit "NoMask"
|
|
firrtl.circuit "NoMask" {
|
|
firrtl.module @NoMask(in %en: !firrtl.uint<1>, in %mask: !firrtl.uint<1>) {
|
|
%MemSimple_read, %MemSimple_write = firrtl.mem Undefined {depth = 12 : i64, name = "MemSimple", portNames = ["read", "write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<42>>, !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
|
|
// Enable:
|
|
%0 = firrtl.subfield %MemSimple_write[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
firrtl.connect %0, %en : !firrtl.uint<1>, !firrtl.uint<1>
|
|
|
|
// Mask:
|
|
%1 = firrtl.subfield %MemSimple_write[mask] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
firrtl.connect %1, %mask : !firrtl.uint<1>, !firrtl.uint<1>
|
|
|
|
// CHECK: [[AND:%.+]] = firrtl.and %mask, %en
|
|
// CHECK: firrtl.connect %MemSimple_W0_en, [[AND]]
|
|
}
|
|
}
|
|
|
|
// Check a memory with a mask gets lowered properly.
|
|
// CHECK-LABEL: firrtl.circuit "YesMask"
|
|
firrtl.circuit "YesMask" {
|
|
firrtl.module @YesMask(in %en: !firrtl.uint<1>, in %mask: !firrtl.uint<4>) {
|
|
%MemSimple_read, %MemSimple_write = firrtl.mem Undefined {depth = 1022 : i64, name = "MemSimple", portNames = ["read", "write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<10>, en: uint<1>, clk: clock, data flip: uint<40>>, !firrtl.bundle<addr: uint<10>, en: uint<1>, clk: clock, data: uint<40>, mask: uint<4>>
|
|
|
|
// Enable:
|
|
%0 = firrtl.subfield %MemSimple_write[en] : !firrtl.bundle<addr: uint<10>, en: uint<1>, clk: clock, data: uint<40>, mask: uint<4>>
|
|
firrtl.connect %0, %en : !firrtl.uint<1>, !firrtl.uint<1>
|
|
|
|
// Mask:
|
|
%1 = firrtl.subfield %MemSimple_write[mask] : !firrtl.bundle<addr: uint<10>, en: uint<1>, clk: clock, data: uint<40>, mask: uint<4>>
|
|
firrtl.connect %1, %mask : !firrtl.uint<4>, !firrtl.uint<4>
|
|
|
|
// CHECK: firrtl.connect %MemSimple_W0_en, %en
|
|
// CHECK: firrtl.connect %MemSimple_W0_mask, %mask
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: firrtl.circuit "MemDepth1"
|
|
firrtl.circuit "MemDepth1" {
|
|
// CHECK: firrtl.memmodule private @mem0_ext
|
|
// CHECK-SAME: depth = 1
|
|
firrtl.module @MemDepth1(in %clock: !firrtl.clock, in %en: !firrtl.uint<1>,
|
|
in %addr: !firrtl.uint<1>, in %data: !firrtl.uint<32>) {
|
|
// CHECK: firrtl.instance mem0 @mem0(in W0_addr: !firrtl.uint<1>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<32>, in W0_mask: !firrtl.uint<4>)
|
|
// CHECK: firrtl.connect %mem0_W0_data, %data : !firrtl.uint<32>
|
|
%mem0_write = firrtl.mem Old {depth = 1 : i64, name = "mem0", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<32>, mask: uint<4>>
|
|
%1 = firrtl.subfield %mem0_write[addr] : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<32>, mask: uint<4>>
|
|
firrtl.connect %1, %addr : !firrtl.uint<1>, !firrtl.uint<1>
|
|
%3 = firrtl.subfield %mem0_write[en] : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<32>, mask: uint<4>>
|
|
firrtl.connect %3, %en : !firrtl.uint<1>, !firrtl.uint<1>
|
|
%0 = firrtl.subfield %mem0_write[clk] : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<32>, mask: uint<4>>
|
|
firrtl.connect %0, %clock : !firrtl.clock, !firrtl.clock
|
|
%2 = firrtl.subfield %mem0_write[data] : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<32>, mask: uint<4>>
|
|
firrtl.connect %2, %data : !firrtl.uint<32>, !firrtl.uint<32>
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: firrtl.circuit "inferUnmaskedMemory"
|
|
firrtl.circuit "inferUnmaskedMemory" {
|
|
firrtl.module @inferUnmaskedMemory(in %clock: !firrtl.clock, in %rAddr: !firrtl.uint<4>, in %rEn: !firrtl.uint<1>, out %rData: !firrtl.uint<8>, in %wMode: !firrtl.uint<1>, in %wMask: !firrtl.uint<1>, in %wData: !firrtl.uint<8>) {
|
|
%tbMemoryKind1_r, %tbMemoryKind1_w = firrtl.mem Undefined {depth = 16 : i64, modName = "tbMemoryKind1_ext", name = "tbMemoryKind1", portNames = ["r", "w"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<8>>, !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%0 = firrtl.subfield %tbMemoryKind1_w[data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%1 = firrtl.subfield %tbMemoryKind1_w[mask] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%2 = firrtl.subfield %tbMemoryKind1_w[addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%3 = firrtl.subfield %tbMemoryKind1_w[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%4 = firrtl.subfield %tbMemoryKind1_w[clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%5 = firrtl.subfield %tbMemoryKind1_r[data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
%6 = firrtl.subfield %tbMemoryKind1_r[addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
%7 = firrtl.subfield %tbMemoryKind1_r[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
%8 = firrtl.subfield %tbMemoryKind1_r[clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
firrtl.connect %8, %clock : !firrtl.clock, !firrtl.clock
|
|
firrtl.connect %7, %rEn : !firrtl.uint<1>, !firrtl.uint<1>
|
|
firrtl.connect %6, %rAddr : !firrtl.uint<4>, !firrtl.uint<4>
|
|
firrtl.connect %rData, %5 : !firrtl.uint<8>, !firrtl.uint<8>
|
|
firrtl.connect %4, %clock : !firrtl.clock, !firrtl.clock
|
|
firrtl.connect %3, %rEn : !firrtl.uint<1>, !firrtl.uint<1>
|
|
firrtl.connect %2, %rAddr : !firrtl.uint<4>, !firrtl.uint<4>
|
|
firrtl.connect %1, %wMask : !firrtl.uint<1>, !firrtl.uint<1>
|
|
firrtl.connect %0, %wData : !firrtl.uint<8>, !firrtl.uint<8>
|
|
// CHECK: [[AND:%.+]] = firrtl.and %wMask, %rEn
|
|
// CHECK: firrtl.connect %tbMemoryKind1_W0_en, %0
|
|
%MReadWrite_readwrite = firrtl.mem Undefined {depth = 12 : i64, name = "MReadWrite", portNames = ["readwrite"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, rdata flip: uint<42>, wmode: uint<1>, wdata: uint<42>, wmask: uint<1>>
|
|
%rw_en = firrtl.subfield %MReadWrite_readwrite[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, rdata flip: uint<42>, wmode: uint<1>, wdata: uint<42>, wmask: uint<1>>
|
|
%rw_wmode = firrtl.subfield %MReadWrite_readwrite[wmode] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, rdata flip: uint<42>, wmode: uint<1>, wdata: uint<42>, wmask: uint<1>>
|
|
%rw_mask = firrtl.subfield %MReadWrite_readwrite[wmask] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, rdata flip: uint<42>, wmode: uint<1>, wdata: uint<42>, wmask: uint<1>>
|
|
firrtl.connect %rw_en, %rEn : !firrtl.uint<1>, !firrtl.uint<1>
|
|
firrtl.connect %rw_wmode, %wMode : !firrtl.uint<1>, !firrtl.uint<1>
|
|
firrtl.connect %rw_mask, %wMask : !firrtl.uint<1>, !firrtl.uint<1>
|
|
// CHECK: %[[MReadWrite_RW0_addr:.+]], %[[MReadWrite_RW0_en:.+]], %[[MReadWrite_RW0_clk:.+]], %[[MReadWrite_RW0_wmode:.+]], %[[MReadWrite_RW0_wdata:.+]], %[[MReadWrite_RW0_rdata:.+]] = firrtl.instance MReadWrite @MReadWrite
|
|
// CHECK: firrtl.connect %[[MReadWrite_RW0_en]], %rEn : !firrtl.uint<1>
|
|
// CHECK: %1 = firrtl.and %wMask, %wMode : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
|
|
// CHECK: firrtl.connect %[[MReadWrite_RW0_wmode]], %1 : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// Check that annotations are copied over to the instance.
|
|
// CHECK-LABEL: firrtl.circuit "Annotations"
|
|
firrtl.circuit "Annotations" {
|
|
// CHECK: firrtl.module private @mem0
|
|
// CHECK-NEXT: firrtl.instance mem0_ext {annotations = [{class = "test"}]} @mem0_ex
|
|
firrtl.module @Annotations() attributes {annotations = [{class = "sifive.enterprise.firrtl.MarkDUTAnnotation"}]} {
|
|
// No annotations copied to this instance.
|
|
// CHECK: irrtl.instance mem0 @mem0
|
|
%mem0_write = firrtl.mem Undefined {annotations = [{class = "test"}], depth = 12 : i64, name = "mem0", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
}
|
|
}
|
|
|
|
// Check that annotations are copied over to the instance.
|
|
// CHECK-LABEL: firrtl.circuit "NonLocalAnnotation"
|
|
firrtl.circuit "NonLocalAnnotation" {
|
|
|
|
// CHECK: hw.hierpath private @[[nla_0:.+]] [@NonLocalAnnotation::@dut, @DUT::@[[MEM0:.+]], @mem0]
|
|
hw.hierpath private @nla0 [@NonLocalAnnotation::@dut, @DUT::@mem0]
|
|
// CHECK: hw.hierpath private @[[nla_1:.+]] [@NonLocalAnnotation::@dut, @DUT::@[[MEM1:.+]], @mem1]
|
|
hw.hierpath private @nla1 [@NonLocalAnnotation::@dut, @DUT]
|
|
|
|
// CHECK: firrtl.module @NonLocalAnnotation()
|
|
firrtl.module @NonLocalAnnotation() {
|
|
firrtl.instance dut sym @dut @DUT()
|
|
}
|
|
// CHECK: firrtl.module private @mem0
|
|
// CHECK: firrtl.instance mem0_ext sym @mem0_ext
|
|
// CHECK-SAME: {annotations = [{circt.nonlocal = @[[nla_0]], class = "test0"}]}
|
|
// CHECK-SAME: @mem0_ext(
|
|
// CHECK: }
|
|
|
|
// CHECK: firrtl.module private @mem1
|
|
// CHECK: firrtl.instance mem0_ext sym @mem0_ext
|
|
// CHECK-SAME: {annotations = [{circt.nonlocal = @[[nla_1]], class = "test1"}]}
|
|
// CHECK-SAME: @mem0_ext(
|
|
|
|
// CHECK: firrtl.module @DUT()
|
|
firrtl.module @DUT() {
|
|
// This memory has a symbol and an NLA directly targetting it.
|
|
// CHECK: firrtl.instance mem0 sym @[[MEM0]] @mem0
|
|
%mem0_write = firrtl.mem sym @mem0 Undefined {annotations = [{circt.nonlocal = @nla0, class = "test0"}], depth = 12 : i64, name = "mem0", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
|
|
// This memory does not have a symbol already attached.
|
|
// CHECK: firrtl.instance mem1 sym @[[MEM1]] @mem1
|
|
%mem1_write = firrtl.mem Undefined {annotations = [{circt.nonlocal = @nla1, class = "test1"}], depth = 12 : i64, name = "mem1", portNames = ["write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>>
|
|
|
|
// LowerMemory should ignore MemOps that are not seqmems. The following memory is a combmem with readLatency=0.
|
|
%MRead_read = firrtl.mem Undefined {depth = 12 : i64, name = "MRead", portNames = ["read"], readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<42>>
|
|
// CHECK: %MRead_read = firrtl.mem Undefined
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: "MemoryInLayer"
|
|
firrtl.circuit "MemoryInLayer" {
|
|
firrtl.layer @A bind {}
|
|
firrtl.module @MemoryInLayer() {
|
|
|
|
// CHECK: firrtl.layerblock @A
|
|
// CHECK-NEXT: firrtl.instance mem
|
|
firrtl.layerblock @A {
|
|
%mem_w = firrtl.mem sym @mem Undefined {
|
|
annotations = [],
|
|
depth = 2 : i64,
|
|
name = "mem",
|
|
portNames = ["w"],
|
|
readLatency = 1 : i32,
|
|
writeLatency = 1 : i32
|
|
} : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<1>, mask: uint<1>>
|
|
}
|
|
|
|
}
|
|
}
|