Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 6 additions & 1 deletion lib/src/module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ abstract class Module {

/// Converts a [hierarchy] (like used in [_checkValidHierarchy]) into a string
/// that can be used for error messages.
static String _hierarchyListToString(List<Module> hierarchy) =>
static String _hierarchyListToString(Iterable<Module> hierarchy) =>
hierarchy.map((e) => e.name).join('.');

/// Adds a [Module] to this as a subModule.
Expand Down Expand Up @@ -1107,6 +1107,11 @@ abstract class Module {
return hier.toString();
}

/// Returns the hierarchical name of this [Module] with the parent [hierarchy]
/// included, separated by `.`s, e.g. `top.mid.leaf`. Because it depends on
/// [hierarchy], this is only valid after [build] has been called.
String get hierarchicalName => _hierarchyListToString(hierarchy());

/// Returns a synthesized version of this [Module].
///
/// Currently returns one long file in SystemVerilog, but in the future
Expand Down
10 changes: 7 additions & 3 deletions lib/src/modules/conditionals/always.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2021-2024 Intel Corporation
// Copyright (C) 2021-2025 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// always.dart
Expand Down Expand Up @@ -135,8 +135,12 @@ abstract class Always extends Module with SystemVerilog {
}

// share the registration information down
conditional.updateAssignmentMaps(
assignedReceiverToOutputMap, assignedDriverToInputMap);
conditional.updateRegistration(
assignedReceiverToOutputMap: assignedReceiverToOutputMap,
assignedDriverToInputMap: assignedDriverToInputMap,
parentConditional: null,
parentAlways: this,
);
}
}

Expand Down
46 changes: 39 additions & 7 deletions lib/src/modules/conditionals/conditional.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import 'package:meta/meta.dart';
import 'package:rohd/rohd.dart';
import 'package:rohd/src/modules/conditionals/always.dart';
import 'package:rohd/src/modules/conditionals/ssa.dart';

/// Represents an some logical assignments or actions that will only happen
Expand All @@ -28,19 +29,50 @@ abstract class Conditional {
/// This is used for things like [Sequential]'s pre-tick values.
Map<Logic, LogicValue> _driverValueOverrideMap = {};

/// The [Conditional] that contains this [Conditional], if there is one.
///
/// This is only initialized after it's been included inside an [Always].
late final Conditional? _parentConditional;

/// The [Always] parent of this [Conditional], if there is one.
///
/// This is only initialized after it's been included inside an [Always].
late final Always _parentAlways;

/// A string representing the hierarchical path to this [Conditional],
/// including the module path to the [_parentAlways] and the names of
/// [Conditional]s within that [Always] down to `this` one.
@protected
@internal
String get hierarchyString => [
_parentConditional?.hierarchyString ?? _parentAlways.hierarchicalName,
runtimeType
].join('.');

/// Updates registration information for the [Conditional], passed down from
/// the parent [Always] or [Conditional].
///
/// Updates the values of [_assignedReceiverToOutputMap] and
/// [_assignedDriverToInputMap] and passes them down to all sub-[Conditional]s
/// as well.
@internal
void updateAssignmentMaps(
Map<Logic, Logic> assignedReceiverToOutputMap,
Map<Logic, Logic> assignedDriverToInputMap,
) {
void updateRegistration({
required Map<Logic, Logic> assignedReceiverToOutputMap,
required Map<Logic, Logic> assignedDriverToInputMap,
required Conditional? parentConditional,
required Always parentAlways,
}) {
_assignedReceiverToOutputMap = assignedReceiverToOutputMap;
_assignedDriverToInputMap = assignedDriverToInputMap;
_parentConditional = parentConditional;
_parentAlways = parentAlways;
for (final conditional in conditionals) {
conditional.updateAssignmentMaps(
assignedReceiverToOutputMap, assignedDriverToInputMap);
conditional.updateRegistration(
assignedReceiverToOutputMap: assignedReceiverToOutputMap,
assignedDriverToInputMap: assignedDriverToInputMap,
parentConditional: this,
parentAlways: parentAlways,
);
}
}

Expand Down Expand Up @@ -204,7 +236,7 @@ abstract class Conditional {
receiverOutput.put(LogicValue.x);
}
} on WriteAfterReadException catch (e) {
throw e.cloneWithAddedPath(' at (driving X) $this');
throw e.cloneWithAddedPath(' at (driving X) $this [$hierarchyString]');
}

drivenSignals?.addAll(receivers);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/modules/conditionals/conditional_assign.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class ConditionalAssign extends Conditional {
_receiverOutput.put(currentValue);
}
} on WriteAfterReadException catch (e) {
throw e.cloneWithAddedPath(' at $this');
throw e.cloneWithAddedPath(' at $this [$hierarchyString]');
}

if (drivenSignals != null &&
Expand Down
2 changes: 2 additions & 0 deletions test/comb_mod_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ void main() {
} on Exception catch (e) {
expect(e, isA<WriteAfterReadException>());
expect(e.toString(), contains('internalReadEn '));
expect(
e.toString(), contains('singlereadandwriterf.rf_read.If.Case'));
}
}
});
Expand Down
11 changes: 11 additions & 0 deletions test/module_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -386,4 +386,15 @@ void main() {
}
});
});

test('hierarchicalName', () async {
final topInput = Logic();
final top = FlexibleModule(name: 'top')..addInput('a', topInput);
final mid = FlexibleModule(name: 'mid')..addInput('a', top.input('a'));
final sub = FlexibleModule(name: 'sub')..addInput('a', mid.input('a'));

await top.build();

expect(sub.hierarchicalName, 'top.mid.sub');
});
}
Loading