Files
Jungfraujoch/fpga/hls/parallel_stream.h

116 lines
3.6 KiB
C++

// Copyright (2019-2023) Paul Scherrer Institute
// 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;
std::chrono::seconds timeout;
size_t max_elements;
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(size_t nelem = UINT64_MAX, std::chrono::seconds blocking_timeout = std::chrono::minutes(15))
: max_elements(nelem), data(), timeout(blocking_timeout) {};
void write(const T& tail) {
std::unique_lock<std::mutex> ul(m);
while (data.size() >= max_elements) {
if (c_full.wait_for(ul, timeout)
== std::cv_status::timeout)
throw std::runtime_error("Likely deadlock");
}
internal_write(tail);
}
bool write_nb(const T& tail) {
std::unique_lock<std::mutex> ul(m);
if (data.size() >= max_elements) return false;
internal_write(tail);
return true;
}
bool read_nb(T& head) {
std::unique_lock<std::mutex> ul(m);
if (data.empty()) return false;
internal_read(head);
return true;
}
void read(T& head) {
std::unique_lock<std::mutex> ul(m);
while (data.empty()) {
if (c_empty.wait_for(ul, timeout)
== std::cv_status::timeout)
throw std::runtime_error("Likely deadlock");
}
internal_read(head);
}
bool full() const {
std::unique_lock<std::mutex> ul(m);
return (data.size() >= max_elements);
}
bool empty() const {
std::unique_lock<std::mutex> 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:
stream() : stream<T>(DEPTH) {}
};
}
#endif //JUNGFRAUJOCH_PARALLEL_STREAM_H