Changeset 29


Ignore:
Timestamp:
02/17/12 10:38:41 (6 years ago)
Author:
shan2
Message:

ForSyDe-SystemC/CoMPSoC: added priliminary support for interospection of port types, improved the generated source files.

Location:
ForSyDe-SystemC/branches/CoMPSoC/src/forsyde
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • ForSyDe-SystemC/branches/CoMPSoC/src/forsyde/sdfmoc.hpp

    r27 r29  
    5151    unsigned toks; 
    5252    std::vector<sc_object*> boundChans; 
     53    std::string portType; 
    5354}; 
    5455 
     
    181182        boundInChans[0].port = &iport; 
    182183        boundInChans[0].toks = itoks[0]; 
     184        boundInChans[0].portType = typeid(ITYP).name(); 
    183185        boundOutChans.resize(1);    // only one output port 
    184186        boundOutChans[0].port = &oport; 
    185187        boundOutChans[0].toks = otoks[0]; 
     188        boundOutChans[0].portType = typeid(OTYP).name(); 
    186189        for (int i=0;i<iport.size();i++) 
    187190            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
     
    258261        boundInChans[0].port = &iport1; 
    259262        boundInChans[0].toks = itoks[0]; 
     263        boundInChans[0].portType = typeid(I1TYP).name(); 
    260264        boundInChans[1].port = &iport2; 
    261265        boundInChans[1].toks = itoks[1]; 
     266        boundInChans[1].portType = typeid(I2TYP).name(); 
    262267        boundOutChans.resize(1);    // only one output port 
    263268        boundOutChans[0].port = &oport; 
    264269        boundOutChans[0].toks = otoks[0]; 
     270        boundOutChans[0].portType = typeid(OTYP).name(); 
    265271        for (int i=0;i<iport1.size();i++) 
    266272            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport1[i])); 
     
    340346        boundInChans[0].port = &iport1; 
    341347        boundInChans[0].toks = itoks[0]; 
     348        boundInChans[0].portType = typeid(I1TYP).name(); 
    342349        boundInChans[1].port = &iport2; 
    343350        boundInChans[1].toks = itoks[1]; 
     351        boundInChans[1].portType = typeid(I2TYP).name(); 
    344352        boundInChans[2].port = &iport3; 
    345353        boundInChans[2].toks = itoks[2]; 
     354        boundInChans[2].portType = typeid(I3TYP).name(); 
    346355        boundOutChans.resize(1);    // only one output port 
    347356        boundOutChans[0].port = &oport; 
    348357        boundOutChans[0].toks = otoks[0]; 
     358        boundOutChans[0].portType = typeid(OTYP).name(); 
    349359        for (int i=0;i<iport1.size();i++) 
    350360            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport1[i])); 
     
    430440        boundInChans[0].port = &iport1; 
    431441        boundInChans[0].toks = itoks[0]; 
     442        boundInChans[0].portType = typeid(I1TYP).name(); 
    432443        boundInChans[1].port = &iport2; 
    433444        boundInChans[1].toks = itoks[1]; 
     445        boundInChans[1].portType = typeid(I2TYP).name(); 
    434446        boundInChans[2].port = &iport3; 
    435447        boundInChans[2].toks = itoks[2]; 
     448        boundInChans[2].portType = typeid(I3TYP).name(); 
    436449        boundInChans[3].port = &iport4; 
    437450        boundInChans[3].toks = itoks[3]; 
     451        boundInChans[3].portType = typeid(I4TYP).name(); 
    438452        boundOutChans.resize(1);    // only one output port 
    439453        boundOutChans[0].port = &oport; 
    440454        boundOutChans[0].toks = otoks[0]; 
     455        boundOutChans[0].portType = typeid(OTYP).name(); 
    441456        for (int i=0;i<iport1.size();i++) 
    442457            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport1[i])); 
     
    507522        boundInChans[0].port = &iport; 
    508523        boundInChans[0].toks = 1; 
     524        boundInChans[0].portType = typeid(IOTYP).name(); 
    509525        boundOutChans.resize(1);    // only one output port 
    510526        boundOutChans[0].port = &oport; 
    511527        boundOutChans[0].toks = 1; 
     528        boundOutChans[0].portType = typeid(IOTYP).name(); 
    512529        for (int i=0;i<iport.size();i++) 
    513530            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
     
    563580            in_val = iport.read();  // read from input 
    564581            WRITE_MULTIPORT(oport,in_val);    // write to the output 
     582        } 
     583    } 
     584     
     585    void bindInfo() 
     586    { 
     587        boundInChans.resize(1);     // only one input ports 
     588        boundInChans[0].port = &iport; 
     589        boundInChans[0].toks = 1; 
     590        boundInChans[0].portType = typeid(IOTYP).name(); 
     591        boundOutChans.resize(1);    // only one output port 
     592        boundOutChans[0].port = &oport; 
     593        boundOutChans[0].toks = 1; 
     594        boundOutChans[0].portType = typeid(IOTYP).name(); 
     595        for (int i=0;i<iport.size();i++) 
     596            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
     597        for (int i=0;i<oport.size();i++) 
     598            boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
     599    } 
     600}; 
     601 
     602//! Process constructor for a constant source process 
     603/*! This class is used to build a souce process with constant output. 
     604 * Its main purpose is to be used in test-benches. 
     605 *  
     606 * This class can directly be instantiated to build a process. 
     607 */ 
     608template <class OTYP> 
     609class constant : public process 
     610{ 
     611public: 
     612    sc_fifo_out<OTYP> oport;     ///< port for the output channel 
     613 
     614    //! The constructor requires the module name 
     615    /*! It creates an SC_THREAD which runs the user-imlpemented function 
     616     * and writes the result using the output port 
     617     */ 
     618    constant(sc_module_name _name, 
     619             OTYP val 
     620            ):process(_name), cval(val) 
     621    { 
     622         
     623    } 
     624     
     625    std::string ForSyDe_kind() {return "SDF::constant";}; 
     626     
     627    OTYP cval; 
     628     
     629private: 
     630 
     631    //! The main and only execution thread of the module 
     632    void worker() 
     633    { 
     634        while (1) 
     635        { 
     636            WRITE_MULTIPORT(oport,cval);    // write to the output 
     637        } 
     638    } 
     639     
     640    void bindInfo() 
     641    { 
     642        boundOutChans.resize(1);    // only one output port 
     643        boundOutChans[0].port = &oport; 
     644        boundOutChans[0].toks = 1; 
     645        boundOutChans[0].portType = typeid(OTYP).name(); 
     646        for (int i=0;i<oport.size();i++) 
     647            boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
     648    } 
     649}; 
     650 
     651//! Process constructor for a source process 
     652/*! This class is used to build a souce process which only has an output. 
     653 * Given an initial state and a function, the process repeatedly applies 
     654 * the function to the current state to produce next state, which is 
     655 * also the process output. It can be used in test-benches. 
     656 *  
     657 * Note that this is an abstract class and can not be directly 
     658 * instantiated. The designer should derive from this class and 
     659 * implement the _func function which is run on each evaluation cycle to 
     660 * produce an output. 
     661 */ 
     662template <class OTYP> 
     663class source : public process 
     664{ 
     665public: 
     666    sc_fifo_out<OTYP> oport;     ///< port for the output channel 
     667 
     668    //! The constructor requires the module name 
     669    /*! It creates an SC_THREAD which runs the user-imlpemented function 
     670     * and writes the result using the output port 
     671     */ 
     672    source(sc_module_name _name,   ///< The module name 
     673             OTYP ist                ///< Initial state 
     674          ):process(_name), init_st(ist) 
     675    { 
     676         
     677    } 
     678     
     679    std::string ForSyDe_kind() {return "SDF::source";}; 
     680     
     681    OTYP init_st; 
     682     
     683private: 
     684 
     685    //! The main and only execution thread of the module 
     686    void worker() 
     687    { 
     688        OTYP curst_val = init_st, nxst_val; 
     689        WRITE_MULTIPORT(oport,curst_val);      // write the initial state 
     690        while (1) 
     691        { 
     692            _func(nxst_val, curst_val);        // produce a new value 
     693            curst_val = nxst_val; 
     694            WRITE_MULTIPORT(oport,curst_val);  // write to the output 
     695        } 
     696    } 
     697     
     698    void bindInfo() 
     699    { 
     700        boundOutChans.resize(1);    // only one output port 
     701        boundOutChans[0].port = &oport; 
     702        boundOutChans[0].toks = 1; 
     703        boundOutChans[0].portType = typeid(OTYP).name(); 
     704        for (int i=0;i<oport.size();i++) 
     705            boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
     706    } 
     707 
     708protected: 
     709    //! The main caclulation function 
     710    /*! It is abstract and the user should provide an implementation for 
     711     * it in the derived class. 
     712     */ 
     713    virtual void (_func)(OTYP&, const OTYP&) = 0; 
     714}; 
     715 
     716//! Process constructor for a source process with vector input 
     717/*! This class is used to build a souce process which only has an output. 
     718 * Given the test bench vector, the process iterates over the emenets 
     719 * of the vector and outputs one value on each evaluation cycle. 
     720 */ 
     721template <class OTYP> 
     722class vsource : public process 
     723{ 
     724public: 
     725    sc_fifo_out<OTYP> oport;     ///< port for the output channel 
     726 
     727    //! The constructor requires the module name 
     728    /*! It creates an SC_THREAD which writes the result using the output 
     729     * port. 
     730     */ 
     731    vsource(sc_module_name _name,           ///< The module name 
     732            const std::vector<OTYP>& invec  ///< Initial vector 
     733           ):process(_name), in_vec(invec) 
     734    { 
     735         
     736    } 
     737     
     738    std::string ForSyDe_kind() {return "SDF::vsource";}; 
     739     
     740    std::vector<OTYP> in_vec; 
     741     
     742private: 
     743 
     744    //! The main and only execution thread of the module 
     745    void worker() 
     746    { 
     747        typename std::vector<OTYP>::iterator itr; 
     748        for (itr=in_vec.begin();itr!=in_vec.end();itr++) 
     749        { 
     750            OTYP out_val = *itr; 
     751            WRITE_MULTIPORT(oport,out_val);    // write to the output 
     752        } 
     753    } 
     754     
     755    void bindInfo() 
     756    { 
     757        boundOutChans.resize(1);    // only one output port 
     758        boundOutChans[0].port = &oport; 
     759        boundOutChans[0].toks = 1; 
     760        boundOutChans[0].portType = typeid(OTYP).name(); 
     761        for (int i=0;i<oport.size();i++) 
     762            boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
     763    } 
     764}; 
     765 
     766//! Process constructor for a sink process 
     767/*! This class is used to build a sink process which only has an input. 
     768 * Its main purpose is to be used in test-benches. 
     769 *  
     770 * Note that this is an abstract class and can not be directly 
     771 * instantiated. The designer should derive from this class and 
     772 * implement the _func function which is run in each evaluation cycle on 
     773 * the received input. 
     774 */ 
     775template <class ITYP> 
     776class sink : public process 
     777{ 
     778public: 
     779    sc_fifo_in<ITYP> iport;         ///< port for the input channel 
     780 
     781    //! The constructor requires the module name 
     782    /*! It creates an SC_THREAD which runs the user-imlpemented function 
     783     * in each cycle. 
     784     */ 
     785    sink(sc_module_name _name 
     786        ):process(_name) 
     787    { 
     788         
     789    } 
     790     
     791    std::string ForSyDe_kind() {return "SDF::sink";}; 
     792private: 
     793 
     794    //! The main and only execution thread of the module 
     795    void worker() 
     796    { 
     797        ITYP in_val; 
     798        while (1) 
     799        { 
     800            in_val = iport.read(); 
     801            _func(in_val);       // run the function 
     802        } 
     803    } 
     804     
     805    void bindInfo() 
     806    { 
     807        boundInChans.resize(1);     // only one input ports 
     808        boundInChans[0].port = &iport; 
     809        boundInChans[0].toks = 1; 
     810        boundInChans[0].portType = typeid(ITYP).name(); 
     811        for (int i=0;i<iport.size();i++) 
     812            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
     813    } 
     814 
     815protected: 
     816    //! The main caclulation function 
     817    /*! It is abstract and the user should provide an implementation for 
     818     * it in the derived class. 
     819     */ 
     820    virtual void (_func)(ITYP) = 0; 
     821}; 
     822 
     823//! The zip process with variable number of inputs and one output 
     824/*! This process "zips" the incoming signals into one signal of tuples. 
     825 */ 
     826template <class... ITYPs> 
     827class zipN : public process 
     828{ 
     829public: 
     830    std::tuple <sc_fifo_in<ITYPs>...> iport;///< tuple of ports for the input channels 
     831    sc_fifo_out<std::tuple< 
     832                           std::vector<ITYPs>... 
     833                           > > oport;   ///< port for the output channel 
     834 
     835    //! The constructor requires the module name 
     836    /*! It creates an SC_THREAD which reads data from its input port, 
     837     * zips them together and writes the results using the output port 
     838     */ 
     839    zipN(sc_module_name _name, ///< Module name 
     840         std::vector<unsigned> inToks 
     841        ):process(_name) 
     842    { 
     843        if (inToks.size()!=sizeof...(ITYPs)) 
     844            SC_REPORT_ERROR(name(),"Wrong number of consumption rates provided"); 
     845        itoks = inToks; 
     846        otoks.push_back(1); 
     847    } 
     848     
     849    std::string ForSyDe_kind() {return "SDF::zipN";}; 
     850     
     851private: 
     852 
     853    //! The main and only execution thread of the module 
     854    void worker() 
     855    { 
     856        std::tuple<std::vector<ITYPs>...> in_vals; 
     857        while (1) 
     858        { 
     859            in_vals = sc_fifo_tuple_read<ITYPs...>(iport, itoks); 
     860            WRITE_MULTIPORT(oport,in_vals);    // write to the output 
     861        } 
     862    } 
     863     
     864    void bindInfo() 
     865    { 
     866        boundInChans.resize(sizeof...(ITYPs)); 
     867        boundOutChans.resize(1); 
     868        boundOutChans[0].port = &oport; 
     869        boundOutChans[0].toks = otoks[0]; 
     870        boundOutChans[0].portType = typeid(std::tuple<std::vector<ITYPs>...>).name(); 
     871        populateIPorts<ITYPs...>(boundInChans, itoks, iport); 
     872        for (int i=0;i<oport.size();i++) 
     873            boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
     874    } 
     875     
     876    // Begin of some TMP magic // 
     877    template<size_t N,class R, class T> 
     878    struct fifo_read_helper 
     879    { 
     880        static void read(R& ret, T& t, const std::vector<unsigned int>& itoks) 
     881        { 
     882            fifo_read_helper<N-1,R,T>::read(ret,t,itoks); 
     883            for (unsigned int i=0;i<itoks[N];i++) 
     884                std::get<N>(ret).push_back(std::get<N>(t).read()); 
     885        } 
     886    }; 
     887 
     888    template<class R, class T> 
     889    struct fifo_read_helper<0,R,T> 
     890    { 
     891        static void read(R& ret, T& t, const std::vector<unsigned int>& itoks) 
     892        { 
     893            for (unsigned int i=0;i<itoks[0];i++) 
     894                std::get<0>(ret).push_back(std::get<0>(t).read()); 
     895        } 
     896    }; 
     897 
     898    template<class... T> 
     899    std::tuple<std::vector<T>...> sc_fifo_tuple_read(std::tuple<sc_fifo_in<T>...>& ports, 
     900                                                     const std::vector<unsigned int>& itoks) 
     901    { 
     902        std::tuple<std::vector<T>...> ret; 
     903        fifo_read_helper<sizeof...(T)-1, 
     904                         std::tuple<std::vector<T>...>, 
     905                         std::tuple<sc_fifo_in<T>...>>::read(ret,ports,itoks); 
     906        return ret; 
     907    } 
     908    // End of TMP magic // 
     909    // Begin of some TMP magic // 
     910    template<size_t N, class T> 
     911    struct populateIPorts_helper 
     912    { 
     913        static void populate(std::vector<PortInfo>& boundInChans, 
     914                             const std::vector<unsigned>& itoks, T& ports) 
     915        { 
     916            populateIPorts_helper<N-1,T>::populate(boundInChans,itoks,ports); 
     917            boundInChans[N].port = &std::get<N>(ports); 
     918            boundInChans[N].toks = itoks[N]; 
     919            //~ boundInChans[N].portType = typeid(*std::get<N>(ports).data_type).name(); 
     920            for (int i=0;i<std::get<N>(ports).size();i++) 
     921                boundInChans[N].boundChans.push_back( 
     922                    dynamic_cast<sc_object*>(std::get<N>(ports)[i]) 
     923                ); 
     924        } 
     925    }; 
     926 
     927    template<class T> 
     928    struct populateIPorts_helper<0,T> 
     929    { 
     930        static void populate(std::vector<PortInfo>& boundInChans, 
     931                             const std::vector<unsigned>& itoks, T& ports) 
     932        { 
     933            boundInChans[0].port = &std::get<0>(ports); 
     934            boundInChans[0].toks = itoks[0]; 
     935            //~ boundInChans[0].portType = typeid(*std::get<0>(ports).data_type).name(); 
     936            for (int i=0;i<std::get<0>(ports).size();i++) 
     937                boundInChans[0].boundChans.push_back( 
     938                    dynamic_cast<sc_object*>(std::get<0>(ports)[i]) 
     939                ); 
     940        } 
     941    }; 
     942 
     943    template<class... T> 
     944    void populateIPorts(std::vector<PortInfo>& boundInChans, 
     945                        const std::vector<unsigned>& itoks, 
     946                        std::tuple<sc_fifo_in<T>...>& ports) 
     947    { 
     948        populateIPorts_helper<sizeof...(T)-1, 
     949            std::tuple<sc_fifo_in<T>...>>::populate(boundInChans, itoks, ports); 
     950    } 
     951    // End of TMP magic // 
     952}; 
     953 
     954//! The unzip process with one input and two outputs 
     955/*! This process "unzips" a signal of tuples into two separate signals 
     956 */ 
     957template <class OTYP1, class OTYP2> 
     958class unzip : public process 
     959{ 
     960public: 
     961    sc_fifo_in<std::tuple< 
     962                          std::vector<OTYP1>,std::vector<OTYP2> 
     963                          >> iport;         ///< port for the input channel 
     964    sc_fifo_out<OTYP1> oport1; ///< port for the output channel 1 
     965    sc_fifo_out<OTYP2> oport2; ///< port for the output channel 2 
     966 
     967    //! The constructor requires the module name 
     968    /*! It creates an SC_THREAD which reads data from its input ports, 
     969     * unzips them and writes the results using the output ports 
     970     */ 
     971    unzip(sc_module_name _name, 
     972          unsigned out1Toks, 
     973          unsigned out2Toks 
     974         ):process(_name) 
     975    { 
     976        itoks.push_back(1); 
     977        otoks.push_back(out1Toks); 
     978        otoks.push_back(out2Toks); 
     979    } 
     980     
     981    std::string ForSyDe_kind() {return "SDF::unzip";}; 
     982     
     983private: 
     984 
     985    //! The main and only execution thread of the module 
     986    void worker() 
     987    { 
     988        std::tuple<std::vector<OTYP1>,std::vector<OTYP2>> in_val; 
     989        std::vector<OTYP1> out_val1; 
     990        std::vector<OTYP2> out_val2; 
     991        while (1) 
     992        { 
     993            in_val = iport.read();  // read from input 
     994            std::tie(out_val1,out_val2) = in_val; 
     995            WRITE_VEC_MULTIPORT(oport1,out_val1,otoks[0]);// write to the output 
     996            WRITE_VEC_MULTIPORT(oport2,out_val2,otoks[1]);// write to the output 
     997        } 
     998    } 
     999     
     1000    void bindInfo() 
     1001    { 
     1002        boundInChans.resize(1);     // only one input port 
     1003        boundInChans[0].port = &iport; 
     1004        boundInChans[0].toks = itoks[0]; 
     1005        boundInChans[0].portType = typeid(std::tuple<std::vector<OTYP1>, 
     1006                                                     std::vector<OTYP2>>).name(); 
     1007        boundOutChans.resize(2);    // two output ports 
     1008        boundOutChans[0].port = &oport1; 
     1009        boundOutChans[0].toks = otoks[0]; 
     1010        boundOutChans[0].portType = typeid(OTYP1).name(); 
     1011        boundOutChans[1].port = &oport2; 
     1012        boundOutChans[1].toks = otoks[1]; 
     1013        boundOutChans[1].portType = typeid(OTYP2).name(); 
     1014        for (int i=0;i<iport.size();i++) 
     1015            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
     1016        for (int i=0;i<oport1.size();i++) 
     1017            boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport1[i])); 
     1018        for (int i=0;i<oport2.size();i++) 
     1019            boundOutChans[1].boundChans.push_back(dynamic_cast<sc_object*>(oport2[i])); 
     1020    } 
     1021 
     1022}; 
     1023 
     1024//! The unzip process with one input and variable number of outputs 
     1025/*! This process "unzips" the incoming signal into a tuple of signals. 
     1026 */ 
     1027template <class... ITYPs> 
     1028class unzipN : public process 
     1029{ 
     1030public: 
     1031    sc_fifo_in<std::tuple< 
     1032                          std::vector<ITYPs>... 
     1033                          > > iport;///< port for the input channel 
     1034    std::tuple <sc_fifo_out<ITYPs>...> oport;///< tuple of ports for the output channels 
     1035 
     1036    //! The constructor requires the module name 
     1037    /*! It creates an SC_THREAD which reads data from its input port, 
     1038     * unzips it and writes the results using the output ports 
     1039     */ 
     1040    unzipN(sc_module_name _name, 
     1041           std::vector<unsigned> outToks 
     1042          ):process(_name) 
     1043    { 
     1044        if (outToks.size()!=sizeof...(ITYPs)) 
     1045            SC_REPORT_ERROR(name(),"Wrong number of production rates provided"); 
     1046        itoks.push_back(1); 
     1047        otoks = outToks; 
     1048    } 
     1049     
     1050    std::string ForSyDe_kind() {return "SDF::unzipN";}; 
     1051     
     1052private: 
     1053 
     1054    //! The main and only execution thread of the module 
     1055    void worker() 
     1056    { 
     1057        std::tuple<std::vector<ITYPs>...> in_vals; 
     1058        while (1) 
     1059        { 
     1060            in_vals = iport.read(); 
     1061            sc_fifo_tuple_write<ITYPs...>(in_vals, oport); 
     1062        } 
     1063    } 
     1064     
     1065    void bindInfo() 
     1066    { 
     1067        boundInChans.resize(1);     // only one input port 
     1068        boundInChans[0].port = &iport; 
     1069        boundInChans[0].toks = itoks[0]; 
     1070        boundOutChans.resize(sizeof...(ITYPs));    // output ports 
     1071        for (int i=0;i<iport.size();i++) 
     1072            boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
     1073        populateOPorts<ITYPs...>(boundOutChans, otoks, oport); 
     1074    } 
     1075     
     1076    // Begin of some TMP magic // 
     1077    template<size_t N,class R,  class T> 
     1078    struct fifo_write_helper 
     1079    { 
     1080        static void write(const R& vals, T& t) 
     1081        { 
     1082            fifo_write_helper<N-1,R,T>::write(vals,t); 
     1083            for (unsigned int i=0;i<(std::get<N>(vals)).size();i++) 
     1084                std::get<N>(t).write(std::get<N>(vals)[i]); 
     1085        } 
     1086    }; 
     1087 
     1088    template<class R, class T> 
     1089    struct fifo_write_helper<0,R,T> 
     1090    { 
     1091        static void write(const R& vals, T& t) 
     1092        { 
     1093            for (unsigned int i=0;i<(std::get<0>(vals)).size();i++) 
     1094                std::get<0>(t).write(std::get<0>(vals)[i]); 
     1095        } 
     1096    }; 
     1097 
     1098    template<class... T> 
     1099    void sc_fifo_tuple_write(const std::tuple<std::vector<T>...>& vals, 
     1100                             std::tuple<sc_fifo_out<T>...>& ports) 
     1101    { 
     1102        fifo_write_helper<sizeof...(T)-1, 
     1103                          std::tuple<std::vector<T>...>, 
     1104                          std::tuple<sc_fifo_out<T>...>>::write(vals,ports); 
     1105    } 
     1106    // End of TMP magic // 
     1107    // Begin of some TMP magic // 
     1108    template<size_t N, class T> 
     1109    struct populateOPorts_helper 
     1110    { 
     1111        static void populate(std::vector<PortInfo>& boundOutChans, 
     1112                             const std::vector<unsigned>& otoks, T& ports) 
     1113        { 
     1114            populateOPorts_helper<N-1,T>::populate(boundOutChans,otoks,ports); 
     1115            boundOutChans[N].port = &std::get<N>(ports); 
     1116            boundOutChans[N].toks = otoks[N]; 
     1117            for (int i=0;i<std::get<N>(ports).size();i++) 
     1118                boundOutChans[N].boundChans.push_back( 
     1119                    dynamic_cast<sc_object*>(std::get<N>(ports)[i]) 
     1120                ); 
     1121        } 
     1122    }; 
     1123 
     1124    template<class T> 
     1125    struct populateOPorts_helper<0,T> 
     1126    { 
     1127        static void populate(std::vector<PortInfo>& boundOutChans, 
     1128                             const std::vector<unsigned>& otoks, T& ports) 
     1129        { 
     1130            boundOutChans[0].port = &std::get<0>(ports); 
     1131            boundOutChans[0].toks = otoks[0]; 
     1132            for (int i=0;i<std::get<0>(ports).size();i++) 
     1133                boundOutChans[0].boundChans.push_back( 
     1134                    dynamic_cast<sc_object*>(std::get<0>(ports)[i]) 
     1135                ); 
     1136        } 
     1137    }; 
     1138 
     1139    template<class... T> 
     1140    void populateOPorts(std::vector<PortInfo>& boundOutChans, 
     1141                        const std::vector<unsigned>& otoks, 
     1142                        std::tuple<sc_fifo_out<T>...>& ports) 
     1143    { 
     1144        populateOPorts_helper<sizeof...(T)-1, 
     1145            std::tuple<sc_fifo_out<T>...>>::populate(boundOutChans, otoks, ports); 
     1146    } 
     1147    // End of TMP magic // 
     1148}; 
     1149 
     1150//! Process constructor for a fan-out process with one input and one output 
     1151/*! This class is used to build a fanout processes with one input 
     1152 * and one output. The class is parameterized for input and output 
     1153 * data-types. 
     1154 *  
     1155 * This class exist because it is impossible to connect channels 
     1156 * directly to ports in SystemC (which may be needed in hierarchical 
     1157 * designs). It will be used when it is needed to connect an input 
     1158 * port of a module to the input channels of multiple processes (modules). 
     1159 */ 
     1160template <class IOTYP> 
     1161class fanout : public process 
     1162{ 
     1163public: 
     1164    sc_fifo_in<IOTYP> iport;        ///< port for the input channel 
     1165    sc_fifo_out<IOTYP> oport;       ///< port for the output channel 
     1166 
     1167    //! The constructor requires the module name 
     1168    /*! It creates an SC_THREAD which reads data from its input port, 
     1169     * applies and writes the results using the output port 
     1170     */ 
     1171    fanout(sc_module_name _name 
     1172          ):process(_name) 
     1173    { 
     1174         
     1175    } 
     1176     
     1177    std::string ForSyDe_kind() {return "SDF::fanout";}; 
     1178     
     1179private: 
     1180 
     1181    //! The main and only execution thread of the module 
     1182    void worker() 
     1183    { 
     1184        IOTYP in_val; 
     1185        IOTYP out_val; 
     1186        while (1) 
     1187        { 
     1188            in_val = iport.read();  // read from input 
     1189            out_val = in_val;        // same output 
     1190            WRITE_MULTIPORT(oport,out_val);    // write to the output 
    5651191        } 
    5661192    } 
     
    5791205            boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
    5801206    } 
    581 }; 
    582  
    583 //! Process constructor for a constant source process 
    584 /*! This class is used to build a souce process with constant output. 
    585  * Its main purpose is to be used in test-benches. 
    586  *  
    587  * This class can directly be instantiated to build a process. 
    588  */ 
    589 template <class OTYP> 
    590 class constant : public process 
    591 { 
    592 public: 
    593     sc_fifo_out<OTYP> oport;     ///< port for the output channel 
    594  
    595     //! The constructor requires the module name 
    596     /*! It creates an SC_THREAD which runs the user-imlpemented function 
    597      * and writes the result using the output port 
    598      */ 
    599     constant(sc_module_name _name, 
    600              OTYP val 
    601             ):process(_name), cval(val) 
    602     { 
    603          
    604     } 
    605      
    606     std::string ForSyDe_kind() {return "SDF::constant";}; 
    607      
    608     OTYP cval; 
    609      
    610 private: 
    611  
    612     //! The main and only execution thread of the module 
    613     void worker() 
    614     { 
    615         while (1) 
    616         { 
    617             WRITE_MULTIPORT(oport,cval);    // write to the output 
    618         } 
    619     } 
    620      
    621     void bindInfo() 
    622     { 
    623         boundOutChans.resize(1);    // only one output port 
    624         boundOutChans[0].port = &oport; 
    625         boundOutChans[0].toks = 1; 
    626         for (int i=0;i<oport.size();i++) 
    627             boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
    628     } 
    629 }; 
    630  
    631 //! Process constructor for a source process 
    632 /*! This class is used to build a souce process which only has an output. 
    633  * Given an initial state and a function, the process repeatedly applies 
    634  * the function to the current state to produce next state, which is 
    635  * also the process output. It can be used in test-benches. 
    636  *  
    637  * Note that this is an abstract class and can not be directly 
    638  * instantiated. The designer should derive from this class and 
    639  * implement the _func function which is run on each evaluation cycle to 
    640  * produce an output. 
    641  */ 
    642 template <class OTYP> 
    643 class source : public process 
    644 { 
    645 public: 
    646     sc_fifo_out<OTYP> oport;     ///< port for the output channel 
    647  
    648     //! The constructor requires the module name 
    649     /*! It creates an SC_THREAD which runs the user-imlpemented function 
    650      * and writes the result using the output port 
    651      */ 
    652     source(sc_module_name _name,   ///< The module name 
    653              OTYP ist                ///< Initial state 
    654           ):process(_name), init_st(ist) 
    655     { 
    656          
    657     } 
    658      
    659     std::string ForSyDe_kind() {return "SDF::source";}; 
    660      
    661     OTYP init_st; 
    662      
    663 private: 
    664  
    665     //! The main and only execution thread of the module 
    666     void worker() 
    667     { 
    668         OTYP curst_val = init_st, nxst_val; 
    669         WRITE_MULTIPORT(oport,curst_val);      // write the initial state 
    670         while (1) 
    671         { 
    672             _func(nxst_val, curst_val);        // produce a new value 
    673             curst_val = nxst_val; 
    674             WRITE_MULTIPORT(oport,curst_val);  // write to the output 
    675         } 
    676     } 
    677      
    678     void bindInfo() 
    679     { 
    680         boundOutChans.resize(1);    // only one output port 
    681         boundOutChans[0].port = &oport; 
    682         boundOutChans[0].toks = 1; 
    683         for (int i=0;i<oport.size();i++) 
    684             boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
    685     } 
    686  
    687 protected: 
    688     //! The main caclulation function 
    689     /*! It is abstract and the user should provide an implementation for 
    690      * it in the derived class. 
    691      */ 
    692     virtual void (_func)(OTYP&, const OTYP&) = 0; 
    693 }; 
    694  
    695 //! Process constructor for a source process with vector input 
    696 /*! This class is used to build a souce process which only has an output. 
    697  * Given the test bench vector, the process iterates over the emenets 
    698  * of the vector and outputs one value on each evaluation cycle. 
    699  */ 
    700 template <class OTYP> 
    701 class vsource : public process 
    702 { 
    703 public: 
    704     sc_fifo_out<OTYP> oport;     ///< port for the output channel 
    705  
    706     //! The constructor requires the module name 
    707     /*! It creates an SC_THREAD which writes the result using the output 
    708      * port. 
    709      */ 
    710     vsource(sc_module_name _name,           ///< The module name 
    711             const std::vector<OTYP>& invec  ///< Initial vector 
    712            ):process(_name), in_vec(invec) 
    713     { 
    714          
    715     } 
    716      
    717     std::string ForSyDe_kind() {return "SDF::vsource";}; 
    718      
    719     std::vector<OTYP> in_vec; 
    720      
    721 private: 
    722  
    723     //! The main and only execution thread of the module 
    724     void worker() 
    725     { 
    726         typename std::vector<OTYP>::iterator itr; 
    727         for (itr=in_vec.begin();itr!=in_vec.end();itr++) 
    728         { 
    729             OTYP out_val = *itr; 
    730             WRITE_MULTIPORT(oport,out_val);    // write to the output 
    731         } 
    732     } 
    733      
    734     void bindInfo() 
    735     { 
    736         boundOutChans.resize(1);    // only one output port 
    737         boundOutChans[0].port = &oport; 
    738         boundOutChans[0].toks = 1; 
    739         for (int i=0;i<oport.size();i++) 
    740             boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
    741     } 
    742 }; 
    743  
    744 //! Process constructor for a sink process 
    745 /*! This class is used to build a sink process which only has an input. 
    746  * Its main purpose is to be used in test-benches. 
    747  *  
    748  * Note that this is an abstract class and can not be directly 
    749  * instantiated. The designer should derive from this class and 
    750  * implement the _func function which is run in each evaluation cycle on 
    751  * the received input. 
    752  */ 
    753 template <class ITYP> 
    754 class sink : public process 
    755 { 
    756 public: 
    757     sc_fifo_in<ITYP> iport;         ///< port for the input channel 
    758  
    759     //! The constructor requires the module name 
    760     /*! It creates an SC_THREAD which runs the user-imlpemented function 
    761      * in each cycle. 
    762      */ 
    763     sink(sc_module_name _name 
    764         ):process(_name) 
    765     { 
    766          
    767     } 
    768      
    769     std::string ForSyDe_kind() {return "SDF::sink";}; 
    770 private: 
    771  
    772     //! The main and only execution thread of the module 
    773     void worker() 
    774     { 
    775         ITYP in_val; 
    776         while (1) 
    777         { 
    778             in_val = iport.read(); 
    779             _func(in_val);       // run the function 
    780         } 
    781     } 
    782      
    783     void bindInfo() 
    784     { 
    785         boundInChans.resize(1);     // only one input ports 
    786         boundInChans[0].port = &iport; 
    787         boundInChans[0].toks = 1; 
    788         for (int i=0;i<iport.size();i++) 
    789             boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
    790     } 
    791  
    792 protected: 
    793     //! The main caclulation function 
    794     /*! It is abstract and the user should provide an implementation for 
    795      * it in the derived class. 
    796      */ 
    797     virtual void (_func)(ITYP) = 0; 
    798 }; 
    799  
    800 //! The zip process with variable number of inputs and one output 
    801 /*! This process "zips" the incoming signals into one signal of tuples. 
    802  */ 
    803 template <class... ITYPs> 
    804 class zipN : public process 
    805 { 
    806 public: 
    807     std::tuple <sc_fifo_in<ITYPs>...> iport;///< tuple of ports for the input channels 
    808     sc_fifo_out<std::tuple< 
    809                            std::vector<ITYPs>... 
    810                            > > oport;   ///< port for the output channel 
    811  
    812     //! The constructor requires the module name 
    813     /*! It creates an SC_THREAD which reads data from its input port, 
    814      * zips them together and writes the results using the output port 
    815      */ 
    816     zipN(sc_module_name _name, ///< Module name 
    817          std::vector<unsigned> inToks 
    818         ):process(_name) 
    819     { 
    820         if (inToks.size()!=sizeof...(ITYPs)) 
    821             SC_REPORT_ERROR(name(),"Wrong number of consumption rates provided"); 
    822         itoks = inToks; 
    823         otoks.push_back(1); 
    824     } 
    825      
    826     std::string ForSyDe_kind() {return "SDF::zipN";}; 
    827      
    828 private: 
    829  
    830     //! The main and only execution thread of the module 
    831     void worker() 
    832     { 
    833         std::tuple<std::vector<ITYPs>...> in_vals; 
    834         while (1) 
    835         { 
    836             in_vals = sc_fifo_tuple_read<ITYPs...>(iport, itoks); 
    837             WRITE_MULTIPORT(oport,in_vals);    // write to the output 
    838         } 
    839     } 
    840      
    841     void bindInfo() 
    842     { 
    843         boundInChans.resize(sizeof...(ITYPs)); 
    844         boundOutChans.resize(1); 
    845         boundOutChans[0].port = &oport; 
    846         boundOutChans[0].toks = otoks[0]; 
    847         populateIPorts<ITYPs...>(boundInChans, itoks, iport); 
    848         for (int i=0;i<oport.size();i++) 
    849             boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
    850     } 
    851      
    852     // Begin of some TMP magic // 
    853     template<size_t N,class R, class T> 
    854     struct fifo_read_helper 
    855     { 
    856         static void read(R& ret, T& t, const std::vector<unsigned int>& itoks) 
    857         { 
    858             fifo_read_helper<N-1,R,T>::read(ret,t,itoks); 
    859             for (unsigned int i=0;i<itoks[N];i++) 
    860                 std::get<N>(ret).push_back(std::get<N>(t).read()); 
    861         } 
    862     }; 
    863  
    864     template<class R, class T> 
    865     struct fifo_read_helper<0,R,T> 
    866     { 
    867         static void read(R& ret, T& t, const std::vector<unsigned int>& itoks) 
    868         { 
    869             for (unsigned int i=0;i<itoks[0];i++) 
    870                 std::get<0>(ret).push_back(std::get<0>(t).read()); 
    871         } 
    872     }; 
    873  
    874     template<class... T> 
    875     std::tuple<std::vector<T>...> sc_fifo_tuple_read(std::tuple<sc_fifo_in<T>...>& ports, 
    876                                                      const std::vector<unsigned int>& itoks) 
    877     { 
    878         std::tuple<std::vector<T>...> ret; 
    879         fifo_read_helper<sizeof...(T)-1, 
    880                          std::tuple<std::vector<T>...>, 
    881                          std::tuple<sc_fifo_in<T>...>>::read(ret,ports,itoks); 
    882         return ret; 
    883     } 
    884     // End of TMP magic // 
    885     // Begin of some TMP magic // 
    886     template<size_t N, class T> 
    887     struct populateIPorts_helper 
    888     { 
    889         static void populate(std::vector<PortInfo>& boundInChans, 
    890                              const std::vector<unsigned>& itoks, T& ports) 
    891         { 
    892             populateIPorts_helper<N-1,T>::populate(boundInChans,itoks,ports); 
    893             boundInChans[N].port = &std::get<N>(ports); 
    894             boundInChans[N].toks = itoks[N]; 
    895             for (int i=0;i<std::get<N>(ports).size();i++) 
    896                 boundInChans[N].boundChans.push_back( 
    897                     dynamic_cast<sc_object*>(std::get<N>(ports)[i]) 
    898                 ); 
    899         } 
    900     }; 
    901  
    902     template<class T> 
    903     struct populateIPorts_helper<0,T> 
    904     { 
    905         static void populate(std::vector<PortInfo>& boundInChans, 
    906                              const std::vector<unsigned>& itoks, T& ports) 
    907         { 
    908             boundInChans[0].port = &std::get<0>(ports); 
    909             boundInChans[0].toks = itoks[0]; 
    910             for (int i=0;i<std::get<0>(ports).size();i++) 
    911                 boundInChans[0].boundChans.push_back( 
    912                     dynamic_cast<sc_object*>(std::get<0>(ports)[i]) 
    913                 ); 
    914         } 
    915     }; 
    916  
    917     template<class... T> 
    918     void populateIPorts(std::vector<PortInfo>& boundInChans, 
    919                         const std::vector<unsigned>& itoks, 
    920                         std::tuple<sc_fifo_in<T>...>& ports) 
    921     { 
    922         populateIPorts_helper<sizeof...(T)-1, 
    923             std::tuple<sc_fifo_in<T>...>>::populate(boundInChans, itoks, ports); 
    924     } 
    925     // End of TMP magic // 
    926 }; 
    927  
    928 //! The unzip process with one input and two outputs 
    929 /*! This process "unzips" a signal of tuples into two separate signals 
    930  */ 
    931 template <class OTYP1, class OTYP2> 
    932 class unzip : public process 
    933 { 
    934 public: 
    935     sc_fifo_in<std::tuple< 
    936                           std::vector<OTYP1>,std::vector<OTYP2> 
    937                           >> iport;         ///< port for the input channel 
    938     sc_fifo_out<OTYP1> oport1; ///< port for the output channel 1 
    939     sc_fifo_out<OTYP2> oport2; ///< port for the output channel 2 
    940  
    941     //! The constructor requires the module name 
    942     /*! It creates an SC_THREAD which reads data from its input ports, 
    943      * unzips them and writes the results using the output ports 
    944      */ 
    945     unzip(sc_module_name _name, 
    946           unsigned out1Toks, 
    947           unsigned out2Toks 
    948          ):process(_name) 
    949     { 
    950         itoks.push_back(1); 
    951         otoks.push_back(out1Toks); 
    952         otoks.push_back(out2Toks); 
    953     } 
    954      
    955     std::string ForSyDe_kind() {return "SDF::unzip";}; 
    956      
    957 private: 
    958  
    959     //! The main and only execution thread of the module 
    960     void worker() 
    961     { 
    962         std::tuple<std::vector<OTYP1>,std::vector<OTYP2>> in_val; 
    963         std::vector<OTYP1> out_val1; 
    964         std::vector<OTYP2> out_val2; 
    965         while (1) 
    966         { 
    967             in_val = iport.read();  // read from input 
    968             std::tie(out_val1,out_val2) = in_val; 
    969             WRITE_VEC_MULTIPORT(oport1,out_val1,otoks[0]);// write to the output 
    970             WRITE_VEC_MULTIPORT(oport2,out_val2,otoks[1]);// write to the output 
    971         } 
    972     } 
    973      
    974     void bindInfo() 
    975     { 
    976         boundInChans.resize(1);     // only one input port 
    977         boundInChans[0].port = &iport; 
    978         boundInChans[0].toks = itoks[0]; 
    979         boundOutChans.resize(2);    // two output ports 
    980         boundOutChans[0].port = &oport1; 
    981         boundOutChans[0].toks = otoks[0]; 
    982         boundOutChans[1].port = &oport2; 
    983         boundOutChans[1].toks = otoks[1]; 
    984         for (int i=0;i<iport.size();i++) 
    985             boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
    986         for (int i=0;i<oport1.size();i++) 
    987             boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport1[i])); 
    988         for (int i=0;i<oport2.size();i++) 
    989             boundOutChans[1].boundChans.push_back(dynamic_cast<sc_object*>(oport2[i])); 
    990     } 
    991  
    992 }; 
    993  
    994 //! The unzip process with one input and variable number of outputs 
    995 /*! This process "unzips" the incoming signal into a tuple of signals. 
    996  */ 
    997 template <class... ITYPs> 
    998 class unzipN : public process 
    999 { 
    1000 public: 
    1001     sc_fifo_in<std::tuple< 
    1002                           std::vector<ITYPs>... 
    1003                           > > iport;///< port for the input channel 
    1004     std::tuple <sc_fifo_out<ITYPs>...> oport;///< tuple of ports for the output channels 
    1005  
    1006     //! The constructor requires the module name 
    1007     /*! It creates an SC_THREAD which reads data from its input port, 
    1008      * unzips it and writes the results using the output ports 
    1009      */ 
    1010     unzipN(sc_module_name _name, 
    1011            std::vector<unsigned> outToks 
    1012           ):process(_name) 
    1013     { 
    1014         if (outToks.size()!=sizeof...(ITYPs)) 
    1015             SC_REPORT_ERROR(name(),"Wrong number of production rates provided"); 
    1016         itoks.push_back(1); 
    1017         otoks = outToks; 
    1018     } 
    1019      
    1020     std::string ForSyDe_kind() {return "SDF::unzipN";}; 
    1021      
    1022 private: 
    1023  
    1024     //! The main and only execution thread of the module 
    1025     void worker() 
    1026     { 
    1027         std::tuple<std::vector<ITYPs>...> in_vals; 
    1028         while (1) 
    1029         { 
    1030             in_vals = iport.read(); 
    1031             sc_fifo_tuple_write<ITYPs...>(in_vals, oport); 
    1032         } 
    1033     } 
    1034      
    1035     void bindInfo() 
    1036     { 
    1037         boundInChans.resize(1);     // only one input port 
    1038         boundInChans[0].port = &iport; 
    1039         boundInChans[0].toks = itoks[0]; 
    1040         boundOutChans.resize(sizeof...(ITYPs));    // output ports 
    1041         for (int i=0;i<iport.size();i++) 
    1042             boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
    1043         populateOPorts<ITYPs...>(boundOutChans, otoks, oport); 
    1044     } 
    1045      
    1046     // Begin of some TMP magic // 
    1047     template<size_t N,class R,  class T> 
    1048     struct fifo_write_helper 
    1049     { 
    1050         static void write(const R& vals, T& t) 
    1051         { 
    1052             fifo_write_helper<N-1,R,T>::write(vals,t); 
    1053             for (unsigned int i=0;i<(std::get<N>(vals)).size();i++) 
    1054                 std::get<N>(t).write(std::get<N>(vals)[i]); 
    1055         } 
    1056     }; 
    1057  
    1058     template<class R, class T> 
    1059     struct fifo_write_helper<0,R,T> 
    1060     { 
    1061         static void write(const R& vals, T& t) 
    1062         { 
    1063             for (unsigned int i=0;i<(std::get<0>(vals)).size();i++) 
    1064                 std::get<0>(t).write(std::get<0>(vals)[i]); 
    1065         } 
    1066     }; 
    1067  
    1068     template<class... T> 
    1069     void sc_fifo_tuple_write(const std::tuple<std::vector<T>...>& vals, 
    1070                              std::tuple<sc_fifo_out<T>...>& ports) 
    1071     { 
    1072         fifo_write_helper<sizeof...(T)-1, 
    1073                           std::tuple<std::vector<T>...>, 
    1074                           std::tuple<sc_fifo_out<T>...>>::write(vals,ports); 
    1075     } 
    1076     // End of TMP magic // 
    1077     // Begin of some TMP magic // 
    1078     template<size_t N, class T> 
    1079     struct populateOPorts_helper 
    1080     { 
    1081         static void populate(std::vector<PortInfo>& boundOutChans, 
    1082                              const std::vector<unsigned>& otoks, T& ports) 
    1083         { 
    1084             populateOPorts_helper<N-1,T>::populate(boundOutChans,otoks,ports); 
    1085             boundOutChans[N].port = &std::get<N>(ports); 
    1086             boundOutChans[N].toks = otoks[N]; 
    1087             for (int i=0;i<std::get<N>(ports).size();i++) 
    1088                 boundOutChans[N].boundChans.push_back( 
    1089                     dynamic_cast<sc_object*>(std::get<N>(ports)[i]) 
    1090                 ); 
    1091         } 
    1092     }; 
    1093  
    1094     template<class T> 
    1095     struct populateOPorts_helper<0,T> 
    1096     { 
    1097         static void populate(std::vector<PortInfo>& boundOutChans, 
    1098                              const std::vector<unsigned>& otoks, T& ports) 
    1099         { 
    1100             boundOutChans[0].port = &std::get<0>(ports); 
    1101             boundOutChans[0].toks = otoks[0]; 
    1102             for (int i=0;i<std::get<0>(ports).size();i++) 
    1103                 boundOutChans[0].boundChans.push_back( 
    1104                     dynamic_cast<sc_object*>(std::get<0>(ports)[i]) 
    1105                 ); 
    1106         } 
    1107     }; 
    1108  
    1109     template<class... T> 
    1110     void populateOPorts(std::vector<PortInfo>& boundOutChans, 
    1111                         const std::vector<unsigned>& otoks, 
    1112                         std::tuple<sc_fifo_out<T>...>& ports) 
    1113     { 
    1114         populateOPorts_helper<sizeof...(T)-1, 
    1115             std::tuple<sc_fifo_out<T>...>>::populate(boundOutChans, otoks, ports); 
    1116     } 
    1117     // End of TMP magic // 
    1118 }; 
    1119  
    1120 //! Process constructor for a fan-out process with one input and one output 
    1121 /*! This class is used to build a fanout processes with one input 
    1122  * and one output. The class is parameterized for input and output 
    1123  * data-types. 
    1124  *  
    1125  * This class exist because it is impossible to connect channels 
    1126  * directly to ports in SystemC (which may be needed in hierarchical 
    1127  * designs). It will be used when it is needed to connect an input 
    1128  * port of a module to the input channels of multiple processes (modules). 
    1129  */ 
    1130 template <class IOTYP> 
    1131 class fanout : public process 
    1132 { 
    1133 public: 
    1134     sc_fifo_in<IOTYP> iport;        ///< port for the input channel 
    1135     sc_fifo_out<IOTYP> oport;       ///< port for the output channel 
    1136  
    1137     //! The constructor requires the module name 
    1138     /*! It creates an SC_THREAD which reads data from its input port, 
    1139      * applies and writes the results using the output port 
    1140      */ 
    1141     fanout(sc_module_name _name 
    1142           ):process(_name) 
    1143     { 
    1144          
    1145     } 
    1146      
    1147     std::string ForSyDe_kind() {return "SDF::fanout";}; 
    1148      
    1149 private: 
    1150  
    1151     //! The main and only execution thread of the module 
    1152     void worker() 
    1153     { 
    1154         IOTYP in_val; 
    1155         IOTYP out_val; 
    1156         while (1) 
    1157         { 
    1158             in_val = iport.read();  // read from input 
    1159             out_val = in_val;        // same output 
    1160             WRITE_MULTIPORT(oport,out_val);    // write to the output 
    1161         } 
    1162     } 
    1163      
    1164     void bindInfo() 
    1165     { 
    1166         boundInChans.resize(1);     // only one input ports 
    1167         boundInChans[0].port = &iport; 
    1168         boundInChans[0].toks = 1; 
    1169         boundOutChans.resize(1);    // only one output port 
    1170         boundOutChans[0].port = &oport; 
    1171         boundOutChans[0].toks = 1; 
    1172         for (int i=0;i<iport.size();i++) 
    1173             boundInChans[0].boundChans.push_back(dynamic_cast<sc_object*>(iport[i])); 
    1174         for (int i=0;i<oport.size();i++) 
    1175             boundOutChans[0].boundChans.push_back(dynamic_cast<sc_object*>(oport[i])); 
    1176     } 
    11771207 
    11781208}; 
  • ForSyDe-SystemC/branches/CoMPSoC/src/forsyde/xml.hpp

    r28 r29  
    260260                //unzipChans[0]->second.srcPort = zipChan->second.srcActor; 
    261261                unzipChans[1]->second.srcActor = zipChan->second.srcActor; 
     262                // port info propagation 
     263                dynamic_cast<SDF::process*>(zipChan->second.srcActor)->boundOutChans =  
     264                    it->second->boundOutChans; 
     265                //TODO: What else?? 
    262266                // remove the zipped channel 
    263267                channels.erase(zipChan); 
     
    280284                for (auto it3=unzipChans.begin();it3!=unzipChans.end();it3++) 
    281285                    (*it3)->second.srcActor = zipChan->second.srcActor; 
     286                dynamic_cast<SDF::process*>(zipChan->second.srcActor)->boundOutChans =  
     287                    it->second->boundOutChans; 
     288                //TODO: What else?? 
    282289                // remove the zipped channel 
    283290                channels.erase(zipChan); 
     
    300307                for (auto it3=unzipChans.begin();it3!=unzipChans.end();it3++) 
    301308                    (*it3)->second.desActor = zipChan->second.desActor; 
     309                dynamic_cast<SDF::process*>(zipChan->second.desActor)->boundInChans =  
     310                    it->second->boundInChans; 
    302311                // remove the zipped channel 
    303312                channels.erase(zipChan); 
     
    484493                                    xml_node<> *fileNode = doc.allocate_node(node_element, "file"); 
    485494                                    srcFilesNode->append_node(fileNode); 
    486                                     char* ts2 = doc.allocate_string(getFuncName(it->first).append(".cpp").c_str()); 
     495                                    char* ts2 = doc.allocate_string(getFuncName(it->first).append(".c").c_str()); 
    487496                                    xml_attribute<> *fNameAttr = doc.allocate_attribute("file", ts2); 
    488497                                    fileNode->append_attribute(fNameAttr); 
     
    598607     * all of the code sections enclosed by "#pragma ForSyDe begin process.fname" 
    599608     * and "#pragma ForSyDe end process.fname" and generates separate 
    600      * "process.fname.cpp" files for each pair. 
     609     * "process.fname.c" files for each pair. 
    601610     */ 
    602611    void printSrc(const char* projectPath, const char* exportPath) 
     
    655664                    if (getFuncName(it->first)==funName) 
    656665                    { 
    657                         for (unsigned i=0;i<it->second->itoks.size();i++) 
    658                             oFile << "    " << "void" << "** inp" << i+1 
     666                        for (unsigned i=0;i<it->second->boundInChans.size();i++) 
     667                            oFile << "    " << it->second->boundInChans[i].portType << "** inp" << i+1 
    659668                                  << " = data_in["  
    660669                                  << i << "];" << std::endl; 
    661                         for (unsigned i=0;i<it->second->otoks.size();i++) 
    662                             oFile << "    " << "void" << "** out" << i+1 
     670                        for (unsigned i=0;i<it->second->boundOutChans.size();i++) 
     671                            oFile << "    " << it->second->boundOutChans[i].portType << "** out" << i+1 
    663672                                  << " = data_out[" 
    664                                   << i << "];" << std::endl << std::endl; 
     673                                  << i << "];" << std::endl; 
     674                        oFile << std::endl; 
    665675                        break; 
    666676                    } 
Note: See TracChangeset for help on using the changeset viewer.