From 6337251b83239b1b694431ba276616c2f60002c3 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Thu, 25 Aug 2022 19:52:16 -0400 Subject: [PATCH 01/12] [FIX-issue#99] Allowing negative logic index values --- lib/src/logic.dart | 14 +++++++++----- lib/src/modules/bus.dart | 18 ++++++++++-------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/src/logic.dart b/lib/src/logic.dart index 31ec5552b..6ff4a4f8f 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -444,21 +444,25 @@ class Logic { /// [startIndex] must be less than [endIndex]. If [startIndex] and [endIndex] are equal, then a /// zero-width signal is returned. Logic getRange(int startIndex, int endIndex) { - if (endIndex < startIndex) { + // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) + var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; + var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; + + if (modifiedEndIndex < modifiedStartIndex) { throw Exception( 'End ($endIndex) cannot be less than start ($startIndex).'); } - if (endIndex > width) { + if (modifiedEndIndex > width) { throw Exception('End ($endIndex) must be less than width ($width).'); } - if (startIndex < 0) { + if (modifiedStartIndex < 0) { throw Exception( 'Start ($startIndex) must be greater than or equal to 0.'); } - if (endIndex == startIndex) { + if (modifiedEndIndex == modifiedStartIndex) { return Const(0, width: 0); } - return slice(endIndex - 1, startIndex); + return slice(modifiedEndIndex - 1, modifiedStartIndex); } /// Returns a new [Logic] with width [newWidth] where new bits added are zeros diff --git a/lib/src/modules/bus.dart b/lib/src/modules/bus.dart index e4dfc8ce7..fe7359732 100644 --- a/lib/src/modules/bus.dart +++ b/lib/src/modules/bus.dart @@ -30,21 +30,23 @@ class BusSubset extends Module with InlineSystemVerilog { BusSubset(Logic bus, this.startIndex, this.endIndex, {String name = 'bussubset'}) : super(name: name) { - if (startIndex < 0 || endIndex < 0) { - throw Exception('Cannot access negative indices!' - ' Indices $startIndex and/or $endIndex are invalid.'); - } - if (endIndex > bus.width - 1 || startIndex > bus.width - 1) { + // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) + var modifiedStartIndex = + (startIndex < 0) ? bus.width + startIndex : startIndex; + var modifiedEndIndex = (endIndex < 0) ? bus.width + endIndex : endIndex; + + if (modifiedEndIndex > bus.width - 1 || + modifiedStartIndex > bus.width - 1) { throw Exception( 'Index out of bounds, indices $startIndex and $endIndex must be less than width-1'); } _original = Module.unpreferredName('original_' + bus.name); - _subset = - Module.unpreferredName('subset_${endIndex}_${startIndex}_' + bus.name); + _subset = Module.unpreferredName( + 'subset_${modifiedEndIndex}_${modifiedStartIndex}_' + bus.name); addInput(_original, bus, width: bus.width); - var newWidth = (endIndex - startIndex).abs() + 1; + var newWidth = (modifiedEndIndex - modifiedStartIndex).abs() + 1; addOutput(_subset, width: newWidth); subset .makeUnassignable(); // so that people can't do a slice assign, not (yet?) implemented From b2e9cdea2695111c10beb68d2674816a3b985d75 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Thu, 25 Aug 2022 20:22:11 -0400 Subject: [PATCH 02/12] [Fix-issue#99] getRange exception removed and handled in slice() --- lib/src/logic.dart | 19 ++----------------- lib/src/modules/bus.dart | 8 +++++++- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/lib/src/logic.dart b/lib/src/logic.dart index 6ff4a4f8f..56842556f 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -444,25 +444,10 @@ class Logic { /// [startIndex] must be less than [endIndex]. If [startIndex] and [endIndex] are equal, then a /// zero-width signal is returned. Logic getRange(int startIndex, int endIndex) { - // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) - var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; - var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; - - if (modifiedEndIndex < modifiedStartIndex) { - throw Exception( - 'End ($endIndex) cannot be less than start ($startIndex).'); - } - if (modifiedEndIndex > width) { - throw Exception('End ($endIndex) must be less than width ($width).'); - } - if (modifiedStartIndex < 0) { - throw Exception( - 'Start ($startIndex) must be greater than or equal to 0.'); - } - if (modifiedEndIndex == modifiedStartIndex) { + if (endIndex == startIndex) { return Const(0, width: 0); } - return slice(modifiedEndIndex - 1, modifiedStartIndex); + return slice(endIndex - 1, startIndex); } /// Returns a new [Logic] with width [newWidth] where new bits added are zeros diff --git a/lib/src/modules/bus.dart b/lib/src/modules/bus.dart index fe7359732..dee2f24ec 100644 --- a/lib/src/modules/bus.dart +++ b/lib/src/modules/bus.dart @@ -35,10 +35,16 @@ class BusSubset extends Module with InlineSystemVerilog { (startIndex < 0) ? bus.width + startIndex : startIndex; var modifiedEndIndex = (endIndex < 0) ? bus.width + endIndex : endIndex; + // If a converted index value is still -ve then it's an Index out of bounds on a Logic Bus + if (modifiedStartIndex < 0 || modifiedEndIndex < 0) { + throw Exception( + 'Start ($startIndex=$modifiedStartIndex) and End ($endIndex=$modifiedEndIndex) must be greater than or equal to 0.'); + } + // If the +ve indices are more than Logic bus width, Index out of bounds if (modifiedEndIndex > bus.width - 1 || modifiedStartIndex > bus.width - 1) { throw Exception( - 'Index out of bounds, indices $startIndex and $endIndex must be less than width-1'); + 'Index out of bounds, indices $startIndex and $endIndex must be less than width'); } _original = Module.unpreferredName('original_' + bus.name); From 773003bb6172fdd4bbc5f12dfa0920da6cc9bf07 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Fri, 2 Sep 2022 09:42:27 -0400 Subject: [PATCH 03/12] [Fix-Issue#99] Allowing negative indices for all getRange(), operator[] & slice() and testing --- lib/src/logic.dart | 13 +++++++++++-- lib/src/modules/bus.dart | 19 +++++++------------ lib/src/utilities/simcompare.dart | 2 +- lib/src/values/logic_value.dart | 10 ++++++---- test/bus_test.dart | 20 +++++++++++++++++++- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/lib/src/logic.dart b/lib/src/logic.dart index 56842556f..cc65f3e36 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -433,7 +433,12 @@ class Logic { /// If [endIndex] is less than [startIndex], the returned value will be reversed relative /// to the original signal. Logic slice(int endIndex, int startIndex) { - return BusSubset(this, startIndex, endIndex).subset; + // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) + var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; + var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; + + // Create a new bus subset + return BusSubset(this, modifiedStartIndex, modifiedEndIndex).subset; } /// Returns a version of this [Logic] with the bit order reversed. @@ -447,7 +452,11 @@ class Logic { if (endIndex == startIndex) { return Const(0, width: 0); } - return slice(endIndex - 1, startIndex); + + // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) + var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; + var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; + return slice(modifiedEndIndex - 1, modifiedStartIndex); } /// Returns a new [Logic] with width [newWidth] where new bits added are zeros diff --git a/lib/src/modules/bus.dart b/lib/src/modules/bus.dart index dee2f24ec..6cc32ed6f 100644 --- a/lib/src/modules/bus.dart +++ b/lib/src/modules/bus.dart @@ -9,6 +9,7 @@ /// import 'package:rohd/rohd.dart'; +import 'package:test/expect.dart'; /// A [Module] which gives access to a subset range of signals of the input. /// @@ -30,29 +31,23 @@ class BusSubset extends Module with InlineSystemVerilog { BusSubset(Logic bus, this.startIndex, this.endIndex, {String name = 'bussubset'}) : super(name: name) { - // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) - var modifiedStartIndex = - (startIndex < 0) ? bus.width + startIndex : startIndex; - var modifiedEndIndex = (endIndex < 0) ? bus.width + endIndex : endIndex; - // If a converted index value is still -ve then it's an Index out of bounds on a Logic Bus - if (modifiedStartIndex < 0 || modifiedEndIndex < 0) { + if (startIndex < 0 || endIndex < 0) { throw Exception( - 'Start ($startIndex=$modifiedStartIndex) and End ($endIndex=$modifiedEndIndex) must be greater than or equal to 0.'); + 'Start ($startIndex) and End ($endIndex) must be greater than or equal to 0.'); } // If the +ve indices are more than Logic bus width, Index out of bounds - if (modifiedEndIndex > bus.width - 1 || - modifiedStartIndex > bus.width - 1) { + if (endIndex > bus.width - 1 || startIndex > bus.width - 1) { throw Exception( 'Index out of bounds, indices $startIndex and $endIndex must be less than width'); } _original = Module.unpreferredName('original_' + bus.name); - _subset = Module.unpreferredName( - 'subset_${modifiedEndIndex}_${modifiedStartIndex}_' + bus.name); + _subset = + Module.unpreferredName('subset_${endIndex}_${startIndex}_' + bus.name); addInput(_original, bus, width: bus.width); - var newWidth = (modifiedEndIndex - modifiedStartIndex).abs() + 1; + var newWidth = (endIndex - startIndex).abs() + 1; addOutput(_subset, width: newWidth); subset .makeUnassignable(); // so that people can't do a slice assign, not (yet?) implemented diff --git a/lib/src/utilities/simcompare.dart b/lib/src/utilities/simcompare.dart index da4038efe..80b7630a1 100644 --- a/lib/src/utilities/simcompare.dart +++ b/lib/src/utilities/simcompare.dart @@ -169,7 +169,7 @@ class SimCompare { Directory(dir).createSync(recursive: true); File(tmpTestFile).writeAsStringSync(testbench); var compileResult = Process.runSync('iverilog', - ['-g2012', tmpTestFile, '-o', tmpOutput] + iverilogExtraArgs); + ['-g2012', '-o', tmpOutput, ...iverilogExtraArgs, tmpTestFile]); bool printIfContentsAndCheckError(dynamic output) { if (output.toString().isNotEmpty) print(output); return output diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart index 917122f8a..8fdd791d7 100644 --- a/lib/src/values/logic_value.dart +++ b/lib/src/values/logic_value.dart @@ -287,18 +287,20 @@ abstract class LogicValue { /// [startIndex] must be less than [endIndex]. If [startIndex] and [endIndex] are equal, then a /// zero-width value is returned. LogicValue getRange(int startIndex, int endIndex) { - if (endIndex < startIndex) { + var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; + var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; + if (modifiedEndIndex < modifiedStartIndex) { throw Exception( 'End ($endIndex) cannot be less than start ($startIndex).'); } - if (endIndex > width) { + if (modifiedEndIndex > width) { throw Exception('End ($endIndex) must be less than width ($width).'); } - if (startIndex < 0) { + if (modifiedStartIndex < 0) { throw Exception( 'Start ($startIndex) must be greater than or equal to 0.'); } - return _getRange(startIndex, endIndex); + return _getRange(modifiedStartIndex, modifiedEndIndex); } /// Returns a subset [LogicValue]. It is inclusive of [start], exclusive of [end]. diff --git a/test/bus_test.dart b/test/bus_test.dart index 881ab2b4d..d4d4966e4 100644 --- a/test/bus_test.dart +++ b/test/bus_test.dart @@ -42,6 +42,9 @@ class BusTestModule extends Module { var aBJoined = addOutput('a_b_joined', width: a.width + b.width); var aPlusB = addOutput('a_plus_b', width: a.width); var a1 = addOutput('a1'); + var aNegativeShrunk = addOutput('a_neg_shrunk', width: 3); + var aRNegativeSliced = addOutput('a_r_neg_sliced', width: 5); + var aNegativeRange = addOutput('a_neg_range', width: 3); aBar <= ~a; aAndB <= a & b; @@ -52,6 +55,9 @@ class BusTestModule extends Module { aBJoined <= [b, a].swizzle(); a1 <= a[1]; aPlusB <= a + b; + aNegativeShrunk <= a.slice(-6, 0); + aRNegativeSliced <= a.slice(-5, -1); + aNegativeRange <= a.getRange(-3, 8); } } @@ -148,7 +154,10 @@ void main() { 'a_reversed': 8, 'a_range': 3, 'a_b_joined': 16, - 'a_plus_b': 8 + 'a_plus_b': 8, + 'a_neg_shrunk': 3, + 'a_r_neg_sliced': 5, + 'a_neg_range': 3 }; test('NotGate bus', () async { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); @@ -190,6 +199,9 @@ void main() { Vector({'a': 0}, {'a_shrunk': 0}), Vector({'a': 0xff}, {'a_shrunk': bin('111')}), Vector({'a': 0xf5}, {'a_shrunk': 5}), + Vector({'a': 0}, {'a_neg_shrunk': 0}), + Vector({'a': 0xff}, {'a_neg_shrunk': bin('111')}), + Vector({'a': 0xf5}, {'a_neg_shrunk': 5}) ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -205,6 +217,9 @@ void main() { Vector({'a': 0}, {'a_rsliced': 0}), Vector({'a': 0xff}, {'a_rsliced': bin('11111')}), Vector({'a': 0xf5}, {'a_rsliced': 0xf}), + Vector({'a': 0}, {'a_r_neg_sliced': 0}), + Vector({'a': 0xff}, {'a_r_neg_sliced': bin('11111')}), + Vector({'a': 0xf5}, {'a_r_neg_sliced': 0xf}), ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -235,6 +250,9 @@ void main() { Vector({'a': 0}, {'a_range': 0}), Vector({'a': 0xff}, {'a_range': 7}), Vector({'a': bin('10100101')}, {'a_range': bin('101')}), + Vector({'a': 0}, {'a_neg_range': 0}), + Vector({'a': 0xff}, {'a_neg_range': 7}), + Vector({'a': bin('10100101')}, {'a_neg_range': bin('101')}), ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( From ecdb7091e4e272653cadce9835ead36dccb7e539 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Fri, 2 Sep 2022 10:03:15 -0400 Subject: [PATCH 04/12] [Fix-Issue#99] Documentation on getRange(), slice() & operator[] and Bug fix on getRange() condition startindex<=endindex --- lib/src/logic.dart | 12 ++++++++++-- lib/src/values/logic_value.dart | 3 ++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/src/logic.dart b/lib/src/logic.dart index cc65f3e36..bfcfc8718 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -424,14 +424,17 @@ class Logic { } /// Accesses the [index]th bit of this signal. + /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) + /// -([width]) <= [index] < [width] Logic operator [](int index) { return slice(index, index); } /// Accesses a subset of this signal from [startIndex] to [endIndex], both inclusive. /// - /// If [endIndex] is less than [startIndex], the returned value will be reversed relative + /// If [endIndex] comes before the [startIndex] on position, the returned value will be reversed relative /// to the original signal. + /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) Logic slice(int endIndex, int startIndex) { // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; @@ -446,8 +449,9 @@ class Logic { /// Returns a subset [Logic]. It is inclusive of [startIndex], exclusive of [endIndex]. /// - /// [startIndex] must be less than [endIndex]. If [startIndex] and [endIndex] are equal, then a + /// [startIndex] must come before the [endIndex]. If [startIndex] and [endIndex] are equal, then a /// zero-width signal is returned. + /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) Logic getRange(int startIndex, int endIndex) { if (endIndex == startIndex) { return Const(0, width: 0); @@ -456,6 +460,10 @@ class Logic { // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; + if (modifiedEndIndex < modifiedStartIndex) { + throw Exception( + 'End ($endIndex) cannot be less than start ($startIndex).'); + } return slice(modifiedEndIndex - 1, modifiedStartIndex); } diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart index 8fdd791d7..422775398 100644 --- a/lib/src/values/logic_value.dart +++ b/lib/src/values/logic_value.dart @@ -284,8 +284,9 @@ abstract class LogicValue { /// Returns a subset [LogicValue]. It is inclusive of [startIndex], exclusive of [endIndex]. /// - /// [startIndex] must be less than [endIndex]. If [startIndex] and [endIndex] are equal, then a + /// [startIndex] must come before the [endIndex] on position. If [startIndex] and [endIndex] are equal, then a /// zero-width value is returned. + /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) LogicValue getRange(int startIndex, int endIndex) { var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; From 9ee47b6d87807e92da8b027818d5c5d9d40d9a19 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 4 Oct 2022 16:31:34 -0400 Subject: [PATCH 05/12] [Issue-99] Fixing comments and testcases --- example/increment_value.dart | 71 +++++++++++++ example/slice_value.dart | 99 +++++++++++++++++++ lib/src/logic.dart | 41 +++++++- lib/src/modules/bus.dart | 1 - .../utilities/traverseable_collection.dart | 4 +- lib/src/values/logic_value.dart | 36 ++++++- test/bus_test.dart | 79 +++++++++------ 7 files changed, 292 insertions(+), 39 deletions(-) create mode 100644 example/increment_value.dart create mode 100644 example/slice_value.dart diff --git a/example/increment_value.dart b/example/increment_value.dart new file mode 100644 index 000000000..af1a80564 --- /dev/null +++ b/example/increment_value.dart @@ -0,0 +1,71 @@ +/// Copyright (C) 2021 Intel Corporation +/// SPDX-License-Identifier: BSD-3-Clause +/// +/// increment_value.dart +/// Increment a value by 1 +/// +/// 2021 September 17 +/// Author: Rahul Gautham Putcha +/// + +// Import the ROHD package + +import 'package:rohd/rohd.dart'; + +class Rough extends Module { + // For convenience, map interesting outputs to short variable names for consumers of this module + Logic get nextVal => output('nextVal'); + final int width; + Rough(Logic val, {this.width = 8, String name = 'rough'}) + : super(name: name) { + val = addInput('val', val, width: width); + var nextVal = addOutput('nextVal', width: width); + nextVal <= val + 0x1; // Increment a value by 1 + } +} + +// Let's simulate with this counter a little, generate a waveform, and take a look at generated SystemVerilog. +Future main({bool noPrint = false}) async { + // Define some local signals. + var en = Logic(name: 'en', width: 8); + + // Build a counter. + var counter = Rough(en); + + // Before we can simulate or generate code with the counter, we need to build it. + await counter.build(); + + // Let's see what this module looks like as SystemVerilog, so we can pass it to other tools. + var systemVerilogCode = counter.generateSynth(); + if (!noPrint) print(systemVerilogCode); + + // Now let's try simulating! + + // Let's start off with a disabled counter and asserting reset. + en.inject(0); + + // Attach a waveform dumper so we can see what happens. + if (!noPrint) WaveDumper(counter); + + // Raise enable at time 45. + Simulator.registerAction( + 45, () => en.put(1)); // substituting value at time 45 + + // Print a message when we're done with the simulation! + Simulator.registerAction(100, () { + // print (sim...) at time 100 + if (!noPrint) print('Simulation completed!'); + }); + + // Set a maximum time for the simulation so it doesn't keep running forever. + Simulator.setMaxSimTime(100); + + // Kick off the simulation. + await Simulator.run(); + + // We can take a look at the waves now. + if (!noPrint) { + print( + 'To view waves, check out waves.vcd with a waveform viewer (e.g. `gtkwave waves.vcd`).'); + } +} diff --git a/example/slice_value.dart b/example/slice_value.dart new file mode 100644 index 000000000..983c314aa --- /dev/null +++ b/example/slice_value.dart @@ -0,0 +1,99 @@ +/// Copyright (C) 2021 Intel Corporation +/// SPDX-License-Identifier: BSD-3-Clause +/// +/// rough.dart +/// Checking out the library +/// +/// 2021 October 04 +/// Author: Rahul Gautham Putcha +/// + +// Import the ROHD package + +import 'package:rohd/rohd.dart'; + +class LogicSubset extends Module { + // For convenience, map interesting outputs to short variable names for consumers of this module + Logic get nextVal => output('nextVal'); + final int width; + + Logic negativeSliceTransform(Logic val) { + Logic nextVal = addOutput('nextVal', width: width); + + // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" + nextVal <= val.slice(val.width - 1, -3); // output: 0b110011 + // nextVal <= val.slice(val.width -1, -9); // output: Error! Overflow of start index: : Values allowed [-8, 7] + return nextVal; + } + + Logic positiveSliceTransform(Logic val) { + Logic nextVal = addOutput('nextVal', width: width); + + // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" + nextVal <= val.slice(5, 0); // output: 0b110011 + // nextVal <= val.slice(8, 0); // output: Error! Overflow of end index: Values allowed [-8, 7] + return nextVal; + } + + Logic negativGetRangeTransform(Logic val) { + Logic nextVal = addOutput('nextVal', width: width); + + // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" + nextVal <= val.slice(val.width - 1, -3); // output: 0b110011 + // nextVal <= val.getRange(val.width - 1, -9); // output: Error! Overflow of start index: : Values allowed [-8, 7] + return nextVal; + } + + LogicSubset(Logic val, {this.width = 8, String name = 'rough'}) + : super(name: name) { + val = addInput('val', val, width: width); + negativeSliceTransform(val); + // positiveSliceTransform(val); + } +} + +// Let's simulate with this counter a little, generate a waveform, and take a look at generated SystemVerilog. +Future main({bool noPrint = false}) async { + // Define some local signals. + var en = Logic(name: 'en', width: 8); + + // Build a counter. + var counter = LogicSubset(en); + + // Before we can simulate or generate code with the counter, we need to build it. + await counter.build(); + + // Let's see what this module looks like as SystemVerilog, so we can pass it to other tools. + var systemVerilogCode = counter.generateSynth(); + if (!noPrint) print(systemVerilogCode); + + // Now let's try simulating! + + // Let's start off with a disabled counter and asserting reset. + en.inject(0); + + // Attach a waveform dumper so we can see what happens. + if (!noPrint) WaveDumper(counter); + + // Raise enable at time 45. + Simulator.registerAction( + 45, () => en.put(1)); // substituting value at time 45 + + // Print a message when we're done with the simulation! + Simulator.registerAction(100, () { + // print (sim...) at time 100 + if (!noPrint) print('Simulation completed!'); + }); + + // Set a maximum time for the simulation so it doesn't keep running forever. + Simulator.setMaxSimTime(100); + + // Kick off the simulation. + await Simulator.run(); + + // We can take a look at the waves now. + if (!noPrint) { + print( + 'To view waves, check out waves.vcd with a waveform viewer (e.g. `gtkwave waves.vcd`).'); + } +} diff --git a/lib/src/logic.dart b/lib/src/logic.dart index bfcfc8718..c1c4f9ced 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -424,8 +424,23 @@ class Logic { } /// Accesses the [index]th bit of this signal. - /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) + /// + /// Negative/Positive index values are allowed. (The negative indexing starts from the end=[width]-1) /// -([width]) <= [index] < [width] + /// + /// ```dart + /// Logic nextVal = addOutput('nextVal', width: width); + /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" + /// // Positive Indexing + /// nextVal <= val[3]; // output: 0 + /// + /// // Negative Indexing + /// nextVal <= val[-3]; // output: 1 + /// + /// // Error case + /// nextVal <= val[-9]; // Error!: allowed values [-8, 7] + /// ``` + /// Logic operator [](int index) { return slice(index, index); } @@ -435,6 +450,17 @@ class Logic { /// If [endIndex] comes before the [startIndex] on position, the returned value will be reversed relative /// to the original signal. /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) + /// + /// ```dart + /// Logic nextVal = addOutput('nextVal', width: width); + /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" + /// // Negative Slicing + /// nextVal <= val.slice(val.width - 1, -3); // output: 0b110011 + /// + /// // Positive Slicing + /// nextVal <= val.slice(5, 0); // output: 0b110011 + /// ``` + /// Logic slice(int endIndex, int startIndex) { // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; @@ -449,9 +475,20 @@ class Logic { /// Returns a subset [Logic]. It is inclusive of [startIndex], exclusive of [endIndex]. /// - /// [startIndex] must come before the [endIndex]. If [startIndex] and [endIndex] are equal, then a + /// The [startIndex] must come before the [endIndex]. If [startIndex] and [endIndex] are equal, then a /// zero-width signal is returned. /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) + /// + /// ```dart + /// Logic nextVal = addOutput('nextVal', width: width); + /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" + /// // Negative getRange + /// nextVal <= val.getRange(val.width - 1, -3); // output: 0b110011 + /// + /// // Positive getRange + /// nextVal <= val.getRange(5, 0); // output: 0b110011 + /// ``` + /// Logic getRange(int startIndex, int endIndex) { if (endIndex == startIndex) { return Const(0, width: 0); diff --git a/lib/src/modules/bus.dart b/lib/src/modules/bus.dart index 6cc32ed6f..7528dd490 100644 --- a/lib/src/modules/bus.dart +++ b/lib/src/modules/bus.dart @@ -9,7 +9,6 @@ /// import 'package:rohd/rohd.dart'; -import 'package:test/expect.dart'; /// A [Module] which gives access to a subset range of signals of the input. /// diff --git a/lib/src/utilities/traverseable_collection.dart b/lib/src/utilities/traverseable_collection.dart index 06c4d5ad2..46d575bdc 100644 --- a/lib/src/utilities/traverseable_collection.dart +++ b/lib/src/utilities/traverseable_collection.dart @@ -57,8 +57,10 @@ class TraverseableCollection { /// The object at the given [index] in the collection. /// /// The [index] must be a valid index of this collection, which means that index must be non-negative and less than [length]. + /// Negative/Positive index values are allowed. (Negative index values are positioned from back) T operator [](int index) { - return _list[index]; + int modifiedIndex = (index < 0) ? length + index : index; + return _list[modifiedIndex]; } /// Whether [item] is in the collection. diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart index 422775398..408a11dd2 100644 --- a/lib/src/values/logic_value.dart +++ b/lib/src/values/logic_value.dart @@ -268,12 +268,29 @@ abstract class LogicValue { } /// Returns the `i`th bit of this [LogicValue] + /// + /// The [index] provided can be positive or negative. For positive [index], the + /// indexing is performed from front of the LogicValue. For negative [index], + /// the indexing started from last index and goes to front. + /// Note: the [index] value must follow, -width <= [index] < width + /// + /// ```dart [TODO] + /// var bitValue = Logic(name: "bit_value", width: 8); + /// bitValue <= 0xf5; // Assign a LogicValue literal to our new variable + /// // Positive Indexing + /// var bitIndexValue = bitValue[2]; + /// print(bitIndexValue); // This prints `1b'0x1` + /// // Negative Indexing + /// var bitIndexValue = bitValue[-2]; + /// print(bitIndexValue); // This prints `1b'0x0` + /// ``` LogicValue operator [](int index) { - if (index >= width || index < 0) { + var modifiedIndex = (index < 0) ? width + index : index; + if (modifiedIndex >= width || modifiedIndex < 0) { throw IndexError(index, this, 'LogicValueIndexOutOfRange', - 'Index out of range: $index.', width); + 'Index out of range: $index (=$modifiedIndex).', width); } - return _getIndex(index); + return _getIndex(modifiedIndex); } /// Returns the `i`th bit of this [LogicValue]. Performs no boundary checks. @@ -286,7 +303,7 @@ abstract class LogicValue { /// /// [startIndex] must come before the [endIndex] on position. If [startIndex] and [endIndex] are equal, then a /// zero-width value is returned. - /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) + /// Negative/Positive index values are allowed. (The negative indexing starts from the end=[width]-1) LogicValue getRange(int startIndex, int endIndex) { var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; @@ -314,6 +331,17 @@ abstract class LogicValue { /// /// If [endIndex] is less than [startIndex], the returned value will be reversed relative /// to the original value. + /// + /// ```dart [TODO] + /// var bitValue = Logic(name: "bit_value", width: 8); + /// bitValue <= 0x; // Assign a LogicValue literal to our new variable + /// // Positive Indexing + /// var bitIndexValue = bitValue[2]; + /// print(bitIndexValue); // This prints `1b'0x1` + /// // Negative Indexing + /// var bitIndexValue = bitValue[-2]; + /// print(bitIndexValue); // This prints `1b'0x0` + /// ``` LogicValue slice(int endIndex, int startIndex) { if (startIndex <= endIndex) { return getRange(startIndex, endIndex + 1); diff --git a/test/bus_test.dart b/test/bus_test.dart index d4d4966e4..b1e1fb9a0 100644 --- a/test/bus_test.dart +++ b/test/bus_test.dart @@ -35,16 +35,33 @@ class BusTestModule extends Module { var aBar = addOutput('a_bar', width: a.width); var aAndB = addOutput('a_and_b', width: a.width); - var aShrunk = addOutput('a_shrunk', width: 3); - var aRSliced = addOutput('a_rsliced', width: 5); - var aReversed = addOutput('a_reversed', width: a.width); - var aRange = addOutput('a_range', width: 3); + var aBJoined = addOutput('a_b_joined', width: a.width + b.width); var aPlusB = addOutput('a_plus_b', width: a.width); var a1 = addOutput('a1'); - var aNegativeShrunk = addOutput('a_neg_shrunk', width: 3); - var aRNegativeSliced = addOutput('a_r_neg_sliced', width: 5); - var aNegativeRange = addOutput('a_neg_range', width: 3); + // Slicing with Positive Indices + var aShrunk1 = addOutput('a_shrunk', width: 3); + var aShrunk2 = addOutput('a_shrunk', width: 3); + var aShrunk3 = addOutput('a_shrunk', width: 3); + // Slicing with negative indices + var aNegativeShrunk1 = addOutput('a_neg_shrunk1', width: 3); + var aNegativeShrunk2 = addOutput('a_neg_shrunk2', width: 3); + var aNegativeShrunk3 = addOutput('a_neg_shrunk3', width: 3); + // Logic Reverse value + var aReversed = addOutput('a_reversed', width: a.width); + // Slicing and reversing the value + var aRSliced1 = addOutput('a_rsliced', width: 5); + var aRSliced2 = addOutput('a_rsliced', width: 5); + var aRSliced3 = addOutput('a_rsliced', width: 5); + // Slicing and reversing the value via negative indices + var aRNegativeSliced1 = addOutput('a_r_neg_sliced1', width: 5); + var aRNegativeSliced2 = addOutput('a_r_neg_sliced2', width: 5); + var aRNegativeSliced3 = addOutput('a_r_neg_sliced3', width: 5); + // Getting the range of consecutive values over the Logic (subset) + var aRange = addOutput('a_range', width: 3); + var aNegativeRange1 = addOutput('a_neg_range1', width: 3); + var aNegativeRange2 = addOutput('a_neg_range2', width: 3); + var aNegativeRange3 = addOutput('a_neg_range3', width: 3); aBar <= ~a; aAndB <= a & b; @@ -55,9 +72,9 @@ class BusTestModule extends Module { aBJoined <= [b, a].swizzle(); a1 <= a[1]; aPlusB <= a + b; - aNegativeShrunk <= a.slice(-6, 0); - aRNegativeSliced <= a.slice(-5, -1); - aNegativeRange <= a.getRange(-3, 8); + aNegativeShrunk1 <= a.slice(-6, 0); + aRNegativeSliced1 <= a.slice(-5, -1); + aNegativeRange1 <= a.getRange(-3, 8); } } @@ -196,12 +213,12 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ - Vector({'a': 0}, {'a_shrunk': 0}), - Vector({'a': 0xff}, {'a_shrunk': bin('111')}), - Vector({'a': 0xf5}, {'a_shrunk': 5}), - Vector({'a': 0}, {'a_neg_shrunk': 0}), - Vector({'a': 0xff}, {'a_neg_shrunk': bin('111')}), - Vector({'a': 0xf5}, {'a_neg_shrunk': 5}) + Vector({'a': 0}, {'a_shrunk1': 0}), + Vector({'a': 0xff}, {'a_shrunk1': bin('111')}), + Vector({'a': 0xf5}, {'a_shrunk1': 5}), + Vector({'a': 0}, {'a_neg_shrunk1': 0}), + Vector({'a': 0xff}, {'a_neg_shrunk1': bin('111')}), + Vector({'a': 0xf5}, {'a_neg_shrunk1': 5}) ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -214,12 +231,12 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ - Vector({'a': 0}, {'a_rsliced': 0}), - Vector({'a': 0xff}, {'a_rsliced': bin('11111')}), - Vector({'a': 0xf5}, {'a_rsliced': 0xf}), - Vector({'a': 0}, {'a_r_neg_sliced': 0}), - Vector({'a': 0xff}, {'a_r_neg_sliced': bin('11111')}), - Vector({'a': 0xf5}, {'a_r_neg_sliced': 0xf}), + Vector({'a': 0}, {'a_rsliced1': 0}), + Vector({'a': 0xff}, {'a_rsliced1': bin('11111')}), + Vector({'a': 0xf5}, {'a_rsliced1': 0xf}), + Vector({'a': 0}, {'a_r_neg_sliced1': 0}), + Vector({'a': 0xff}, {'a_r_neg_sliced1': bin('11111')}), + Vector({'a': 0xf5}, {'a_r_neg_sliced1': 0xf}), ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -232,9 +249,9 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ - Vector({'a': 0}, {'a_reversed': 0}), - Vector({'a': 0xff}, {'a_reversed': 0xff}), - Vector({'a': 0xf5}, {'a_reversed': 0xaf}), + Vector({'a': 0}, {'a_reversed1': 0}), + Vector({'a': 0xff}, {'a_reversed1': 0xff}), + Vector({'a': 0xf5}, {'a_reversed1': 0xaf}), ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -247,12 +264,12 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ - Vector({'a': 0}, {'a_range': 0}), - Vector({'a': 0xff}, {'a_range': 7}), - Vector({'a': bin('10100101')}, {'a_range': bin('101')}), - Vector({'a': 0}, {'a_neg_range': 0}), - Vector({'a': 0xff}, {'a_neg_range': 7}), - Vector({'a': bin('10100101')}, {'a_neg_range': bin('101')}), + Vector({'a': 0}, {'a_range1': 0}), + Vector({'a': 0xff}, {'a_range1': 7}), + Vector({'a': bin('10100101')}, {'a_range1': bin('101')}), + Vector({'a': 0}, {'a_neg_range1': 0}), + Vector({'a': 0xff}, {'a_neg_range1': 7}), + Vector({'a': bin('10100101')}, {'a_neg_range1': bin('101')}), ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( From 492707579e3184e697f0eac714be11ce885bcecd Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 11 Oct 2022 13:19:47 -0400 Subject: [PATCH 06/12] [Fix-Issue-99] Adding Logic & Logic Values testcases and dart doc examples in comments --- lib/src/logic.dart | 19 +-- lib/src/values/logic_value.dart | 23 ++- test/bus_test.dart | 259 ++++++++++++++++++++++++++------ test/logic_value_test.dart | 34 ++++- 4 files changed, 264 insertions(+), 71 deletions(-) diff --git a/lib/src/logic.dart b/lib/src/logic.dart index c1c4f9ced..53aacfd9d 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -430,15 +430,16 @@ class Logic { /// /// ```dart /// Logic nextVal = addOutput('nextVal', width: width); - /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" + /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b00001000" /// // Positive Indexing - /// nextVal <= val[3]; // output: 0 + /// nextVal <= val[3]; // output: 1 /// /// // Negative Indexing - /// nextVal <= val[-3]; // output: 1 + /// nextVal <= val[-5]; // output: 1 /// - /// // Error case + /// // Error cases /// nextVal <= val[-9]; // Error!: allowed values [-8, 7] + /// nextVal <= val[8]; // Error!: allowed values [-8, 7] /// ``` /// Logic operator [](int index) { @@ -455,14 +456,14 @@ class Logic { /// Logic nextVal = addOutput('nextVal', width: width); /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" /// // Negative Slicing - /// nextVal <= val.slice(val.width - 1, -3); // output: 0b110011 + /// nextVal <= val.slice(val.width - 1, -3); // = val.slice(7,5) & output: 0b110, where the output.width=3 /// /// // Positive Slicing - /// nextVal <= val.slice(5, 0); // output: 0b110011 + /// nextVal <= val.slice(5, 0); // = val.slice(-3, -8) & output: 0b001110, where the output.width=6 /// ``` /// Logic slice(int endIndex, int startIndex) { - // Given start and end index, if either of them are seen to be -ve index value(s) then conver them to a +ve index value(s) + // Given start and end index, if either of them are seen to be -ve index value(s) then convert them to a +ve index value(s) var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; @@ -483,10 +484,10 @@ class Logic { /// Logic nextVal = addOutput('nextVal', width: width); /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" /// // Negative getRange - /// nextVal <= val.getRange(val.width - 1, -3); // output: 0b110011 + /// nextVal <= val.getRange(-3, val.width); // = val.getRange(5,8) & output: 0b110, where the output.width=3 /// /// // Positive getRange - /// nextVal <= val.getRange(5, 0); // output: 0b110011 + /// nextVal <= val.getRange(0, 6); // = val.slice(0, -2) & output: 0b001110, where the output.width=6 /// ``` /// Logic getRange(int startIndex, int endIndex) { diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart index 408a11dd2..e68f6e286 100644 --- a/lib/src/values/logic_value.dart +++ b/lib/src/values/logic_value.dart @@ -307,16 +307,18 @@ abstract class LogicValue { LogicValue getRange(int startIndex, int endIndex) { var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; + // TODO: modifiedEndIndex must not be less than or equal to start Index if (modifiedEndIndex < modifiedStartIndex) { throw Exception( 'End ($endIndex) cannot be less than start ($startIndex).'); } if (modifiedEndIndex > width) { - throw Exception('End ($endIndex) must be less than width ($width).'); + throw Exception( + 'End $modifiedEndIndex(=$endIndex) must be less than width ($width).'); } if (modifiedStartIndex < 0) { throw Exception( - 'Start ($startIndex) must be greater than or equal to 0.'); + 'Start $modifiedStartIndex(=$startIndex) must be greater than or equal to 0.'); } return _getRange(modifiedStartIndex, modifiedEndIndex); } @@ -333,20 +335,15 @@ abstract class LogicValue { /// to the original value. /// /// ```dart [TODO] - /// var bitValue = Logic(name: "bit_value", width: 8); - /// bitValue <= 0x; // Assign a LogicValue literal to our new variable - /// // Positive Indexing - /// var bitIndexValue = bitValue[2]; - /// print(bitIndexValue); // This prints `1b'0x1` - /// // Negative Indexing - /// var bitIndexValue = bitValue[-2]; - /// print(bitIndexValue); // This prints `1b'0x0` + /// /// ``` LogicValue slice(int endIndex, int startIndex) { - if (startIndex <= endIndex) { - return getRange(startIndex, endIndex + 1); + var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; + var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; + if (modifiedStartIndex <= modifiedEndIndex) { + return getRange(modifiedStartIndex, modifiedEndIndex + 1); } else { - return getRange(endIndex, startIndex + 1).reversed; + return getRange(modifiedEndIndex, modifiedStartIndex + 1).reversed; } } diff --git a/test/bus_test.dart b/test/bus_test.dart index b1e1fb9a0..43f241093 100644 --- a/test/bus_test.dart +++ b/test/bus_test.dart @@ -13,17 +13,46 @@ import 'package:test/test.dart'; import 'package:rohd/src/utilities/simcompare.dart'; class BusTestModule extends Module { + // --- Getters --- Logic get aBar => output('a_bar'); Logic get aAndB => output('a_and_b'); - Logic get aShrunk => output('a_shrunk'); - Logic get aRSliced => output('a_rsliced'); - Logic get aReversed => output('a_reversed'); - Logic get aRange => output('a_range'); Logic get aBJoined => output('a_b_joined'); Logic get a1 => output('a1'); Logic get aPlusB => output('a_plus_b'); + // Getters for Logic subset test variables + Logic get aReversed => output('a_reversed'); + // --- Getters for Slicing + Logic get aShrunk1 => output('a_shrunk1'); + Logic get aShrunk2 => output('a_shrunk2'); + Logic get aShrunk3 => output('a_shrunk3'); + Logic get aNegShrunk1 => output('a_neg_shrunk1'); + Logic get aNegShrunk2 => output('a_neg_shrunk2'); + Logic get aNegShrunk3 => output('a_neg_shrunk3'); + // --- Getters for Reverse Slicing + Logic get aRSliced1 => output('a_rsliced1'); + Logic get aRSliced2 => output('a_rsliced2'); + Logic get aRSliced3 => output('a_rsliced3'); + Logic get aRNegativeSliced1 => output('a_r_neg_sliced1'); + Logic get aRNegativeSliced2 => output('a_r_neg_sliced2'); + Logic get aRNegativeSliced3 => output('a_r_neg_sliced3'); + // --- Getters for getRange + Logic get aRange1 => output('a_range1'); + Logic get aRange2 => output('a_range2'); + Logic get aRange3 => output('a_range3'); + Logic get aNegativeRange1 => output('a_neg_range1'); + Logic get aNegativeRange2 => output('a_neg_range2'); + Logic get aNegativeRange3 => output('a_neg_range3'); + // --- Getters for operator[] + // Logic get aOperatorIndexing1 => output('a_operator_indexing1'); + // Logic get aOperatorIndexing2 => output('a_operator_indexing2'); + // Logic get aOperatorIndexing3 => output('a_operator_indexing3'); + // Logic get aOperatorNegIndexing1 => output('a_operator_neg_indexing1'); + // Logic get aOperatorNegIndexing2 => output('a_operator_neg_indexing2'); + // Logic get aOperatorNegIndexing3 => output('a_operator_neg_indexing3'); + BusTestModule(Logic a, Logic b) : super(name: 'bustestmodule') { + // --- Declaration --- if (a.width != b.width) { throw Exception('a and b must be same width, but found "$a" and "$b".'); } @@ -39,42 +68,78 @@ class BusTestModule extends Module { var aBJoined = addOutput('a_b_joined', width: a.width + b.width); var aPlusB = addOutput('a_plus_b', width: a.width); var a1 = addOutput('a1'); + + // Logic Reverse value + var aReversed = addOutput('a_reversed', width: a.width); // Slicing with Positive Indices - var aShrunk1 = addOutput('a_shrunk', width: 3); - var aShrunk2 = addOutput('a_shrunk', width: 3); - var aShrunk3 = addOutput('a_shrunk', width: 3); + var aShrunk1 = addOutput('a_shrunk1', width: 3); + var aShrunk2 = addOutput('a_shrunk2', width: 2); + var aShrunk3 = addOutput('a_shrunk3', width: 1); // Slicing with negative indices var aNegativeShrunk1 = addOutput('a_neg_shrunk1', width: 3); - var aNegativeShrunk2 = addOutput('a_neg_shrunk2', width: 3); - var aNegativeShrunk3 = addOutput('a_neg_shrunk3', width: 3); - // Logic Reverse value - var aReversed = addOutput('a_reversed', width: a.width); + var aNegativeShrunk2 = addOutput('a_neg_shrunk2', width: 2); + var aNegativeShrunk3 = addOutput('a_neg_shrunk3', width: 1); // Slicing and reversing the value - var aRSliced1 = addOutput('a_rsliced', width: 5); - var aRSliced2 = addOutput('a_rsliced', width: 5); - var aRSliced3 = addOutput('a_rsliced', width: 5); + var aRSliced1 = addOutput('a_rsliced1', width: 5); + var aRSliced2 = addOutput('a_rsliced2', width: 2); + var aRSliced3 = addOutput('a_rsliced3', width: 1); // Slicing and reversing the value via negative indices var aRNegativeSliced1 = addOutput('a_r_neg_sliced1', width: 5); - var aRNegativeSliced2 = addOutput('a_r_neg_sliced2', width: 5); - var aRNegativeSliced3 = addOutput('a_r_neg_sliced3', width: 5); + var aRNegativeSliced2 = addOutput('a_r_neg_sliced2', width: 2); + var aRNegativeSliced3 = addOutput('a_r_neg_sliced3', width: 1); // Getting the range of consecutive values over the Logic (subset) - var aRange = addOutput('a_range', width: 3); + var aRange1 = addOutput('a_range1', width: 3); + var aRange2 = addOutput('a_range2', width: 2); + var aRange3 = addOutput('a_range3', width: 1); var aNegativeRange1 = addOutput('a_neg_range1', width: 3); - var aNegativeRange2 = addOutput('a_neg_range2', width: 3); - var aNegativeRange3 = addOutput('a_neg_range3', width: 3); + var aNegativeRange2 = addOutput('a_neg_range2', width: 2); + var aNegativeRange3 = addOutput('a_neg_range3', width: 1); + // // Operator Indexing with positive index value + // var aOperatorIndexing1 = addOutput('a_operator_indexing1', width: 1); + // var aOperatorIndexing2 = addOutput('a_operator_indexing2', width: 1); + // var aOperatorIndexing3 = addOutput('a_operator_indexing3', width: 1); + // // Operator Indexing with negative index value + // var aOperatorNegIndexing1 = addOutput('a_operator_neg_indexing1', width: 1); + // var aOperatorNegIndexing2 = addOutput('a_operator_neg_indexing2', width: 1); + // var aOperatorNegIndexing3 = addOutput('a_operator_neg_indexing3', width: 1); + // --- Assignments --- aBar <= ~a; aAndB <= a & b; - aShrunk <= a.slice(2, 0); - aRSliced <= a.slice(3, 7); - aReversed <= a.reversed; - aRange <= a.getRange(5, 8); aBJoined <= [b, a].swizzle(); a1 <= a[1]; aPlusB <= a + b; + + // Logic Subset functionality + aShrunk1 <= a.slice(2, 0); + aShrunk2 <= a.slice(1, 0); + aShrunk3 <= a.slice(0, 0); aNegativeShrunk1 <= a.slice(-6, 0); + aNegativeShrunk2 <= a.slice(-7, 0); + aNegativeShrunk3 <= a.slice(-8, 0); + + aRSliced1 <= a.slice(3, 7); + aRSliced2 <= a.slice(6, 7); + aRSliced3 <= a.slice(7, 7); aRNegativeSliced1 <= a.slice(-5, -1); - aNegativeRange1 <= a.getRange(-3, 8); + aRNegativeSliced2 <= a.slice(-2, -1); + aRNegativeSliced3 <= a.slice(-1, -1); + + aRange1 <= a.getRange(5, 8); + aRange2 <= a.getRange(6, 8); + aRange3 <= a.getRange(7, 8); + aNegativeRange1 <= a.getRange(-3, 8); // NOTE: endIndex value is exclusive + aNegativeRange2 <= a.getRange(-2, 8); + aNegativeRange3 <= a.getRange(-1, 8); + + // aOperatorIndexing1 <= a[0]; + // aOperatorIndexing2 <= a[a.width - 1]; + // aOperatorIndexing3 <= a[4]; + // aOperatorNegIndexing1 <= a[-1]; + // aOperatorNegIndexing2 <= a[-2]; + // aOperatorNegIndexing3 <= a[-a.width]; + + aReversed <= a.reversed; } } @@ -126,7 +191,7 @@ void main() { var a = Logic(width: 8); var b = Logic(width: 8); var gtm = BusTestModule(a, b); - var out = gtm.aShrunk; + var out = gtm.aShrunk1; await gtm.build(); a.put(0); expect(out.value.toInt(), equals(0)); @@ -136,6 +201,20 @@ void main() { expect(out.value.toInt(), equals(5)); }); + // test('Operator Indexing', () async { + // var a = Logic(width: 8); + // var b = Logic(width: 8); + // var gtm = BusTestModule(a, b); + // var out = gtm.aOperatorIndexing1; + // await gtm.build(); + // a.put(0); + // expect(out.value.toInt(), equals(0)); + // a.put(0xff); + // expect(out.value.toInt(), equals(bin('1'))); + // a.put(0xc1); + // expect(out.value.toInt(), equals(bin('1'))); + // }); + test('Bus swizzle', () async { var a = Logic(width: 8); var b = Logic(width: 8); @@ -166,15 +245,42 @@ void main() { 'b': 8, 'a_bar': 8, 'a_and_b': 8, - 'a_shrunk': 3, - 'a_rsliced': 5, - 'a_reversed': 8, - 'a_range': 3, 'a_b_joined': 16, 'a_plus_b': 8, - 'a_neg_shrunk': 3, - 'a_r_neg_sliced': 5, - 'a_neg_range': 3 + + // Slicing + 'a_shrunk1': 3, + 'a_shrunk2': 2, + 'a_shrunk3': 1, + 'a_neg_shrunk1': 3, + 'a_neg_shrunk2': 2, + 'a_neg_shrunk3': 1, + // Reverse Slicing + 'a_rsliced1': 5, + 'a_rsliced2': 2, + 'a_rsliced3': 1, + 'a_r_neg_sliced1': 5, + 'a_r_neg_sliced2': 2, + 'a_r_neg_sliced3': 1, + + // getRange + 'a_range1': 3, + 'a_range2': 2, + 'a_range3': 1, + 'a_neg_range1': 3, + 'a_neg_range2': 2, + 'a_neg_range3': 1, + + // // operator[] + // 'a_operator_indexing1': 3, + // 'a_operator_indexing2': 2, + // 'a_operator_indexing3': 1, + // 'a_operator_neg_indexing1': 3, + // 'a_operator_neg_indexing2': 2, + // 'a_operator_neg_indexing3': 1, + + // Logic bus value Reversed + 'a_reversed': 8 }; test('NotGate bus', () async { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); @@ -213,12 +319,33 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ + // Positive Indexing + // Test set 1 Vector({'a': 0}, {'a_shrunk1': 0}), - Vector({'a': 0xff}, {'a_shrunk1': bin('111')}), - Vector({'a': 0xf5}, {'a_shrunk1': 5}), + Vector({'a': 0xfa}, {'a_shrunk1': bin('010')}), + Vector({'a': 0xab}, {'a_shrunk1': 3}), + // Test set 2 + Vector({'a': 0}, {'a_shrunk2': 0}), + Vector({'a': 0xec}, {'a_shrunk2': bin('00')}), + Vector({'a': 0xfa}, {'a_shrunk2': 2}), + // Test set 3 + Vector({'a': 0}, {'a_shrunk3': 0}), + Vector({'a': 0xff}, {'a_shrunk3': bin('1')}), + Vector({'a': 0xba}, {'a_shrunk3': 0}), + + // Negative Indexing + // Test set 1 Vector({'a': 0}, {'a_neg_shrunk1': 0}), - Vector({'a': 0xff}, {'a_neg_shrunk1': bin('111')}), - Vector({'a': 0xf5}, {'a_neg_shrunk1': 5}) + Vector({'a': 0xfa}, {'a_neg_shrunk1': bin('010')}), + Vector({'a': 0xab}, {'a_neg_shrunk1': 3}), + // Test set 2 + Vector({'a': 0}, {'a_neg_shrunk2': 0}), + Vector({'a': 0xec}, {'a_neg_shrunk2': bin('00')}), + Vector({'a': 0xfa}, {'a_neg_shrunk2': 2}), + // Test set 3 + Vector({'a': 0}, {'a_neg_shrunk3': 0}), + Vector({'a': 0xff}, {'a_neg_shrunk3': bin('1')}), + Vector({'a': 0xba}, {'a_neg_shrunk3': 0}) ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -231,12 +358,33 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ + // Positive Indexing + // Test set 1 Vector({'a': 0}, {'a_rsliced1': 0}), - Vector({'a': 0xff}, {'a_rsliced1': bin('11111')}), + Vector({'a': 0xac}, {'a_rsliced1': bin('10101')}), Vector({'a': 0xf5}, {'a_rsliced1': 0xf}), + // Test set 2 + Vector({'a': 0}, {'a_rsliced2': 0}), + Vector({'a': 0xab}, {'a_rsliced2': bin('01')}), + Vector({'a': 0xac}, {'a_rsliced2': 1}), + // Test set 3 + Vector({'a': 0}, {'a_rsliced3': 0}), + Vector({'a': 0xaf}, {'a_rsliced3': bin('1')}), + Vector({'a': 0xaf}, {'a_rsliced3': 1}), + + // Negative Indexing + // Test set 1 Vector({'a': 0}, {'a_r_neg_sliced1': 0}), - Vector({'a': 0xff}, {'a_r_neg_sliced1': bin('11111')}), + Vector({'a': 0xac}, {'a_r_neg_sliced1': bin('10101')}), Vector({'a': 0xf5}, {'a_r_neg_sliced1': 0xf}), + // Test set 2 + Vector({'a': 0}, {'a_r_neg_sliced2': 0}), + Vector({'a': 0xab}, {'a_r_neg_sliced2': bin('01')}), + Vector({'a': 0xac}, {'a_r_neg_sliced2': 1}), + // Test set 3 + Vector({'a': 0}, {'a_r_neg_sliced3': 0}), + Vector({'a': 0xaf}, {'a_r_neg_sliced3': bin('1')}), + Vector({'a': 0xaf}, {'a_r_neg_sliced3': 1}) ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -249,9 +397,9 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ - Vector({'a': 0}, {'a_reversed1': 0}), - Vector({'a': 0xff}, {'a_reversed1': 0xff}), - Vector({'a': 0xf5}, {'a_reversed1': 0xaf}), + Vector({'a': 0}, {'a_reversed': 0}), + Vector({'a': 0xff}, {'a_reversed': 0xff}), + Vector({'a': 0xf5}, {'a_reversed': 0xaf}), ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( @@ -264,12 +412,33 @@ void main() { var gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); await gtm.build(); var vectors = [ + // Positive Indexing + // Test set 1 Vector({'a': 0}, {'a_range1': 0}), - Vector({'a': 0xff}, {'a_range1': 7}), - Vector({'a': bin('10100101')}, {'a_range1': bin('101')}), + Vector({'a': 0xaf}, {'a_range1': 5}), + Vector({'a': bin('11000101')}, {'a_range1': bin('110')}), + // Test set 2 + Vector({'a': 0}, {'a_range2': 0}), + Vector({'a': 0xaf}, {'a_range2': 2}), + Vector({'a': bin('10111111')}, {'a_range2': bin('10')}), + // Test set 3 + Vector({'a': 0}, {'a_range3': 0}), + Vector({'a': 0x80}, {'a_range3': 1}), + Vector({'a': bin('10000000')}, {'a_range3': bin('1')}), + + // Negative Indexing + // Test set 1 Vector({'a': 0}, {'a_neg_range1': 0}), - Vector({'a': 0xff}, {'a_neg_range1': 7}), - Vector({'a': bin('10100101')}, {'a_neg_range1': bin('101')}), + Vector({'a': 0xaf}, {'a_neg_range1': 5}), + Vector({'a': bin('11000101')}, {'a_neg_range1': bin('110')}), + // Test set 2 + Vector({'a': 0}, {'a_neg_range2': 0}), + Vector({'a': 0xaf}, {'a_neg_range2': 2}), + Vector({'a': bin('10111111')}, {'a_neg_range2': bin('10')}), + // Test set 3 + Vector({'a': 0}, {'a_neg_range3': 0}), + Vector({'a': 0x80}, {'a_neg_range3': 1}), + Vector({'a': bin('10000000')}, {'a_neg_range3': bin('1')}), ]; await SimCompare.checkFunctionalVector(gtm, vectors); var simResult = SimCompare.iverilogVector( diff --git a/test/logic_value_test.dart b/test/logic_value_test.dart index 8d70931d8..fd91153b8 100644 --- a/test/logic_value_test.dart +++ b/test/logic_value_test.dart @@ -326,9 +326,17 @@ void main() { () => LogicValue.ofString('0101')[10], throwsA(isA())); expect( - // index - negative - () => LogicValue.ofString('0101')[-1], + // index - out of range + () => LogicValue.ofString('0101')[-5], throwsA(isA())); + expect( + // index - negative + LogicValue.ofString('0111')[-1], + equals(LogicValue.zero)); + expect( + // index - negative + LogicValue.ofString('0100')[-2], + equals(LogicValue.one)); expect( // reversed LogicValue.ofString('0101').reversed, @@ -338,9 +346,21 @@ void main() { LogicValue.ofString('0101').getRange(0, 2), equals(LogicValue.ofString('01'))); expect( - // getRange - bad inputs start < 0 - () => LogicValue.ofString('0101').getRange(-2, 1), + // getRange - negative end index and start < end + LogicValue.ofString('0101').getRange(1, -2), + LogicValue.zero); + expect( + // getRange - negative end index and start < end + LogicValue.ofString('0101').getRange(-3, 4), + equals(LogicValue.ofString('010'))); + expect( + // getRange - negative end index and start > end - error! start must be less than end + () => LogicValue.ofString('0101').getRange(-1, -2), throwsA(isA())); + // expect( // TODO: Resolving this test seems to cause errors in other test cases + // // getRange - negative end index and start = end | error! start must be less than end + // () => LogicValue.ofString('0101').getRange(-1, -1), + // throwsA(isA())); expect( // getRange - bad inputs start > end () => LogicValue.ofString('0101').getRange(2, 1), @@ -351,8 +371,14 @@ void main() { throwsA(isA())); expect(LogicValue.ofString('xz01').slice(2, 1), equals(LogicValue.ofString('z0'))); + expect(LogicValue.ofString('xz01').slice(-2, -3), + equals(LogicValue.ofString('z0'))); expect(LogicValue.ofString('xz01').slice(1, 3), equals(LogicValue.ofString('0zx'))); + expect(LogicValue.ofString('xz01').slice(-3, -1), + equals(LogicValue.ofString('0zx'))); + expect(LogicValue.ofString('xz01').slice(-2, -2), + equals(LogicValue.ofString('z'))); expect( // isValid - valid LogicValue.ofString('0101').isValid, From 0a7a5ebc2356fa8cc25105e1fa9c50f1a383b53c Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 11 Oct 2022 13:21:21 -0400 Subject: [PATCH 07/12] Remove unnecessary example files --- example/increment_value.dart | 71 -------------------------- example/slice_value.dart | 99 ------------------------------------ 2 files changed, 170 deletions(-) delete mode 100644 example/increment_value.dart delete mode 100644 example/slice_value.dart diff --git a/example/increment_value.dart b/example/increment_value.dart deleted file mode 100644 index af1a80564..000000000 --- a/example/increment_value.dart +++ /dev/null @@ -1,71 +0,0 @@ -/// Copyright (C) 2021 Intel Corporation -/// SPDX-License-Identifier: BSD-3-Clause -/// -/// increment_value.dart -/// Increment a value by 1 -/// -/// 2021 September 17 -/// Author: Rahul Gautham Putcha -/// - -// Import the ROHD package - -import 'package:rohd/rohd.dart'; - -class Rough extends Module { - // For convenience, map interesting outputs to short variable names for consumers of this module - Logic get nextVal => output('nextVal'); - final int width; - Rough(Logic val, {this.width = 8, String name = 'rough'}) - : super(name: name) { - val = addInput('val', val, width: width); - var nextVal = addOutput('nextVal', width: width); - nextVal <= val + 0x1; // Increment a value by 1 - } -} - -// Let's simulate with this counter a little, generate a waveform, and take a look at generated SystemVerilog. -Future main({bool noPrint = false}) async { - // Define some local signals. - var en = Logic(name: 'en', width: 8); - - // Build a counter. - var counter = Rough(en); - - // Before we can simulate or generate code with the counter, we need to build it. - await counter.build(); - - // Let's see what this module looks like as SystemVerilog, so we can pass it to other tools. - var systemVerilogCode = counter.generateSynth(); - if (!noPrint) print(systemVerilogCode); - - // Now let's try simulating! - - // Let's start off with a disabled counter and asserting reset. - en.inject(0); - - // Attach a waveform dumper so we can see what happens. - if (!noPrint) WaveDumper(counter); - - // Raise enable at time 45. - Simulator.registerAction( - 45, () => en.put(1)); // substituting value at time 45 - - // Print a message when we're done with the simulation! - Simulator.registerAction(100, () { - // print (sim...) at time 100 - if (!noPrint) print('Simulation completed!'); - }); - - // Set a maximum time for the simulation so it doesn't keep running forever. - Simulator.setMaxSimTime(100); - - // Kick off the simulation. - await Simulator.run(); - - // We can take a look at the waves now. - if (!noPrint) { - print( - 'To view waves, check out waves.vcd with a waveform viewer (e.g. `gtkwave waves.vcd`).'); - } -} diff --git a/example/slice_value.dart b/example/slice_value.dart deleted file mode 100644 index 983c314aa..000000000 --- a/example/slice_value.dart +++ /dev/null @@ -1,99 +0,0 @@ -/// Copyright (C) 2021 Intel Corporation -/// SPDX-License-Identifier: BSD-3-Clause -/// -/// rough.dart -/// Checking out the library -/// -/// 2021 October 04 -/// Author: Rahul Gautham Putcha -/// - -// Import the ROHD package - -import 'package:rohd/rohd.dart'; - -class LogicSubset extends Module { - // For convenience, map interesting outputs to short variable names for consumers of this module - Logic get nextVal => output('nextVal'); - final int width; - - Logic negativeSliceTransform(Logic val) { - Logic nextVal = addOutput('nextVal', width: width); - - // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" - nextVal <= val.slice(val.width - 1, -3); // output: 0b110011 - // nextVal <= val.slice(val.width -1, -9); // output: Error! Overflow of start index: : Values allowed [-8, 7] - return nextVal; - } - - Logic positiveSliceTransform(Logic val) { - Logic nextVal = addOutput('nextVal', width: width); - - // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" - nextVal <= val.slice(5, 0); // output: 0b110011 - // nextVal <= val.slice(8, 0); // output: Error! Overflow of end index: Values allowed [-8, 7] - return nextVal; - } - - Logic negativGetRangeTransform(Logic val) { - Logic nextVal = addOutput('nextVal', width: width); - - // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" - nextVal <= val.slice(val.width - 1, -3); // output: 0b110011 - // nextVal <= val.getRange(val.width - 1, -9); // output: Error! Overflow of start index: : Values allowed [-8, 7] - return nextVal; - } - - LogicSubset(Logic val, {this.width = 8, String name = 'rough'}) - : super(name: name) { - val = addInput('val', val, width: width); - negativeSliceTransform(val); - // positiveSliceTransform(val); - } -} - -// Let's simulate with this counter a little, generate a waveform, and take a look at generated SystemVerilog. -Future main({bool noPrint = false}) async { - // Define some local signals. - var en = Logic(name: 'en', width: 8); - - // Build a counter. - var counter = LogicSubset(en); - - // Before we can simulate or generate code with the counter, we need to build it. - await counter.build(); - - // Let's see what this module looks like as SystemVerilog, so we can pass it to other tools. - var systemVerilogCode = counter.generateSynth(); - if (!noPrint) print(systemVerilogCode); - - // Now let's try simulating! - - // Let's start off with a disabled counter and asserting reset. - en.inject(0); - - // Attach a waveform dumper so we can see what happens. - if (!noPrint) WaveDumper(counter); - - // Raise enable at time 45. - Simulator.registerAction( - 45, () => en.put(1)); // substituting value at time 45 - - // Print a message when we're done with the simulation! - Simulator.registerAction(100, () { - // print (sim...) at time 100 - if (!noPrint) print('Simulation completed!'); - }); - - // Set a maximum time for the simulation so it doesn't keep running forever. - Simulator.setMaxSimTime(100); - - // Kick off the simulation. - await Simulator.run(); - - // We can take a look at the waves now. - if (!noPrint) { - print( - 'To view waves, check out waves.vcd with a waveform viewer (e.g. `gtkwave waves.vcd`).'); - } -} From 347ea3e5455557f46d2338a74a3227e91e20bdea Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 11 Oct 2022 14:05:11 -0400 Subject: [PATCH 08/12] [Fix-Issue-99] addition of doc example to LogicValue operator[] & addition of testcases to Logic operator[] --- lib/src/values/logic_value.dart | 34 ++++++++++----- test/bus_test.dart | 77 +++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 44 deletions(-) diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart index e68f6e286..a43122a3c 100644 --- a/lib/src/values/logic_value.dart +++ b/lib/src/values/logic_value.dart @@ -274,21 +274,19 @@ abstract class LogicValue { /// the indexing started from last index and goes to front. /// Note: the [index] value must follow, -width <= [index] < width /// - /// ```dart [TODO] - /// var bitValue = Logic(name: "bit_value", width: 8); - /// bitValue <= 0xf5; // Assign a LogicValue literal to our new variable - /// // Positive Indexing - /// var bitIndexValue = bitValue[2]; - /// print(bitIndexValue); // This prints `1b'0x1` - /// // Negative Indexing - /// var bitIndexValue = bitValue[-2]; - /// print(bitIndexValue); // This prints `1b'0x0` + /// ```dart + /// LogicValue.ofString('1111')[2]; // equals(LogicValue.one) + /// LogicValue.ofString('0111')[-1]; // equals(LogicValue.zero) + /// LogicValue.ofString('0100')[-2]; // equals(LogicValue.one) + /// LogicValue.ofString('0101')[-5]; // Error - out of range + /// LogicValue.ofString('0101')[10]; // Error - out of range /// ``` + /// LogicValue operator [](int index) { var modifiedIndex = (index < 0) ? width + index : index; if (modifiedIndex >= width || modifiedIndex < 0) { throw IndexError(index, this, 'LogicValueIndexOutOfRange', - 'Index out of range: $index (=$modifiedIndex).', width); + 'Index out of range: $modifiedIndex (=$index).', width); } return _getIndex(modifiedIndex); } @@ -304,6 +302,16 @@ abstract class LogicValue { /// [startIndex] must come before the [endIndex] on position. If [startIndex] and [endIndex] are equal, then a /// zero-width value is returned. /// Negative/Positive index values are allowed. (The negative indexing starts from the end=[width]-1) + /// + /// ```dart [TODO] + /// LogicValue.ofString('0101').getRange(0, 2); // equals(LogicValue.ofString('01')) + /// LogicValue.ofString('0101').getRange(1, -2); // = LogicValue.zero + /// LogicValue.ofString('0101').getRange(-3, 4); // equals(LogicValue.ofString('010')) + /// LogicValue.ofString('0101').getRange(-1, -2); // Error - negative end index and start > end - error! start must be less than end + /// LogicValue.ofString('0101').getRange(2, 1); // Error - bad inputs start > end + /// LogicValue.ofString('0101').getRange(0, 7); // Error - bad inputs end > length-1 + /// ``` + /// LogicValue getRange(int startIndex, int endIndex) { var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; var modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; @@ -335,7 +343,11 @@ abstract class LogicValue { /// to the original value. /// /// ```dart [TODO] - /// + /// LogicValue.ofString('xz01').slice(2, 1); // equals(LogicValue.ofString('z0')) + /// LogicValue.ofString('xz01').slice(-2, -3); // equals(LogicValue.ofString('z0')) + /// LogicValue.ofString('xz01').slice(1, 3); // equals(LogicValue.ofString('0zx')) + /// LogicValue.ofString('xz01').slice(-3, -1); // equals(LogicValue.ofString('0zx')) + /// LogicValue.ofString('xz01').slice(-2, -2); // equals(LogicValue.ofString('z')) /// ``` LogicValue slice(int endIndex, int startIndex) { var modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; diff --git a/test/bus_test.dart b/test/bus_test.dart index 43f241093..b601d37f5 100644 --- a/test/bus_test.dart +++ b/test/bus_test.dart @@ -44,12 +44,12 @@ class BusTestModule extends Module { Logic get aNegativeRange2 => output('a_neg_range2'); Logic get aNegativeRange3 => output('a_neg_range3'); // --- Getters for operator[] - // Logic get aOperatorIndexing1 => output('a_operator_indexing1'); - // Logic get aOperatorIndexing2 => output('a_operator_indexing2'); - // Logic get aOperatorIndexing3 => output('a_operator_indexing3'); - // Logic get aOperatorNegIndexing1 => output('a_operator_neg_indexing1'); - // Logic get aOperatorNegIndexing2 => output('a_operator_neg_indexing2'); - // Logic get aOperatorNegIndexing3 => output('a_operator_neg_indexing3'); + Logic get aOperatorIndexing1 => output('a_operator_indexing1'); + Logic get aOperatorIndexing2 => output('a_operator_indexing2'); + Logic get aOperatorIndexing3 => output('a_operator_indexing3'); + Logic get aOperatorNegIndexing1 => output('a_operator_neg_indexing1'); + Logic get aOperatorNegIndexing2 => output('a_operator_neg_indexing2'); + Logic get aOperatorNegIndexing3 => output('a_operator_neg_indexing3'); BusTestModule(Logic a, Logic b) : super(name: 'bustestmodule') { // --- Declaration --- @@ -94,14 +94,14 @@ class BusTestModule extends Module { var aNegativeRange1 = addOutput('a_neg_range1', width: 3); var aNegativeRange2 = addOutput('a_neg_range2', width: 2); var aNegativeRange3 = addOutput('a_neg_range3', width: 1); - // // Operator Indexing with positive index value - // var aOperatorIndexing1 = addOutput('a_operator_indexing1', width: 1); - // var aOperatorIndexing2 = addOutput('a_operator_indexing2', width: 1); - // var aOperatorIndexing3 = addOutput('a_operator_indexing3', width: 1); - // // Operator Indexing with negative index value - // var aOperatorNegIndexing1 = addOutput('a_operator_neg_indexing1', width: 1); - // var aOperatorNegIndexing2 = addOutput('a_operator_neg_indexing2', width: 1); - // var aOperatorNegIndexing3 = addOutput('a_operator_neg_indexing3', width: 1); + // Operator Indexing with positive index value + var aOperatorIndexing1 = addOutput('a_operator_indexing1', width: 1); + var aOperatorIndexing2 = addOutput('a_operator_indexing2', width: 1); + var aOperatorIndexing3 = addOutput('a_operator_indexing3', width: 1); + // Operator Indexing with negative index value + var aOperatorNegIndexing1 = addOutput('a_operator_neg_indexing1', width: 1); + var aOperatorNegIndexing2 = addOutput('a_operator_neg_indexing2', width: 1); + var aOperatorNegIndexing3 = addOutput('a_operator_neg_indexing3', width: 1); // --- Assignments --- aBar <= ~a; @@ -132,12 +132,12 @@ class BusTestModule extends Module { aNegativeRange2 <= a.getRange(-2, 8); aNegativeRange3 <= a.getRange(-1, 8); - // aOperatorIndexing1 <= a[0]; - // aOperatorIndexing2 <= a[a.width - 1]; - // aOperatorIndexing3 <= a[4]; - // aOperatorNegIndexing1 <= a[-1]; - // aOperatorNegIndexing2 <= a[-2]; - // aOperatorNegIndexing3 <= a[-a.width]; + aOperatorIndexing1 <= a[0]; + aOperatorIndexing2 <= a[a.width - 1]; + aOperatorIndexing3 <= a[4]; + aOperatorNegIndexing1 <= a[-a.width]; + aOperatorNegIndexing2 <= a[-1]; + aOperatorNegIndexing3 <= a[-2]; aReversed <= a.reversed; } @@ -201,19 +201,30 @@ void main() { expect(out.value.toInt(), equals(5)); }); - // test('Operator Indexing', () async { - // var a = Logic(width: 8); - // var b = Logic(width: 8); - // var gtm = BusTestModule(a, b); - // var out = gtm.aOperatorIndexing1; - // await gtm.build(); - // a.put(0); - // expect(out.value.toInt(), equals(0)); - // a.put(0xff); - // expect(out.value.toInt(), equals(bin('1'))); - // a.put(0xc1); - // expect(out.value.toInt(), equals(bin('1'))); - // }); + test('Operator Indexing', () async { + var a = Logic(width: 8); + var b = Logic(width: 8); + var gtm = BusTestModule(a, b); + var out1 = gtm.aOperatorIndexing1; + var out2 = gtm.aOperatorIndexing2; + var out3 = gtm.aOperatorIndexing3; + var out4 = gtm.aOperatorNegIndexing1; + var out5 = gtm.aOperatorNegIndexing2; + var out6 = gtm.aOperatorNegIndexing3; + await gtm.build(); + a.put(bin('11111110')); + expect(out1.value.toInt(), equals(0)); + a.put(bin('10000000')); + expect(out2.value.toInt(), equals(bin('1'))); + a.put(bin('11101111')); + expect(out3.value.toInt(), equals(bin('0'))); + a.put(bin('11111110')); + expect(out4.value.toInt(), equals(0)); + a.put(bin('10000000')); + expect(out5.value.toInt(), equals(bin('1'))); + a.put(bin('10111111')); + expect(out6.value.toInt(), equals(bin('0'))); + }); test('Bus swizzle', () async { var a = Logic(width: 8); From d53d885ddff07fec7decadb3bbb129f1fe32f1b5 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 11 Oct 2022 17:06:34 -0400 Subject: [PATCH 09/12] [FIX-ISSUE-99] Added Operator Indexing testcase for Logic (simcompare group) --- .../utilities/traverseable_collection.dart | 6 +--- lib/src/values/logic_value.dart | 23 ++++++------- test/bus_test.dart | 34 +++++++++++++++---- test/logic_value_test.dart | 11 +++--- 4 files changed, 45 insertions(+), 29 deletions(-) diff --git a/lib/src/utilities/traverseable_collection.dart b/lib/src/utilities/traverseable_collection.dart index ad9f479a8..1afcde270 100644 --- a/lib/src/utilities/traverseable_collection.dart +++ b/lib/src/utilities/traverseable_collection.dart @@ -58,11 +58,7 @@ class TraverseableCollection { /// /// The [index] must be a valid index of this collection, which means that /// index must be non-negative and less than [length]. - /// Negative/Positive index values are allowed. (Negative index values are positioned from back) - T operator [](int index) { - final modifiedIndex = (index < 0) ? length + index : index; - return _list[modifiedIndex]; - } + T operator [](int index) => _list[index]; /// Whether [item] is in the collection. bool contains(T item) => _set.contains(item); diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart index 135cce3a2..e90e73a51 100644 --- a/lib/src/values/logic_value.dart +++ b/lib/src/values/logic_value.dart @@ -306,9 +306,9 @@ abstract class LogicValue { /// Note: the [index] value must follow, -width <= [index] < width /// /// ```dart - /// LogicValue.ofString('1111')[2]; // equals(LogicValue.one) - /// LogicValue.ofString('0111')[-1]; // equals(LogicValue.zero) - /// LogicValue.ofString('0100')[-2]; // equals(LogicValue.one) + /// LogicValue.ofString('1111')[2]; // == LogicValue.one + /// LogicValue.ofString('0111')[-1]; // == LogicValue.zero + /// LogicValue.ofString('0100')[-2]; // == LogicValue.one /// LogicValue.ofString('0101')[-5]; // Error - out of range /// LogicValue.ofString('0101')[10]; // Error - out of range /// ``` @@ -337,9 +337,9 @@ abstract class LogicValue { /// Negative/Positive index values are allowed. (The negative indexing starts from the end=[width]-1) /// /// ```dart [TODO] - /// LogicValue.ofString('0101').getRange(0, 2); // equals(LogicValue.ofString('01')) - /// LogicValue.ofString('0101').getRange(1, -2); // = LogicValue.zero - /// LogicValue.ofString('0101').getRange(-3, 4); // equals(LogicValue.ofString('010')) + /// LogicValue.ofString('0101').getRange(0, 2); // == LogicValue.ofString('01') + /// LogicValue.ofString('0101').getRange(1, -2); // == LogicValue.zero + /// LogicValue.ofString('0101').getRange(-3, 4); // == LogicValue.ofString('010') /// LogicValue.ofString('0101').getRange(-1, -2); // Error - negative end index and start > end - error! start must be less than end /// LogicValue.ofString('0101').getRange(2, 1); // Error - bad inputs start > end /// LogicValue.ofString('0101').getRange(0, 7); // Error - bad inputs end > length-1 @@ -349,7 +349,6 @@ abstract class LogicValue { final modifiedStartIndex = (startIndex < 0) ? width + startIndex : startIndex; final modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; - // TODO: modifiedEndIndex must not be less than or equal to start Index if (modifiedEndIndex < modifiedStartIndex) { throw Exception( 'End ($endIndex) cannot be less than start ($startIndex).'); @@ -380,11 +379,11 @@ abstract class LogicValue { /// reversed relative to the original value. /// /// ```dart [TODO] - /// LogicValue.ofString('xz01').slice(2, 1); // equals(LogicValue.ofString('z0')) - /// LogicValue.ofString('xz01').slice(-2, -3); // equals(LogicValue.ofString('z0')) - /// LogicValue.ofString('xz01').slice(1, 3); // equals(LogicValue.ofString('0zx')) - /// LogicValue.ofString('xz01').slice(-3, -1); // equals(LogicValue.ofString('0zx')) - /// LogicValue.ofString('xz01').slice(-2, -2); // equals(LogicValue.ofString('z')) + /// LogicValue.ofString('xz01').slice(2, 1); // == LogicValue.ofString('z0') + /// LogicValue.ofString('xz01').slice(-2, -3); // == LogicValue.ofString('z0') + /// LogicValue.ofString('xz01').slice(1, 3); // == LogicValue.ofString('0zx') + /// LogicValue.ofString('xz01').slice(-3, -1); // == LogicValue.ofString('0zx') + /// LogicValue.ofString('xz01').slice(-2, -2); // == LogicValue.ofString('z') /// ``` LogicValue slice(int endIndex, int startIndex) { final modifiedStartIndex = diff --git a/test/bus_test.dart b/test/bus_test.dart index cc03082c9..4709ec041 100644 --- a/test/bus_test.dart +++ b/test/bus_test.dart @@ -283,13 +283,13 @@ void main() { 'a_neg_range2': 2, 'a_neg_range3': 1, - // // operator[] - // 'a_operator_indexing1': 3, - // 'a_operator_indexing2': 2, - // 'a_operator_indexing3': 1, - // 'a_operator_neg_indexing1': 3, - // 'a_operator_neg_indexing2': 2, - // 'a_operator_neg_indexing3': 1, + // operator[] + 'a_operator_indexing1': 1, + 'a_operator_indexing2': 1, + 'a_operator_indexing3': 1, + 'a_operator_neg_indexing1': 1, + 'a_operator_neg_indexing2': 1, + 'a_operator_neg_indexing3': 1, // Logic bus value Reversed 'a_reversed': 8, @@ -321,6 +321,26 @@ void main() { Vector({'a': 1, 'b': 1}, {'a_and_b': 1}), Vector({'a': 0xff, 'b': 0xaa}, {'a_and_b': 0xaa}), ]; + + await SimCompare.checkFunctionalVector(gtm, vectors); + final simResult = SimCompare.iverilogVector( + gtm.generateSynth(), gtm.runtimeType.toString(), vectors, + signalToWidthMap: signalToWidthMap); + expect(simResult, equals(true)); + }); + + test('Operator indexing', () async { + final gtm = BusTestModule(Logic(width: 8), Logic(width: 8)); + await gtm.build(); + final vectors = [ + Vector({'a': bin('11111110')}, {'a_operator_indexing1': 0}), + Vector({'a': bin('10000000')}, {'a_operator_indexing2': 1}), + Vector({'a': bin('11101111')}, {'a_operator_indexing3': 0}), + Vector({'a': bin('11111110')}, {'a_operator_neg_indexing1': 0}), + Vector({'a': bin('10000000')}, {'a_operator_neg_indexing2': 1}), + Vector({'a': bin('10111111')}, {'a_operator_neg_indexing3': 0}), + ]; + await SimCompare.checkFunctionalVector(gtm, vectors); final simResult = SimCompare.iverilogVector( gtm.generateSynth(), gtm.runtimeType.toString(), vectors, diff --git a/test/logic_value_test.dart b/test/logic_value_test.dart index 73320cbf2..a30580a21 100644 --- a/test/logic_value_test.dart +++ b/test/logic_value_test.dart @@ -346,13 +346,14 @@ void main() { LogicValue.ofString('0101').getRange(-3, 4), equals(LogicValue.ofString('010'))); expect( - // getRange - negative end index and start > end - error! start must be less than end + // getRange - negative end index and start > end - error! start must + // be less than end () => LogicValue.ofString('0101').getRange(-1, -2), throwsA(isA())); - // expect( // TODO: Resolving this test seems to cause errors in other test cases - // // getRange - negative end index and start = end | error! start must be less than end - // () => LogicValue.ofString('0101').getRange(-1, -1), - // throwsA(isA())); + expect( + // getRange - same index results zero width value + () => LogicValue.ofString('0101').getRange(-1, -1), + LogicValue.ofString('')); expect( // getRange - bad inputs start > end () => LogicValue.ofString('0101').getRange(2, 1), From a368ea1f68b308bc94aff74386aff2716122b777 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 11 Oct 2022 17:08:39 -0400 Subject: [PATCH 10/12] [FIX-ISSUE-99] Fixed Logic value testcase bug --- test/logic_value_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/logic_value_test.dart b/test/logic_value_test.dart index a30580a21..36d2a44c7 100644 --- a/test/logic_value_test.dart +++ b/test/logic_value_test.dart @@ -352,7 +352,7 @@ void main() { throwsA(isA())); expect( // getRange - same index results zero width value - () => LogicValue.ofString('0101').getRange(-1, -1), + LogicValue.ofString('0101').getRange(-1, -1), LogicValue.ofString('')); expect( // getRange - bad inputs start > end From c6baf885b2150f24ae4580987e33e336d5f7d675 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 11 Oct 2022 17:34:40 -0400 Subject: [PATCH 11/12] doc changes --- lib/src/utilities/traverseable_collection.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/utilities/traverseable_collection.dart b/lib/src/utilities/traverseable_collection.dart index 1afcde270..bda61dd8b 100644 --- a/lib/src/utilities/traverseable_collection.dart +++ b/lib/src/utilities/traverseable_collection.dart @@ -57,7 +57,7 @@ class TraverseableCollection { /// The object at the given [index] in the collection. /// /// The [index] must be a valid index of this collection, which means that - /// index must be non-negative and less than [length]. + /// [index] must be non-negative and less than [length]. T operator [](int index) => _list[index]; /// Whether [item] is in the collection. From 19774cc541db934b2ebec4a88c9e1891bf280f20 Mon Sep 17 00:00:00 2001 From: "Putcha, Rahul Gautham" Date: Tue, 11 Oct 2022 20:04:11 -0400 Subject: [PATCH 12/12] [FIXED-ISSUE-99] Typos fixed & cleaning docs --- lib/src/logic.dart | 10 +++++----- lib/src/utilities/simcompare.dart | 3 --- lib/src/values/logic_value.dart | 7 ++++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/src/logic.dart b/lib/src/logic.dart index ec7c8cb90..453344b1e 100644 --- a/lib/src/logic.dart +++ b/lib/src/logic.dart @@ -455,12 +455,12 @@ class Logic { /// /// ```dart /// Logic nextVal = addOutput('nextVal', width: width); - /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b00001000" + /// // Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110" /// // Positive Indexing /// nextVal <= val[3]; // output: 1 /// /// // Negative Indexing - /// nextVal <= val[-5]; // output: 1 + /// nextVal <= val[-5]; // output: 1, also val[3] == val[-5] /// /// // Error cases /// nextVal <= val[-9]; // Error!: allowed values [-8, 7] @@ -504,8 +504,7 @@ class Logic { /// [endIndex]. /// /// The [startIndex] must come before the [endIndex]. If [startIndex] and - /// [endIndex] are equal, then a - /// zero-width signal is returned. + /// [endIndex] are equal, then a zero-width signal is returned. /// Negative/Positive index values are allowed. (The negative indexing starts from where the array ends) /// /// ```dart @@ -530,7 +529,8 @@ class Logic { final modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; if (modifiedEndIndex < modifiedStartIndex) { throw Exception( - 'End ($endIndex) cannot be less than start ($startIndex).'); + 'End $modifiedEndIndex(=$endIndex) cannot be less than start' + ' $modifiedStartIndex(=$startIndex).'); } return slice(modifiedEndIndex - 1, modifiedStartIndex); } diff --git a/lib/src/utilities/simcompare.dart b/lib/src/utilities/simcompare.dart index 1b30b6183..48e9b6085 100644 --- a/lib/src/utilities/simcompare.dart +++ b/lib/src/utilities/simcompare.dart @@ -205,9 +205,6 @@ abstract class SimCompare { File(tmpTestFile).writeAsStringSync(testbench); final compileResult = Process.runSync('iverilog', ['-g2012', '-o', tmpOutput, ...iverilogExtraArgs, tmpTestFile]); - // [TODO] Old verilog code - // final compileResult = Process.runSync('iverilog', - // ['-g2012', tmpTestFile, '-o', tmpOutput] + iverilogExtraArgs); bool printIfContentsAndCheckError(dynamic output) { if (output.toString().isNotEmpty) { print(output); diff --git a/lib/src/values/logic_value.dart b/lib/src/values/logic_value.dart index e90e73a51..8d8c22629 100644 --- a/lib/src/values/logic_value.dart +++ b/lib/src/values/logic_value.dart @@ -303,7 +303,7 @@ abstract class LogicValue { /// the indexing is performed from front of the LogicValue. /// For negative [index], the indexing started from last index and /// goes to front. - /// Note: the [index] value must follow, -width <= [index] < width + /// Note: the [index] value must follow, -[width] <= [index] < [width] /// /// ```dart /// LogicValue.ofString('1111')[2]; // == LogicValue.one @@ -317,7 +317,7 @@ abstract class LogicValue { final modifiedIndex = (index < 0) ? width + index : index; if (modifiedIndex >= width || modifiedIndex < 0) { throw IndexError(index, this, 'LogicValueIndexOutOfRange', - 'Index out of range: $modifiedIndex (=$index).', width); + 'Index out of range: $modifiedIndex(=$index).', width); } return _getIndex(modifiedIndex); } @@ -351,7 +351,8 @@ abstract class LogicValue { final modifiedEndIndex = (endIndex < 0) ? width + endIndex : endIndex; if (modifiedEndIndex < modifiedStartIndex) { throw Exception( - 'End ($endIndex) cannot be less than start ($startIndex).'); + 'End $modifiedEndIndex(=$endIndex) cannot be less than start ' + '$modifiedStartIndex(=$startIndex).'); } if (modifiedEndIndex > width) { throw Exception(