Skip to content

Commit

Permalink
Add ways to access sources of inputs and inouts (#503)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkorbel1 authored Aug 6, 2024
1 parent dd3f43d commit d41029e
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 98 deletions.
1 change: 0 additions & 1 deletion lib/src/diagnostics/inspector_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ extension _ModuleDevToolUtils on Module {
Map<String, dynamic> toJson({bool skipCustomModules = true}) {
final json = {
'name': name,
// ignore: invalid_use_of_protected_member
'inputs': inputs.map((key, value) => MapEntry(key, value.toMap())),
'outputs': outputs.map((key, value) => MapEntry(key, value.toMap())),
};
Expand Down
6 changes: 0 additions & 6 deletions lib/src/interfaces/interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,13 @@ class Interface<TagType> {
for (final port in getPorts(inputTags).values) {
port <=
(port is LogicArray
// ignore: invalid_use_of_protected_member
? module.addInputArray(
uniquify(port.name),
srcInterface.port(port.name),
dimensions: port.dimensions,
elementWidth: port.elementWidth,
numUnpackedDimensions: port.numUnpackedDimensions,
)
// ignore: invalid_use_of_protected_member
: module.addInput(
uniquify(port.name),
srcInterface.port(port.name),
Expand All @@ -105,14 +103,12 @@ class Interface<TagType> {
if (outputTags != null) {
for (final port in getPorts(outputTags).values) {
final output = (port is LogicArray
// ignore: invalid_use_of_protected_member
? module.addOutputArray(
uniquify(port.name),
dimensions: port.dimensions,
elementWidth: port.elementWidth,
numUnpackedDimensions: port.numUnpackedDimensions,
)
// ignore: invalid_use_of_protected_member
: module.addOutput(
uniquify(port.name),
width: port.width,
Expand All @@ -136,15 +132,13 @@ class Interface<TagType> {

port <=
(port is LogicArray
// ignore: invalid_use_of_protected_member
? module.addInOutArray(
uniquify(port.name),
srcInterface.port(port.name),
dimensions: port.dimensions,
elementWidth: port.elementWidth,
numUnpackedDimensions: port.numUnpackedDimensions,
)
// ignore: invalid_use_of_protected_member
: module.addInOut(
uniquify(port.name),
srcInterface.port(port.name),
Expand Down
104 changes: 66 additions & 38 deletions lib/src/module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,20 @@ abstract class Module {
final TraverseableCollection<Logic> _internalSignals =
TraverseableCollection();

/// An internal list of inputs to this [Module].
final Map<String, Logic> _inputs = {};
/// An internal mapping of inputs to this [Module].
late final Map<String, Logic> _inputs = {};

/// An internal list of outputs to this [Module].
final Map<String, Logic> _outputs = {};
/// An internal mapping of outputs to this [Module].
late final Map<String, Logic> _outputs = {};

/// An internal list of inouts to this [Module].
final Map<String, Logic> _inOuts = {};
/// An internal mapping of inOuts to this [Module].
late final Map<String, Logic> _inOuts = {};

/// An internal mapping of input names to their sources to this [Module].
late final Map<String, Logic> _inputSources = {};

/// An internal mapping of inOut names to their sources to this [Module].
late final Map<String, Logic> _inOutSources = {};

/// The parent [Module] of this [Module].
///
Expand All @@ -60,7 +66,10 @@ abstract class Module {

/// A map from [input] port names to this [Module] to corresponding [Logic]
/// signals.
@protected
///
/// Note that [inputs] should only be used to drive hardware *within* a
/// [Module]. To access the signal that drives these inputs, use
/// [inputSource].
Map<String, Logic> get inputs => UnmodifiableMapView<String, Logic>(_inputs);

/// A map from [output] port names to this [Module] to corresponding [Logic]
Expand All @@ -70,7 +79,10 @@ abstract class Module {

/// A map from [inOut] port names to this [Module] to corresponding [Logic]
/// signals.
@protected
///
/// Note that [inOuts] should only be used for hardware *within* a [Module].
/// To access the signal that drives/received these inOuts from outside of
/// this [Module], use [inOutSource].
Map<String, Logic> get inOuts => UnmodifiableMapView<String, Logic>(_inOuts);

/// An [Iterable] of all [Module]s contained within this [Module].
Expand Down Expand Up @@ -101,16 +113,21 @@ abstract class Module {
/// named [name].
///
/// Only logic within this [Module] should consume this signal.
@protected
Logic input(String name) => _inputs.containsKey(name)
? _inputs[name]!
: throw PortDoesNotExistException(
'Input name "$name" not found as an input to this Module.');

/// The original `source` provided to the creation of the [input] port [name]
/// via [addInput] or [addInputArray].
Logic inputSource(String name) =>
_inputSources[name] ??
(throw PortDoesNotExistException(
'$name is not an input of this Module.'));

/// Provides the [input] named [name] if it exists, otherwise `null`.
///
/// Only logic within this [Module] should consume this signal.
@protected
Logic? tryInput(String name) => _inputs[name];

/// Accesses the [Logic] associated with this [Module]s output port
Expand All @@ -130,14 +147,19 @@ abstract class Module {
/// named [name].
///
/// Only logic within this [Module] should consume this signal.
@protected
Logic inOut(String name) => _inOuts.containsKey(name)
? _inOuts[name]!
: throw PortDoesNotExistException(
'InOut name "$name" not found as an in/out of this Module.');

/// The original `source` provided to the creation of the [inOut] port [name]
/// via [addInOut] or [addInOutArray].
Logic inOutSource(String name) =>
_inOutSources[name] ??
(throw PortDoesNotExistException(
'$name is not an inOut of this Module.'));

/// Provides the [inOut] named [name] if it exists, otherwise `null`.
@protected
Logic? tryInOut(String name) => _inOuts[name];

/// Returns true iff [signal] is the same [Logic] as the [input] port of this
Expand Down Expand Up @@ -602,26 +624,29 @@ abstract class Module {
/// Registers a signal as an input to this [Module] and returns an input port
/// that can be consumed.
///
/// The return value is the same as what is returned by [input].
@protected
Logic addInput(String name, Logic x, {int width = 1}) {
/// The return value is the same as what is returned by [input] and should
/// only be used within this [Module]. The provided [source] is accessible via
/// [inputSource].
Logic addInput(String name, Logic source, {int width = 1}) {
_checkForSafePortName(name);
if (x.width != width) {
throw PortWidthMismatchException(x, width);
if (source.width != width) {
throw PortWidthMismatchException(source, width);
}

if (x is LogicStructure) {
if (source is LogicStructure) {
// ignore: parameter_assignments
x = x.packed;
source = source.packed;
}

final inPort = Logic(name: name, width: width, naming: Naming.reserved)
..gets(x)
..gets(source)
// ignore: invalid_use_of_protected_member
..parentModule = this;

_inputs[name] = inPort;

_inputSources[name] = source;

return inPort;
}

Expand All @@ -634,24 +659,27 @@ abstract class Module {
/// Registers a signal as an inOut to this [Module] and returns an inOut port
/// that can be consumed.
///
/// The return value is the same as what is returned by [inOut].
@protected
LogicNet addInOut(String name, Logic x, {int width = 1}) {
/// The return value is the same as what is returned by [inOut] and should
/// only be used within this [Module]. The provided [source] is accessible via
/// [inOutSource].
LogicNet addInOut(String name, Logic source, {int width = 1}) {
_checkForSafePortName(name);
if (x.width != width) {
throw PortWidthMismatchException(x, width);
if (source.width != width) {
throw PortWidthMismatchException(source, width);
}

_inOutDrivers.add(x);
_inOutDrivers.add(source);

final inOutPort =
LogicNet(name: name, width: width, naming: Naming.reserved)
// ignore: invalid_use_of_protected_member
..parentModule = this
..gets(x);
..gets(source);

_inOuts[name] = inOutPort;

_inOutSources[name] = source;

return inOutPort;
}

Expand All @@ -661,12 +689,11 @@ abstract class Module {
///
/// This is very similar to [addInput], except for [LogicArray]s.
///
/// Performs validation on overall width matching for [x], but not on
/// Performs validation on overall width matching for [source], but not on
/// [dimensions], [elementWidth], or [numUnpackedDimensions].
@protected
LogicArray addInputArray(
String name,
Logic x, {
Logic source, {
List<int> dimensions = const [1],
int elementWidth = 1,
int numUnpackedDimensions = 0,
Expand All @@ -680,20 +707,21 @@ abstract class Module {
numUnpackedDimensions: numUnpackedDimensions,
naming: Naming.reserved,
)
..gets(x)
..gets(source)
// ignore: invalid_use_of_protected_member
..setAllParentModule(this);

_inputs[name] = inArr;

_inputSources[name] = source;

return inArr;
}

/// Registers an output to this [Module] and returns an output port that
/// can be driven.
///
/// The return value is the same as what is returned by [output].
@protected
Logic addOutput(String name, {int width = 1}) {
_checkForSafePortName(name);

Expand All @@ -711,7 +739,6 @@ abstract class Module {
/// named [name].
///
/// This is very similar to [addOutput], except for [LogicArray]s.
@protected
LogicArray addOutputArray(
String name, {
List<int> dimensions = const [1],
Expand Down Expand Up @@ -741,20 +768,19 @@ abstract class Module {
///
/// This is very similar to [addInOut], except for [LogicArray]s.
///
/// Performs validation on overall width matching for [x], but not on
/// Performs validation on overall width matching for [source], but not on
/// [dimensions], [elementWidth], or [numUnpackedDimensions].
@protected
LogicArray addInOutArray(
String name,
Logic x, {
Logic source, {
List<int> dimensions = const [1],
int elementWidth = 1,
int numUnpackedDimensions = 0,
}) {
_checkForSafePortName(name);

// make sure we register all the _inOutDrivers properly
final xElems = [x];
final xElems = [source];
for (var i = 0; i < xElems.length; i++) {
final xi = xElems[i];
_inOutDrivers.add(xi);
Expand All @@ -770,12 +796,14 @@ abstract class Module {
numUnpackedDimensions: numUnpackedDimensions,
naming: Naming.reserved,
)
..gets(x)
..gets(source)
// ignore: invalid_use_of_protected_member
..setAllParentModule(this);

_inOuts[name] = inOutArr;

_inOutSources[name] = source;

return inOutArr;
}

Expand Down
3 changes: 3 additions & 0 deletions lib/src/signals/logic_structure.dart
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ class LogicStructure implements Logic {

/// Performs a recursive call of setting [parentModule] on all of [elements]
/// and their [elements] for any sub-[LogicStructure]s.
///
/// This should *only* be called by [Module.build]. It is used to optimize
/// search.
@protected
void setAllParentModule(Module? newParentModule) {
parentModule = newParentModule;
Expand Down
Loading

0 comments on commit d41029e

Please sign in to comment.