|
6 | 6 | * Diego Arturo Avila Torres <diego.avila@uned.cr>
|
7 | 7 | *
|
8 | 8 | */
|
| 9 | +#include <memory> |
| 10 | +#include <stdexcept> |
| 11 | +#include <string> |
9 | 12 |
|
10 | 13 | #include <cynq/xrt/accelerator.hpp>
|
11 | 14 |
|
12 | 15 | #include <cynq/accelerator.hpp>
|
13 | 16 | #include <cynq/enums.hpp>
|
14 | 17 | #include <cynq/status.hpp>
|
15 | 18 |
|
| 19 | +extern "C" { |
| 20 | +#include <pynq_api.h> /* FIXME: to be removed in future releases */ |
| 21 | +} |
| 22 | + |
| 23 | +/* |
| 24 | + * FIXME: This implementation is fully based on the PYNQ C API from the |
| 25 | + * community. This must be updated once the PYNQ C port as been done |
| 26 | + * in a decent manner. |
| 27 | + */ |
| 28 | + |
| 29 | +static constexpr uint64_t kAddrSpace = 65536; |
| 30 | + |
16 | 31 | namespace cynq {
|
17 |
| -Status XRTAccelerator::Start(const StartMode /*mode*/) { return Status{}; } |
| 32 | +/** |
| 33 | + * @brief Specialisation of the parameters given by the UltraScale. This is |
| 34 | + * only available by the source file to encapsulate the dependencies involved. |
| 35 | + */ |
| 36 | +struct XrtAcceleratorParameters : public AcceleratorParameters { |
| 37 | + /** Accelerator address */ |
| 38 | + uint64_t addr_; |
| 39 | + /** Address space size */ |
| 40 | + uint64_t addr_space_size_; |
| 41 | + /** HLS Design */ |
| 42 | + PYNQ_HLS hls_; |
| 43 | + /** Virtual destructor required for the inheritance */ |
| 44 | + virtual ~XrtAcceleratorParameters() = default; |
| 45 | +}; |
| 46 | + |
| 47 | +XRTAccelerator::XRTAccelerator(const uint64_t addr) |
| 48 | + : addr_{addr}, |
| 49 | + addr_space_size_{kAddrSpace}, |
| 50 | + accel_params_{std::make_unique<XrtAcceleratorParameters>()} { |
| 51 | + /* The assumption is that at this point, it is ok */ |
| 52 | + auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get()); |
| 53 | + |
| 54 | + params->addr_ = this->addr_; |
| 55 | + params->addr_space_size_ = this->addr_space_size_; |
| 56 | + |
| 57 | + if (PYNQ_SUCCESS != |
| 58 | + PYNQ_openHLS(¶ms->hls_, this->addr_, this->addr_space_size_)) { |
| 59 | + std::string msg = "Cannot open the design in addr: "; |
| 60 | + msg += std::to_string(this->addr_); |
| 61 | + throw std::runtime_error(msg); |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +Status XRTAccelerator::Start(const StartMode mode) { |
| 66 | + constexpr uint64_t ctrl_reg_addr = 0x00; |
| 67 | + const uint8_t ctrl_reg_val = StartMode::Once == mode ? 0x01 : 0x81; |
| 68 | + return this->WriteRegister(ctrl_reg_addr, &ctrl_reg_val, sizeof(uint8_t)); |
| 69 | +} |
| 70 | + |
| 71 | +Status XRTAccelerator::Stop() { |
| 72 | + constexpr uint64_t ctrl_reg_addr = 0x00; |
| 73 | + const uint8_t ctrl_reg_val = 0x0; |
| 74 | + return this->WriteRegister(ctrl_reg_addr, &ctrl_reg_val, sizeof(uint8_t)); |
| 75 | +} |
18 | 76 |
|
19 |
| -Status XRTAccelerator::Stop() { return Status{}; } |
| 77 | +DeviceStatus XRTAccelerator::GetStatus() { |
| 78 | + constexpr uint64_t ctrl_reg_addr = 0x00; |
| 79 | + uint8_t ctrl_reg_val = 0x0; |
20 | 80 |
|
21 |
| -DeviceStatus XRTAccelerator::GetStatus() { return DeviceStatus::Idle; } |
| 81 | + Status st = this->ReadRegister(ctrl_reg_addr, &ctrl_reg_val, sizeof(uint8_t)); |
| 82 | + if (Status::OK != st.code) { |
| 83 | + return DeviceStatus::Error; |
| 84 | + } |
22 | 85 |
|
23 |
| -Status XRTAccelerator::WriteRegister(const uint64_t /*address*/, |
24 |
| - const uint8_t* /*data*/, |
25 |
| - const size_t /*size*/) { |
| 86 | + switch (ctrl_reg_val) { |
| 87 | + case 0x01: |
| 88 | + case 0x03: |
| 89 | + case 0x81: |
| 90 | + case 0x83: |
| 91 | + return DeviceStatus::Running; |
| 92 | + case 0x04: |
| 93 | + return DeviceStatus::Idle; |
| 94 | + case 0x06: |
| 95 | + return DeviceStatus::Done; |
| 96 | + default: |
| 97 | + return DeviceStatus::Unknown; |
| 98 | + } |
| 99 | +} |
| 100 | + |
| 101 | +Status XRTAccelerator::WriteRegister(const uint64_t address, |
| 102 | + const uint8_t *data, const size_t size) { |
| 103 | + auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get()); |
| 104 | + auto ret = PYNQ_writeToHLS(¶ms->hls_, const_cast<uint8_t *>(data), |
| 105 | + address, size); |
| 106 | + if (PYNQ_SUCCESS != ret) { |
| 107 | + std::string msg = "Cannot write on HLS register: "; |
| 108 | + msg += std::to_string(address); |
| 109 | + msg += " the payload with size: "; |
| 110 | + msg += std::to_string(size); |
| 111 | + return Status{Status::REGISTER_IO_ERROR, msg}; |
| 112 | + } |
26 | 113 | return Status{};
|
27 | 114 | }
|
28 | 115 |
|
29 |
| -Status XRTAccelerator::ReadRegister(const uint64_t /*address*/, |
30 |
| - uint8_t* /*data*/, const size_t /*size*/) { |
| 116 | +Status XRTAccelerator::ReadRegister(const uint64_t address, uint8_t *data, |
| 117 | + const size_t size) { |
| 118 | + auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get()); |
| 119 | + auto ret = PYNQ_readFromHLS(¶ms->hls_, data, address, size); |
| 120 | + if (PYNQ_SUCCESS != ret) { |
| 121 | + std::string msg = "Cannot read on HLS register: "; |
| 122 | + msg += std::to_string(address); |
| 123 | + msg += " the payload with size: "; |
| 124 | + msg += std::to_string(size); |
| 125 | + return Status{Status::REGISTER_IO_ERROR, msg}; |
| 126 | + } |
31 | 127 | return Status{};
|
32 | 128 | }
|
| 129 | + |
| 130 | +XRTAccelerator::~XRTAccelerator() { |
| 131 | + /* The assumption is that at this point, it is ok */ |
| 132 | + auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get()); |
| 133 | + PYNQ_closeHLS(¶ms->hls_); |
| 134 | +} |
| 135 | + |
33 | 136 | } // namespace cynq
|
0 commit comments