diff --git a/examples/sy/signal_abstraction/main.cpp b/examples/sy/signal_abstraction/main.cpp new file mode 100644 index 0000000..424a6c1 --- /dev/null +++ b/examples/sy/signal_abstraction/main.cpp @@ -0,0 +1,10 @@ +#include "top.hpp" + +int sc_main(int argc, char **argv) +{ + top top1("top1"); + + sc_start(); + + return 0; +} diff --git a/examples/sy/signal_abstraction/top.hpp b/examples/sy/signal_abstraction/top.hpp new file mode 100644 index 0000000..ba8fe79 --- /dev/null +++ b/examples/sy/signal_abstraction/top.hpp @@ -0,0 +1,47 @@ +#include + +using namespace sc_core; +using namespace ForSyDe; + + +void report_func(abst_ext inp1) +{ + if (inp1.is_present()) + std::cout << "Input value: " << inp1.unsafe_from_abst_ext() << std::endl; + else + std::cout << "Input value: absent" << std::endl; +} + +void signalabst_func(abst_ext& out, const unsigned long& take, const std::vector>& inp) +{ + + + float sum = 0; + for (unsigned long i = 0; i < inp.size(); i++) + { + sum += unsafe_from_abst_ext(inp[i]); + } + out.set_val(sum/take); +} + +SC_MODULE(top) + +{ + SY::signal out_source; + SY::signal out_signalabst; + + std::vector> s1 = {36.7, 36.8, 36.7, 36.8, 36.9, 36.9, 37.0, 37.0, 37.1, 37.2, 37.3, 37.2, 37.3, 37.3, 37.4, 37.5, 37.6, 36.6}; + std::vector> s2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; + + + SC_CTOR(top) + { + std::cout< ("signalabst", 4, signalabst_func); + abstsig-> iport1 (out_source); + abstsig-> oport1(out_signalabst); + SY::make_sink("report1", report_func, out_signalabst); + } +}; + diff --git a/examples/ut/two_scenario/controller.hpp b/examples/ut/two_scenario/controller.hpp new file mode 100644 index 0000000..87fc059 --- /dev/null +++ b/examples/ut/two_scenario/controller.hpp @@ -0,0 +1,71 @@ +#ifndef CONTROLLER_HPP +#define CONTROLLER_HPP + +#include + +typedef std::function (const std::vector&)> scenrio_func; + +///!< gamma function for the zipU process of the top module +size_t gamma_func_zipa (const size_t &ca) +{ + return ca; +} + +size_t gamma_func_zipb (const size_t &ca) +{ + return 1; +} + +///& inp) +{ + + if (cur_state == 0) + next_state = 1; + else + next_state = 0; + +} + +void output_decode_detector_func( + std::vector< + std::tuple< + size_t, size_t, scenrio_func + > + >& out, const int& cur_state, const std::vector& inp +) +{ + out.resize(1); + if (cur_state == 0) + { + out[0] = std::make_tuple(3, 1, [=] (const std::vector& inp){ + std::vector out(1); + out[0] =inp[0] + inp[1] + inp[2]; + return out; + }); + } + else + { + out[0] = std::make_tuple(2, 1, [=] (const std::vector& inp){ + std::vector out(1); + out[0] =inp[1]-inp[0]; + return out; + }); + } + +} + +///& out, const std::vector,std::vector>>>& inp) +{ + out = std::get<2>(std::get<1>(inp[0])[0])(std::get<0>(inp[0])); +} + + +#endif diff --git a/examples/ut/two_scenario/main.cpp b/examples/ut/two_scenario/main.cpp new file mode 100644 index 0000000..9c84ff0 --- /dev/null +++ b/examples/ut/two_scenario/main.cpp @@ -0,0 +1,12 @@ +#include "top.hpp" + +int sc_main(int argc, char **argv) +{ + top top1("top1"); + + sc_start(); + + return 0; +} + + diff --git a/examples/ut/two_scenario/ramp.hpp b/examples/ut/two_scenario/ramp.hpp new file mode 100644 index 0000000..f1cae9a --- /dev/null +++ b/examples/ut/two_scenario/ramp.hpp @@ -0,0 +1,14 @@ + +#ifndef RAMP_HPP +#define RAMP_HPP + +#include + +using namespace ForSyDe; + +void ramp_func(int& out1, const int& inp1) +{ + out1 = inp1 + 1; +} + +#endif diff --git a/examples/ut/two_scenario/report.hpp b/examples/ut/two_scenario/report.hpp new file mode 100644 index 0000000..7aa4c18 --- /dev/null +++ b/examples/ut/two_scenario/report.hpp @@ -0,0 +1,14 @@ +#ifndef REPORT_HPP +#define REPORT_HPP + +#include +#include + +using namespace ForSyDe; + +void report_func(const int& inp1) +{ + std::cout << "output value: " << inp1 << std::endl; +} + +#endif diff --git a/examples/ut/two_scenario/top.hpp b/examples/ut/two_scenario/top.hpp new file mode 100644 index 0000000..35330ba --- /dev/null +++ b/examples/ut/two_scenario/top.hpp @@ -0,0 +1,62 @@ +#include +#include "report.hpp" +#include "ramp.hpp" +#include "controller.hpp" + +using namespace sc_core; +using namespace ForSyDe; + + +SC_MODULE(top) +{ + UT::signal from_source, from_constant, from_kernels; + UT::signal zip_control; + UT::signal,std::vector>>> from_zip; + UT::signal> from_detector, from_detector2; + + SC_CTOR(top) + { + + UT::make_source("ramp1", ramp_func, 1, 20, from_source); + + UT::make_constant("constant1", 1, 0, from_constant); + auto detector = UT::make_mealy("detector", + gamma_detector_func, + next_state_detector_func, + output_decode_detector_func, + 0, + from_detector, + from_constant + ); + + detector->oport1(from_detector2); + + UT::make_comb("cextract",[](std::vector& out,const std::vector>& inp){ + out.resize(1); + out[0] = std::get<0>(inp[0]); + }, 1, zip_control, from_detector2); + + /// -> Without using helper + + // auto zipU1 = new UT::zipU , size_t>("zipU1", gamma_func_zipa, gamma_func_zipb); + // zipU1->iport1 (from_source); + // zipU1->iport2 (from_detector); + // zipU1->controlport (zip_control); + // zipU1->oport1 (from_zip); + + + // -> using helper + + UT::make_zipU("zipU1", gamma_func_zipa, gamma_func_zipb, from_zip, from_source, from_detector, zip_control); + UT::make_comb ("kernels", + kernel_func, + 1, + from_kernels, + from_zip + ); + + UT::make_sink("sink", report_func, from_kernels); + } + +}; + diff --git a/src/forsyde/sy_process_constructors.hpp b/src/forsyde/sy_process_constructors.hpp index 6afb2e3..dd3d2c6 100644 --- a/src/forsyde/sy_process_constructors.hpp +++ b/src/forsyde/sy_process_constructors.hpp @@ -2112,6 +2112,96 @@ class fanout : public sy_process #endif }; +template +class signalabst : public sy_process +{ +public: + typedef std::function&, const unsigned long&, const std::vector>&)> functype; + + SY_in iport1; ///< port for the input channel + SY_out oport1; ///< port for the output channel + + signalabst(const sc_module_name& _name, + const unsigned long& take_samples, functype _func + ) : sy_process(_name), take_samples(take_samples), _func(_func) + { +#ifdef FORSYDE_INTROSPECTION + + +#endif + } + + //! Specifying from which process constructor is the module built + std::string forsyde_kind() const {return "SY::signalabst";} + +private: + + abst_ext* ival1; + abst_ext* oval1; + std::vector>* ivals; + unsigned long take_samples; + functype _func; + int tok_cnt; + + + //Implementing the abstract semantics + void init() + { + ival1 = new abst_ext; + oval1 = new abst_ext; + ivals = new std::vector>; + tok_cnt = 0; + + + } + + void prep() + { + + *ival1 = iport1.read(); + ivals->push_back(*ival1); + tok_cnt ++; + } + + void exec() + { + if (tok_cnt == take_samples) + { + _func(*oval1, take_samples, *ivals); + tok_cnt = 0; + ivals->clear(); + } + + else + { + oval1->set_abst(); + } + + } + + void prod() + { + WRITE_MULTIPORT(oport1, abst_ext(*oval1)) + } + + void clean() + { + delete oval1; + delete ival1; + delete ivals; + } + +#ifdef FORSYDE_INTROSPECTION + void bindInfo() + { + boundInChans.resize(1); // only one input port + boundInChans[0].port = &iport1; + boundOutChans.resize(1); // only one output port + boundOutChans[0].port = &oport1; + } +#endif +}; + } } diff --git a/src/forsyde/ut_helpers.hpp b/src/forsyde/ut_helpers.hpp index 15b6106..28556ff 100644 --- a/src/forsyde/ut_helpers.hpp +++ b/src/forsyde/ut_helpers.hpp @@ -496,6 +496,36 @@ inline fanout* make_fanout(const std::string& pName, return p; } +//! Helper function to construct a zipU process +/*! This function is used to construct a zipU process (SystemC module) and + * connect its output and output signals. + * It provides a more functional style definition of a ForSyDe process. + * It also removes bilerplate code by using type-inference feature of + * C++ and automatic binding to the input FIFOs. + */ + +template class I1If, + class T2, template class I2If, + class TCS, template class I3If, + template class OIf> +inline zipU* make_zipU(const std::string& pName, + const typename zipU::gamma_functype& _gamma_func_a, + const typename zipU::gamma_functype& _gamma_func_b, + OIf,std::vector>>& outS, + I1If& inp1S, + I2If& inp2S, + I3If& inp3S + ) +{ + auto p = new zipU(pName.c_str(), _gamma_func_a, _gamma_func_b); + + (*p).iport1(inp1S); + (*p).iport2(inp2S); + (*p).controlport(inp3S); + (*p).oport1(outS); + + return p; +} } } diff --git a/src/forsyde/ut_process_constructors.hpp b/src/forsyde/ut_process_constructors.hpp index e059433..834055a 100644 --- a/src/forsyde/ut_process_constructors.hpp +++ b/src/forsyde/ut_process_constructors.hpp @@ -1741,6 +1741,87 @@ class fanout : public ut_process #endif }; +//! The zipU process with two inputs and one output +/*! This process "zips" the incoming two signals into one signal of tuples with using control signal + */ + +template +class zipU : public ut_process +{ +public: + UT_in iport1; ///< port for the input channel 1 + UT_in iport2; ///< port for the input channel 2 + UT_in controlport; ///< port for the control signal + UT_out,std::vector>> oport1; ///< port for the output channel + + typedef std::function gamma_functype; + + + //! The constructor requires the module name + /*! It creates an SC_THREAD which reads data from its input port, + * zips them together and writes the results using the output port + */ + zipU(const sc_module_name& _name, + const gamma_functype& _gamma_func_a, + const gamma_functype& _gamma_func_b + ) : ut_process(_name), iport1("iport1"), iport2("iport2"), controlport("controlport"), oport1("oport1"), + _gamma_func_a(_gamma_func_a), _gamma_func_b(_gamma_func_b) + { } + + //! Specifying from which process constructor is the module built + std::string forsyde_kind() const {return "UT::zipU";} + +private: + + gamma_functype _gamma_func_a, _gamma_func_b; + + // intermediate values + std::vector i1vals; + std::vector i2vals; + TCS control_tkn; + + void init() + { + + } + + void prep() + { + control_tkn = controlport.read(); + size_t c1 = _gamma_func_a(control_tkn); + size_t c2 = _gamma_func_b(control_tkn); + + i1vals.resize(c1); + i2vals.resize(c2); + + for (auto it=i1vals.begin();it!=i1vals.end();it++) + *it = iport1.read(); + for (auto it=i2vals.begin();it!=i2vals.end();it++) + *it = iport2.read(); + } + + void exec() {} + + void prod() + { + WRITE_MULTIPORT(oport1,std::make_tuple(i1vals,i2vals)) // write to the output + } + + void clean() {} + +#ifdef FORSYDE_INTROSPECTION + void bindInfo() + { + boundInChans.resize(2); // two input ports + boundInChans[0].port = &iport1; + boundInChans[1].port = &iport2; + boundOutChans.resize(1); // only one output port + boundOutChans[0].port = &oport1; + } +#endif +}; + + } }