Son Teslim Tarihi: 11 Aralık 2017 23:00Operating Systems,
Not: siteye dosya yükleyemediğimdem buraya pdf'i kopyaladım; ekdeki zip dosyası ödevde kullanılıcaktır.
CS307 – Operating Systems
Term Project - Phase 1
In a computer system, there are four important components: CPU, Disk, Memory and Input/
Output Devices. When a program wants to be executed, it is read from the disk, loaded into
the memory and then one by one its instructions are fetched, decoded and executed by CPU.
In this project, you will be creating a basic virtual computer system in which you will
simulate CPU, Memory and I/O devices.
In the first phase of the project, you are expected write a program which will simulate a
computer system: It will read one assembly file, load this file into a virtual Memory and
then a virtual CPU will execute the instructions of the process one-by-one.
For the purpose of creating a virtual computer system, you will be given three template
classes: CPU, Memory, ProcessImage and a complete Assembler/Disassembler. The usage and
details of the classes and the flow of the program will be explained below:
CPU is the class where the instructions are executed. The registers of CPU are initiated with the
register values of the process image that will be executed.
CPU has normally three main functions: fetch(), decode() and execute(). fetch() takes the
instruction which will be executed from the memory, decode() decodes this instruction
and execute() executes the instruction.
For this project, the CPU class will have two functions: fetch() and decodeExecute(). fetch() will
have the same functionality: It will take the instruction from memory, store it in the Instruction
Register and increment the Program Counter. In decodeExecute() function you will take the
instruction from Instruction Register, decode and execute it.
Memory is the class where the instructions of processes are stored. It has a private member
called memory of the type char array. As each assembly instruction is 32 bits, your program
will store these instructions using 4 bytes and these bytes will be represented ascharacters.
Process Image is the class where all the information related to a process is stored. Each process
keeps its registers, a base register and a limit register where the base register points to the first
instruction in the memory for the corresponding process. The template exists for Process Image
Class but you need to implement its functions.
OS Class (extends Thread)
Operating System class deals with scheduling and memory management and enables the
concurrent execution of multiple programs. It maintains two queues: Block and Ready Queue. At
any given time, there will be only one process running. Each newly arriving process will be
appended at the end of the Ready Queue and then the processes in the Ready Queue will be
executed in a round robin fashion.
In this simulation environment, there are two types of system calls: console input and output. If a
running process blocks for console input it will be sent to Blocked Queue until the input entered by
the user from the console. In case a system call for output is issued, OS will immediately give the
output and put the process at the end of the Ready Queue.
InputThread Class (extends Thread)
This class will be in OS class, will start working when OS thread starts working and stop working
when OS thread stops working. The responsibility of this class is to get the input from the console.
When a process issues a system call it will be extracted from the ready queue and will be sent to
blocked queue as explained above. This class as a separate thread will constantly check if there is
any process inside the blocked queue and if so, it will wait for an input from the user and when the
user enters an input it will update the necessary register, remove the process from the blocked
queue and put it again at the end of the ready queue. One thing you have to pay attention is that
while this class checks the blocked queue and waits for an input, OS class should continue working
and executing the other processes in the ready queue.
Your program will initially read assembly instructions from a file called assemblyInput.asm,
transform them into binary code and write it to a file called assemblyInput.bin. This step is
called the assembly phase, essentially your program is transforming the assembly
instructions into binary code.
The task of reading assembly instructions and transforming them into bit code was actually
the main topic of the Programming Assignment I. Therefore, you do not need to rewrite an
assembler, you will be given the implementation of an assembler and you can use its member
functions to convert the instructions into a binary file and convert it back.
Creating assemblyInput.bin means that there is a program (or in other words process) which
will be executed, therefore a ProcessImage is created. The registers of the ProcessImage will
be initially 0. You will read the binary code from assemblyInput.bin, then load it into the
memory array of the Memory class. You will keep the starting position and the size of the
binary code in the base and limit registers of the ProcessImage.
After loading the binary code into Memory, you will put the ProcessImage at the end of the
Ready Queue. CPU will take the first ProcessImage in the Ready Queue and load it into CPU
(copy the registers, base register and limit register into CPU) and start the fetch-decodeexecute
cycle of the CPU. The fetch function will receive the instruction which will be
executed from memory using Program Counter and the address stored in Base Register. The
decodeExecute function will decode and execute the instruction.
The virtual Operating System will use Round Robin scheduling with quantum = 5 for
scheduling. The fetch-decode-execute cycle of CPU will continue until the ready
queue is empty. When the ready and the blocked queue is empty, the Operating
System will stop its execution and the simulation will end.
For the first phase of the project, you will only work with a single process for
simplification. You should implement Ready, Blocked Queue and Round Robin
Scheduling as you are dealing with multiple processes, however for this phase
assemblyInput.asm will contain the instructions of a single process and when this
process is finished, the simulation will also be finished.
For evaluation purposes, after the process is finished, you will store the registers in
CPU back into the ProcessImage and then write these registers into a file called
Below is also the step-by-step explanation of the program flow:
1. Create the instances of Memory, CPU and OS.
2. Read the processes from the disk and convert it into a binary file
3. Create a process image for each process, read the binary file(s) and load it/them into the
4. Put processes into the ready queue.
5. Start OS Thread (and consequently Input Thread).
6. Until all the processes finish, take the first process from the ready queue, send it to CPU
(make the context switch for the chosen process) and let it run for the given quantum or
until it blocks for input
7. If any running process gets blocked for console input, put it at the end of the Blocked
8. If any running process issues a console output, write the desired output to the console
and put the process at the end of the Ready Queue. A console output in this case will not
actually block the process but it will still cause a context switch.
9. If an input is entered from the console by the user, it will be consumed by the first
process in the Blocked Queue. You need to make necessary changes for that process
with respect to the given input and send it back to the Ready Queue. If there is no
process in the Blocked Queue, ignore the input.
10. After all of the processes finish, you can terminate the simulation.
While accessing shared variables from different threads, please provide mutual exclusion using
mutexes to avoid any read/write conflicts.
Assembly Instructions and Register Usage
Below you can find the assembly instructions and their usages, it is the same as Programming
ADD S1 S2 S3 => S1 = S2 + S3
SUB S3 S4 S1 => S3 = S4 – S1
ADDI S1 S2 C => S1 = S2 + C
SUBI S3 S4 C => S3 = S4 – C
ORI S1 S2 C => S1 = S2 | C (Bitwise ORoperation)
BEQ S1 S2 C => If S1 is equal to S2, then assign PC to C (PC = C if S1== S2)
LUI S1 C =>S1 = C || 0x00 where || is concatenation
LW S1 S2 => Store the value at the memory location pointed by S2 in S1 (S1 = *S2)
SW S1 S2 => Store S1 in the memory location pointed by S2 (*S2 = S1) Where C is a 16-bit
unsigned integer and S0-S7 registers are 32 bit unsigned integers.
SYSCALL => System call used for IO operations. If V is equal to 0, then you will read an input
from console using cin. You can assume that the input will be a 32-bit unsigned integer. After
receiving the input, you will write the result to the register V. If V is not equal to 0, then you will
outputthe value of V to the console.
Bit Representations of Register and Operations
PC => 00000 V => 00010
S0=> 00011 S1 =>00100 S2 => 00101 S3 => 00110
S4 => 00111 S5 => 01000 S6 => 01001 S7 => 01010
BR => 01011 $0 => 01100
Bit representation for Operations:
ADD =>010000 SUB=>010001 ADDI =>000010 SUBI =>000011
ORI =>011111 BEQ =>000111 LUI =>001000 LW =>001001
SYSCALL => 00000000000000000000000000000000 (32 0’s)
Execution of Pointer Operations
As the execution of pointer operations may be tricky, below are examples for the execution of
LW S1 S2 –> Assume that S2 = 3, then S1 = memory[BR + 3]
SW S1 S2 -> Assume that S1 = 5 and S2 = 3, then memory[BR + 3] = 5
Sample Runs & Further Technicalities
Below you can find an explained sample run which can further explain the technical details
of the assignment. You will also be given two additional sample runs. Assume that you have
an assembly instruction file which contains the following instructions:
ADDI S3 S4 0010001000100011
ADD S1 S7 S5
Your program will open the file and read these instructions. Then it will transform these instructions into
Then you will transform this code into binary code and find their char (ASCII) representation:
00001000 11000111 00100010 00100011 -> 8 199 34 35 -> BS Ç " #
01000000 10001010 01000000 00000000 -> 64 138 64 0 -> @ Š @ NUL
After converting the instructions into the binary code, we create a ProcessImage for this process.
Initially, each register of the ProcessImage is initialized to 0:
S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, $0 = 0, PC = 0, V = 0, IR = 0,
BR = 0, LR = 0
After initializing ProcessImage, we will load the binary code in assemblyCode.bin to the
memory. As the memory is initially empty, the memory array inside Memory object will
look like this:
0 1 2 3 4 5 6 7 8 …
BS Ç " # @ Š @ NUL
As the instructions for the process are stored starting at the index 0 and the size of the
instructions is 8, you will change the Base Register and Limit Register of the ProcessImage
BR = 0, LR = 8
After that, the ProcessImage is ready. We will copy the registers of ProcessImage into
CPU: S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, $0 = 0, PC = 0, V = 0, IR =
BR = 0, LR = 8
After copying the ProcessImage registers into CPU, the fetch-decode-execute cycle will start.
Fetch function will receive the instruction according to the Base Register and Program Counter:
fetch() -> Receive the instruction at Base Register (0) + Program Counter (0)*4 -> BS Ç “ #
Afterwards fetch() will store this register in Instruction Register:
BS Ç “ # -> 12 199 34 35 -> 00001000 11000111 00100010 00100011 -> 147268131
IR = 147268131
And increment the Program Counter by four as each instruction is 4
byte: PC = 4
Then decodeExecute() function will decode the IR and execute the
operation: IR = 147268131 -> 000010 00110 00111 0010001000100011
-> S3 = 0 + 8739
-> S3 = 8739
Since Program Counter is not equal to Limit Register, the fetch-decode-execute cycle will run
Fetch() -> Receive the instruction at Base Register (0) + Program Counter (4) -> @ Š @ NUL
Afterwards Fetch() will store this register in Instruction Register:
@ Š @ NUL -> 64 138 64 0 -> 01000000 10001010 01000000 00000000 -> 1082802176
IR = 1082802176
And increment the Program Counter by four:
PC = 8
Then decodeExecute() function will decode the IR and execute the operation:
IR = 1082802176-> 010000 00100 01010 01000 00000000000
-> S1 = 0 + 0
-> S1 = 0
When Program Counter is equal to Limit Register, it means that the process is finished. In
the second phase of the simulation, we will only run one process and since it is over, we
finish the fetch-decode-execute cycle. Afterwards we copy the CPU registers back to
S0 = 0, S1 = 0, S2 = 0, S3 = 8739, S4 = 0, S5 = 0, S6 = 0, S7 = 0, $0 = 0, PC = 8, V = 0,
IR = 1082802176, BR = 0, LR = 8
Afterwards we will write the registers to a file called processRegisterDump.bin. Each line will
contain one register and it will look like this:
Eklenen dosyaları görmek için giriş yapınız !
Senin için küçük bir hatırlatma
İletişime geçebilmek için teklif vermelisiniz
Ücret gerektirmeyen ilanlar için afaki rakam verebilirsiniz (ör:10tl)