-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,087 additions
and
34 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
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,20 @@ | ||
# APB BFM | ||
|
||
The APB BFM is a collection of [ROHD-VF](https://github.com/intel/rohd-vf) components and objects that are helpful for validating hardware that contains an APB interface. It includes all the basic APB interface features for sending and responding to reads and writes, including with strobes and errors. | ||
|
||
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). | ||
|
||
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. | ||
|
||
## Unsupported features | ||
|
||
The following features are not supported by or have no utilities within the BFM: | ||
|
||
- **Wake-up signalling**: wake-up features are not considered. | ||
- **Protection**: protection features are not considered. | ||
- **User requests and responses**: these signals are un-driven and not monitored by the BFM. | ||
- **Retry on error**: it is up to the user of the BFM to write any error handling logic. |
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,168 @@ | ||
// Copyright (C) 2023 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// apb_completer.dart | ||
// An agent for completing APB requests. | ||
// | ||
// 2023 June 12 | ||
// Author: Max Korbel <max.korbel@intel.com> | ||
|
||
import 'dart:async'; | ||
|
||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
import 'package:rohd_vf/rohd_vf.dart'; | ||
|
||
/// A model for the completer side of an [ApbInterface]. | ||
class ApbCompleterAgent extends Agent { | ||
/// The interface to drive. | ||
final ApbInterface intf; | ||
|
||
/// The index that this is listening to on the [intf]. | ||
final int selectIndex; | ||
|
||
/// A place where the completer should save and retrieve data. | ||
/// | ||
/// The [ApbCompleterAgent] will reset [storage] whenever the `resetN` signal | ||
/// is dropped. | ||
final MemoryStorage storage; | ||
|
||
/// A function which delays the response for the given `request`. | ||
/// | ||
/// If none is provided, then the delay will always be `0`. | ||
final int Function(ApbPacket request)? responseDelay; | ||
|
||
/// A function that determines whether a response for a request should contain | ||
/// an error (`slvErr`). | ||
/// | ||
/// If none is provided, it will always respond with no error. | ||
final bool Function(ApbPacket request)? respondWithError; | ||
|
||
/// If true, then returned data on an error will be `x`. | ||
final bool invalidReadDataOnError; | ||
|
||
/// If true, then writes that respond with an error will not store into the | ||
/// [storage]. | ||
final bool dropWriteDataOnError; | ||
|
||
/// Creates a new model [ApbCompleterAgent]. | ||
ApbCompleterAgent( | ||
{required this.intf, | ||
required this.storage, | ||
required Component parent, | ||
this.selectIndex = 0, | ||
this.responseDelay, | ||
this.respondWithError, | ||
this.invalidReadDataOnError = true, | ||
this.dropWriteDataOnError = true, | ||
String name = 'apbCompleter'}) | ||
: super(name, parent); | ||
|
||
@override | ||
Future<void> run(Phase phase) async { | ||
unawaited(super.run(phase)); | ||
|
||
intf.resetN.negedge.listen((event) { | ||
storage.reset(); | ||
}); | ||
|
||
_respond(ready: false); | ||
|
||
// wait for reset to complete | ||
await intf.resetN.nextPosedge; | ||
|
||
while (!Simulator.simulationHasEnded) { | ||
await _receive(); | ||
} | ||
} | ||
|
||
/// Calculates a strobed version of data. | ||
LogicValue _strobeData( | ||
LogicValue originalData, LogicValue newData, LogicValue strobe) => | ||
[ | ||
for (var i = 0; i < strobe.width; i++) | ||
(strobe[i].toBool() ? newData : originalData) | ||
.getRange(i * 8, i * 8 + 8) | ||
].rswizzle(); | ||
|
||
/// Receives one packet (or returns if not selected). | ||
Future<void> _receive() async { | ||
await intf.enable.nextPosedge; | ||
|
||
if (!intf.sel[selectIndex].value.toBool()) { | ||
// we're not selected, wait for the next time | ||
return; | ||
} | ||
|
||
ApbPacket packet; | ||
if (intf.write.value.toBool()) { | ||
packet = ApbWritePacket( | ||
addr: intf.addr.value, | ||
data: intf.wData.value, | ||
strobe: intf.strb.value, | ||
); | ||
} else { | ||
packet = ApbReadPacket(addr: intf.addr.value); | ||
} | ||
|
||
if (responseDelay != null) { | ||
final delayCycles = responseDelay!(packet); | ||
if (delayCycles > 0) { | ||
await intf.clk.waitCycles(delayCycles); | ||
} | ||
} | ||
|
||
if (packet is ApbWritePacket) { | ||
final writeError = respondWithError != null && respondWithError!(packet); | ||
|
||
// store the data | ||
if (!(writeError && dropWriteDataOnError)) { | ||
storage.writeData( | ||
packet.addr, | ||
packet.strobe.and().toBool() // don't `readData` if all 1's | ||
? packet.data | ||
: _strobeData( | ||
storage.readData(packet.addr), | ||
packet.data, | ||
packet.strobe, | ||
), | ||
); | ||
} | ||
|
||
_respond( | ||
ready: true, | ||
error: writeError, | ||
); | ||
} else if (packet is ApbReadPacket) { | ||
// capture the data | ||
_respond( | ||
ready: true, | ||
data: storage.readData(packet.addr), | ||
error: respondWithError != null && respondWithError!(packet), | ||
); | ||
} | ||
|
||
// drop the ready when enable drops | ||
await intf.enable.nextNegedge; | ||
_respond(ready: false); | ||
} | ||
|
||
/// Sets up response signals for the completer (including using inject). | ||
void _respond({required bool ready, bool? error, LogicValue? data}) { | ||
Simulator.injectAction(() { | ||
intf.ready.put(ready); | ||
|
||
if (error == null) { | ||
intf.slvErr?.put(LogicValue.x); | ||
} else { | ||
intf.slvErr?.put(error); | ||
} | ||
|
||
if (data == null || ((error ?? false) && invalidReadDataOnError)) { | ||
intf.rData.put(LogicValue.x); | ||
} else { | ||
intf.rData.put(data); | ||
} | ||
}); | ||
} | ||
} |
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,10 @@ | ||
// Copyright (C) 2023 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
export 'abp_completer.dart'; | ||
export 'apb_compliance_checker.dart'; | ||
export 'apb_monitor.dart'; | ||
export 'apb_packet.dart'; | ||
export 'apb_requester.dart'; | ||
export 'apb_requester_driver.dart'; | ||
export 'apb_tracker.dart'; |
Oops, something went wrong.