Commit 615f6dd2 authored by Jens Korinth's avatar Jens Korinth

Backport bugfixes and improvements from ATS branch

* backport improved vc709.tcl
* support for MSI-X interrupts
* support for BlueDMA replacement for dual_dma
* Platform API: raw read/writes
* setup.sh automatically builds .jar
* Compose: dumps Configuration in output directory
* Compose: adds activated Features to last dir level
* new Feature ATS+PRI w/Tcl support
* new Feature BlueDMA w/Tcl support
* some bugfixes regarding Features
parent 8a5068c7
......@@ -22,11 +22,10 @@
//! @authors J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
//!
#include <assert.h>
#include <tapasco_global.h>
#include <tapasco_address_map.h>
#include <platform.h>
#define TAPASCO_MAX_INSTANCES 128
static platform_ctl_addr_t _bases[TAPASCO_MAX_INSTANCES] = { 0 };
static inline tapasco_reg_addr_t base_addr(uint32_t const slot_id) {
......@@ -34,7 +33,7 @@ static inline tapasco_reg_addr_t base_addr(uint32_t const slot_id) {
tapasco_reg_addr_t ret = _bases[slot_id];
if (! ret)
ret = (_bases[slot_id] = platform_address_get_slot_base(slot_id, 0));
assert(ret > 0);
assert(slot_id == 0 || ret > 0);
return ret;
}
......
......@@ -29,6 +29,7 @@
#include <tapasco_address_map.h>
#include <tapasco_scheduler.h>
#include <tapasco_logging.h>
#include <tapasco_status.h>
#include <platform.h>
#include <platform_errors.h>
......@@ -38,6 +39,7 @@ struct tapasco_dev_ctx {
tapasco_jobs_t *jobs;
tapasco_ctx_t *ctx;
tapasco_dev_id_t id;
tapasco_status_t *status;
};
/** Interrupt handler callback. */
......@@ -59,7 +61,9 @@ tapasco_res_t tapasco_create_device(tapasco_ctx_t *ctx, tapasco_dev_id_t const d
{
tapasco_dev_ctx_t *p = (tapasco_dev_ctx_t *)malloc(sizeof(struct tapasco_dev_ctx));
if (p) {
tapasco_res_t res = tapasco_functions_init(&p->functions);
tapasco_res_t res = tapasco_status_init(&p->status);
res = res == TAPASCO_SUCCESS ? tapasco_functions_init(p->status,
&p->functions) : res;
res = res == TAPASCO_SUCCESS ? tapasco_jobs_init(&p->jobs) : res;
if (res != TAPASCO_SUCCESS) return res;
p->ctx = ctx;
......@@ -78,6 +82,7 @@ void tapasco_destroy_device(tapasco_ctx_t *ctx, tapasco_dev_ctx_t *dev_ctx)
platform_stop(0);
tapasco_jobs_deinit(dev_ctx->jobs);
tapasco_functions_deinit(dev_ctx->functions);
tapasco_status_deinit(dev_ctx->status);
free(dev_ctx);
}
......@@ -198,6 +203,20 @@ tapasco_res_t tapasco_device_job_get_return(tapasco_dev_ctx_t *dev_ctx,
return tapasco_jobs_get_return(dev_ctx->jobs, j_id, ret_len, ret_value);
}
tapasco_res_t tapasco_device_has_capability(tapasco_dev_ctx_t *dev_ctx,
tapasco_device_capability_t cap)
{
switch (cap) {
case TAPASCO_DEVICE_CAP_ATSPRI:
return tapasco_status_has_capability_0(dev_ctx->status, TAPASCO_CAP0_ATSPRI);
case TAPASCO_DEVICE_CAP_ATSCHECK:
return tapasco_status_has_capability_0(dev_ctx->status, TAPASCO_CAP0_ATSCHECK);
default:
WRN("unknown capability: %d (0x%0x)", cap, cap);
return TAPASCO_FAILURE;
}
}
void irq_handler(int const event)
{
LOG(LALL_IRQ, "IRQ event #%d", event);
......
......@@ -25,8 +25,8 @@
#define TAPASCO_FUNCTIONS_H__
#include <tapasco.h>
#define TAPASCO_MAX_INSTANCES 128
#include <tapasco_global.h>
#include <tapasco_status.h>
/**
* Identifies a 'slot' in the configuration, i.e., one possible instantiation
......@@ -39,10 +39,12 @@ typedef struct tapasco_functions tapasco_functions_t;
/**
* Initializes a function struct by populating with current data from device.
* @param status pointer to internal status core struct.
* @param funcs pointer to internal functions struct pointer.
* @return TAPASCO_SUCCESS if successful.
**/
tapasco_res_t tapasco_functions_init(tapasco_functions_t **funcs);
tapasco_res_t tapasco_functions_init(const tapasco_status_t *status,
tapasco_functions_t **funcs);
/**
* Releases the given function struct an allocated memory.
......
//
// Copyright (C) 2016 Jens Korinth, TU Darmstadt
//
// This file is part of Tapasco (TPC).
//
// Tapasco is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Tapasco is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tapasco. If not, see <http://www.gnu.org/licenses/>.
//
//! @file tpc_global.h
//! @brief Global definitions for the TPC implementation.
//! @authors J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
//!
#ifndef TAPASCO_GLOBAL_H__
#define TAPASCO_GLOBAL_H__
#define TAPASCO_MAX_INSTANCES 128
#endif /* TAPASCO_GLOBAL_H__ */
......@@ -25,7 +25,7 @@
#define TAPASCO_STATUS_H__
#include <tapasco.h>
#include <tapasco_functions.h>
#include <tapasco_global.h>
typedef struct tapasco_status tapasco_status_t;
struct tapasco_status {
......
......@@ -29,7 +29,6 @@
#include <tapasco_errors.h>
#include <tapasco_address_map.h>
#include <tapasco_logging.h>
#include <tapasco_status.h>
#include <platform.h>
/** State of functions, e.g., busy or idle. */
......@@ -73,16 +72,13 @@ static void setup_functions_from_status(tapasco_status_t const *status,
p->func[i] = status->id[i] ? tapasco_functions_create(status->id[i], i) : NULL;
}
tapasco_res_t tapasco_functions_init(tapasco_functions_t **funcs) {
tapasco_res_t tapasco_functions_init(const tapasco_status_t *status, tapasco_functions_t **funcs) {
tapasco_res_t res = TAPASCO_SUCCESS;
*funcs = (tapasco_functions_t *)malloc(sizeof(tapasco_functions_t));
if (! funcs) return TAPASCO_ERR_OUT_OF_MEMORY;
memset(*funcs, 0, sizeof(tapasco_functions_t));
tapasco_status_t *status = NULL;
res = tapasco_status_init(&status);
if (res == TAPASCO_SUCCESS)
setup_functions_from_status(status, *funcs);
tapasco_status_deinit(status);
assert (status);
setup_functions_from_status(status, *funcs);
return res;
}
......
......@@ -25,6 +25,7 @@ set_target_properties (tapasco-benchmark PROPERTIES COMPILE_FLAGS ${ADD_CXXFLAGS
set_target_properties (tapasco-benchmark PROPERTIES LINK_FLAGS ${ADD_LDFLAGS})
add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/json11.cpp ${CMAKE_CURRENT_SOURCE_DIR}/json11.hpp
COMMAND rm -rf json11
COMMAND git clone https://github.com/dropbox/json11.git
COMMAND cp json11/json11.* ${CMAKE_CURRENT_SOURCE_DIR}
)
......
/**
* @file AtsPriScreen.hpp
* @brief ATS/PRI check screen: Interfaces with ATScheck IP core.
* @author J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
**/
#ifndef ATSPRI_SCREEN_HPP__
#define ATSPRI_SCREEN_HPP__
#include <tapasco.hpp>
#include <platform.h>
#include "MenuScreen.hpp"
#include "WordManipulator.hpp"
class AtsPriScreen : public MenuScreen {
public:
AtsPriScreen(Tapasco *tapasco) : MenuScreen("ATS/PRI direct interface",
vector<string>()), _w(0), _b(31), _maxlen(0), tapasco(tapasco) {
delay_us = 250; // update delay
// require ATS/PRI
if (tapasco->has_capability(TAPASCO_DEVICE_CAP_ATSPRI) != TAPASCO_SUCCESS ||
tapasco->has_capability(TAPASCO_DEVICE_CAP_ATSCHECK) != TAPASCO_SUCCESS)
throw "need both ATS/PRI and ATScheck capabilities!";
// get ATScheck base address
_base = platform::platform_address_get_special_base(
platform::PLATFORM_SPECIAL_CTL_ATSPRI
);
// intialize word manipulators
for (int i = 0; i < ATS_REGC; ++i)
_word[i].reset(new WordManipulator(0));
_newp.reset(new WordManipulator(0));
_newp->set_description("New package");
_sendp.reset(new WordManipulator(0));
_sendp->set_description("Send package");
_write_status.reset(new WordManipulator(0));
_write_status->set_description("Write status");
_read_status.reset(new WordManipulator(0));
_read_status->set_description("Read status");
_inv_counter.reset(new WordManipulator(0));
_inv_counter->set_description("Invalidate Packages");
_inc_pkg_counter.reset(new WordManipulator(0));
_inc_pkg_counter->set_description("Total Incoming");
// compute max length of a word manipulator render
for (int i = 0; i < ATS_REGC; ++i)
_maxlen = _word[i]->length() > _maxlen ? _word[i]->length() : _maxlen;
if (_newp->length() > _maxlen) _maxlen = _newp->length();
if (_sendp->length() > _maxlen) _maxlen = _sendp->length();
if (_write_status->length() > _maxlen) _maxlen = _write_status->length();
if (_read_status->length() > _maxlen) _maxlen = _read_status->length();
}
virtual ~AtsPriScreen() {}
protected:
virtual void render() {
const int h = (rows - 3) / ATS_REGC;
int start_row = (rows - 3 - h * ATS_REGC) / 2;
int start_col = (cols - _maxlen) / 2;
// render first block: input request words
for (int i = 0; i < ATS_REGC / 2; ++i)
_word[i]->render(start_col, start_row + i, i == _w ? _b : -1);
// render second block: output response words
for (int i = ATS_REGC / 2; i < ATS_REGC; ++i)
print_reversed([&](){
_word[i]->render(start_col, start_row + 1 + i, i == _w ? _b : -1);
});
// top line
const char tmp[] = "wasd: move bit cursor t: toggle bit o: send p: request new package q: quit";
// render additional stuff
print_reversed([&](){mvprintw(0, (cols - strlen(tmp)) / 2, tmp);});
print_reversed([&](){_newp->render(start_col, start_row + ATS_REGC + 2);});
print_reversed([&](){_sendp->render(start_col, start_row + ATS_REGC + 3);});
print_reversed([&](){_write_status->render(start_col, start_row + ATS_REGC + 4);});
print_reversed([&](){_read_status->render(start_col, start_row + ATS_REGC + 5);});
print_reversed([&](){_inv_counter->render(start_col, start_row + ATS_REGC + 6);});
print_reversed([&](){_inc_pkg_counter->render(start_col, start_row + ATS_REGC + 7);});
}
virtual int perform(const int choice) {
bool arrowKey = false;
if (choice == KEY_UP || static_cast<char>(choice) == 'w') {
_w = _w == 0 ? 7 : _w - 1;
arrowKey = true;
}
if (choice == KEY_DOWN || static_cast<char>(choice) == 's') {
_w = _w == 7 ? 0 : _w + 1;
arrowKey = true;
}
if (choice == KEY_RIGHT || static_cast<char>(choice) == 'd') {
_b = _b == 0 ? 31 : _b - 1;
arrowKey = true;
}
if (choice == KEY_LEFT || static_cast<char>(choice) == 'a') {
_b = _b == 31 ? 0 : _b + 1;
arrowKey = true;
}
if (arrowKey) return ERR;
if (static_cast<char>(choice) == 't') return toggle_bit();
if (static_cast<char>(choice) == 'o') return send();
if (static_cast<char>(choice) == 'p') return request();
if (static_cast<char>(choice) == 'r') return reset();
if (choice == ERR) delay();
if (static_cast<char>(choice) == 'q') return 0;
return ERR;
}
virtual void update() {
// update new package register
updateWord(*_newp, 16);
// update send package register
updateWord(*_sendp, 17);
// update read status register
updateWord(*_read_status, 19);
// update write status register
updateWord(*_write_status, 18);
// update invalid package counter
updateWord(*_inv_counter, 20);
// update incoming package counter
updateWord(*_inc_pkg_counter, 21);
// update package in and out registers
for (int i = 0; i < ATS_REGC; ++i)
updateWord(*_word[i], i);
}
private:
static constexpr int ATS_REGC { 16 };
int _w, _b;
std::unique_ptr<WordManipulator> _word[ATS_REGC];
std::unique_ptr<WordManipulator> _newp;
std::unique_ptr<WordManipulator> _sendp;
std::unique_ptr<WordManipulator> _write_status;
std::unique_ptr<WordManipulator> _read_status;
std::unique_ptr<WordManipulator> _inv_counter;
std::unique_ptr<WordManipulator> _inc_pkg_counter;
size_t _maxlen;
platform::platform_ctl_addr_t _base;
Tapasco *tapasco;
int toggle_bit() {
_word[_w]->tgl(_b);
platform::platform_ctl_addr_t h = platform::platform_address_get_special_base(
platform::PLATFORM_SPECIAL_CTL_ATSPRI
);
auto v = _word[_w]->value();
if (platform::platform_write_ctl(h + _w * 0x4, sizeof(v), &v,
platform::PLATFORM_CTL_FLAGS_NONE) != platform::PLATFORM_SUCCESS) {
_word[_w + 8]->error_on();
}
return ERR;
}
int send() {
uint32_t v { 1 };
platform::platform_ctl_addr_t h = platform::platform_address_get_special_base(
platform::PLATFORM_SPECIAL_CTL_ATSPRI
);
if (platform::platform_write_ctl(h + 0x4 * 17, sizeof(v), &v,
platform::PLATFORM_CTL_FLAGS_NONE) != platform::PLATFORM_SUCCESS) {
return 0;
}
return ERR;
}
int request() {
uint32_t v { 0 };
platform::platform_ctl_addr_t h = platform::platform_address_get_special_base(
platform::PLATFORM_SPECIAL_CTL_ATSPRI
);
if (platform::platform_write_ctl(h + 0x4 * 16, sizeof(v), &v,
platform::PLATFORM_CTL_FLAGS_NONE) != platform::PLATFORM_SUCCESS) {
return 0;
}
return ERR;
}
int reset() {
platform::platform_ctl_addr_t h = platform::platform_address_get_special_base(
platform::PLATFORM_SPECIAL_CTL_ATSPRI
);
uint32_t v[] = {
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
};
for (int i = 0; i < ATS_REGC / 2; ++i) {
if (platform::platform_write_ctl(h + i * 0x4, sizeof(v[i]), &v[i],
platform::PLATFORM_CTL_FLAGS_NONE) != platform::PLATFORM_SUCCESS) {
throw "could not write register";
}
}
return ERR;
}
/** Toggle to reversed, print, untoggle. **/
void print_reversed(std::function<void()> fn) {
attron(A_REVERSE);
fn();
attroff(A_REVERSE);
}
void updateWord(WordManipulator& w, size_t reg_idx) {
uint32_t d { 0 };
if (platform::platform_read_ctl(_base + 0x4 * reg_idx, sizeof(d), &d,
platform::PLATFORM_CTL_FLAGS_NONE) != platform::PLATFORM_SUCCESS) {
w.error_on();
} else {
w.set(d);
w.error_off();
}
}
};
#endif /* ATSPRI_SCREEN_HPP__*/
/* vim: set foldmarker=@{,@} foldlevel=0 foldmethod=marker : */
/**
* @file MonitorScreen.hpp
* @brief Register monitor screen for the blue infrastructure of TPC.
* @author J. Hofmann, TU Darmstadt (hofmann@esa.tu-darmstadt.de)
**/
#ifndef BLUE_DEBUG_SCREEN_HPP__
#define BLUE_DEBUG_SCREEN_HPP__
#include <tapasco.hpp>
#include <platform.h>
#include "MenuScreen.hpp"
class BlueDebugScreen : public MenuScreen {
public:
BlueDebugScreen(Tapasco *tapasco) : MenuScreen("Blue Monitor", vector<string>()), tapasco(tapasco) {
delay_us = 250;
// We go with eight interrupts for now...
for(int i = 0; i < total_interrupts; ++i) {
interrupt_data d;
intr.interrupts.push_back(d);
}
int pba_vecs = (total_interrupts / 64) + ((total_interrupts % 64) != 0);
for(int i = 0; i < pba_vecs; ++i) {
intr.pba.push_back(0);
}
}
virtual ~BlueDebugScreen() {}
protected:
virtual void render() {
constexpr int rowc = 5;
constexpr int colc = 16;
const int h = (rows - 3) / rowc;
const int w = cols / colc;
int start_row = (rows - 3 - h * rowc) / 2;
int start_col = (cols - w * colc) / 2;
render_dma(start_row, start_col);
start_col += 80;
render_msix(start_row, start_col);
}
virtual int perform(const int choice) {
if (choice == ERR) delay();
return choice;
}
virtual void update() {
// Update BlueDMA data
platform::platform_read_ctl(0x300000 + 0, sizeof(dma.host_addr), &dma.host_addr, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 8, sizeof(dma.fpga_addr), &dma.fpga_addr, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 16, sizeof(dma.transfer_length), &dma.transfer_length, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 24, sizeof(dma.id), &dma.id, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 32, sizeof(dma.cmd), &dma.cmd, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 40, sizeof(dma.status), &dma.status, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 48, sizeof(dma.read_requests), &dma.read_requests, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 56, sizeof(dma.write_requests), &dma.write_requests, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 64, sizeof(dma.ack_count), &dma.ack_count, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 120, sizeof(dma.reads_faulty), &dma.reads_faulty, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 128, sizeof(dma.writes_faulty), &dma.writes_faulty, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 136, sizeof(dma.get_delay), &dma.get_delay, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 144, sizeof(dma.put_delay), &dma.put_delay, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 152, sizeof(dma.last_written), &dma.last_written, platform::PLATFORM_CTL_FLAGS_RAW);
platform::platform_read_ctl(0x300000 + 160, sizeof(dma.last_read), &dma.last_read, platform::PLATFORM_CTL_FLAGS_RAW);
// Update Interrupt data
uint32_t base_addr = 0x500000;
for(int i = 0; i < total_interrupts; ++i) {
platform::platform_read_ctl(base_addr, sizeof(intr.interrupts[i].addr), &intr.interrupts[i].addr, platform::PLATFORM_CTL_FLAGS_RAW);
base_addr += 8;
platform::platform_read_ctl(base_addr, sizeof(intr.interrupts[i].data), &intr.interrupts[i].data, platform::PLATFORM_CTL_FLAGS_RAW);
base_addr += 4;
platform::platform_read_ctl(base_addr, sizeof(intr.interrupts[i].vector_control), &intr.interrupts[i].vector_control, platform::PLATFORM_CTL_FLAGS_RAW);
base_addr += 4;
}
base_addr = 0x502000;
for(int i = 0; i < 1 + (total_interrupts / 64) + ((total_interrupts % 64) != 0); ++i) {
platform::platform_read_ctl(base_addr, sizeof(intr.pba[i]), &intr.pba[i], platform::PLATFORM_CTL_FLAGS_RAW);
base_addr += 8;
}
base_addr = 0x504000;
platform::platform_read_ctl(base_addr, sizeof(intr.core_id), &intr.core_id, platform::PLATFORM_CTL_FLAGS_RAW);
base_addr += 4;
platform::platform_read_ctl(base_addr, sizeof(intr.enableAndMask), &intr.enableAndMask, platform::PLATFORM_CTL_FLAGS_RAW);
base_addr += 4;
platform::platform_read_ctl(base_addr, sizeof(intr.completedInterrupts), &intr.completedInterrupts, platform::PLATFORM_CTL_FLAGS_RAW);
base_addr += 4;
platform::platform_read_ctl(base_addr, sizeof(intr.sentInterrupts), &intr.sentInterrupts, platform::PLATFORM_CTL_FLAGS_RAW);
}
private:
struct dma_regs {
uint64_t host_addr;
uint64_t fpga_addr;
uint64_t transfer_length;
uint64_t id;
uint64_t cmd;
uint64_t status;
uint64_t read_requests;
uint64_t write_requests;
uint64_t ack_count;
uint64_t reads_faulty;
uint64_t writes_faulty;
uint64_t get_delay;
uint64_t put_delay;
uint64_t last_written;
uint64_t last_read;
};
struct interrupt_data {
uint64_t addr;
uint32_t data;
uint32_t vector_control;
};
struct intr_regs {
std::vector<interrupt_data> interrupts;
std::vector<uint64_t> pba;
uint32_t core_id;
uint32_t enableAndMask;
uint32_t completedInterrupts;
uint32_t sentInterrupts;
};
dma_regs dma;
intr_regs intr;
const int32_t total_interrupts = 64;
void render_dma(int start_row, int start_col) {
mvprintw(start_row++, start_col, "Host Address: %016lx, FPGA Address: %016lx", dma.host_addr, dma.fpga_addr);
mvprintw(start_row++, start_col, "Bytes to Transfer: %ld", dma.transfer_length);
mvprintw(start_row++, start_col, "Read requests: %ld, Reads faulty: %ld", dma.read_requests, dma.reads_faulty);
mvprintw(start_row++, start_col, "Write requests: %ld, Writes faulty: %ld", dma.write_requests, dma.writes_faulty);
mvprintw(start_row++, start_col, "ACKs: %ld", dma.ack_count);
mvprintw(start_row++, start_col, "Last written: %lx, Last read: %lx", dma.last_written, dma.last_read);
uint32_t total_gets = (dma.get_delay & 0xFFFFFFFF);
uint32_t total_puts = (dma.put_delay & 0xFFFFFFFF);
uint32_t get_delay = (dma.get_delay >> 32);
uint32_t put_delay = (dma.put_delay >> 32);
double get_latency = (double) get_delay / (double) total_gets;
double put_latency = (double) put_delay / (double) total_puts;
mvprintw(start_row++, start_col, "Put Delay: %f, Total Puts: %d %d", put_latency, total_puts, put_delay);
mvprintw(start_row++, start_col, "Get Delay: %f, Total Gets: %d %d", get_latency, total_gets, get_delay);
}
void render_msix(int start_row, int start_col) {
mvprintw(start_row++, start_col, "Core ID: %x", intr.core_id);
for(int i = 0; i < total_interrupts; ++i) {
if(!intr.interrupts[i].vector_control) {
mvprintw(start_row++, start_col, "Interrupt %d Address: %016lx Data: %08x Vector: %08x", i, intr.interrupts[i].addr, intr.interrupts[i].data, intr.interrupts[i].vector_control);
}
}
int pba_vecs = (total_interrupts / 64) + ((total_interrupts % 64) != 0);
for(int i = 0; i < pba_vecs; ++i) {
mvprintw(start_row++, start_col, "PBA %d - %d: %16lx", i * 64, i * 64 + 63, intr.pba[i]);
}
mvprintw(start_row++, start_col, "Enable: %x Mask: %x", (intr.enableAndMask >> 16) & 0x1, intr.enableAndMask & 0x1);
mvprintw(start_row++, start_col, "Sent Interrupts: %d", intr.sentInterrupts);
mvprintw(start_row++, start_col, "Completed Interrupts: %d", intr.completedInterrupts & 0xFFFF);
mvprintw(start_row++, start_col, "Interrupt Sent delay: %d", (intr.completedInterrupts >> 16) & 0xFFFF);
}
Tapasco *tapasco;
};
#endif
......@@ -11,18 +11,27 @@
#include "TapascoStatusScreen.hpp"
#include "InterruptStressTestScreen.hpp"
#include "MonitorScreen.hpp"
#include "BlueDebugScreen.hpp"
#include "AtsPriScreen.hpp"
using namespace tapasco;
class TapascoDebugMenu : public MenuScreen {
public:
TapascoDebugMenu() : MenuScreen("Welcome to the interactive TPC Debugger", vector<string>()) {
TapascoDebugMenu() : MenuScreen("Welcome to the interactive TaPaSCo Debugger", vector<string>()) {
options.push_back("Show kernel map of current bitstream");
screens.push_back(new TapascoStatusScreen(&tapasco));
options.push_back("Perform interrupt stress test");
screens.push_back(new InterruptStressTestScreen(&tapasco));
options.push_back("Monitor device registers");
screens.push_back(new MonitorScreen(&tapasco));
options.push_back("Monitor blue infrastructure");
screens.push_back(new BlueDebugScreen(&tapasco));
if (tapasco.has_capability(TAPASCO_DEVICE_CAP_ATSPRI) == TAPASCO_SUCCESS &&
tapasco.has_capability(TAPASCO_DEVICE_CAP_ATSCHECK) == TAPASCO_SUCCESS) {
options.push_back("ATS/PRI direct interface");
screens.push_back(new AtsPriScreen(&tapasco));
}
options.push_back("Exit");
}
virtual ~TapascoDebugMenu() {
......
/**
* @file WordManipulator.hpp
* @brief ATS/PRI check screen: Model of a 32bit register.
* @author J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
**/
#ifndef WORDMANIPULATOR_HPP__
#define WORDMANIPULATOR_HPP__
#include <iomanip>
#include <ncurses.h>
#include <stdint.h>
#include <string>
#include <sstream>
/**
* WordManipulator models a 32bit register with operations on it.
* It can render itself using ncurses, in a format like this:
* |00000000|00000000|00000000|00000000| 0x00000000 Description
**/
class WordManipulator {
public:
WordManipulator(uint32_t init) : _v(init), _error_on(false), _desc("") {}
virtual ~WordManipulator() {}
bool bit(uint8_t bit) const { return (_v & (1 << bit)) > 0; }
void set(uint8_t bit) { _v |= (1 << bit); }
void clr(uint8_t bit) { _v &= ~(1 << bit); }
void tgl(uint8_t bit) { _v ^= (1 << bit); }
uint32_t value() const { return _v; }
void set(uint32_t v) { _v = v; }
void error_on() { _error_on = true; }
void error_off() { _error_on = false; }
void set_description(std::string d) { _desc = d; }
size_t length() { return 47 + _desc.length(); }
void render(int x, int y, uint8_t b = -1) {
std::stringstream formatted;
for(int i = 0; i < 32; i += 1) {
if((i % 8) == 0) formatted << '|';
formatted << bit(31 - i);
}
formatted << "| 0x" << std::hex << std::setfill('0') << std::setw(8) << _v;
formatted << " " << _desc;
if (_error_on) attron(COLOR_PAIR(1));
mvprintw(y, x, formatted.str().c_str());
if (_error_on) attroff(COLOR_PAIR(1));
if (b >= 0) {
attron(A_REVERSE);
mvprintw(y, x + 1 + ((31 - b) / 8) + (31 - b), "%d", bit(b));
attroff(A_REVERSE);
}
}
private:
uint32_t _v;
bool _error_on;
std::string _desc;
};
#endif /* WORDMANIPULATOR_HPP__*/
......@@ -187,6 +187,9 @@ int main(int argc, const char *argv[]) {
ofstream f(argc >= 2 ? argv[1] : ss.str());
f << benchmark.dump();
f.close();
} catch (const char *msg) {
endwin();
cerr << "ERROR: " << msg << endl;
} catch (...) {
endwin();
throw;
......
......@@ -42,5 +42,9 @@ int main(int argc, char *argv[])
exit_ncurses();
cerr << "Unknown error occurred." << endl;
exit(1);
} catch (...) {
exit_ncurses();
cerr << "ERROR" << endl;
throw;
}
}
......@@ -26,12 +26,16 @@ namespace eval tapasco {