Skip to content

Commit

Permalink
Two implementations of rr arbiter, bug fix for grant reset, organize …
Browse files Browse the repository at this point in the history
…arbiters
  • Loading branch information
mkorbel1 committed Dec 16, 2023
1 parent e276335 commit 77935a3
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 197 deletions.
2 changes: 1 addition & 1 deletion lib/rohd_hcl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-3-Clause

export 'src/adder.dart';
export 'src/arbiter.dart';
export 'src/arbiters/arbiters.dart';
export 'src/carry_save_mutiplier.dart';
export 'src/component_config/component_config.dart';
export 'src/count.dart';
Expand Down
46 changes: 46 additions & 0 deletions lib/src/arbiters/arbiter.dart
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'));
}
}
}
6 changes: 6 additions & 0 deletions lib/src/arbiters/arbiters.dart
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';
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
Expand All @@ -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, [
Expand All @@ -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)
Expand All @@ -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(
Expand All @@ -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],
],
),
]);
Expand Down
23 changes: 23 additions & 0 deletions lib/src/arbiters/priority_arbiter.dart
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
]),
]);
}
}
31 changes: 31 additions & 0 deletions lib/src/arbiters/rotate_round_robin_arbiter.dart
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];
}
}
}
8 changes: 8 additions & 0 deletions lib/src/arbiters/round_robin_arbiter.dart
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);
}
16 changes: 16 additions & 0 deletions lib/src/arbiters/stateful_arbiter.dart
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);
}
}
Loading

0 comments on commit 77935a3

Please sign in to comment.