diff --git a/lib/src/modules/conditional.dart b/lib/src/modules/conditional.dart index 8c46498f6..535e35729 100644 --- a/lib/src/modules/conditional.dart +++ b/lib/src/modules/conditional.dart @@ -740,6 +740,16 @@ abstract class Conditional { /// This is used for [Combinational.ssa]. Map _processSsa(Map currentMappings, {required int context}); + + /// Drives X to all receivers. + void _driveX(Set drivenSignals) { + for (final receiver in receivers) { + receiverOutput(receiver).put(LogicValue.x); + if (!drivenSignals.contains(receiver) || receiver.value.isValid) { + drivenSignals.add(receiver); + } + } + } } /// Represents a group of [Conditional]s to be executed. @@ -957,12 +967,7 @@ class Case extends Conditional { if (!expression.value.isValid) { // if expression has X or Z, then propogate X's! - for (final receiver in receivers) { - receiverOutput(receiver).put(LogicValue.x); - if (!drivenSignals.contains(receiver) || receiver.value.isValid) { - drivenSignals.add(receiver); - } - } + _driveX(drivenSignals); return; } @@ -975,9 +980,8 @@ class Case extends Conditional { conditional.execute(drivenSignals, guard); } if (foundMatch != null && conditionalType == ConditionalType.unique) { - throw Exception('Unique case statement had multiple matching cases.' - ' Original: "$foundMatch".' - ' Duplicate: "$item".'); + _driveX(drivenSignals); + return; } foundMatch = item; @@ -996,8 +1000,8 @@ class Case extends Conditional { } else if (foundMatch == null && (conditionalType == ConditionalType.unique || conditionalType == ConditionalType.priority)) { - throw Exception('$conditionalType case statement had no matching case,' - ' and type was $conditionalType.'); + _driveX(drivenSignals); + return; } } diff --git a/test/conditionals_test.dart b/test/conditionals_test.dart index 829c8ee0f..4c87cb3a3 100644 --- a/test/conditionals_test.dart +++ b/test/conditionals_test.dart @@ -141,6 +141,28 @@ class CaseModule extends Module { } } +class UniqueCase extends Module { + UniqueCase(Logic a, Logic b) : super(name: 'UniqueCase') { + a = addInput('a', a); + b = addInput('b', b); + final c = addOutput('c'); + final d = addOutput('d'); + Combinational([ + Case( + Const(1), + [ + CaseItem(a, [c < 1, d < 0]), + CaseItem(b, [c < 1, d < 0]), + ], + defaultItem: [ + c < 0, + d < 1, + ], + conditionalType: ConditionalType.unique), + ]); + } +} + enum SeqCondModuleType { caseNormal, caseZ, ifNormal } class SeqCondModule extends Module { @@ -568,6 +590,18 @@ void main() { expect(simResult, equals(true)); }); + test('Unique case', () async { + final mod = UniqueCase(Logic(), Logic()); + await mod.build(); + final vectors = [ + Vector({'a': 0, 'b': 0}, {'c': 0, 'd': 1}), + Vector({'a': 0, 'b': 1}, {'c': 1, 'd': 0}), + Vector({'a': 1, 'b': 0}, {'c': 1, 'd': 0}), + Vector({'a': 1, 'b': 1}, {'c': LogicValue.x, 'd': LogicValue.x}), + ]; + await SimCompare.checkFunctionalVector(mod, vectors); + }); + test('conditional ff', () async { final mod = SequentialModule(Logic(), Logic(), Logic(width: 8)); await mod.build();