-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from definelicht/subflows
Subflows
- Loading branch information
Showing
6 changed files
with
99 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,12 @@ | ||
/// @author Johannes de Fine Licht ([email protected]) | ||
/// @copyright This software is copyrighted under the BSD 3-Clause License. | ||
/// @copyright This software is copyrighted under the BSD 3-Clause License. | ||
|
||
#pragma once | ||
|
||
#ifndef HLSLIB_SYNTHESIS | ||
#include <condition_variable> | ||
#include <mutex> | ||
#include <queue> | ||
#include <thread> | ||
#include <vector> | ||
// #include "hlslib/Stream.h" | ||
|
@@ -16,9 +19,10 @@ | |
// which will launch them as a C++ thread when running simulation, but will | ||
// fall back on normal function calls when running synthesis. | ||
// | ||
// The macro HLSLIB_DATAFLOW_INIT must be called before adding dataflow | ||
// functions, in order to initialize the local context. | ||
// The macro HLSLIB_DATAFLOW_FINALIZE must be called before returning from the | ||
// top level function to join the dataflow threads. | ||
// HLSLIB_DATAFLOW_INIT currently has no purpose, but is included for symmetry. | ||
// | ||
// TODO: HLSLIB_DATAFLOW_FUNCTION does not work when calling templated functions | ||
// with multiple arguments, as it considers the comma a separator between | ||
|
@@ -36,11 +40,11 @@ namespace hlslib { | |
#else | ||
namespace { | ||
class _Dataflow { | ||
|
||
private: | ||
public: | ||
inline _Dataflow() {} | ||
inline ~_Dataflow() { this->Join(); } | ||
|
||
private: | ||
template <typename T> | ||
struct non_deducible { | ||
using type = T; | ||
|
@@ -60,39 +64,27 @@ class _Dataflow { | |
} | ||
|
||
public: | ||
inline static _Dataflow& Get() { // Singleton pattern | ||
static _Dataflow df; | ||
return df; | ||
} | ||
|
||
template <class Ret, typename... Args> | ||
void AddFunction(Ret (*func)(Args...), non_deducible_t<Args>... args) { | ||
threads_.emplace_back(func, passed_by(std::forward<Args>(args), | ||
std::is_reference<Args>{})...); | ||
} | ||
|
||
// template <typename T, typename... Args> | ||
// Stream<T>& EmplaceStream(Args&&... args) { | ||
// streams_.emplace_back(std::unique_ptr<Stream<T>>(new Stream<T>(args...))); | ||
// return *static_cast<Stream<T> *>(streams_.back().get()); | ||
// } | ||
|
||
inline void Join() { | ||
for (auto &t : threads_) { | ||
for (auto& t : threads_) { | ||
t.join(); | ||
} | ||
threads_.clear(); | ||
} | ||
|
||
private: | ||
private: | ||
std::vector<std::thread> threads_{}; | ||
// std::vector<std::unique_ptr<_StreamBase>> streams_{}; | ||
}; | ||
#define HLSLIB_DATAFLOW_INIT() | ||
#define HLSLIB_DATAFLOW_INIT() ::hlslib::_Dataflow __hlslib_dataflow_context; | ||
#define HLSLIB_DATAFLOW_FUNCTION(func, ...) \ | ||
::hlslib::_Dataflow::Get().AddFunction(func, __VA_ARGS__) | ||
#define HLSLIB_DATAFLOW_FINALIZE() ::hlslib::_Dataflow::Get().Join(); | ||
} | ||
__hlslib_dataflow_context.AddFunction(func, __VA_ARGS__) | ||
#define HLSLIB_DATAFLOW_FINALIZE() __hlslib_dataflow_context.Join(); | ||
} // namespace | ||
#endif | ||
|
||
} // End namespace hlslib | ||
} // End namespace hlslib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#pragma once | ||
|
||
using Data_t = int; | ||
constexpr int kSize = 128; | ||
|
||
extern "C" void Subflow(const Data_t* memIn, Data_t* memOut); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#include "Subflow.h" | ||
|
||
#include "hlslib/xilinx/Simulation.h" | ||
#include "hlslib/xilinx/Stream.h" | ||
|
||
void ReadIn(const Data_t* memIn, hlslib::Stream<Data_t>& inPipe) { | ||
for (unsigned i = 0; i < kSize; ++i) { | ||
#pragma HLS PIPELINE II=1 | ||
inPipe.Push(memIn[i]); | ||
} | ||
} | ||
|
||
void AddOne(hlslib::Stream<Data_t>& inPipe, hlslib::Stream<Data_t>& internal) { | ||
for (unsigned i = 0; i < kSize; ++i) { | ||
#pragma HLS PIPELINE II=1 | ||
internal.Push(inPipe.Pop() + 1); | ||
} | ||
} | ||
|
||
void MultiplyByTwo(hlslib::Stream<Data_t>& internal, | ||
hlslib::Stream<Data_t>& outPipe) { | ||
for (unsigned i = 0; i < kSize; ++i) { | ||
#pragma HLS PIPELINE II=1 | ||
outPipe.Push(internal.Pop() * 2); | ||
} | ||
} | ||
|
||
void Subtask(hlslib::Stream<Data_t>& inPipe, hlslib::Stream<Data_t>& outPipe) { | ||
HLSLIB_DATAFLOW_INIT(); | ||
hlslib::Stream<Data_t> internal; | ||
HLSLIB_DATAFLOW_FUNCTION(AddOne, inPipe, internal); | ||
HLSLIB_DATAFLOW_FUNCTION(MultiplyByTwo, internal, outPipe); | ||
HLSLIB_DATAFLOW_FINALIZE(); | ||
} | ||
|
||
void WriteOut(hlslib::Stream<Data_t>& outPipe, Data_t* memOut) { | ||
for (unsigned i = 0; i < kSize; ++i) { | ||
#pragma HLS PIPELINE II=1 | ||
memOut[i] = outPipe.Pop(); | ||
} | ||
} | ||
|
||
void Subflow(const Data_t* memIn, Data_t* memOut) { | ||
#pragma HLS DATAFLOW | ||
HLSLIB_DATAFLOW_INIT(); | ||
hlslib::Stream<Data_t> inPipe, outPipe; | ||
HLSLIB_DATAFLOW_FUNCTION(ReadIn, memIn, inPipe); | ||
HLSLIB_DATAFLOW_FUNCTION(Subtask, inPipe, outPipe); | ||
HLSLIB_DATAFLOW_FUNCTION(WriteOut, outPipe, memOut); | ||
HLSLIB_DATAFLOW_FINALIZE(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#include <random> | ||
|
||
#include "Subflow.h" | ||
#include "catch.hpp" | ||
|
||
TEST_CASE("Subflow", "[Subflow]") { | ||
std::random_device rd; | ||
std::default_random_engine re(rd()); | ||
std::uniform_int_distribution<Data_t> dist(10, 1); | ||
std::vector<Data_t> memIn(kSize), memOut(kSize); | ||
for (unsigned i = 0; i < kSize; ++i) { | ||
memIn[i] = dist(re); | ||
} | ||
Subflow(memIn.data(), memOut.data()); | ||
for (unsigned i = 0; i < kSize; ++i) { | ||
REQUIRE(memOut[i] == (memIn[i] + 1) * 2); | ||
} | ||
} |