mod common; mod analysis; use analysis::*; use common::*; use structopt::StructOpt; use std::path::PathBuf; use std::fs::File; use std::io::prelude::*; #[derive(Debug, StructOpt)] #[structopt(name = "srp analysis", about = "Example: cargo run -- -e cargo run -- -e -o analysis_1.json cargo run -- -e -i tasks_1.json cargo run -- -e -i tasks_2.json -o analysis_2.json")] struct Opt { #[structopt(short, long)] exact: bool, #[structopt(short, long)] output_analysis: Option<PathBuf>, #[structopt(short, long)] input_tasks: Option<PathBuf>, } fn main() -> std::io::Result<()> { let opt = Opt::from_args(); // println!("{:?}", opt); /* SAVES DOWN THE TASKS SET 1 and 2 to json let tasks_1 = &taskset_1(); let tasks_2 = &taskset_2(); let tasks_1_json: String = serde_json::to_string(&tasks_1).unwrap(); let tasks_2_json: String = serde_json::to_string(&tasks_2).unwrap(); write_file_string(tasks_1_json, "tasks_1.json".to_string()); write_file_string(tasks_2_json, "tasks_2.json".to_string()); */ // Default task set let mut tasks: Tasks = taskset_1(); // Tasks input, if no input a default task input taskset_1 is used match opt.input_tasks { Some(file) => { let mut file = File::open(file)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; tasks = serde_json::from_str(&contents).unwrap(); println!("\nTask set is loaded from {:?}", file); } None => println!("\nA default task set is loaded!") }; // Print out tasks println!("---------------------------- Tasks ----------------------------\n"); for t in &tasks { println!("Task {} | Prio {} | Deadline {} | Inter_arrival {} |", t.id, t.prio, t.deadline, t.inter_arrival); println!("{:?} \n", t.trace); } println!("----------------------------------------------------------------\n"); // let (ip, tr) = pre_analysis(&tasks); // println!("{:?}", ip); // println!("{:?}", tr); // Calculate and print load factor for the CPU let load_f = load_factor(&tasks); println!("\nCPU load: {}\n", load_f); // Prints out if exact or apporoximated preemptions calculation if opt.exact { println!("Exact preemption calculation: YES\n"); } else { println!("Exact preemption calculation: NO\n"); } // Makes the analysis let analysis = analysis(&tasks, opt.exact); // Prints out the results of the analysis println!("---------------------------- Results of the analysis ----------------------------\n"); for a in &analysis { println!("Task {:?} | Response time {} | WCET {} | Blocking time {} | Preemption time {} |\n", a.task.id, a.response_time, a.wcet, a.blocking_time, a.preemption_time); } println!("---------------------------------------------------------------------------------\n"); // Checks if the analysis is schedulable and prints out the results let schedule_check = schedulable_check(&analysis); if schedule_check && !(load_f > 1.0) { println!("The taskset is schedulable: YES\n") } else { println!("The taskset is schedulable: NO\n"); println!("Reasons:"); if load_f > 1.0 { println!("- The CPU is overloaded!\n"); } if schedule_check { println!("- Deadline miss!\n") } } // Output analysis saved as json? let analysis_json: String = serde_json::to_string(&analysis).unwrap(); match opt.output_analysis { Some(file) => { match write_file(analysis_json, file) { Ok(()) => (), Err(err) => panic!(err), } println!("The Analysis is saved: YES\n"); } None => println!("The Analysis is saved: NO\n"), }; Ok(()) } fn write_file_string(contents: String, file_name: String) -> std::io::Result<()> { let mut file = File::create(file_name)?; file.write_all(contents.as_bytes())?; Ok(()) } fn write_file(contents: String, file_name: PathBuf) -> std::io::Result<()> { let mut file = File::create(file_name)?; file.write_all(contents.as_bytes())?; Ok(()) } fn taskset_1() -> Tasks { let t1 = Task { id: "T1".to_string(), prio: 1, deadline: 100, inter_arrival: 100, trace: Trace { id: "T1".to_string(), start: 0, end: 10, inner: vec![], }, }; let t2 = Task { id: "T2".to_string(), prio: 2, deadline: 200, inter_arrival: 200, trace: Trace { id: "T2".to_string(), start: 0, end: 30, inner: vec![ Trace { id: "R1".to_string(), start: 10, end: 20, inner: vec![Trace { id: "R2".to_string(), start: 12, end: 16, inner: vec![], }], }, Trace { id: "R1".to_string(), start: 22, end: 28, inner: vec![], }, ], }, }; let t3 = Task { id: "T3".to_string(), prio: 3, deadline: 50, inter_arrival: 50, trace: Trace { id: "T3".to_string(), start: 0, end: 30, inner: vec![Trace { id: "R2".to_string(), start: 10, end: 20, inner: vec![], }], }, }; let tasks: Tasks = vec![t1, t2, t3]; return tasks; } fn taskset_2() -> Tasks { let t1 = Task { id: "T1".to_string(), prio: 1, deadline: 200, inter_arrival: 200, trace: Trace { id: "T1".to_string(), start: 0, end: 15, inner: vec![ Trace { id: "R3".to_string(), start: 2, end: 8, inner: vec![], }, Trace { id: "R1".to_string(), start: 9, end: 13, inner: vec![], }, ], }, }; let t2 = Task { id: "T2".to_string(), prio: 2, deadline: 200, inter_arrival: 200, trace: Trace { id: "T2".to_string(), start: 0, end: 37, inner: vec![ Trace { id: "R1".to_string(), start: 10, end: 18, inner: vec![Trace { id: "R2".to_string(), start: 12, end: 16, inner: vec![], }], }, Trace { id: "R1".to_string(), start: 22, end: 25, inner: vec![], }, ], }, }; let t3 = Task { id: "T3".to_string(), prio: 3, deadline: 100, inter_arrival: 100, trace: Trace { id: "T3".to_string(), start: 0, end: 20, inner: vec![Trace { id: "R3".to_string(), start: 8, end: 20, inner: vec![], }], }, }; let tasks: Tasks = vec![t1, t2, t3]; return tasks; }