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

Gated counter and toggle gate #111

Merged
merged 57 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
689694b
Initial implementation of clock gating
mkorbel1 Sep 13, 2024
7721fbe
tiny tweaks
mkorbel1 Sep 16, 2024
f649e60
Merge branch 'main' of https://github.com/intel/rohd-hcl into clk_gate
mkorbel1 Sep 16, 2024
a0a2685
improve testing
mkorbel1 Sep 18, 2024
edce116
updating documentation on clock gating
mkorbel1 Sep 19, 2024
d9b138c
fixing tests, adding docs
mkorbel1 Sep 19, 2024
897f75a
Merge branch 'main' of https://github.com/intel/rohd-hcl into clk_gate
mkorbel1 Sep 19, 2024
4d384a2
fix tests
mkorbel1 Sep 19, 2024
254c26b
add docs for clock gating
mkorbel1 Sep 19, 2024
589f49a
fix formatting
mkorbel1 Sep 19, 2024
7c6d62d
Clean up clock gating, fix latched enable, improve doc and examples
mkorbel1 Sep 24, 2024
69b5eee
fix required reset
mkorbel1 Sep 25, 2024
8734217
initial work on gated counter
mkorbel1 Sep 26, 2024
db2ec9e
get test actually passing
mkorbel1 Sep 26, 2024
b1c99d1
support decrement driven enables on upper
mkorbel1 Sep 27, 2024
4b28e98
add overflow support
mkorbel1 Sep 27, 2024
bb73b9b
handle max
mkorbel1 Sep 27, 2024
fb94e8c
initial impl for underflow check
mkorbel1 Oct 1, 2024
2a087d2
refactoring sum testing for reuse
mkorbel1 Oct 1, 2024
909179d
initial randomized counter test working
mkorbel1 Oct 1, 2024
50f07ed
connect rest of cfg to counter and checker
mkorbel1 Oct 2, 2024
f28a3db
test both kinds of counters randomly
mkorbel1 Oct 2, 2024
5933e57
random tests run, but dont pass
mkorbel1 Oct 2, 2024
1d4db3b
basic gated counter gates somewhat reasonably
mkorbel1 Oct 2, 2024
80bbf1c
move clock gating inside the toggle gate
mkorbel1 Oct 2, 2024
0a0c96e
a couple random gated counters work
mkorbel1 Oct 2, 2024
bc52329
do a better job turning off clocks for saturation cases
mkorbel1 Oct 2, 2024
81c5175
upper bit incr only dont enable lower test
mkorbel1 Oct 2, 2024
f6a0205
disabling turns off whole counter
mkorbel1 Oct 2, 2024
20dbc41
fix consistency for random tests
mkorbel1 Oct 3, 2024
edad5ec
some range fixes
mkorbel1 Oct 3, 2024
21a3b24
fix unstable reset value case
mkorbel1 Oct 3, 2024
188a122
debugging errors
mkorbel1 Oct 14, 2024
c9be886
Merge branch 'main' of https://github.com/intel/rohd-hcl into gated_c…
mkorbel1 Oct 14, 2024
4966c74
down counter by 1 tests passing
mkorbel1 Oct 14, 2024
a842006
fix may underflow calculation
mkorbel1 Oct 14, 2024
b3180e4
fix underflow issues
mkorbel1 Oct 14, 2024
5f7f62f
handle big increments
mkorbel1 Oct 14, 2024
e703abc
fix another incr ungating issue
mkorbel1 Oct 15, 2024
0339bcf
fix some underflow issues
mkorbel1 Oct 15, 2024
7f97a94
fix overflow issue
mkorbel1 Oct 15, 2024
3bd1838
fix overly ambitious incr guard
mkorbel1 Oct 15, 2024
e77b338
fix over enthusiastic gating
mkorbel1 Oct 15, 2024
fd68e99
fix decr danger bug
mkorbel1 Oct 15, 2024
f8d5047
variable amount gating on bigger counter testing
mkorbel1 Oct 18, 2024
0e9675b
toggle gate test
mkorbel1 Oct 18, 2024
6d273e1
toggle gate tests done
mkorbel1 Oct 18, 2024
dcceff8
test with multiple intfs
mkorbel1 Oct 18, 2024
14596e6
cleanup
mkorbel1 Oct 18, 2024
40268a0
test with clock gating disabled
mkorbel1 Oct 18, 2024
c044dc6
doc updates
mkorbel1 Oct 21, 2024
d6bd34d
add test for all gated together
mkorbel1 Oct 22, 2024
b44fc61
Merge branch 'main' of https://github.com/intel/rohd-hcl into gated_c…
mkorbel1 Oct 22, 2024
2825a73
more docs updates
mkorbel1 Oct 22, 2024
308dac5
added test for gated counter configurator
mkorbel1 Oct 22, 2024
4567c21
Merge branch 'main' of https://github.com/intel/rohd-hcl into gated_c…
mkorbel1 Nov 1, 2024
2879e59
fix header
mkorbel1 Nov 1, 2024
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
3 changes: 3 additions & 0 deletions .github/workflows/general.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ jobs:

- name: Generate HTML for examples
run: tool/gh_actions/create_htmls.sh

- name: Check temporary test files
run: tool/gh_actions/check_tmp_test.sh

# https://github.com/devcontainers/ci/blob/main/docs/github-action.md
- name: Build dev container and run tests in it
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tmp*
confapp/.vscode/*
*tracker.json
*tracker.log
devtools_options.yaml
*.sv

# Exceptions
Expand Down
4 changes: 3 additions & 1 deletion doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Some in-development items will have opened issues, as well. Feel free to create
- Counters
- [Summation](./components/summation.md#sum)
- [Binary counter](./components/summation.md#counter)
- [Gated counter](./components/summation.md#gated-counter)
- Gray counter
- Pseudorandom
- LFSR
Expand All @@ -73,8 +74,9 @@ Some in-development items will have opened issues, as well. Feel free to create
- CRC
- [Parity](./components/parity.md)
- Interleaving
- Clocking
- Gating
- [Clock gating](./components/clock_gating.md)
- [Toggle gating](./components/toggle_gate.md)
- Data flow
- Ready/Valid
- Connect/Disconnect
Expand Down
8 changes: 8 additions & 0 deletions doc/components/summation.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@ The `Counter` also has a `Counter.simple` constructor which is intended for very
// A counter which increments by 1 each cycle up to 5, then rolls over.
Counter.simple(clk: clk, reset: reset, maxValue: 5);
```

## Gated Counter

The `GatedCounter` is a version of a `Counter` which contains a number of power-saving features including clock gating to save on flop power and enable gating to avoid unnecessary combinational toggles.

The `GatedCounter` has a `clkGatePartitionIndex` which determines a dividing line for the counter to be clock gated such that flops at or above that index will be independently clock gated from the flops below that index. This is an effective method of saving extra power on many counters because the upper bits of the counter may change much less frequently than the lower bits (or vice versa). If the index is negative or greater than or equal to the width of the counter, then the whole counter will be clock gated in unison.
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved

The `gateToggles` flag will enable `ToggleGate` insertion on a per-interface basis to help reduce combinational toggles within the design when interfaces are not enabled.
16 changes: 16 additions & 0 deletions doc/components/toggle_gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Toggle Gate

The `ToggleGate` component is intended to help save power by avoiding unnecessary toggles through combinational logic. It accomplishes this by flopping the previous value of data and muxing the previous value to the `gatedData` output if the `enable` is low. By default, the flops within the `ToggleGate` are also clock gated for extra power savings, but it can be controlled via a `ClockGateControlInterface`.

As an example use case, if you have a large arithmetic unit but only care about the result when a `valid` bit is high, you could use a `ToggleGate` so that the inputs to that combinational logic do not change unless `valid` is high.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be an interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you elaborate? what do you mean?

```dart
final toggleGate = ToggleGate(
clk: clk,
reset: reset,
enable: arithmeticDataValid,
data: arithmeticData,
);

BigArithmeticUnit(dataIn: toggleGate.gatedData);
```
1 change: 1 addition & 0 deletions lib/rohd_hcl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export 'src/serialization/serialization.dart';
export 'src/shift_register.dart';
export 'src/sort.dart';
export 'src/summation/summation.dart';
export 'src/toggle_gate.dart';
export 'src/utils.dart';
56 changes: 45 additions & 11 deletions lib/src/component_config/components/config_summation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,24 +112,56 @@ class CounterConfigurator extends SummationConfigurator {
/// The reset value.
final IntConfigKnob resetValueKnob = IntConfigKnob(value: 0);

/// Whether to instantiate a [GatedCounter].
final ToggleConfigKnob clockGatingKnob = ToggleConfigKnob(value: false);

/// The clock gating partition index.
final IntOptionalConfigKnob clockGatingPartitionIndexKnob =
IntOptionalConfigKnob(value: null);

/// The gate toggles knob.
final ToggleConfigKnob gateTogglesKnob = ToggleConfigKnob(value: false);

@override
Map<String, ConfigKnob<dynamic>> get knobs => {
...super.knobs,
'Reset Value': resetValueKnob,
'Clock Gating': clockGatingKnob,
if (clockGatingKnob.value) ...{
'Clock Gating Partition Index': clockGatingPartitionIndexKnob,
'Gate Toggles': gateTogglesKnob,
},
};

@override
Module createModule() => Counter(
sumInterfaceKnobs.knobs
.map((e) => e as SumInterfaceKnob)
.map((e) => SumInterface(
hasEnable: e.hasEnableKnob.value,
fixedAmount:
e.isFixedValueKnob.value ? e.fixedValueKnob.value : null,
width: e.widthKnob.value,
increments: e.incrementsKnob.value,
))
.toList(),
Module createModule() {
final sumIntfs = sumInterfaceKnobs.knobs
.map((e) => e as SumInterfaceKnob)
.map((e) => SumInterface(
hasEnable: e.hasEnableKnob.value,
fixedAmount:
e.isFixedValueKnob.value ? e.fixedValueKnob.value : null,
width: e.widthKnob.value,
increments: e.incrementsKnob.value,
))
.toList();

if (clockGatingKnob.value) {
return GatedCounter(
sumIntfs,
resetValue: resetValueKnob.value,
width: widthKnob.value,
minValue: minValueKnob.value,
maxValue: maxValueKnob.value,
saturates: saturatesKnob.value,
clk: Logic(),
reset: Logic(),
clkGatePartitionIndex: clockGatingPartitionIndexKnob.value,
gateToggles: gateTogglesKnob.value,
);
} else {
return Counter(
sumIntfs,
resetValue: resetValueKnob.value,
width: widthKnob.value,
minValue: minValueKnob.value,
Expand All @@ -138,6 +170,8 @@ class CounterConfigurator extends SummationConfigurator {
clk: Logic(),
reset: Logic(),
);
}
}

@override
String get name => 'Counter';
Expand Down
69 changes: 49 additions & 20 deletions lib/src/summation/counter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// 2024 August 26
// Author: Max Korbel <[email protected]>

import 'package:meta/meta.dart';
import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_hcl/src/summation/summation_base.dart';
Expand All @@ -17,6 +18,19 @@ class Counter extends SummationBase {
/// The output value of the counter.
Logic get count => output('count');

/// The main clock signal.
@visibleForTesting
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
@protected
late final Logic clk;

/// The reset signal.
@protected
late final Logic reset;

/// The restart signal.
@protected
late final Logic? restart;

/// Creates a counter that increments according to the provided [interfaces].
///
/// The [width] can be either explicitly provided or inferred from other
Expand Down Expand Up @@ -50,39 +64,54 @@ class Counter extends SummationBase {
super.saturates,
super.name = 'counter',
}) : super(initialValue: resetValue) {
clk = addInput('clk', clk);
reset = addInput('reset', reset);
this.clk = addInput('clk', clk);
this.reset = addInput('reset', reset);

if (restart != null) {
restart = addInput('restart', restart);
this.restart = addInput('restart', restart);
} else {
this.restart = null;
}

addOutput('count', width: width);

final sum = Sum(
interfaces,
initialValue:
restart != null ? mux(restart, initialValueLogic, count) : count,
maxValue: maxValueLogic,
minValue: minValueLogic,
width: width,
saturates: saturates,
);
_buildLogic();
}

/// The internal [Sum] that is used to keep track of the count.
@protected
late final Sum summer = Sum(
interfaces,
initialValue:
restart != null ? mux(restart!, initialValueLogic, count) : count,
maxValue: maxValueLogic,
minValue: minValueLogic,
width: width,
saturates: saturates,
);

/// Builds the internal logic for the counter.
void _buildLogic() {
buildFlops();

// need to flop these since value is flopped
overflowed <= flop(clk, summer.overflowed, reset: reset);
underflowed <= flop(clk, summer.underflowed, reset: reset);

equalsMax <= count.eq(maxValueLogic);
equalsMin <= count.eq(minValueLogic);
}

/// Builds the flops that store the [count].
@protected
void buildFlops() {
count <=
flop(
clk,
sum.sum,
summer.sum,
reset: reset,
resetValue: initialValueLogic,
);

// need to flop these since value is flopped
overflowed <= flop(clk, sum.overflowed, reset: reset);
underflowed <= flop(clk, sum.underflowed, reset: reset);

equalsMax <= count.eq(maxValueLogic);
equalsMin <= count.eq(minValueLogic);
}

/// A simplified constructor for [Counter] that accepts a single fixed amount
Expand Down
Loading
Loading