diff --git a/backends/GenerateCPPCSP.hs b/backends/GenerateCPPCSP.hs index d3e878d..4d60106 100644 --- a/backends/GenerateCPPCSP.hs +++ b/backends/GenerateCPPCSP.hs @@ -25,46 +25,6 @@ In order to compile the generated code, you will need: * The C++CSP2 library (>= 2.0.2), available from , and any appropriate dependencies (e.g. Boost). -For the array handling I am currently using a combination of std::vector and an array view class (tockArrayView) I built myself. - -I considered the following options: - -1. in-built C arrays - -2. boost::array - -3. std::vector - -4. boost::multi_array - -5. Blitz++ - -6. Roll my own. - -Option 1 is what Adam used in GenerateC, but it involves carrying around the array sizes, which is a real pain. -Options 2 and 3 are fairly similar (boost::array is possible because arrays are of constant size in occam) but neither supports multiple dimensions -nor array slicing, so that would have been awkward. -Option 4 does support multiple dimensions and array slicing - but the latter would involve keeping tabs of the dimensions of the *original* array -(that was sliced *from*), even through multiple slices and indexes, which would have been a nightmare. -Option 5 makes slicing nice and simple, and multiple dimensions are easy too. However, things like retyping are still a big problem, so in the end -it became untenable. - -Therefore the only remaining option was 6. I use std::vector (although this may become boost::array) to actually store each array, and then -use tockArrayView to work with the array. tockArrayView represents a view of an array, and never allocates or deallocates any memory. Thus they -can be passed around freely, which makes them easy to work with. - -For the ANY type I am currently using boost::any. However, this is not a correct solution because the type that occam pulls out is not -necessarily the type that was put in. Therefore ANY probably needs some serialisation of types (akin to what used to happen in C++CSP.NET) -to work properly. - -For the variant protocols I am using boost::variant. But when there are more than 9 cases, I have to chain several variants together. -This is perfectly legal C++, but I think it is causing excessive memory usage in g++ (or possibly the tuples that work similarly...) - -For the sequential protocols (including those after a tag in variant protocols) I am using boost::tuple for convenience (along with the handy -boost::tie function to extract the values). However I suspect this (or the variants -- see above) is causing a lot of memory usage in g++. Plus, -when more than 9 items are present in the protocol (including variant-tag) I have to chain the tuples together, which means chaining the tie function -as well. May be worth changing in future. - Channels of direction 'A.DirUnknown' are passed around as pointers to a One2OneChannel\<\> object. To read I use the reader() function and to write I use the writer() function. For channels of direction 'A.DirInput' or 'A.DirOutput' I actually pass the Chanin\<\> and Chanout\<\> objects as you would expect. -} @@ -793,13 +753,13 @@ cppgenRetypeSizes m destT destN srcT srcV tell ["}"] in case destT of -- TODO we should be able to remove this check now that arrays have changed + -- TODO or at least it needs fixing in some way... -- An array -- figure out the genMissing dimension, if there is one. A.Array destDS _ -> case (indexOfFreeDimensions destDS) of -- No free dimensions; check the complete array matches in size. [] -> checkSize - -- Free dimensions; tockArrayView will check at run-time instead _ -> return () -- Not array; just check the size is 1. _ -> checkSize diff --git a/support/tock_support_cppcsp.h b/support/tock_support_cppcsp.h index a52eacb..d2ce5a4 100644 --- a/support/tock_support_cppcsp.h +++ b/support/tock_support_cppcsp.h @@ -109,224 +109,6 @@ public: } }; - -//For tieing together chained tuples: - -template -inline boost::tuple -tie10(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, - T9& t9, T10 t10) { - return boost::tuple - (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); -} - -inline std::pair< boost::array , unsigned > tockDims(const unsigned d0) -{ - boost::array r; - r[0] = d0; - return std::pair< boost::array , unsigned >(r,d0 == 0 ? 0 : 1); -} - -/* -Generates functions like this: -inline std::pair< boost::array , unsigned > tockDims(const unsigned d0,const unsigned d1,const unsigned d2) -{ - boost::array r; - r[0] = d0; - r[1] = d1; - r[2] = d2; - return std::pair< boost::array , unsigned >(r,d1 * d2); -} -*/ - -#define TOCKDIMS_ARGS(___z,NUM,___data) ,const unsigned d##NUM -#define TOCKDIMS_ASSIGN(___z,NUM,___data) r[ NUM ] = d##NUM ; -#define TOCKDIMS_MULT(___z,NUM,___data) * d##NUM - -#define TOCKDIMS(___z,NUM,___data) inline std::pair< boost::array,unsigned> tockDims(\ - const unsigned d0 BOOST_PP_REPEAT_FROM_TO(1,NUM,TOCKDIMS_ARGS,0) ) { \ - boost::array r; BOOST_PP_REPEAT(NUM,TOCKDIMS_ASSIGN,0) \ - return std::pair< boost::array , unsigned >(r,1 BOOST_PP_REPEAT_FROM_TO(1,NUM,TOCKDIMS_MULT,0) ); } - -//Up to 12 dimensions: -BOOST_PP_REPEAT_FROM_TO(2,12,TOCKDIMS,0) - - -template < typename T, unsigned DIMS > -class tockArrayView -{ - T* realArray; - boost::array dims; - //dims[1] * dims[2] * dims[3] ... - //If DIMS is 0 or 1, totalSubDim will be 1 - unsigned totalSubDim; - - template - inline void operator=(const U&) {} - - inline tockArrayView(T* _realArray,const boost::array& _biggerDims,unsigned _totalSubDim) - : realArray(_realArray),totalSubDim(_totalSubDim) - { - memcpy(dims.c_array(),_biggerDims.data() + 1,sizeof(unsigned) * DIMS); - } - friend class tockArrayView; - - //TODO change the other methods so we can feed a string in here (the Meta) to report to occam_stop - inline void correctDimsRetype(const unsigned totalSourceBytes) - { - if (totalSubDim == 0 || dims[0] == 0) - { - //Can only happen if one of the dimensions is zero, i.e. unknown - //We must find this dimension and calculate it: - - unsigned zeroDim; - unsigned totalDim = 1; - for (unsigned i = 0;i < DIMS;i++) - { - if (dims[i] == 0) - zeroDim = i; - else - totalDim *= dims[i]; - } - - //Check it fits exactly: - if ((totalSourceBytes / totalDim) % sizeof(T) != 0) - { - occam_stop ("", 3, "invalid size for RETYPES/RESHAPES (%d does not divide into %d)", (totalSourceBytes / totalDim), sizeof(T)); - } - - //Set the size of the unknown dimension: - dims[zeroDim] = (totalSourceBytes / totalDim) / sizeof(T); - - totalSubDim = (totalDim * dims[zeroDim]) / dims[0]; - } - - } - - -public: - inline tockArrayView() - : realArray(NULL) - { - dims.assign(0); - totalSubDim = 0; - } - - inline tockArrayView(const tockArrayView& v) - : realArray(v.realArray), - dims(v.dims), - totalSubDim(v.totalSubDim) - { - } - - - inline tockArrayView(T* _realArray,const std::pair< boost::array , unsigned >& _dims) - : realArray(_realArray),dims(_dims.first),totalSubDim(_dims.second) - { - } - - inline tockArrayView(std::vector::type>& _vec,const std::pair< boost::array , unsigned >& _dims) - : realArray(_vec.empty() ? NULL : &(_vec.at(0))),dims(_dims.first),totalSubDim(_dims.second) - { - } - - //The retyping constructors have their parameters in the other order to the same-type functions above, - //to avoid ambiguities between retyping and same types (especially when const is involved): - - template - inline tockArrayView(const std::pair< boost::array , unsigned >& _dims,U* _realArray) - : realArray(reinterpret_cast(_realArray)),dims(_dims.first),totalSubDim(_dims.second) - { - //Assume it's a single U item: - correctDimsRetype(sizeof(U)); - } - - - //Retyping, same number of dims: - template - inline tockArrayView(const std::pair< boost::array , unsigned >& _dims,const tockArrayView& tav) - : realArray(reinterpret_cast(tav.data())),dims(_dims.first),totalSubDim(_dims.second) - { - correctDimsRetype(tav.size() * sizeof(U)); - } - - inline tockArrayView operator[] (const unsigned index) const - { - return tockArrayView(realArray + (totalSubDim * index),dims,DIMS <= 1 ? 1 : (totalSubDim / dims[1])); - } - - inline tockArrayView sliceFor(const unsigned amount) const - { - return sliceFromFor(0,amount); - } - - inline tockArrayView sliceFrom(const unsigned index) const - { - return sliceFromFor(index,dims[0] - index); - } - - inline tockArrayView sliceFromFor(const unsigned index,const unsigned amount) const - { - boost::array sliceDims = dims; - sliceDims[0] = amount; - - return tockArrayView(realArray + (totalSubDim * index),std::make_pair(sliceDims,totalSubDim)); - } - - inline T* data() const - { - return realArray; - } - - inline const boost::array& getDims() const - { - return dims; - } - - inline unsigned getTotalSubDim() const - { - return totalSubDim; - } - - inline unsigned size() const - { - return dims[0] * totalSubDim; - } - - inline unsigned extent(const unsigned dim) const - { - return dims[dim]; - } - - inline operator tockArrayView() const - { - return tockArrayView((const T*)realArray,std::make_pair(dims,totalSubDim)); - } - -}; - -template -class tockArrayView -{ - T* realArray; - - inline tockArrayView(T* _realArray,boost::array,unsigned) - : realArray(_realArray) - { - } - - friend class tockArrayView; - -public: - - //Should only be used on arrays with zero dimensions: - inline T& access() const - { - return *realArray; - } -}; - class tockSendableArrayOfBytes { private: @@ -344,26 +126,12 @@ public: { } - ///Also for the sender: - template - inline explicit tockSendableArrayOfBytes(const tockArrayView& arr) - : n(0),sp(arr.data()) - { - } - ///For the receiver: inline tockSendableArrayOfBytes(unsigned _n,void* p) : n(_n),dp(p) { } - //Also for the receiver: - template - inline explicit tockSendableArrayOfBytes(unsigned _n, const tockArrayView& arr) - : n(_n),dp(arr.data()) - { - } - inline void operator=(const tockSendableArrayOfBytes& _src) { //We use the receiver's byte count: @@ -382,44 +150,6 @@ inline void tockRecvInt(const csp::Chanin& c, unsigned c >> d; } -template -class tockSendableArray -{ -private: - tockSendableArrayOfBytes aob; -public: - template - inline explicit tockSendableArray(const tockArrayView& arr) - : aob(N*sizeof(T),arr.data()) - { - } - - template - inline explicit tockSendableArray(const tockArrayView& arr) - : aob(arr.data()) - { - } -}; - -template -inline void tockSendArray(const csp::Chanout< tockSendableArray >& out,const tockArrayView& arr) -{ - out << tockSendableArray(arr); -} - -template -inline void tockRecvArray(const csp::Chanin< tockSendableArray >& in,const tockArrayView& arr) -{ - tockSendableArray tsa(arr); - in >> tsa; -} - -template -inline void tockSendArray(const csp::Chanout< tockSendableArray >& out,const tockArrayView& arr) -{ - out << tockSendableArray(arr); -} - inline void tockSendArrayOfBytes(const csp::Chanout& c, const tockSendableArrayOfBytes& b) { c << b;