|
@@ -0,0 +1,352 @@
|
|
|
|
+/**
|
|
|
|
+ * @file tests/fddevs/models.hpp
|
|
|
|
+ * @author The ARTIS Development Team
|
|
|
|
+ * See the AUTHORS or Authors.txt file
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * ARTIS - the multimodeling and simulation environment
|
|
|
|
+ * This file is a part of the ARTIS environment
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2013-2019 ULCO http://www.univ-littoral.fr
|
|
|
|
+ *
|
|
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
|
|
+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
|
+ * (at your option) any later version.
|
|
|
|
+ *
|
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
+ * GNU General Public License for more details.
|
|
|
|
+ *
|
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#ifndef TESTS_FDDEVS_MODELS_HPP
|
|
|
|
+#define TESTS_FDDEVS_MODELS_HPP
|
|
|
|
+
|
|
|
|
+#include <artis-star/common/time/DoubleTime.hpp>
|
|
|
|
+#include <artis-star/common/utils/Trace.hpp>
|
|
|
|
+
|
|
|
|
+#include <artis-star/kernel/fddevs/Dynamics.hpp>
|
|
|
|
+
|
|
|
|
+namespace artis {
|
|
|
|
+ namespace tests {
|
|
|
|
+ namespace fddevs {
|
|
|
|
+
|
|
|
|
+ enum CRC_state_values {
|
|
|
|
+ I0 = 0, I1, G, GR, WW, W, DW
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ class CRC : public artis::fddevs::Dynamics<common::DoubleTime, CRC, CRC_state_values> {
|
|
|
|
+ public:
|
|
|
|
+ enum inputs {
|
|
|
|
+ IN_P
|
|
|
|
+ };
|
|
|
|
+ enum outputs {
|
|
|
|
+ OUT_G, OUT_W
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ CRC(const std::string& name,
|
|
|
|
+ const artis::fddevs::Context<common::DoubleTime, CRC, artis::common::NoParameters>& context)
|
|
|
|
+ :
|
|
|
|
+ artis::fddevs::Dynamics<common::DoubleTime, CRC, CRC_state_values>(name,
|
|
|
|
+ context)
|
|
|
|
+ {
|
|
|
|
+ input_ports({{IN_P, "p"}});
|
|
|
|
+ output_ports({{OUT_G, "g"},
|
|
|
|
+ {OUT_W, "w"}});
|
|
|
|
+
|
|
|
|
+ initial_state(I0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ~CRC() override = default;
|
|
|
|
+
|
|
|
|
+ void delta_tau(typename common::DoubleTime::type /* t */) override
|
|
|
|
+ {
|
|
|
|
+ switch (state()) {
|
|
|
|
+ case I0: {
|
|
|
|
+ state(I1);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case I1: {
|
|
|
|
+ state(G);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case G: {
|
|
|
|
+ state(G);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case GR: {
|
|
|
|
+ state(WW);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case WW: {
|
|
|
|
+ state(W);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case W: {
|
|
|
|
+ state(DW);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case DW: {
|
|
|
|
+ state(G);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void
|
|
|
|
+ delta_x(typename common::DoubleTime::type /* t */,
|
|
|
|
+ typename common::DoubleTime::type /* e */,
|
|
|
|
+ const common::Bag<common::DoubleTime>& bag) override
|
|
|
|
+ {
|
|
|
|
+ assert(bag.size() == 1);
|
|
|
|
+
|
|
|
|
+ if (bag.at(0).on_port(IN_P) and state() == G) {
|
|
|
|
+ state(GR);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ common::Bag<common::DoubleTime>
|
|
|
|
+ lambda(typename common::DoubleTime::type /* t */) const override
|
|
|
|
+ {
|
|
|
|
+ common::Bag<common::DoubleTime> msgs;
|
|
|
|
+
|
|
|
|
+ switch (state()) {
|
|
|
|
+ case I0:
|
|
|
|
+ msgs.push_back(
|
|
|
|
+ artis::common::ExternalEvent<common::DoubleTime>(OUT_W, 0));
|
|
|
|
+ break;
|
|
|
|
+ case I1:
|
|
|
|
+ msgs.push_back(
|
|
|
|
+ artis::common::ExternalEvent<common::DoubleTime>(OUT_G, 1));
|
|
|
|
+ break;
|
|
|
|
+ case G:
|
|
|
|
+ break;
|
|
|
|
+ case GR:
|
|
|
|
+ msgs.push_back(
|
|
|
|
+ artis::common::ExternalEvent<common::DoubleTime>(OUT_G, 0));
|
|
|
|
+ break;
|
|
|
|
+ case WW:
|
|
|
|
+ msgs.push_back(
|
|
|
|
+ artis::common::ExternalEvent<common::DoubleTime>(OUT_W, 1));
|
|
|
|
+ break;
|
|
|
|
+ case W:
|
|
|
|
+ msgs.push_back(
|
|
|
|
+ artis::common::ExternalEvent<common::DoubleTime>(OUT_W, 0));
|
|
|
|
+ break;
|
|
|
|
+ case DW:
|
|
|
|
+ msgs.push_back(
|
|
|
|
+ artis::common::ExternalEvent<common::DoubleTime>(OUT_G, 1));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return msgs;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool rho(typename common::DoubleTime::type /* time */,
|
|
|
|
+ const common::Bag<common::DoubleTime>& bag) const override
|
|
|
|
+ {
|
|
|
|
+ return state() == G and bag.at(0).on_port(IN_P);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ typename common::DoubleTime::type
|
|
|
|
+ tau(typename common::DoubleTime::type /* t */) const override
|
|
|
|
+ {
|
|
|
|
+ switch (state()) {
|
|
|
|
+ case I0:
|
|
|
|
+ return 0;
|
|
|
|
+ case I1:
|
|
|
|
+ return 0;
|
|
|
|
+ case G:
|
|
|
|
+ return 10;
|
|
|
|
+ case GR:
|
|
|
|
+ return 5;
|
|
|
|
+ case WW:
|
|
|
|
+ return 2;
|
|
|
|
+ case W:
|
|
|
|
+ return 26;
|
|
|
|
+ case DW:
|
|
|
|
+ return 2;
|
|
|
|
+ }
|
|
|
|
+ return common::DoubleTime::infinity;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ enum MXR_state_values {
|
|
|
|
+ A00 = 0, A01, A10, A11, R11
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ class MXR : public artis::fddevs::Dynamics<common::DoubleTime, MXR, MXR_state_values> {
|
|
|
|
+ public:
|
|
|
|
+ enum inputs {
|
|
|
|
+ IN_A, IN_B
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ MXR(const std::string& name,
|
|
|
|
+ const artis::fddevs::Context<common::DoubleTime, MXR, artis::common::NoParameters>& context)
|
|
|
|
+ :
|
|
|
|
+ artis::fddevs::Dynamics<common::DoubleTime, MXR, MXR_state_values>(name,
|
|
|
|
+ context)
|
|
|
|
+ {
|
|
|
|
+ input_ports({{IN_A, "a"},
|
|
|
|
+ {IN_B, "b"}});
|
|
|
|
+ initial_state(A00);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ~MXR() override = default;
|
|
|
|
+
|
|
|
|
+ void delta_tau(typename common::DoubleTime::type /* t */) override
|
|
|
|
+ {
|
|
|
|
+ if (state() == A11) { state(R11); }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void
|
|
|
|
+ delta_x(typename common::DoubleTime::type /* t */,
|
|
|
|
+ typename common::DoubleTime::type /* e */,
|
|
|
|
+ const common::Bag<common::DoubleTime>& bag) override
|
|
|
|
+ {
|
|
|
|
+ std::for_each(bag.begin(), bag.end(),
|
|
|
|
+ [this](const artis::common::ExternalEvent<common::DoubleTime>& e) {
|
|
|
|
+ int data;
|
|
|
|
+
|
|
|
|
+ e.data()(data);
|
|
|
|
+ if (e.on_port(IN_A)) {
|
|
|
|
+ switch (state()) {
|
|
|
|
+ case A00: {
|
|
|
|
+ if (data == 1) { state(A01); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case A01: {
|
|
|
|
+ if (data == 0) { state(A00); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case A10: {
|
|
|
|
+ if (data == 1) { state(A11); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case A11: {
|
|
|
|
+ if (data == 0) { state(A10); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case R11:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ } else if (e.on_port(IN_B)) {
|
|
|
|
+ switch (state()) {
|
|
|
|
+ case A00: {
|
|
|
|
+ if (data == 1) { state(A10); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case A01: {
|
|
|
|
+ if (data == 1) { state(A11); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case A10: {
|
|
|
|
+ if (data == 0) { state(A00); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case A11: {
|
|
|
|
+ if (data == 0) { state(A01); }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case R11:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ common::Bag<common::DoubleTime>
|
|
|
|
+ lambda(typename common::DoubleTime::type /* t */) const override
|
|
|
|
+ {
|
|
|
|
+ common::Bag<common::DoubleTime> msgs;
|
|
|
|
+
|
|
|
|
+ return msgs;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool rho(typename common::DoubleTime::type /* time */,
|
|
|
|
+ const common::Bag<common::DoubleTime>& /* bag */) const override
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ typename common::DoubleTime::type
|
|
|
|
+ tau(typename common::DoubleTime::type /* t */) const override
|
|
|
|
+ {
|
|
|
|
+ if (state() == A11) { return 0.01; }
|
|
|
|
+ else { return common::DoubleTime::infinity; }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ enum Beep_state_values {
|
|
|
|
+ INIT = 0, SEND
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ class Beep
|
|
|
|
+ : public artis::fddevs::Dynamics<common::DoubleTime, Beep, Beep_state_values> {
|
|
|
|
+ public:
|
|
|
|
+ enum outputs {
|
|
|
|
+ OUT_P
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ Beep(const std::string& name,
|
|
|
|
+ const artis::fddevs::Context<common::DoubleTime, Beep, artis::common::NoParameters>& context)
|
|
|
|
+ :
|
|
|
|
+ artis::fddevs::Dynamics<common::DoubleTime, Beep, Beep_state_values>(name,
|
|
|
|
+ context)
|
|
|
|
+ {
|
|
|
|
+ output_ports({{OUT_P, "p"}});
|
|
|
|
+
|
|
|
|
+ initial_state(INIT);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ~Beep() override = default;
|
|
|
|
+
|
|
|
|
+ void delta_tau(typename common::DoubleTime::type /* t */) override
|
|
|
|
+ {
|
|
|
|
+ if (state() == INIT) { state(SEND); }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ common::Bag<common::DoubleTime>
|
|
|
|
+ lambda(typename common::DoubleTime::type /* t */) const override
|
|
|
|
+ {
|
|
|
|
+ common::Bag<common::DoubleTime> msgs;
|
|
|
|
+
|
|
|
|
+ switch (state()) {
|
|
|
|
+ case INIT:
|
|
|
|
+ msgs.push_back(
|
|
|
|
+ artis::common::ExternalEvent<common::DoubleTime>(OUT_P, 1));
|
|
|
|
+ break;
|
|
|
|
+ case SEND:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return msgs;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool rho(typename common::DoubleTime::type /* time */,
|
|
|
|
+ const common::Bag<common::DoubleTime>& /* bag */) const override
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ typename common::DoubleTime::type
|
|
|
|
+ tau(typename common::DoubleTime::type /* t */) const override
|
|
|
|
+ {
|
|
|
|
+ switch (state()) {
|
|
|
|
+ case INIT:
|
|
|
|
+ return 27;
|
|
|
|
+ case SEND:
|
|
|
|
+ return common::DoubleTime::infinity;
|
|
|
|
+ }
|
|
|
|
+ return common::DoubleTime::infinity;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+} // namespace artis tests fddevs
|
|
|
|
+
|
|
|
|
+#endif
|