-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
358 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Extrema | ||
|
||
ROHD-HCL provides a component to find the extrema of a list of Logic. | ||
|
||
The component `Extrema` will determine an extrema (maximum or minimum) and their position in a list of `Logic`s. | ||
|
||
## Description | ||
|
||
`Extrema` will take in an input containing a `List<Logic>` along with a parameter `max`. | ||
|
||
* `max` is a boolean indicating whether to find the maximum value (`true`), or the minimum value (`false`). Default is `true`. | ||
|
||
`Extrema` will then ouput two `Logic` signals: | ||
|
||
* `index` The index or position of the first extrema in the list. | ||
|
||
* `index` will be a `Logic` with the smallest width needed to represent the largest possible index in the list. | ||
|
||
* If multiple instances of the same extrema exists in the list, the index of the first instance will be returned. | ||
|
||
* `val` The value of the extrema. | ||
|
||
* `val` will be a `Logic` with a width equal to the largest width of any element in the list. | ||
|
||
The `List<Logic>` may contain `Logic`s of any width. They will all be considered positive unsigned numbers. | ||
|
||
`Extrema` will throw an exception if the `Logic` list is empty. | ||
|
||
## Example Usage | ||
|
||
Dart code: | ||
|
||
```dart | ||
void main() { | ||
// Example list of Logic signals. | ||
final signals = [ | ||
Logic(width: 8)..put(LogicValue.of([LogicValue.one, LogicValue.zero])), //0b10 | ||
Logic(width: 4)..put(LogicValue.ofInt(13, 4)), //0xD | ||
Logic()..put(LogicValue.one), //0b1 | ||
Logic(width: 8)..put(LogicValue.ofString('00001101')), // 0xD | ||
Logic(width: 4)..put(LogicValue.ofString('0001')), //0b1 | ||
]; | ||
// Create an Extrema module to find the minimum value. | ||
final findMin = Extrema(signals, max: false); | ||
await findMin.build(); | ||
// Create an Extrema module to find the first maximum value. | ||
final findMax = Extrema(signals); | ||
await findMax.build(); | ||
// Assign the integer representation of the value of the index to a variable. | ||
final x = findMax.index.value.toInt(); | ||
print('x equals findMax index: $x'); | ||
// print the index and value of the minimum as values | ||
print('findMin index as a value: ${findMin.index.value}'); | ||
print('findMin value as a value: ${findMin.val.value}'); | ||
// print the index and value of the maximum as values | ||
print('findMax index as a value: ${findMax.index.value}'); | ||
print('findMax val as a value: ${findMax.val.value}'); | ||
} | ||
``` | ||
|
||
Console output: | ||
|
||
```console | ||
x equals findMax index: 1 | ||
findMin index as a value: 3'h2 | ||
findMin value as a value: 8'h1 | ||
findMax index as a value: 3'h1 | ||
findMax val as a value: 8'hd | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright (C) 2024 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// config_extrema.dart | ||
// Configurator for extrema. | ||
// | ||
// 2024 September 16 | ||
// Author: Roberto Torres <[email protected]> | ||
// | ||
|
||
import 'dart:collection'; | ||
|
||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// A [Configurator] for [Extrema]. | ||
class ExtremaConfigurator extends Configurator { | ||
/// A knob controlling the number of logics to compare. | ||
final IntConfigKnob signalsKnob = IntConfigKnob(value: 4); | ||
|
||
/// A knob controlling the width of each element to sort. | ||
final IntConfigKnob logicWidthKnob = IntConfigKnob(value: 8); | ||
|
||
/// A knob controlling whether to find Max or Min. | ||
final ToggleConfigKnob maxKnob = ToggleConfigKnob(value: true); | ||
|
||
@override | ||
late final Map<String, ConfigKnob<dynamic>> knobs = UnmodifiableMapView({ | ||
'Length of list (number of elements)': signalsKnob, | ||
'Element width (for all elements)': logicWidthKnob, | ||
'Find maximum (uncheck for minimum)': maxKnob, | ||
}); | ||
|
||
@override | ||
Module createModule() { | ||
final signals = List.generate( | ||
signalsKnob.value, (index) => Logic(width: logicWidthKnob.value)); | ||
|
||
return Extrema( | ||
signals, | ||
max: maxKnob.value, | ||
); | ||
} | ||
|
||
@override | ||
final String name = 'Extrema'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright (C) 2024 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// extrema.dart | ||
// Implementation of finding extremas (max or min) of signals. | ||
// | ||
// 2024 September 16 | ||
// Author: Roberto Torres <[email protected]> | ||
// | ||
|
||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// Determines the extremas (maximum or minimum) of a List<[Logic]>. | ||
class Extrema extends Module { | ||
/// The [index] of the extrema. | ||
Logic get index => output('index'); | ||
|
||
/// The [val] of the extrema. | ||
Logic get val => output('val'); | ||
|
||
/// Finds an extrema of List<[Logic]> [signals]. Inputs need not be the same | ||
/// width, and will all be considered positive unsigned numbers. | ||
/// | ||
/// If [max] is `true`, will find maximum value, else will find minimum. | ||
/// | ||
/// Outputs the [index] and [val] of the extrema in the list of [signals]. | ||
Extrema(List<Logic> signals, {bool max = true}) { | ||
// List to consume inputs internally. | ||
final logics = <Logic>[]; | ||
|
||
// Adds input for every element in the signals list, to logics. | ||
for (var i = 0; i < signals.length; i++) { | ||
logics.add(addInput('signal$i', signals[i], width: signals[i].width)); | ||
} | ||
|
||
// Check if list is empty | ||
if (logics.isEmpty) { | ||
throw RohdHclException('List cannot be empty.'); | ||
} | ||
|
||
// Find the max width of all inputs. | ||
var maxWidth = 0; | ||
for (var i = 0; i < logics.length; i++) { | ||
if (logics[i].width > maxWidth) { | ||
maxWidth = logics[i].width; | ||
} | ||
} | ||
|
||
// Check max width and prepend with 0s. Will make all inputs same width. | ||
for (var i = 0; i < logics.length; i++) { | ||
if (logics[i].width < maxWidth) { | ||
logics[i] = logics[i].zeroExtend(maxWidth); | ||
} | ||
} | ||
|
||
// Find indexWidth, initialize extremaIndex and extremaVal. | ||
final indexWidth = log2Ceil(logics.length); | ||
Logic extremaIndex = Const(0, width: indexWidth); | ||
var extremaVal = logics[0]; | ||
|
||
// If max is true, find max value. Else, find min value. | ||
for (var i = 1; i < logics.length; i++) { | ||
final compareVal = | ||
max ? logics[i].gt(extremaVal) : logics[i].lt(extremaVal); | ||
extremaVal = Logic(name: 'muxOut$i', width: maxWidth) | ||
..gets(mux(compareVal, logics[i], extremaVal)); | ||
extremaIndex = mux(compareVal, Const(i, width: indexWidth), extremaIndex); | ||
} | ||
|
||
// Generate outputs here. | ||
addOutput('index', width: extremaIndex.width); | ||
index <= extremaIndex; | ||
|
||
addOutput('val', width: extremaVal.width); | ||
val <= extremaVal; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// Copyright (C) 2024 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// extrema_test.dart | ||
// Tests for extrema. | ||
// | ||
// 2024 September 16 | ||
// Author: Roberto Torres <[email protected]> | ||
// | ||
|
||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
void main() { | ||
tearDown(() async { | ||
await Simulator.reset(); | ||
}); | ||
test('Extrema of a list of Logics, all same width.', () async { | ||
// Create a list of Logic objects with different values. | ||
final logics = [ | ||
Logic(width: 8)..put(LogicValue.ofString('01101101')), // 109 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00010100')), // 20 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00000011')), // 3 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00001111')) // 15 in decimal | ||
]; | ||
|
||
// Create an instance of Extrema to use for finding first minimum. | ||
final findMin = Extrema(logics, max: false); | ||
await findMin.build(); | ||
|
||
// Create an instance of FindMax. | ||
final findMax = Extrema(logics); | ||
await findMax.build(); | ||
|
||
// Verify the min value and index | ||
expect(findMin.val.value.toInt(), equals(3)); | ||
expect(findMin.index.value.toInt(), equals(2)); | ||
|
||
// Verify the max value and index. | ||
expect(findMax.val.value.toInt(), equals(109)); | ||
expect(findMax.index.value.toInt(), equals(0)); | ||
}); | ||
|
||
test('Extrema of a list of Logics, different widths.', () async { | ||
// Create a list of Logic objects with different values. | ||
final logics = [ | ||
Logic(width: 8)..put(LogicValue.ofString('01101101')), // 109 in decimal | ||
Logic(width: 4)..put(LogicValue.ofString('0101')), // 5 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00010100')), // 20 in decimal | ||
Logic(width: 2)..put(LogicValue.ofString('11')), // 3 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00001111')) // 15 in decimal | ||
]; | ||
|
||
// Create an instance of FindMin. | ||
final findMin = Extrema(logics, max: false); | ||
await findMin.build(); | ||
|
||
// Create an instance of FindMax. | ||
final findMax = Extrema(logics); | ||
await findMax.build(); | ||
|
||
// Verify the min value and index | ||
expect(findMin.val.value.toInt(), equals(3)); | ||
expect(findMin.index.value.toInt(), equals(3)); | ||
|
||
// Verify the max value and index. | ||
expect(findMax.val.value.toInt(), equals(109)); | ||
expect(findMax.index.value.toInt(), equals(0)); | ||
}); | ||
|
||
test('List with same extrema including min in first and last.', () async { | ||
// Create a list of Logic objects with different values. | ||
final logics = [ | ||
Logic(width: 8)..put(LogicValue.ofString('00000011')), // 3 in decimal | ||
Logic(width: 4)..put(LogicValue.ofString('1101')), // 13 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00000100')), // 4 in decimal | ||
Logic(width: 2)..put(LogicValue.ofString('11')), // 3 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00001100')), // 12 in decimal | ||
Logic(width: 6)..put(LogicValue.ofString('001101')), // 13 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00000011')), // 3 in decimal | ||
]; | ||
|
||
// Create an instance of FindMin. | ||
final findMin = Extrema(logics, max: false); | ||
await findMin.build(); | ||
|
||
// Create an instance of FindMax. | ||
final findMax = Extrema(logics); | ||
await findMax.build(); | ||
|
||
// Verify the min value and index | ||
expect(findMin.val.value.toInt(), equals(3)); | ||
expect(findMin.index.value.toInt(), equals(0)); | ||
|
||
// Verify the max value and index. | ||
expect(findMax.val.value.toInt(), equals(13)); | ||
expect(findMax.index.value.toInt(), equals(1)); | ||
}); | ||
|
||
test('List with same extrema including max in first and last.', () async { | ||
// Create a list of Logic objects with different values. | ||
final logics = [ | ||
Logic(width: 8)..put(LogicValue.ofString('000001101')), // 13 in decimal | ||
Logic(width: 4)..put(LogicValue.ofString('1101')), // 13 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00000100')), // 4 in decimal | ||
Logic(width: 2)..put(LogicValue.ofString('11')), // 3 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('00001100')), // 12 in decimal | ||
Logic(width: 6)..put(LogicValue.ofString('000011')), // 3 in decimal | ||
Logic(width: 8)..put(LogicValue.ofString('000001101')), // 13 in decimal | ||
]; | ||
|
||
// Create an instance of FindMin. | ||
final findMin = Extrema(logics, max: false); | ||
await findMin.build(); | ||
|
||
// Create an instance of FindMax. | ||
final findMax = Extrema(logics); | ||
await findMax.build(); | ||
|
||
// Verify the min value and index | ||
expect(findMin.val.value.toInt(), equals(3)); | ||
expect(findMin.index.value.toInt(), equals(3)); | ||
|
||
// Verify the max value and index. | ||
expect(findMax.val.value.toInt(), equals(13)); | ||
expect(findMax.index.value.toInt(), equals(0)); | ||
}); | ||
|
||
test('List containing one element.', () async { | ||
// Create a list of Logic objects with different values | ||
final logics = [ | ||
Logic(width: 4)..put(LogicValue.ofString('1100')), // 12 in decimal | ||
]; | ||
|
||
// Create an instance of FindMin. | ||
final findMin = Extrema(logics, max: false); | ||
await findMin.build(); | ||
|
||
// Create an instance of FindMax | ||
final findMax = Extrema(logics); | ||
await findMax.build(); | ||
|
||
// Verify the minimum value and index | ||
expect(findMax.val.value.toInt(), equals(12)); | ||
expect(findMax.index.value.toInt(), equals(0)); | ||
}); | ||
|
||
test('Empty List.', () async { | ||
// Create a list of Logic objects with | ||
final logics = List<Logic>.empty(); | ||
|
||
// Try to create an instance of Extrema | ||
expect(() => Extrema(logics), throwsA(isA<RohdHclException>())); | ||
}); | ||
} |