Unverified Commit f5f24ef8 authored by zyno42's avatar zyno42
Browse files

Improve code for Registers and Local Memory panes

Replace unnecessary `StatefulList`s with `ListStates`.
Make the number of registers and the size of local memory endless.
parent 3bad6ea4
use std::collections::HashMap;
use tui::widgets::ListState;
use log::{error, trace, warn};
use tapasco::{
......@@ -53,8 +55,8 @@ pub struct App<'a> {
pub tabs: TabsState<'a>,
pub pe_infos: StatefulList<String>,
pub pes: Vec<(usize, PE)>, // Plural of Processing Element (PEs)
pub register_list: StatefulList<String>,
pub local_memory_list: StatefulList<String>,
pub register_list: ListState,
pub local_memory_list: ListState,
pub messages: Vec<String>,
}
......@@ -151,9 +153,9 @@ impl<'a> App<'a> {
StatefulList::with_items_selected(pe_infos, 0)
};
// There are theoretically endless registers. 100 seems to be a good value.
let register_list = StatefulList::with_items(vec!["".to_string(); 100]);
let local_memory_list = StatefulList::new();
// There are theoretically endless registers and local memory
let register_list = ListState::default();
let local_memory_list = ListState::default();
// Parse bitstream info from the Status core
let mut bitstream_info = String::new();
......@@ -328,7 +330,7 @@ impl<'a> App<'a> {
.expect("There should have been a selected PE. This is a bug."))
.expect("There should have been a PE for the selection. This is a bug.")
.1 // ignore the index, select the PE from the tuple
.set_arg(self.register_list.state.selected().unwrap(),
.set_arg(self.register_list.selected().unwrap(),
PEParameter::Single64(new_value)) {
// but log this error in case the code changes
error!("Error setting argument: {}.
......@@ -336,6 +338,11 @@ impl<'a> App<'a> {
important. You should fix this app.", e);
}
self.messages.push(format!("In slot {} set argument register {} to new value: {}.",
self.pe_infos.state.selected().unwrap(),
self.register_list.selected().unwrap(),
new_value));
self.input_mode = InputMode::Navigation;
}
}
......@@ -359,7 +366,7 @@ impl<'a> App<'a> {
_ => return None,
};
// Get the PE with the real ID of the selected Slot
// Get the PE with the real ID of the selected slot
let (_, pe) = self
.pes
.iter()
......@@ -410,7 +417,7 @@ impl<'a> App<'a> {
(ptr as *mut u32).write_volatile(1);
}
return format!("Started PE with ID: {}.", pe.id())
return format!("Send start signal to PE in slot: {}.", self.pe_infos.state.selected().expect("There needs to be a selected PE. This is a bug."))
}
"No PE selected.".to_string()
......@@ -445,9 +452,11 @@ impl<'a> App<'a> {
// TODO: add a function parameter for the number of registers that should be read to make it
// dependent on the size of the UI frame.
pub fn get_argument_registers(&mut self) -> Vec<String> {
pub fn get_argument_registers(&mut self, number_of_lines: usize) -> Vec<String> {
let number_of_registers = self.register_list.selected().unwrap_or(0) + number_of_lines;
if let Some(pe) = self.get_current_pe() {
let argument_registers = (0..self.register_list.items.len())
let argument_registers = (0..number_of_registers)
.map(|i| {
match pe
.read_arg(i, 8)
......@@ -470,14 +479,14 @@ impl<'a> App<'a> {
}
}
pub fn dump_current_pe_local_memory(&self) -> Vec<String> {
pub fn dump_current_pe_local_memory(&self, number_of_lines: usize) -> Vec<String> {
if let Some(pe) = self.get_current_pe() {
let local_memory = match pe.local_memory() {
Some(m) => m,
_ => return vec!["No local memory for this PE.".to_string()],
};
let mut memory_cells: Box<[u8]> = Box::new([0_u8; 16 * 100]);
let mut memory_cells: Vec<u8> = vec![0_u8; 16 * number_of_lines];
match local_memory.dma().copy_from(0, &mut memory_cells) {
Ok(_) => {}
_ => return vec!["Could not read PE Local Memory!".to_string()],
......@@ -610,21 +619,21 @@ impl<'a> TabsState<'a> {
}
}
use tui::widgets::ListState;
pub struct StatefulList<T> {
pub state: ListState,
pub items: Vec<T>,
}
impl<T> StatefulList<T> {
pub fn new() -> Self {
impl<T> Default for StatefulList<T> {
fn default() -> Self {
Self {
state: ListState::default(),
items: Vec::new(),
}
}
}
impl<T> StatefulList<T> {
pub fn with_items(items: Vec<T>) -> Self {
Self {
state: ListState::default(),
......@@ -641,8 +650,17 @@ impl<T> StatefulList<T> {
list
}
}
pub fn next(&mut self) {
// Define a new trait so we can implement methods for ListState
pub trait Select {
fn next(&mut self);
fn previous(&mut self);
fn unselect(&mut self);
}
impl<T> Select for StatefulList<T> {
fn next(&mut self) {
let n = match self.state.selected() {
Some(m) => {
if m >= self.items.len() - 1 {
......@@ -657,7 +675,7 @@ impl<T> StatefulList<T> {
self.state.select(Some(n));
}
pub fn previous(&mut self) {
fn previous(&mut self) {
let n = match self.state.selected() {
Some(m) => {
if m == 0 {
......@@ -672,7 +690,37 @@ impl<T> StatefulList<T> {
self.state.select(Some(n));
}
pub fn unselect(&mut self) {
fn unselect(&mut self) {
self.state.select(None);
}
}
impl Select for ListState {
fn next(&mut self) {
let n = match self.selected() {
Some(m) => m + 1,
None => 0,
};
self.select(Some(n));
}
fn previous(&mut self) {
let n = match self.selected() {
Some(m) => {
if m == 0 {
0
} else {
m - 1
}
}
None => 0,
};
self.select(Some(n));
}
fn unselect(&mut self) {
self.select(None);
}
}
......@@ -107,7 +107,6 @@ fn run_event_loop<B: Backend>(app: &mut App, terminal: &mut Terminal<B>) -> Resu
// Match the input mode, either you're in line input mode where you enter new
// values for registers or you're in the default navigation mode.
// TODO: refactor app.on_enter and app.on_* into this match
match app.input_mode {
InputMode::Edit => match event.code {
KeyCode::Char(c) => app.input.push(c),
......@@ -292,7 +291,7 @@ fn draw_tab_peek_and_poke_pes<B: Backend>(f: &mut Frame<B>, app: &mut App, chunk
} else {
"Register List (r: Refresh, Escape: back, j:\u{2193}, k:\u{2191}, Enter/l: set Register)"
};
let registers = app.get_argument_registers();
let registers = app.get_argument_registers((register_chunks[1].height - 2).into());
let registers: Vec<ListItem> = registers
.iter()
.map(|i| ListItem::new(vec![Spans::from(Span::raw(i))]))
......@@ -304,11 +303,11 @@ fn draw_tab_peek_and_poke_pes<B: Backend>(f: &mut Frame<B>, app: &mut App, chunk
))
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
.highlight_symbol("> ");
f.render_stateful_widget(registers, register_chunks[1], &mut app.register_list.state);
f.render_stateful_widget(registers, register_chunks[1], &mut app.register_list);
// Local Memory (also a stateful list for editing TODO?)
// TODO: query and draw only as many addresses as there is space in the frame
let local_memory = app.dump_current_pe_local_memory();
let local_memory = app.dump_current_pe_local_memory((horizontal_chunks[1].height - 2).into());
let local_memory: Vec<ListItem> = local_memory
.iter()
.map(|i| ListItem::new(vec![Spans::from(Span::raw(i))]))
......@@ -320,7 +319,7 @@ fn draw_tab_peek_and_poke_pes<B: Backend>(f: &mut Frame<B>, app: &mut App, chunk
f.render_stateful_widget(
local_memory,
horizontal_chunks[1],
&mut app.local_memory_list.state,
&mut app.local_memory_list,
);
// Draw an input line if in Edit Mode
......@@ -348,7 +347,7 @@ fn draw_tab_peek_and_poke_pes<B: Backend>(f: &mut Frame<B>, app: &mut App, chunk
draw_block_with_paragraph(
f,
"Messages",
app.messages.iter().rev().take((f.size().height - 2).into()).rev().cloned().collect::<Vec<String>>().join("\n"),
app.messages.iter().rev().take((vertical_chunks[2].height - 2).into()).rev().cloned().collect::<Vec<String>>().join("\n"),
vertical_chunks[2],
);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment