Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions examples/basic-example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

#include <cstdint>
#include <iostream>
#include <memory>
#include <string>

Expand All @@ -26,8 +27,8 @@ static constexpr char kBitstream[] = EXAMPLE_BITSTREAM_LOCATION;
static constexpr char kXclBin[] = EXAMPLE_DEFAULT_XCLBIN_LOCATION;

// Given by the design
static constexpr uint64_t kAccelAddress = 0xa0000000;
static constexpr uint64_t kDmaAddress = 0xa0010000;
static constexpr uint64_t kAccelAddress = EXAMPLE_ACCEL_ADDR;
static constexpr uint64_t kDmaAddress = EXAMPLE_DMA_ADDR;

// Addresses of the accelerator
static constexpr uint64_t kAccelNumDataAddr = 0x20;
Expand Down Expand Up @@ -60,12 +61,29 @@ int main() {

// Fill data on *in_data*...

// Configure the accel
accel->Write(kAccelNumDataAddr, &kNumData, kNumData);

// Start the accel in autorestart
accel->Start(StartMode::Continuous);

// Read the defaults:
uint32_t incols = 0;
uint32_t outcols = 0;

accel->Read(32, &incols, 1);
accel->Read(48, &outcols, 1);
std::cout << "Initial InCols: " << incols << std::endl;
std::cout << "Initial OutCols: " << outcols << std::endl;

// Configure the accel
incols = kNumData;
outcols = kNumData;
accel->Write(24, &incols, 1);
accel->Write(40, &outcols, 1);

accel->Read(32, &incols, 1);
accel->Read(48, &outcols, 1);
std::cout << "Configured InCols: " << incols << std::endl;
std::cout << "Configured OutCols: " << outcols << std::endl;

// Move the data
in_mem->Sync(SyncType::HostToDevice);
mover->Upload(in_mem, in_mem->Size(), ExecutionType::Sync);
Expand Down
9 changes: 9 additions & 0 deletions include/cynq/accelerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
#include <cynq/status.hpp>

namespace cynq {
/**
* @brief Define an abstract representation of the accelerator parameters
* with some prefilled fields
*/
struct AcceleratorParameters {
/** Virtual destructor required for the inheritance */
virtual ~AcceleratorParameters() = default;
};

/**
* @brief Interface for standardising the API for any Accelerator device:
* XRTAccelerator
Expand Down
1 change: 1 addition & 0 deletions include/cynq/status.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct Status {
by a function */
INCOMPATIBLE_PARAMETER,
CONFIGURATION_ERROR, /** Configuration error*/
REGISTER_IO_ERROR, /** Register MMIO error */
NOT_IMPLEMENTED, /** Not implemented error */
};

Expand Down
29 changes: 26 additions & 3 deletions include/cynq/xrt/accelerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
*
*/
#pragma once

#include <memory>

#include <cynq/accelerator.hpp>
#include <cynq/enums.hpp>
#include <cynq/status.hpp>
Expand All @@ -19,13 +22,25 @@ namespace cynq {
*/
class XRTAccelerator : public IAccelerator {
public:
XRTAccelerator() {}
/**
* @brief Delete the default constructor since address is needed
*/
XRTAccelerator() = delete;
/**
* @brief Construct a new XRTAccelerator object
*
* It constructs an accessor to the accelerator in the PL design according
* to the AXI-lite memory mapping. This is widely compatible with AXI4-lite
* controlled HLS designs.
*
* @param addr 64-bit address in the physical memory space
*/
explicit XRTAccelerator(const uint64_t addr);
/**
* @brief ~XRTAccelerator destructor method
* Destroy the XRTAccelerator object
*
*/
virtual ~XRTAccelerator() = default;
virtual ~XRTAccelerator();
/**
* @brief Start method
* This method starts the accelerator in either once or continuous mode (with
Expand Down Expand Up @@ -87,5 +102,13 @@ class XRTAccelerator : public IAccelerator {
*/
Status ReadRegister(const uint64_t address, uint8_t *data,
const size_t size) override;

private:
/** Accelerator address */
uint64_t addr_;
/** Address space size */
uint64_t addr_space_size_;
/** Accelerator-specific configurations */
std::unique_ptr<AcceleratorParameters> accel_params_;
};
} // namespace cynq
4 changes: 2 additions & 2 deletions src/cynq/accelerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@

namespace cynq {
std::shared_ptr<IAccelerator> IAccelerator::Create(IAccelerator::Type impl,
const uint64_t /*addr*/) {
const uint64_t addr) {
switch (impl) {
case IAccelerator::Type::XRT:
return std::make_shared<XRTAccelerator>();
return std::make_shared<XRTAccelerator>(addr);
default:
return nullptr;
}
Expand Down
119 changes: 111 additions & 8 deletions src/cynq/xrt/accelerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,131 @@
* Diego Arturo Avila Torres <diego.avila@uned.cr>
*
*/
#include <memory>
#include <stdexcept>
#include <string>

#include <cynq/xrt/accelerator.hpp>

#include <cynq/accelerator.hpp>
#include <cynq/enums.hpp>
#include <cynq/status.hpp>

extern "C" {
#include <pynq_api.h> /* FIXME: to be removed in future releases */
}

/*
* FIXME: This implementation is fully based on the PYNQ C API from the
* community. This must be updated once the PYNQ C port as been done
* in a decent manner.
*/

static constexpr uint64_t kAddrSpace = 65536;

namespace cynq {
Status XRTAccelerator::Start(const StartMode /*mode*/) { return Status{}; }
/**
* @brief Specialisation of the parameters given by the UltraScale. This is
* only available by the source file to encapsulate the dependencies involved.
*/
struct XrtAcceleratorParameters : public AcceleratorParameters {
/** Accelerator address */
uint64_t addr_;
/** Address space size */
uint64_t addr_space_size_;
/** HLS Design */
PYNQ_HLS hls_;
/** Virtual destructor required for the inheritance */
virtual ~XrtAcceleratorParameters() = default;
};

XRTAccelerator::XRTAccelerator(const uint64_t addr)
: addr_{addr},
addr_space_size_{kAddrSpace},
accel_params_{std::make_unique<XrtAcceleratorParameters>()} {
/* The assumption is that at this point, it is ok */
auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get());

params->addr_ = this->addr_;
params->addr_space_size_ = this->addr_space_size_;

if (PYNQ_SUCCESS !=
PYNQ_openHLS(&params->hls_, this->addr_, this->addr_space_size_)) {
std::string msg = "Cannot open the design in addr: ";
msg += std::to_string(this->addr_);
throw std::runtime_error(msg);
}
}

Status XRTAccelerator::Start(const StartMode mode) {
constexpr uint64_t ctrl_reg_addr = 0x00;
const uint8_t ctrl_reg_val = StartMode::Once == mode ? 0x01 : 0x81;
return this->WriteRegister(ctrl_reg_addr, &ctrl_reg_val, sizeof(uint8_t));
}

Status XRTAccelerator::Stop() {
constexpr uint64_t ctrl_reg_addr = 0x00;
const uint8_t ctrl_reg_val = 0x0;
return this->WriteRegister(ctrl_reg_addr, &ctrl_reg_val, sizeof(uint8_t));
}

Status XRTAccelerator::Stop() { return Status{}; }
DeviceStatus XRTAccelerator::GetStatus() {
constexpr uint64_t ctrl_reg_addr = 0x00;
uint8_t ctrl_reg_val = 0x0;

DeviceStatus XRTAccelerator::GetStatus() { return DeviceStatus::Idle; }
Status st = this->ReadRegister(ctrl_reg_addr, &ctrl_reg_val, sizeof(uint8_t));
if (Status::OK != st.code) {
return DeviceStatus::Error;
}

Status XRTAccelerator::WriteRegister(const uint64_t /*address*/,
const uint8_t* /*data*/,
const size_t /*size*/) {
switch (ctrl_reg_val) {
case 0x01:
case 0x03:
case 0x81:
case 0x83:
return DeviceStatus::Running;
case 0x04:
return DeviceStatus::Idle;
case 0x06:
return DeviceStatus::Done;
default:
return DeviceStatus::Unknown;
}
}

Status XRTAccelerator::WriteRegister(const uint64_t address,
const uint8_t *data, const size_t size) {
auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get());
auto ret = PYNQ_writeToHLS(&params->hls_, const_cast<uint8_t *>(data),
address, size);
if (PYNQ_SUCCESS != ret) {
std::string msg = "Cannot write on HLS register: ";
msg += std::to_string(address);
msg += " the payload with size: ";
msg += std::to_string(size);
return Status{Status::REGISTER_IO_ERROR, msg};
}
return Status{};
}

Status XRTAccelerator::ReadRegister(const uint64_t /*address*/,
uint8_t* /*data*/, const size_t /*size*/) {
Status XRTAccelerator::ReadRegister(const uint64_t address, uint8_t *data,
const size_t size) {
auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get());
auto ret = PYNQ_readFromHLS(&params->hls_, data, address, size);
if (PYNQ_SUCCESS != ret) {
std::string msg = "Cannot read on HLS register: ";
msg += std::to_string(address);
msg += " the payload with size: ";
msg += std::to_string(size);
return Status{Status::REGISTER_IO_ERROR, msg};
}
return Status{};
}

XRTAccelerator::~XRTAccelerator() {
/* The assumption is that at this point, it is ok */
auto params = dynamic_cast<XrtAcceleratorParameters *>(accel_params_.get());
PYNQ_closeHLS(&params->hls_);
}

} // namespace cynq
4 changes: 3 additions & 1 deletion third-party/resources/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ default_xclbin_location = fmt.format(meson.global_source_root(), files('default.

cpp_args += [
'-DEXAMPLE_BITSTREAM_LOCATION=' + matrix_bitstream_location,
'-DEXAMPLE_DEFAULT_XCLBIN_LOCATION=' + default_xclbin_location
'-DEXAMPLE_DEFAULT_XCLBIN_LOCATION=' + default_xclbin_location,
'-DEXAMPLE_ACCEL_ADDR=0xa0000000',
'-DEXAMPLE_DMA_ADDR=0xa0010000'
]