Commit 76afcbb3 by Marcus Winter

dataflow_cpp: number of slices can now be set at runtime

parent 2f7e8112
......@@ -35,6 +35,7 @@ class Scheduler;
class ClockListener;
struct InitData {
int slices;
Scheduler * sched;
ClockListener * sink_listener;
};
......
......@@ -35,11 +35,11 @@ namespace embb {
namespace dataflow {
namespace internal {
template <int Slices, typename Type>
template <typename Type>
class ConstantSource
: public Node {
public:
typedef Outputs<Slices, Type> OutputsType;
typedef Outputs<Type> OutputsType;
private:
OutputsType outputs_;
......
......@@ -41,18 +41,18 @@ namespace internal {
class Scheduler;
template <typename, int>
template <typename>
class Out;
template <typename Type, int Slices>
template <typename Type>
class In {
public:
typedef Signal<Type> SignalType;
In() : connected_(false) {}
In() : values_(NULL), connected_(false), slices_(0) {}
SignalType const & GetSignal(int clock) const {
return values_[clock % Slices];
return values_[clock % slices_];
}
Type GetValue(int clock) const {
......@@ -66,26 +66,37 @@ class In {
bool IsConnected() const { return connected_; }
void SetConnected() { connected_ = true; }
void SetSlices(int slices) {
slices_ = slices;
values_ = reinterpret_cast<SignalType*>(
embb::base::Allocation::Allocate(
sizeof(SignalType)*slices_));
for (int ii = 0; ii < slices_; ii++) {
values_[ii] = SignalType();
}
}
void SetListener(ClockListener * listener) { listener_ = listener; }
void Clear(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
values_[idx].Clear();
}
friend class Out<Type, Slices>;
friend class Out<Type>;
private:
SignalType values_[Slices];
SignalType * values_;
ClockListener * listener_;
bool connected_;
int slices_;
#if EMBB_DATAFLOW_TRACE_SIGNAL_HISTORY
embb::base::Spinlock lock_;
std::vector<SignalType> history_;
#endif
void Receive(SignalType const & value) {
const int idx = value.GetClock() % Slices;
const int idx = value.GetClock() % slices_;
if (values_[idx].GetClock() >= value.GetClock())
EMBB_THROW(embb::base::ErrorException,
"Received signal does not increase clock.");
......@@ -99,6 +110,7 @@ class In {
}
void ReceiveInit(InitData * init_data) {
SetSlices(init_data->slices);
listener_->OnInit(init_data);
}
};
......
......@@ -36,7 +36,6 @@ namespace dataflow {
namespace internal {
template <
int,
typename = embb::base::internal::Nil,
typename = embb::base::internal::Nil,
typename = embb::base::internal::Nil,
......@@ -44,8 +43,8 @@ template <
typename = embb::base::internal::Nil>
class Inputs;
template <int Slices>
class Inputs<Slices, embb::base::internal::Nil, embb::base::internal::Nil,
template <>
class Inputs<embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil>
: public Tuple<embb::base::internal::Nil, embb::base::internal::Nil,
......@@ -60,17 +59,15 @@ class Inputs<Slices, embb::base::internal::Nil, embb::base::internal::Nil,
virtual void OnInit(InitData * /*init_data*/) {}
};
template <int Slices, typename T1>
class Inputs<Slices, T1, embb::base::internal::Nil, embb::base::internal::Nil,
template <typename T1>
class Inputs<T1, embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil>
: public Tuple<In<T1, Slices>, embb::base::internal::Nil,
: public Tuple<In<T1>, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil>
, public ClockListener {
public:
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 1;
test_count_ = 1;
}
void SetListener(ClockListener * listener) {
......@@ -89,7 +86,7 @@ class Inputs<Slices, T1, embb::base::internal::Nil, embb::base::internal::Nil,
this->template Get<0>().Clear(clock);
}
virtual void OnClock(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
if (count_[idx] == 0) {
EMBB_THROW(embb::base::ErrorException,
"All inputs already fired for this clock.");
......@@ -101,25 +98,31 @@ class Inputs<Slices, T1, embb::base::internal::Nil, embb::base::internal::Nil,
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
slices_ = init_data->slices;
count_ = reinterpret_cast<embb::base::Atomic<int>*>(
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 1;
}
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
embb::base::Atomic<int> * count_;
int test_count_;
ClockListener * listener_;
int slices_;
};
template <int Slices, typename T1, typename T2>
class Inputs<Slices, T1, T2, embb::base::internal::Nil,
template <typename T1, typename T2>
class Inputs<T1, T2, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil>
: public Tuple<In<T1, Slices>, In<T2, Slices>, embb::base::internal::Nil,
: public Tuple<In<T1>, In<T2>, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil>
, public ClockListener {
public:
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 2;
test_count_ = 2;
}
void SetListener(ClockListener * listener) {
......@@ -142,7 +145,7 @@ class Inputs<Slices, T1, T2, embb::base::internal::Nil,
this->template Get<1>().Clear(clock);
}
virtual void OnClock(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
if (count_[idx] == 0) {
EMBB_THROW(embb::base::ErrorException,
"All inputs already fired for this clock.");
......@@ -154,25 +157,31 @@ class Inputs<Slices, T1, T2, embb::base::internal::Nil,
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
slices_ = init_data->slices;
count_ = reinterpret_cast<embb::base::Atomic<int>*>(
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 2;
}
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
embb::base::Atomic<int> * count_;
int test_count_;
ClockListener * listener_;
int slices_;
};
template <int Slices, typename T1, typename T2, typename T3>
class Inputs<Slices, T1, T2, T3, embb::base::internal::Nil,
template <typename T1, typename T2, typename T3>
class Inputs<T1, T2, T3, embb::base::internal::Nil,
embb::base::internal::Nil>
: public Tuple<In<T1, Slices>, In<T2, Slices>, In<T3, Slices>,
: public Tuple<In<T1>, In<T2>, In<T3>,
embb::base::internal::Nil, embb::base::internal::Nil>
, public ClockListener {
public:
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 3;
test_count_ = 3;
}
void SetListener(ClockListener * listener) {
......@@ -199,7 +208,7 @@ class Inputs<Slices, T1, T2, T3, embb::base::internal::Nil,
this->template Get<2>().Clear(clock);
}
virtual void OnClock(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
if (count_[idx] == 0) {
EMBB_THROW(embb::base::ErrorException,
"All inputs already fired for this clock.");
......@@ -211,24 +220,30 @@ class Inputs<Slices, T1, T2, T3, embb::base::internal::Nil,
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
slices_ = init_data->slices;
count_ = reinterpret_cast<embb::base::Atomic<int>*>(
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 3;
}
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
embb::base::Atomic<int> * count_;
int test_count_;
ClockListener * listener_;
int slices_;
};
template <int Slices, typename T1, typename T2, typename T3, typename T4>
class Inputs<Slices, T1, T2, T3, T4, embb::base::internal::Nil>
: public Tuple<In<T1, Slices>, In<T2, Slices>, In<T3, Slices>,
In<T4, Slices>, embb::base::internal::Nil>
template <typename T1, typename T2, typename T3, typename T4>
class Inputs<T1, T2, T3, T4, embb::base::internal::Nil>
: public Tuple<In<T1>, In<T2>, In<T3>,
In<T4>, embb::base::internal::Nil>
, public ClockListener {
public:
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 4;
test_count_ = 4;
}
void SetListener(ClockListener * listener) {
......@@ -259,7 +274,7 @@ class Inputs<Slices, T1, T2, T3, T4, embb::base::internal::Nil>
this->template Get<3>().Clear(clock);
}
virtual void OnClock(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
if (count_[idx] == 0) {
EMBB_THROW(embb::base::ErrorException,
"All inputs already fired for this clock.");
......@@ -271,25 +286,31 @@ class Inputs<Slices, T1, T2, T3, T4, embb::base::internal::Nil>
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
slices_ = init_data->slices;
count_ = reinterpret_cast<embb::base::Atomic<int>*>(
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 4;
}
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
embb::base::Atomic<int> * count_;
int test_count_;
ClockListener * listener_;
int slices_;
};
template <int Slices, typename T1, typename T2, typename T3, typename T4,
template <typename T1, typename T2, typename T3, typename T4,
typename T5>
class Inputs
: public Tuple<In<T1, Slices>, In<T2, Slices>, In<T3, Slices>,
In<T4, Slices>, In<T5, Slices> >
: public Tuple<In<T1>, In<T2>, In<T3>,
In<T4>, In<T5> >
, public ClockListener {
public:
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 5;
test_count_ = 5;
}
void SetListener(ClockListener * listener) {
......@@ -324,7 +345,7 @@ class Inputs
this->template Get<4>().Clear(clock);
}
virtual void OnClock(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
if (count_[idx] == 0) {
EMBB_THROW(embb::base::ErrorException,
"All inputs already fired for this clock.");
......@@ -336,13 +357,21 @@ class Inputs
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
slices_ = init_data->slices;
count_ = reinterpret_cast<embb::base::Atomic<int>*>(
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 5;
}
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
embb::base::Atomic<int> * count_;
int test_count_;
ClockListener * listener_;
int slices_;
};
} // namespace internal
......
......@@ -37,11 +37,11 @@ namespace internal {
class Scheduler;
template <typename Type, int Slices>
template <typename Type>
class Out {
public:
typedef Signal<Type> SignalType;
typedef In<Type, Slices> InType;
typedef In<Type> InType;
Out() {
}
......
......@@ -35,7 +35,6 @@ namespace dataflow {
namespace internal {
template <
int,
typename = embb::base::internal::Nil,
typename = embb::base::internal::Nil,
typename = embb::base::internal::Nil,
......@@ -43,8 +42,8 @@ template <
typename = embb::base::internal::Nil >
class Outputs;
template <int Slices>
class Outputs<Slices, embb::base::internal::Nil, embb::base::internal::Nil,
template <>
class Outputs<embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil>
: public Tuple<embb::base::internal::Nil, embb::base::internal::Nil,
......@@ -53,43 +52,43 @@ class Outputs<Slices, embb::base::internal::Nil, embb::base::internal::Nil,
public:
};
template <int Slices, typename T1>
class Outputs<Slices, T1, embb::base::internal::Nil, embb::base::internal::Nil,
template <typename T1>
class Outputs<T1, embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil>
: public Tuple<Out<T1, Slices>, embb::base::internal::Nil,
: public Tuple<Out<T1>, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::internal::Nil> {
public:
};
template <int Slices, typename T1, typename T2>
class Outputs<Slices, T1, T2, embb::base::internal::Nil,
template <typename T1, typename T2>
class Outputs<T1, T2, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil>
: public Tuple<Out<T1, Slices>, Out<T2, Slices>, embb::base::internal::Nil,
: public Tuple<Out<T1>, Out<T2>, embb::base::internal::Nil,
embb::base::internal::Nil, embb::base::internal::Nil> {
public:
};
template <int Slices, typename T1, typename T2, typename T3>
class Outputs<Slices, T1, T2, T3, embb::base::internal::Nil,
template <typename T1, typename T2, typename T3>
class Outputs<T1, T2, T3, embb::base::internal::Nil,
embb::base::internal::Nil>
: public Tuple<Out<T1, Slices>, Out<T2, Slices>, Out<T3, Slices>,
: public Tuple<Out<T1>, Out<T2>, Out<T3>,
embb::base::internal::Nil, embb::base::internal::Nil> {
public:
};
template <int Slices, typename T1, typename T2, typename T3, typename T4>
class Outputs<Slices, T1, T2, T3, T4, embb::base::internal::Nil>
: public Tuple<Out<T1, Slices>, Out<T2, Slices>, Out<T3, Slices>,
Out<T4, Slices>, embb::base::internal::Nil>{
template <typename T1, typename T2, typename T3, typename T4>
class Outputs<T1, T2, T3, T4, embb::base::internal::Nil>
: public Tuple<Out<T1>, Out<T2>, Out<T3>,
Out<T4>, embb::base::internal::Nil>{
public:
};
template <int Slices, typename T1, typename T2, typename T3, typename T4,
template <typename T1, typename T2, typename T3, typename T4,
typename T5>
class Outputs
: public Tuple<Out<T1, Slices>, Out<T2, Slices>, Out<T3, Slices>,
Out<T4, Slices>, Out<T5, Slices> > {
: public Tuple<Out<T1>, Out<T2>, Out<T3>,
Out<T4>, Out<T5> > {
public:
};
......
......@@ -37,24 +37,25 @@ namespace embb {
namespace dataflow {
namespace internal {
template <int Slices, bool Serial, class INPUTS, class OUTPUTS> class Process;
template <bool Serial, class INPUTS, class OUTPUTS> class Process;
template <
int Slices, bool Serial,
bool Serial,
typename I1, typename I2, typename I3, typename I4, typename I5,
typename O1, typename O2, typename O3, typename O4, typename O5>
class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
Outputs<Slices, O1, O2, O3, O4, O5> >
class Process< Serial, Inputs<I1, I2, I3, I4, I5>,
Outputs<O1, O2, O3, O4, O5> >
: public Node
, public ClockListener {
public:
typedef Inputs<Slices, I1, I2, I3, I4, I5> InputsType;
typedef Outputs<Slices, O1, O2, O3, O4, O5> OutputsType;
typedef Inputs<I1, I2, I3, I4, I5> InputsType;
typedef Outputs<O1, O2, O3, O4, O5> OutputsType;
typedef ProcessExecutor< InputsType, OutputsType > ExecutorType;
typedef typename ExecutorType::FunctionType FunctionType;
explicit Process(FunctionType function)
: executor_(function) {
: executor_(function)
, slices_(0) {
next_clock_ = 0;
queued_clock_ = 0;
bool ordered = Serial;
......@@ -79,6 +80,14 @@ class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
}
virtual void Init(InitData * init_data) {
slices_ = init_data->slices;
//inputs_.SetSlices(init_data->slices);
action_ = reinterpret_cast<Action*>(
embb::base::Allocation::Allocate(
sizeof(Action)*slices_));
for (int ii = 0; ii < slices_; ii++) {
action_[ii] = Action();
}
SetScheduler(init_data->sched);
executor_.Init(init_data, outputs_);
}
......@@ -117,7 +126,7 @@ class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
bool retry = true;
while (retry) {
int clk = next_clock_;
int clk_end = clk + Slices;
int clk_end = clk + slices_;
int clk_res = clk;
for (int ii = clk; ii < clk_end; ii++) {
if (!inputs_.AreAtClock(ii)) {
......@@ -129,7 +138,7 @@ class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
if (next_clock_.CompareAndSwap(clk, clk_res)) {
while (queued_clock_.Load() < clk) continue;
for (int ii = clk; ii < clk_res; ii++) {
const int idx = ii % Slices;
const int idx = ii % slices_;
action_[idx] = Action(this, ii);
sched_->Enqueue(queue_id_, action_[idx]);
}
......@@ -141,7 +150,7 @@ class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
}
}
} else {
const int idx = clock % Slices;
const int idx = clock % slices_;
action_[idx] = Action(this, clock);
sched_->Spawn(action_[idx]);
}
......@@ -155,10 +164,11 @@ class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
InputsType inputs_;
OutputsType outputs_;
ExecutorType executor_;
Action action_[Slices];
Action * action_;
embb::base::Atomic<int> next_clock_;
embb::base::Atomic<int> queued_clock_;
int queue_id_;
int slices_;
};
} // namespace internal
......
......@@ -36,12 +36,17 @@ namespace embb {
namespace dataflow {
namespace internal {
template <int Slices>
class SchedulerMTAPI : public Scheduler {
public:
SchedulerMTAPI() {
SchedulerMTAPI(int slices)
: slices_(slices) {
embb::tasks::Node & node = embb::tasks::Node::GetInstance();
for (int ii = 0; ii < Slices; ii++) {
group_ = reinterpret_cast<embb::tasks::Group**>(
embb::base::Allocation::Allocate(
sizeof(embb::tasks::Group*)*slices_));
for (int ii = 0; ii < slices_; ii++) {
embb::tasks::Group & group = node.CreateGroup();
group_[ii] = &group;
}
......@@ -58,21 +63,22 @@ class SchedulerMTAPI : public Scheduler {
}
virtual ~SchedulerMTAPI() {
embb::tasks::Node & node = embb::tasks::Node::GetInstance();
for (int ii = 0; ii < Slices; ii++) {
for (int ii = 0; ii < slices_; ii++) {
group_[ii]->WaitAll(MTAPI_INFINITE);
node.DestroyGroup(*group_[ii]);
}
embb::base::Allocation::Free(group_);
for (int ii = 0; ii < queue_count_; ii++) {
node.DestroyQueue(*queue_[ii]);
}
embb::base::Allocation::Free(queue_);
}
virtual void Spawn(Action & action) {
const int idx = action.GetClock() % Slices;
const int idx = action.GetClock() % slices_;
group_[idx]->Spawn(embb::base::MakeFunction(action, &Action::RunMTAPI));
}
virtual void Enqueue(int process_id, Action & action) {
const int idx = action.GetClock() % Slices;
const int idx = action.GetClock() % slices_;
const int queue_id = process_id % queue_count_;
queue_[queue_id]->Spawn(group_[idx],
embb::base::MakeFunction(action, &Action::RunMTAPI));
......@@ -82,9 +88,10 @@ class SchedulerMTAPI : public Scheduler {
}
private:
embb::tasks::Group * group_[Slices];
embb::tasks::Group ** group_;
embb::tasks::Queue ** queue_;
int queue_count_;
int slices_;
};
} // namespace internal
......
......@@ -27,7 +27,6 @@
#ifndef EMBB_DATAFLOW_INTERNAL_SELECT_H_
#define EMBB_DATAFLOW_INTERNAL_SELECT_H_
#include <embb/dataflow/internal/action.h>
#include <embb/dataflow/internal/signal.h>
#include <embb/dataflow/internal/node.h>
#include <embb/dataflow/internal/inputs.h>
......@@ -37,13 +36,13 @@ namespace embb {
namespace dataflow {
namespace internal {
template <int Slices, typename Type>
template <typename Type>
class Select
: public Node
, public ClockListener {
public:
typedef Inputs<Slices, bool, Type, Type> InputsType;
typedef Outputs<Slices, Type> OutputsType;
typedef Inputs<bool, Type, Type> InputsType;
typedef Outputs<Type> OutputsType;
Select() {
inputs_.SetListener(this);
......@@ -82,6 +81,8 @@ class Select
}
virtual void Init(InitData * init_data) {
slices_ = init_data->slices;
//inputs_.SetSlices(slices_);
SetScheduler(init_data->sched);
GetOutput<0>().SendInit(init_data);
}
......@@ -124,7 +125,7 @@ class Select
private:
InputsType inputs_;
OutputsType outputs_;
Action action_[Slices];
int slices_;
};
} // namespace internal
......
......@@ -36,16 +36,15 @@ namespace embb {
namespace dataflow {
namespace internal {
template <int Slices, class Inputs> class Sink;
template <class Inputs> class Sink;
template <
int Slices,
typename I1, typename I2, typename I3, typename I4, typename I5>
class Sink< Slices, Inputs<Slices, I1, I2, I3, I4, I5> >
class Sink< Inputs<I1, I2, I3, I4, I5> >
: public Node
, public ClockListener {
public:
typedef Inputs<Slices, I1, I2, I3, I4, I5> InputsType;
typedef Inputs<I1, I2, I3, I4, I5> InputsType;
typedef SinkExecutor< InputsType > ExecutorType;
typedef typename ExecutorType::FunctionType FunctionType;
......@@ -73,6 +72,13 @@ class Sink< Slices, Inputs<Slices, I1, I2, I3, I4, I5> >
}
virtual void Init(InitData * init_data) {
slices_ = init_data->slices;
action_ = reinterpret_cast<Action*>(
embb::base::Allocation::Allocate(
sizeof(Action)*slices_));
for (int ii = 0; ii < slices_; ii++) {
action_[ii] = Action();
}
SetListener(init_data->sink_listener);
SetScheduler(init_data->sched);
listener_->OnInit(init_data);
......@@ -96,7 +102,7 @@ class Sink< Slices, Inputs<Slices, I1, I2, I3, I4, I5> >
bool retry = true;
while (retry) {
int clk = next_clock_;
int clk_end = clk + Slices;
int clk_end = clk + slices_;
int clk_res = clk;
for (int ii = clk; ii < clk_end; ii++) {
if (!inputs_.AreAtClock(ii)) {
......@@ -108,7 +114,7 @@ class Sink< Slices, Inputs<Slices, I1, I2, I3, I4, I5> >
if (next_clock_.CompareAndSwap(clk, clk_res)) {
while (queued_clock_.Load() < clk) continue;
for (int ii = clk; ii < clk_res; ii++) {
const int idx = ii % Slices;
const int idx = ii % slices_;
action_[idx] = Action(this, ii);
sched_->Enqueue(queue_id_, action_[idx]);
}
......@@ -128,11 +134,12 @@ class Sink< Slices, Inputs<Slices, I1, I2, I3, I4, I5> >
private:
InputsType inputs_;
ExecutorType executor_;
Action action_[Slices];
Action * action_;
ClockListener * listener_;
embb::base::Atomic<int> next_clock_;
embb::base::Atomic<int> queued_clock_;
int queue_id_;
int slices_;
};
} // namespace internal
......
......@@ -38,8 +38,8 @@ namespace internal {
template <class Inputs>
class SinkExecutor;
template <int Slices, typename I1>
class SinkExecutor< Inputs<Slices, I1> > {
template <typename I1>
class SinkExecutor< Inputs<I1> > {
public:
typedef embb::base::Function<void, I1 const &> FunctionType;
......@@ -47,7 +47,7 @@ class SinkExecutor< Inputs<Slices, I1> > {
void Execute(
int clock,
Inputs<Slices, I1> & inputs) {
Inputs<I1> & inputs) {
function_(
inputs.template Get<0>().GetValue(clock));
}
......@@ -56,8 +56,8 @@ class SinkExecutor< Inputs<Slices, I1> > {
FunctionType function_;
};
template <int Slices, typename I1, typename I2>
class SinkExecutor< Inputs<Slices, I1, I2> > {
template <typename I1, typename I2>
class SinkExecutor< Inputs<I1, I2> > {
public:
typedef embb::base::Function<void, I1 const &, I2 const &> FunctionType;
......@@ -65,7 +65,7 @@ class SinkExecutor< Inputs<Slices, I1, I2> > {
void Execute(
int clock,
Inputs<Slices, I1, I2> & inputs) {
Inputs<I1, I2> & inputs) {
function_(
inputs.template Get<0>().GetValue(clock),
inputs.template Get<1>().GetValue(clock));
......@@ -75,8 +75,8 @@ class SinkExecutor< Inputs<Slices, I1, I2> > {
FunctionType function_;
};
template <int Slices, typename I1, typename I2, typename I3>
class SinkExecutor< Inputs<Slices, I1, I2, I3> > {
template <typename I1, typename I2, typename I3>
class SinkExecutor< Inputs<I1, I2, I3> > {
public:
typedef embb::base::Function<void, I1 const &, I2 const &, I3 const &>
FunctionType;
......@@ -85,7 +85,7 @@ class SinkExecutor< Inputs<Slices, I1, I2, I3> > {
void Execute(
int clock,
Inputs<Slices, I1, I2, I3> & inputs) {
Inputs<I1, I2, I3> & inputs) {
function_(
inputs.template Get<0>().GetValue(clock),
inputs.template Get<1>().GetValue(clock),
......@@ -96,8 +96,8 @@ class SinkExecutor< Inputs<Slices, I1, I2, I3> > {
FunctionType function_;
};
template <int Slices, typename I1, typename I2, typename I3, typename I4>
class SinkExecutor< Inputs<Slices, I1, I2, I3, I4> > {
template <typename I1, typename I2, typename I3, typename I4>
class SinkExecutor< Inputs<I1, I2, I3, I4> > {
public:
typedef embb::base::Function<void, I1 const &, I2 const &, I3 const &,
I4 const &> FunctionType;
......@@ -106,7 +106,7 @@ class SinkExecutor< Inputs<Slices, I1, I2, I3, I4> > {
void Execute(
int clock,
Inputs<Slices, I1, I2, I3, I4> & inputs) {
Inputs<I1, I2, I3, I4> & inputs) {
function_(
inputs.template Get<0>().GetValue(clock),
inputs.template Get<1>().GetValue(clock),
......@@ -118,9 +118,9 @@ class SinkExecutor< Inputs<Slices, I1, I2, I3, I4> > {
FunctionType function_;
};
template <int Slices, typename I1, typename I2, typename I3, typename I4,
template <typename I1, typename I2, typename I3, typename I4,
typename I5>
class SinkExecutor< Inputs<Slices, I1, I2, I3, I4, I5> > {
class SinkExecutor< Inputs<I1, I2, I3, I4, I5> > {
public:
typedef embb::base::Function<void, I1 const &, I2 const &, I3 const &,
I4 const &, I5 const &> FunctionType;
......@@ -129,7 +129,7 @@ class SinkExecutor< Inputs<Slices, I1, I2, I3, I4, I5> > {
void Execute(
int clock,
Inputs<Slices, I1, I2, I3, I4, I5> & inputs) {
Inputs<I1, I2, I3, I4, I5> & inputs) {
function_(
inputs.template Get<0>().GetValue(clock),
inputs.template Get<1>().GetValue(clock),
......
......@@ -35,15 +35,14 @@ namespace embb {
namespace dataflow {
namespace internal {
template <int Slices, class Outputs> class Source;
template <class Outputs> class Source;
template <
int Slices,
typename O1, typename O2, typename O3, typename O4, typename O5>
class Source< Slices, Outputs<Slices, O1, O2, O3, O4, O5> >
class Source< Outputs<O1, O2, O3, O4, O5> >
: public Node {
public:
typedef Outputs<Slices, O1, O2, O3, O4, O5> OutputsType;
typedef Outputs<O1, O2, O3, O4, O5> OutputsType;
typedef SourceExecutor< OutputsType > ExecutorType;
typedef typename ExecutorType::FunctionType FunctionType;
......
......@@ -41,8 +41,8 @@ class Scheduler;
template <class OUTPUTS>
class SourceExecutor;
template <int Slices, typename O1>
class SourceExecutor< Outputs<Slices, O1> > {
template <typename O1>
class SourceExecutor< Outputs<O1> > {
public:
typedef embb::base::Function<bool, O1 &> FunctionType;
......@@ -50,14 +50,14 @@ class SourceExecutor< Outputs<Slices, O1> > {
bool Execute(
int clock,
Outputs<Slices, O1> & outputs) {
Outputs<O1> & outputs) {
O1 o1;
bool result = function_(o1);
outputs.template Get<0>().Send(Signal<O1>(clock, o1));
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1> & outputs) {
void Init(InitData * init_data, Outputs<O1> & outputs) {
outputs.template Get<0>().SendInit(init_data);
}
......@@ -65,8 +65,8 @@ class SourceExecutor< Outputs<Slices, O1> > {
FunctionType function_;
};
template <int Slices, typename O1, typename O2>
class SourceExecutor< Outputs<Slices, O1, O2> > {
template <typename O1, typename O2>
class SourceExecutor< Outputs<O1, O2> > {
public:
typedef embb::base::Function<bool, O1 &, O2 &> FunctionType;
......@@ -74,7 +74,7 @@ class SourceExecutor< Outputs<Slices, O1, O2> > {
bool Execute(
int clock,
Outputs<Slices, O1, O2> & outputs) {
Outputs<O1, O2> & outputs) {
O1 o1;
O2 o2;
bool result = function_(o1, o2);
......@@ -83,7 +83,7 @@ class SourceExecutor< Outputs<Slices, O1, O2> > {
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1, O2> & outputs) {
void Init(InitData * init_data, Outputs<O1, O2> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
}
......@@ -92,8 +92,8 @@ class SourceExecutor< Outputs<Slices, O1, O2> > {
FunctionType function_;
};
template <int Slices, typename O1, typename O2, typename O3>
class SourceExecutor< Outputs<Slices, O1, O2, O3> > {
template <typename O1, typename O2, typename O3>
class SourceExecutor< Outputs<O1, O2, O3> > {
public:
typedef embb::base::Function<bool, O1 &, O2 &, O3 &> FunctionType;
......@@ -101,7 +101,7 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3> > {
bool Execute(
int clock,
Outputs<Slices, O1, O2, O3> & outputs) {
Outputs<O1, O2, O3> & outputs) {
O1 o1;
O2 o2;
O3 o3;
......@@ -112,7 +112,7 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3> > {
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1, O2, O3> & outputs) {
void Init(InitData * init_data, Outputs<O1, O2, O3> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
......@@ -122,8 +122,8 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3> > {
FunctionType function_;
};
template <int Slices, typename O1, typename O2, typename O3, typename O4>
class SourceExecutor< Outputs<Slices, O1, O2, O3, O4> > {
template <typename O1, typename O2, typename O3, typename O4>
class SourceExecutor< Outputs<O1, O2, O3, O4> > {
public:
typedef embb::base::Function<bool, O1 &, O2 &, O3 &, O4 &> FunctionType;
......@@ -131,7 +131,7 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3, O4> > {
bool Execute(
int clock,
Outputs<Slices, O1, O2, O3, O4> & outputs) {
Outputs<O1, O2, O3, O4> & outputs) {
O1 o1;
O2 o2;
O3 o3;
......@@ -144,7 +144,7 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3, O4> > {
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1, O2, O3, O4> & outputs) {
void Init(InitData * init_data, Outputs<O1, O2, O3, O4> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
......@@ -155,9 +155,9 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3, O4> > {
FunctionType function_;
};
template <int Slices, typename O1, typename O2, typename O3, typename O4,
template <typename O1, typename O2, typename O3, typename O4,
typename O5>
class SourceExecutor< Outputs<Slices, O1, O2, O3, O4, O5> > {
class SourceExecutor< Outputs<O1, O2, O3, O4, O5> > {
public:
typedef embb::base::Function<bool, O1 &, O2 &, O3 &, O4 &, O5 &> FunctionType;
......@@ -165,7 +165,7 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3, O4, O5> > {
bool Execute(
int clock,
Outputs<Slices, O1, O2, O3, O4, O5> & outputs) {
Outputs<O1, O2, O3, O4, O5> & outputs) {
O1 o1;
O2 o2;
O3 o3;
......@@ -181,7 +181,7 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3, O4, O5> > {
}
void Init(
InitData * init_data, Outputs<Slices, O1, O2, O3, O4, O5> & outputs) {
InitData * init_data, Outputs<O1, O2, O3, O4, O5> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
......
......@@ -27,7 +27,6 @@
#ifndef EMBB_DATAFLOW_INTERNAL_SWITCH_H_
#define EMBB_DATAFLOW_INTERNAL_SWITCH_H_
#include <embb/dataflow/internal/action.h>
#include <embb/dataflow/internal/signal.h>
#include <embb/dataflow/internal/node.h>
#include <embb/dataflow/internal/inputs.h>
......@@ -37,13 +36,13 @@ namespace embb {
namespace dataflow {
namespace internal {
template <int Slices, typename Type>
template <typename Type>
class Switch
: public Node
, public ClockListener {
public:
typedef Inputs<Slices, bool, Type> InputsType;
typedef Outputs<Slices, Type, Type> OutputsType;
typedef Inputs<bool, Type> InputsType;
typedef Outputs<Type, Type> OutputsType;
Switch() {
inputs_.SetListener(this);
......@@ -79,6 +78,7 @@ class Switch
}
virtual void Init(InitData * init_data) {
//inputs_.SetSlices(init_data->slices);
SetScheduler(init_data->sched);
GetOutput<0>().SendInit(init_data);
GetOutput<1>().SendInit(init_data);
......@@ -122,7 +122,6 @@ class Switch
private:
InputsType inputs_;
OutputsType outputs_;
Action action_[Slices];
};
} // namespace internal
......
......@@ -669,7 +669,6 @@ class Network {
#else
template <int Slices>
class Network : public internal::ClockListener {
public:
Network() {}
......@@ -679,7 +678,7 @@ class Network : public internal::ClockListener {
typename T4 = embb::base::internal::Nil,
typename T5 = embb::base::internal::Nil>
struct Inputs {
typedef internal::Inputs<Slices, T1, T2, T3, T4, T5> Type;
typedef internal::Inputs<T1, T2, T3, T4, T5> Type;
};
template <typename T1, typename T2 = embb::base::internal::Nil,
......@@ -687,7 +686,7 @@ class Network : public internal::ClockListener {
typename T4 = embb::base::internal::Nil,
typename T5 = embb::base::internal::Nil>
struct Outputs {
typedef internal::Outputs<Slices, T1, T2, T3, T4, T5> Type;
typedef internal::Outputs<T1, T2, T3, T4, T5> Type;
};
template <class Inputs, class Outputs> class SerialProcess;
......@@ -695,20 +694,20 @@ class Network : public internal::ClockListener {
template <
typename I1, typename I2, typename I3, typename I4, typename I5,
typename O1, typename O2, typename O3, typename O4, typename O5>
class SerialProcess< internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >
: public internal::Process< Slices, true,
internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> > {
class SerialProcess< internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> >
: public internal::Process< true,
internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> > {
public:
typedef typename internal::Process< Slices, true,
internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >::FunctionType
typedef typename internal::Process< true,
internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> >::FunctionType
FunctionType;
explicit SerialProcess(FunctionType function)
: internal::Process< Slices, true,
internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >(function) {
: internal::Process< true,
internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> >(function) {
//empty
}
};
......@@ -718,31 +717,31 @@ class Network : public internal::ClockListener {
template <
typename I1, typename I2, typename I3, typename I4, typename I5,
typename O1, typename O2, typename O3, typename O4, typename O5>
class ParallelProcess< internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >
: public internal::Process< Slices, false,
internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >{
class ParallelProcess< internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> >
: public internal::Process< false,
internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> >{
public:
typedef typename internal::Process< Slices, false,
internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >::FunctionType
typedef typename internal::Process< false,
internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> >::FunctionType
FunctionType;
explicit ParallelProcess(FunctionType function)
: internal::Process< Slices, false,
internal::Inputs<Slices, I1, I2, I3, I4, I5>,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >(function) {
: internal::Process< false,
internal::Inputs<I1, I2, I3, I4, I5>,
internal::Outputs<O1, O2, O3, O4, O5> >(function) {
//empty
}
};
template<typename Type>
class Switch : public internal::Switch<Slices, Type> {
class Switch : public internal::Switch<Type> {
public:
};
template<typename Type>
class Select : public internal::Select<Slices, Type> {
class Select : public internal::Select<Type> {
public:
};
......@@ -750,15 +749,15 @@ class Network : public internal::ClockListener {
typename I3 = embb::base::internal::Nil,
typename I4 = embb::base::internal::Nil,
typename I5 = embb::base::internal::Nil>
class Sink : public internal::Sink<Slices,
internal::Inputs<Slices, I1, I2, I3, I4, I5> > {
class Sink : public internal::Sink<
internal::Inputs<I1, I2, I3, I4, I5> > {
public:
typedef typename internal::Sink<Slices,
internal::Inputs<Slices, I1, I2, I3, I4, I5> >::FunctionType FunctionType;
typedef typename internal::Sink<
internal::Inputs<I1, I2, I3, I4, I5> >::FunctionType FunctionType;
explicit Sink(FunctionType function)
: internal::Sink<Slices,
internal::Inputs<Slices, I1, I2, I3, I4, I5> >(function) {
: internal::Sink<
internal::Inputs<I1, I2, I3, I4, I5> >(function) {
//empty
}
};
......@@ -767,16 +766,16 @@ class Network : public internal::ClockListener {
typename O3 = embb::base::internal::Nil,
typename O4 = embb::base::internal::Nil,
typename O5 = embb::base::internal::Nil>
class Source : public internal::Source<Slices,
internal::Outputs<Slices, O1, O2, O3, O4, O5> > {
class Source : public internal::Source<
internal::Outputs<O1, O2, O3, O4, O5> > {
public:
typedef typename internal::Source<Slices,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >::FunctionType
typedef typename internal::Source<
internal::Outputs<O1, O2, O3, O4, O5> >::FunctionType
FunctionType;
explicit Source(FunctionType function)
: internal::Source<Slices,
internal::Outputs<Slices, O1, O2, O3, O4, O5> >(function) {
: internal::Source<
internal::Outputs<O1, O2, O3, O4, O5> >(function) {
//empty
}
};
......@@ -787,10 +786,10 @@ class Network : public internal::ClockListener {
}
template<typename Type>
class ConstantSource : public internal::ConstantSource<Slices, Type> {
class ConstantSource : public internal::ConstantSource<Type> {
public:
explicit ConstantSource(Type value)
: internal::ConstantSource<Slices, Type>(value) {
: internal::ConstantSource<Type>(value) {
//empty
}
};
......@@ -800,24 +799,36 @@ class Network : public internal::ClockListener {
sources_.push_back(&source);
}
void operator () () {
void operator () (int slices) {
slices_ = slices;
internal::SchedulerSequential sched_seq;
internal::SchedulerMTAPI<Slices> sched_mtapi;
internal::SchedulerMTAPI sched_mtapi(slices_);
internal::Scheduler * sched = &sched_mtapi;
internal::InitData init_data;
init_data.slices = slices_;
init_data.sched = sched;
init_data.sink_listener = this;
sink_counter_ = reinterpret_cast<embb::base::Atomic<int>*>(
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
sink_counter_[ii] = 0;
}
sink_count_ = 0;
for (size_t it = 0; it < sources_.size(); it++)
sources_[it]->Init(&init_data);
for (int ii = 0; ii < Slices; ii++) sink_counter_[ii] = 0;
for (int ii = 0; ii < slices_; ii++) {
sink_counter_[ii] = 0;
}
int clock = 0;
while (clock >= 0) {
const int idx = clock % Slices;
const int idx = clock % slices_;
while (sink_counter_[idx] > 0) embb::base::Thread::CurrentYield();
sched->WaitForSlice(idx);
if (!SpawnClock(clock))
......@@ -825,10 +836,10 @@ class Network : public internal::ClockListener {
clock++;
}
int ii = clock - Slices + 1;
int ii = clock - slices_ + 1;
if (ii < 0) ii = 0;
for (; ii < clock; ii++) {
const int idx = ii % Slices;
const int idx = ii % slices_;
while (sink_counter_[idx] > 0) embb::base::Thread::CurrentYield();
sched->WaitForSlice(idx);
}
......@@ -841,7 +852,7 @@ class Network : public internal::ClockListener {
* corresponding slot, thus allowing a new token to be emitted.
*/
virtual void OnClock(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
const int cnt = --sink_counter_[idx];
if (cnt < 0)
EMBB_THROW(embb::base::ErrorException,
......@@ -861,15 +872,16 @@ class Network : public internal::ClockListener {
std::vector<internal::Node*> processes_;
std::vector<internal::Node*> sources_;
std::vector<internal::Node*> sinks_;
embb::base::Atomic<int> sink_counter_[Slices];
embb::base::Atomic<int> * sink_counter_;
int sink_count_;
int slices_;
#if EMBB_DATAFLOW_TRACE_SIGNAL_HISTORY
std::vector<int> spawn_history_[Slices];
#endif
bool SpawnClock(int clock) {
const int idx = clock % Slices;
const int idx = clock % slices_;
bool result = true;
#if EMBB_DATAFLOW_TRACE_SIGNAL_HISTORY
spawn_history_[idx].push_back(clock);
......
......@@ -39,7 +39,7 @@
#define NUM_SLICES 8
#define TEST_COUNT 12
typedef embb::dataflow::Network<NUM_SLICES> MyNetwork;
typedef embb::dataflow::Network MyNetwork;
typedef MyNetwork::ConstantSource< int > MyConstantSource;
typedef MyNetwork::Source< int > MySource;
typedef MyNetwork::SerialProcess< MyNetwork::Inputs<int>::Type,
......@@ -206,7 +206,7 @@ void SimpleTest::TestBasic() {
network.AddSource(source);
try {
network();
network(NUM_SLICES);
} catch (embb::base::ErrorException & e) {
PT_ASSERT_MSG(false, e.What());
}
......
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