-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmips.py
240 lines (201 loc) · 7.25 KB
/
mips.py
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
import sys
fr = open(sys.argv[1], 'r') # 파일 읽기
fw = open(sys.argv[1] + '.out.txt', 'w') # 결과 파일 쓰기
''' Instruction을 받아오는 함수 선언 '''
### Instruction Fetch ###
def fetch(instruction):
# instruction이 안들어왔거나 flush 해야할때 0 반환
if (instruction == 0):
opcode = 0
rs = 0
rt = 0
rd = 0
pcw = 1
iiw = 1
return opcode, pcw, iiw, rs, rt, rd
else:
# instruction이 들어왔다면 instruction을 파싱해서 각 레지스터 값을 반환
instruction = instruction.strip('\n').split(' ')
opcode = instruction[0]
if opcode == 'ADDI' or opcode == 'ORI': # I-Type immediate values parsing
rt = instruction[1].strip(',')[1]
rs = instruction[2].strip(',')[1]
rd = 0
elif opcode == 'LW' or opcode == 'SW': # I-Type load and store parsing
rt = instruction[1].strip(',')[1]
rd, rs = instruction[2].split('(')
rd = 0
rs = rs.strip(')')[1]
else: # R-Type parsing
rd = instruction[1].strip(',')[1]
rs = instruction[2].strip(',')[1]
rt = instruction[3][1]
pcw = 1
iiw = 1
return opcode, pcw, iiw, rs, rt, rd
### 출력 테이블 ###
fw.write('|-------------|-----------------|-------------------------------------------|--------------|--------------|-----------------------|--------------------------------------|\n')
fw.write('| Cycle # | IF/ID | ID/EX | EX/MEM | MEM/WB | Forward | |\n')
fw.write('|-------------|-----------------|-------------------------------------------|--------------|--------------|-----------------------|--------------------------------------|\n')
''' 메인 프로세서 '''
count = 0
cycle = 0
while True:
# 싸이클 수 증가
cycle += 1
### Writeback ###
try:
if emopc == 0:
mwrd = 0
mww = 0
else:
mwrd = emrd
mww = emw
# 첫 싸이클 때 입력 값이 없어서 생기는 오류 처리
except:
mwrd = 0
mww = 0
### Memory ###
try:
if ieopc == 0:
emopc = 0
emrd = 0
emw = 0
else: # ID/EX stage에서 넘겨 받은 destination register를 rd register로 넘겨줌
emopc = ieopc
if ied == 1: # ied 1인 경우 R-type
emrd = ierd
elif ied == 0: # ied 가 0인 경우 I-type
emrd = iert
emw = iew # ID/EX stage에서 넘겨 받은 regWrite
# 첫 싸이클 때 입력 값이 없어서 생기는 오류 처리
except:
emopc = 0
emrd = 0
emw = 0
### Execution ###
try:
if iiopc == 0: # 오퍼레이션 코드가 없으면 버블이다
ieopc = 0
iers = 0
iert = 0
ierd = 0
iew = 0
iem = 0
ied = 0
fa = '00'
fb = '00'
else:
ieopc = iiopc
iers = iirs
iert = iirt
ierd = iird
iew = 1
# Forwarding
# fa, fb 값 초기화
fa = '00'
fb = '00'
# EX hazard
if emw == 1 and emrd != 0 and emrd == iers:
fa = '10'
elif emw == 1 and emrd != 0 and emrd == iert:
fb = '10'
# MEM hazard (not 의 뒷부분은 더블 데이터 해저드를 방지 하기 위한 조건 검사)
if mww == 1 and mwrd != 0 and mwrd == iers and not (emw == 1 and emrd != 0 and emrd == iers):
fa = '01'
elif mww == 1 and mwrd != 0 and mwrd == iert and not (emw == 1 and emrd != 0 and emrd == iert):
fb = '01'
# lw instruction 이라면 메모리를 사용하는 것이기 때문에 memread == 1
if ieopc == 'LW':
iem = 1
else:
iem = 0
# Instruction Type 에 따라 dst register 판단해서 dst register 값 넘겨주기
if ieopc == 0: # 넘겨 받는 레지스터 값이 하나도 없을 경우 버블이다
ied = 0
elif ieopc == 'ADD' or ieopc == 'OR': # R-Type 일경우 (destination register는 rd)
ied = 1
else: # I-Type 일경우 (destination register는 rt)
ied = 0
# 첫 싸이클 때 입력 값이 없어서 생기는 오류 처리
except:
ieopc = 0
iers = 0
iert = 0
ierd = 0
iew = 0
iem = 0
ied = 0
fa = '00'
fb = '00'
### Instruction Decode ###
try:
if pcw == 1 and iiw == 1:
iiopc = opc
iirs = rs
iirt = rt
iird = rd
# load-use data hazard determination
if iem == 1 and (iert == iirs or iert == iirt != 0) and iert != 0:
# pc write와 IF/ID Write 0 으로 설정
pcw = 0
iiw = 0
# 다음 stage로 값이 넘어가지 않도록 iiopc == 0으로 변경
iiopc = 0
else: # instruction이 더이상 없을 시
iiopc = 0
iirs = 0
iirt = 0
iird = 0
# 첫 싸이클 때 입력 값이 없어서 생기는 오류 처리
except:
iiopc = 0
iirs = 0
iirt = 0
iird = 0
try:
if (pcw != 0 and iiw != 0): # pipeline bubble이 발생하지 않을 경우
# instruction 읽어오기
instruction = fr.readline()
if not instruction:
instruction = 0
### Instruction Fetch ###
opc, pcw, iiw, rs, rt, rd = fetch(instruction)
ief = 0
else: # pipeline stall을 해야할 경우 새로운 Instruction을 불러오지 않고 한번 더 같은 instruction으로 진행
if not instruction: # 더 이상 읽을 instruction이 없을 경우
if count == 5: # 현재 들어온 싸이클을 모두 읽은 후 종료
break # 종료
count += 1
ief = 1 # bubble을 만들어야하기 때문에 flush는 1
# 파이프라인 버블이 있을 때 출력
### 테이블 출력 ###
fw.write('| | $rs | $rt | $rd | $rs | $rt | $rd | $write | memread | $dst | $rd | $write | $rd | $write | Forward A | Forward B | PC write | IF/ID write | ID/EX flush |\n')
fw.write('| Cycle {:>3} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} |\n'\
.format(cycle, iirs, iirt, iird, iers, iert, ierd, iew, iem, ied, emrd, emw, mwrd, mww, fa, fb, pcw, iiw, ief))
fw.write('|-------------|-----|-----|-----|-----|-----|-----|--------|---------|------|-----|--------|-----|--------|-----------|-----------|----------|-------------|-------------|\n')
# pc write 와 IF/ID write 를 == 1로 와 flush 를 0으로 재설정 후 다음 싸이클로 continue
pcw = 1
iiw = 1
ief = 0
continue
except:
# instruction 읽어오기
instruction = fr.readline()
if not instruction:
instruction = 0
### Instruction Fetch ###
opc, pcw, iiw, rs, rt, rd = fetch(instruction)
ief = 0
if not instruction: # 더 이상 읽을 instruction이 없을 경우
if count == 5: # 현재 들어온 싸이클을 모두 읽은 후 종료
break # 종료
count += 1
### 테이블 출력 ###
fw.write('| | $rs | $rt | $rd | $rs | $rt | $rd | $write | memread | $dst | $rd | $write | $rd | $write | Forward A | Forward B | PC write | IF/ID write | ID/EX flush |\n')
fw.write('| Cycle {:>3} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} | {:>2} |\n'\
.format(cycle, iirs, iirt, iird, iers, iert, ierd, iew, iem, ied, emrd, emw, mwrd, mww, fa, fb, pcw, iiw, ief))
fw.write('|-------------|-----|-----|-----|-----|-----|-----|--------|---------|------|-----|--------|-----|--------|-----------|-----------|----------|-------------|-------------|\n')
### 파일 읽기 쓰기 종료 ###
fr.close()
fw.close()