Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Applications

This chapter gives an overview of how to write a top-level application.

Create the Engine

The first thing to do is to create a simulation Engine:

use gwr_engine::engine::Engine;
fn main() {
#[allow(unused_variables, unused_mut)]
let mut engine = Engine::default();
}

The engine provides the top-level entity for the simulation that must be used as the parent to top-level components.

Instantiate Components

Then simulation components can be created. An example of a very basic simulation is to create a data Source and Sink.

In this case the Source is configured to emit the value 0x123 ten times:

use gwr_components::source::Source;
use gwr_components::sink::Sink;
use gwr_components::{connect_port, option_box_repeat};
use gwr_engine::engine::Engine;
fn main() {
let mut engine = Engine::default();
let clock = engine.default_clock();
let source = Source::new_and_register(&engine, engine.top(), "source", option_box_repeat!(0x123 ; 10));
let sink = Sink::new_and_register(&engine, &clock, engine.top(), "sink");
connect_port!(source, tx => sink, rx)
    .expect("should be able to connect `Source` to `Sink`");
}
use gwr_components::source::Source;
use gwr_components::sink::Sink;
use gwr_components::{connect_port, option_box_repeat};
use gwr_engine::engine::Engine;
fn main() {
let mut engine = Engine::default();
let clock = engine.default_clock();
let source = Source::new_and_register(&engine, engine.top(), "source", option_box_repeat!(0x123 ; 10));
let sink = Sink::new_and_register(&engine, &clock, engine.top(), "sink");
connect_port!(source, tx => sink, rx)
    .expect("should be able to connect `Source` to `Sink`");
}

Connect Components

Ports are connected together using the helper connect_port! macro. The connections are always done in the direction of data flow tx -> rx.

use gwr_components::source::Source;
use gwr_components::sink::Sink;
use gwr_components::{connect_port, option_box_repeat};
use gwr_engine::engine::Engine;
fn main() {
let mut engine = Engine::default();
let clock = engine.default_clock();
let source = Source::new_and_register(&engine, engine.top(), "source", option_box_repeat!(0x123 ; 10));
let sink = Sink::new_and_register(&engine, &clock, engine.top(), "sink");
connect_port!(source, tx => sink, rx)
    .expect("should be able to connect `Source` to `Sink`");
}

Run Simulation

Now that everything has been created and connected the simulation can be run using the run_simulation! macro:

use gwr_components::source::Source;
use gwr_components::sink::Sink;
use gwr_components::{connect_port, option_box_repeat};
use gwr_engine::engine::Engine;
use gwr_engine::run_simulation;
fn main() {
let mut engine = Engine::default();
let clock = engine.default_clock();
let source = Source::new_and_register(&engine, engine.top(), "source", option_box_repeat!(0x123 ; 10));
let sink = Sink::new_and_register(&engine, &clock, engine.top(), "sink");
connect_port!(source, tx => sink, rx)
    .expect("should be able to connect `Source` to `Sink`");
run_simulation!(engine);
}

The run_simulation! spawns the components specified and then starts then runs the engine to completion.

Check Results

So, after the simulation has completed it is possible to check that the Sink has received all the expected data.

use gwr_components::source::Source;
use gwr_components::sink::Sink;
use gwr_components::{connect_port, option_box_repeat};
use gwr_engine::engine::Engine;
use gwr_engine::run_simulation;
fn main() {
let mut engine = Engine::default();
let clock = engine.default_clock();
let source = Source::new_and_register(&engine, engine.top(), "source", option_box_repeat!(0x123 ; 10));
let sink = Sink::new_and_register(&engine, &clock, engine.top(), "sink");
connect_port!(source, tx => sink, rx)
    .expect("should be able to connect `Source` to `Sink`");
run_simulation!(engine);
assert_eq!(sink.num_sunk(), 10);
}

Full Source

The entire example (including the use statements that are required to pull in the dependencies) looks like this:

use gwr_components::source::Source;
use gwr_components::sink::Sink;
use gwr_components::{connect_port, option_box_repeat};
use gwr_engine::engine::Engine;
use gwr_engine::run_simulation;

fn main() {
    let mut engine = Engine::default();
    let clock = engine.default_clock();
    let source = Source::new_and_register(&engine, engine.top(), "source", option_box_repeat!(0x123 ; 10));
    let sink = Sink::new_and_register(&engine, &clock, engine.top(), "sink");
    connect_port!(source, tx => sink, rx)
        .expect("should be able to connect `Source` to `Sink`");
    run_simulation!(engine);
    assert_eq!(sink.num_sunk(), 10);
}