Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gates should output X (never Z) when inputs are invalid #393

Merged
merged 7 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions benchmark/comb_guard_fanout_benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ class CombGuardFanoutBenchmark extends AsyncBenchmarkBase {
CombGuardFanoutBenchmark({this.numPuts = 100})
: super('CombGuardFanoutBenchmark');

@override
Future<void> teardown() async {
await Simulator.reset();
}

CombGuardFanout? mod;
final Logic a = Logic(width: 8);

Expand Down
14 changes: 7 additions & 7 deletions lib/src/modules/conditional.dart
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,12 @@ class ConditionalAssign extends Conditional {
guard(driver);
}

_receiverOutput.put(driverValue(driver));
final currentValue = driverValue(driver);
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
if (!currentValue.isValid) {
_receiverOutput.put(LogicValue.x);
} else {
_receiverOutput.put(currentValue);
}

if (!drivenSignals.contains(receiver) || receiver.value.isValid) {
drivenSignals.add(receiver);
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -1406,12 +1411,7 @@ class If extends Conditional {
break;
} else if (driverValue(iff.condition) != LogicValue.zero) {
// x and z propagation
for (final receiver in receivers) {
receiverOutput(receiver).put(driverValue(iff.condition)[0]);
if (!drivenSignals.contains(receiver) || receiver.value.isValid) {
drivenSignals.add(receiver);
}
}
_driveX(drivenSignals);
break;
}
// if it's 0, then continue searching down the path
Expand Down
6 changes: 3 additions & 3 deletions lib/src/modules/gates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -661,11 +661,11 @@ class Mux extends Module with InlineSystemVerilog {
/// Executes the functional behavior of the mux.
void _execute() {
if (!_control.value.isValid) {
out.put(_control.value);
out.put(LogicValue.x);
} else if (_control.value == LogicValue.zero) {
out.put(_d0.value);
out.put(_d0.value.isValid ? _d0.value : LogicValue.x);
} else if (_control.value == LogicValue.one) {
out.put(_d1.value);
out.put(_d1.value.isValid ? _d1.value : LogicValue.x);
}
}

Expand Down
8 changes: 3 additions & 5 deletions lib/src/utilities/simcompare.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,9 @@ class Vector {
}
return arrAssigns.toString();
} else {
var assignmentValue = inputValues[signalName];
if (assignmentValue is BigInt) {
assignmentValue = LogicValue.of(assignmentValue, width: signal.width);
}
return '$signalName = $assignmentValue;';
final signalVal =
LogicValue.of(inputValues[signalName], width: signal.width);
return '$signalName = $signalVal;';
}
}).join('\n');

Expand Down
45 changes: 45 additions & 0 deletions test/conditionals_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ class UniqueCase extends Module {

enum SeqCondModuleType { caseNormal, caseZ, ifNormal }

class ConditionalAssignModule extends Module {
ConditionalAssignModule(
Logic a,
) : super(name: 'ConditionalAssignModule') {
a = addInput('a', a);
final c = addOutput('c');
Combinational([c < a]);
}
}

class SeqCondModule extends Module {
Logic get equal => output('equal');
SeqCondModule(Logic clk, Logic a, {required SeqCondModuleType combType}) {
Expand Down Expand Up @@ -214,6 +224,18 @@ class IfBlockModule extends Module {
}
}

class IffModule extends Module {
IffModule(Logic a, Logic b) : super(name: 'Iffmodule') {
a = addInput('a', a);
b = addInput('b', b);
final c = addOutput('c');

Combinational([
If(a, then: [c < b])
]);
}
}

class SingleIfBlockModule extends Module {
SingleIfBlockModule(Logic a) : super(name: 'singleifblockmodule') {
a = addInput('a', a);
Expand Down Expand Up @@ -537,6 +559,17 @@ void main() {
expect(simResult, equals(true));
});

test('if invalid ', () async {
final mod = IffModule(Logic(), Logic());
await mod.build();
final vectors = [
Vector({'a': 1, 'b': 0}, {'c': 0}),
Vector({'a': LogicValue.z, 'b': 1}, {'c': LogicValue.x}),
Vector({'a': LogicValue.x, 'b': 0}, {'c': LogicValue.x}),
];
await SimCompare.checkFunctionalVector(mod, vectors);
});

test('single iffblock comb', () async {
final mod = SingleIfBlockModule(Logic());
await mod.build();
Expand All @@ -562,6 +595,18 @@ void main() {
expect(simResult, equals(true));
});

test('Conditional assign module with invalid inputs', () async {
final mod = ConditionalAssignModule(Logic());
await mod.build();
final vectors = [
Vector({'a': 1}, {'c': 1}),
Vector({'a': 0}, {'c': 0}),
Vector({'a': LogicValue.z}, {'c': LogicValue.x}),
Vector({'a': LogicValue.x}, {'c': LogicValue.x}),
];
await SimCompare.checkFunctionalVector(mod, vectors);
});

test('single elseifblock comb', () async {
final mod = SingleElseIfBlockModule(Logic());
await mod.build();
Expand Down
18 changes: 15 additions & 3 deletions test/gate_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -414,13 +414,25 @@ void main() {
test('Mux bus', () async {
final mod = MuxWrapper(Logic(), Logic(width: 8), Logic(width: 8));
await mod.build();
final vectors = [
final vector1 = [
Vector({'control': 1, 'd0': 12, 'd1': 15}, {'y': 15}),
Vector({'control': 0, 'd0': 18, 'd1': 7}, {'y': 18}),
Vector({'control': 0, 'd0': 3, 'd1': 6}, {'y': 3}),
Vector({'control': 0, 'd0': 10, 'd1': LogicValue.z}, {'y': 10}),
Vector({'control': 1, 'd0': LogicValue.z, 'd1': 6}, {'y': 6}),
];
await SimCompare.checkFunctionalVector(mod, vectors);
final simResult = SimCompare.iverilogVector(mod, vectors);

final vector2 = [
Vector(
{'control': 1, 'd0': 6, 'd1': LogicValue.z}, {'y': LogicValue.x}),
Vector(
{'control': LogicValue.z, 'd0': 10, 'd1': 6}, {'y': LogicValue.x}),
Vector(
{'control': 0, 'd0': LogicValue.z, 'd1': 10}, {'y': LogicValue.x}),
];

await SimCompare.checkFunctionalVector(mod, vector1 + vector2);
final simResult = SimCompare.iverilogVector(mod, vector1);
expect(simResult, equals(true));
});

Expand Down