Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
b91e5c0
WIP: refactoring AXI to support various interface variants.
kimmeljo Aug 28, 2025
8dfe6b9
WIP: refactor into proper channels
kimmeljo Sep 2, 2025
8690d59
WIP: sw arch cleanup
kimmeljo Sep 2, 2025
1eb378d
WIP: bug fix plus working on memory BFM
kimmeljo Sep 2, 2025
912fe48
WIP: more enhancements
kimmeljo Sep 3, 2025
e187d10
WIP: adding directionality to agents and adding ready driver.
kimmeljo Sep 3, 2025
7a80dde
WIP: val components for AXI-S
kimmeljo Sep 3, 2025
54ed170
WIP: filling out ace4
kimmeljo Sep 3, 2025
671a485
WIP: first attempt at AXI5 support
kimmeljo Sep 5, 2025
010e6ba
adding snoop channels and clusters for axi5
kimmeljo Sep 5, 2025
0135080
WIP: checkpoint for axi5 bfm stuff
kimmeljo Sep 5, 2025
2df2d5e
WIP: trackerString for packets
kimmeljo Sep 5, 2025
03e4220
WIP: start of drivers
kimmeljo Sep 5, 2025
8cf471a
WIP: initial work on axi5 monitors
kimmeljo Sep 5, 2025
5d7bb8a
WIP: handling multi beat driving and monitoring axi5
kimmeljo Sep 6, 2025
9e91257
WIP: agents for axi5
kimmeljo Sep 6, 2025
8adaff3
wip: adding copy constructors and unit test for connecting main and s…
kimmeljo Sep 8, 2025
4975cbe
WIP: axi5_bfm test started
kimmeljo Sep 8, 2025
808c2cc
WIP: bfm test stood up but not working
kimmeljo Sep 8, 2025
98bcdb4
WIP: stream val collateral and working bfm test
kimmeljo Sep 8, 2025
dcee20d
Merge branch 'main' into axi
kimmeljo Sep 8, 2025
d0b13dc
WIP: bfm tests passing
kimmeljo Sep 8, 2025
3421c35
Merge branch 'main' into axi
kimmeljo Sep 8, 2025
30540eb
idmixinenable on B channel
kimmeljo Sep 9, 2025
fe90fe7
idmixinenable on B channel
kimmeljo Sep 9, 2025
0e1ae31
idmixinenable on R channel
kimmeljo Sep 9, 2025
dfde462
W monitor bug
kimmeljo Sep 9, 2025
4375f94
R monitor bug
kimmeljo Sep 9, 2025
c61e01f
bug with TID in AXI5-S
kimmeljo Sep 10, 2025
8373d1c
adding clone methods to all packets and structures
kimmeljo Sep 12, 2025
a30ba09
forgot clone for axi-s packets
kimmeljo Sep 12, 2025
528387a
WIP: adding LTI and doing some re-org
kimmeljo Sep 18, 2025
c17e240
adding clone methods to lti packets
kimmeljo Sep 19, 2025
3bf4c7a
lti completion is from main to provider
kimmeljo Sep 19, 2025
be17b85
adding encodings for lti responses
kimmeljo Sep 19, 2025
81fe069
fixes to AXI-S interface and enhancing ready driver
kimmeljo Sep 24, 2025
d45f0d7
fixing lti transport and bfms to properly use crediting
kimmeljo Sep 24, 2025
1254c90
fixing mmu axi mixin to use untranslated trans version
kimmeljo Sep 24, 2025
9c9154d
Moving data packet fields to BigInt
kimmeljo Sep 24, 2025
99bf5ce
fixing bug with AXI-S keep signal in val collateral
kimmeljo Sep 24, 2025
6100415
updating axi resp field enums
kimmeljo Sep 24, 2025
43d15eb
adding relevant mmu signal enums
kimmeljo Sep 26, 2025
25969b1
adding MSI interface per AXI spec
kimmeljo Oct 1, 2025
2ca0d07
export msi
kimmeljo Oct 1, 2025
af6d828
no last in MSI
kimmeljo Oct 1, 2025
75dc04f
moving all monitors to previousValue
kimmeljo Oct 6, 2025
c08de99
LTI credit monitor
kimmeljo Oct 15, 2025
fe65a0d
lti credit monitor bug
kimmeljo Oct 17, 2025
7a69ad1
LTI fixes on LR and LM
kimmeljo Oct 27, 2025
a8dcb28
bug in driver handling of ready signal
kimmeljo Oct 29, 2025
2b5d201
Tag agent init bug
kimmeljo Oct 29, 2025
5d4095c
LTI tracker logs missing Time column values and should be printing in…
kimmeljo Nov 6, 2025
ad2365d
Allowing timeoutCycles and driveDelay to be nullable at the agent level
kimmeljo Nov 6, 2025
49823fb
artificial cycle delay in axi drivers
kimmeljo Nov 7, 2025
bfff89e
LTI credit flow control in BFM
kimmeljo Nov 8, 2025
dbbbbe9
lti credit bug fix 1
kimmeljo Nov 8, 2025
1454452
adding link utilization hook into axi drivers
kimmeljo Nov 11, 2025
ae356b7
link utilization toggle in driver
kimmeljo Nov 12, 2025
cbb4c4a
link util enable on by default
kimmeljo Nov 12, 2025
edac353
WIP: moving DTI to HCL
kimmeljo Nov 18, 2025
17fa2b1
WIP: more progress
kimmeljo Nov 18, 2025
3b6a8b9
WIP: closer to send side being ready
kimmeljo Nov 19, 2025
4cbccb2
receiving side initial implementation
kimmeljo Nov 20, 2025
30cef4a
breaking out interface tx/rx into generic modules
kimmeljo Nov 20, 2025
674b651
custom sends
kimmeljo Nov 20, 2025
42c45cb
generalizing part 1
kimmeljo Nov 20, 2025
b5a715f
ready for initial testing after abstract refactor
kimmeljo Nov 20, 2025
fbd3075
basic unit tests for dti interface tx
kimmeljo Nov 20, 2025
0001370
dti interface rx basic unit tests
kimmeljo Nov 20, 2025
13892ed
doa controller tests with standard DTI controllers passing
kimmeljo Nov 20, 2025
14ffdf9
basic unit tests passing for dti tbu main
kimmeljo Nov 20, 2025
06f7b78
dti tbu sub basic tests passing and doing some renaming
kimmeljo Nov 21, 2025
92a82c7
bandwidth testing for dti tx looking good
kimmeljo Nov 21, 2025
388987f
dti interface rx bandwidth tests looking good
kimmeljo Nov 21, 2025
b1202f9
fixing arbiter generation
kimmeljo Nov 24, 2025
3322802
DTI rx backpressure unit testing
kimmeljo Nov 24, 2025
d23289e
DTI tx backpressure unit tests
kimmeljo Nov 24, 2025
b52dc68
final prep for merge into ROHD-HCL
kimmeljo Nov 26, 2025
9cd5f8a
Merge branch 'axi' into axi_dti
kimmeljo Nov 26, 2025
1ae083a
bug fix in rx side where flits were getting reordered if LAST comes b…
kimmeljo Dec 9, 2025
ef83b20
refactor of stream controllers to move outside of DTI
kimmeljo Dec 11, 2025
8f94e5b
dti message abstraction
kimmeljo Dec 12, 2025
a677a8e
Merge branch 'main' into axi_dti
kimmeljo Dec 19, 2025
cbaf2ac
fix lint errors, documentation, copyright
kimmeljo Dec 21, 2025
3ba6bf0
adding the register messages from dti tbu
kimmeljo Dec 21, 2025
aaff5ea
no wave dumper in final change set
kimmeljo Dec 21, 2025
7a29f80
small fix to naming of dti structs
kimmeljo Dec 23, 2025
4121a6a
init bug
kimmeljo Dec 23, 2025
9647030
buffer overwrite bug
kimmeljo Dec 24, 2025
c0d1383
rx msg bug
kimmeljo Dec 24, 2025
5675908
more dti rx bug fixes
kimmeljo Dec 24, 2025
bd2da41
feedback part 1
kimmeljo Jan 5, 2026
5f06122
protecting more internal members and fixing lint error
kimmeljo Jan 5, 2026
d06f1df
Merge branch 'main' into axi_dti
desmonddak Apr 23, 2026
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
8 changes: 6 additions & 2 deletions doc/components/amba/axi.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ For code examples of how to work with both individual channel interfaces and clu

## HW

There are no current HW implementations for AXI-based controllers. This will be done in future work.
### AXI-S Controller

Note that part of the difficulty is in defining what the "other side" of the controller's interface looks like.
Implementations of generic HW for both sending and receiving arbitrary data on an AXI-S interface are included. Primarily, the complexity of such components is in breaking out or aggregating arbitrarily long data into or from flits on the interface over time while overlaying the correct metadata into/from the other stream signals.

The implementations can be found in `lib/src/protocols/amba5/axi_s/*.dart`.

For code examples of how to work with stream controllers, see `test/protocols/amba5/axi_s/axi_s_interface_*_test.dart`.

## Validation

Expand Down
25 changes: 25 additions & 0 deletions doc/components/amba/dti.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# DTI

ROHD-HCL contains a bunch of collateral for DTI. The collateral includes message definitions as `LogicStructure`s and HW that enables protocol compliant sending and receiving of DTI messages over AXI-S.

For cross-referencing against the official DTI specification:

- Any DTI collateral should be aligned with [DTI specification `H`](https://developer.arm.com/documentation/ihi0088/latest/).

## Messages

DTI messages are implemented as ROHD `LogicStructure`s. The fields including widths, parametrization, etc. are in accordance with the DTI specification. These can be used to conveniently construct and pass around DTI messages in HW. In some cases, there are also SW hooks to populate DTI messages (ex: from an AXI write/read).

**NOTE**: Currently, only the `TBU` messages have been implemented. Future work will cover other message groups (ex: `ATS`).

For code examples of how to work with DTI messages, see `test/protocols/amba5/dti/dti_controller_test.dart`.

## Controllers

The abstract class `DtiController` implements a generic ROHD `Module` to send and receive DTI messages over an AXI-S interface pair. On the other side of the AXI-S pair is a configurable collection of `ReadyValidInterface`s on a per message class basis. There is a sub-collection for the messages that the controller should send and a sub-collection for the messages that the controller should receive. The handling of each supported message class is configurable through the `DtiMessageInterfaceConfig` object. Properties that can be configured include FIFO depths and crediting.

Implementations of the abstract `DtiController` add functionality specific to a given "flavor" of agent that talks DTI (TBU, ATS, etc.). These implementations also include "standard" constructors that support the typical TX and RX messages given directionality (main versus subordinate).

**NOTE**: Currently, only `TBU` flavors of the generic `DtiController` have been implemented. Future work will cover other message groups (ex: `ATS`).

For code examples of how to work with DTI controllers, see `test/protocols/amba5/dti/dti_controller_test.dart`.
1 change: 1 addition & 0 deletions lib/rohd_hcl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export 'src/interfaces/interfaces.dart';
export 'src/memory/memories.dart';
export 'src/models/models.dart';
export 'src/priority_encoder.dart';
export 'src/protocols/protocols.dart';
export 'src/reduction_tree.dart';
export 'src/reduction_tree_generator.dart';
export 'src/rotate.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/src/interfaces/amba5/axi5_s.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class Axi5StreamInterface extends Axi5TransportInterface {
if (useLast) Logic.port('TLAST'),
if (useWakeup) Logic.port('TWAKEUP'),
if (idWidth > 0) Logic.port('TID', idWidth),
if (userWidth > 0) Logic.port('TUSER'),
if (userWidth > 0) Logic.port('TUSER', userWidth),
], [
PairDirection.fromProvider,
]);
Expand Down
1 change: 0 additions & 1 deletion lib/src/interfaces/ready_valid_interface.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:rohd/rohd.dart';
// Copyright (C) 2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
Expand Down
5 changes: 5 additions & 0 deletions lib/src/protocols/amba5/amba5.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright (C) 2024-2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'axi_s/axi_s.dart';
export 'dti/dti.dart';
6 changes: 6 additions & 0 deletions lib/src/protocols/amba5/axi_s/axi_s.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (C) 2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'axi_s_interface_rx.dart';
export 'axi_s_interface_tx.dart';
export 'axi_s_utils.dart';
246 changes: 246 additions & 0 deletions lib/src/protocols/amba5/axi_s/axi_s_interface_rx.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// Copyright (C) 2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// axi_s_interface_rx.dart
// HW to receive arbitrary messages over AXI-S.
//
// 2025 December
// Author: Josh Kimmel <joshua1.kimmel@intel.com>

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

/// A generic module to receive messages over AXI-S.
class AxiStreamInterfaceRx extends Module {
/// Clock and reset.
@protected
late final Axi5SystemInterface sys;

/// Inbound messages.
@protected
late final Axi5StreamInterface stream;

/// The maximum size of any message we expect
/// to receive over the AXI-S interface.
late final int maxMsgRxSize;

/// Can we accept a new message.
///
/// This effectively drives TREADY.
@protected
late final Logic canAcceptMsg;

/// Fixed source ID for this module.
///
/// Received in TDEST signal.
/// Drop if doesn't match.
@protected
late final Logic? srcId;

/// New message received indicator.
Logic get msgValid => output('msgValid');

/// New message received.
Logic get msg => output('msg');

/// New message's source over AXI.
Logic? get msgSrc => output('msgSrc');

/// New message's user field over AXI.
Logic? get msgUser => output('msgUser');

/// New message's strobe field over AXI.
Logic? get msgStrb => output('msgStrb');

/// New message's kep field over AXI.
Logic? get msgKeep => output('msgKeep');

/// Constructor.
AxiStreamInterfaceRx({
required Axi5SystemInterface sys,
required Axi5StreamInterface stream,
required Logic canAcceptMsg,
required this.maxMsgRxSize,
Logic? srcId,
super.name = 'axiStreamInterfaceRx',
}) {
this.sys = addPairInterfacePorts(sys, PairRole.consumer);
this.stream = addPairInterfacePorts(
stream,
PairRole.consumer,
uniquify: (original) => '${name}_stream_$original',
);
this.canAcceptMsg =
addInput('canAcceptMsg', canAcceptMsg, width: canAcceptMsg.width);
if (srcId != null) {
this.srcId = addInput('srcId', srcId, width: srcId.width);
} else {
this.srcId = null;
}

addOutput('msgValid');
addOutput('msg', width: maxMsgRxSize);
if (stream.idWidth > 0) {
addOutput('msgSrc', width: stream.idWidth);
}
if (stream.userWidth > 0) {
addOutput('msgUser', width: stream.userWidth);
}
if (stream.useStrb) {
addOutput('msgStrb', width: maxMsgRxSize ~/ 8);
}
if (stream.useKeep) {
addOutput('msgKeep', width: maxMsgRxSize ~/ 8);
}

_build();
}

void _build() {
// max # of beats we could possibly expect for a single message
final numBeats = (maxMsgRxSize / stream.dataWidth).ceil();

// conditions under which we should capture/forward flits
final idHit = (stream.destWidth > 0
? (srcId?.eq(stream.dest) ?? Const(1))
: Const(1));
final inAccept = stream.valid & (stream.ready ?? Const(1)) & idHit;
final inLast = inAccept & idHit & (stream.last ?? Const(1));

// handle TWAKEUP if present
final isAwake = Logic(name: 'isAwake');
if (stream.useWakeup) {
isAwake <= flop(sys.clk, stream.wakeup ?? Const(1), reset: ~sys.resetN);
} else {
isAwake <= Const(1); // always awake
}

// case 1: every message can be captured in a single beat
// simplify the HW
if (numBeats == 1) {
msgValid <= inLast & isAwake;
msg <= stream.data!.getRange(0, maxMsgRxSize);
if (stream.useStrb) {
msgStrb?.gets(stream.strb?.getRange(0, maxMsgRxSize ~/ 8) ??
~Const(0, width: maxMsgRxSize ~/ 8));
}
if (stream.useKeep) {
msgKeep?.gets(stream.keep?.getRange(0, maxMsgRxSize ~/ 8) ??
~Const(0, width: maxMsgRxSize ~/ 8));
}
}
// case 2: message might come in over multiple beats
else {
// count the number of beats in a given message
// restart whenever we see a TLAST
final beatCounter = Counter.simple(
clk: sys.clk,
reset: ~sys.resetN,
enable: inAccept,
restart: inLast,
width: numBeats.bitLength);

// capture the individual beats of the message
// and store them for assembly later
final msgFlits = <Logic>[];
for (var i = 0; i < numBeats - 1; i++) {
msgFlits.add(Logic(name: 'inBeats$i', width: stream.dataWidth));
Sequential(sys.clk, reset: ~sys.resetN, [
msgFlits[i] <
mux(inAccept & beatCounter.count.eq(i), stream.data!, msgFlits[i])
]);
}

// must select the correct arrangement of flits
final priorFlitsCases = <Logic, Logic>{};
for (var i = 0; i < numBeats; i++) {
priorFlitsCases[Const(i, width: beatCounter.count.width)] = [
...msgFlits.sublist(0, i),
stream.data!,
...msgFlits.sublist(i),
].rswizzle();
}
final priorFlits = cases(
beatCounter.count,
conditionalType: ConditionalType.unique,
priorFlitsCases,
defaultValue: Const(0, width: numBeats * stream.dataWidth),
);

// handle strobes
if (stream.useStrb) {
final msgStrbs = <Logic>[];
for (var i = 0; i < numBeats - 1; i++) {
msgStrbs.add(Logic(name: 'inStrbs$i', width: stream.strbWidth));
Sequential(sys.clk, reset: ~sys.resetN, [
msgStrbs[i] <
mux(inAccept & beatCounter.count.eq(i), stream.strb!,
msgStrbs[i])
]);
}
final priorStrbsCases = <Logic, Logic>{};
for (var i = 0; i < numBeats; i++) {
priorStrbsCases[Const(i, width: beatCounter.count.width)] = [
...msgStrbs.sublist(0, i),
stream.strb!,
...msgStrbs.sublist(i),
].rswizzle();
}
final priorStrbs = cases(
beatCounter.count,
conditionalType: ConditionalType.unique,
priorStrbsCases,
defaultValue: ~Const(0, width: numBeats * stream.strbWidth),
);
msgStrb?.gets(priorStrbs.getRange(0, maxMsgRxSize ~/ 8));
}

// handle keeps
if (stream.useKeep) {
final msgKeeps = <Logic>[];
for (var i = 0; i < numBeats - 1; i++) {
msgKeeps.add(Logic(name: 'inKeeps$i', width: stream.strbWidth));
Sequential(sys.clk, reset: ~sys.resetN, [
msgKeeps[i] <
mux(inAccept & beatCounter.count.eq(i), stream.keep!,
msgKeeps[i])
]);
}
final priorKeepsCases = <Logic, Logic>{};
for (var i = 0; i < numBeats; i++) {
priorKeepsCases[Const(i, width: beatCounter.count.width)] = [
...msgKeeps.sublist(0, i),
stream.keep!,
...msgKeeps.sublist(i),
].rswizzle();
}
final priorKeeps = cases(
beatCounter.count,
conditionalType: ConditionalType.unique,
priorKeepsCases,
defaultValue: ~Const(0, width: numBeats * stream.strbWidth),
);
msgKeep?.gets(priorKeeps.getRange(0, maxMsgRxSize ~/ 8));
}

// the last flit comes straight from the interface
// for performance
msgValid <= inLast & isAwake;
msg <= priorFlits.getRange(0, maxMsgRxSize);
}

// drive TREADY
if (stream.ready != null) {
stream.ready! <= canAcceptMsg;
}

// TID and TUSER must hold constant for a single stream message
// and message beats cannot be interleaved
// so it is safe to just grab the source directly from the interface
msgSrc?.gets(stream.id ?? Const(0, width: stream.idWidth));
if (stream.userWidth > 0) {
msgUser?.gets(stream.user ?? Const(0, width: stream.userWidth));
}
}
}
Loading
Loading