-
Notifications
You must be signed in to change notification settings - Fork 24
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
Tree component #155
Open
desmonddak
wants to merge
25
commits into
intel:main
Choose a base branch
from
desmonddak:treeComponent
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Tree component #155
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
a283f76
general binary tree component and test
desmonddak b185b1d
documentation and an experimental LogicArray binary tree
desmonddak b9fdf61
working binary tree
desmonddak 30b9eb3
updated code documentation
desmonddak a0760ea
working reduction tree
desmonddak 57a7f76
refactored into an iterative function
desmonddak d73020b
preparted to merge iter into top class
desmonddak 1563fd8
merged ReductionTree module with internal recursion, documentation
desmonddak 343e45f
use floating_point.md from fpmult branch
desmonddak 7a10bfe
don't use WaveDumper in regressions
desmonddak 8593dcc
remove binary_tree as reduction_tree covers
desmonddak 8db0a58
reduction_tree in rohd_hcl, remove binary_tree
desmonddak e7a24f7
forgot to saveall in vscode -- rohd_hcl.dart fix
desmonddak 8fec4f9
Binary tree replaced bin reduction tree.
desmonddak fac01f3
better use of dart maps
desmonddak edac48f
use a record for capturing state
desmonddak a366b84
improve documentation with better examples
desmonddak 8c10cae
doc fix, more code neatening for clarity
desmonddak aadd721
doc cleanup
desmonddak 9d02b42
more doc cleanup
desmonddak 60a4f03
more documentation cleanup in code and markdown
desmonddak d5d32f6
added reduction_tree to README.md
desmonddak c43be66
Merge branch 'main' into treeComponent
desmonddak 7393863
doc fix
desmonddak 5a11f8a
dead link fix
desmonddak File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,53 @@ | ||
# Reduction Tree | ||
|
||
The `ReductionTree` component is a general tree generator that allows for arbitrary radix or tree-branching factor in the computation. It takes a sequence of `Logic` values and performs a specified operation at each node of the tree, taking in 'radix' inputs and producing one output. If the operation widens the output (say in addition), then the `ReductionTree` will widen values using either sign-extension or zero-extension as specified. | ||
|
||
The input sequence is provided in the form 'List\<Logic\>'. The operation must be provided in the form | ||
|
||
```dart | ||
Logic Function(List<Logic> operands) | ||
``` | ||
|
||
and support operand lengths between $[2,radix]$. | ||
|
||
The `ReductionTree` does not require the sequence length to be a power of the radix; it can be of arbitrary length. | ||
|
||
The resulting tree can be pipelined by specifying the depth of nodes before a pipestage is added. Since the input can be of arbitrary length, paths in the tree may not be balanced, and extra pipestages will be added in shorter sections of the tree to align the computation. | ||
|
||
Here is an example radix-4 computation tree using native addition on 79 13-bit inputs, pipelining every 2 operations deep, and producing a single 13-bit result. | ||
|
||
```dart | ||
Logic addReduce(List<Logic> inputs) { | ||
final a = inputs.reduce((v, e) => v + e); | ||
return a; | ||
} | ||
/// Tree reduction using addReduce | ||
const width = 13; | ||
const length = 79; | ||
final vec = <Logic>[]; | ||
|
||
final reductionTree = ReductionTree( | ||
vec, radix: 4, addReduce, clk: clk, depthToFlop; 2); | ||
``` | ||
|
||
Here is the same example radix-4 computation tree but using prefix adders on 79 13-bit inputs, pipelining every 2 operations deep, and producing a single 21-bit result, due to width-extension of the prefix adder, adding 1 bit for each addition in 7 levels of the tree. | ||
|
||
```dart | ||
Logic addReduceWithAdders(List<Logic> inputs) { | ||
if (inputs.length < 4) { | ||
return inputs.reduce((v, e) => v + e); | ||
} else { | ||
final add0 = ParallelPrefixAdder(inputs[0], inputs[1]); | ||
final add1 = ParallelPrefixAdder(inputs[2], inputs[3]); | ||
final add2 = ParallelPrefixAdder(add0.sum, add1.sum); | ||
return add2.sum; | ||
} | ||
|
||
/// Tree reduction using addReduceWithAdders | ||
const width = 13; | ||
const length = 79; | ||
final vec = <Logic>[]; | ||
|
||
final reductionTree = ReductionTree( | ||
vec, radix: 4, addReduceWithAdders, clk: clk, depthToFlop; 2, signExtend: true); | ||
``` |
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,144 @@ | ||
// Copyright (C) 2025 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// reduction_tree.dart | ||
// A generator for creating tree reduction computations. | ||
// | ||
// 2025 January 10 | ||
// Author: Desmond A Kirkpatrick <desmond.a.kirkpatrick@intel.com | ||
|
||
import 'dart:math'; | ||
|
||
import 'package:meta/meta.dart'; | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// A generator which constructs a tree of radix-input / 1-output modules. | ||
class ReductionTree extends Module { | ||
/// The radix-sized input operation to be performed at each node. | ||
@protected | ||
final Logic Function(List<Logic> inputs) operation; | ||
|
||
/// Specified width of input to each reduction node (e.g., binary: radix=2) | ||
@protected | ||
late final int radix; | ||
|
||
/// When [signExtend] is true, use sign-extension on values, | ||
/// otherwise use zero-extension. | ||
@protected | ||
late final bool signExtend; | ||
|
||
/// Specified depth of nodes at which to flop (requires [clk]). | ||
@protected | ||
late final int? depthToFlop; | ||
|
||
/// Optional [clk] input to create pipeline. | ||
@protected | ||
late final Logic? clk; | ||
|
||
/// Optional [reset] input to reset pipeline. | ||
@protected | ||
late final Logic? reset; | ||
|
||
/// Optional [enable] input to enable pipeline. | ||
@protected | ||
late final Logic? enable; | ||
|
||
/// The final output of the tree computation. | ||
Logic get out => output('out'); | ||
|
||
/// The combinational depth since the last flop. The total compute depth of | ||
/// the tree is: depth + flopDepth * depthToflop; | ||
int get depth => _computed.depth; | ||
|
||
/// The flop depth of the tree from the output to the leaves. | ||
int get flopDepth => _computed.flopDepth; | ||
|
||
/// Capture the record of compute: the final value, its depth (from last | ||
/// flop or input), and its flopDepth if pipelined. | ||
late final ({Logic value, int depth, int flopDepth}) _computed; | ||
|
||
/// Generate a tree based on dividing the input [sequence] of a node into | ||
/// segments, recursively constructing [radix] child nodes to operate | ||
/// on each segment. | ||
/// - [sequence] is the input sequence to be reduced using the tree of | ||
/// operations. | ||
/// - Logic Function(List<Logic> inputs) [operation] is the operation to be | ||
/// performed at each node. Note that [operation] can widen the output. The | ||
/// logic function must support the operation for 2 to radix inputs. | ||
/// - [radix] is the width of reduction at each node in the tree (e.g., | ||
/// binary: radix=2). | ||
/// - [signExtend] if true, use sign-extension to widen [Logic] values as | ||
/// needed in the tree, otherwise use zero-extension (default). | ||
/// | ||
/// Optional parameters to be used for creating a pipelined computation tree: | ||
/// - [clk], [reset], [enable] are optionally provided to allow for flopping. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is the |
||
/// - [depthToFlop] specifies how many nodes deep separate flops. | ||
ReductionTree(List<Logic> sequence, this.operation, | ||
{this.radix = 2, | ||
this.signExtend = false, | ||
this.depthToFlop, | ||
Logic? clk, | ||
Logic? enable, | ||
Logic? reset, | ||
super.name = 'reduction_tree'}) { | ||
if (sequence.isEmpty) { | ||
throw RohdHclException("Don't use ReductionTree " | ||
'with an empty sequence'); | ||
} | ||
sequence = [ | ||
for (var i = 0; i < sequence.length; i++) | ||
addInput('seq$i', sequence[i], width: sequence[i].width) | ||
]; | ||
this.clk = (clk != null) ? addInput('clk', clk) : null; | ||
this.enable = (enable != null) ? addInput('enable', enable) : null; | ||
this.reset = (reset != null) ? addInput('reset', reset) : null; | ||
|
||
_computed = reductionTreeRecurse(sequence); | ||
addOutput('out', width: _computed.value.width) <= _computed.value; | ||
} | ||
|
||
/// Local conditional flop using module reset/enable | ||
Logic localFlop(Logic d, {bool doFlop = false}) => | ||
condFlop(doFlop ? clk : null, reset: reset, en: enable, d); | ||
|
||
/// Recursively construct the computation tree | ||
({Logic value, int depth, int flopDepth}) reductionTreeRecurse( | ||
List<Logic> seq) { | ||
if (seq.length < radix) { | ||
return (value: operation(seq), depth: 0, flopDepth: 0); | ||
} else { | ||
final results = <({Logic value, int depth, int flopDepth})>[]; | ||
final segment = seq.length ~/ radix; | ||
var pos = 0; | ||
for (var i = 0; i < radix; i++) { | ||
final c = reductionTreeRecurse(seq | ||
.getRange(pos, (i < radix - 1) ? pos + segment : seq.length) | ||
.toList()); | ||
results.add(c); | ||
pos += segment; | ||
} | ||
final flopDepth = results.map((c) => c.flopDepth).reduce(max); | ||
final treeDepth = results.map((c) => c.depth).reduce(max); | ||
|
||
final alignedResults = results | ||
.map((c) => localFlop(c.value, doFlop: c.flopDepth < flopDepth)); | ||
|
||
final depthFlop = (depthToFlop != null) && | ||
(treeDepth > 0) & (treeDepth % depthToFlop! == 0); | ||
final resultsFlop = | ||
alignedResults.map((r) => localFlop(r, doFlop: depthFlop)); | ||
|
||
final alignWidth = results.map((c) => c.value.width).reduce(max); | ||
final resultsExtend = resultsFlop.map((r) => | ||
signExtend ? r.signExtend(alignWidth) : r.zeroExtend(alignWidth)); | ||
|
||
final computed = operation(resultsExtend.toList()); | ||
return ( | ||
value: computed, | ||
depth: depthFlop ? 0 : treeDepth + 1, | ||
flopDepth: flopDepth + (depthFlop ? 1 : 0) | ||
); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this equal to the latency in cycles?