Skip to content

Commit

Permalink
Added Null width check and additional changes based on feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
mjayasim9 committed Jul 28, 2023
1 parent cf52b6d commit 360aaf6
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 74 deletions.
6 changes: 6 additions & 0 deletions lib/src/exceptions/logic/signal_width_mismatch_exception.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,10 @@ class SignalWidthMismatchException extends RohdException {
: super('Value $val has the wrong width.'
' Expected $expectedWidth but found $actualWidth.'
' $additionalMessage');

/// Constructs a new [Exception] for when a dynamic has no width or it could
/// not be inferred.
SignalWidthMismatchException.forNull(dynamic val)
: super('Could not infer width of value $val.'
' Please provide a valid width.');
}
35 changes: 26 additions & 9 deletions lib/src/modules/conditional.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import 'dart:async';
import 'dart:collection';

import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:rohd/rohd.dart';
import 'package:rohd/src/collections/duplicate_detection_set.dart';
Expand All @@ -18,6 +19,7 @@ import 'package:rohd/src/exceptions/exceptions.dart';
import 'package:rohd/src/utilities/sanitizer.dart';
import 'package:rohd/src/utilities/synchronous_propagator.dart';
import 'package:rohd/src/utilities/uniquifier.dart';
import 'package:test/test.dart';

/// Represents a block of logic, similar to `always` blocks in SystemVerilog.
abstract class _Always extends Module with CustomSystemVerilog {
Expand Down Expand Up @@ -899,27 +901,41 @@ enum ConditionalType {
/// input is not provided, then the width of the result is inferred from the
/// width of the entries.
Logic cases(Logic expression, Map<dynamic, dynamic> conditions,
{int? width, ConditionalType conditionalType = ConditionalType.none}) {
for (final condition in conditions.entries) {
{int? width,
ConditionalType conditionalType = ConditionalType.none,
dynamic defaultValue}) {
for (final conditionValue in [
...conditions.values,
if (defaultValue != null) defaultValue
]) {
int? inferredWidth;

if (condition.value is Logic) {
inferredWidth = (condition.value as Logic).width;
} else if (condition.value is LogicValue) {
inferredWidth = (condition.value as LogicValue).width;
if (conditionValue is Logic) {
inferredWidth = conditionValue.width;
} else if (conditionValue is LogicValue) {
inferredWidth = conditionValue.width;
}

if (width != inferredWidth && width != null && inferredWidth != null) {
throw SignalWidthMismatchException.forDynamic(
condition.value, width, inferredWidth);
conditionValue, width, inferredWidth);
}

width ??= inferredWidth;

if (width == null && inferredWidth == null) {
throw SignalWidthMismatchException.forNull(conditionValue);
}

if (width != inferredWidth && inferredWidth != null) {
throw SignalWidthMismatchException.forDynamic(
condition.value, width!, inferredWidth);
conditionValue, width!, inferredWidth);
}
}

if (defaultValue == null) {}

for (final condition in conditions.entries) {
if (condition.key is Logic) {
if (expression.width != (condition.key as Logic).width) {
throw SignalWidthMismatchException.forDynamic(
Expand Down Expand Up @@ -948,7 +964,8 @@ Logic cases(Logic expression, Map<dynamic, dynamic> conditions,
: Const(condition.key, width: expression.width),
[result < condition.value])
],
conditionalType: conditionalType)
conditionalType: conditionalType,
defaultItem: defaultValue != null ? [result < defaultValue] : [])
]);

return result;
Expand Down
159 changes: 94 additions & 65 deletions test/gate_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -205,85 +205,114 @@ void main() {
expect(result.value, LogicValue.one);
});

test('Cases test Int', () {
final control = Logic(width: 8);
final d0 = Logic(width: 8);
final d1 = Logic(width: 8);
final result = cases(
control,
{
d0: 2,
d1: 3,
},
width: 8);

d0.put(2);
d1.put(3);
control.put(2);

expect(result.value, LogicValue.ofInt(2, 8));

control.put(3);

expect(result.value, LogicValue.ofInt(3, 8));
});
group('cases', () {
test('Cases test Int', () {
final control = Logic(width: 8);
final d0 = Logic(width: 8);
final d1 = Logic(width: 8);
final result = cases(
control,
{
d0: 2,
d1: 3,
},
width: 8);

d0.put(2);
d1.put(3);
control.put(2);

expect(result.value, LogicValue.ofInt(2, 8));

control.put(3);

expect(result.value, LogicValue.ofInt(3, 8));
});

test('Cases test Logic', () {
final control = Logic();
final d0 = Logic();
final d1 = Logic();
final result = cases(control, {
d0: LogicValue.zero,
d1: LogicValue.one,
test('Cases test Logic', () {
final control = Logic();
final d0 = Logic();
final d1 = Logic();
final result = cases(control, {
d0: LogicValue.zero,
d1: LogicValue.one,
});

d0.put(LogicValue.zero);
d1.put(LogicValue.one);

control.put(0);
expect(result.value, LogicValue.zero);

control.put(1);
expect(result.value, LogicValue.one);
});

d0.put(LogicValue.zero);
d1.put(LogicValue.one);
test('Cases test Default', () {
final control = Logic(width: 4);
const d0 = 1;
const d1 = 2;
final result = cases(
control,
{
d0: 1,
d1: 2,
},
width: 4,
defaultValue: 3);

control.put(LogicValue.zero);
expect(result.value, LogicValue.ofInt(3, 4));
});

control.put(0);
expect(result.value, LogicValue.zero);
test('Cases test Exceptions(Int)', () {
final control = Logic(width: 4);
final d0 = Logic(width: 4);
final d1 = Logic(width: 8);

control.put(1);
expect(result.value, LogicValue.one);
});
control.put(LogicValue.ofInt(2, 4));
d0.put(LogicValue.ofInt(2, 4));
d1.put(LogicValue.ofInt(3, 8));

test('Cases test Exceptions(Int)', () {
final control = Logic(width: 4);
final d0 = Logic(width: 4);
final d1 = Logic(width: 8);
expect(() => cases(control, {d0: 2, d1: 3}),
throwsA(isA<SignalWidthMismatchException>()));
});

control.put(LogicValue.ofInt(2, 4));
d0.put(LogicValue.ofInt(2, 4));
d1.put(LogicValue.ofInt(3, 8));
test('Cases test Condition width Exception', () {
final control = Logic();
final d0 = Logic();
final d1 = Logic(width: 8);

expect(() => cases(control, {d0: 2, d1: 3}),
throwsA(isA<SignalWidthMismatchException>()));
});
control.put(LogicValue.zero);
d0.put(LogicValue.zero);
d1.put(LogicValue.ofInt(1, 8));

test('Cases test Condition width Exception', () {
final control = Logic();
final d0 = Logic();
final d1 = Logic(width: 8);
expect(() => cases(control, {d0: 0, d1: 1}),
throwsA(isA<SignalWidthMismatchException>()));
});

control.put(LogicValue.zero);
d0.put(LogicValue.zero);
d1.put(LogicValue.ofInt(1, 8));
test('Cases test Expression width Exception', () {
final control = Logic();
final d0 = Logic(width: 8);
final d1 = Logic(width: 8);

expect(() => cases(control, {d0: 0, d1: 1}),
throwsA(isA<SignalWidthMismatchException>()));
});
control.put(LogicValue.one);
d0.put(LogicValue.zero);
d1.put(LogicValue.one);

test('Cases test Expression width Exception', () {
final control = Logic();
final d0 = Logic(width: 8);
final d1 = Logic(width: 8);
expect(() => cases(control, {d0: 0, d1: 1}),
throwsA(isA<SignalWidthMismatchException>()));
});

control.put(LogicValue.one);
d0.put(LogicValue.zero);
d1.put(LogicValue.one);
test('Cases test Null width Exception', () {
final control = Logic();
const d0 = 2;
const d1 = 4;

expect(() => cases(control, {d0: 0, d1: 1}),
throwsA(isA<SignalWidthMismatchException>()));
control.put(LogicValue.zero);
expect(() => cases(control, {d0: 2, d1: 4}, defaultValue: 3),
throwsA(isA<SignalWidthMismatchException>()));
});
});

group('simcompare', () {
Expand Down

0 comments on commit 360aaf6

Please sign in to comment.