burritos/src/simulator/mem_cmp.rs

367 lines
9.2 KiB
Rust
Raw Normal View History

use std::{fs, io::{BufRead, BufReader, Lines, Error}};
2023-02-08 15:50:14 +01:00
use crate::Machine;
2023-02-08 14:34:09 +01:00
const MEM_SIZE : usize = 4096;
2023-02-08 15:51:55 +01:00
/* TRUCS MANQUANTS
2023-02-07 15:19:38 +01:00
* Verifier qu'il y a un nombre pair de caractere hexa dans la ligne correspondante d'une section du fichier source
* Sinon on ne peut pas automatiquement remplir chaque octect car 2 hexa = 1 octet
*/
/* FORMAT FICHIER.TXT Représentant la mémoire apres éxecution d'un prog
* PC
* SP
* Section_1
* Section_2
* ...
* ...
* Section_n
*/
/* Chaque section se divise en 3 parties, sur 2 lignes de texte
* addr ESPACE len
* content
*/
//content est une suite hexadécimale
//Section dans le fichier, champ String car informations proviennent d'un fichier txt
2023-02-15 18:01:50 +01:00
pub struct SectionFormat{
2023-02-07 15:19:38 +01:00
addr: String,
len: String,
content: String,
}
//Section dans le programme
2023-02-15 18:01:50 +01:00
pub struct Section{
2023-02-07 15:19:38 +01:00
addr: usize, // adresse dans la mémoire
len: usize, // nombre d'octets de la donnée à addr
content: Vec<u8>, // la donnée en question
}
/*
* Voir si instanciation d'une structure deplace les valeurs "locales" à la méthode from, je sais plus ....
*/
impl Section{
2023-02-07 15:19:38 +01:00
fn from(section: &SectionFormat) -> Section {
2023-02-07 15:19:38 +01:00
let mut content: Vec<u8> = Vec::new();
let addr: usize = string_hex_to_usize(&section.addr);
let len: usize = string_hex_to_usize(&section.len);
2023-02-07 15:19:38 +01:00
let mut tmp_a: char = ' ';
for (i, c) in section.content.chars().enumerate(){
if i%2 == 0 {
tmp_a = c;
}
else {
2023-03-10 11:03:54 +01:00
content.push(two_hex_to_u8(tmp_a,c));
}
}
2023-02-07 15:19:38 +01:00
2023-03-08 13:04:03 +01:00
Section{addr, len, content}
2023-02-07 15:19:38 +01:00
}
2023-02-08 12:37:21 +01:00
2023-03-08 13:04:03 +01:00
fn print_section(s: &Section){
2023-03-03 12:21:37 +01:00
println!("ADDR :: {:x}", s.addr);
println!("LEN :: {:x}", s.len);
2023-02-08 12:37:21 +01:00
println!("CONTENT :: {:?}", s.content);
}
2023-02-07 15:19:38 +01:00
}
2023-02-07 22:50:55 +01:00
/*
* Representation de l'etat de la mémoire (apres execution.... a confirmer), sous forme de sections
*/
2023-03-08 13:04:03 +01:00
pub struct MemChecker{
2023-02-07 22:50:55 +01:00
pc: usize,
sp: usize,
sections: Vec<Section>,
}
2023-03-08 13:04:03 +01:00
impl MemChecker{
2023-02-08 12:37:21 +01:00
2023-03-08 11:15:13 +01:00
///Translate lines of a file in e Vector of String
///We need this method to parse the memory we received
///
/// ### Parameters
///
/// - **Lines** The file to parse
///
/// ### Return
/// - A vector of String where each line of the file os an element of the vector
2023-02-15 18:01:50 +01:00
fn vect_from_lines(lines: &mut Lines<BufReader<fs::File>>, pc: &mut usize, sp: &mut usize) -> Vec<String>{
let mut vector = Vec::new();
2023-03-08 13:04:03 +01:00
for (_,line) in lines.enumerate() {
2023-02-15 18:01:50 +01:00
vector.push(line.unwrap());
}
let size = vector.len();
*pc = string_hex_to_usize(vector.get(size - 2).expect("0"));
*sp = string_hex_to_usize(vector.get(size - 1).expect("0"));
vector
}
2023-03-08 11:15:13 +01:00
/// Fill a mem checker from a file (here the mock memory)
/// Extract the values of pc, sp and sections
///
/// ### Parameter
/// -**path** addr to the file
///
/// ### Return
/// Mem-checker filled
pub fn from(path: &str) -> Result<MemChecker, Error> {
2023-02-08 12:37:21 +01:00
let file = fs::File::open(path)?;
2023-02-15 18:01:50 +01:00
2023-03-08 13:04:03 +01:00
let reader = BufReader::new(file);
2023-02-15 18:01:50 +01:00
let mut lines = reader.lines();
let mut pc: usize = 0;
let mut sp: usize = 0;
2023-03-08 13:04:03 +01:00
let vector = MemChecker::vect_from_lines(&mut lines, &mut pc, &mut sp);
2023-02-15 18:01:50 +01:00
2023-02-08 12:37:21 +01:00
let mut sections: Vec<Section> = Vec::new();
let mut tmp_addr_str: String = String::new();
let mut tmp_len_str: String = String::new();
2023-02-15 18:01:50 +01:00
let default = String::new();
for i in 0..vector.len()-2 {
let current_line = vector.get(i).unwrap_or(&default);
//Lecture des sections
if i % 2 == 0 {
2023-02-15 18:01:50 +01:00
//lecture ligne ADDR LEN
let next_word_index = current_line.find(' ').unwrap();
tmp_addr_str = String::from(&current_line[0..next_word_index]);
tmp_len_str = String::from(&current_line[next_word_index+1..]);
}
else {
2023-02-15 18:01:50 +01:00
//lecture ligne CONTENT
let section_f = SectionFormat{
addr: tmp_addr_str.clone(),
len: tmp_len_str.clone(),
2023-03-10 11:03:54 +01:00
content: current_line.clone().replace(' ', ""),
2023-02-15 18:01:50 +01:00
};
sections.push(Section::from(&section_f));
}
2023-02-08 12:37:21 +01:00
2023-02-15 18:01:50 +01:00
}
Ok(MemChecker{pc, sp, sections})
2023-02-08 12:37:21 +01:00
}
2023-03-08 11:15:13 +01:00
/// Print the content of a Mem_Checker
///
/// ### Parameter
///
/// - **m_c** Contains the data we want to print
2023-03-08 13:04:03 +01:00
pub fn print_mem_checker(m_c: &MemChecker){
println!("PC :: {:x}", m_c.pc);
println!("SP :: {:x}", m_c.sp);
2023-02-08 12:37:21 +01:00
for(i,s) in m_c.sections.iter().enumerate() {
println!("\nSection {}\n", i);
2023-03-10 11:03:54 +01:00
Section::print_section(s);
2023-02-08 12:37:21 +01:00
}
}
2023-02-08 14:34:09 +01:00
2023-03-08 11:15:13 +01:00
/// Fill a machine's memory from a Mem Chacker
///
/// ### Parameters
///
/// - **m_c** contains the data
/// - **machine** contains the memry to fill
2023-03-08 13:04:03 +01:00
pub fn fill_memory_from_mem_checker(m_c: &MemChecker, machine: &mut Machine){
2023-02-08 15:50:14 +01:00
machine.sp = m_c.sp;
2023-03-08 17:58:38 +01:00
machine.int_reg.set_reg(2, m_c.sp as i64);
2023-02-08 15:50:14 +01:00
machine.pc = m_c.pc as u64;
2023-02-08 14:34:09 +01:00
2023-02-08 15:50:14 +01:00
for section in m_c.sections.iter() {
for (i,b) in section.content.iter().enumerate() {
machine.main_memory[section.addr + i] = *b;
}
}
}
2023-02-08 14:34:09 +01:00
2023-02-08 15:50:14 +01:00
/*
* FOR DEBUG
*/
2023-03-08 13:04:03 +01:00
fn compare_print_m_c_machine(m_c: &MemChecker, machine: &mut Machine){
2023-02-08 14:34:09 +01:00
2023-03-08 13:04:03 +01:00
MemChecker::print_mem_checker(m_c);
2023-02-08 15:50:14 +01:00
for section in m_c.sections.iter() {
print!("\n\n");
2023-02-08 14:34:09 +01:00
2023-02-08 15:50:14 +01:00
println!("Content addr : {}", section.addr);
println!("Content len (number of bytes) : {}", section.len);
for i in 0..section.len {
println!("mem[{}] = {}", section.addr + i, machine.main_memory[section.addr + i]);
}
}
2023-02-08 14:34:09 +01:00
}
2023-02-08 15:50:14 +01:00
2023-03-08 13:34:12 +01:00
/// Compare sections of a memChecker and a machine memory
///
/// ### Parameters
///
/// - **m_c** contains section of the memory checker
/// - **machine** contains the main memory
2023-03-08 13:04:03 +01:00
pub fn compare_machine_memory(m_c: &MemChecker, machine: &Machine) -> bool {
2023-03-08 13:34:12 +01:00
m_c.sections.iter().map(|section| {
2023-03-08 17:58:38 +01:00
(0..section.len).into_iter().all(|i| machine.main_memory[section.addr + i] == section.content[i])
}).all(|e| e)
2023-03-07 17:32:59 +01:00
}
}
2023-02-15 18:01:50 +01:00
fn string_hex_to_usize(s: &String) -> usize {
2023-03-10 10:38:58 +01:00
if s.is_empty() {
2023-02-15 18:01:50 +01:00
return 0;
}
let max_pow = (s.len()-1) as u32;
let mut ret_value: usize = 0;
let base: usize = 16;
for (i,c )in s.chars().enumerate(){
2023-02-08 12:37:21 +01:00
//println!("Current char :: {} :: Current pow :: {} ::", c, max_pow - (i as u32));
2023-03-08 13:04:03 +01:00
let tmp: usize = one_hex_to_dec(c) as usize;
ret_value += base.pow(max_pow - (i as u32))*tmp;
}
2023-02-07 22:50:55 +01:00
2023-03-10 10:38:58 +01:00
ret_value
2023-02-07 22:50:55 +01:00
}
2023-02-07 22:50:55 +01:00
/*
* c doit etre un caractère hexadécimale
*/
fn one_hex_to_dec(c: char) -> u8 {
match c {
'A' | 'a' => 10,
'B' | 'b' => 11,
'C' | 'c' => 12,
'D' | 'd' => 13,
'E' | 'e' => 14,
'F' | 'f' => 15,
_ => {
2023-03-10 10:38:58 +01:00
c.to_digit(10).unwrap() as u8
2023-03-01 15:11:35 +01:00
},
2023-02-07 22:50:55 +01:00
}
2023-03-01 15:11:35 +01:00
}
2023-02-07 22:50:55 +01:00
2023-02-07 22:50:55 +01:00
fn two_hex_to_u8(c1: char, c2: char) -> u8 {
let a = one_hex_to_dec(c1);
let b = one_hex_to_dec(c2);
16*a + b
}
#[cfg(test)]
mod tests {
use super::*;
2023-02-08 12:37:21 +01:00
#[test]
2023-02-08 15:50:14 +01:00
fn test_fill_memory(){
2023-03-13 23:55:35 +01:00
let m_c = MemChecker::from("test/machine/memory.txt").unwrap();
let mut machine = Machine::init_machine();
2023-03-08 13:04:03 +01:00
MemChecker::fill_memory_from_mem_checker(&m_c, &mut machine);
MemChecker::compare_print_m_c_machine(&m_c, &mut machine);
2023-02-08 15:50:14 +01:00
}
#[test]
fn test_enum_start_at_zero(){
let v = vec![1,2,3];
for (i,val) in v.iter().enumerate() {
println!("i = {} :: v[i] = {}", i, val);
}
}
#[test]
2023-03-08 13:04:03 +01:00
fn test_create_mem_checker(){
2023-03-13 23:55:35 +01:00
let m_c = MemChecker::from("test/machine/memory.txt").unwrap();
2023-03-08 13:04:03 +01:00
MemChecker::print_mem_checker(&m_c);
2023-02-08 12:37:21 +01:00
}
#[test]
fn test_string_hex_to_usize(){
let s = String::from("AE1F20");
//println!("taille de string : {}", s.len());
let expected: usize = 11411232;
let result = string_hex_to_usize(&s);
assert_eq!(expected,result);
}
#[test]
fn test_create_section_content(){
let section_format = SectionFormat{
addr: "0".to_string(),
len: "0".to_string(),
content: "00FF0AA0A5".to_string(),
};
let section = Section::from(&section_format);
2023-03-10 10:38:58 +01:00
let expected_vec: Vec<u8> = vec![0u8, 255u8, 10u8, 160u8, 165u8];
//println!("Vec from created section {:?}", &section.content);
//println!("Expected vec {:?}", &expected_vec);
assert_eq!(section.content, expected_vec);
}
#[test]
fn test_hex_1(){
let b = two_hex_to_u8('0', '0');
assert_eq!(0u8, b);
}
#[test]
fn test_hex_2(){
let b = two_hex_to_u8('F', 'F');
assert_eq!(255u8, b);
}
#[test]
fn test_hex_3(){
let b = two_hex_to_u8('0', 'A');
assert_eq!(10u8, b);
}
#[test]
fn test_hex_4(){
let b = two_hex_to_u8('A', '0');
assert_eq!(160u8, b);
}
#[test]
fn test_hex_5(){
let b = two_hex_to_u8('A', '5');
assert_eq!(165u8, b);
}
2023-02-08 15:51:55 +01:00
}