Computer Organization
A class focused on computer organization, assembly language, and operating systems with a heavy emphasis on systems and low-level programming. This was a group project to build an Instruction Pipeline and Cache Simulator (IPLC-Sim). I wrote the code for creating the Cache and Cache functions, which should dynamically build the optimal cache data structure based on user input and properly handle the caching and hits and misses.
Here is a snippet of my code from the cache initialization:
void iplc_sim_init(int index, int blocksize, int assoc)
{
int i=0, j=0;
unsigned long cache_size = 0;
cache_index = index;
cache_blocksize = blocksize;
cache_assoc = assoc;
cache_blockoffsetbits =
(int) rint((log( (double) (blocksize * 4) )/ log(2)));
/* Note: rint function rounds the result up prior to casting */
cache_size = assoc * ( 1 << index ) * ((32 * blocksize) + 33 - index - cache_blockoffsetbits);
printf("Cache Configuration \n");
printf(" Index: %d bits or %d lines \n", cache_index, (1<<cache_index) );
printf(" BlockSize: %d \n", cache_blocksize );
printf(" Associativity: %d \n", cache_assoc );
printf(" BlockOffSetBits: %d \n", cache_blockoffsetbits );
printf(" CacheSize: %lu \n", cache_size );
if (cache_size > MAX_CACHE_SIZE ) {
printf("Cache too big. Great than MAX SIZE of %d .... \n", MAX_CACHE_SIZE);
exit(-1);
}
cache = (cache_line_t *) malloc((sizeof(cache_line_t) * 1<<index));
// Dynamically create our cache based on the information the user entered
for (i = 0; i < (1<<index); i++) {
// DONE Cache:
/* initialize and fill in with 0s */
cache[i].valid = (int *)calloc(sizeof(int), assoc);
cache[i].tag = (int *)calloc(sizeof(int), assoc);
cache[i].replaced = (int *)calloc(sizeof(int), assoc);
for (j=0; j<assoc; j++){
cache[i].valid[j] = 0;
cache[i].tag[j] = 0;
}
}
// init the pipeline -- set all data to zero and instructions to NOP
for (i = 0; i < MAX_STAGES; i++) {
// itype is set to O which is NOP type instruction
bzero(&(pipeline[i]), sizeof(pipeline_t));
}
}
{
int i=0, j=0;
unsigned long cache_size = 0;
cache_index = index;
cache_blocksize = blocksize;
cache_assoc = assoc;
cache_blockoffsetbits =
(int) rint((log( (double) (blocksize * 4) )/ log(2)));
/* Note: rint function rounds the result up prior to casting */
cache_size = assoc * ( 1 << index ) * ((32 * blocksize) + 33 - index - cache_blockoffsetbits);
printf("Cache Configuration \n");
printf(" Index: %d bits or %d lines \n", cache_index, (1<<cache_index) );
printf(" BlockSize: %d \n", cache_blocksize );
printf(" Associativity: %d \n", cache_assoc );
printf(" BlockOffSetBits: %d \n", cache_blockoffsetbits );
printf(" CacheSize: %lu \n", cache_size );
if (cache_size > MAX_CACHE_SIZE ) {
printf("Cache too big. Great than MAX SIZE of %d .... \n", MAX_CACHE_SIZE);
exit(-1);
}
cache = (cache_line_t *) malloc((sizeof(cache_line_t) * 1<<index));
// Dynamically create our cache based on the information the user entered
for (i = 0; i < (1<<index); i++) {
// DONE Cache:
/* initialize and fill in with 0s */
cache[i].valid = (int *)calloc(sizeof(int), assoc);
cache[i].tag = (int *)calloc(sizeof(int), assoc);
cache[i].replaced = (int *)calloc(sizeof(int), assoc);
for (j=0; j<assoc; j++){
cache[i].valid[j] = 0;
cache[i].tag[j] = 0;
}
}
// init the pipeline -- set all data to zero and instructions to NOP
for (i = 0; i < MAX_STAGES; i++) {
// itype is set to O which is NOP type instruction
bzero(&(pipeline[i]), sizeof(pipeline_t));
}
}
See the full iplc-sim code on my github: https://github.com/marymonty/sample_code/tree/master/c/PipelineCacheSimulatorProject
Operating Systems
A class focused on computer operating systems design and implementation, with topics including concurrent processes and synchronization problems, process management and scheduling of processes, virtual memory management, device management, and file systems, programmed mostly in C and Python. This was a group project to create a simulated cpu scheduler based on three different algorithms - first come first served, round robbin, and shortest remaining time. My code was for the shortest remaining time method, which schedules tasks by selecting the process with the shortest CPU burst time as the next process executed by the CPU.
Here is a snippet of my code from my shortest remaining time C file:
/* populateReadyQueue
a function to populate the readyQueue based on the priority set in the calcSRTPriority function
params:
proc_scheduler : the schedule of processes, made in order of arrival times
current_time_elapsed : the time that has passed in the simulation
*/
void populateReadyQueue(scheduler* proc_scheduler, int current_time_elapsed, double lambda, double alpha)
{ /* first, get the current process by using peek */
process current_proc = peek(&proc_scheduler->processes);
/* next get the arrival time */
int current_proc_arrival = current_proc.arrival_time;
printf("\tPROCESS %d HAS ARRIVAL TIME OF %d\n", current_proc.pid, current_proc.arrival_time);
a function to populate the readyQueue based on the priority set in the calcSRTPriority function
params:
proc_scheduler : the schedule of processes, made in order of arrival times
current_time_elapsed : the time that has passed in the simulation
*/
void populateReadyQueue(scheduler* proc_scheduler, int current_time_elapsed, double lambda, double alpha)
{ /* first, get the current process by using peek */
process current_proc = peek(&proc_scheduler->processes);
/* next get the arrival time */
int current_proc_arrival = current_proc.arrival_time;
printf("\tPROCESS %d HAS ARRIVAL TIME OF %d\n", current_proc.pid, current_proc.arrival_time);
/* priority_metric is how we order the processes in the readyQueue */
double current_proc_priority;
/* check the current processes arrival time against the current_time_elapsed */
while (current_time_elapsed <= current_proc_arrival)
{
printf("\tADDING PROCESS %d TO THE READY QUEUE\n", current_proc.pid);
double current_proc_priority;
/* check the current processes arrival time against the current_time_elapsed */
while (current_time_elapsed <= current_proc_arrival)
{
printf("\tADDING PROCESS %d TO THE READY QUEUE\n", current_proc.pid);
/* calculate the priority metric for the current process */
current_proc_priority = calcSRTPriority(current_proc, lambda, alpha);
/* if the readyQueue is empty we need to make a newNode to head the list */
if(isEmpty(&proc_scheduler->readyQueue))
{
printf("\tTHIS IS THE FIRST PROCESS BEING ADDED TO THE READYQUEUE\n");
current_proc_priority = calcSRTPriority(current_proc, lambda, alpha);
/* if the readyQueue is empty we need to make a newNode to head the list */
if(isEmpty(&proc_scheduler->readyQueue))
{
printf("\tTHIS IS THE FIRST PROCESS BEING ADDED TO THE READYQUEUE\n");
proc_scheduler->readyQueue = newNode(current_proc, current_proc_priority);
}
/* else the readyQueue already has a head and we can just push to it */
else
{
push(&proc_scheduler->readyQueue, current_proc, current_proc_priority);
}
/* pop from the list since we have moved the process from the processes
to the readyQueue so it no longer needs to be in the processes list */
pop(&proc_scheduler->processes);
/* need to update the current process and arrival time for the while loop
(we dont need to go to &proc_scheduler->processes->next because when we pop
we reload the processes into the head */
if (!isEmpty(&proc_scheduler->processes))
{
current_proc = peek(&proc_scheduler->processes);
current_proc_arrival = current_proc.arrival_time;
printf("\tPROCESS %d HAS ARRIVAL TIME OF %d\n", current_proc.pid, current_proc.arrival_time);
}
else //no more processes
{
return;
}
}
}
}
/* else the readyQueue already has a head and we can just push to it */
else
{
push(&proc_scheduler->readyQueue, current_proc, current_proc_priority);
}
/* pop from the list since we have moved the process from the processes
to the readyQueue so it no longer needs to be in the processes list */
pop(&proc_scheduler->processes);
/* need to update the current process and arrival time for the while loop
(we dont need to go to &proc_scheduler->processes->next because when we pop
we reload the processes into the head */
if (!isEmpty(&proc_scheduler->processes))
{
current_proc = peek(&proc_scheduler->processes);
current_proc_arrival = current_proc.arrival_time;
printf("\tPROCESS %d HAS ARRIVAL TIME OF %d\n", current_proc.pid, current_proc.arrival_time);
}
else //no more processes
{
return;
}
}
}
View the full code on my github: https://github.com/marymonty/sample_code/blob/master/c/OperatingSystems/cpu_scheduler_srt.c