Skip to content

Commit

Permalink
Signal class rewritten
Browse files Browse the repository at this point in the history
- Added support to contiguous inputs (which are now the default setting)
- For non-contiguous signals, an internal buffer is allocated with signal data, and data copy has been minimized as much as possible
- When gathering a signal from Matlab, data type and signal are now read directly from the SimStruct
- For the time being, only double signal are supported, which are the Simulink defaults. The structure for including the support of other data types is already present, and it will be included in the upcoming releases
  • Loading branch information
diegoferigo committed Feb 22, 2018
1 parent 9652ba5 commit deed69e
Show file tree
Hide file tree
Showing 6 changed files with 467 additions and 428 deletions.
48 changes: 7 additions & 41 deletions toolbox/include/base/BlockInformation.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "AnyType.h"
#include <string>
#include <cstdint>

namespace wbt {
class BlockInformation;
Expand All @@ -21,37 +20,6 @@ namespace wbt {
PortDataTypeBoolean,
} PortDataType;

class Data
{
private:
double buffer;
public:
inline double doubleData() const { return buffer; }
inline void doubleData(const double& data) { buffer = data; }
inline float floatData() const { return static_cast<float>(buffer); }
inline void floatData(const float& data) { buffer = static_cast<float>(data); }

inline int8_t int8Data() const { return static_cast<int8_t>(buffer); }
inline void int8Data(const int8_t& data) { buffer = static_cast<int8_t>(data); }
inline uint8_t uint8Data() const { return static_cast<uint8_t>(buffer); }
inline void uint8Data(const uint8_t& data) { buffer = static_cast<uint8_t>(data); }

inline int16_t int16Data() const { return static_cast<int16_t>(buffer); }
inline void int16Data(const int16_t& data) { buffer = static_cast<int16_t>(data); }
inline uint16_t uint16Data() const { return static_cast<uint16_t>(buffer); }
inline void uint16Data(const uint16_t& data) { buffer = static_cast<uint16_t>(data); }

inline int32_t int32Data() const { return static_cast<int32_t>(buffer); }
inline void int32Data(const int32_t& data) { buffer = static_cast<int32_t>(data); }
inline uint32_t uint32Data() const { return static_cast<uint32_t>(buffer); }
inline void uint32Data(const uint32_t& data) { buffer = static_cast<uint32_t>(data); }

inline bool booleanData() const { return static_cast<bool>(buffer); }
inline void booleanData(const bool& data) { buffer = static_cast<bool>(data); }

friend Signal;
};

extern const std::string BlockOptionPrioritizeOrder;
}

Expand All @@ -61,7 +29,7 @@ class wbt::BlockInformation {
BlockInformation() = default;
virtual ~BlockInformation() = default;

// Block Options methods
// BLOCK OPTIONS METHODS
// =====================

/**
Expand All @@ -74,7 +42,7 @@ class wbt::BlockInformation {
virtual bool optionFromKey(const std::string& key, double& option) const;


// Parameters methods
// PARAMETERS METHODS
// ==================

/**
Expand All @@ -88,12 +56,10 @@ class wbt::BlockInformation {
virtual bool getStringParameterAtIndex(unsigned parameterIndex, std::string& stringParameter) const = 0;
virtual bool getScalarParameterAtIndex(unsigned parameterIndex, double& value) const = 0;
virtual bool getBooleanParameterAtIndex(unsigned parameterIndex, bool& value) const = 0;
// virtual bool getAnyTypeAtIndex(unsigned parameterIndex, AnyType* data) = 0;
// virtual bool getCellAtIndex(unsigned parameterIndex, AnyCell& map) = 0;
virtual bool getStructAtIndex(unsigned parameterIndex, AnyStruct& map) const = 0;
virtual bool getVectorAtIndex(unsigned parameterIndex, std::vector<double>& vec) const = 0;

// Port information methods
// PORT INFORMATION SETTERS
// ========================

virtual bool setNumberOfInputPorts(unsigned numberOfPorts) = 0;
Expand All @@ -114,13 +80,13 @@ class wbt::BlockInformation {
virtual bool setInputPortType(unsigned portNumber, PortDataType portType) = 0;
virtual bool setOutputPortType(unsigned portNumber, PortDataType portType) = 0;

// Port data
// =========
// PORT INFORMATION GETTERS
// ========================

virtual unsigned getInputPortWidth(unsigned portNumber) const = 0;
virtual unsigned getOutputPortWidth(unsigned portNumber) const = 0;
virtual wbt::Signal getInputPortSignal(unsigned portNumber) const = 0;
virtual wbt::Signal getOutputPortSignal(unsigned portNumber)const = 0;
virtual wbt::Signal getInputPortSignal(unsigned portNumber, int portWidth = -1) const = 0;
virtual wbt::Signal getOutputPortSignal(unsigned portNumber, int portWidth = -1) const = 0;
};

#endif /* end of include guard: WBT_BLOCKINFORMATION_H */
175 changes: 150 additions & 25 deletions toolbox/include/base/Signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,175 @@
#define WBT_SIGNAL_H

#include "BlockInformation.h"
#include <vector>
#include <cassert>
#include <memory>

namespace wbt {
class Signal;
enum SignalDataFormat {
NONCONTIGUOUS = 0,
CONTIGUOUS = 1,
CONTIGUOUS_ZEROCOPY = 2
};
}

class wbt::Signal
{
private:
PortDataType portType;
bool isContiguous;
bool isConstPort;
int m_width;
const bool m_isConst;
const PortDataType m_portDataType;
const SignalDataFormat m_dataFormat;

void** nonContiguousData;
void* contiguousData;
void* m_bufferPtr;

void deleteBuffer();
void allocateBuffer(const void* const bufferInput, void*& bufferOutput, unsigned length);

template <typename T> T* getCastBuffer() const;

public:
Signal();
// Ctor and Dtor
Signal(const SignalDataFormat& dataFormat = CONTIGUOUS_ZEROCOPY,
const PortDataType& dataType = PortDataTypeDouble,
const bool& isConst = true);
~Signal();
// Copy
Signal(const Signal& signal);
Signal& operator=(const Signal& signal) = delete;
// Move
Signal(Signal&& signal);
Signal& operator=(Signal&& signal) = delete;

void initSignalType(wbt::PortDataType type, bool constPort);
bool initializeBufferFromContiguous(const void* buffer);
bool initializeBufferFromContiguousZeroCopy(const void* buffer);
bool initializeBufferFromNonContiguous(const void* const* bufferPtrs);

void setContiguousBuffer(void* buffer);
void setContiguousBuffer(const void* buffer);
void setNonContiguousBuffer(void** buffer);
void setNonContiguousBuffer(const void* const* buffer);
bool isConst() const;
unsigned getWidth() const;
PortDataType getPortDataType() const;
SignalDataFormat getDataFormat() const;
template <typename T> T* getBuffer() const;
template <typename T> T get(const unsigned& i) const;

const Data get(unsigned index) const;
void* getContiguousBuffer();
std::vector<double> getStdVector(unsigned length) const;
void setWidth(const unsigned& width);
bool set(const unsigned& index, const double& data);
template <typename T> bool setBuffer(const T* data, const unsigned& length);
};

//the missing are cast
void set(unsigned index, double data);
void setBuffer(const double* data, const unsigned length, unsigned startIndex = 0);
template <typename T>
T* wbt::Signal::getBuffer() const
{
// Check the returned matches the same type of the portType.
// If this is not met, appliying pointer arithmetics on the returned
// pointer would show unknown behaviour.
switch(m_portDataType) {
case wbt::PortDataTypeDouble:
if (typeid(T).hash_code() != typeid(double).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeSingle:
if (typeid(T).hash_code() != typeid(float).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeInt8:
if (typeid(T).hash_code() != typeid(int8_t).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeUInt8:
if (typeid(T).hash_code() != typeid(uint8_t).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeInt16:
if (typeid(T).hash_code() != typeid(int16_t).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeUInt16:
if (typeid(T).hash_code() != typeid(uint16_t).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeInt32:
if (typeid(T).hash_code() != typeid(int32_t).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeUInt32:
if (typeid(T).hash_code() != typeid(uint32_t).hash_code()) {
return nullptr;
}
break;
case wbt::PortDataTypeBoolean:
if (typeid(T).hash_code() != typeid(bool).hash_code()) {
return nullptr;
}
break;
default:
return nullptr;
break;
}

void set(unsigned index, int32_t data);
void setBuffer(const int32_t* data, const unsigned length, unsigned startIndex = 0);
// Return the correct pointer
return static_cast<T*>(m_bufferPtr);
}

void set(unsigned index, uint32_t data);
void setBuffer(const uint32_t* data, const unsigned length, unsigned startIndex = 0);
template <typename T>
bool wbt::Signal::setBuffer(const T* data, const unsigned& length)
{
// Non contiguous signals follow the Simulink convention of being read-only
if (m_dataFormat == NONCONTIGUOUS || m_isConst) {
return false;
}

void set(unsigned index, bool data);
void setBuffer(const bool* data, const unsigned length, unsigned startIndex = 0);
if (m_dataFormat == CONTIGUOUS_ZEROCOPY && length > m_width) {
return false;
}

};
if (typeid(getBuffer<T>()).hash_code() != typeid(T*).hash_code()) {
return false;
}

switch (m_dataFormat) {
case CONTIGUOUS:
// Delete the current array
if (m_bufferPtr) {
delete getBuffer<T>();
m_bufferPtr = nullptr;
m_width = 0;
}
// Allocate a new empty array
m_bufferPtr = static_cast<void*>(new T[length]);
m_width = length;
// Fill it with new data
std::copy(data, data + length, getBuffer<T>());
break;
case CONTIGUOUS_ZEROCOPY:
// Reset current data
std::fill(getBuffer<T>(), getBuffer<T>() + m_width, 0);
// Copy new data
std::copy(data, data + length, getBuffer<T>());
// Update the width
m_width = length;
break;
case NONCONTIGUOUS:
return false;
}

return true;
}

template <typename T>
T wbt::Signal::get(const unsigned& i) const
{
T* buffer = getBuffer<T>();
assert(buffer);

return buffer[i];
}

#endif /* end of include guard: WBT_SIGNAL_H */
22 changes: 17 additions & 5 deletions toolbox/include/base/SimulinkBlockInformation.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,30 @@ class wbt::SimulinkBlockInformation : public wbt::BlockInformation
private:
SimStruct* simstruct;

PortDataType mapSimulinkToPortType(const DTypeId& typeId) const;
DTypeId mapPortTypeToSimulink(const PortDataType& dataType) const;

public:
SimulinkBlockInformation(SimStruct* simstruct);
~SimulinkBlockInformation() override = default;

// BLOCK OPTIONS METHODS
// =====================

bool optionFromKey(const std::string& key, double& option) const override;

//Parameters methods
// PARAMETERS METHODS
// ==================

bool getStringParameterAtIndex(unsigned parameterIndex, std::string& stringParameter) const override;
bool getScalarParameterAtIndex(unsigned parameterIndex, double& value) const override;
bool getBooleanParameterAtIndex(unsigned parameterIndex, bool& value) const override;
bool getStructAtIndex(unsigned parameterIndex, AnyStruct& map) const override;
bool getVectorAtIndex(unsigned parameterIndex, std::vector<double>& vec) const override;

//Port information methods
// PORT INFORMATION SETTERS
// ========================

bool setNumberOfInputPorts(unsigned numberOfPorts) override;
bool setNumberOfOutputPorts(unsigned numberOfPorts) override;
bool setInputPortVectorSize(unsigned portNumber, int portSize) override;
Expand All @@ -38,11 +48,13 @@ class wbt::SimulinkBlockInformation : public wbt::BlockInformation
bool setInputPortType(unsigned portNumber, PortDataType portType) override;
bool setOutputPortType(unsigned portNumber, PortDataType portType) override;

//Port data
// PORT INFORMATION GETTERS
// ========================

unsigned getInputPortWidth(unsigned portNumber) const override;
unsigned getOutputPortWidth(unsigned portNumber) const override;
wbt::Signal getInputPortSignal(unsigned portNumber) const override;
wbt::Signal getOutputPortSignal(unsigned portNumber) const override;
wbt::Signal getInputPortSignal(unsigned portNumber, int portWidth = DYNAMICALLY_SIZED) const override;
wbt::Signal getOutputPortSignal(unsigned portNumber, int portWidth = DYNAMICALLY_SIZED) const override;
};

#endif /* end of include guard: WBT_SIMULINKBLOCKINFORMATION_H */
Loading

0 comments on commit deed69e

Please sign in to comment.