2023-02-08 01:17:46 +01:00
|
|
|
use std::fs;
|
|
|
|
use std::io;
|
|
|
|
use std::io::BufRead;
|
2023-02-15 18:01:50 +01:00
|
|
|
use std::io::BufReader;
|
|
|
|
use std::io::Lines;
|
2023-02-08 15:50:14 +01:00
|
|
|
use crate::Machine;
|
2023-02-08 01:17:46 +01:00
|
|
|
|
2023-02-08 14:34:09 +01:00
|
|
|
const MEM_SIZE : usize = 4096;
|
|
|
|
|
2023-02-08 01:17:46 +01:00
|
|
|
|
|
|
|
|
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-08 01:17:46 +01:00
|
|
|
|
2023-02-07 15:19:38 +01:00
|
|
|
fn from(section: &SectionFormat) -> Section {
|
2023-02-08 01:17:46 +01:00
|
|
|
|
2023-02-07 15:19:38 +01:00
|
|
|
let mut content: Vec<u8> = Vec::new();
|
2023-02-08 01:17:46 +01:00
|
|
|
let addr: usize = string_hex_to_usize(§ion.addr);
|
|
|
|
let len: usize = string_hex_to_usize(§ion.len);
|
2023-02-07 15:19:38 +01:00
|
|
|
|
2023-02-07 22:40:53 +01:00
|
|
|
let mut tmp_a: char = ' ';
|
|
|
|
let mut tmp_b: char = ' ';
|
|
|
|
|
|
|
|
for (i, c) in section.content.chars().enumerate(){
|
|
|
|
|
|
|
|
if i%2 == 0 {
|
|
|
|
tmp_a = c;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tmp_b = c;
|
|
|
|
content.push(two_hex_to_u8(tmp_a,tmp_b));
|
|
|
|
}
|
|
|
|
}
|
2023-02-07 15:19:38 +01:00
|
|
|
|
|
|
|
Section{addr:addr, len:len, content:content}
|
|
|
|
}
|
2023-02-08 12:37:21 +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-02-15 18:01:50 +01:00
|
|
|
pub struct Mem_Checker{
|
2023-02-07 22:50:55 +01:00
|
|
|
pc: usize,
|
|
|
|
sp: usize,
|
|
|
|
sections: Vec<Section>,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Mem_Checker{
|
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();
|
|
|
|
for (i,line) in lines.enumerate() {
|
|
|
|
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-02-08 01:17:46 +01:00
|
|
|
|
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
|
2023-02-15 18:01:50 +01:00
|
|
|
pub fn from(path: &String) -> Mem_Checker {
|
2023-02-08 12:37:21 +01:00
|
|
|
|
2023-03-01 16:12:46 +01:00
|
|
|
let file = fs::File::open(path).expect("Wrong filename");
|
2023-02-15 18:01:50 +01:00
|
|
|
|
|
|
|
let reader = io::BufReader::new(file);
|
|
|
|
let mut lines = reader.lines();
|
|
|
|
|
2023-02-08 01:17:46 +01:00
|
|
|
let mut pc: usize = 0;
|
|
|
|
let mut sp: usize = 0;
|
2023-02-15 18:01:50 +01:00
|
|
|
let vector = Mem_Checker::vect_from_lines(&mut lines, &mut pc, &mut sp);
|
|
|
|
|
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
|
2023-03-01 16:12:46 +01:00
|
|
|
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(¤t_line[0..next_word_index]);
|
|
|
|
tmp_len_str = String::from(¤t_line[next_word_index+1..]);
|
2023-02-08 01:17:46 +01:00
|
|
|
}
|
|
|
|
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-01 16:12:46 +01:00
|
|
|
content: current_line.clone().replace(" ", ""),
|
2023-02-15 18:01:50 +01:00
|
|
|
};
|
|
|
|
sections.push(Section::from(§ion_f));
|
2023-02-08 01:17:46 +01:00
|
|
|
}
|
2023-02-08 12:37:21 +01:00
|
|
|
|
2023-02-15 18:01:50 +01:00
|
|
|
}
|
|
|
|
|
2023-02-08 12:37:21 +01:00
|
|
|
Mem_Checker{pc:pc, sp:sp, sections:sections}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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-02-15 18:01:50 +01:00
|
|
|
pub fn print_Mem_Checker(m_c: &Mem_Checker){
|
2023-03-01 16:12:46 +01:00
|
|
|
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);
|
|
|
|
Section::print_Section(&s);
|
|
|
|
}
|
|
|
|
|
2023-02-08 01:17:46 +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-02-15 18:01:50 +01:00
|
|
|
pub fn fill_memory_from_Mem_Checker(m_c: &Mem_Checker, machine: &mut Machine){
|
2023-02-08 15:50:14 +01:00
|
|
|
|
|
|
|
machine.sp = m_c.sp;
|
2023-03-05 23:49:28 +01:00
|
|
|
machine.int_reg.set_reg(2, m_c.pc 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
|
|
|
|
*/
|
|
|
|
fn compare_print_m_c_machine(m_c: &Mem_Checker, machine: &mut Machine){
|
2023-02-08 14:34:09 +01:00
|
|
|
|
2023-02-08 15:50:14 +01:00
|
|
|
Mem_Checker::print_Mem_Checker(m_c);
|
|
|
|
|
|
|
|
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-07 17:32:59 +01:00
|
|
|
pub fn compare_machine_memory(m_c: &Mem_Checker, machine: &Machine) -> bool {
|
|
|
|
|
|
|
|
for section in m_c.sections.iter() {
|
|
|
|
for i in 0..section.len {
|
|
|
|
if machine.main_memory[section.addr + i] != section.content[i] {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-02-08 15:50:14 +01:00
|
|
|
|
2023-02-08 01:17:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-02-15 18:01:50 +01:00
|
|
|
fn string_hex_to_usize(s: &String) -> usize {
|
|
|
|
|
|
|
|
if s.len() == 0 {
|
|
|
|
return 0;
|
|
|
|
}
|
2023-02-08 01:17:46 +01:00
|
|
|
|
|
|
|
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-02-08 01:17:46 +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-02-08 01:17:46 +01:00
|
|
|
return ret_value;
|
2023-02-07 22:50:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-08 01:17:46 +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-01 15:11:35 +01:00
|
|
|
let ret : u8 = c.to_digit(10).unwrap() as u8;
|
2023-02-07 22:50:55 +01:00
|
|
|
return ret;
|
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-08 01:17:46 +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
|
|
|
|
}
|
|
|
|
|
2023-02-08 01:17:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Juste pour voir si via BufReader les \n sont présent, apres test il s'avère que non
|
|
|
|
* De toute facon on limitera d'une section la lecture par len
|
|
|
|
*/
|
|
|
|
fn test_show_sections_file(){
|
|
|
|
let file = fs::File::open("test_file_section.txt").expect("Wrong filename");
|
|
|
|
let reader = io::BufReader::new(file);
|
|
|
|
|
|
|
|
for line in reader.lines() {
|
|
|
|
//println!("Tailles de la ligne : {}",
|
|
|
|
let current = line.unwrap();
|
|
|
|
//println!("Taille de la ligne : {}", current.len()); // En effet pas de \n dans chaque line, parfait
|
|
|
|
println!("{}", ¤t);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-02-07 22:40:53 +01:00
|
|
|
#[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(){
|
|
|
|
let path = "osef".to_string();
|
|
|
|
let m_c = Mem_Checker::from(&path);
|
|
|
|
let mut machine = Machine::_init_machine();
|
|
|
|
|
|
|
|
Mem_Checker::fill_memory_from_Mem_Checker(&m_c, &mut machine);
|
|
|
|
|
|
|
|
print!("\n Comparing memory from loaded context\n\n");
|
|
|
|
|
|
|
|
Mem_Checker::compare_print_m_c_machine(&m_c, &mut machine);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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]
|
|
|
|
fn test_create_Mem_Checker(){
|
2023-02-08 12:37:21 +01:00
|
|
|
let path: String = "osef".to_string();
|
|
|
|
let m_c = Mem_Checker::from(&path);
|
|
|
|
Mem_Checker::print_Mem_Checker(&m_c);
|
|
|
|
}
|
|
|
|
|
2023-02-08 01:17:46 +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 tmp_fct_read_file(){
|
|
|
|
println!("Reading A file \n");
|
|
|
|
test_show_sections_file();
|
|
|
|
}
|
|
|
|
|
2023-02-07 22:40:53 +01:00
|
|
|
#[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(§ion_format);
|
|
|
|
let mut expected_vec: Vec<u8> = Vec::new();
|
|
|
|
expected_vec.push(0u8);
|
|
|
|
expected_vec.push(255u8);
|
|
|
|
expected_vec.push(10u8);
|
|
|
|
expected_vec.push(160u8);
|
|
|
|
expected_vec.push(165u8);
|
|
|
|
|
|
|
|
//println!("Vec from created section {:?}", §ion.content);
|
|
|
|
//println!("Expected vec {:?}", &expected_vec);
|
|
|
|
|
|
|
|
assert_eq!(section.content, expected_vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_mod(){
|
|
|
|
let cond = (0%2) == 0;
|
|
|
|
assert_eq!(true, cond);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_mod_2(){
|
|
|
|
let cond = (1%2) == 1;
|
|
|
|
assert_eq!(true, cond);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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
|
|
|
}
|