build method
Builds the Module and all subModules within it.
It is recommended not to override build nor put logic in build unless you have good reason to do so. Aim to build up relevant logic in the constructor.
All logic within this Module must be defined before the call to
super.build()
. When overriding this method, you should call
super.build()
as the last thing that you do, and you must always call
it.
This method traverses connectivity inwards from this Module's inputs and outputs to determine which Modules are contained within it. During this process, it will set a variety of additional information within the hierarchy.
This function can be used to consume real wallclock time for things like starting up interactions with independent processes (e.g. cosimulation).
This function should only be called one time per Module.
The hierarchy is built "bottom-up", so leaf-level Modules are built before the Modules which contain them.
Implementation
@mustCallSuper
Future<void> build() async {
if (hasBuilt) {
throw Exception(
'This Module has already been built, and can only be built once.');
}
// construct the list of modules within this module
// 1) trace from outputs of this module back to inputs of this module
for (final output in [..._outputs.values, ...inOuts.values]) {
await _traceOutputForModuleContents(output, dontAddSignal: true);
}
// 2) trace from inputs of all modules to inputs of this module
for (final input in [..._inputs.values, ...inOuts.values]) {
await _traceInputForModuleContents(input, dontAddSignal: true);
}
// set unique module instance names for submodules
final uniquifier = Uniquifier();
for (final module in _subModules) {
module._uniqueInstanceName = uniquifier.getUniqueName(
initialName: Sanitizer.sanitizeSV(module.name),
reserved: module.reserveName);
}
_checkValidHierarchy(visited: {});
_hasBuilt = true;
ModuleTree.rootModuleInstance = this;
}