126 lines
4.3 KiB
C++
126 lines
4.3 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
|
|
|
// Based on hls_stream.h from Xilinx VITIS HLS 2023.1
|
|
|
|
// (c) Copyright 2011-2022 Xilinx, Inc.
|
|
// All Rights Reserved.
|
|
//
|
|
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
#ifndef JUNGFRAUJOCH_PARALLEL_STREAM_H
|
|
#define JUNGFRAUJOCH_PARALLEL_STREAM_H
|
|
|
|
#include <cstddef>
|
|
#include <queue>
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <chrono>
|
|
|
|
namespace hls {
|
|
template<class T, int DEPTH=0> class stream;
|
|
|
|
template<class T> class stream<T, 0> {
|
|
private:
|
|
mutable std::mutex m;
|
|
std::condition_variable c_empty;
|
|
std::condition_variable c_full;
|
|
std::queue<T> data;
|
|
constexpr const static std::chrono::seconds timeout = std::chrono::minutes(30);
|
|
size_t max_elements;
|
|
const std::string name;
|
|
|
|
void internal_read(T& head) {
|
|
head = data.front();
|
|
data.pop();
|
|
c_full.notify_one();
|
|
}
|
|
void internal_write(const T& tail) {
|
|
data.push(tail);
|
|
c_empty.notify_one();
|
|
}
|
|
public:
|
|
explicit stream(const char* in_name = "", size_t nelem = UINT64_MAX)
|
|
: name(in_name), max_elements(nelem), data(){};
|
|
|
|
void write(const T& tail) {
|
|
std::unique_lock ul(m);
|
|
while (data.size() >= max_elements) {
|
|
auto start_time = std::chrono::system_clock::now();
|
|
if (c_full.wait_for(ul, timeout) == std::cv_status::timeout) {
|
|
auto now_time = std::chrono::system_clock::now();
|
|
std::chrono::duration<double> elapsed_seconds = now_time - start_time;
|
|
throw std::runtime_error(name + ": likely deadlock to write to FIFO, timeout: " + std::to_string(elapsed_seconds.count()));
|
|
}
|
|
}
|
|
internal_write(tail);
|
|
}
|
|
|
|
bool write_nb(const T& tail) {
|
|
std::unique_lock ul(m);
|
|
if (data.size() >= max_elements) return false;
|
|
internal_write(tail);
|
|
return true;
|
|
}
|
|
|
|
bool read_nb(T& head) {
|
|
std::unique_lock ul(m);
|
|
if (data.empty()) return false;
|
|
internal_read(head);
|
|
return true;
|
|
}
|
|
|
|
void read(T& head) {
|
|
std::unique_lock ul(m);
|
|
while (data.empty()) {
|
|
auto start_time = std::chrono::system_clock::now();
|
|
if (c_empty.wait_for(ul, timeout) == std::cv_status::timeout) {
|
|
|
|
auto now_time = std::chrono::system_clock::now();
|
|
std::chrono::duration<double> elapsed_seconds = now_time - start_time;
|
|
throw std::runtime_error(name + ": likely deadlock to read from FIFO, timeout: " + std::to_string(elapsed_seconds.count()));
|
|
}
|
|
}
|
|
internal_read(head);
|
|
}
|
|
|
|
bool full() const {
|
|
std::unique_lock ul(m);
|
|
return (data.size() >= max_elements);
|
|
}
|
|
|
|
bool empty() const {
|
|
std::unique_lock ul(m);
|
|
return data.empty();
|
|
};
|
|
|
|
size_t size() const { return data.size(); };
|
|
void operator >> (T& rval) { read(rval); }
|
|
void operator << (const T& rval) { write(rval); }
|
|
T read() { T ret; read(ret); return ret; }
|
|
};
|
|
|
|
template<class T, int DEPTH> class stream : public stream<T> {
|
|
public:
|
|
explicit stream(const char* name) : stream<T>(name, DEPTH) {}
|
|
stream() : stream<T>("", DEPTH) {}
|
|
};
|
|
}
|
|
|
|
#endif //JUNGFRAUJOCH_PARALLEL_STREAM_H
|