From 5114f7888bc96c91c58b318aa3ddf901d3ea4ec4 Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Thu, 5 Jan 2023 15:28:11 -0800 Subject: [PATCH] Improve exceptions for Logic.put (#243) --- lib/src/exceptions/exceptions.dart | 5 +-- .../exceptions/logic/logic_exceptions.dart | 4 +++ lib/src/exceptions/logic/put_exception.dart | 20 ++++++++++++ lib/src/logic.dart | 31 +++++++++++-------- test/bus_test.dart | 14 ++++++++- test/math_test.dart | 5 +-- 6 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 lib/src/exceptions/logic/logic_exceptions.dart create mode 100644 lib/src/exceptions/logic/put_exception.dart diff --git a/lib/src/exceptions/exceptions.dart b/lib/src/exceptions/exceptions.dart index a13fbf74d..d9448341e 100644 --- a/lib/src/exceptions/exceptions.dart +++ b/lib/src/exceptions/exceptions.dart @@ -1,7 +1,8 @@ -/// Copyright (C) 2022 Intel Corporation +/// Copyright (C) 2022-2023 Intel Corporation /// SPDX-License-Identifier: BSD-3-Clause - export './conditionals/conditional_exceptions.dart'; +export './logic/logic_exceptions.dart'; export './module/module_exceptions.dart'; export './name/name_exceptions.dart'; export './sim_compare/sim_compare_exceptions.dart'; +export 'rohd_exception.dart'; diff --git a/lib/src/exceptions/logic/logic_exceptions.dart b/lib/src/exceptions/logic/logic_exceptions.dart new file mode 100644 index 000000000..861808203 --- /dev/null +++ b/lib/src/exceptions/logic/logic_exceptions.dart @@ -0,0 +1,4 @@ +/// Copyright (C) 2023 Intel Corporation +/// SPDX-License-Identifier: BSD-3-Clause + +export 'put_exception.dart'; diff --git a/lib/src/exceptions/logic/put_exception.dart b/lib/src/exceptions/logic/put_exception.dart new file mode 100644 index 000000000..81e2b86da --- /dev/null +++ b/lib/src/exceptions/logic/put_exception.dart @@ -0,0 +1,20 @@ +/// Copyright (C) 2023 Intel Corporation +/// SPDX-License-Identifier: BSD-3-Clause +/// +/// put_exception.dart +/// An exception that thrown when a signal failes to `put`. +/// +/// 2023 January 5 +/// Author: Max Korbel +/// + +import 'package:rohd/rohd.dart'; +import 'package:rohd/src/exceptions/rohd_exception.dart'; + +/// An exception that thrown when a [Logic] signal fails to `put`. +class PutException extends RohdException { + /// Creates an exception for when a `put` fails on a `Logic` with [context] as + /// to where the + PutException(String context, String message) + : super('Failed to put value on signal ($context): $message'); +} diff --git a/lib/src/logic.dart b/lib/src/logic.dart index 6e57c595b..e08959a27 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -12,8 +12,8 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; - import 'package:rohd/rohd.dart'; +import 'package:rohd/src/exceptions/logic/logic_exceptions.dart'; import 'package:rohd/src/utilities/sanitizer.dart'; import 'package:rohd/src/utilities/synchronous_propagator.dart'; @@ -201,8 +201,8 @@ class _Wire { /// Injects a value onto this signal in the current [Simulator] tick. /// /// This function calls [put()] in [Simulator.injectAction()]. - void inject(dynamic val, {bool fill = false}) { - Simulator.injectAction(() => put(val, fill: fill)); + void inject(dynamic val, {required String signalName, bool fill = false}) { + Simulator.injectAction(() => put(val, signalName: signalName, fill: fill)); } /// Keeps track of whether there is an active put, to detect reentrance. @@ -218,7 +218,7 @@ class _Wire { /// /// If [fill] is set, all bits of the signal gets set to [val], similar /// to `'` in SystemVerilog. - void put(dynamic val, {bool fill = false}) { + void put(dynamic val, {required String signalName, bool fill = false}) { LogicValue newValue; if (val is int) { if (fill) { @@ -228,7 +228,8 @@ class _Wire { ? LogicValue.zero : val == 1 ? LogicValue.one - : throw Exception('Only can fill 0 or 1, but saw $val.')); + : throw PutException( + signalName, 'Only can fill 0 or 1, but saw $val.')); } else { newValue = LogicValue.ofInt(val, width); } @@ -240,7 +241,8 @@ class _Wire { ? LogicValue.zero : val == BigInt.one ? LogicValue.one - : throw Exception('Only can fill 0 or 1, but saw $val.')); + : throw PutException( + signalName, 'Only can fill 0 or 1, but saw $val.')); } else { newValue = LogicValue.ofBigInt(val, width); } @@ -251,19 +253,21 @@ class _Wire { (val == LogicValue.x || val == LogicValue.z || fill)) { newValue = LogicValue.filled(width, val); } else if (fill) { - throw Exception( + throw PutException(signalName, 'Failed to fill value with $val. To fill, it should be 1 bit.'); } else { newValue = val; } } else { - throw Exception('Unrecognized value "$val" to deposit on this signal. ' + throw PutException( + signalName, + 'Unrecognized value "$val" to deposit on this signal. ' 'Unknown type ${val.runtimeType} cannot be deposited.'); } if (newValue.width != width) { - throw Exception( - 'Updated value width mismatch. The width of $val should be $width.'); + throw PutException(signalName, + 'Updated value width mismatch. The width of $val should be $width.'); } if (_isPutting) { @@ -454,7 +458,7 @@ class Logic { /// /// This function calls [put()] in [Simulator.injectAction()]. void inject(dynamic val, {bool fill = false}) => - _wire.inject(val, fill: fill); + _wire.inject(val, signalName: name, fill: fill); /// Puts a value [val] onto this signal, which may or may not be picked up /// for [changed] in this [Simulator] tick. @@ -466,7 +470,8 @@ class Logic { /// /// If [fill] is set, all bits of the signal gets set to [val], similar /// to `'` in SystemVerilog. - void put(dynamic val, {bool fill = false}) => _wire.put(val, fill: fill); + void put(dynamic val, {bool fill = false}) => + _wire.put(val, signalName: name, fill: fill); /// Connects this [Logic] directly to [other]. /// @@ -491,7 +496,7 @@ class Logic { /// notifies all downstream [Logic]s of the new source [_Wire]. void _updateWire(_Wire newWire) { // first, propagate the new value (if it's different) downstream - _wire.put(newWire.value); + _wire.put(newWire.value, signalName: name); // then, replace the wire newWire._adopt(_wire); diff --git a/test/bus_test.dart b/test/bus_test.dart index 9ab65bfc0..6d634aef3 100644 --- a/test/bus_test.dart +++ b/test/bus_test.dart @@ -1,4 +1,4 @@ -/// Copyright (C) 2021 Intel Corporation +/// Copyright (C) 2021-2023 Intel Corporation /// SPDX-License-Identifier: BSD-3-Clause /// /// bus_test.dart @@ -7,7 +7,9 @@ /// 2021 May 7 /// Author: Max Korbel /// + import 'package:rohd/rohd.dart'; +import 'package:rohd/src/exceptions/logic/logic_exceptions.dart'; import 'package:rohd/src/utilities/simcompare.dart'; import 'package:test/test.dart'; @@ -249,6 +251,16 @@ void main() { b.put(0x55); expect(out.value.toInt(), equals(0x55aa)); }); + + group('put exceptions', () { + test('width mismatch', () { + expect( + () => Logic(name: 'byteSignal', width: 8) + .put(LogicValue.ofString('1010')), + throwsA(const TypeMatcher()), + ); + }); + }); }); group('simcompare', () { diff --git a/test/math_test.dart b/test/math_test.dart index 213e782cf..fe624302a 100644 --- a/test/math_test.dart +++ b/test/math_test.dart @@ -1,12 +1,13 @@ -/// Copyright (C) 2021 Intel Corporation +/// Copyright (C) 2021-2023 Intel Corporation /// SPDX-License-Identifier: BSD-3-Clause /// /// math_test.dart -/// Unit tests for bus-related operations +/// Unit tests for math-related operations /// /// 2021 May 21 /// Author: Max Korbel /// + import 'package:rohd/rohd.dart'; import 'package:rohd/src/utilities/simcompare.dart'; import 'package:test/test.dart';