Blame opae-libs/libopaecxx/samples/hello_fpga-1.cpp

Packit 534379
// Copyright(c) 2018-2020, Intel Corporation
Packit 534379
//
Packit 534379
// Redistribution  and  use  in source  and  binary  forms,  with  or  without
Packit 534379
// modification, are permitted provided that the following conditions are met:
Packit 534379
//
Packit 534379
// * Redistributions of  source code  must retain the  above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer.
Packit 534379
// * Redistributions in binary form must reproduce the above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer in the documentation
Packit 534379
//   and/or other materials provided with the distribution.
Packit 534379
// * Neither the name  of Intel Corporation  nor the names of its contributors
Packit 534379
//   may be used to  endorse or promote  products derived  from this  software
Packit 534379
//   without specific prior written permission.
Packit 534379
//
Packit 534379
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 534379
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO,  THE
Packit 534379
// IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 534379
// ARE DISCLAIMED.  IN NO EVENT  SHALL THE COPYRIGHT OWNER  OR CONTRIBUTORS BE
Packit 534379
// LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
Packit 534379
// CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT  OF
Packit 534379
// SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
Packit 534379
// INTERRUPTION)  HOWEVER CAUSED  AND ON ANY THEORY  OF LIABILITY,  WHETHER IN
Packit 534379
// CONTRACT,  STRICT LIABILITY,  OR TORT  (INCLUDING NEGLIGENCE  OR OTHERWISE)
Packit 534379
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
Packit 534379
// POSSIBILITY OF SUCH DAMAGE.
Packit 534379
#ifdef HAVE_CONFIG_H
Packit 534379
#include <config.h>
Packit 534379
#endif  // HAVE_CONFIG_H
Packit 534379
#include <algorithm>
Packit 534379
#include <chrono>
Packit 534379
#include <iostream>
Packit 534379
#include <string>
Packit 534379
#include <thread>
Packit 534379
Packit 534379
#include <uuid/uuid.h>
Packit 534379
Packit 534379
#include <opae/cxx/core/handle.h>
Packit 534379
#include <opae/cxx/core/properties.h>
Packit 534379
#include <opae/cxx/core/shared_buffer.h>
Packit 534379
#include <opae/cxx/core/token.h>
Packit 534379
#include <opae/cxx/core/version.h>
Packit 534379
Packit 534379
using namespace opae::fpga::types;
Packit 534379
Packit 534379
static const char* NLB0_AFUID = "D8424DC4-A4A3-C413-F89E-433683F9040B";
Packit 534379
static const uint64_t CL = 64;
Packit 534379
static const uint64_t KB = 1024;
Packit 534379
static const uint64_t MB = KB * 1024;
Packit 534379
static const uint64_t LOG2_CL = 6;
Packit 534379
static const size_t LPBK1_DSM_SIZE = 2 * MB;
Packit 534379
static const size_t LPBK1_BUFFER_SIZE = 1 * MB;
Packit 534379
static const size_t LPBK1_BUFFER_ALLOCATION_SIZE = 2 * MB;
Packit 534379
static const uint64_t CSR_SRC_ADDR = 0x0120;
Packit 534379
static const uint32_t CSR_DST_ADDR = 0x0128;
Packit 534379
static const uint32_t CSR_CTL = 0x0138;
Packit 534379
static const uint32_t CSR_CFG = 0x0140;
Packit 534379
static const uint32_t CSR_NUM_LINES = 0x0130;
Packit 534379
static const uint32_t DSM_STATUS_TEST_COMPLETE = 0x40;
Packit 534379
static const uint64_t CSR_AFU_DSM_BASEL = 0x0110;
Packit 534379
Packit 534379
static inline uint64_t cacheline_aligned_addr(uint64_t num) {
Packit 534379
  return num >> LOG2_CL;
Packit 534379
}
Packit 534379
Packit 534379
int main(int argc, char* argv[]) {
Packit 534379
  if ((argc > 1) && ((std::string(argv[1]) == std::string("-v")) ||
Packit 534379
                     (std::string(argv[1]) == std::string("--version")))) {
Packit 534379
    std::cout << "hello_cxxcore " << OPAE_VERSION << " "
Packit 534379
              << OPAE_GIT_COMMIT_HASH;
Packit 534379
    if (OPAE_GIT_SRC_TREE_DIRTY) std::cout << "*";
Packit 534379
    std::cout << std::endl;
Packit 534379
    return 0;
Packit 534379
  }
Packit 534379
Packit 534379
  std::cout << "Using OPAE C++ Core library version '" << version::as_string()
Packit 534379
            << "' build '" << version::build() << "'\n";
Packit 534379
  // look for accelerator with NLB0_AFUID
Packit 534379
  properties::ptr_t filter = properties::get();
Packit 534379
  filter->guid.parse(NLB0_AFUID);
Packit 534379
  filter->type = FPGA_ACCELERATOR;
Packit 534379
Packit 534379
  std::vector<token::ptr_t> tokens = token::enumerate({filter});
Packit 534379
Packit 534379
  // assert we have found at least one
Packit 534379
  if (tokens.size() < 1) {
Packit 534379
    std::cerr << "accelerator not found\n";
Packit 534379
    return -1;
Packit 534379
  }
Packit 534379
  token::ptr_t tok = tokens[0];
Packit 534379
Packit 534379
  // open accelerator and map MMIO
Packit 534379
  handle::ptr_t accel = handle::open(tok, FPGA_OPEN_SHARED);
Packit 534379
Packit 534379
  // allocate buffers
Packit 534379
  shared_buffer::ptr_t dsm = shared_buffer::allocate(accel, LPBK1_DSM_SIZE);
Packit 534379
  shared_buffer::ptr_t inp =
Packit 534379
      shared_buffer::allocate(accel, LPBK1_BUFFER_ALLOCATION_SIZE);
Packit 534379
  shared_buffer::ptr_t out =
Packit 534379
      shared_buffer::allocate(accel, LPBK1_BUFFER_ALLOCATION_SIZE);
Packit 534379
Packit 534379
  std::cout << "Running Test\n";
Packit 534379
Packit 534379
  // initialize buffers
Packit 534379
  std::fill_n(dsm->c_type(), LPBK1_DSM_SIZE, 0);
Packit 534379
  std::fill_n(inp->c_type(), LPBK1_BUFFER_SIZE, 0xAF);
Packit 534379
  std::fill_n(out->c_type(), LPBK1_BUFFER_SIZE, 0xBE);
Packit 534379
Packit 534379
  accel->reset();
Packit 534379
  accel->write_csr64(CSR_AFU_DSM_BASEL, dsm->io_address());
Packit 534379
  accel->write_csr32(CSR_CTL, 0);
Packit 534379
  accel->write_csr32(CSR_CTL, 1);
Packit 534379
  accel->write_csr64(CSR_SRC_ADDR, cacheline_aligned_addr(inp->io_address()));
Packit 534379
  accel->write_csr64(CSR_DST_ADDR, cacheline_aligned_addr(out->io_address()));
Packit 534379
Packit 534379
  accel->write_csr32(CSR_NUM_LINES, LPBK1_BUFFER_SIZE / (1 * CL));
Packit 534379
  accel->write_csr32(CSR_CFG, 0x42000);
Packit 534379
Packit 534379
  // get ptr to device status memory - test complete
Packit 534379
  // temporarily "borrow" a raw pointer to the buffer
Packit 534379
  // status_ptr can be dangling pointer if dsm is the only reference
Packit 534379
  // and it is reset or goes out of scope before status_ptr
Packit 534379
  volatile uint8_t* status_ptr = dsm->c_type() + DSM_STATUS_TEST_COMPLETE;
Packit 534379
  // start the test
Packit 534379
  accel->write_csr32(CSR_CTL, 3);
Packit 534379
Packit 534379
  // wait for test completion
Packit 534379
  while (0 == ((*status_ptr) * 0x1)) {
Packit 534379
    std::this_thread::sleep_for(std::chrono::microseconds(100));
Packit 534379
  }
Packit 534379
Packit 534379
  // stop the device
Packit 534379
  accel->write_csr32(CSR_CTL, 7);
Packit 534379
Packit 534379
  // check output buffer contents
Packit 534379
  std::pair<volatile uint8_t*, volatile uint8_t*> mm = std::mismatch(
Packit 534379
      inp->c_type(), inp->c_type() + LPBK1_BUFFER_SIZE, out->c_type());
Packit 534379
  if (mm.second < out->c_type() + LPBK1_BUFFER_SIZE) {
Packit 534379
    std::cerr << "output does NOT match input at offset: "
Packit 534379
              << (mm.second - out->c_type()) << "\n";
Packit 534379
    return -1;
Packit 534379
  }
Packit 534379
Packit 534379
  std::cout << "Done Running Test\n";
Packit 534379
Packit 534379
  return 0;
Packit 534379
}