-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCPU_Simulator.cpp
More file actions
223 lines (199 loc) · 6.03 KB
/
Copy pathCPU_Simulator.cpp
File metadata and controls
223 lines (199 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
* John Deters
* CPU Simulator
*/
#include "cpu_simulator.h"
#include <fstream>
#include <algorithm>
#include <iterator>
#include <sstream>
// construct CPU
CPU::CPU(std::initializer_list<Program> p_list){
lock_flag_ = false;
program_index_ = 0;
memory_.clear();
current_instruction_ = "";
instruction_fields_.clear();
// add programs from list to vector
for (auto item : p_list)
programs_.push_back(item);
}
// split instructions into pieces
void CPU::split_instruction(){
//std::cout<<"split_instruction"<<std::endl;
// reset vector
instruction_fields_.clear();
// create stream to get individual items
std::istringstream iss(current_instruction_);
// copy items into vector
std::copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(instruction_fields_));
//for (auto i : instruction_fields_)
//std::cout<<"split: "<< i<<std::endl;
}
// run the CPU
void CPU::run(){
//std::cout<<"run"<<std::endl;
// while finished returns true loop programs
while (finished() != false){
// get instruction if program is running
if (programs_[program_index_].get_status() == "running")
// get instruction
current_instruction_ = programs_[program_index_].get_instruction(lock_flag_);
// split and execute if still running
if (programs_[program_index_].get_status() == "running"){
split_instruction();
execute_instruction();
}
// next program to index
program_index_++;
// reset index if out of size
if (program_index_ == programs_.size())
program_index_ = 0;
}
//std::cout<<"complete";
}
// check if unlocked
bool CPU::is_unlock(){
// unlocked and lock flag already called
if ((instruction_fields_[0] == "unlock")&&(lock_flag_ == true)){
//std::cout<<"is_unlock"<<std::endl;
return true;
}
// error if unlocked called before locked
else if ((instruction_fields_[0] == "unlock")&&(lock_flag_ == false)){
programs_[program_index_].set_status("error: unlock called before lock");
std::cout<<"error: unlock called before lock"<<std::endl;
return true;
}
// instruction not unlock
else
return false;
}
// check if print
bool CPU::is_print(){
// print existing variable
std::map<std::string,long>::iterator it = memory_.find(instruction_fields_[1]);
if ((instruction_fields_[0] == "print")&&
(it != memory_.end())){
//std::cout<<"is_print"<<std::endl;
return true;
}
// variable not in map
else if(instruction_fields_[0] == "print"){
programs_[program_index_].set_status("error: variable does not exist");
std::cout<<"error: variable does not exist"<<std::endl;
return false;
}
// not print instruction
else
return false;
}
// check if lock
bool CPU::is_lock(){
// call lock
if (instruction_fields_[0] == "lock"){
//std::cout<<"is_lock"<<std::endl;
return true;
}
// not a lock
else
return false;
}
// check if end
bool CPU::is_end(){
// call end
if (instruction_fields_[0] == "end"){
//std::cout<<"is_end"<<std::endl;
return true;
}
// not end instruction
else
return false;
}
// check if variable assignment
bool CPU::is_assignment(){
// is variable assignment
if (instruction_fields_[1] == "="){
//std::cout<<"is_assignment"<<std::endl;
return true;
}
// not variable assignment
else
return false;
}
// check if any programs running
bool CPU::finished(){
// flag for any running program
bool flag = false;
// double lock call
bool waiting_flag = true;
// check status of each program
for (auto program : programs_){
if (program.get_status() != "waiting") waiting_flag = false;
if (program.get_status() == "running") flag = true;
}
// double lock error
if (waiting_flag == true){
programs_[program_index_].set_status("error: program called twice in same program");
std::cout<<"error: program called twice in same program"<<std::endl;
}
//std::cout<<"finished"<<std::endl;
return flag;
}
// execute current instruction
void CPU::execute_instruction(){
// end instruction
if((is_end() == true)||(current_instruction_ == ""))
programs_[program_index_].set_status("finished");
// lock instruction
else if (is_lock() == true)
lock_flag_ = true;
// unlock instruction
else if (is_unlock() == true)
lock_flag_ = false;
// variable assignment instruction
else if (is_assignment() == true)
memory_[instruction_fields_[0]] = std::stoi(instruction_fields_[2]);
// print instruction
else if (is_print() == true)
std::cout<<memory_.find(instruction_fields_[1])->second<<std::endl;
// command not accepted
else if (current_instruction_ != "waiting"){
std::cout<<"error in command: "<< current_instruction_<<std::endl;
}
}
// Construct Program
Program::Program(std::string file_name){
status_ = "running";
instruction_index_ = 0;
std::ifstream new_file;
new_file.open(file_name);
std::string line;
// get instructions from file
while (std::getline(new_file, line)){
instructions_.push_back(line);
}
}
// get instruction
std::string Program::get_instruction(bool lock_flag){
//std::cout<<"get instruction: ";
// index out of range
if (instruction_index_ == instructions_.size()){
return "";
set_status("finished");
}
// get instruction from vector
std::string instruction = instructions_[instruction_index_];
// wait of lock flag is on
if ((lock_flag == true)&&(instruction == "lock")){
return"waiting";
}
// run instruction
else{
instruction_index_ ++;
//std::cout<<instruction<<std::endl;
return instruction;
}
}