Removed a lot of old comments and support code relating to the way arrays used to be handled in the C++ backend
This commit is contained in:
parent
e1fd001322
commit
5197435b2c
|
@ -25,46 +25,6 @@ In order to compile the generated code, you will need:
|
|||
|
||||
* The C++CSP2 library (>= 2.0.2), available from <http://www.cppcsp.net/>, 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
|
||||
|
|
|
@ -109,224 +109,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//For tieing together chained tuples:
|
||||
|
||||
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
|
||||
class T8, class T9, class T10>
|
||||
inline boost::tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&, T10>
|
||||
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>
|
||||
(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
|
||||
}
|
||||
|
||||
inline std::pair< boost::array<unsigned,1> , unsigned > tockDims(const unsigned d0)
|
||||
{
|
||||
boost::array<unsigned,1> r;
|
||||
r[0] = d0;
|
||||
return std::pair< boost::array<unsigned,1> , unsigned >(r,d0 == 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
/*
|
||||
Generates functions like this:
|
||||
inline std::pair< boost::array<unsigned,2> , unsigned > tockDims(const unsigned d0,const unsigned d1,const unsigned d2)
|
||||
{
|
||||
boost::array<unsigned,2> r;
|
||||
r[0] = d0;
|
||||
r[1] = d1;
|
||||
r[2] = d2;
|
||||
return std::pair< boost::array<unsigned,2> , 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, NUM >,unsigned> tockDims(\
|
||||
const unsigned d0 BOOST_PP_REPEAT_FROM_TO(1,NUM,TOCKDIMS_ARGS,0) ) { \
|
||||
boost::array<unsigned, NUM > r; BOOST_PP_REPEAT(NUM,TOCKDIMS_ASSIGN,0) \
|
||||
return std::pair< boost::array<unsigned, NUM > , 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<unsigned,DIMS> dims;
|
||||
//dims[1] * dims[2] * dims[3] ...
|
||||
//If DIMS is 0 or 1, totalSubDim will be 1
|
||||
unsigned totalSubDim;
|
||||
|
||||
template <typename U>
|
||||
inline void operator=(const U&) {}
|
||||
|
||||
inline tockArrayView(T* _realArray,const boost::array<unsigned,DIMS+1>& _biggerDims,unsigned _totalSubDim)
|
||||
: realArray(_realArray),totalSubDim(_totalSubDim)
|
||||
{
|
||||
memcpy(dims.c_array(),_biggerDims.data() + 1,sizeof(unsigned) * DIMS);
|
||||
}
|
||||
friend class tockArrayView<T,DIMS + 1>;
|
||||
|
||||
//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> , unsigned >& _dims)
|
||||
: realArray(_realArray),dims(_dims.first),totalSubDim(_dims.second)
|
||||
{
|
||||
}
|
||||
|
||||
inline tockArrayView(std::vector<typename boost::remove_const<T>::type>& _vec,const std::pair< boost::array<unsigned,DIMS> , 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 <typename U>
|
||||
inline tockArrayView(const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims,U* _realArray)
|
||||
: realArray(reinterpret_cast<T*>(_realArray)),dims(_dims.first),totalSubDim(_dims.second)
|
||||
{
|
||||
//Assume it's a single U item:
|
||||
correctDimsRetype(sizeof(U));
|
||||
}
|
||||
|
||||
|
||||
//Retyping, same number of dims:
|
||||
template <typename U,unsigned FROMDIMS>
|
||||
inline tockArrayView(const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims,const tockArrayView<U,FROMDIMS>& tav)
|
||||
: realArray(reinterpret_cast<T*>(tav.data())),dims(_dims.first),totalSubDim(_dims.second)
|
||||
{
|
||||
correctDimsRetype(tav.size() * sizeof(U));
|
||||
}
|
||||
|
||||
inline tockArrayView<T,DIMS - 1> operator[] (const unsigned index) const
|
||||
{
|
||||
return tockArrayView<T,DIMS - 1>(realArray + (totalSubDim * index),dims,DIMS <= 1 ? 1 : (totalSubDim / dims[1]));
|
||||
}
|
||||
|
||||
inline tockArrayView<T,DIMS> sliceFor(const unsigned amount) const
|
||||
{
|
||||
return sliceFromFor(0,amount);
|
||||
}
|
||||
|
||||
inline tockArrayView<T,DIMS> sliceFrom(const unsigned index) const
|
||||
{
|
||||
return sliceFromFor(index,dims[0] - index);
|
||||
}
|
||||
|
||||
inline tockArrayView<T,DIMS> sliceFromFor(const unsigned index,const unsigned amount) const
|
||||
{
|
||||
boost::array<unsigned,DIMS> sliceDims = dims;
|
||||
sliceDims[0] = amount;
|
||||
|
||||
return tockArrayView<T,DIMS>(realArray + (totalSubDim * index),std::make_pair(sliceDims,totalSubDim));
|
||||
}
|
||||
|
||||
inline T* data() const
|
||||
{
|
||||
return realArray;
|
||||
}
|
||||
|
||||
inline const boost::array<unsigned,DIMS>& 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 T,DIMS>() const
|
||||
{
|
||||
return tockArrayView<const T,DIMS>((const T*)realArray,std::make_pair(dims,totalSubDim));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class tockArrayView<T,0>
|
||||
{
|
||||
T* realArray;
|
||||
|
||||
inline tockArrayView(T* _realArray,boost::array<unsigned,1>,unsigned)
|
||||
: realArray(_realArray)
|
||||
{
|
||||
}
|
||||
|
||||
friend class tockArrayView<T,1>;
|
||||
|
||||
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 <typename T, unsigned N>
|
||||
inline explicit tockSendableArrayOfBytes(const tockArrayView<T,N>& arr)
|
||||
: n(0),sp(arr.data())
|
||||
{
|
||||
}
|
||||
|
||||
///For the receiver:
|
||||
inline tockSendableArrayOfBytes(unsigned _n,void* p)
|
||||
: n(_n),dp(p)
|
||||
{
|
||||
}
|
||||
|
||||
//Also for the receiver:
|
||||
template <typename T, unsigned N>
|
||||
inline explicit tockSendableArrayOfBytes(unsigned _n, const tockArrayView<T,N>& 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<tockSendableArrayOfBytes>& c, unsigned
|
|||
c >> d;
|
||||
}
|
||||
|
||||
template <typename T, unsigned N>
|
||||
class tockSendableArray
|
||||
{
|
||||
private:
|
||||
tockSendableArrayOfBytes aob;
|
||||
public:
|
||||
template <unsigned D>
|
||||
inline explicit tockSendableArray(const tockArrayView<T,D>& arr)
|
||||
: aob(N*sizeof(T),arr.data())
|
||||
{
|
||||
}
|
||||
|
||||
template <unsigned D>
|
||||
inline explicit tockSendableArray(const tockArrayView<const T,D>& arr)
|
||||
: aob(arr.data())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, unsigned N, unsigned D>
|
||||
inline void tockSendArray(const csp::Chanout< tockSendableArray<T,N> >& out,const tockArrayView<T,D>& arr)
|
||||
{
|
||||
out << tockSendableArray<T,N>(arr);
|
||||
}
|
||||
|
||||
template <typename T, unsigned N, unsigned D>
|
||||
inline void tockRecvArray(const csp::Chanin< tockSendableArray<T,N> >& in,const tockArrayView<T,D>& arr)
|
||||
{
|
||||
tockSendableArray<T,N> tsa(arr);
|
||||
in >> tsa;
|
||||
}
|
||||
|
||||
template <typename T, unsigned N, unsigned D>
|
||||
inline void tockSendArray(const csp::Chanout< tockSendableArray<T,N> >& out,const tockArrayView<const T,D>& arr)
|
||||
{
|
||||
out << tockSendableArray<T,N>(arr);
|
||||
}
|
||||
|
||||
inline void tockSendArrayOfBytes(const csp::Chanout<tockSendableArrayOfBytes>& c, const tockSendableArrayOfBytes& b)
|
||||
{
|
||||
c << b;
|
||||
|
|
Loading…
Reference in New Issue
Block a user