Commit 1007a462 by Marcus Winter

Merge branch 'embb565_dataflow_network_consistency_checking' into development

# Conflicts:
#	dataflow_cpp/include/embb/dataflow/internal/node.h
#	dataflow_cpp/include/embb/dataflow/internal/process.h
#	dataflow_cpp/include/embb/dataflow/network.h
parents 7bc10024 301d6abd
...@@ -35,6 +35,7 @@ class ClockListener { ...@@ -35,6 +35,7 @@ class ClockListener {
public: public:
virtual ~ClockListener() {} virtual ~ClockListener() {}
virtual void OnClock(int /*clock*/) = 0; virtual void OnClock(int /*clock*/) = 0;
virtual bool OnHasCycle(ClockListener * /*node*/) { return false; }
}; };
} // namespace internal } // namespace internal
......
...@@ -73,6 +73,10 @@ class In { ...@@ -73,6 +73,10 @@ class In {
bool IsConnected() const { return connected_; } bool IsConnected() const { return connected_; }
void SetConnected() { connected_ = true; } void SetConnected() { connected_ = true; }
bool HasCycle(ClockListener * node) {
return listener_->OnHasCycle(node);
}
void SetSlices(int slices) { void SetSlices(int slices) {
if (0 < slices_) { if (0 < slices_) {
for (int ii = 0; ii < slices_; ii++) { for (int ii = 0; ii < slices_; ii++) {
......
...@@ -117,6 +117,9 @@ class Inputs<T1, embb::base::internal::Nil, embb::base::internal::Nil, ...@@ -117,6 +117,9 @@ class Inputs<T1, embb::base::internal::Nil, embb::base::internal::Nil,
listener_->OnClock(clock); listener_->OnClock(clock);
} }
} }
virtual bool OnHasCycle(ClockListener * node) {
return listener_->OnHasCycle(node);
}
bool IsFullyConnected() { bool IsFullyConnected() {
return this->template Get<0>().IsConnected(); return this->template Get<0>().IsConnected();
} }
...@@ -185,6 +188,9 @@ class Inputs<T1, T2, embb::base::internal::Nil, ...@@ -185,6 +188,9 @@ class Inputs<T1, T2, embb::base::internal::Nil,
listener_->OnClock(clock); listener_->OnClock(clock);
} }
} }
virtual bool OnHasCycle(ClockListener * node) {
return listener_->OnHasCycle(node);
}
bool IsFullyConnected() { bool IsFullyConnected() {
return this->template Get<0>().IsConnected() & return this->template Get<0>().IsConnected() &
this->template Get<1>().IsConnected(); this->template Get<1>().IsConnected();
...@@ -259,6 +265,9 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil, ...@@ -259,6 +265,9 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil,
listener_->OnClock(clock); listener_->OnClock(clock);
} }
} }
virtual bool OnHasCycle(ClockListener * node) {
return listener_->OnHasCycle(node);
}
bool IsFullyConnected() { bool IsFullyConnected() {
return this->template Get<0>().IsConnected() & return this->template Get<0>().IsConnected() &
this->template Get<1>().IsConnected() & this->template Get<1>().IsConnected() &
...@@ -338,6 +347,9 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil> ...@@ -338,6 +347,9 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil>
listener_->OnClock(clock); listener_->OnClock(clock);
} }
} }
virtual bool OnHasCycle(ClockListener * node) {
return listener_->OnHasCycle(node);
}
bool IsFullyConnected() { bool IsFullyConnected() {
return this->template Get<0>().IsConnected() & return this->template Get<0>().IsConnected() &
this->template Get<1>().IsConnected() & this->template Get<1>().IsConnected() &
...@@ -424,6 +436,9 @@ class Inputs ...@@ -424,6 +436,9 @@ class Inputs
listener_->OnClock(clock); listener_->OnClock(clock);
} }
} }
virtual bool OnHasCycle(ClockListener * node) {
return listener_->OnHasCycle(node);
}
bool IsFullyConnected() { bool IsFullyConnected() {
return this->template Get<0>().IsConnected() && return this->template Get<0>().IsConnected() &&
this->template Get<1>().IsConnected() & this->template Get<1>().IsConnected() &
......
...@@ -45,6 +45,7 @@ class Node { ...@@ -45,6 +45,7 @@ class Node {
virtual void Run(int clock) = 0; virtual void Run(int clock) = 0;
virtual bool IsFullyConnected() = 0; virtual bool IsFullyConnected() = 0;
virtual bool IsSequential() { return true; } virtual bool IsSequential() { return true; }
virtual bool HasCycle() { return false; }
virtual bool Start(int /*clock*/) { virtual bool Start(int /*clock*/) {
EMBB_THROW(embb::base::ErrorException, EMBB_THROW(embb::base::ErrorException,
"Nodes are started implicitly."); "Nodes are started implicitly.");
......
...@@ -36,6 +36,7 @@ namespace dataflow { ...@@ -36,6 +36,7 @@ namespace dataflow {
namespace internal { namespace internal {
class Scheduler; class Scheduler;
class ClockListener;
template <typename Type> template <typename Type>
class Out { class Out {
...@@ -70,6 +71,14 @@ class Out { ...@@ -70,6 +71,14 @@ class Out {
return targets_.size() > 0; return targets_.size() > 0;
} }
bool HasCycle(ClockListener * node) {
bool result = false;
for (size_t ii = 0; ii < targets_.size() && !result; ii++) {
result = result || targets_[ii]->HasCycle(node);
}
return result;
}
private: private:
std::vector< InType * > targets_; std::vector< InType * > targets_;
}; };
......
...@@ -42,6 +42,8 @@ template < ...@@ -42,6 +42,8 @@ template <
typename = embb::base::internal::Nil > typename = embb::base::internal::Nil >
class Outputs; class Outputs;
class ClockListener;
template <> template <>
class Outputs<embb::base::internal::Nil, embb::base::internal::Nil, class Outputs<embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil, embb::base::internal::Nil, embb::base::internal::Nil,
...@@ -53,6 +55,9 @@ class Outputs<embb::base::internal::Nil, embb::base::internal::Nil, ...@@ -53,6 +55,9 @@ class Outputs<embb::base::internal::Nil, embb::base::internal::Nil,
bool IsFullyConnected() { bool IsFullyConnected() {
return true; return true;
} }
bool HasCycle(ClockListener * /*node*/) {
return false;
}
}; };
template <typename T1> template <typename T1>
...@@ -65,6 +70,9 @@ class Outputs<T1, embb::base::internal::Nil, embb::base::internal::Nil, ...@@ -65,6 +70,9 @@ class Outputs<T1, embb::base::internal::Nil, embb::base::internal::Nil,
bool IsFullyConnected() { bool IsFullyConnected() {
return this->template Get<0>().IsConnected(); return this->template Get<0>().IsConnected();
} }
bool HasCycle(ClockListener * node) {
return this->template Get<0>().HasCycle(node);
}
}; };
template <typename T1, typename T2> template <typename T1, typename T2>
...@@ -77,6 +85,10 @@ class Outputs<T1, T2, embb::base::internal::Nil, ...@@ -77,6 +85,10 @@ class Outputs<T1, T2, embb::base::internal::Nil,
return this->template Get<0>().IsConnected() && return this->template Get<0>().IsConnected() &&
this->template Get<1>().IsConnected(); this->template Get<1>().IsConnected();
} }
bool HasCycle(ClockListener * node) {
return this->template Get<0>().HasCycle(node) ||
this->template Get<1>().HasCycle(node);
}
}; };
template <typename T1, typename T2, typename T3> template <typename T1, typename T2, typename T3>
...@@ -85,6 +97,16 @@ class Outputs<T1, T2, T3, embb::base::internal::Nil, ...@@ -85,6 +97,16 @@ class Outputs<T1, T2, T3, embb::base::internal::Nil,
: public Tuple<Out<T1>, Out<T2>, Out<T3>, : public Tuple<Out<T1>, Out<T2>, Out<T3>,
embb::base::internal::Nil, embb::base::internal::Nil> { embb::base::internal::Nil, embb::base::internal::Nil> {
public: public:
bool IsFullyConnected() {
return this->template Get<0>().IsConnected() &&
this->template Get<1>().IsConnected() &&
this->template Get<2>().IsConnected();
}
bool HasCycle(ClockListener * node) {
return this->template Get<0>().HasCycle(node) ||
this->template Get<1>().HasCycle(node) ||
this->template Get<2>().HasCycle(node);
}
}; };
template <typename T1, typename T2, typename T3, typename T4> template <typename T1, typename T2, typename T3, typename T4>
...@@ -92,6 +114,18 @@ class Outputs<T1, T2, T3, T4, embb::base::internal::Nil> ...@@ -92,6 +114,18 @@ class Outputs<T1, T2, T3, T4, embb::base::internal::Nil>
: public Tuple<Out<T1>, Out<T2>, Out<T3>, : public Tuple<Out<T1>, Out<T2>, Out<T3>,
Out<T4>, embb::base::internal::Nil>{ Out<T4>, embb::base::internal::Nil>{
public: public:
bool IsFullyConnected() {
return this->template Get<0>().IsConnected() &&
this->template Get<1>().IsConnected() &&
this->template Get<2>().IsConnected() &&
this->template Get<3>().IsConnected();
}
bool HasCycle(ClockListener * node) {
return this->template Get<0>().HasCycle(node) ||
this->template Get<1>().HasCycle(node) ||
this->template Get<2>().HasCycle(node) ||
this->template Get<3>().HasCycle(node);
}
}; };
template <typename T1, typename T2, typename T3, typename T4, template <typename T1, typename T2, typename T3, typename T4,
...@@ -100,6 +134,20 @@ class Outputs ...@@ -100,6 +134,20 @@ class Outputs
: public Tuple<Out<T1>, Out<T2>, Out<T3>, : public Tuple<Out<T1>, Out<T2>, Out<T3>,
Out<T4>, Out<T5> > { Out<T4>, Out<T5> > {
public: public:
bool IsFullyConnected() {
return this->template Get<0>().IsConnected() &&
this->template Get<1>().IsConnected() &&
this->template Get<2>().IsConnected() &&
this->template Get<3>().IsConnected() &&
this->template Get<4>().IsConnected();
}
bool HasCycle(ClockListener * node) {
return this->template Get<0>().HasCycle(node) ||
this->template Get<1>().HasCycle(node) ||
this->template Get<2>().HasCycle(node) ||
this->template Get<3>().HasCycle(node) ||
this->template Get<4>().HasCycle(node);
}
}; };
} // namespace internal } // namespace internal
......
...@@ -96,6 +96,10 @@ class Process< Serial, Inputs<I1, I2, I3, I4, I5>, ...@@ -96,6 +96,10 @@ class Process< Serial, Inputs<I1, I2, I3, I4, I5>,
return Serial; return Serial;
} }
virtual bool HasCycle() {
return outputs_.HasCycle(this);
}
InputsType & GetInputs() { InputsType & GetInputs() {
return inputs_; return inputs_;
} }
...@@ -158,6 +162,15 @@ class Process< Serial, Inputs<I1, I2, I3, I4, I5>, ...@@ -158,6 +162,15 @@ class Process< Serial, Inputs<I1, I2, I3, I4, I5>,
} }
} }
virtual bool OnHasCycle(ClockListener * node) {
ClockListener * this_node = this;
if (this_node == node) {
return true;
} else {
return outputs_.HasCycle(node);
}
}
private: private:
InputsType inputs_; InputsType inputs_;
OutputsType outputs_; OutputsType outputs_;
......
...@@ -85,6 +85,15 @@ class Select ...@@ -85,6 +85,15 @@ class Select
return inputs_.IsFullyConnected() && outputs_.IsFullyConnected(); return inputs_.IsFullyConnected() && outputs_.IsFullyConnected();
} }
virtual bool OnHasCycle(ClockListener * node) {
ClockListener * this_node = this;
if (this_node == node) {
return true;
} else {
return outputs_.HasCycle(node);
}
}
InputsType & GetInputs() { InputsType & GetInputs() {
return inputs_; return inputs_;
} }
......
...@@ -82,6 +82,15 @@ class Switch ...@@ -82,6 +82,15 @@ class Switch
return inputs_.IsFullyConnected() && outputs_.IsFullyConnected(); return inputs_.IsFullyConnected() && outputs_.IsFullyConnected();
} }
virtual bool OnHasCycle(ClockListener * node) {
ClockListener * this_node = this;
if (this_node == node) {
return true;
} else {
return outputs_.HasCycle(node);
}
}
InputsType & GetInputs() { InputsType & GetInputs() {
return inputs_; return inputs_;
} }
......
...@@ -676,6 +676,8 @@ class Network { ...@@ -676,6 +676,8 @@ class Network {
/** /**
* Checks whether the network is completely connected and free of cycles. * Checks whether the network is completely connected and free of cycles.
* \returns \c true if everything is in order, \c false if not. * \returns \c true if everything is in order, \c false if not.
* \note Executing an invalid network results in an exception. For this
* reason, it is recommended to first check the network using IsValid().
*/ */
bool IsValid(); bool IsValid();
...@@ -685,6 +687,8 @@ class Network { ...@@ -685,6 +687,8 @@ class Network {
* tokens will automatically be derived from the structure of the network * tokens will automatically be derived from the structure of the network
* on the first call of the operator, and the corresponding resources will * on the first call of the operator, and the corresponding resources will
* be allocated then. * be allocated then.
* \note Executing an invalid network results in an exception. For this
* reason, it is recommended to first check the network using IsValid().
*/ */
void operator () (); void operator () ();
}; };
...@@ -846,14 +850,19 @@ class Network : public internal::ClockListener { ...@@ -846,14 +850,19 @@ class Network : public internal::ClockListener {
bool IsValid() { bool IsValid() {
bool valid = true; bool valid = true;
for (size_t ii = 0; ii < sources_.size(); ii++) { // check connectivity
valid = valid & sources_[ii]->IsFullyConnected(); for (size_t ii = 0; ii < sources_.size() && valid; ii++) {
valid = valid && sources_[ii]->IsFullyConnected();
} }
for (size_t ii = 0; ii < processes_.size(); ii++) { for (size_t ii = 0; ii < processes_.size() && valid; ii++) {
valid = valid & processes_[ii]->IsFullyConnected(); valid = valid && processes_[ii]->IsFullyConnected();
} }
for (size_t ii = 0; ii < sinks_.size(); ii++) { for (size_t ii = 0; ii < sinks_.size() && valid; ii++) {
valid = valid & sinks_[ii]->IsFullyConnected(); valid = valid && sinks_[ii]->IsFullyConnected();
}
// check for cycles
for (size_t ii = 0; ii < processes_.size() && valid; ii++) {
valid = valid && !processes_[ii]->HasCycle();
} }
return valid; return valid;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment