Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

rohd-hcl: find #37

Merged
merged 22 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions doc/count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Count

ROHD HCL comes with a Count. The detailed API docs are available [here](https://intel.github.io/rohd-hcl/rohd_hcl/Count-class.html).

A Count will count all one(`1`)/zero(`0`) within a given Logic `bus`.

It takes a Binary Logic `bus` and counts all one or zero within the `bus`. A Count function without any constructor arguments will only count all Ones (`1`).
That is to say, By default a Count will go for counting with a `countOne` which is set as `true` by default.
The boolean `countOne` is optional. Only Logic `bus` is mandatory argument.

This will return a Logic value labeled as `countOne` for `1` and `countZero` for `0`. The value is a result of count of all occurrence parsed (with `countOne` as `1` or `0`) through the entire Logic `bus`.

## Count One

To count all ones just pass in the `bus` with `countOne` as `true`. by default countOne is `true`.

## Count Zero

To count all zeros just pass in the `bus` with `countOne` as `false`.
38 changes: 38 additions & 0 deletions doc/find.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Find

ROHD HCL comes with a Find. The detailed API docs are available [here](https://intel.github.io/rohd-hcl/rohd_hcl/Find-class.html).

A Find will search for first/nth occurrence of one(`1`)/zero(`0`) within a given Logic `bus`.
The underlying implementation uses a Count (see [`Count`](https://intel.github.io/rohd-hcl/rohd_hcl/Count-class.html)) to count 1's or 0's whenever a Logic `n` value
is passed within the constructor argument.

It takes a Binary Logic `bus` and finds the position of any one or zero within the `bus`. A Find function without any constructor arguments will find the first one.
That is to say, By default a Find will go for finding the first occurrence when no `n` is passed. In addition, with `countOne` which is set as `true` by default to
search only one (`1`). Both boolean `countOne` and Logic `n` are optional. Only Logic `bus` is mandatory argument.

This has an output pin named as `find`, for the index position on the occurrence searched (`1`s or `0`s) taken from the LSB (Least significant bit).

## Find First

To find the first occurrence just pass in the `bus` without mentioning any value for `n`.

### Find First One

To find the first occurrence just pass in `bus` without mentioning any value for `n`. In addition to finding first occurrence of One (`1`), set the argument `countOne` to `true`.
By default `countOne` is already set to `true`.

### Find First Zero

To find the first occurrence just pass in `bus` without mentioning any value for `n`. In addition to finding first occurrence of Zero (`0`), set the argument `countOne` to `false`.

## Find Nth

To find the nth occurrence just pass in `bus` along with Logic value `n` passed in as an argument.

### Find Nth One

To find the nth occurrence just pass in `bus` along with Logic value `n` passed in as an argument. In addition to finding occurrence of One (`1`), set the argument `countOne` to `true`.

### Find Nth Zero

To find the nth occurrence just pass in `bus` along with Logic value `n` passed in as an argument. In addition to finding occurrence of Zero (`0`), set the argument `countOne` to `false`.
2 changes: 2 additions & 0 deletions lib/rohd_hcl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
export 'src/adder.dart';
export 'src/arbiter.dart';
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
export 'src/carry_save_mutiplier.dart';
export 'src/count.dart';
export 'src/exceptions.dart';
export 'src/fifo.dart';
export 'src/find.dart';
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
export 'src/interfaces/interfaces.dart';
export 'src/memory/memories.dart';
export 'src/models/models.dart';
Expand Down
39 changes: 39 additions & 0 deletions lib/src/count.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// count.dart
// Implementation of Count Functionality.
//
// 2023 July 11
// Author: Rahul Gautham Putcha <[email protected]>
//

import 'dart:math';

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/src/utils.dart';

/// [Count] `1` or `0`
class Count extends Module {
/// [_output] is output of Count (use index for accessing from outside Module)
late Logic _output;

/// [index] is an getter for output of Count
Logic get index => _output;

/// [Count] `1` or `0`
///
/// Takes in [bus] of type [Logic]. by default performs [countOne] (`1`)
/// if [countOne] is `false` will count `0`
Count(Logic bus, {bool countOne = true}) {
bus = addInput('bus', bus, width: bus.width);
Logic count = Const(0, width: max(1, log2Ceil(bus.width) + 1));
for (var i = 0; i < bus.width; i++) {
count += (countOne ? bus[i] : ~bus[i]).zeroExtend(count.width);
}
_output =
addOutput('count${countOne ? "One" : "Zero"}', width: count.width);

_output <= count;
}
}
75 changes: 75 additions & 0 deletions lib/src/find.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// find.dart
// Implementation of Find Functionality.
//
// 2023 July 11
// Author: Rahul Gautham Putcha <[email protected]>
//

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';

/// Find functionality
///
/// Takes in a [Logic] to find location of `1`s or `0`s.
/// Outputs pin `index` contains position.
class Find extends Module {
/// [index] is an getter for output of Find
Logic get index => output('index');

/// [error] is an getter for error in Find
/// When your find is not found it will result in error `1`
Logic get error => output('error');

/// Find `1`s or `0`s
///
/// Takes in filter search parameter [countOne], default [Find] `1`.
/// If [countOne] is `true` [Find] `1` else [Find] `0`.
///
/// By default [Find] will look for first search parameter `1` or `0`.
/// If [n] is given, [Find] an [n]th search from first occurance.
/// [n] starts from `0` as first find.
///
/// Outputs pin `index` contains position. position starts from `1` based.
Find(Logic bus, {bool countOne = true, Logic? n}) {
bus = addInput('bus', bus, width: bus.width);
final oneHotList = <Logic>[];

if (n != null) {
n = addInput('n', n, width: n.width);
}

// 00000000 [0, 0]
for (var i = 0; i < bus.width; i++) {
// determines if it is what we are looking for?
final valCheck = countOne ? bus[i] : ~bus[i];

final count = Count(bus.getRange(0, i + 1), countOne: countOne);

// Below code will make `n` comparable to `count`
var paddedCountValue = count.index;
var paddedNValue = (n ?? Const(0)) + 1;

if (paddedNValue.width < paddedCountValue.width) {
paddedNValue = paddedNValue.zeroExtend(paddedCountValue.width);
} else {
paddedCountValue = paddedCountValue.zeroExtend(paddedNValue.width);
}

// If bus[i] contains search value (0/1) and it is nth position
// then append Logic `1` else append Logic `0`
oneHotList.add(valCheck & paddedNValue.eq(paddedCountValue));
}

final oneHotBinary = OneHotToBinary(oneHotList.rswizzle());
// Upon search complete, we get the position value in binary `bin` form
final bin = oneHotBinary.binary;
addOutput('index', width: bin.width);
index <= bin;

addOutput('error');
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
error <= oneHotBinary.error;
}
}
10 changes: 8 additions & 2 deletions lib/src/one_hot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,28 @@ class BinaryToOneHot extends Module {
class OneHotToBinary extends Module {
/// The [binary] decoded result.
Logic get binary => output('binary');
Logic get error => output('error');
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved

/// Constructs a [Module] which decodes a one-hot or thermometer-encoded
/// number [onehot] into a 2s complement number [binary] by encoding
/// the position of the '1'
OneHotToBinary(Logic onehot) {
onehot = addInput('onehot', onehot, width: onehot.width);
addOutput('binary', width: log2Ceil(onehot.width + 1));
addOutput('error');
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
Combinational([
Case(onehot, conditionalType: ConditionalType.unique, [
for (var i = 0; i < onehot.width; i++)
CaseItem(
Const(BigInt.from(1) << i, width: onehot.width),
[binary < Const(i, width: binary.width)],
[
binary < Const(i, width: binary.width),
error < 0,
],
)
], defaultItem: [
binary < Const(binary.width, width: binary.width)
binary < Const(0, width: binary.width),
error < 1,
])
]);
}
Expand Down
48 changes: 48 additions & 0 deletions test/count_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// count_test.dart
// Tests for Count
//
// 2023 June 8
// Author: Rahul Gautham Putcha <[email protected]>
//

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/src/count.dart';
import 'package:test/test.dart';

void main() {
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
test('count all 1s', () {
final bus = Const(bin('01101'), width: 5);
final mod = Count(bus);
expect(mod.index.value.toInt(), 3);
});

test('count all 1s when input is all 1s', () {
final bus = Const(bin('11111'), width: 5);
final mod = Count(bus);
expect(mod.index.value.toInt(), 5);
});
test('count all 1s when input is all 0s', () {
final bus = Const(bin('00000'), width: 5);
final mod = Count(bus);
expect(mod.index.value.toInt(), 0);
});

test('count all 0s', () {
final bus = Const(bin('001101'), width: 6);
final mod = Count(bus, countOne: false);
expect(mod.index.value.toInt(), 3);
});
test('count all 0s when input is all 1s', () {
final bus = Const(bin('11111'), width: 5);
final mod = Count(bus, countOne: false);
expect(mod.index.value.toInt(), 0);
});
test('count all 0s when input is all 0s', () {
final bus = Const(bin('00000'), width: 5);
final mod = Count(bus, countOne: false);
expect(mod.index.value.toInt(), 5);
});
}
117 changes: 117 additions & 0 deletions test/find_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// find_test.dart
// Tests for Find
//
// 2023 June 8
// Author: Rahul Gautham Putcha <[email protected]>
//

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_hcl/src/utils.dart';
import 'package:test/test.dart';

void main() {
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
group(
'find first one with n as null',
() => {
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
test('at 0th position', () {
final bus = Const(bin('11010101'), width: 8);
final mod = Find(bus);
expect(mod.index.value.toInt(), 0);
}),
test('at random position', () {
final bus = Const(bin('11111100'), width: 8);
final mod = Find(bus);
expect(mod.index.value.toInt(), 2);
}),
test('at last position', () {
final bus = Const(bin('10000000'), width: 8);
final mod = Find(bus);
expect(mod.index.value.toInt(), 7);
}),
test('when first one is not present', () {
final bus = Const(bin('00000000'), width: 8);
final mod = Find(bus);
// When your find is not found it will result in error
expect(mod.error.value.toInt(), 1);
}),
});

group(
'find first zero with n as null',
() => {
test('at 0th position', () {
final bus = Const(bin('11010100'), width: 8);
final mod = Find(bus, countOne: false);
expect(mod.index.value.toInt(), 0);
}),
test('at random position', () {
final bus = Const(bin('10101011'), width: 8);
final mod = Find(bus, countOne: false);
expect(mod.index.value.toInt(), 2);
}),
test('at last position', () {
final bus = Const(bin('01111111'), width: 8);
final mod = Find(bus, countOne: false);
expect(mod.index.value.toInt(), 7);
}),
test('when first zero is not present', () {
final bus = Const(bin('11111111'), width: 8);
final mod = Find(bus, countOne: false);
// When your find is not found it will result in error
expect(mod.error.value.toInt(), 1);
}),
});

group(
'find nth zero',
() => {
test('n is 0', () {
final bus = Const(bin('11010100'), width: 8);
final mod = Find(bus, countOne: false);
expect(mod.index.value.toInt(), 0);
}),
test('when n is 2 (find 3rd zero; n is zero index)', () {
final bus = Const(bin('10101011'), width: 8);
final mod = Find(bus,
countOne: false, n: Const(2, width: log2Ceil(8) + 1));
expect(mod.index.value.toInt(), 6);
}),
test('n is outside bound', () {
final bus = Const(bin('00000000'), width: 8);
final mod =
Find(bus, countOne: false, n: Const(10, width: log2Ceil(10)));
expect(mod.error.value.toInt(), 1);
}),
test('if all 0s', () {
final bus = Const(bin('00000000'), width: 8);
final mod =
Find(bus, countOne: false, n: Const(7, width: log2Ceil(8)));
expect(mod.index.value.toInt(), 0);
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
}),
test('if all 1s', () {}),
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
});

group(
'find nth one',
() => {
test('n is 0', () {
final bus = Const(bin('11010100'), width: 8);
final mod = Find(bus);
expect(mod.index.value.toInt(), 2);
}),
test('when n is 2 (find 3rd zero; n is zero index)', () {
final bus = Const(bin('10101011'), width: 8);
final mod = Find(bus, n: Const(2, width: log2Ceil(8)));
expect(mod.index.value.toInt(), 3);
}),
test('n is outside bound', () {
final bus = Const(bin('11111111'), width: 8);
final mod = Find(bus, n: Const(10, width: log2Ceil(10)));
expect(mod.error.value.toInt(), 1);
}),
});
}