Coyote/sw/include/cSched.hpp

180 lines
3.7 KiB
C++

#pragma once
#include "cDefs.hpp"
#include <cstdint>
#include <cstdio>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <boost/functional/hash.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#ifdef EN_AVX
#include <x86intrin.h>
#include <smmintrin.h>
#include <immintrin.h>
#endif
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
#include <iostream>
#include <fcntl.h>
#include <inttypes.h>
#include <mutex>
#include <atomic>
#include <sys/mman.h>
#include <sys/types.h>
#include <thread>
#include <sys/ioctl.h>
#include <fstream>
#include <tuple>
#include <condition_variable>
#include <thread>
#include <limits>
#include <queue>
using namespace std;
using namespace boost::interprocess;
namespace fpga {
/* Alias */
using mappedVal = std::pair<csAlloc, void*>; // n_pages, vaddr_non_aligned
using bStream = std::pair<void*, uint32_t>; // vaddr*, length
/* Struct */
struct cLoad {
int32_t cpid;
int32_t oid;
uint32_t priority;
};
/* Schedule reordering */
class taskCmprSched {
private:
bool priority;
bool reorder;
public:
taskCmprSched(const bool& priority, const bool& reorder) {
this->priority = priority;
this->reorder = reorder;
}
bool operator()(const std::unique_ptr<cLoad>& req1, const std::unique_ptr<cLoad>& req2) {
// Comparison
if(priority) {
if(req1->priority < req2->priority) return true;
}
if(reorder) {
if(req1->priority == req2->priority) {
if(req1->oid > req2->oid)
return true;
}
}
return false;
}
};
/**
* @brief Coyote scheduler
*
* This is the main vFPGA scheduler. It schedules submitted user tasks.
* These tasks trickle down: cTask -> cThread -> cProcess -> cSched -> vFPGA
*
*/
class cSched {
protected:
/* Fpga device */
int32_t fd = { 0 };
int32_t vfid = { -1 };
fCnfg fcnfg;
/* Locks */
named_mutex plock; // Internal vFPGA lock
named_mutex mlock; // Internal memory lock
/* Scheduling */
const bool priority;
const bool reorder;
/* Thread */
bool run;
thread scheduler_thread;
/* Current cpid */
int curr_cpid = { -1 };
/* Scheduler queue */
condition_variable cv_queue;
mutex mtx_queue;
priority_queue<std::unique_ptr<cLoad>, vector<std::unique_ptr<cLoad>>, taskCmprSched> request_queue;
/* Scheduling and completion */
condition_variable cv_cmpl;
mutex mtx_cmpl;
/* Bitstream memory */
std::unordered_map<void*, mappedVal> mapped_pages;
/* Partial bitstreams */
std::unordered_map<int32_t, bStream> bstreams;
/* PR */
uint8_t readByte(ifstream& fb);
void reconfigure(void* vaddr, uint32_t len);
/* Internal locks */
inline auto mLock() { mlock.lock(); }
inline auto mUnlock() { mlock.unlock(); }
/* Memory alloc */
void* getMem(const csAlloc& cs_alloc);
void freeMem(void* vaddr);
/* (Thread) Process requests */
void processRequests();
public:
/**
* @brief Ctor, Dtor
*
*/
cSched(int32_t vfid, bool priority = true, bool reorder = true);
~cSched();
/**
* @brief Getters
*
*/
inline auto getVfid() const { return vfid; }
/**
* @brief Reconfigure the vFPGA
*
* @param oid : operator ID
*/
auto isReconfigurable() const { return fcnfg.en_pr; }
void addBitstream(std::string name, int32_t oid);
void removeBitstream(int32_t oid);
bool checkBitstream(int32_t oid);
/**
* @brief Schedule operation
*
* @param cpid - Coyote id
* @param oid - operator id
* @param priority - task priority
*/
void pLock(int32_t cpid, int32_t oid, uint32_t priority);
void pUnlock(int32_t cpid);
};
} /* namespace fpga */