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

Sum and Counter #89

Merged
merged 46 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
8143165
initial implementation of counter, not fully tested yet
mkorbel1 Aug 26, 2024
91cd9d8
testing and bug fixes
mkorbel1 Aug 26, 2024
1eecfd4
extract aggregator
mkorbel1 Aug 27, 2024
502a6ba
minor updates, add restart
mkorbel1 Aug 27, 2024
c10fe20
rename some stuff
mkorbel1 Aug 27, 2024
3b668aa
refactor to sum, add reached ports
mkorbel1 Aug 27, 2024
b154097
add forgotten files
mkorbel1 Aug 27, 2024
558d99a
add ofLogics
mkorbel1 Aug 27, 2024
e0d895d
fix overflow bug, start sum testing
mkorbel1 Aug 27, 2024
bb13be8
fix intf bug
mkorbel1 Aug 27, 2024
870d4f5
fix bug in overflow wrap-around
mkorbel1 Aug 27, 2024
09048bc
refactor sum test
mkorbel1 Aug 27, 2024
29f0c1a
fixing up tests
mkorbel1 Aug 27, 2024
6cd33b6
fix init value bug
mkorbel1 Aug 28, 2024
ae13aac
fix off by one on underflow
mkorbel1 Aug 28, 2024
3533a9c
one rand test passing
mkorbel1 Aug 28, 2024
17fb84e
more testing
mkorbel1 Aug 28, 2024
5d49822
fixing bugs in golden model and design for sum
mkorbel1 Aug 28, 2024
de74777
fix some overflow/underflow bugs
mkorbel1 Aug 28, 2024
503708f
got random test passing 100 times
mkorbel1 Aug 28, 2024
bf1e89a
add eq max/min test
mkorbel1 Aug 28, 2024
cf82fe8
bug fixes on counter, more tests
mkorbel1 Aug 28, 2024
838e459
reorganizing
mkorbel1 Aug 28, 2024
57b9291
refactor counter stuff
mkorbel1 Aug 28, 2024
c308aae
fix bugs, adjust over/under flow
mkorbel1 Aug 28, 2024
882965a
more tests
mkorbel1 Sep 5, 2024
83fdef0
Merge branch 'main' of https://github.com/intel/rohd-hcl into counter
mkorbel1 Sep 5, 2024
a8a5547
refactor utilities to base class
mkorbel1 Sep 5, 2024
3cefdb7
improve width calculations in sum, improve docs
mkorbel1 Sep 5, 2024
9cc4dce
more documentation, more enable
mkorbel1 Sep 6, 2024
a702d77
more documentation improvements
mkorbel1 Sep 6, 2024
db7b90f
more tests
mkorbel1 Sep 6, 2024
392e5fb
add docs about summatino
mkorbel1 Sep 9, 2024
ae5c0c3
add links to docs
mkorbel1 Sep 9, 2024
aad96e0
starting on configurator for counter and sum
mkorbel1 Sep 9, 2024
c7fa3ac
Merge branch 'main' of https://github.com/intel/rohd-hcl into counter
mkorbel1 Sep 10, 2024
1e24518
add configurator for sum and counter
mkorbel1 Sep 10, 2024
ff5936d
add doc comments to configurators
mkorbel1 Sep 10, 2024
0229ff4
fix yosys generated json for schematic viewing
mkorbel1 Sep 10, 2024
56dd786
some minor cleanup from review
mkorbel1 Sep 11, 2024
d53d236
update comments
mkorbel1 Sep 11, 2024
e57f346
clean up TODOs, move to an issue
mkorbel1 Sep 11, 2024
2cca44e
fix lint
mkorbel1 Sep 11, 2024
6e9e79f
minor comment updates
mkorbel1 Sep 16, 2024
95c0716
Merge branch 'main' of https://github.com/intel/rohd-hcl into counter
mkorbel1 Sep 16, 2024
06fd2df
remove prints from divider test
mkorbel1 Sep 16, 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
4 changes: 2 additions & 2 deletions .github/workflows/general.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
uses: flutter-actions/setup-flutter@v2
with:
channel: stable
version: 3.16.3
version: 3.24.2

- name: Analyze flutter source
run: tool/gh_actions/analyze_flutter_source.sh
Expand Down Expand Up @@ -151,7 +151,7 @@ jobs:
uses: flutter-actions/setup-flutter@v2
with:
channel: stable
version: 3.16.3
version: 3.24.2

- name: Build static site
run: tool/gh_actions/hcl_site_generation_build.sh
Expand Down
15 changes: 4 additions & 11 deletions confapp/lib/hcl/view/screen/content_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ class _SVGeneratorState extends State<SVGenerator> {
);
final key = Key(label);

if (knob is IntConfigKnob || knob is StringConfigKnob) {
if (knob is TextConfigKnob) {
selector = TextFormField(
key: key,
initialValue: (knob is IntConfigKnob && knob.value > 255)
? '0x${knob.value.toRadixString(16)}'
: knob.value.toString(),
initialValue: knob.valueString,
decoration: decoration,
validator: (value) {
if (value!.isEmpty) {
if ((value == null || value.isEmpty) && !knob.allowEmpty) {
return 'Please enter value';
}
return null;
Expand All @@ -91,12 +89,7 @@ class _SVGeneratorState extends State<SVGenerator> {
return;
}

if (knob is IntConfigKnob) {
final newValue = int.tryParse(value.toString());
knob.value = newValue ?? knob.value;
} else {
knob.value = value;
}
knob.setValueFromString(value);
});
},
);
Expand Down
2 changes: 1 addition & 1 deletion confapp/lib/hcl/view/screen/schematic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const _suffix = r"""
svg.call(zoom)
.on("dblclick.zoom", null)

graph = JSON.parse(exmpl);
graph = JSON.parse(exmpl.replaceAll("\\", "__"));
if ("creator" in graph) {
graph = d3.HwSchematic.fromYosys(graph);
}
Expand Down
15 changes: 15 additions & 0 deletions confapp/web/flutter_bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{{flutter_js}}
{{flutter_build_config}}
_flutter.loader.load({
serviceWorkerSettings: {
serviceWorkerVersion: {{flutter_service_worker_version}},
},
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine().then(function(appRunner) {
appRunner.runApp();
});
},
config: {
canvasKitBaseUrl: 'canvaskit/',
}
});
20 changes: 1 addition & 19 deletions confapp/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,10 @@
<title>confapp</title>
<link rel="manifest" href="manifest.json">

<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer></script>
</head>
<body>
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine().then(function(appRunner) {
appRunner.runApp();
});
}
});
});
</script>
<script src="flutter_bootstrap.js" async></script>
</body>
</html>
3 changes: 2 additions & 1 deletion doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ Some in-development items will have opened issues, as well. Feel free to create
- Binary-Coded Decimal (BCD)
- [Rotate](./components/rotate.md)
- Counters
- Binary counter
- [Summation](./components/summation.md#sum)
- [Binary counter](./components/summation.md#counter)
- Gray counter
- Pseudorandom
- LFSR
Expand Down
40 changes: 40 additions & 0 deletions doc/components/summation.md
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Summation

ROHD-HCL comes with combinational and sequential components for summing any number of input values, including support for increment/decrement and saturation/roll-over behavior.

## SumInterface

The `SumInterface` is shared between [`Sum`](#sum) and [`Counter`](#counter) components and represents a single element to be summed. Each instance of a `SumInterface` has an associated `amount`, which could either be a fixed constant value (`fixedAmount`) or a dynamic `Logic`. Fixed amounts will do some automatic width inference, unless a `width` is specified. The interface can also optionally include an enable signal. It is implemented as a `PairInterface` where all ports are `fromProvider`. Each interface may be either incrementing or decrementing.

```dart
// An interface with a dynamic 4-bit amount to increment by
SumInterface(width: 4);
```

## Sum

The `Sum` component takes a list of `SumInterface`s and adds them all up. The `saturates` configuration enables saturation behavior, otherwise there will be roll-over at overflow/underflow of the counter at `minValue` and `maxValue`. The sum can also be given an `initialValue` to start at.

Internally, the `Sum` component builds a wider bus which is large enough to hold the biggest possible intermediate value during summation before consideration of overflow and saturation.

Note that the implementation's size and complexity when synthesized depend significantly on the configuration. For example, if everything is a nice power-of-2 number, then the logic is much simpler than otherwise where hardware modulos may be required to properly handle roll-over/under scenarios.

A simpler `Sum.ofLogics` constructor has less configurability, but can be passed a simple `List<Logic>` without needing to construct per-element interfaces.

```dart
// An 8-bit sum of a list of `SumInterface`s
Sum(intfs, width: 8);
```

## Counter

The `Counter` component is a similarly configurable version of the `Sum` which maintains a sequential element to store the previous value.

One additional nice feature of the `Counter` is that it supports a `restart` in addition to the normal `reset`. While `reset` will reset the internal flops, `restart` will re-initialize the internal `Sum` back to the reset value, but still perform the computation on inputs in the current cycle. This is especially useful in case you want to restart a counter while events worth counting may still be occuring.

The `Counter` also has a `Counter.simple` constructor which is intended for very basic scenarios like "count up by 1 each cycle".

```dart
// A counter which increments by 1 each cycle up to 5, then rolls over.
Counter.simple(clk: clk, reset: reset, maxValue: 5);
```
1 change: 1 addition & 0 deletions lib/rohd_hcl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ export 'src/models/models.dart';
export 'src/rotate.dart';
export 'src/shift_register.dart';
export 'src/sort.dart';
export 'src/summation/summation.dart';
export 'src/utils.dart';
2 changes: 2 additions & 0 deletions lib/src/component_config/components/component_registry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ List<Configurator> get componentRegistry => [
FifoConfigurator(),
EccConfigurator(),
RoundRobinArbiterConfigurator(),
CounterConfigurator(),
SumConfigurator(),
PriorityArbiterConfigurator(),
RippleCarryAdderConfigurator(),
CarrySaveMultiplierConfigurator(),
Expand Down
1 change: 1 addition & 0 deletions lib/src/component_config/components/components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export 'config_ripple_carry_adder.dart';
export 'config_rotate.dart';
export 'config_round_robin_arbiter.dart';
export 'config_sort.dart';
export 'config_summation.dart';
144 changes: 144 additions & 0 deletions lib/src/component_config/components/config_summation.dart
mkorbel1 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// config_summation.dart
// Configurators for summation.
//
// 2024 September 6
// Author: Max Korbel <[email protected]>

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_hcl/src/summation/summation_base.dart';

/// A knob for a single sum interface.
class SumInterfaceKnob extends GroupOfKnobs {
/// Whether the sum interface has an enable signal.
ToggleConfigKnob hasEnableKnob = ToggleConfigKnob(value: false);

/// Whether the sum interface has a fixed value.
ToggleConfigKnob isFixedValueKnob = ToggleConfigKnob(value: false);

/// The fixed value of the sum interface, only present when [isFixedValueKnob]
/// is true.
IntConfigKnob fixedValueKnob = IntConfigKnob(value: 1);

/// The width of the sum interface.
IntOptionalConfigKnob widthKnob = IntOptionalConfigKnob(value: 8);

/// Whether the sum interface increments (vs. decrements).
ToggleConfigKnob incrementsKnob = ToggleConfigKnob(value: true);

/// Creates a new sum interface knob.
SumInterfaceKnob() : super({}, name: 'Sum Interface');

@override
Map<String, ConfigKnob<dynamic>> get subKnobs => {
'Has Enable': hasEnableKnob,
'Is Fixed Value': isFixedValueKnob,
if (isFixedValueKnob.value) 'Fixed Value': fixedValueKnob,
'Width': widthKnob,
'Increments': incrementsKnob,
};
}

/// A configurator for a module like [SummationBase].
abstract class SummationConfigurator extends Configurator {
/// The interface knobs.
final ListOfKnobsKnob sumInterfaceKnobs = ListOfKnobsKnob(
count: 1,
generateKnob: (i) => SumInterfaceKnob(),
name: 'Sum Interfaces',
);

/// The width.
final IntOptionalConfigKnob widthKnob = IntOptionalConfigKnob(value: null);

/// The minimum value.
final IntOptionalConfigKnob minValueKnob = IntOptionalConfigKnob(value: 0);

/// The maximum value.
final IntOptionalConfigKnob maxValueKnob = IntOptionalConfigKnob(value: null);

/// Whether the output saturates (vs. rolling over/under).
final ToggleConfigKnob saturatesKnob = ToggleConfigKnob(value: false);

@override
Map<String, ConfigKnob<dynamic>> get knobs => {
'Sum Interfaces': sumInterfaceKnobs,
'Width': widthKnob,
'Minimum Value': minValueKnob,
'Maximum Value': maxValueKnob,
'Saturates': saturatesKnob,
};
}

/// A configurator for [Sum].
class SumConfigurator extends SummationConfigurator {
/// The initial value.
final IntConfigKnob initialValueKnob = IntConfigKnob(value: 0);

@override
Map<String, ConfigKnob<dynamic>> get knobs => {
...super.knobs,
'Initial Value': initialValueKnob,
};

@override
Module createModule() => Sum(
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(),
initialValue: initialValueKnob.value,
width: widthKnob.value,
minValue: minValueKnob.value,
maxValue: maxValueKnob.value,
saturates: saturatesKnob.value,
);

@override
String get name => 'Sum';
}

/// A configurator for [Counter].
class CounterConfigurator extends SummationConfigurator {
/// The reset value.
final IntConfigKnob resetValueKnob = IntConfigKnob(value: 0);

@override
Map<String, ConfigKnob<dynamic>> get knobs => {
...super.knobs,
'Reset Value': resetValueKnob,
};

@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(),
resetValue: resetValueKnob.value,
width: widthKnob.value,
minValue: minValueKnob.value,
maxValue: maxValueKnob.value,
saturates: saturatesKnob.value,
clk: Logic(),
reset: Logic(),
);

@override
String get name => 'Counter';
}
2 changes: 2 additions & 0 deletions lib/src/component_config/config_knobs/config_knobs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export 'choice_config_knob.dart';
export 'config_knob.dart';
export 'group_of_knobs_knob.dart';
export 'int_config_knob.dart';
export 'int_optional_config_knob.dart';
export 'list_of_knobs_knob.dart';
export 'string_config_knob.dart';
export 'text_config_knob.dart';
export 'toggle_config_knob.dart';
12 changes: 10 additions & 2 deletions lib/src/component_config/config_knobs/int_config_knob.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,29 @@
import 'package:rohd_hcl/rohd_hcl.dart';

/// A knob to store an [int].
class IntConfigKnob extends ConfigKnob<int> {
class IntConfigKnob extends TextConfigKnob<int> {
/// Creates a new config knob with the specified initial [value].
IntConfigKnob({required super.value});

@override
Map<String, dynamic> toJson() =>
{'value': value > 255 ? '0x${value.toRadixString(16)}' : value};

@override
String get valueString =>
value > 255 ? '0x${value.toRadixString(16)}' : value.toString();

@override
void loadJson(Map<String, dynamic> decodedJson) {
final val = decodedJson['value'];
if (val is String) {
value = int.parse(val);
setValueFromString(val);
} else {
value = val as int;
}
}

@override
void setValueFromString(String valueString) =>
value = int.tryParse(valueString) ?? value;
}
Loading
Loading