-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Two implementations of rr arbiter, bug fix for grant reset, organize …
…arbiters
- Loading branch information
Showing
9 changed files
with
321 additions
and
197 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright (C) 2023 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// arbiter.dart | ||
// Implementation of arbiters. | ||
// | ||
// 2023 March 13 | ||
// Author: Max Korbel <[email protected]> | ||
|
||
import 'dart:collection'; | ||
import 'package:meta/meta.dart'; | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/src/exceptions.dart'; | ||
|
||
/// An abstract description of an arbiter module. | ||
abstract class Arbiter extends Module { | ||
/// Each element corresponds to an arbitration grant of the correspondingly | ||
/// indexed request passed at construction time. | ||
late final List<Logic> grants = UnmodifiableListView(_grants); | ||
final List<Logic> _grants = []; | ||
|
||
/// Each element is the [input] pin for the correspondingly indexed request. | ||
/// | ||
/// To be used internally to the arbiter only, since this contains the | ||
/// [inputs] of the [Module]. | ||
@protected | ||
late final List<Logic> requests = UnmodifiableListView(_requests); | ||
final List<Logic> _requests = []; | ||
|
||
/// The total number of requests and grants for this [Arbiter]. | ||
late final int count = _requests.length; | ||
|
||
/// Constructs an arbiter where each element in [requests] is a one-bit signal | ||
/// requesting a corresponding bit from [grants]. | ||
Arbiter(List<Logic> requests, {super.name = 'arbiter'}) { | ||
for (var i = 0; i < requests.length; i++) { | ||
if (requests[i].width != 1) { | ||
throw RohdHclException('Each request must be 1 bit,' | ||
' but found ${requests[i]} at index $i.'); | ||
} | ||
|
||
_requests.add(addInput('request_$i', requests[i])); | ||
_grants.add(addOutput('grant_$i')); | ||
} | ||
} | ||
} |
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,6 @@ | ||
export 'arbiter.dart'; | ||
export 'mask_round_robin_arbiter.dart'; | ||
export 'priority_arbiter.dart'; | ||
export 'rotate_round_robin_arbiter.dart'; | ||
export 'round_robin_arbiter.dart'; | ||
export 'stateful_arbiter.dart'; |
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 |
---|---|---|
@@ -1,72 +1,14 @@ | ||
// Copyright (C) 2023 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// arbiter.dart | ||
// Implementation of arbiters. | ||
// | ||
// 2023 March 13 | ||
// Author: Max Korbel <[email protected]> | ||
|
||
import 'dart:collection'; | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/src/exceptions.dart'; | ||
|
||
/// An abstract description of an arbiter module. | ||
abstract class Arbiter extends Module { | ||
/// Each element corresponds to an arbitration grant of the correspondingly | ||
/// indexed request passed at construction time. | ||
List<Logic> get grants => UnmodifiableListView(_grants); | ||
|
||
final List<Logic> _grants = []; | ||
|
||
final List<Logic> _requests = []; | ||
|
||
/// The total number of requests and grants for this [Arbiter]. | ||
int get count => _requests.length; | ||
|
||
/// Constructs an arbiter where each element in [requests] is a one-bit signal | ||
/// requesting a corresponding bit from [grants]. | ||
Arbiter(List<Logic> requests, {super.name = 'arbiter'}) { | ||
for (var i = 0; i < requests.length; i++) { | ||
if (requests[i].width != 1) { | ||
throw RohdHclException('Each request must be 1 bit,' | ||
' but found ${requests[i]} at index $i.'); | ||
} | ||
|
||
_requests.add(addInput('request_$i', requests[i])); | ||
_grants.add(addOutput('grant_$i')); | ||
} | ||
} | ||
} | ||
|
||
/// An [Arbiter] which always picks the lowest-indexed request. | ||
class PriorityArbiter extends Arbiter { | ||
/// Constructs an arbiter where the grant is given to the lowest-indexed | ||
/// request. | ||
PriorityArbiter(super.requests, {super.name = 'priority_arbiter'}) { | ||
Combinational([ | ||
CaseZ(_requests.rswizzle(), conditionalType: ConditionalType.priority, [ | ||
for (var i = 0; i < count; i++) | ||
CaseItem( | ||
Const( | ||
LogicValue.filled(count, LogicValue.z).withSet(i, LogicValue.one), | ||
), | ||
[for (var g = 0; g < count; g++) _grants[g] < (i == g ? 1 : 0)], | ||
) | ||
], defaultItem: [ | ||
for (var g = 0; g < count; g++) _grants[g] < 0 | ||
]), | ||
]); | ||
} | ||
} | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// Round Robin Arbiter. | ||
class RoundRobinArbiter extends Arbiter { | ||
class MaskRoundRobinArbiter extends StatefulArbiter | ||
implements RoundRobinArbiter { | ||
/// Mask to define pending requests to be attended | ||
/// the main idea is to mask the requests as they are granted to ensure all | ||
/// requests are granted once before resetting the mask | ||
/// example: | ||
/// [clk] [_requests] [_requestMask] [_grantMask] [_grants] | ||
/// [clk] [_requests] [_requestMask] [_grantMask] [grants] | ||
/// 0 00100010 & 11111111 = 00100010 -> 00000010 | ||
/// 1 00100010 & 11111100 = 00100000 -> 00100000 | ||
/// 2 10000001 & 11000000 = 10000000 -> 10000000 | ||
|
@@ -76,17 +18,15 @@ class RoundRobinArbiter extends Arbiter { | |
/// handle the missing requests before resetting | ||
List<Logic> _requestMask = []; | ||
|
||
/// Result of masking [_requests] with [_requestMask] | ||
/// Contains bits of [_requests] but as bits are granted, will turn off | ||
/// Result of masking [requests] with [_requestMask] | ||
/// Contains bits of [requests] but as bits are granted, will turn off | ||
List<Logic> _grantMask = []; | ||
|
||
/// Round Robin arbiter handles requests by granting each requestor | ||
/// and keeping record of requests already granted, in order to mask it until | ||
/// granting the turn of each request to start again | ||
RoundRobinArbiter(super.requests, | ||
{required Logic clk, required Logic reset}) { | ||
clk = addInput('clk', clk); | ||
reset = addInput('reset', reset); | ||
MaskRoundRobinArbiter(super.requests, | ||
{required super.clk, required super.reset}) { | ||
_requestMask = List.generate(count, (i) => Logic(name: 'requestMask$i')); | ||
_grantMask = List.generate(count, (i) => Logic(name: 'grantMask$i')); | ||
Sequential(clk, [ | ||
|
@@ -99,7 +39,7 @@ class RoundRobinArbiter extends Arbiter { | |
// Example: | ||
// [_grants] [requestMask] | ||
// 00001000 11110000 | ||
Case(_grants.rswizzle(), conditionalType: ConditionalType.unique, [ | ||
Case(grants.rswizzle(), conditionalType: ConditionalType.unique, [ | ||
for (var i = 0; i < count; i++) | ||
CaseItem( | ||
Const(LogicValue.filled(count, LogicValue.zero) | ||
|
@@ -110,13 +50,15 @@ class RoundRobinArbiter extends Arbiter { | |
]) | ||
// In case [_grants] are all 0s, requestMask gets a reset | ||
], defaultItem: [ | ||
for (var g = 0; g < count; g++) _requestMask[g] < 1, | ||
// leave request mask as-is if there was no grant | ||
//TODO: bug, shouldn't reset masks if no grants! | ||
// for (var g = 0; g < count; g++) _requestMask[g] < 1, | ||
]) | ||
]) | ||
]); | ||
Combinational([ | ||
for (var g = 0; g < count; g++) | ||
_grantMask[g] < _requestMask[g] & _requests[g], | ||
_grantMask[g] < _requestMask[g] & requests[g], | ||
// CaseZ uses [_grantMask] to set the [_grants] based on the | ||
// least significant bit | ||
CaseZ( | ||
|
@@ -127,16 +69,15 @@ class RoundRobinArbiter extends Arbiter { | |
Const(LogicValue.filled(count, LogicValue.z) | ||
.withSet(i, LogicValue.one)), | ||
[ | ||
for (var g = 0; g < count; g++) _grants[g] < (i == g ? 1 : 0), | ||
for (var g = 0; g < count; g++) grants[g] < (i == g ? 1 : 0), | ||
]), | ||
], | ||
// When all bits have been granted, [_grantMask] turns all to 0s because | ||
// of the [_requestMask], therefore logic to define next [_grants] | ||
// relies on [_request] least significant bit | ||
defaultItem: [ | ||
for (var g = 0; g < count; g++) | ||
_grants[g] < | ||
~_requests.rswizzle().getRange(0, g).or() & _requests[g], | ||
grants[g] < ~requests.rswizzle().getRange(0, g).or() & requests[g], | ||
], | ||
), | ||
]); | ||
|
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,23 @@ | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// An [Arbiter] which always picks the lowest-indexed request. | ||
class PriorityArbiter extends Arbiter { | ||
/// Constructs an arbiter where the grant is given to the lowest-indexed | ||
/// request. | ||
PriorityArbiter(super.requests, {super.name = 'priority_arbiter'}) { | ||
Combinational([ | ||
CaseZ(requests.rswizzle(), conditionalType: ConditionalType.priority, [ | ||
for (var i = 0; i < count; i++) | ||
CaseItem( | ||
Const( | ||
LogicValue.filled(count, LogicValue.z).withSet(i, LogicValue.one), | ||
), | ||
[for (var g = 0; g < count; g++) grants[g] < (i == g ? 1 : 0)], | ||
) | ||
], defaultItem: [ | ||
for (var g = 0; g < count; g++) grants[g] < 0 | ||
]), | ||
]); | ||
} | ||
} |
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,31 @@ | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// A round-robin arbiter. | ||
class RotateRoundRobinArbiter extends StatefulArbiter | ||
implements RoundRobinArbiter { | ||
/// Creates an [Arbiter] that fairly takes turns between [requests]. | ||
RotateRoundRobinArbiter(super.requests, | ||
{required super.clk, required super.reset}) { | ||
final preference = Logic(name: 'preference', width: log2Ceil(count)); | ||
|
||
final rotatedReqs = requests | ||
.rswizzle() | ||
.rotateRight(preference, maxAmount: count - 1) | ||
.elements; | ||
final priorityArb = PriorityArbiter(rotatedReqs); | ||
final unRotatedGrants = priorityArb.grants | ||
.rswizzle() | ||
.rotateLeft(preference, maxAmount: count - 1); | ||
|
||
Sequential(clk, reset: reset, [ | ||
If(unRotatedGrants.or(), then: [ | ||
preference < TreeOneHotToBinary(unRotatedGrants).binary + 1, | ||
]), | ||
]); | ||
|
||
for (var i = 0; i < count; i++) { | ||
grants[i] <= unRotatedGrants[i]; | ||
} | ||
} | ||
} |
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,8 @@ | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
abstract class RoundRobinArbiter extends StatefulArbiter { | ||
factory RoundRobinArbiter(List<Logic> requests, | ||
{required Logic clk, required Logic reset}) => | ||
MaskRoundRobinArbiter(requests, clk: clk, reset: reset); | ||
} |
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,16 @@ | ||
import 'package:meta/meta.dart'; | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
abstract class StatefulArbiter extends Arbiter { | ||
@protected | ||
late final Logic clk = input('clk'); | ||
|
||
@protected | ||
late final Logic reset = input('reset'); | ||
|
||
StatefulArbiter(super.requests, {required Logic clk, required Logic reset}) { | ||
addInput('clk', clk); | ||
addInput('reset', reset); | ||
} | ||
} |
Oops, something went wrong.