Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/guided_examples/1_FirstModule_and_SimoSim/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# FirstModule SimoSim

## Introduction
The documents highlights some location in the source of [FirstModule.cc](./FirstModule.cc)
The document highlights some location in the source of [FirstModule.cc](./FirstModule.cc)
to better understand how to write your own `Module` class and how to use it
in `SimoSim`, a general purpose executable to run simulations.

Expand Down
14 changes: 14 additions & 0 deletions docs/guided_examples/1_FirstModule_and_SimoSim/system_config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# Copyright 2026 Matteo Fusi and Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# List all modules in the modules section
modules:
# This is the module of the tutorial
Expand Down
71 changes: 71 additions & 0 deletions docs/guided_examples/2_Ports_and_SimoSim/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Ports and SimoSimo

# Introduction

This document explains basic principle of ports of `Simo` and how to use them
in `SimoSim`.


# Connecting Modules with ports

Ports allow to create connections between modules. The class `Simo::Port` is a
templated class and it is the base class. Any protocol can be built on top of it.
To create a new port class, it is required to implement is the `bool connect(Port* other)`
method in the subclass. This method is called when two ports are connected together
and this is what `SimoSim` uses to connect the ports.

Some templated implementations are already provided in the library to ease integration:
- `Simo::InPort<T>`: Allows to receive a payload of type `T`. It connects to a `Simo::OutPort<T>`
- `Simo::OutPort<T>`: Allows to send a payload of type `T`. It connects to a `Simo::InPort<T>`
- `Simo::BidirectionalPortTyped<OutPayload, InPayload>`: Allows to send a payload of type `OutPayload` and receive a payload of type `InPayload`.
It connects to another `Simo::BidirectionalPortTyped<InPayload, OutPayload>` (notice that
`OutPayload` and `InPayload` are swapped).
- `Simo::BidirectionalPort<T>`: It is an alias for `Simo::BidirectionalPortTyped<T, T>`.
It is a good general-purpose port in case bidirectional communication is needed of
the same payload type.

Look at `Simo/port/Port.h` for the implementation of these classes. Here below a
recap of the methods that `Simo::BidirectionalPort<T>` provides:
```text
+------------------------------------+
| [Port A] |
| - send_out / clear_out works on X |
| - receive_in / clear_in works X |
+------------------------------------+
| ^
| X goes | Y goes
| from A | from B
| to B | to A
v |
+------------------------------------+
| [Port B] |
| - receive_in / clear_in works X |
| - send_out / clear_out works on Y |
+------------------------------------+
```

No specific protocol is enforced and both sides of the port can remove the payload
anytime. This is a design choice to allow more flexibility.

# Connecting ports in SimoSim

The configuration file of `SimoSim` allows to connect using the `connections` section.
Look at [system_config.yaml](./system_config.yaml) for an example:

```yaml
connections:
- ping_module/port: pong_module/port
```

Here `ping_module` and `pong_module` both expose a port named `port`, and these
two are connected together. Look at `tests/collection/PingPongCollection.cc` for
the implementation of these modules and how the ports are defined. Inside a module,
a port can be created with the `Simo::Module::create_port<{Port-Class}>({port_name})`
method.

To run this example, you need the `PingPongCollection`. This is built by default
when Simo is built. To run the example, use the following command:

```bash
SimoSim --config <EXAMPLE_PATH>/system_config.yaml --search-path <SIMO_BUILD_PATH>
```
49 changes: 49 additions & 0 deletions docs/guided_examples/2_Ports_and_SimoSim/system_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright 2026 Matteo Fusi and Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Simple example to demonstrate ports
modules:
- name: ping_module
type: ping
parameters:
- name: period
value:
time: 10
unit: PS
- name: pong_module
type: pong
parameters:
- name: period
value:
time: 10
unit: PS
- name: log_level
value: INFO
- name: collector
type: collector
parameters:
- name: start_time
value:
time: 0
unit: NS
- name: end_time
value:
time: 100
unit: NS
connections:
- ping_module/port: pong_module/port
simulation:
time:
time: 100
unit: NS
5 changes: 5 additions & 0 deletions docs/guided_examples/build_all_examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ BUILD_TYPE="Debug"

while IFS= read -r -d '' dir
do
if [[ ! -f "$dir/CMakeLists.txt" ]]; then
echo "Skipping $dir: no CMakeLists.txt"
continue
fi

pushd "$dir" > /dev/null || exit
echo "Building example in $dir"
cmake -B ./build "-DCMAKE_BUILD_TYPE=$BUILD_TYPE"
Expand Down
5 changes: 5 additions & 0 deletions include/Simo/module/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ class SIMO_PUBLIC Module {

[[nodiscard]] std::string_view name() const;

[[nodiscard]] constexpr std::string name_of_child(
const std::string_view child) const {
return name_ + "/" + std::string(child);
}

[[nodiscard]] Context& sim_ctx() const;

virtual ~Module() {}
Expand Down
4 changes: 3 additions & 1 deletion src/SimoSim/SimoSim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ int main(const int argc, char* argv[]) {
if (verbosity >= 3) {
std::cout << "Detected modules:\n";
for (const auto& type : factory_map | std::views::keys) {
std::cerr << type << "\n";
std::cout << type << "\n";
}
}

Expand Down Expand Up @@ -233,7 +233,9 @@ int main(const int argc, char* argv[]) {
}
}

std::cout << "Starting simulation of " << cfg.simulation.time << "\n";
ctx.run_at(cfg.simulation.time);
std::cout << "Simulation completed\n";
Simo::Log::Logger::flush_all_sinks();

return SUCCESS;
Expand Down
10 changes: 10 additions & 0 deletions tests/module/ModuleTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,13 @@ BOOST_AUTO_TEST_CASE(StdoutLogSetupEnablesLogger) {
BOOST_CHECK(status.success());
BOOST_CHECK_EQUAL(logger.enabled(), true);
}

BOOST_AUTO_TEST_CASE(NameOfChild) {
Simo::Context ctx;
Simo::Parameters p;
Simo::Module m;
p.name("root");
const auto status = m.initialize(ctx, p);
auto child_name = m.name_of_child("child");
BOOST_CHECK_EQUAL(child_name, "root/child");
}