Skip to content

Commit a2c6aca

Browse files
authored
Fix bug in SSA discovery when LogicStructures are used (#540)
1 parent 121951b commit a2c6aca

File tree

3 files changed

+104
-4
lines changed

3 files changed

+104
-4
lines changed

lib/src/modules/conditionals/combinational.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2021-2024 Intel Corporation
1+
// Copyright (C) 2021-2025 Intel Corporation
22
// SPDX-License-Identifier: BSD-3-Clause
33
//
44
// combinational.dart
@@ -137,6 +137,20 @@ class Combinational extends Always {
137137
} else {
138138
toParse.addAll(tpi.dstConnections);
139139
}
140+
141+
// This is critical to make sure we are notifying downstream SSA's even
142+
// if they are driven as a result of being a part of a modified structure.
143+
if (tpi.parentStructure != null) {
144+
toParse.add(tpi.parentStructure!);
145+
}
146+
147+
// This is probably unnecessary, as the SSA would not allow someone to
148+
// reference an element of a structure without separately SSA'ing it.
149+
// However, leaving this in here just in case (probably negligible perf
150+
// impact).
151+
if (tpi is LogicStructure) {
152+
toParse.addAll(tpi.elements);
153+
}
140154
}
141155
}
142156

test/pipeline_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2021-2024 Intel Corporation
1+
// Copyright (C) 2021-2025 Intel Corporation
22
// SPDX-License-Identifier: BSD-3-Clause
33
//
44
// pipeline_test.dart
@@ -247,7 +247,7 @@ void main() {
247247
throwsRangeError);
248248
});
249249

250-
test('getting unregisterd signal on pipeline is error', () {
250+
test('getting unregistered signal on pipeline is error', () {
251251
expect(
252252
() => Pipeline(Logic(), signals: [
253253
Logic()

test/ssa_test.dart

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2023 Intel Corporation
1+
// Copyright (C) 2023-2025 Intel Corporation
22
// SPDX-License-Identifier: BSD-3-Clause
33
//
44
// ssa_test.dart
@@ -21,6 +21,90 @@ abstract class SsaTestModule extends Module {
2121
int model(int a);
2222
}
2323

24+
class SimpleStruct extends LogicStructure {
25+
SimpleStruct()
26+
: super([Logic(width: 4), Logic(width: 4)], name: 'simple_struct');
27+
}
28+
29+
class StructOpRepack extends Module {
30+
late final SimpleStruct x = SimpleStruct()..gets(output('x'));
31+
32+
StructOpRepack(SimpleStruct a) {
33+
a = SimpleStruct()..gets(addInput('a', a, width: 8));
34+
final x_ = SimpleStruct();
35+
36+
x_.elements[0] <= a.elements[0] + 1;
37+
x_.elements[1] <= a.elements[1] + 2;
38+
39+
addOutput('x', width: 8) <= x_;
40+
}
41+
}
42+
43+
class SsaModWithStructElements extends SsaTestModule {
44+
SsaModWithStructElements(Logic a) : super(name: 'struct_elements') {
45+
a = addInput('a', a, width: 8);
46+
final x = addOutput('x', width: 8);
47+
48+
final s1 = SimpleStruct();
49+
50+
final sx = SimpleStruct();
51+
52+
Combinational.ssa((s) => [
53+
s(s1) < a,
54+
s(sx) < StructOpRepack(SimpleStruct()..gets(s(s1))).x,
55+
]);
56+
57+
x <= sx;
58+
}
59+
60+
@override
61+
int model(int a) {
62+
final orig = LogicValue.ofInt(a, 8);
63+
return [
64+
orig.getRange(0, 4) + 1,
65+
orig.getRange(4, 8) + 2,
66+
].rswizzle().toInt();
67+
}
68+
}
69+
70+
class StructOpSplit extends Module {
71+
Logic get x0 => output('x0');
72+
Logic get x1 => output('x1');
73+
74+
StructOpSplit(SimpleStruct a) {
75+
a = SimpleStruct()..gets(addInput('a', a, width: 8));
76+
final x0 = addOutput('x0', width: 4);
77+
final x1 = addOutput('x1', width: 4);
78+
79+
x0 <= a.elements[0] + 1;
80+
x1 <= a.elements[1] + 2;
81+
}
82+
}
83+
84+
class SsaModWithStructSplit extends SsaTestModule {
85+
SsaModWithStructSplit(Logic a) : super(name: 'struct_split') {
86+
a = addInput('a', a, width: 8);
87+
final x = addOutput('x', width: 8);
88+
89+
final s1 = SimpleStruct();
90+
91+
Combinational.ssa((s) => [
92+
s(s1) < a,
93+
s(x) <
94+
() {
95+
final splitMod = StructOpSplit(SimpleStruct()..gets(s(s1)));
96+
return (splitMod.x0 + splitMod.x1).zeroExtend(8);
97+
}(),
98+
]);
99+
}
100+
101+
@override
102+
int model(int a) {
103+
final orig = LogicValue.ofInt(a, 8);
104+
return (orig.getRange(0, 4) + 1 + orig.getRange(4, 8) + 2).toInt();
105+
}
106+
}
107+
24108
class SsaModAssignsOnly extends SsaTestModule {
25109
SsaModAssignsOnly(Logic a) : super(name: 'assigns_only') {
26110
a = addInput('a', a, width: 8);
@@ -338,6 +422,8 @@ void main() {
338422
SsaMix(aInput),
339423
SsaNested(aInput),
340424
SsaMultiDep(aInput),
425+
SsaModWithStructElements(aInput),
426+
SsaModWithStructSplit(aInput),
341427
];
342428

343429
for (final mod in mods) {

0 commit comments

Comments
 (0)