Commit 75546791 by Marcus Winter

dataflow_cpp: check for cycles in graph

parent 60383a1c
...@@ -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) {
slices_ = slices; slices_ = slices;
values_ = reinterpret_cast<SignalType*>( values_ = reinterpret_cast<SignalType*>(
......
...@@ -106,6 +106,9 @@ class Inputs<T1, embb::base::internal::Nil, embb::base::internal::Nil, ...@@ -106,6 +106,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();
} }
...@@ -164,6 +167,9 @@ class Inputs<T1, T2, embb::base::internal::Nil, ...@@ -164,6 +167,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();
...@@ -228,6 +234,9 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil, ...@@ -228,6 +234,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() &
...@@ -297,6 +306,9 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil> ...@@ -297,6 +306,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() &
...@@ -373,6 +385,9 @@ class Inputs ...@@ -373,6 +385,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() &
......
...@@ -44,6 +44,7 @@ class Node { ...@@ -44,6 +44,7 @@ class Node {
virtual bool HasOutputs() const { return false; } virtual bool HasOutputs() const { return false; }
virtual void Run(int clock) = 0; virtual void Run(int clock) = 0;
virtual bool IsFullyConnected() = 0; virtual bool IsFullyConnected() = 0;
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>
...@@ -90,6 +102,11 @@ class Outputs<T1, T2, T3, embb::base::internal::Nil, ...@@ -90,6 +102,11 @@ class Outputs<T1, T2, T3, embb::base::internal::Nil,
this->template Get<1>().IsConnected() && this->template Get<1>().IsConnected() &&
this->template Get<2>().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>
...@@ -103,6 +120,12 @@ class Outputs<T1, T2, T3, T4, embb::base::internal::Nil> ...@@ -103,6 +120,12 @@ class Outputs<T1, T2, T3, T4, embb::base::internal::Nil>
this->template Get<2>().IsConnected() && this->template Get<2>().IsConnected() &&
this->template Get<3>().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,
...@@ -118,6 +141,13 @@ class Outputs ...@@ -118,6 +141,13 @@ class Outputs
this->template Get<3>().IsConnected() && this->template Get<3>().IsConnected() &&
this->template Get<4>().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
......
...@@ -98,6 +98,10 @@ class Process< Serial, Inputs<I1, I2, I3, I4, I5>, ...@@ -98,6 +98,10 @@ class Process< Serial, Inputs<I1, I2, I3, I4, I5>,
return inputs_.IsFullyConnected() && outputs_.IsFullyConnected(); return inputs_.IsFullyConnected() && outputs_.IsFullyConnected();
} }
virtual bool HasCycle() {
return outputs_.HasCycle(this);
}
InputsType & GetInputs() { InputsType & GetInputs() {
return inputs_; return inputs_;
} }
...@@ -160,6 +164,15 @@ class Process< Serial, Inputs<I1, I2, I3, I4, I5>, ...@@ -160,6 +164,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_;
} }
......
...@@ -838,14 +838,19 @@ class Network : public internal::ClockListener { ...@@ -838,14 +838,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