diff --git a/Exercises/Response-Time Analysis/.vscode/launch.json b/Exercises/Response-Time Analysis/.vscode/launch.json index 0f57c54..38b9d19 100644 --- a/Exercises/Response-Time Analysis/.vscode/launch.json +++ b/Exercises/Response-Time Analysis/.vscode/launch.json @@ -22,4 +22,4 @@ "preLaunchTask": "build" } ] -} +} \ No newline at end of file diff --git a/Exercises/Response-Time Analysis/build/real_time_analysis b/Exercises/Response-Time Analysis/build/real_time_analysis new file mode 100644 index 0000000..9013645 Binary files /dev/null and b/Exercises/Response-Time Analysis/build/real_time_analysis differ diff --git a/Exercises/Response-Time Analysis/src/real_time_analysis copy.py b/Exercises/Response-Time Analysis/src/real_time_analysis copy.py new file mode 100644 index 0000000..8bac94c --- /dev/null +++ b/Exercises/Response-Time Analysis/src/real_time_analysis copy.py @@ -0,0 +1,88 @@ +import pandas as pd +import math + + +def read_csv(file): + """ + Read tasks from a CSV file and convert to a list of task dictionaries. + """ + df = pd.read_csv(file) + req_columns = ['Task', 'BCET', 'WCET', 'Period', 'Deadline', 'Priority'] + + if not all(col in df.columns for col in req_columns): + raise ValueError(f"Missing required column(s): {req_columns}") + + tasks = [] + for _, row in df.iterrows(): + task = { + "name": row['Task'], + "bcet": row['BCET'], + "wcet": row['WCET'], + "period": row['Period'], + "deadline": row['Deadline'], + "priority": row['Priority'] + } + tasks.append(task) + + return tasks + + +def response_time_analysis(tasks): + """ + Perform Response-Time Analysis. + """ + # Sort tasks by priority (lower number means higher priority) + sorted_tasks = sorted(tasks, key=lambda x: x['priority']) + + results = [] + + for i, task in enumerate(sorted_tasks): + R = task['wcet'] # Initial response time + last_R = -1 + schedulable = True + + while R != last_R: + last_R = R + interference = 0 + + # Calculate interference from higher-priority tasks + for j in range(i): + higher_task = sorted_tasks[j] + interference += math.ceil(R / higher_task['period']) * higher_task['wcet'] + + R = task['wcet'] + interference + + # Check if the task is schedulable + if R > task['deadline']: + schedulable = False + break + + # Store results + result = { + 'Task': task['name'], + 'WCRT': R, + 'Deadline': task['deadline'], + 'Status': 'Schedulable' if schedulable else 'Not Schedulable' + } + results.append(result) + + return results + + +def run_rta(path_file): + """ + Main function to read tasks and perform response time analysis. + """ + # Read tasks from CSV + tasks = read_csv(path_file) + + # Perform response time analysis + analysis_results = response_time_analysis(tasks) + + # Print results + for result in analysis_results: + if result['Status'] == 'Schedulable': + print(f"Task {result['Task']} is schedulable with WCRT = {result['WCRT']:.1f}") + else: + print(f"Task {result['Task']} is not schedulable with WCRT.") + return analysis_results diff --git a/Exercises/Response-Time Analysis/src/real_time_analysis.cpp b/Exercises/Response-Time Analysis/src/real_time_analysis.cpp new file mode 100644 index 0000000..fbb2d2a --- /dev/null +++ b/Exercises/Response-Time Analysis/src/real_time_analysis.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +struct Task { + string id; + int BCET; + int WCET; + int period; + int deadline; + int priority; // Lower number => higher priority for RMS, if you wish +}; + + +void readTasksCSV(const string& filename, vector& tasks) +{ + ifstream file(filename); + if (!file.is_open()) { + cerr << "Error: Could not open file " << filename << endl; + return; + } + + string line; + getline(file, line); // Skip header + + while (getline(file, line)) + { + stringstream ss(line); + Task task; + string token; + + getline(ss, token, ','); // Task ID + task.id = token; + getline(ss, token, ','); // WCET + task.WCET = stoi(token); + getline(ss, token, ','); // BCET + task.BCET = stoi(token); + getline(ss, token, ','); // Period + task.period = stoi(token); + getline(ss, token, ','); // Deadline + task.deadline = stoi(token); + getline(ss, token, ','); // Priority + task.priority = stoi(token); + + tasks.push_back(task); + } + file.close(); +} + +void RTA_test(vector& tasks) +{ + // Sort tasks by priority (lower number means higher priority) + sort(tasks.begin(), tasks.end(), [](const Task& a, const Task& b) { + return a.priority < b.priority; // Ensure lower priority number = higher priority + }); + + for (size_t task = 0; task < tasks.size(); task++) + { + int R = tasks[task].WCET; + int last_R = -1; + bool schedulable = true; + int I = 0; // Reset interference for each iteration + + while (R != last_R) + { + last_R = R; + + // Compute interference from higher-priority tasks + for (size_t j = 0; j < task; j++) + { + I += ceil((double)R / tasks[j].period) * tasks[j].WCET; + } + + R = I + tasks[task].WCET; + + if (R > tasks[task].deadline) + { + cout << "Task " << tasks[task].id << " is not schedulable." << endl; + schedulable = false; + break; + } + } + + if (schedulable) + { + cout << "Task " << tasks[task].id << " is schedulable with WCRT = " << R << endl; + } + } +} + +int main(int argc, char* argv[]) +{ + if (argc != 2) { + cerr << "Usage: " << argv[0] << " " << endl; + return 1; + } + + string filename = argv[1]; + vector tasks; + readTasksCSV(filename, tasks); + + RTA_test(tasks); + + return 0; +} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/.vscode/c_cpp_properties.json b/Exercises/Very Simple Simulator/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..8f6a31f --- /dev/null +++ b/Exercises/Very Simple Simulator/.vscode/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [], + "compilerPath": "/usr/bin/g++", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/.vscode/launch.json b/Exercises/Very Simple Simulator/.vscode/launch.json new file mode 100644 index 0000000..204b3a0 --- /dev/null +++ b/Exercises/Very Simple Simulator/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug C++", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/very_simple_simulator", + "args": ["${workspaceFolder}/exercise-TC2.csv"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "build" + } + ] +} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/.vscode/settings.json b/Exercises/Very Simple Simulator/.vscode/settings.json new file mode 100644 index 0000000..0cba2e6 --- /dev/null +++ b/Exercises/Very Simple Simulator/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "iostream": "cpp" + } +} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/.vscode/tasks.json b/Exercises/Very Simple Simulator/.vscode/tasks.json new file mode 100644 index 0000000..11023fd --- /dev/null +++ b/Exercises/Very Simple Simulator/.vscode/tasks.json @@ -0,0 +1,43 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "g++", + "args": [ + "-g", + "${workspaceFolder}/src/very_simple_simulator.cpp", + "-o", + "${workspaceFolder}/build/very_simple_simulator" + ], + "group": "build", + "problemMatcher": [ + "$gcc" + ] + }, + { + "type": "cppbuild", + "label": "C/C++: g++ build active file", + "command": "/usr/bin/g++", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ] +} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/02225_Exercise.pdf b/Exercises/Very Simple Simulator/02225_Exercise.pdf new file mode 100644 index 0000000..f49c082 Binary files /dev/null and b/Exercises/Very Simple Simulator/02225_Exercise.pdf differ diff --git a/Exercises/Very Simple Simulator/README.txt b/Exercises/Very Simple Simulator/README.txt new file mode 100644 index 0000000..f028b24 --- /dev/null +++ b/Exercises/Very Simple Simulator/README.txt @@ -0,0 +1,14 @@ +README.txt + +The files in the Exerercise/Content tab are test cases are provided as a starting point for the 02225 DRTS exercise. + +They are in CSV (Comma-Separated Values) format and contain the model parameters for periodic tasks: + + - Task: Task name + - BCET: Best-case execution time + - WCET: Worst-case execution time + - Period: Task period + - Deadline: Task deadline (equal to the period) + - Priority: Task priority (assigned by Rate Monotonic scheduling, with lower period yielding higher priority) + +These examples illustrate one possible format. Students may use a different format and create additional test cases. diff --git a/Exercises/Very Simple Simulator/build/very_simple_simulator b/Exercises/Very Simple Simulator/build/very_simple_simulator new file mode 100644 index 0000000..e41076a Binary files /dev/null and b/Exercises/Very Simple Simulator/build/very_simple_simulator differ diff --git a/Exercises/Very Simple Simulator/exercise-TC1.csv b/Exercises/Very Simple Simulator/exercise-TC1.csv new file mode 100644 index 0000000..89e3ebe --- /dev/null +++ b/Exercises/Very Simple Simulator/exercise-TC1.csv @@ -0,0 +1,8 @@ +Task,BCET,WCET,Period,Deadline,Priority +T1,0,1,6,6,1 +T2,3,4,60,60,7 +T3,1,1,10,10,2 +T4,1,2,12,12,3 +T5,1,2,15,15,4 +T6,1,3,20,20,5 +T7,1,4,30,30,6 \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/exercise-TC2.csv b/Exercises/Very Simple Simulator/exercise-TC2.csv new file mode 100644 index 0000000..2427ced --- /dev/null +++ b/Exercises/Very Simple Simulator/exercise-TC2.csv @@ -0,0 +1,12 @@ +Task,BCET,WCET,Period,Deadline,Priority +T1,0,1,15,15,1 +T2,1,2,20,20,2 +T3,2,3,25,25,3 +T4,2,4,30,30,4 +T5,3,5,50,50,5 +T6,3,5,60,60,6 +T7,4,6,75,75,7 +T8,5,9,100,100,8 +T9,3,12,120,120,9 +T10,5,11,150,150,10 +T11,6,15,300,300,11 \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/exercise-TC3.csv b/Exercises/Very Simple Simulator/exercise-TC3.csv new file mode 100644 index 0000000..8cd09de --- /dev/null +++ b/Exercises/Very Simple Simulator/exercise-TC3.csv @@ -0,0 +1,10 @@ +Task,BCET,WCET,Period,Deadline,Priority +T1,1,3,40,40,1 +T2,2,7,80,80,2 +T3,1,13,100,100,3 +T4,3,18,160,160,4 +T5,1,22,200,200,5 +T6,5,27,300,300,6 +T7,8,29,320,320,7 +T8,10,34,400,400,8 +T9,22,35,480,480,9 \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/src/very_simple_simulator.cpp b/Exercises/Very Simple Simulator/src/very_simple_simulator.cpp new file mode 100644 index 0000000..399bd1e --- /dev/null +++ b/Exercises/Very Simple Simulator/src/very_simple_simulator.cpp @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include + +using namespace std; + +// Define the Task structure +struct Task { + string id; + int BCET; + int WCET; + int period; + int deadline; + int priority; // Lower number => higher priority for RMS, if you wish +}; + +// Define the Job structure +struct Job { + Task task; + int releaseTime; + int remainingTime; + int responseTime; +}; + +// Function to read tasks from a CSV file +void readTasksCSV(const string& filename, vector& tasks) +{ + ifstream file(filename); + if (!file.is_open()) + { + cerr << "Error: Could not open file " << filename << endl; + return; + } + + string line; + getline(file, line); // Skip header + + while (getline(file, line)) + { + stringstream ss(line); + Task task; + string token; + + getline(ss, token, ','); // Task ID + task.id = token; + getline(ss, token, ','); // WCET + task.WCET = stoi(token); + getline(ss, token, ','); // BCET + task.BCET = stoi(token); + getline(ss, token, ','); // Period + task.period = stoi(token); + getline(ss, token, ','); // Deadline + task.deadline = stoi(token); + getline(ss, token, ','); // Priority + task.priority = stoi(token); + + tasks.push_back(task); + } + file.close(); +} + +// Function to check if all jobs are completed +bool allJobsCompleted(const vector& jobs) +{ + for (const auto& job : jobs) { + if (job.remainingTime > 0) { + return false; + } + } + return true; +} + +// Function to find the job with the highest priority +Job *highest_priority(vector& readyList) +{ + return *min_element( + readyList.begin(), + readyList.end(), + [](Job* a, Job* b) { + return a->task.priority < b->task.priority; + } + ); +} + +// Function to get the list of ready jobs +vector get_ready(vector& jobs, int currentTime) +{ + vector readyList; + for (auto& j : jobs) { + if (j.releaseTime <= currentTime && j.remainingTime > 0) { + readyList.push_back(&j); + } + } + return readyList; +} + +int main(int argc, char* argv[]) +{ + if (argc != 2) { + cerr << "Usage: " << argv[0] << " " << endl; + return 1; + } + + string filename = argv[1]; + vector tasks; + readTasksCSV(filename, tasks); + + int n = 1000; + int currentTime = 0; + + vector jobs; + jobs.reserve(tasks.size()); + for (const auto& t : tasks) { + jobs.push_back({t, 0, t.WCET, 0}); + } + + vector worstCaseResponseTimes(tasks.size(), 0); + + while (currentTime < n && !allJobsCompleted(jobs)) + { + // Release new jobs at the start of each period + for (const auto& t : tasks) + { + if (currentTime != 0 && currentTime % t.period == 0) { + jobs.push_back({t, currentTime, t.WCET, 0}); + } + } + + // Get the list of ready jobs + vector readyList = get_ready(jobs, currentTime); + + // If no jobs are ready, increment the current time + if (readyList.empty()) + { + currentTime++; + continue; + } + + // Get the job with the highest priority + Job* currentJob = highest_priority(readyList); + + if (currentJob != nullptr) + { + // Execute the job for one time unit + currentJob->remainingTime--; + currentTime++; + + // If the job is completed, update its response time + if (currentJob->remainingTime <= 0) + { + currentJob->responseTime = currentTime - currentJob->releaseTime; + int taskIndex = distance( + tasks.begin(), + find_if(tasks.begin(), tasks.end(), [&](const Task& tk){ + return tk.id == currentJob->task.id; + }) + ); + worstCaseResponseTimes[taskIndex] = max( + worstCaseResponseTimes[taskIndex], + currentJob->responseTime + ); + } + } + else + { + currentJob->remainingTime--; + currentTime++; + } + } + + // Output the worst-case response times for each task + for (size_t i = 0; i < tasks.size(); ++i) + { + cout << "Task " << tasks[i].id + << " WCRT: " << worstCaseResponseTimes[i] << endl; + } + + return 0; +} \ No newline at end of file