Skip to content

Commit b4da671

Browse files
committed
[FIRRTL] FlattenMemories: handle memories with enums
This adds support to flatten memories with enumeration in them. Enumerations are treated as non-aggregate types, and so they get a single bit mask to control the whole value.
1 parent 0c5f60c commit b4da671

File tree

3 files changed

+36
-34
lines changed

3 files changed

+36
-34
lines changed

lib/Dialect/FIRRTL/FIRRTLTypes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ FIRRTLBaseType FIRRTLBaseType::getAllConstDroppedType() {
813813
FIRRTLBaseType FIRRTLBaseType::getMaskType() {
814814
return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*this)
815815
.Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
816-
AnalogType>([&](Type) {
816+
AnalogType, FEnumType>([&](Type) {
817817
return UIntType::get(this->getContext(), 1, this->isConst());
818818
})
819819
.Case<BundleType>([&](BundleType bundleType) {

lib/Dialect/FIRRTL/Transforms/FlattenMemory.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,13 @@ struct FlattenMemoryPass
215215
return false;
216216
return true;
217217
})
218-
.Case<IntType>([&](auto iType) {
219-
results.push_back({iType});
220-
return iType.getWidth().has_value();
218+
.Case<IntType>([&](IntType type) {
219+
results.push_back(type);
220+
return type.getWidth().has_value();
221+
})
222+
.Case<FEnumType>([&](FEnumType type) {
223+
results.emplace_back(type);
224+
return true;
221225
})
222226
.Default([&](auto) { return false; });
223227
};

test/Dialect/FIRRTL/flatten-memory.mlir

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,31 @@
22

33

44
firrtl.circuit "Mem" {
5-
firrtl.module public @Mem(in %clock: !firrtl.clock, in %rAddr: !firrtl.uint<4>, in %rEn: !firrtl.uint<1>, out %rData: !firrtl.bundle<a: uint<8>, b: uint<8>>, in %wAddr: !firrtl.uint<4>, in %wEn: !firrtl.uint<1>, in %wMask: !firrtl.bundle<a: uint<1>, b: uint<1>>, in %wData: !firrtl.bundle<a: uint<8>, b: uint<8>>) {
6-
%memory_r, %memory_w = firrtl.mem Undefined {depth = 16 : i64, name = "memory", portNames = ["r", "w"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>, !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
7-
%0 = firrtl.subfield %memory_r[clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
5+
firrtl.module public @Mem(in %clock: !firrtl.clock, in %rAddr: !firrtl.uint<4>, in %rEn: !firrtl.uint<1>, out %rData: !firrtl.bundle<a: uint<8>, b: enum<A = 128>>, in %wAddr: !firrtl.uint<4>, in %wEn: !firrtl.uint<1>, in %wMask: !firrtl.bundle<a: uint<1>, b: uint<1>>, in %wData: !firrtl.bundle<a: uint<8>, b: enum<A = 128>>) {
6+
%memory_r, %memory_w = firrtl.mem Undefined {depth = 16 : i64, name = "memory", portNames = ["r", "w"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>, !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
7+
%0 = firrtl.subfield %memory_r[clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
88
firrtl.matchingconnect %0, %clock : !firrtl.clock
9-
%1 = firrtl.subfield %memory_r[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
9+
%1 = firrtl.subfield %memory_r[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
1010
firrtl.matchingconnect %1, %rEn : !firrtl.uint<1>
11-
%2 = firrtl.subfield %memory_r[addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
11+
%2 = firrtl.subfield %memory_r[addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
1212
firrtl.matchingconnect %2, %rAddr : !firrtl.uint<4>
13-
%3 = firrtl.subfield %memory_r[data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
14-
firrtl.matchingconnect %rData, %3 : !firrtl.bundle<a: uint<8>, b: uint<8>>
15-
%4 = firrtl.subfield %memory_w[clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
13+
%3 = firrtl.subfield %memory_r[data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
14+
firrtl.matchingconnect %rData, %3 : !firrtl.bundle<a: uint<8>, b: enum<A = 128>>
15+
%4 = firrtl.subfield %memory_w[clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
1616
firrtl.matchingconnect %4, %clock : !firrtl.clock
17-
%5 = firrtl.subfield %memory_w[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
17+
%5 = firrtl.subfield %memory_w[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
1818
firrtl.matchingconnect %5, %wEn : !firrtl.uint<1>
19-
%6 = firrtl.subfield %memory_w[addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
19+
%6 = firrtl.subfield %memory_w[addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
2020
firrtl.matchingconnect %6, %wAddr : !firrtl.uint<4>
21-
%7 = firrtl.subfield %memory_w[mask] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
21+
%7 = firrtl.subfield %memory_w[mask] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
2222
firrtl.matchingconnect %7, %wMask : !firrtl.bundle<a: uint<1>, b: uint<1>>
23-
%8 = firrtl.subfield %memory_w[data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
24-
firrtl.matchingconnect %8, %wData : !firrtl.bundle<a: uint<8>, b: uint<8>>
23+
%8 = firrtl.subfield %memory_w[data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
24+
firrtl.matchingconnect %8, %wData : !firrtl.bundle<a: uint<8>, b: enum<A = 128>>
2525
// ---------------------------------------------------------------------------------
2626
// After flattenning the memory data
2727
// CHECK: %[[memory_r:.+]], %[[memory_w:.+]] = firrtl.mem Undefined {depth = 16 : i64, name = "memory", portNames = ["r", "w"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32}
2828
// CHECK-SAME: !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: uint<16>>, !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: uint<16>, mask: uint<2>>
29-
// CHECK: %[[memory_r_0:.+]] = firrtl.wire {name = "memory_r"} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
29+
// CHECK: %[[memory_r_0:.+]] = firrtl.wire {name = "memory_r"} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
3030
// CHECK: %[[v0:.+]] = firrtl.subfield %[[memory_r]][addr]
3131
// CHECK: firrtl.matchingconnect %[[v0]], %[[memory_r_addr:.+]] :
3232
// CHECK: %[[v1:.+]] = firrtl.subfield %[[memory_r]][en]
@@ -37,13 +37,13 @@ firrtl.circuit "Mem" {
3737
//
3838
// ---------------------------------------------------------------------------------
3939
// Read ports
40-
// CHECK: %[[v4:.+]] = firrtl.bitcast %[[v3]] : (!firrtl.uint<16>) -> !firrtl.bundle<a: uint<8>, b: uint<8>>
40+
// CHECK: %[[v4:.+]] = firrtl.bitcast %[[v3]] : (!firrtl.uint<16>) -> !firrtl.bundle<a: uint<8>, b: enum<A = 128>
4141
// CHECK: firrtl.matchingconnect %[[memory_r_data:.+]], %[[v4]] :
4242
// --------------------------------------------------------------------------------
4343
// Write Ports
44-
// CHECK: %[[memory_w_1:.+]] = firrtl.wire {name = "memory_w"} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
44+
// CHECK: %[[memory_w_1:.+]] = firrtl.wire {name = "memory_w"} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>
4545
// CHECK: %[[v9:.+]] = firrtl.subfield %[[memory_w]][data]
46-
// CHECK: %[[v17:.+]] = firrtl.bitcast %[[v15:.+]] : (!firrtl.bundle<a: uint<8>, b: uint<8>>) -> !firrtl.uint<16>
46+
// CHECK: %[[v17:.+]] = firrtl.bitcast %[[v15:.+]] : (!firrtl.bundle<a: uint<8>, b: enum<A = 128>>) -> !firrtl.uint<16>
4747
// CHECK: firrtl.matchingconnect %[[v9]], %[[v17]]
4848
//
4949
// --------------------------------------------------------------------------------
@@ -53,24 +53,24 @@ firrtl.circuit "Mem" {
5353
// CHECK: firrtl.matchingconnect %[[v11]], %[[v12]]
5454
// --------------------------------------------------------------------------------
5555
// Connections to module ports
56-
// CHECK: %[[v21:.+]] = firrtl.subfield %[[memory_r_0]][clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
56+
// CHECK: %[[v21:.+]] = firrtl.subfield %[[memory_r_0]][clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>
5757
// CHECK: firrtl.matchingconnect %[[v21]], %clock :
58-
// CHECK: %[[v22:.+]] = firrtl.subfield %[[memory_r_0]][en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
58+
// CHECK: %[[v22:.+]] = firrtl.subfield %[[memory_r_0]][en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
5959
// CHECK: firrtl.matchingconnect %[[v22]], %rEn : !firrtl.uint<1>
60-
// CHECK: %[[v23:.+]] = firrtl.subfield %[[memory_r_0]][addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
60+
// CHECK: %[[v23:.+]] = firrtl.subfield %[[memory_r_0]][addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
6161
// CHECK: firrtl.matchingconnect %[[v23]], %rAddr : !firrtl.uint<4>
62-
// CHECK: %[[v24:.+]] = firrtl.subfield %[[memory_r_0]][data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: uint<8>>>
63-
// CHECK: firrtl.matchingconnect %rData, %[[v24]] : !firrtl.bundle<a: uint<8>, b: uint<8>>
64-
// CHECK: %[[v25:.+]] = firrtl.subfield %[[memory_w_1]][clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
62+
// CHECK: %[[v24:.+]] = firrtl.subfield %[[memory_r_0]][data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: bundle<a: uint<8>, b: enum<A = 128>>>
63+
// CHECK: firrtl.matchingconnect %rData, %[[v24]] : !firrtl.bundle<a: uint<8>, b: enum<A = 128>>
64+
// CHECK: %[[v25:.+]] = firrtl.subfield %[[memory_w_1]][clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
6565
// CHECK: firrtl.matchingconnect %[[v25]], %clock : !firrtl.clock
66-
// CHECK: %[[v26:.+]] = firrtl.subfield %[[memory_w_1]][en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
66+
// CHECK: %[[v26:.+]] = firrtl.subfield %[[memory_w_1]][en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
6767
// CHECK: firrtl.matchingconnect %[[v26]], %wEn : !firrtl.uint<1>
68-
// CHECK: %[[v27:.+]] = firrtl.subfield %[[memory_w_1]][addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
68+
// CHECK: %[[v27:.+]] = firrtl.subfield %[[memory_w_1]][addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
6969
// CHECK: firrtl.matchingconnect %[[v27]], %wAddr : !firrtl.uint<4>
70-
// CHECK: %[[v28:.+]] = firrtl.subfield %[[memory_w_1]][mask] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
70+
// CHECK: %[[v28:.+]] = firrtl.subfield %[[memory_w_1]][mask] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
7171
// CHECK: firrtl.matchingconnect %[[v28]], %wMask : !firrtl.bundle<a: uint<1>, b: uint<1>>
72-
// CHECK: %[[v29:.+]] = firrtl.subfield %[[memory_w_1]][data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: uint<8>>, mask: bundle<a: uint<1>, b: uint<1>>>
73-
// CHECK: firrtl.matchingconnect %[[v29]], %wData : !firrtl.bundle<a: uint<8>, b: uint<8>>
72+
// CHECK: %[[v29:.+]] = firrtl.subfield %[[memory_w_1]][data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data: bundle<a: uint<8>, b: enum<A = 128>>, mask: bundle<a: uint<1>, b: uint<1>>>
73+
// CHECK: firrtl.matchingconnect %[[v29]], %wData : !firrtl.bundle<a: uint<8>, b: enum<A = 128>>
7474
}
7575

7676
firrtl.module @MemoryRWSplit(in %clock: !firrtl.clock, in %rwEn: !firrtl.uint<1>, in %rwMode: !firrtl.uint<1>, in %rwAddr: !firrtl.uint<4>, in %rwMask: !firrtl.bundle<a: uint<1>, b: uint<1>>, in %rwDataIn: !firrtl.bundle<a: uint<8>, b: uint<9>>, out %rwDataOut: !firrtl.bundle<a: uint<8>, b: uint<9>>) {
@@ -118,10 +118,8 @@ firrtl.module @MemoryRWSplit(in %clock: !firrtl.clock, in %rwEn: !firrtl.uint<1>
118118
// Ensure 0 bit fields are handled properly.
119119
%ram_MPORT = firrtl.mem Undefined {depth = 4 : i64, name = "ram", portNames = ["MPORT"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<2>, en: uint<1>, clk: clock, data: bundle<entry: bundle<a: uint<0>, b: uint<1>, c: uint<2>>>, mask: bundle<entry: bundle<a: uint<1>, b: uint<1>, c: uint<1>>>>
120120
// CHECK: %ram_MPORT = firrtl.mem Undefined {depth = 4 : i64, name = "ram", portNames = ["MPORT"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<2>, en: uint<1>, clk: clock, data: uint<3>, mask: uint<3>>
121-
122121
}
123122

124-
125123
firrtl.module @ZeroBitMasks(in %clock: !firrtl.clock, in %reset: !firrtl.uint<1>, in %io: !firrtl.bundle<a: uint<0>, b: uint<20>>) {
126124
%invalid = firrtl.invalidvalue : !firrtl.bundle<a: uint<1>, b: uint<1>>
127125
%invalid_0 = firrtl.invalidvalue : !firrtl.bundle<a: uint<0>, b: uint<20>>

0 commit comments

Comments
 (0)