Skip to content

Commit

Permalink
Start using communicator to update memory
Browse files Browse the repository at this point in the history
  • Loading branch information
cayb0rg committed Feb 9, 2024
1 parent 33e0f18 commit 0c85693
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 118 deletions.
2 changes: 1 addition & 1 deletion src/agent/datapath_communicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl DatapathCommunicator {

/// Copies the contents of `data` to the emulator core's memory at `ptr`. Copies until either the end of `data` or
/// the end of the emulaot core's memory.
pub fn set_memory(&self, ptr: usize, data: Vec<u8>) {
pub fn set_memory(&self, ptr: u64, data: u32) {
self.send_message(Command::SetMemory(ptr, data));
}

Expand Down
2 changes: 1 addition & 1 deletion src/agent/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub enum Command {
Initialize(usize, Vec<u8>),
SetExecuteSpeed(u32),
SetRegister(String, u64),
SetMemory(usize, Vec<u8>),
SetMemory(u64, u32),
Execute,
ExecuteInstruction,
ExecuteStage,
Expand Down
147 changes: 86 additions & 61 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use monaco::{
MarkerSeverity,
}
};
use swim::ui::{footer::component::FooterTabState, swim_editor::component::EditorTabState};
use swim::{emulation_core::{architectures::AvailableDatapaths, mips::instruction::get_string_version}, ui::{footer::component::FooterTabState, hex_editor::component::{parse_hexdump, UpdatedLine}, swim_editor::component::EditorTabState}};
use swim::parser::parser_structs_and_enums::ProgramInfo;
use std::rc::Rc;
use swim::agent::datapath_communicator::DatapathCommunicator;
Expand Down Expand Up @@ -298,10 +298,13 @@ fn app(props: &AppProps) -> Html {

let trigger = use_force_update();
let communicator = props.communicator;
let datapath_state = datapath_state.clone();

use_callback(
move |_, _| {
let mut datapath = datapath.borrow_mut();
let datapath = datapath.borrow_mut();

let communicator = communicator.clone();
let text_model = text_model.clone();

let program_info_ref = Rc::clone(&program_info_ref);
Expand All @@ -311,78 +314,100 @@ fn app(props: &AppProps) -> Html {

let current_memory_text_model_value = memory_text_model.get_value();

match datapath.memory.parse_hexdump(&current_memory_text_model_value) {
match parse_hexdump(&current_memory_text_model_value) {
Ok(instructions) => {
// Memory parsed with no errors
match datapath.memory.store_hexdump(instructions) {
Ok(changed_lines) => {
// Memory updated successfully
let program_info = program_info_ref.borrow().clone();
let mut lines_beyond_counter = program_info.address_to_line_number.len();
let mut curr_value = text_model.get_value().to_owned();
let mut add_new_lines = false;
for line in changed_lines {
// Check if we're updating or appending instruction
if line.line_number < program_info.address_to_line_number.len() {
let updated_line = program_info.address_to_line_number[line.line_number] as f64 + 1.0;
let curr_model = text_model.as_ref();

// Get the current line's contents in the code editor
let line_to_replace = curr_model.get_line_content(updated_line);
// Create the range to replace
let mut start_line_column = 0.0;
let end_line_column = line_to_replace.len() as f64 + 2.0;
for (i, c) in line_to_replace.chars().enumerate() {
if c.is_alphanumeric() {
start_line_column = i as f64 + 1.0;
break;
}
}
let edit_range = monaco::sys::Range::new(updated_line, start_line_column, updated_line, end_line_column);
let before_cursor_state = monaco::sys::Selection::new(updated_line, start_line_column, updated_line,end_line_column);
// Create the edit operation using the range and new text
let edit_operations: monaco::sys::editor::IIdentifiedSingleEditOperation = Object::new().unchecked_into();
edit_operations.set_range(&edit_range);
edit_operations.set_text(Some(&line.text));
// Append it to JavaScript Array
let edit_operations_array = js_sys::Array::new();
edit_operations_array.push(&edit_operations);
let before_cursor_state_array = js_sys::Array::new();
before_cursor_state_array.push(&before_cursor_state);
// Do the edit!
curr_model.push_edit_operations(&before_cursor_state_array, &edit_operations_array, None);
} else if line.line_number == lines_beyond_counter {
// Append instruction
if !add_new_lines {
// If we've added new lines already,
// start adding new lines by getting a copy of the current text model to append to
add_new_lines = true;
curr_value = text_model.get_value();
}
curr_value.push_str("\n");
curr_value.push_str(&line.text);
lines_beyond_counter += 1;

let mut changed_lines: Vec<UpdatedLine> = vec![];
for (i, data) in instructions.iter().enumerate() {
let address = i as u64;
// change string version based on architecture
let string_version = match datapath_state.current_architecture {
AvailableDatapaths::MIPS => {
match get_string_version(*data) {
Ok(string) => string,
Err(string) => string,
}
},
AvailableDatapaths::RISCV => {
String::from("")
}
if add_new_lines {
text_model.set_value(&curr_value);
};

let curr_word = match datapath.memory.load_word(address * 4) {
Ok(data) => data,
Err(e) => {
debug!("{:?}", e);
0
}
};
if curr_word != *data {
debug!("address: {:?}", address * 4);
log::debug!("curr word: {}, new word: {}", curr_word, data);
changed_lines.push(UpdatedLine::new(string_version, i));

},
Err(err) => {
debug!("Error: {}", err)
communicator.set_memory(address * 4, *data);
}
};
()
}
// Memory updated successfully
let program_info = program_info_ref.borrow().clone();
let mut lines_beyond_counter = program_info.address_to_line_number.len();
let mut curr_value = text_model.get_value().to_owned();
let mut add_new_lines = false;
for line in changed_lines {
// Check if we're updating or appending instruction
if line.line_number < program_info.address_to_line_number.len() {
let updated_line = program_info.address_to_line_number[line.line_number] as f64 + 1.0;
let curr_model = text_model.as_ref();

// Get the current line's contents in the code editor
let line_to_replace = curr_model.get_line_content(updated_line);
// Create the range to replace
let mut start_line_column = 0.0;
let end_line_column = line_to_replace.len() as f64 + 2.0;
for (i, c) in line_to_replace.chars().enumerate() {
if c.is_alphanumeric() {
start_line_column = i as f64 + 1.0;
break;
}
}
let edit_range = monaco::sys::Range::new(updated_line, start_line_column, updated_line, end_line_column);
let before_cursor_state = monaco::sys::Selection::new(updated_line, start_line_column, updated_line,end_line_column);
// Create the edit operation using the range and new text
let edit_operations: monaco::sys::editor::IIdentifiedSingleEditOperation = Object::new().unchecked_into();
edit_operations.set_range(&edit_range);
edit_operations.set_text(Some(&line.text));
// Append it to JavaScript Array
let edit_operations_array = js_sys::Array::new();
edit_operations_array.push(&edit_operations);
let before_cursor_state_array = js_sys::Array::new();
before_cursor_state_array.push(&before_cursor_state);
// Do the edit!
curr_model.push_edit_operations(&before_cursor_state_array, &edit_operations_array, None);
} else if line.line_number == lines_beyond_counter {
// Append instruction
if !add_new_lines {
// If we've added new lines already,
// start adding new lines by getting a copy of the current text model to append to
add_new_lines = true;
curr_value = text_model.get_value();
}
curr_value.push_str("\n");
curr_value.push_str(&line.text);
lines_beyond_counter += 1;
}
}
if add_new_lines {
text_model.set_value(&curr_value);
}
},
Err(err) => {
debug!("Error updating memory: {}", err)
}
}

let hexdump = &datapath.memory.generate_formatted_hex();
let hexdump = datapath.memory.generate_formatted_hex();

memory_text_model.set_value(hexdump);
memory_text_model.set_value(&hexdump);

// Update the parsed info for text and data segment views
let (program_info, _) = parser(text_model.get_value());
Expand Down
2 changes: 1 addition & 1 deletion src/emulation_core/datapath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub trait Datapath {
/// Retrieve all memory as-is.
fn get_memory(&self) -> &Memory;

fn set_memory(&mut self, ptr: usize, data: Vec<u8>);
fn set_memory(&mut self, ptr: u64, data: u32);

/// Returns if the datapath is in a "halted" or "stopped" state. This may
/// be true in the case where an error had occurred previously.
Expand Down
4 changes: 2 additions & 2 deletions src/emulation_core/mips/datapath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ impl Datapath for MipsDatapath {
&self.memory
}

fn set_memory(&mut self, _ptr: usize, _data: Vec<u8>) {
todo!()
fn set_memory(&mut self, _ptr: u64, _data: u32) {
self.memory.store_word(_ptr, _data);
}

fn is_halted(&self) -> bool {
Expand Down
92 changes: 40 additions & 52 deletions src/emulation_core/mips/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ pub struct Memory {
pub memory: Vec<u8>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct UpdatedLine {
pub text: String,
pub line_number: usize
}

impl UpdatedLine {
pub fn new(text: String, line_number: usize) -> Self {
UpdatedLine {
text,
line_number
}
}
}
// #[derive(Clone, Debug, PartialEq)]
// pub struct UpdatedLine {
// pub text: String,
// pub line_number: usize
// }

// impl UpdatedLine {
// pub fn new(text: String, line_number: usize) -> Self {
// UpdatedLine {
// text,
// line_number
// }
// }
// }

impl Default for Memory {
fn default() -> Self {
Expand Down Expand Up @@ -128,44 +128,32 @@ impl Memory {
Ok(result)
}

pub fn parse_hexdump(&mut self, input: &str) -> Result<Vec<u32>, String> {
let mut words = Vec::new();
for line in input.lines() {
let parts: Vec<&str> = line.split('\t').collect();
for &part in &parts[2..6] {
let data = u32::from_str_radix(part, 16).map_err(|e| e.to_string())?;
words.push(data);
}
}
Ok(words)
}

// Returns instructions that were updated with their string versions and line numbers
pub fn store_hexdump(&mut self, instructions: Vec<u32>) -> Result<Vec<UpdatedLine>, String> {
let mut changed_lines: Vec<UpdatedLine> = vec![];
for (i, data) in instructions.iter().enumerate() {
let address = i as u64;
let line = match get_string_version(*data) {
Ok(string) => string,
Err(string) => string,
};
let curr_word = match self.load_word(address * 4) {
Ok(data) => data,
Err(e) => {
debug!("{:?}", e);
0
}
};
if curr_word != *data {
changed_lines.push(UpdatedLine::new(line, i));
self.store_word(address * 4, *data)?
}
}

Ok(changed_lines)
}

pub fn generate_formatted_hex(&mut self) -> String {
// // Returns instructions that were updated with their string versions and line numbers
// pub fn store_hexdump(&mut self, instructions: Vec<u32>) -> Result<Vec<UpdatedLine>, String> {
// let mut changed_lines: Vec<UpdatedLine> = vec![];
// for (i, data) in instructions.iter().enumerate() {
// let address = i as u64;
// let line = match get_string_version(*data) {
// Ok(string) => string,
// Err(string) => string,
// };
// let curr_word = match self.load_word(address * 4) {
// Ok(data) => data,
// Err(e) => {
// debug!("{:?}", e);
// 0
// }
// };
// if curr_word != *data {
// changed_lines.push(UpdatedLine::new(line, i));
// self.store_word(address * 4, *data)?
// }
// }

// Ok(changed_lines)
// }

pub fn generate_formatted_hex(&self) -> String {
let iterator = MemoryIter::new(&self);

let mut string: String = "".to_string();
Expand Down
26 changes: 26 additions & 0 deletions src/ui/hex_editor/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ pub struct HexEditorProps {
pub instruction_num: UseStateHandle<u64>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct UpdatedLine {
pub text: String,
pub line_number: usize
}
impl UpdatedLine {
pub fn new(text: String, line_number: usize) -> Self {
UpdatedLine {
text,
line_number
}
}
}

#[function_component(HexEditor)]
pub fn hex_editor(props: &HexEditorProps) -> Html {
let editor_link = CodeEditorLink::new();
Expand Down Expand Up @@ -204,3 +218,15 @@ fn get_options() -> IStandaloneEditorConstructionOptions {

options
}

pub fn parse_hexdump(input: &str) -> Result<Vec<u32>, String> {
let mut words = Vec::new();
for line in input.lines() {
let parts: Vec<&str> = line.split('\t').collect();
for &part in &parts[2..6] {
let data = u32::from_str_radix(part, 16).map_err(|e| e.to_string())?;
words.push(data);
}
}
Ok(words)
}
2 changes: 2 additions & 0 deletions static/assembly_examples/data.asm
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.text
addi $t0, $zero, 300
addi $t1, $zero, 340
addi $t2, $zero, 380
syscall
.data
a_secret: .ascii "hi"
Expand Down

0 comments on commit 0c85693

Please sign in to comment.