Skip to content
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

AXI4 Interface and Functional Modeling #159

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
647 changes: 647 additions & 0 deletions lib/src/interfaces/axi4.dart

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion lib/src/interfaces/interfaces.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2023-2024 Intel Corporation
// Copyright (C) 2024-2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'apb.dart';
export 'axi4.dart';
10 changes: 10 additions & 0 deletions lib/src/models/axi4_bfm/axi4_bfm.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (C) 2024-2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'axi4_compliance_checker.dart';
export 'axi4_main.dart';
export 'axi4_main_driver.dart';
export 'axi4_monitor.dart';
export 'axi4_packet.dart';
export 'axi4_subordinate.dart';
export 'axi4_tracker.dart';
128 changes: 128 additions & 0 deletions lib/src/models/axi4_bfm/axi4_compliance_checker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright (C) 2024-2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// axi4_compliance_checker.dart
// Compliance checking for AXI4.
//
// 2025 January
// Author: Josh Kimmel <[email protected]>

import 'dart:async';

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

/// A checker for some of the rules defined in the AXI4 interface specification.
///
/// This does not necessarily cover all rules defined in the spec.
class Axi4ComplianceChecker extends Component {
/// AXI4 System Interface.
final Axi4SystemInterface sIntf;

/// AXI4 Read Interface.
final Axi4ReadInterface rIntf;

/// AXI4 Write Interface.
final Axi4WriteInterface wIntf;

/// Creates a new compliance checker for AXI4.
Axi4ComplianceChecker(
this.sIntf,
this.rIntf,
this.wIntf, {
required Component parent,
String name = 'axi4ComplianceChecker',
}) : super(name, parent);

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

// wait for reset to complete
await sIntf.resetN.nextPosedge;

// checks to run
// READ REQUESTS
// number of flits returned matches ARLEN if no error
// if RLAST is present, asserted on the final flit only
// if RID is present, every read response should match
// a pending request ARID
// WRITE REQUESTS
// number of flits sent matches AWLEN
// WLAST is asserted on the final flit only
// if BID is present, every write response should match
// a pending request AWID

final rLastPresent = rIntf.rLast != null;

final readReqMap = <int, List<int>>{};
final writeReqMap = <int, List<int>>{};
var lastWriteReqId = -1;

sIntf.clk.posedge.listen((event) {
// capture read requests for counting
if (rIntf.arValid.previousValue!.isValid &&
rIntf.arValid.previousValue!.toBool()) {
final id = rIntf.arId?.previousValue?.toInt() ?? 0;
final len = (rIntf.arLen?.previousValue?.toInt() ?? 0) + 1;
readReqMap[id] = [len, 0];
}

// track read response flits
if (rIntf.rValid.previousValue!.isValid &&
rIntf.rValid.previousValue!.toBool()) {
final id = rIntf.rId?.previousValue?.toInt() ?? 0;
if (!readReqMap.containsKey(id)) {
logger.severe(
'Cannot match a read response to any pending read request. '
'ID captured by the response was $id.');
}

readReqMap[id]![1] = readReqMap[id]![1] + 1;
final len = readReqMap[id]![0];
final currCount = readReqMap[id]![1];
if (currCount > len) {
logger.severe(
'Received more read response data flits than indicated by the '
'request with ID $id ARLEN. Expected $len but got $currCount');
} else if (currCount == len &&
rLastPresent &&
!rIntf.rLast!.previousValue!.toBool()) {
logger.severe('Received the final flit in the read response data per '
'the request with ID $id ARLEN but RLAST is not asserted.');
}
}

// track write requests
if (wIntf.awValid.previousValue!.isValid &&
wIntf.awValid.previousValue!.toBool()) {
final id = wIntf.awId?.previousValue?.toInt() ?? 0;
final len = (wIntf.awLen?.previousValue?.toInt() ?? 0) + 1;
writeReqMap[id] = [len, 0];
lastWriteReqId = id;
}

// track write data flits
if (wIntf.wValid.previousValue!.isValid &&
wIntf.wValid.previousValue!.toBool()) {
final id = lastWriteReqId;
if (!writeReqMap.containsKey(id)) {
logger.severe('There is no pending write request '
'to associate with valid write data.');
}

writeReqMap[id]![1] = writeReqMap[id]![1] + 1;
final len = writeReqMap[id]![0];
final currCount = writeReqMap[id]![1];
if (currCount > len) {
logger.severe(
'Sent more write data flits than indicated by the request '
'with ID $id AWLEN. Expected $len but sent $currCount');
} else if (currCount == len && !wIntf.wLast.previousValue!.toBool()) {
logger.severe('Sent the final flit in the write data per the request '
'with ID $id AWLEN but WLAST is not asserted.');
}
}
});
}
}
63 changes: 63 additions & 0 deletions lib/src/models/axi4_bfm/axi4_main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (C) 2024-2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// axi4_main.dart
// An agent sending for AXI4 requests.
//
// 2025 January
// Author: Josh Kimmel <[email protected]>

import 'package:rohd_hcl/rohd_hcl.dart';
import 'package:rohd_hcl/src/models/axi4_bfm/axi4_bfm.dart';
import 'package:rohd_vf/rohd_vf.dart';

/// An agent for sending requests on
/// the [Axi4ReadInterface] and [Axi4WriteInterface].
///
/// Driven read packets will update the returned data into the same packet.
class Axi4MainAgent extends Agent {
/// AXI4 System Interface.
final Axi4SystemInterface sIntf;

/// AXI4 Read Interface.
final Axi4ReadInterface rIntf;

/// AXI4 Write Interface.
final Axi4WriteInterface wIntf;

/// The sequencer where requests should be sent.
late final Sequencer<Axi4RequestPacket> sequencer;

/// The driver that sends the requests over the interface.
late final Axi4MainDriver driver;

/// The number of cycles before timing out if no transactions can be sent.
final int timeoutCycles;

/// The number of cycles before an objection will be dropped when there are
/// no pending packets to send.
final int dropDelayCycles;

/// Constructs a new [Axi4MainAgent].
Axi4MainAgent({
required this.sIntf,
required this.rIntf,
required this.wIntf,
required Component parent,
String name = 'axiMainAgent',
this.timeoutCycles = 500,
this.dropDelayCycles = 30,
}) : super(name, parent) {
sequencer = Sequencer<Axi4RequestPacket>('sequencer', this);

driver = Axi4MainDriver(
parent: this,
sIntf: sIntf,
rIntf: rIntf,
wIntf: wIntf,
sequencer: sequencer,
timeoutCycles: timeoutCycles,
dropDelayCycles: dropDelayCycles,
);
}
}
Loading
Loading