Skip to content

Commit

Permalink
Find and Count (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
RPG-coder-intc authored Oct 12, 2023
1 parent 1208cb4 commit 6b9313b
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 3 deletions.
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/rohd_hcl-library.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/rohd_hcl-library.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` 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';
export 'src/carry_save_mutiplier.dart';
export 'src/count.dart';
export 'src/exceptions.dart';
export 'src/fifo.dart';
export 'src/find.dart';
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;
}
}
81 changes: 81 additions & 0 deletions lib/src/find.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// 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');

/// If `true`, then the [error] output will be generated.
final bool generateError;

/// 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, this.generateError = false}) {
bus = addInput('bus', bus, width: bus.width);
final oneHotList = <Logic>[];

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

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(), generateError: true);
// Upon search complete, we get the position value in binary `bin` form
final bin = oneHotBinary.binary;
addOutput('index', width: bin.width);
index <= bin;

if (generateError) {
addOutput('error');
error <= oneHotBinary.error;
}
}
}
24 changes: 21 additions & 3 deletions lib/src/one_hot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,39 @@ class OneHotToBinary extends Module {
/// The [binary] decoded result.
Logic get binary => output('binary');

/// The [error] in getting result.
Logic get error => output('error');

/// If `true`, then the [error] output will be generated.
final bool generateError;

/// 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) {
OneHotToBinary(
Logic onehot, {
this.generateError = false,
}) {
onehot = addInput('onehot', onehot, width: onehot.width);
addOutput('binary', width: log2Ceil(onehot.width + 1));

if (generateError) {
addOutput('error');
}

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),
if (generateError) error < 0,
],
)
], defaultItem: [
binary < Const(binary.width, width: binary.width)
binary < Const(0, width: binary.width),
if (generateError) 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() {
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);
});
}
Loading

0 comments on commit 6b9313b

Please sign in to comment.