Skip to content

Commit

Permalink
Ready/Valid BFM (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkorbel1 authored Jan 8, 2024
1 parent c3dfa9f commit 4de3cca
Show file tree
Hide file tree
Showing 14 changed files with 556 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ tmp*
*.vcd
.vscode/*
confapp/.vscode/*
*tracker.json
*tracker.log

# Exceptions
!.vscode/extensions.json
Expand Down
1 change: 1 addition & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Some in-development items will have opened issues, as well. Feel free to create
- HBM
- Models
- [APB](./components/apb_bfm.md)
- [Ready/Valid](./components/ready_valid_bfm.md)

----------------

Expand Down
4 changes: 2 additions & 2 deletions doc/components/apb_bfm.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ The APB BFM is a collection of [ROHD-VF](https://github.com/intel/rohd-vf) compo

The main two components are the `ApbRequesterAgent` and the `ApbCompleterAgent`, which behave like a "requester" and "completer" as described in the APB spec, respectively. The `ApbRequesterAgent` has a standard `Sequencer` that accepts `ApbPacket`s to be driven out to the completer. The `ApbCompleterAgent` has default behavior and accepts a `MemoryStorage` instance as a memory model. See the API docs for more details on how to use each of these components, which both have substantial configurability to control behavior.

A `ApbMonitor` is also included, which implements the standard `Monitor` and provides a stream of `ApbPacket`s monitored on positive edges of the clock. The `ApbTracker` can be used to log all items detected by the monitor by implementing the standard `Tracker` API (log file or JSON both supported).
An `ApbMonitor` is also included, which implements the standard `Monitor` and provides a stream of `ApbPacket`s monitored on positive edges of the clock. The `ApbTracker` can be used to log all items detected by the monitor by implementing the standard `Tracker` API (log file or JSON both supported).

Finally, a `ApbComplianceChecker` monitors an `ApbInterface` for a subset of the rules described in the APB specification. Errors are flagged using the `severe` log messages, as is standard for errors in ROHD-VF.

The unit tests in `apb_test.dart`, which have a completer and requester communicating with each other, are a good example for setting up the APB BFM.
The unit tests in `apb_bfm_test.dart`, which have a completer and requester communicating with each other, are a good example for setting up the APB BFM.

## Unsupported features

Expand Down
13 changes: 13 additions & 0 deletions doc/components/ready_valid_bfm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Ready/Valid BFM

The Ready/Valid BFM is a collection of [ROHD-VF](https://github.com/intel/rohd-vf) components and objects that are helpful for validating hardware that contains interfaces that use a ready/valid protocol. To summarize:

- When a transmitter has something to send, it raises `valid`.
- When a receiver is able to accept something, it raises `ready`.
- When both `valid` and `ready` are high, the transaction is accepted by both sides.

The main two components are the `ReadyValidTransmitterAgent` and `ReadyValidReceiverAgent`, which transmit and receive `data`, respectively. Any bundle of information can be mapped onto the `data` bus. Both agents provide a `blockRate` argument which controls a random weighted chance of preventing a transaction from occuring (either delaying a `valid` or dropping a `ready`).

Additionally, the `ReadyValidMonitor` can be placed on any ready/valid protocol to observe transactions that are accepted. The resulting `ReadyValidPacket`s can also be logged via the `ReadyValidTracker`.

The unit tests in `ready_valid_bfm_test.dart`, which have a transmitter and receiver agent talking to each other, can serve as a good example of how to use these components.
3 changes: 2 additions & 1 deletion lib/src/models/models.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (C) 2023 Intel Corporation
// Copyright (C) 2023-2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'apb_bfm/apb_bfm.dart';
export 'memory_model.dart';
export 'ready_valid_bfm/ready_valid_bfm.dart';
export 'sparse_memory_storage.dart';
40 changes: 40 additions & 0 deletions lib/src/models/ready_valid_bfm/ready_valid_agent.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// ready_valid_agent.dart
// A generic agent for ready/valid protocol.
//
// 2024 January 5
// Author: Max Korbel <[email protected]>

import 'package:rohd/rohd.dart';
import 'package:rohd_vf/rohd_vf.dart';

/// A generic agent for ready/valid protocol.
abstract class ReadyValidAgent extends Agent {
/// The clock.
final Logic clk;

/// Active-high reset.
final Logic reset;

/// Ready signal.
final Logic ready;

/// Valid signal.
final Logic valid;

/// Data being transmitted.
final Logic data;

/// Creates a new agent.
ReadyValidAgent({
required this.clk,
required this.reset,
required this.ready,
required this.valid,
required this.data,
required Component? parent,
String name = 'readyValidComponent',
}) : super(name, parent);
}
10 changes: 10 additions & 0 deletions lib/src/models/ready_valid_bfm/ready_valid_bfm.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'ready_valid_agent.dart';
export 'ready_valid_monitor.dart';
export 'ready_valid_packet.dart';
export 'ready_valid_receiver_agent.dart';
export 'ready_valid_tracker.dart';
export 'ready_valid_transmitter_agent.dart';
export 'ready_valid_transmitter_driver.dart';
60 changes: 60 additions & 0 deletions lib/src/models/ready_valid_bfm/ready_valid_monitor.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// ready_valid_monitor.dart
// A monitor for ready/valid protocol.
//
// 2024 January 5
// Author: Max Korbel <[email protected]>

import 'dart:async';

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_vf/rohd_vf.dart';

/// A [Monitor] for ready/valid protocol.
class ReadyValidMonitor extends Monitor<ReadyValidPacket> {
/// The clock.
final Logic clk;

/// Active-high reset.
final Logic reset;

/// Ready signal.
final Logic ready;

/// Valid signal.
final Logic valid;

/// Data being transmitted.
final Logic data;

/// Creates a new [ReadyValidMonitor].
ReadyValidMonitor({
required this.clk,
required this.reset,
required this.ready,
required this.valid,
required this.data,
required Component? parent,
String name = 'readyValidMonitor',
}) : super(name, parent);

@override
Future<void> run(Phase phase) async {
unawaited(super.run(phase));

await reset.nextNegedge;

clk.posedge.listen((event) {
if (!ready.previousValue!.isValid || !valid.previousValue!.isValid) {
logger.severe('Both ready and valid must be valid for protocol,'
' but found ready=${ready.value} and valid=${valid.value}');
} else if (ready.previousValue!.toBool() &&
valid.previousValue!.toBool()) {
add(ReadyValidPacket(data.previousValue!));
}
});
}
}
33 changes: 33 additions & 0 deletions lib/src/models/ready_valid_bfm/ready_valid_packet.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// ready_valid_packet.dart
// A monitor for ready/valid protocol.
//
// 2024 January 5
// Author: Max Korbel <[email protected]>

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_vf/rohd_vf.dart';

/// A packet to be transmitted over a ready/valid interface.
class ReadyValidPacket extends SequenceItem implements Trackable {
/// The data associated with this packet.
final LogicValue data;

/// Constructs a new packet with associated [data].
ReadyValidPacket(this.data);

@override
String? trackerString(TrackerField field) {
switch (field.title) {
case ReadyValidTracker.timeField:
return Simulator.time.toString();
case ReadyValidTracker.dataField:
return data.toString();
}

return null;
}
}
57 changes: 57 additions & 0 deletions lib/src/models/ready_valid_bfm/ready_valid_receiver_agent.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// ready_valid_receiver_agent.dart
// An agent for receiving over a ready/valid protocol.
//
// 2024 January 5
// Author: Max Korbel <[email protected]>

import 'dart:async';
import 'dart:math';

import 'package:rohd/rohd.dart';
import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_vf/rohd_vf.dart';

/// An [Agent] for receiving over a ready/valid protocol.
class ReadyValidReceiverAgent extends ReadyValidAgent {
/// Probability (from 0 to 1) of blocking a ready from being driven.
///
/// 0 -> never block, accept transactions as soon as possible.
final double blockRate;

/// Creates an [Agent] for receiving over a ready/valid protocol.
ReadyValidReceiverAgent({
required super.clk,
required super.reset,
required super.ready,
required super.valid,
required super.data,
required super.parent,
this.blockRate = 0,
super.name = 'readyValidReceiverAgent',
});

@override
Future<void> run(Phase phase) async {
unawaited(super.run(phase));

final random = Test.random ?? Random();

await _drive(LogicValue.zero);

await reset.nextNegedge;

while (!Simulator.simulationHasEnded) {
final doBlock = random.nextDouble() < blockRate;

await _drive(doBlock ? LogicValue.zero : LogicValue.one);
}
}

Future<void> _drive(LogicValue newReady) async {
ready.inject(newReady);
await clk.nextPosedge;
}
}
24 changes: 24 additions & 0 deletions lib/src/models/ready_valid_bfm/ready_valid_tracker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:rohd_hcl/src/models/models.dart';
import 'package:rohd_vf/rohd_vf.dart';

/// A tracker for a ready/valid protocol.
class ReadyValidTracker extends Tracker<ReadyValidPacket> {
/// Tracker field for simulation time.
static const timeField = 'time';

/// Tracker field for data.
static const dataField = 'data';

/// Creates a new tracker for a ready/valid protocol.
ReadyValidTracker({
String name = 'readyValidTracker',
super.dumpJson,
super.dumpTable,
super.outputFolder,
int timeColumnWidth = 12,
int dataColumnWidth = 14,
}) : super(name, [
TrackerField(timeField, columnWidth: timeColumnWidth),
TrackerField(dataField, columnWidth: dataColumnWidth),
]);
}
45 changes: 45 additions & 0 deletions lib/src/models/ready_valid_bfm/ready_valid_transmitter_agent.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// ready_valid_transmitter_agent.dart
// An agent for transmitting over a ready/valid protocol.
//
// 2024 January 5
// Author: Max Korbel <[email protected]>

import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_vf/rohd_vf.dart';

/// An [Agent] for transmitting over a ready/valid protocol.
class ReadyValidTransmitterAgent extends ReadyValidAgent {
/// The [Sequencer] to send [ReadyValidPacket]s into.
late final Sequencer<ReadyValidPacket> sequencer;

/// Creates an [Agent] for transmitting over a ready/valid protocol.
///
/// The [blockRate] is the probability (from 0 to 1) of blocking a valid from
/// being driven.
ReadyValidTransmitterAgent({
required super.clk,
required super.reset,
required super.ready,
required super.valid,
required super.data,
required super.parent,
double blockRate = 0,
super.name = 'readyValidTransmitterAgent',
}) {
sequencer = Sequencer<ReadyValidPacket>('sequencer', this);

ReadyValidTransmitterDriver(
clk: clk,
reset: reset,
ready: ready,
valid: valid,
data: data,
sequencer: sequencer,
blockRate: blockRate,
parent: this,
);
}
}
Loading

0 comments on commit 4de3cca

Please sign in to comment.