From 63f1e01286ec77d1fb956794579348f488421ce5 Mon Sep 17 00:00:00 2001 From: rubenasplund <ruben.asplund@hotmail.com> Date: Thu, 14 Jan 2021 19:31:39 +0100 Subject: [PATCH] Added command-line interface --- srp_analysis/Cargo.toml | 3 + srp_analysis/src/analysis.rs | 2 +- srp_analysis/src/common.rs | 8 +-- srp_analysis/src/main.rs | 125 ++++++++++++++++++++++++++++++++--- 4 files changed, 125 insertions(+), 13 deletions(-) diff --git a/srp_analysis/Cargo.toml b/srp_analysis/Cargo.toml index cb6789f..ab13076 100644 --- a/srp_analysis/Cargo.toml +++ b/srp_analysis/Cargo.toml @@ -7,3 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +serde = { version = "1.0", features = ["derive"] } +structopt = { version = "0.3"} +serde_json = "1.0" diff --git a/srp_analysis/src/analysis.rs b/srp_analysis/src/analysis.rs index e91754a..9c1a634 100644 --- a/srp_analysis/src/analysis.rs +++ b/srp_analysis/src/analysis.rs @@ -18,7 +18,7 @@ pub fn analysis(tasks: &Tasks, exact: bool) -> Vec<TaskData>{ // Checks if the analysis is schedulable // returns false if it is not schedulable -pub fn schedulable_check(analysis: Vec<TaskData>) -> bool{ +pub fn schedulable_check(analysis: &Vec<TaskData>) -> bool{ // check if response time is less then deadline for a in analysis { if a.task.deadline < a.response_time { diff --git a/srp_analysis/src/common.rs b/srp_analysis/src/common.rs index 40db8b7..7be93ce 100644 --- a/srp_analysis/src/common.rs +++ b/srp_analysis/src/common.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, HashSet}; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct TaskData { pub task: Task, pub response_time: u32, @@ -9,7 +10,7 @@ pub struct TaskData { pub preemption_time: u32 } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Task { pub id: String, pub prio: u8, @@ -18,8 +19,7 @@ pub struct Task { pub trace: Trace, } -//#[derive(Debug, Clone)] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Trace { pub id: String, pub start: u32, diff --git a/srp_analysis/src/main.rs b/srp_analysis/src/main.rs index 302baeb..fbbf6f6 100644 --- a/srp_analysis/src/main.rs +++ b/srp_analysis/src/main.rs @@ -2,29 +2,138 @@ mod common; mod analysis; use analysis::*; use common::*; +use structopt::StructOpt; +use std::path::PathBuf; -fn main() { +use std::fs::File; +use std::io::prelude::*; - let tasks = taskset_2(); +#[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); - println!("CPU load {}", load_factor(&tasks)); - let analysis = analysis(&tasks, true); + // 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!("{:?} Response time {} | WCET {} | Blocking time {} | Preemption time {}", + println!("Task {:?} | Response time {} | WCET {} | Blocking time {} | Preemption time {} |\n", a.task.id, a.response_time, a.wcet, a.blocking_time, a.preemption_time); } - if schedulable_check(analysis) { - println!("OK! The taskset is schedulable!") + 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!("ERROR! The taskset is NOT schedulable!") + 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(), -- GitLab