verilog五层流水线CPU-P7(全指令+异常中断处理+外设连接)

模块设计

整体视图:

cpu:

1. GRF(寄存器堆)

端口名 输入\输出 位宽 功能
clk Input 1 时钟信号
reset Input 1 复位信号
WE Input 1 使能信号
PC Input 31:0 pc
A1 Input 4:0 输入寄存器地址端口1
A2 Input 4:0 输入寄存器地址端口2
A3 Input 4:0 输入寄存器地址端口3,写寄存器地址
EXTRA Input 4:0 输入寄存器地址端口EX,读寄存器地址
WD Input 31:0 数据输入端口,输入一个32位数据,存入编码为A3的寄存器中
RD1 Output 31:0 输出编码为A1中输入的寄存器中的值
RD2 Output 31:0 输出编码为A2中输入的寄存器中的值
RDEXTRA Output 31:0 输出编码为EXTRA中输入的寄存器中的值

初始化!!

verilog
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
module GRF (
input clk,
input reset,
input WE,
input [31:0] PC,
input [4:0] A1,
input [4:0] A2,
input [4:0] A3,
input [4:0] EXTRA,
input [31:0] WD,
output [31:0] RD1,
output [31:0] RD2,
output [31:0] RDEXTRA

);

reg [31:0] registers[31:0];
integer i;
assign RD1 = (A1 === 5'b0) ? 32'b0 : ((A1 === A3) && WE) ? WD : registers[A1];
assign RD2 = (A2 === 5'b0) ? 32'b0 : ((A2 === A3) && WE) ? WD : registers[A2];
assign RDEXTRA = (EXTRA === 5'b0) ? 32'b0 : ((EXTRA === A3) && WE) ? WD : registers[EXTRA];

initial begin
for (i = 0; i < 32; i = i + 1) begin
registers[i] = 32'b0;
end
end


always @(posedge clk) begin
if (reset) begin
for (i = 0; i < 32; i = i + 1) begin
registers[i] <= 32'b0;
end
end else begin
if (WE) begin
registers[A3] <= WD;
end
end
end

endmodule

2. DATA

端口名 输入\输出 位宽 功能
cpu_data_rdata I 31:0 数据存储器存储的相应数据
cpu_data_addr O 31:0 数据存储器存储的相应数据
cpu_data_wdata O 31:0 待写入数据存储器相应数据
cpu_data_byteen O 3:0 四位字节使能
cpu_inst_addr O 31:0 M 级 PC

使用课程组给定的外部实现,通过bridge连接。

verilog
1
2
3
4
5
assign cpu_inst_addr=pc_E_OUT;
assign cpu_data_addr=ao_E_OUT;
assign cpu_data_byteen=(req===1'b1)?4'b0:data_byteen_IN;////////
assign cpu_data_wdata=(memdata<<(wd_sll*8));
assign memoutdata=cpu_data_rdata;

3. NPC

端口名 输入\输出 位宽 功能
clk Input 1 时钟信号
reset Input 1 复位信号
beq_judge Input 1 beq指令pc选择
bne_judge Input 1 bne指令pc选择
j_if Input 1 j指令pc选择
jr_if Input 1 jr指令pc选择
jal_if Input 1 jal指令pc选择
eret_if Input 1 eret指令pc选择
imm Input 31:0 位扩展后的立即数
PC_D Input 31:0 D级PC
j_addr Input 25:0 j指令跳转地址
jr_addr Input 31:0 jr指令跳转地址
NPC Output 31:0 输出的真实pc值
EPC Input 31:0 eret跳转所需EPC
EXCcodeF Output 4:0 F级异常码

外部引入两个对应位置的寄存器通过ALU的减法结果zero,通过与beq_if(判断指令是否为beq)连接,实现beq(if$[rs]==$[rt]): PC=PC+offest+4。

verilog
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
`define Int         5'b00000//0
`define AdEL 5'b00100//4
`define AdES 5'b00101//5
`define Syscall 5'b01000//8
`define RI 5'b01010//10
`define Ov 5'b01100//12
module NPC (
input clk,
input reset,
input req,
input beq_judge,
input bne_judge,
input block,
input j_if,
input jr_if,
input jal_if,
input eret_if,
input [31:0] imm,
input [31:0] PC_D,
input [25:0] j_addr,
input [31:0] jr_addr,
input [31:0] EPC,
output reg [31:0] NPC,
output [4:0] EXCcodeF
);

assign EXCcodeF = ((NPC<32'h3000||NPC>32'h6ffc||NPC[1:0]!=2'b00)===1'b1) ? `AdEL : `Int;

initial begin
NPC = 32'h0000_3000;
end

always @(posedge clk) begin
if (reset) begin
NPC <= 32'h00003000;
end
else if (req) begin
NPC <= 32'h00004180;
end
else if (eret_if) begin
NPC <= EPC;
end
else if (block === 1) begin
NPC <= NPC;
end
else if (j_if == 1'b1 || jal_if == 1'b1) begin
NPC <= {PC_D[31 : 28], j_addr, 2'b00};
end
else if (jr_if == 1'b1) begin
NPC <= jr_addr;
end
else if (beq_judge || bne_judge) begin
NPC <= ((imm << 2) + PC_D + 4);
end
else begin
NPC <= (NPC + 4);
end

end

endmodule

4.IM:

端口名 输入\输出 位宽 功能
i_inst_addr Input 31:0 pc
i_inst_rdata Output 31:0 指令机器码

使用课程组给定的外部实现,通过bridge连接。

5.ALU

端口名 输入\输出 位宽 功能
ALUOp Input 3:0 ALU功能选择
A Input 31:0 待处理数字1
B Input 31:0 待处理数字2
result Output 31:0 计算结果
overflow Output 1 溢出判断
ir_E Input 31:0 E级code
load_if Input 1 load型指令判断
store_if Input 1 store型指令判断
regwrite_if Input 1 grf写使能判断(暂留)
EXCcodeE Output 4:0 E级异常码
verilog
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
`define ADD 4'b0000
`define SUB 4'b0001
`define MUL 4'b0010
`define DIV 4'b0011
`define AND 4'b0100
`define OR 4'b0101
`define SLT 4'b0110
`define SLTU 4'b0111

`define OPCODE0 6'b000000
`define FUNC_ADD 6'b100000
`define FUNC_SUB 6'b100010
`define OPCODE_ADDI 6'b001000

`define LB 6'b100000///
`define LH 6'b100001///
`define LW 6'b100011
`define LBU 6'b100100///
`define LHU 6'b100101///

`define Int 5'b00000//0
`define AdEL 5'b00100//4
`define AdES 5'b00101//5
`define Syscall 5'b01000//8
`define RI 5'b01010//10
`define Ov 5'b01100//12
module ALU (
input [ 3:0] aluop,
input [31:0] A,
input [31:0] B,
input [31:0] ir_E,
input [3:0]load_if,
input [3:0]store_if,
input regwrite_if,

output [31:0] result,
output [4:0] EXCcodeE,
output overflow
);
reg [32:0] bit_33;
wire [32:0]tempA;
wire [32:0]tempB;
wire [5:0] opcode_E;
wire [5:0] func_E;
wire add_if;
wire addi_if;
wire sub_if;
wire l_if;
assign opcode_E=ir_E[31:26];
assign func_E=ir_E[5:0];
assign add_if=(opcode_E===`OPCODE0&&func_E===`FUNC_ADD);
assign sub_if=(opcode_E===`OPCODE0&&func_E===`FUNC_SUB);
assign addi_if=(opcode_E===`OPCODE_ADDI);

assign l_if=(opcode_E===`LW)||(opcode_E===`LB)||(opcode_E===`LH)||(opcode_E===`LBU)||(opcode_E===`LHU);

assign tempA={A[31],A};
assign tempB={B[31],B};
assign overflow = (bit_33[32]!==bit_33[31])?1'b1:1'b0;
assign result = bit_33[31:0];
assign EXCcodeE=
(((|load_if)===1'b1)&&(overflow===1'b1))?`AdEL:
(((|store_if)===1'b1)&&(overflow===1'b1))?`AdES:
((sub_if||add_if||addi_if)&&(overflow===1'b1))?`Ov:
`Int;//!!!

always @(*) begin
case (aluop)
`ADD: bit_33 = tempA + tempB;
`SUB: bit_33 = tempA - tempB;
`MUL: bit_33 = tempA * tempB;
`DIV: bit_33 = tempA / tempB;
`AND: bit_33 = tempA & tempB;
`OR: bit_33 = tempA | tempB;
`SLT: bit_33 = ($signed(A)<$signed(B))?$signed(33'b1):$signed(33'b0);
`SLTU: bit_33 = (A < B)?33'b1:33'b0;
default: begin
bit_33 = 33'b0;
end
endcase

end

endmodule

ALUOp:(留一位给剩下的)

0000 0001 0010 0011 0100 0101 0110 0111
add sub mul(无用) div(无用) and or slt sltu

6.EXT

端口名 输入\输出 位宽 功能
imm Input 15:0 16位立即数
extp Input 1 位扩展选择功能
extresult Output 31:0 位扩展计算结果
verilog
1
2
3
4
5
6
7
8
9
10
module EXT (
input [1:0] extop,
input [15:0] imm,
output [31:0] extresult
);
assign extresult = (extop == 2'b00) ? {16'h0000, imm} :
(extop == 2'b01) ? {{16{imm[15]}}, imm} :
(extop == 2'b10) ? {imm, 16'h0000} : {16'h0000, imm};//²âÊÔ
endmodule

EXTOp: 00 01 10 11
功能 0扩展 符号扩展 高位加载 空余

7.CTRL

端口名 输入\输出 位宽 功能
opcode Input 5:0 高六位opcode
func Input 5:0 低六位opcode
instr Input 31:0 指令码
regwrite Output 1 reg写使能
regwritedst Output 1:0 寄存器写选择
alusrc Output 1 alu选择imm入B口
memwrite Output 1 mem写使能
memtoreg Output 1 mem写入reg选择
jr_if Output 1 jr判断
j_if Output 1 j判断
jal_if Output 1 jal判断
beq_if Output 1 beq判断
bne_if Output 1 bne判断
eret_if Output 1 eret判断
mfc0_if Output 1 mfc0判断
mtc0_if Output 1 mtc0判断
EXCcodeD Output 4:0 D级异常码
extop Output 1:0 ext功能选择
aluop Output 3:0 alu功能选择

通过输入的指令码各部分,进行操作状态输出。

执行指令
信号名 add sub and or mult/multu div/divu slt sltu andi addi lui ori j jal jr beq bne eret sw/sh/sb lw/lh&lhu/lb&lbu nop syscall mfhi/lo mthi/lo mfc0 mtc0
opcode 000000 000000 000000 000000 000000 000000 000000 000000 001100 001000 001111 001101 000010 000011 000000 000100 000101 010000 101011 101001 101000 100011 100001 100101 100000 100100 000000 000000 000000 000000 01000 01000
func 100000 100010 100100 100101 011000 011001 011010 011011 101010 101011 001000 011000 000000 001100 010000 010010 010001 010011 [25:21]: 00100 [25:21]: 00100
regwrite 1 1 1 1 0 0 1 1 1 1 1 1 0 1 0 0 0 0 0 1 0 0 1 0 0 1
regwritedst(2) 01(rd) 01 01 01 00 00 01 01 00 00 00 00(rt) 00 10($ra) 00 00 00 00 00 00 00 00 01 00 00 00
alusrc(imm) 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0
memwrite 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1111 0011 0001 1111 0011 0001 0 0 0 0 0 0
memtoreg 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1111 0 0 0 0 0 0
extop(2) 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 01 01 00 01 01 00 00 00 0 0 0
beq_if 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
bne_if 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
j_if 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
jal_if 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
jr_if 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
eret_if 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
mfc0_if 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
mtc0_if 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
ALU_ctr3 0 0 1 1 1 1 1 1 1 0 1(or$0) 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1
ALU_ctr2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ALU_ctr1 0 1 0 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

不用ALU默认为与(100),防止额外的加减法溢出

verilog
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
`timescale 1ns / 1ps
//////OPCODE=0
`define OPCODE0 6'b000000
`define ADD 6'b100000
`define SUB 6'b100010
`define AND 6'b100100
`define OR 6'b100101
`define JR 6'b001000
`define SLT 6'b101010
`define SLTU 6'b101011
`define SYSCALL 6'b001100

`define MULT 6'b011000///
`define MULTU 6'b011001///
`define DIV 6'b011010
`define DIVU 6'b011011///

`define MFHI 6'b010000///
`define MTHI 6'b010001///
`define MFLO 6'b010010///
`define MTLO 6'b010011///
/////////
`define ADDI 6'b001000
`define ANDI 6'b001100
`define ORI 6'b001101
`define LUI 6'b001111

`define JAL 6'b000011

`define SB 6'b101000///
`define SH 6'b101001///
`define SW 6'b101011

`define LB 6'b100000///
`define LH 6'b100001///
`define LW 6'b100011
`define LBU 6'b100100///
`define LHU 6'b100101///



`define BEQ 6'b000100
`define BNE 6'b000101///
`define FUNC0 6'b000000

`define NOP 6'b000000
///////////////////////////COP0 6'b010000
`define COP0 6'b010000\
//5:0
`define ERET 6'b011000

//25:21
`define MFC0 5'b00000
`define MTC0 5'b00100


/////////////////////////////
`define Int 5'b00000//0
`define AdEL 5'b00100//4
`define AdES 5'b00101//5
`define Syscall 5'b01000//8
`define RI 5'b01010//10
`define Ov 5'b01100//12
module CTRL (
input [5:0] opcode,
input [5:0] func,
input [31:0] instr,
output reg regwrite,
output reg [1:0] regwritedst,
output reg alusrc,
output reg [3:0] memwrite,
output reg [3:0] memtoreg,
output reg [1:0] extop,
output reg [3:0] aluop,



output reg beq_if,
output reg bne_if,
output reg j_if,
output reg jr_if,
output reg jal_if,
output reg[4:0] EXCcodeD,
output eret_if,
output reg mtc0_if,
output reg mfc0_if
);
//EXER
assign eret_if=(opcode===`COP0&&func===`ERET)?1'b1:1'b0;
always @(*) begin
EXCcodeD=`Int;
mtc0_if=0;
mfc0_if=0;
if (instr == 32'b0) begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} = {1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00; //unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end else begin
case (opcode)
`OPCODE0:
case (func)
`ADD: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0000;
end
`SUB: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0001;
end
`AND: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`OR: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0101;
end
`JR: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b1,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`SLT: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0110;
end
`SLTU: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0111;
end

`MFHI: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`MFLO: begin
{regwrite , regwritedst} = {1'b1,2'b01};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`MTHI: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`MTLO: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end

`MULT: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`MULTU: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`DIV: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`DIVU: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`SYSCALL: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
EXCcodeD=`Syscall;

end
default: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
EXCcodeD=`RI;
end
endcase
`COP0: begin
case (func)
`ERET: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
default: begin
if(instr[25:21]==`MTC0) begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
mtc0_if=1;
end
else if(instr[25:21]==`MFC0) begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
mfc0_if=1;
end
else begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00;
//unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0000;
EXCcodeD= `RI;
end
end
endcase
end
`ANDI: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0100;
end
`ADDI: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`LUI: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b10; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0101;
end
`ORI: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0101;
end
`JAL: begin
{regwrite , regwritedst} = {1'b1,2'b10};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b1,1'b0,1'b0};
extop = 2'b00; //unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`BEQ: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b1,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`BNE: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} = {1'b0,1'b0,1'b0,1'b0,1'b1};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
end
`SW: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b1111,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`SH: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0011,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`SB: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0001,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`LW: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b1111};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`LH: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0011};
{beq_if , j_if , jal_if , jr_if, bne_if} = {1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`LHU: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0011};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`LB: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0001};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
`LBU: begin
{regwrite , regwritedst} = {1'b1,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0001};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b01; //unsigned,signed,lui
alusrc = 1'b1; //grf,imm
aluop = 4'b0000;
end
default: begin
{regwrite , regwritedst} = {1'b0,2'b00};//rt,rd,31
{memwrite , memtoreg} = {4'b0,4'b0};
{beq_if , j_if , jal_if , jr_if, bne_if} =
{1'b0,1'b0,1'b0,1'b0,1'b0};
extop = 2'b00; //unsigned,signed,lui
alusrc = 1'b0; //grf,imm
aluop = 4'b0100;
EXCcodeD =`RI;
end
endcase
end

end
endmodule

各信号注意点:

  • mfc0,mtco位数特殊。

8.HCTRL

端口名 输入\输出 位宽 批注
IR_F Input 31:0 /
IR_D Input 31:0 /
RS_D Input 4:0 /
RT_D Input 4:0 /
RS_E Input 4:0 /
RT_E Input 4:0 /
WA_E Input 4:0 /
WA_M Input 4:0 /
WA_W Input 4:0 /
memtoreg_E Input 1 /
memtoreg_M Input 1 /
regwrite_E Input 1 /
regwrite_M Input 1 /
regwrite_W Input 1 /
memwrite_M Input 1 /
BUSY Input 1 乘除器阻塞
D_CLEAR Output 1 D流水寄存器清空
F_BLOCK Output 1 F流水寄存器保持
PC_BLOCK Output 1 PC保持
rd1_sel Output 1:0 R1_D_IN选择
rd2_sel Output 1:0 R2_D_IN选择
frd1_sel Output 1:0 aluA选择
frd1_sel Output 1:0 aluB选择
memdata_sel Output 1:0 mem写入WD选择
verilog
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
`timescale 1ns / 1ps
`define OPCODE0 6'b000000
`define ADD 6'b100000
`define SUB 6'b100010
`define AND 6'b100100
`define OR 6'b100101
`define JR 6'b001000
`define SLT 6'b101010
`define SLTU 6'b101011
`define SYSCALL 6'b001100

`define MULT 6'b011000///
`define MULTU 6'b011001///
`define DIV 6'b011010
`define DIVU 6'b011011///

`define MFHI 6'b010000///
`define MTHI 6'b010001///
`define MFLO 6'b010010///
`define MTLO 6'b010011///
/////////
`define ADDI 6'b001000
`define ANDI 6'b001100
`define ORI 6'b001101
`define LUI 6'b001111

`define J 6'b000010
`define JAL 6'b000011

`define SB 6'b101000///
`define SH 6'b101001///
`define SW 6'b101011

`define LB 6'b100000///
`define LH 6'b100001///
`define LW 6'b100011
`define LBU 6'b100100///
`define LHU 6'b100101///



`define BEQ 6'b000100
`define BNE 6'b000101///
`define FUNC0 6'b000000

`define NOP 6'b000000
///////////////////////////COP0 6'b010000
`define COP0 6'b010000\
//5:0
`define ERET 6'b011000

//25:21
`define MFC0 5'b00000
`define MTC0 5'b00100
module HCTRL (
input clk,
input [31:0] IR_D,
input [31:0] IR_E,
input [31:0] IR_M,
input [4:0] RS_D,
input [4:0] RT_D,
input [4:0] RS_E,
input [4:0] RT_E,
input [4:0] WA_M,
input [4:0] WA_W,
input [4:0] WA_E,
input [3:0] memtoreg_E,
input [3:0] memtoreg_M,
input regwrite_E,
input regwrite_M,
input regwrite_W,
input BUSY,
input [3:0] memwrite_M,
output reg D_CLEAR,
output reg F_BLOCK,
output reg PC_BLOCK,
output reg [1:0] rd1_sel,
output reg [1:0] rd2_sel,
output reg [1:0] frd1_sel,
output reg [1:0] frd2_sel,
output reg [1:0] memdata_sel

);

reg [31:0] E_T_new;
reg [31:0] M_T_new;
reg [31:0] W_T_new;
reg [31:0] T_use;
wire [5:0] opcode_D;
wire [5:0] func_D;
wire use_less_E_new;
wire use_less_M_new;
wire use_less_W_new;
wire alutype;
wire swtype;
wire lwtype;
wire muldivtype;
wire mftype;
wire mttype;

wire mfc0_D;
wire mfc0_E;
wire mfc0_M;
wire mtc0_D;
wire mtc0_E;
wire mtc0_M;
wire eret;
wire syscall;
wire eret_after_mtc0;

assign alutype=((opcode_D===`OPCODE0)&&(func_D===`ADD||func_D===`SUB||func_D===`AND||func_D===`OR||func_D===`SLT||func_D===`SLTU))||
(opcode_D===`ORI)||(opcode_D===`ADDI)||(opcode_D===`ANDI);

assign swtype = (opcode_D === `SW) || (opcode_D === `SB) || (opcode_D === `SH);
assign lwtype=(opcode_D===`LW)||(opcode_D===`LB)||(opcode_D===`LH)||(opcode_D===`LBU)||(opcode_D===`LHU);

assign muldivtype=((opcode_D===`OPCODE0)&&(func_D===`MULT||func_D===`MULTU||func_D===`DIV||func_D===`DIVU));
assign mftype = ((opcode_D === `OPCODE0) && (func_D === `MFHI || func_D === `MFLO));
assign mttype = ((opcode_D === `OPCODE0) && (func_D === `MTHI || func_D === `MTLO));

assign eret = (opcode_D === `COP0 && func_D === `ERET);
assign syscall = (opcode_D === `OPCODE0 && func_D === `SYSCALL);

assign mfc0_D = (IR_D[31:21] === 11'b010000_00000);
assign mfc0_E = (IR_E[31:21] === 11'b010000_00000);
assign mfc0_M = (IR_M[31:21] === 11'b010000_00000);
assign mtc0_D = (IR_D[31:21] === 11'b010000_00100);
assign mtc0_E = (IR_E[31:21] === 11'b010000_00100);
assign mtc0_M = (IR_M[31:21] === 11'b010000_00100);

assign eret_after_mtc0=( eret && ((IR_E[31:21]===11'b010000_00100&&IR_E[15:11]===5'b01110)||(IR_M[31:21]===11'b010000_00100&&IR_M[15:11]===5'b01110) ) )?1'b1:1'b0;

assign use_less_E_new=((((WA_E==RS_D&&RS_D!==5'b0)||(WA_E==RT_D&&RT_D!==5'b0))&&(regwrite_E)&&(T_use < E_T_new))===1);
assign use_less_M_new=((((WA_M==RS_D&&RS_D!==5'b0)||(WA_M==RT_D&&RT_D!==5'b0))&&(regwrite_M)&&(T_use < M_T_new))===1);
assign use_less_W_new=((((WA_W==RS_D&&RS_D!==5'b0)||(WA_W==RT_D&&RT_D!==5'b0))&&(regwrite_W)&&(T_use < W_T_new))===1);

assign opcode_D = IR_D[31:26];
assign func_D = IR_D[5:0];
always @(*) begin
if (mfc0_E|| ((memtoreg_E===4'b0001||memtoreg_E===4'b0011||memtoreg_E===4'b1111) && regwrite_E) ) begin
E_T_new = 2;
end else if (((memtoreg_E === 4'b0000) && regwrite_E) || mftype === 1) begin
E_T_new = 1;
end else begin
E_T_new = 0;
end

if (mfc0_M||memtoreg_M===4'b0001||memtoreg_M===4'b0011||memtoreg_M===4'b1111) begin
M_T_new = 1;
end else begin
M_T_new = 0;
end
W_T_new = 0;
if (alutype === 1 || muldivtype === 1 || mttype === 1 || lwtype === 1 || swtype === 1) begin
T_use = 1;
end else if (mtc0_D) begin
T_use = 2;
end
else if ( syscall||eret||mfc0_D||opcode_D === `LUI || opcode_D === `J || opcode_D === `JAL || IR_D === 32'b0||mftype===1) begin
T_use = 100;
end else begin
T_use = 0;
end
if (eret_after_mtc0||use_less_E_new || use_less_M_new || use_less_W_new||(BUSY===1&&(muldivtype===1||mftype===1||mttype===1))) begin
PC_BLOCK = 1;
D_CLEAR = 1;
F_BLOCK = 1;
end else begin

PC_BLOCK = 0;
D_CLEAR = 0;
F_BLOCK = 0;
end



if ((M_T_new === 32'b0) && (WA_M == RS_E&& RS_E!==5'b0) && (regwrite_M)) begin
frd1_sel = 1;
end else if ((W_T_new === 32'b0) && (WA_W == RS_E&& RS_E!==5'b0) && (regwrite_W)) begin
frd1_sel = 2;
end else begin
frd1_sel = 0;
end

if ((M_T_new === 32'b0) && (WA_M === RT_E && RT_E!==5'b0) && (regwrite_M)) begin
frd2_sel = 1;
end else if ((W_T_new === 32'b0) && (WA_W === RT_E&& RT_E!==5'b0) && (regwrite_W)) begin
frd2_sel = 2;
end else begin
frd2_sel = 0;
end




if (M_T_new === 32'b0 && (WA_M === RS_D && RS_D !== 5'b0) && regwrite_M) begin
rd1_sel = 0;
end else begin
rd1_sel = 1;
end
if (M_T_new === 32'b0 && (WA_M === RT_D && RT_D !== 5'b0) && regwrite_M) begin
rd2_sel = 0;
end else begin
rd2_sel = 1;
end


if (memwrite_M !== 4'b0000) begin
memdata_sel = 2'b0; //normal 1->grfextrain=>rdextra
end else begin
memdata_sel = 2'b0; //normal
end

end

endmodule

注意mfc0与eret的阻塞。

9.MULDIV

端口名 输入\输出 位宽 批注
clk Input 1 /
reset Input 1 /
req Input 1 异常中断启动(也是m级有异常)
op Input 2:0 功能选择
A Input 31:0 数A
B Input 31:0 数B
inster Input 31:0 机器码
HI_OUT Output 31:0 HI寄存器值
LO_OUT Output 31:0 LO寄存器值
busy Output 1 乘除阻塞

通过count来计数count大于1时将busy置1且count–,当判断为乘除指令时start置1,此时将count初始化,完成周期阻塞。

只有busy为1 ,且判断D级为乘除指令才会阻塞。

verilog
1
2
3
4
5
6
HCTRL:
if (eret_after_mtc0||use_less_E_new || use_less_M_new || use_less_W_new||(BUSY===1&&(muldivtype===1||mftype===1||mttype===1))) begin
PC_BLOCK = 1;
D_CLEAR = 1;
F_BLOCK = 1;
end
verilog
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
`define MULTop      3'b000///
`define MULTUop 3'b001///
`define DIVop 3'b010
`define DIVUop 3'b011///


`define MULT 6'b011000///
`define MULTU 6'b011001///
`define DIV 6'b011010
`define DIVU 6'b011011///


`define MTHI 6'b010001
`define MTLO 6'b010011
`define OPCODE0 6'b000000
module MULDIV (
input [2:0] op,
input clk,
input reset,
input req,
input [31:0] inster,
input [31:0] A,
input [31:0] B,

output [31:0] HI_OUT,
output [31:0] LO_OUT,
output busy
);
reg [31:0] count;
reg [31:0] HI;
reg [31:0] LO;
wire [5:0]opcode;
wire [5:0]func;
wire start;
wire [65:0]bit_66_mult;
wire [65:0]bit_66_multu;
wire [65:0]bit_66_div;
wire [65:0]bit_66_divu;
wire [65:0]bit_66_divmod;
wire [65:0]bit_66_divumod;
assign HI_OUT=HI;
assign LO_OUT=LO;
assign start=(req===1'b1)?1'b0:
(opcode===`OPCODE0)&&((func===`MULT)||(func===`MULTU)||(func===`DIV)||(func===`DIVU));
assign busy=(count>0)?1'b1:1'b0;
assign opcode=inster[31:26];
assign func=inster[5:0];
assign bit_66_mult=$signed(A)*$signed(B);
assign bit_66_multu=A*B;
assign bit_66_div=$signed(A)/$signed(B);
assign bit_66_divu=A/B;
assign bit_66_divmod=$signed(A)%$signed(B);
assign bit_66_divumod=A%B;

always @(posedge clk) begin
if (reset) begin
HI<=32'b0;
LO<=32'b0;
count<=0;

end
else begin
if(count>0) begin
count<=count-1;
end
if (start) begin
case(op)
`MULTop: begin
HI<=bit_66_mult[63:32];
LO<=bit_66_mult[31:0];
count<=6;
end
`MULTUop: begin
HI<=bit_66_multu[63:32];
LO<=bit_66_multu[31:0];
count<=6;
end
`DIVop: begin
HI<=bit_66_divmod[31:0];
LO<=bit_66_div[31:0];
count<=11;
end
`DIVUop: begin
HI<=bit_66_divumod[31:0];
LO<=bit_66_divu[31:0];
count<=11;
end

endcase
end
else if(opcode===`OPCODE0&&func===`MTHI&&!req) begin
HI<=A;
end
else if (opcode===`OPCODE0&&func===`MTLO&&!req) begin
LO<=A;
end
else begin
end
end
end



endmodule

10.LOADEXT

端口名 输入\输出 位宽 批注
memtoreg Input 3:0 /
memwrite Input 3:0 /
ir Input 31:0 机器码
addr Input 31:0 写入地址
memoutdata Input 31:0 内存读取值
memwrite_databyteen Output 3:0 内存写字节控制
extmemoutdata Output 31:0 内存读字节扩展结果
wd_sll Output 1:0 内存写字节移位同步量

因为如sh指令,要写入的始终是reg[15:0],如果只控制写入字节会导致错位

通过移位,使得总是低位的字节写入对应位置内存

verilog
1
assign cpu_data_wdata=(memdata<<(wd_sll*8));

sw 指令:向内存写入对应的字

地址[1:0] m_data_byteen [3:0] 用途
XX 1111 m_data_wdata[31:24] 写入 byte3 m_data_wdata[23:16] 写入 byte2 m_data_wdata[15:8] 写入 byte1 m_data_wdata[7:0] 写入 byte0

sh 指令:向内存写入对应的半字

地址[1:0] m_data_byteen [3:0] 用途
0X 0011 m_data_wdata[15:8] 写入 byte1 m_data_wdata[7:0] 写入 byte0
1X 1100 m_data_wdata[31:24] 写入 byte3 m_data_wdata[23:16] 写入 byte2

sb 指令:向内存写入对应的字节

地址[1:0] m_data_byteen [3:0] 用途
00 0001 m_data_wdata[7:0] 写入 byte0
01 0010 m_data_wdata[15:8] 写入 byte1
10 0100 m_data_wdata[23:16] 写入 byte2
11 1000 m_data_wdata[31:24] 写入 byte3

lw,lh,lb同理,通过(ir[28]===1’b1可以判断是否为无符号读

verilog
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
`define Int         5'b00000//0
`define AdEL 5'b00100//4
`define AdES 5'b00101//5
`define Syscall 5'b01000//8
`define RI 5'b01010//10
`define Ov 5'b01100//12
module LOADEXT (
input [3:0] memtoreg,
input [3:0] memwrite,
input [31:0] ir,
input [31:0] addr,
input [31:0] memoutdata,
output [3:0] memwrite_databyteen,
output [31:0] extmemoutdata,
output [1:0] wd_sll,
output reg [4:0] EXCcodeM
);
always @(*) begin
if(memwrite!=4'b0) begin//store
if( (addr[1:0]!==2'b0&&memwrite===4'b1111)||
(addr[0]!==1'b0&&memwrite===4'b0011)||
(((addr>=32'h7f00&&addr<=32'h7f0b||addr>=32'h7f10&&addr<=32'h7f1b)===1'b1)&&(memwrite===4'b0011||memwrite===4'b0001))||
(((addr>=32'h7f08&&addr<=32'h7f0b||addr>=32'h7f18&&addr<=32'h7f1b)===1'b1)&&memwrite!==4'b0000)||
(( !((addr>=32'h7f00&&addr<=32'h7f0b||addr>=32'h7f10&&addr<=32'h7f1b||addr>=32'h7f20&&addr<=32'h7f23||addr>=32'h0000&&addr<=32'h2fff)===1'b1) )&&memwrite!==4'b0000)
) begin
EXCcodeM=`AdES;
end
else begin
EXCcodeM=`Int;
end
end
else if(memtoreg!=4'b0)begin//load
if( (addr[1:0]!==2'b0&&memtoreg===4'b1111)||
(addr[0]!==1'b0&&memtoreg===4'b0011)||
(((addr>=32'h7f00&&addr<=32'h7f0b||addr>=32'h7f10&&addr<=32'h7f1b)===1'b1)&&(memtoreg===4'b0011||memtoreg===4'b0001))||
((!((addr>=32'h7f00&&addr<=32'h7f0b||addr>=32'h7f10&&addr<=32'h7f1b||addr>=32'h7f20&&addr<=32'h7f23||addr>=32'h0000&&addr<=32'h2fff)===1'b1) )&&memtoreg!==4'b0000)
) begin
EXCcodeM=`AdEL;
end
else begin
EXCcodeM=`Int;
end
end
else begin
EXCcodeM=`Int;
end
end


wire [3:0] memtoreg_databyteen;
assign memtoreg_databyteen=(memtoreg === 4'b1111) ? {4'b1111} :
(memtoreg === 4'b0011) ? {4'b0011<<{addr[1],1'b0}} :
(memtoreg === 4'b0001) ? {4'b0001<<addr[1:0]} :4'b0000;
assign memwrite_databyteen=(memwrite === 4'b1111) ? {4'b1111} :
(memwrite === 4'b0011) ? {4'b0011<<{addr[1],1'b0}} :
(memwrite === 4'b0001) ? {4'b0001<<addr[1:0]} :4'b0000;
assign wd_sll=(memwrite === 4'b1111) ? 2'b0 :
(memwrite === 4'b0011) ? {addr[1],1'b0} :
(memwrite === 4'b0001) ? addr[1:0] :2'b0;
assign extmemoutdata = (memtoreg_databyteen === 4'b1111) ? {memoutdata} :
(memtoreg_databyteen === 4'b0011) ? ((ir[28]===1'b1)?{16'b0,memoutdata[15:0]}:{{16{memoutdata[15]}},memoutdata[15:0]}):
(memtoreg_databyteen === 4'b1100) ? ((ir[28]===1'b1)?{16'b0,memoutdata[31:16]}:{{16{memoutdata[31]}},memoutdata[31:16]}) :
(memtoreg_databyteen === 4'b0001) ? ((ir[28]===1'b1)?{24'b0,memoutdata[7:0]}:{{24{memoutdata[7]}},memoutdata[7:0]} ):
(memtoreg_databyteen === 4'b0010) ? ((ir[28]===1'b1)?{24'b0,memoutdata[15:8]}:{{24{memoutdata[15]}},memoutdata[15:8]} ) :
(memtoreg_databyteen === 4'b0100) ? ((ir[28]===1'b1)?{24'b0,memoutdata[23:16]}:{{24{memoutdata[23]}},memoutdata[23:16]} ) :
(memtoreg_databyteen === 4'b1000) ? ((ir[28]===1'b1)?{24'b0,memoutdata[31:24]}:{{24{memoutdata[31]}},memoutdata[31:24]} ) : {32'b0};
endmodule

11.流水线REG

F:

verilog
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
`timescale 1ns / 1ps

module F_REG (
input clk,
input reset,
input BLOCK,
input req,
input [31:0]EPC,
input eret_if,
input [4:0]EXCcodeF_Freg_IN,
output [4:0]EXCcodeF_Freg_OUT,
input BD_F_IN,
input [31:0] PC_F_IN,
input [31:0] IR_F_IN,
output BD_F_OUT,
output [31:0] PC_F_OUT,
output [31:0] IR_F_OUT

);
reg BD_F;
reg [31:0] PC_F;
reg [31:0] IR_F;
reg [4:0]EXCcodeF_Freg;
assign PC_F_OUT = PC_F;
assign IR_F_OUT = IR_F;
assign BD_F_OUT=BD_F;

assign EXCcodeF_Freg_OUT = EXCcodeF_Freg;

always @(posedge clk) begin
if (reset) begin
PC_F <= 32'h00003000;
IR_F <= 32'b0;
BD_F <= 1'b0;
EXCcodeF_Freg <= 5'b0;
end else begin
if(req) begin
PC_F <= 32'h00004180;
IR_F <= 32'b0;
BD_F <= 1'b0;
EXCcodeF_Freg <= 5'b0;
end
else if(eret_if&&!BLOCK) begin
PC_F <= EPC;
IR_F <= 32'b0;
BD_F <= BD_F;
EXCcodeF_Freg <= 5'b0;
end
else if (BLOCK) begin
PC_F <= PC_F;
IR_F <= IR_F;
BD_F <= BD_F;
EXCcodeF_Freg <= EXCcodeF_Freg;
end else begin
PC_F <= PC_F_IN;
IR_F <= IR_F_IN;
BD_F <= BD_F_IN;
EXCcodeF_Freg <= EXCcodeF_Freg_IN;
end
end
end
endmodule

D:

verilog
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
`timescale 1ns / 1ps

module D_REG (
input clk,
input reset,
input D_CLEAR,
input req,
input [31:0]EPC,
input EXLClr,
input BD_D_IN,
output BD_D_OUT,
input [31:0] PC_D_IN,
input [31:0] IR_D_IN,
input [31:0] R1_D_IN,
input [31:0] R2_D_IN,

output [31:0] PC_D_OUT,
output [31:0] R1_D_OUT,
output [31:0] R2_D_OUT,
output [31:0] IR_D_OUT,

input [4:0]EXCcodeF_Dreg_IN,
output [4:0]EXCcodeF_Dreg_OUT,
input [4:0]EXCcodeD_Dreg_IN,
output [4:0]EXCcodeD_Dreg_OUT,


input regwrite,
input [1:0] regwritedst,
input alusrc,
input [3:0] memwrite,
input [3:0] memtoreg,
input [3:0] aluop,
input jal_if,
input mtc0_if,
input mfc0_if,
input [31:0] IMM_D_IN,

output [3:0] memtoreg_E,
output regwrite_E,
output [1:0] regwritedst_E,
output [3:0] memwrite_E,
output alusrc_E,
output [3:0] aluop_E,
output jal_if_E,
output mfc0_if_E,
output mtc0_if_E,
output [31:0] IMM_D_OUT

);
reg [4:0]EXCcodeF_Dreg;
reg [4:0]EXCcodeD_Dreg;
reg BD_D;

reg [31:0] PC_D;
reg [31:0] R1_D;
reg [31:0] R2_D;
reg [31:0] IR_D;
reg [31:0] IMM_D;
reg regwritereg;
reg [1:0] regwritedstreg;
reg alusrcreg;
reg [3:0]memwritereg;
reg [3:0] memtoregreg;
reg [3:0] aluopreg;
reg jal_ifreg;
reg mtc0_ifreg;
reg mfc0_ifreg;

assign EXCcodeF_Dreg_OUT=EXCcodeF_Dreg;
assign EXCcodeD_Dreg_OUT=EXCcodeD_Dreg;
assign BD_D_OUT=BD_D;

assign PC_D_OUT = PC_D;
assign R1_D_OUT = R1_D;
assign R2_D_OUT = R2_D;
assign IR_D_OUT = IR_D;
assign IMM_D_OUT = IMM_D;
assign regwrite_E = regwritereg;
assign regwritedst_E = regwritedstreg;
assign memtoreg_E = memtoregreg;
assign memwrite_E = memwritereg;
assign alusrc_E = alusrcreg;
assign aluop_E = aluopreg;
assign jal_if_E = jal_ifreg;
assign mtc0_if_E =mtc0_ifreg;
assign mfc0_if_E =mfc0_ifreg;
always @(posedge clk) begin
if (reset) begin
EXCcodeF_Dreg<=5'b0;
EXCcodeD_Dreg<=5'b0;
mfc0_ifreg<=1'b0;
mtc0_ifreg<=1'b0;
PC_D <= 32'h00003000;
BD_D <= 1'b0;
R1_D <= 32'b0;
R2_D <= 32'b0;
IR_D <= 32'b0;
IMM_D <= 32'b0;
jal_ifreg <= 0;
regwritereg <= 0;
regwritedstreg <= 2'b0;
alusrcreg <= 0;
memwritereg <= 4'b0;
memtoregreg <= 4'b0;
aluopreg <= 4'b0;
end else begin
if(req) begin
EXCcodeF_Dreg<=5'b0;
EXCcodeD_Dreg<=5'b0;
mfc0_ifreg<=1'b0;
mtc0_ifreg<=1'b0;
PC_D <= 32'h00004180;
BD_D <= 1'b0;
R1_D <= 32'b0;
R2_D <= 32'b0;
IR_D <= 32'b0;
IMM_D <= 32'b0;
jal_ifreg <= 0;
regwritereg <= 1'b0;
regwritedstreg <= 2'b0;
alusrcreg <= 0;
memwritereg <= 4'b0;
memtoregreg <= 4'b0;
aluopreg <= 4'b0;
end

else if (D_CLEAR) begin
EXCcodeF_Dreg<=5'b0;
EXCcodeD_Dreg<=5'b0;
mfc0_ifreg<=1'b0;
mtc0_ifreg<=1'b0;
PC_D <= PC_D_IN;//////
BD_D <= BD_D_IN;//////
R1_D <= 32'b0;
R2_D <= 32'b0;
IR_D <= 32'b0;
IMM_D <= 32'b0;
jal_ifreg <= 0;
regwritereg <= 1'b0;
regwritedstreg <= 2'b0;
alusrcreg <= 0;
memwritereg <= 4'b0;
memtoregreg <= 4'b0;
aluopreg <= 4'b0;
end
else begin
EXCcodeF_Dreg<=EXCcodeF_Dreg_IN;
EXCcodeD_Dreg<=EXCcodeD_Dreg_IN;
mfc0_ifreg<=mfc0_if;
mtc0_ifreg<=mtc0_if;
PC_D <= PC_D_IN;
BD_D <= BD_D_IN;
IR_D <= IR_D_IN;
R1_D <= R1_D_IN;
R2_D <= R2_D_IN;
IMM_D <= IMM_D_IN;
jal_ifreg <= jal_if;
regwritereg <= regwrite;
regwritedstreg <= regwritedst;
alusrcreg <= alusrc;
memwritereg <= memwrite;
memtoregreg <= memtoreg;
aluopreg <= aluop;
end
end
end
endmodule

E:

verilog
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
`timescale 1ns / 1ps

module E_REG (
input clk,
input reset,
input req,
input [31:0]EPC,
input EXLClr,
input BD_E_IN,
output BD_E_OUT,
input [31:0] PC_E_IN,
input [31:0] AO_E_IN,
input [31:0] WD_E_IN,
input [4:0] WA_E_IN,
input [31:0] IR_E_IN,
output [31:0] PC_E_OUT,
output [31:0] AO_E_OUT,
output [31:0] WD_E_OUT,
output [4:0] WA_E_OUT,
output [31:0] IR_E_OUT,

input [4:0]EXCcodeF_Ereg_IN,
output [4:0]EXCcodeF_Ereg_OUT,
input [4:0]EXCcodeD_Ereg_IN,
output [4:0]EXCcodeD_Ereg_OUT,
input [4:0]EXCcodeE_Ereg_IN,
output [4:0]EXCcodeE_Ereg_OUT,

input regwrite,
input [3:0] memwrite,
input [3:0] memtoreg,

output [3:0] memtoreg_M,
output regwrite_M,
output [3:0] memwrite_M,

input mtc0_if_E,
input mfc0_if_E,
output mfc0_if_M,
output mtc0_if_M

);
reg [4:0]EXCcodeF_Ereg;
reg [4:0]EXCcodeD_Ereg;
reg [4:0]EXCcodeE_Ereg;
reg mtc0_if_Ereg;
reg mfc0_if_Ereg;

reg BD_E;

reg [31:0] PC_E;
reg [31:0] AO_E;
reg [31:0] WD_E;
reg [4:0] WA_E;
reg [31:0] IR_E;
reg regwritereg;
reg [3:0] memtoregreg;
reg [3:0] memwritereg;
assign PC_E_OUT = PC_E;
assign AO_E_OUT = AO_E;
assign WD_E_OUT = WD_E;
assign WA_E_OUT = WA_E;
assign IR_E_OUT = IR_E;
assign memtoreg_M = memtoregreg;
assign memwrite_M = memwritereg;
assign regwrite_M = regwritereg;

assign EXCcodeF_Ereg_OUT=EXCcodeF_Ereg;
assign EXCcodeD_Ereg_OUT=EXCcodeD_Ereg;
assign EXCcodeE_Ereg_OUT=EXCcodeE_Ereg;
assign mfc0_if_M=mfc0_if_Ereg;
assign mtc0_if_M=mtc0_if_Ereg;

assign BD_E_OUT=BD_E;


always @(posedge clk) begin
if (reset) begin
EXCcodeF_Ereg<=5'b0;
EXCcodeD_Ereg<=5'b0;
EXCcodeE_Ereg<=5'b0;
mfc0_if_Ereg<=1'b0;
mtc0_if_Ereg<=1'b0;
PC_E <= 32'h00003000;
BD_E <= 1'b0;
WD_E <= 32'b0;
WA_E <= 5'b0;
IR_E <= 32'b0;
memtoregreg <= 4'b0;
memwritereg <= 4'b0;
regwritereg <= 0;
end else begin
if(req) begin
EXCcodeF_Ereg<=5'b0;
EXCcodeD_Ereg<=5'b0;
EXCcodeE_Ereg<=5'b0;
mfc0_if_Ereg<=1'b0;
mtc0_if_Ereg<=1'b0;
PC_E <= 32'h00004180;
BD_E <= 1'b0;
WD_E <= 32'b0;
WA_E <= 5'b0;
IR_E <= 32'b0;
memtoregreg <= 4'b0;
memwritereg <= 4'b0;
regwritereg <= 0;
end
else begin


EXCcodeF_Ereg<=EXCcodeF_Ereg_IN;
EXCcodeD_Ereg<=EXCcodeD_Ereg_IN;
EXCcodeE_Ereg<=EXCcodeE_Ereg_IN;

mfc0_if_Ereg<=mfc0_if_E;
mtc0_if_Ereg<=mtc0_if_E;

PC_E <= PC_E_IN;
BD_E <= BD_E_IN;
AO_E <= AO_E_IN;
WD_E <= WD_E_IN;
WA_E <= WA_E_IN;
IR_E <= IR_E_IN;
memtoregreg <= memtoreg;
memwritereg <= memwrite;
regwritereg <= regwrite;
end


end

end
endmodule

M:

verilog
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
`timescale 1ns / 1ps

module M_REG (
input clk,
input reset,
input req,
input [31:0] PC_M_IN,
input [31:0] AO_M_IN,
input [31:0] MD_M_IN,
input [4:0] WA_M_IN,
output [31:0] AO_M_OUT,
output [31:0] MD_M_OUT,
output [4:0] WA_M_OUT,
output [31:0] PC_M_OUT,

input regwrite,
input [3:0] memtoreg,

output [3:0] memtoreg_W,
output regwrite_W

);
reg [31:0] AO_M;
reg [31:0] MD_M;
reg [4:0] WA_M;
reg [31:0] PC_M;
reg regwritereg;
reg [3:0] memtoregreg;
assign AO_M_OUT = AO_M;
assign MD_M_OUT = MD_M;
assign WA_M_OUT = WA_M;
assign PC_M_OUT = PC_M;
assign regwrite_W = regwritereg;
assign memtoreg_W = memtoregreg;
always @(posedge clk) begin
if (reset) begin
AO_M <= 32'b0;
MD_M <= 32'b0;
WA_M <= 5'b0;
PC_M <= 32'h00003000;
regwritereg <= 0;
memtoregreg <= 4'b0;
end else begin
if(req) begin
AO_M <= 32'b0;
MD_M <= 32'b0;
WA_M <= 5'b0;
PC_M <= 32'h00004180;
regwritereg <= 1'b0;
memtoregreg <= 4'b0;
end
else begin

AO_M <= AO_M_IN;
MD_M <= MD_M_IN;
WA_M <= WA_M_IN;
PC_M <= PC_M_IN;
regwritereg <= regwrite;
memtoregreg <= memtoreg;
end

end
end
endmodule

注意一下特殊的清空或者阻塞reqeret_if信号即可。

12.CPU

x_D_IN表示一个名为x的信号,IN表示输入,D表示输入的流水线寄存器

x_E 表示一个名为x的信号,处于E时期,可能为D_OUT或者E_IN。

M_REG表示其前一阶段为M阶段。

转发表:

供给者序号\需求者 D级grf的输出 E级alu的输入 M级mem的内存写入数据WD
0 AO_E_OUT r1_D_OUT/r2_D_OUT WD_E_OUT
1 rd1/rd2 AO_E_OUT realgrfdata(真实值)
2 / grfwritedata(包括memout和AO_M_OUT) /

mux暂时不用,改为assign选择。

MUX选择信号表:

序号 \ 需求者/控制信号 aluB/alusrc AO_E_IN/jal_if WA_E_IN/regdst_E grfwritedata/memtoreg_W
0 转发后的rd2 aluresult rt AO_M_OUT(alu结果)
1 imm pc+8(jal使用0) rd MD_M_OUT(内存读取)
2 / LO/HI(由指令判断在jal_if前) 31 /

MFC0通过M级选择输出AO_M_IN实现。

非重要信号不列出选择,详见下方。

verilog
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
//////////////////////
`define MFHI 6'b010000///
`define MTHI 6'b010001///
`define MFLO 6'b010010///
`define MTLO 6'b010011///
`define OPCODE0 6'b000000///

`define Int 5'b00000//0
`define AdEL 5'b00100//4
`define AdES 5'b00101//5
`define Syscall 5'b01000//8
`define RI 5'b01010//10
`define Ov 5'b01100//12
module CPU(
input clk,
input reset,

input req,
input [31:0] EPC,
input [31:0] CP0outdata,
output [31:0] CP0indata,
output CP0en,
output [4:0] CP0addr,
output BD_IN,
output EXLClr,




output [31:0] M_PC,
output [4:0] EXCcodeE_M,
output [4:0] EXCcodeD_M,
output [4:0] EXCcodeF_M,
output [4:0] EXCcodeM_M,

/////////////////////////////////////////IM
output [31:0] i_inst_addr,//pc
input [31:0] i_inst_rdata,//inster
///////////////////////////////////////////DATA
output [31:0] cpu_data_addr,
output [31:0] cpu_data_wdata,
output [3 :0] cpu_data_byteen,
output [31:0] cpu_inst_addr,
input [31:0] cpu_data_rdata,
////////////////////////////////////////////grf
output w_grf_we,
output [4:0] w_grf_addr,
output [31:0] w_grf_wdata,
output [31:0] w_inst_addr

);
///////////////////////////////////////////////WIRE
wire d_clear;
wire f_block;
wire pc_block;
wire [1:0] rd1_sel;
wire [1:0] rd2_sel;
wire [1:0] frd1_sel;
wire [1:0] frd2_sel;
wire [31:0] pc_NPC_IM;//
wire [31:0] ir_IM_F;//
wire [31:0] pc_F_OUT;//
wire [31:0] ir_F_OUT;//
wire [31:0] r1_D_IN;
wire [31:0] r2_D_IN;
wire [31:0] rd1;
wire [31:0] rd2;
wire [3:0] memwrite;
wire [3:0]memtoreg;
wire regwrite;
wire [1:0] regwritedst;
wire alusrc;

wire beq_if;
wire bne_if;
wire j_if;
wire jr_if;
wire jal_if;
wire eret_if;

wire [1:0] extop;
wire [3:0] aluop;

wire [31:0] extresult;

wire [31:0] imm_D_OUT;
wire [31:0] pc_D_OUT;
wire [31:0] r1_D_OUT;
wire [31:0] r2_D_OUT;
wire [31:0] ir_D_OUT;
wire [3:0] aluop_E;
wire [3:0] memwrite_E;
wire [3:0]memtoreg_E;
wire regwrite_E;
wire [1:0] regwritedst_E;
wire alusrc_E;
wire beq_judge;
wire bne_judge;
wire jal_if_E;

wire [31:0] aluA;
wire [31:0] aluB;
wire overflow;
wire [31:0] aluresult;

wire [31:0] ao_E_IN;
wire [3:0] memwrite_M;
wire [3:0]memtoreg_M;
wire regwrite_M;

wire [31:0] wd_E_IN;
wire [4:0] wa_E_IN;
wire [31:0] pc_E_OUT;
wire [31:0] ao_E_OUT;
wire [31:0] wd_E_OUT;
wire [4:0] wa_E_OUT;


wire [31:0] memoutdata;
wire [31:0] extmemoutdata;

wire [3:0]memtoreg_W;
wire regwrite_W;

wire [31:0] md_M_OUT;
wire [31:0] md_M_IN;
wire [31:0] ao_M_IN;
wire [31:0] ao_M_OUT;
wire [4:0] wa_M_OUT;

wire [31:0] pc_M_OUT;

wire [31:0] grfdata;

wire [31:0]memdata;
wire [1:0]memdata_sel;
wire [31:0]rdextra;
wire [31:0]ir_E_OUT;

wire [3:0]data_byteen_IN;

wire [31:0] HI;
wire [31:0] LO;
wire busy;
wire [1:0] wd_sll;
wire [4:0]grfextrain;


wire [4:0]EXCcodeF_F;
wire [4:0]EXCcodeF_D;
wire [4:0]EXCcodeF_E;
wire [4:0]EXCcodeF_M;

wire [4:0]EXCcodeD_D;
wire [4:0]EXCcodeD_E;
wire [4:0]EXCcodeD_M;

wire [4:0]EXCcodeE_E;
wire [4:0]EXCcodeE_M;

wire [4:0]EXCcodeM_M;

wire mtc0_if;
wire mfc0_if;
wire mtc0_if_E;
wire mfc0_if_E;
wire mtc0_if_M;
wire mfc0_if_M;

wire BD_F;
wire BD_D;
wire BD_E;
wire BD_M;

//////IM
assign i_inst_addr=pc_NPC_IM;
assign ir_IM_F=i_inst_rdata;
//////DATA
assign cpu_inst_addr=pc_E_OUT;
assign cpu_data_addr=ao_E_OUT;
assign cpu_data_byteen=(req===1'b1)?4'b0:data_byteen_IN;////////
assign cpu_data_wdata=(memdata<<(wd_sll*8));
assign memoutdata=cpu_data_rdata;

/////GRF
assign w_grf_we=regwrite_W;
assign w_grf_addr=wa_M_OUT;
assign w_grf_wdata=grfdata;
assign w_inst_addr=pc_M_OUT;

////////////////////////////////////////////////////MUX_F

assign r1_D_IN=(rd1_sel===2'b00)?((wa_E_OUT===5'b0)?32'b0:ao_E_OUT):rd1;
assign r2_D_IN=(rd2_sel===2'b00)?((wa_E_OUT===5'b0)?32'b0:ao_E_OUT):rd2;

assign beq_judge=(beq_if&&(r1_D_IN==r2_D_IN))?1'b1:1'b0;
assign bne_judge=(bne_if&&(r1_D_IN!=r2_D_IN))?1'b1:1'b0;

////////////////////////////////////////////////////MUX_D

assign aluA=(ir_D_OUT[25:21]===5'b0)?(32'b0):((frd1_sel===2'b00)?r1_D_OUT:
(frd1_sel===2'b01)?ao_E_OUT:grfdata);
assign aluB=(alusrc_E===1'b0)?((ir_D_OUT[20:16]===5'b0)?32'b0:(frd2_sel===2'b00)?r2_D_OUT:
(frd2_sel===2'b01)?ao_E_OUT:grfdata):(imm_D_OUT);
////////////////////////////////////////////////////MUX_E

assign ao_E_IN=(ir_D_OUT[31:26]===`OPCODE0&&ir_D_OUT[5:0]===`MFHI)?HI:
(ir_D_OUT[31:26]===`OPCODE0&&ir_D_OUT[5:0]===`MFLO)?LO:
((jal_if_E===1'b1)?(pc_D_OUT+8):aluresult);//pc+8
assign wd_E_IN=(ir_D_OUT[20:16]===5'b0)?32'b0:(frd2_sel===2'b00)?r2_D_OUT:
(frd2_sel===2'b01)?ao_E_OUT:grfdata;
assign wa_E_IN=(regwritedst_E===2'b00)?ir_D_OUT[20:16]:
(regwritedst_E===2'b01)?ir_D_OUT[15:11]:5'b11111;

////////////////////////////////////////////////////MUX_M

assign memdata=(memdata_sel===2'b00)?(wd_E_OUT):
rdextra;
assign md_M_IN=extmemoutdata;
assign grfextrain=ir_E_OUT[20:16];//rt
assign grfdata=(memtoreg_W===4'b0)?ao_M_OUT:md_M_OUT;
assign ao_M_IN=(mfc0_if_M)?CP0outdata:ao_E_OUT;


assign M_PC=pc_E_OUT;
assign BD_IN=BD_M;
assign BD_F=(j_if||jal_if||jr_if||beq_if||bne_if)?1'b1:1'b0;
assign CP0en=(mtc0_if_M===1)?1'b1:1'b0;
assign CP0addr=(ir_E_OUT[15:11]);
assign CP0indata=rdextra;
assign EXLClr=(ir_E_OUT===32'b010000_1000_0000_0000_0000_0000_011000)?1'b1:1'b0;

////////////////////////////////////////////////////MUX_W
HCTRL hctrl(
.clk(clk),//
.IR_D(ir_F_OUT),
.IR_E(ir_D_OUT),//
.IR_M(ir_E_OUT),
.D_CLEAR(d_clear),//
.F_BLOCK(f_block),//
.PC_BLOCK(pc_block),//
.BUSY(busy),
.RS_D(ir_F_OUT[25:21]),//
.RT_D(ir_F_OUT[20:16]),//
.RS_E(ir_D_OUT[25:21]),//
.RT_E(ir_D_OUT[20:16]),//
.WA_M(wa_E_OUT),//
.WA_W(wa_M_OUT),//
.WA_E(wa_E_IN),//
.memtoreg_E(memtoreg_E),//
.memtoreg_M(memtoreg_M),//
.regwrite_E(regwrite_E),//
.regwrite_M(regwrite_M),//
.regwrite_W(regwrite_W),//
.memwrite_M(memwrite_M),


.rd1_sel(rd1_sel),
.rd2_sel(rd2_sel),
.frd1_sel(frd1_sel),
.frd2_sel(frd2_sel),
.memdata_sel(memdata_sel)
);
///////////////////////////////////F
NPC npc (
.clk(clk), //
.reset(reset), //
.req(req),
.NPC(pc_NPC_IM), //
.PC_D(pc_F_OUT),//
.block(pc_block),//
.beq_judge(beq_judge),
.bne_judge(bne_judge), //
.j_if(j_if), //
.jr_if(jr_if),//
.jal_if(jal_if), //
.eret_if(eret_if),

.EPC(EPC),
.EXCcodeF(EXCcodeF_F),
.imm(extresult), //
.j_addr(ir_F_OUT[25:0]), //
.jr_addr(r1_D_IN)//
);
F_REG f_reg (
.clk(clk), //
.reset(reset), //
.BLOCK(f_block), //
.req(req),
.EPC(EPC),
.eret_if(eret_if),
.PC_F_IN(pc_NPC_IM), //
.IR_F_IN((EXCcodeF_F!==`Int)?32'b0:ir_IM_F), //
.PC_F_OUT(pc_F_OUT), //
.EXCcodeF_Freg_IN(EXCcodeF_F),
.EXCcodeF_Freg_OUT(EXCcodeF_D),
.IR_F_OUT(ir_F_OUT),//
.BD_F_IN(BD_F),
.BD_F_OUT(BD_D)
);
////////////////////////////////////D
GRF grf (
.clk(clk), //
.reset(reset), //
.PC(pc_M_OUT), //
.WE(regwrite_W), //
.A1(ir_F_OUT[25:21]), //RS
.A2(ir_F_OUT[20:16]), //RT
.A3(wa_M_OUT),
.EXTRA(grfextrain), //
.WD(grfdata), //
.RD1(rd1), //
.RD2(rd2),
.RDEXTRA(rdextra) //
);

CTRL ctrl (
.instr(ir_F_OUT),//
.opcode(ir_F_OUT[31:26]),//
.func(ir_F_OUT[5:0]),//

.regwrite(regwrite),//
.regwritedst(regwritedst),//
.alusrc(alusrc),//
.memwrite(memwrite),//
.memtoreg(memtoreg),//
.beq_if(beq_if),//
.bne_if(bne_if),
.j_if(j_if),//
.jr_if(jr_if),//
.jal_if(jal_if),//
.eret_if(eret_if),
.mtc0_if(mtc0_if),
.mfc0_if(mfc0_if),
.EXCcodeD(EXCcodeD_D),
.extop(extop),//
.aluop(aluop)//
);
EXT ext (
.extop(extop), //
.imm(ir_F_OUT[15:0]), //
.extresult(extresult) //
);
D_REG d_reg (
.clk(clk), //
.reset(reset), //
.D_CLEAR(d_clear), //
.req(req),
.EPC(EPC),
.EXLClr(EXLClr),
.regwrite(regwrite),//
.regwritedst(regwritedst),//
.alusrc(alusrc),//
.memwrite(memwrite),//
.memtoreg(memtoreg),//
.aluop(aluop),//
.jal_if(jal_if),//
.mtc0_if(mtc0_if),
.mfc0_if(mfc0_if),

.regwritedst_E(regwritedst_E),//
.alusrc_E(alusrc_E),//
.memwrite_E(memwrite_E),//
.memtoreg_E(memtoreg_E),//
.regwrite_E(regwrite_E),//
.aluop_E(aluop_E),//
.jal_if_E(jal_if_E),
.mtc0_if_E(mtc0_if_E),
.mfc0_if_E(mfc0_if_E),

.PC_D_IN(pc_F_OUT), //
.IR_D_IN((EXCcodeD_D===`RI)?32'b0:ir_F_OUT), //
.IMM_D_IN(extresult),//
.R1_D_IN(r1_D_IN), //
.R2_D_IN(r2_D_IN), //

.IMM_D_OUT(imm_D_OUT),//
.PC_D_OUT(pc_D_OUT), //
.R1_D_OUT(r1_D_OUT), //
.R2_D_OUT(r2_D_OUT), //
.IR_D_OUT(ir_D_OUT),//

.EXCcodeF_Dreg_IN(EXCcodeF_D),
.EXCcodeF_Dreg_OUT(EXCcodeF_E),
.EXCcodeD_Dreg_IN(EXCcodeD_D),
.EXCcodeD_Dreg_OUT(EXCcodeD_E),
.BD_D_IN(BD_D),
.BD_D_OUT(BD_E)

);
////////////////////////////////////E
ALU alu (
.aluop(aluop_E), //
.A(aluA), //
.B(aluB), //
.result(aluresult),
.load_if(memtoreg_E),
.store_if(memwrite_E),
.regwrite_if(regwrite_E),
.ir_E(ir_D_OUT),
.EXCcodeE(EXCcodeE_E), //
.overflow(overflow) //
);
MULDIV muldiv(
.clk(clk),//
.reset(reset),//
.req(req),
.op(ir_D_OUT[2:0]),//
.inster(ir_D_OUT),//
.A(aluA),//
.B(aluB),//
.HI_OUT(HI),
.LO_OUT(LO),
.busy(busy)
);


E_REG e_reg (
.clk(clk), //
.reset(reset), //
.req(req),
.EXLClr(EXLClr),
.EPC(EPC),
.IR_E_IN(ir_D_OUT),
.IR_E_OUT(ir_E_OUT),

.memwrite((EXCcodeE_E===`AdES)?4'b0:memwrite_E),//!!!!
.memtoreg((EXCcodeE_E===`AdEL)?4'b0:memtoreg_E),//
.regwrite((EXCcodeE_E===`Ov||EXCcodeE_E===`AdEL)?1'b0:regwrite_E),//

.memwrite_M(memwrite_M),//
.memtoreg_M(memtoreg_M),//
.regwrite_M(regwrite_M),//

.PC_E_IN(pc_D_OUT), //
.AO_E_IN(ao_E_IN), //
.WD_E_IN(wd_E_IN), //
.WA_E_IN(wa_E_IN), //
.PC_E_OUT(pc_E_OUT), //
.AO_E_OUT(ao_E_OUT), //
.WD_E_OUT(wd_E_OUT), //
.WA_E_OUT(wa_E_OUT),//

.EXCcodeF_Ereg_IN(EXCcodeF_E),
.EXCcodeF_Ereg_OUT(EXCcodeF_M),
.EXCcodeD_Ereg_IN(EXCcodeD_E),
.EXCcodeD_Ereg_OUT(EXCcodeD_M),
.EXCcodeE_Ereg_IN(EXCcodeE_E),
.EXCcodeE_Ereg_OUT(EXCcodeE_M),
.mtc0_if_E(mtc0_if_E),
.mfc0_if_E(mfc0_if_E),
.mtc0_if_M(mtc0_if_M),
.mfc0_if_M(mfc0_if_M),
.BD_E_IN(BD_E),
.BD_E_OUT(BD_M)

);
/////////////////////////////////M

LOADEXT loadext (
.ir(ir_E_OUT),
.addr(ao_E_OUT),
.memtoreg(memtoreg_M),
.memwrite(memwrite_M),
.memoutdata(memoutdata),
.memwrite_databyteen(data_byteen_IN),
.extmemoutdata(extmemoutdata),
.wd_sll(wd_sll),
.EXCcodeM(EXCcodeM_M)
);
M_REG m_reg (
.clk(clk), //
.reset(reset), //
.req(req),

.memtoreg((EXCcodeM_M===`AdEL)?1'b0:memtoreg_M),//
.regwrite((EXCcodeM_M===`AdEL)?1'b0:regwrite_M),//

.memtoreg_W(memtoreg_W),//
.regwrite_W(regwrite_W),//

.AO_M_IN(ao_M_IN), //
.MD_M_IN(md_M_IN), //
.WA_M_IN(wa_E_OUT),//
.PC_M_IN(pc_E_OUT), //
.AO_M_OUT(ao_M_OUT), //
.MD_M_OUT(md_M_OUT), //
.WA_M_OUT(wa_M_OUT),//
.PC_M_OUT(pc_M_OUT)//
);

/////////////////////////////////W

endmodule

原先剩下的留给上机接memdata的其他可能输入。

verilog
1
2
3
4
5
if (memwrite_M!==4'b0000) begin
memdata_sel = 0;//normal 1->grfextrain=>rdextra
end else begin
memdata_sel = 0;//normal
end

对于MULT/MULTU/DIV/DIVU

通过busy信号,阻塞D级的MULT/MULTU/DIV/DIVU/MTHI/MTLO/MFHI/MFLO

乘法周期为5,除法周期为10.

13.CP0

端口 方向 位数 解释
clk IN 1 时钟信号。
reset IN 1 复位信号。
en IN 1 写使能信号。
CP0Add IN 5 读取/写入目标寄存器地址。
CP0In IN 32 写入寄存器数据。
CP0Out OUT 32 读出寄存器数据。
VPC IN 32 当前异常中断发生时PC的值。
BD_IN IN 1 当前异常中断发生指令是否是延迟槽内指令。
ExcCodein IN 5 当前发生异常类型。
HWInt IN 6 外部产生的中断信号。
EXLClr IN 1 是否结束异常中断处理(复位 EXL)。
EPCout OUT 32 EPC 的值。
req OUT 1 进入处理程序请求。
verilog
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
`define Int 5'b00000//0
`define AdEL 5'b00100//4
`define AdES 5'b00101//5
`define Syscall 5'b01000//8
`define RI 5'b01010//10
`define Ov 5'b01100//12

module CP0 (
input clk,
input reset,
input [31:0] VPC,
input BD_IN,
input [4:0] ExcCodein,
input [5:0] HWInt, //外部产生的中断信号
input EXLClr, //是否结束异常中断处理(复位 EXL)
output [31:0] EPCout, //EPC 的值。
output req, //进入处理程序请求。


input en,
input [4:0] CP0addr,
input [31:0] CP0in,
output [31:0] CP0out


);
reg [31:0] SR;
reg req_reg;
reg [31:0] Cause;
reg [31:0] EPC;

wire [5:0] IM; //Interrupt Mask
wire EXL;
wire IE;
wire BD;
wire [5:0] IP;
wire [4:0] ExcCode;
assign IM = SR[15:10];
assign EXL = SR[1];
assign IE = SR[0];
assign BD = Cause[31];
assign IP = Cause[15:10];
assign ExcCode = Cause[6:2];
assign req = req_reg;
assign EPCout = EPC;

assign CP0out = (CP0addr == 12) ? SR : (CP0addr == 13) ? Cause : (CP0addr == 14) ? EPC : 32'b0;
always @(posedge clk) begin
if (reset) begin
SR <= 32'b0;
//SR<=32'b0000_0000_0000_0000_1111_1100_0000_0001;
Cause <= 32'b0;
EPC <= 32'b0;
req_reg <= 1'b0;
end else begin
if (req_reg) begin
Cause[15:10] <= HWInt;
Cause[31] <= BD_IN;
SR[1] <= 1'b1; //exl
if (BD_IN) begin
EPC <= VPC - 4;
end else begin
EPC <= VPC;
end
if(((ExcCodein!==5'b0)&&((HWInt&IM)!==6'b0)&&(IE===1'b1))) //中断且异常取中断
begin
Cause[6:2] <= `Int;
end else begin
Cause[6:2] <= ExcCodein; //excode
end
end
else if (en) begin
case (CP0addr)
12: SR <= CP0in;
13: Cause <= CP0in;
14: EPC <= CP0in;
default: begin
SR <= SR;
Cause <= Cause;
EPC <= EPC;
end
endcase
end else if (EXLClr) begin
SR[1] <= 1'b0; //exl
end else begin

end
end
end
always @(*) begin
if( EXL===1'b0 && ( (ExcCodein!==5'b0) || (((HWInt&IM)!==6'b0)&&(IE===1'b1)) ) ) begin//异常||中断
req_reg = 1'b1;
end
//todo :req
else begin
req_reg = 1'b0;
end

end

endmodule

14.TIMER

verilog
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
`timescale 1ns / 1ps
`define IDLE 2'b00
`define LOAD 2'b01
`define CNT 2'b10
`define INT 2'b11

`define ctrl mem[0]
`define preset mem[1]
`define count mem[2]
module TIMER(
input clk,
input reset,
input [31:2] Addr,
input WE,
input [31:0] Din,
output [31:0] Dout,
output IRQ
);

reg [1:0] state;
reg [31:0] mem [2:0];

reg _IRQ;
assign IRQ = `ctrl[3] & _IRQ;

assign Dout = mem[Addr[3:2]];

wire [31:0] load = Addr[3:2] == 0 ? {28'h0, Din[3:0]} : Din;

integer i;
always @(posedge clk) begin
if(reset) begin
state <= 0;
for(i = 0; i < 3; i = i+1) mem[i] <= 0;
_IRQ <= 0;
end
else if(WE) begin
// $display("%d@: *%h <= %h", $time, {Addr, 2'b00}, load);
mem[Addr[3:2]] <= load;
end
else begin
case(state)
`IDLE : if(`ctrl[0]) begin
state <= `LOAD;
_IRQ <= 1'b0;
end
`LOAD : begin
`count <= `preset;
state <= `CNT;
end
`CNT :
if(`ctrl[0]) begin
if(`count > 1) `count <= `count-1;
else begin
`count <= 0;
state <= `INT;
_IRQ <= 1'b1;
end
end
else state <= `IDLE;
default : begin
if(`ctrl[2:1] == 2'b00) `ctrl[0] <= 1'b0;
else _IRQ <= 1'b0;
state <= `IDLE;
end
endcase
end
end

endmodule

15.BRIDGE

verilog
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
module BRIDGE (
//cpu
input [ 31:0] cpu_data_addr,
input [ 31:0] cpu_data_wdata,
input [3 : 0] cpu_data_byteen,
output [ 31:0] cpu_data_rdata,

//DM
output [31:0] m_data_addr, // DM 读写地址
input [31:0] m_data_rdata, // DM 读取数据
output [31:0] m_data_wdata, // DM 待写入数据
output [ 3:0] m_data_byteen,

//inter generator
output [31:0] m_int_addr, // 中断发生器待写入地址!!!
output [ 3:0] m_int_byteen,

//timer
output timer0_en,
output [31:0] timer0_addr,
output [31:0] timer0_Din,
input [31:0] timer0_Dout,

output timer1_en,
output [31:0] timer1_addr,
output [31:0] timer1_Din,
input [31:0] timer1_Dout
);
wire DM;
wire TIMER0;
wire TIMER1;
wire INTER;
assign DM=((cpu_data_addr>=32'h00000000&&cpu_data_addr<=32'h0000_2FFF)===1'b1)?1'b1:1'b0;
assign TIMER0=((cpu_data_addr>=32'h0000_7F00&&cpu_data_addr<=32'h0000_7F0B)===1'b1)?1'b1:1'b0;
assign TIMER1=((cpu_data_addr>=32'h0000_7F10&&cpu_data_addr<=32'h0000_7F1B)===1'b1)?1'b1:1'b0;
assign INTER=((cpu_data_addr>=32'h0000_7F20&&cpu_data_addr<=32'h0000_7F23)===1'b1)?1'b1:1'b0;

assign cpu_data_rdata=(DM)?m_data_rdata:
(TIMER0)?timer0_Dout:
(TIMER1)?timer1_Dout:32'b0;


assign m_data_addr = cpu_data_addr;
assign m_data_wdata = cpu_data_wdata;
assign m_data_byteen = (DM) ? cpu_data_byteen : 4'b0;

assign m_int_addr = cpu_data_addr;
assign m_int_byteen = (INTER) ? cpu_data_byteen : 4'b0;

assign timer0_addr = cpu_data_addr;
assign timer0_Din = cpu_data_wdata;
assign timer0_en = (TIMER0) ? cpu_data_byteen : 4'b0;

assign timer1_addr = cpu_data_addr;
assign timer1_Din = cpu_data_wdata;
assign timer1_en = (TIMER1) ? cpu_data_byteen : 4'b0;

endmodule

16.mips(顶层模块)

verilog
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
`define MFHI    6'b010000///
`define MTHI 6'b010001///
`define MFLO 6'b010010///
`define MTLO 6'b010011///
`define OPCODE0 6'b000000///
module mips(
input clk, // 时钟信号
input reset, // 同步复位信号
input interrupt, // 外部中断信号
output [31:0] macroscopic_pc, // 宏观 PC**************

output [31:0] i_inst_addr, // IM 读取地址(取指 PC)
input [31:0] i_inst_rdata, // IM 读取数据

output [31:0] m_data_addr, // DM 读写地址
input [31:0] m_data_rdata, // DM 读取数据
output [31:0] m_data_wdata, // DM 待写入数据
output [3 :0] m_data_byteen, // DM 字节使能信号

output [31:0] m_int_addr, // 中断发生器待写入地址!!!
output [3 :0] m_int_byteen, // 中断发生器字节使能信号!!!

output [31:0] m_inst_addr, // M 级 PC******

output w_grf_we, // GRF 写使能信号
output [4 :0] w_grf_addr, // GRF 待写入寄存器编号
output [31:0] w_grf_wdata, // GRF 待写入数据

output [31:0] w_inst_addr // W 级 PC*******
);
wire req;
wire [31:0] m_pc;
wire [31:0] w_pc;
wire [31:0] epc;
wire [4:0] ExcCodein;
wire BD_IN;
wire [4:0]EXCcodeF_M;
wire [4:0]EXCcodeD_M;
wire [4:0]EXCcodeE_M;
wire [4:0]EXCcodeM_M;
wire EXLClr;
wire CP0en;
wire [4:0]CP0addr;
wire [31:0]CP0in;
wire [31:0]CP0out;
wire [5:0]HWInt;


wire timer0_IRQ;
wire timer1_IRQ;
wire timer0_en;
wire timer1_en;

wire [31:0]timer0_addr;
wire [31:0]timer0_Din;
wire [31:0]timer0_Dout;

wire [31:0]timer1_addr;
wire [31:0]timer1_Din;
wire [31:0]timer1_Dout;

wire [31:0] cpu_data_addr;
wire [31:0] cpu_data_wdata;
wire [3 :0] cpu_data_byteen;
wire [31:0] cpu_inst_addr;
wire [31:0] cpu_data_rdata;

assign macroscopic_pc=m_pc;



assign m_inst_addr=m_pc;
assign w_inst_addr=w_pc;
assign HWInt={3'b0,interrupt,timer1_IRQ,timer0_IRQ};
assign ExcCodein=(EXCcodeF_M!==5'b0)?EXCcodeF_M:
(EXCcodeD_M!==5'b0)?EXCcodeD_M:
(EXCcodeE_M!==5'b0)?EXCcodeE_M:
(EXCcodeM_M!==5'b0)?EXCcodeM_M:5'b0;
CP0 CP0(
.clk(clk),
.reset(reset),
.VPC(m_pc),
.BD_IN(BD_IN),
.ExcCodein(ExcCodein),
.HWInt(HWInt), //外部产生的中断信号
.EXLClr(EXLClr), //是否结束异常中断处理(复位 EXL)
.EPCout(epc), //EPC 的值。
.req(req), //进入处理程序请求。
.en(CP0en),
.CP0addr(CP0addr),
.CP0in(CP0in),
.CP0out(CP0out)
);
BRIDGE bridge(
//cpu
.cpu_data_addr(cpu_data_addr),
.cpu_data_wdata(cpu_data_wdata),
.cpu_data_byteen(cpu_data_byteen),
.cpu_data_rdata(cpu_data_rdata),

//DM
.m_data_addr(m_data_addr), // DM 读写地址
.m_data_rdata(m_data_rdata), // DM 读取数据
.m_data_wdata(m_data_wdata), // DM 待写入数据
.m_data_byteen(m_data_byteen),

//inter generator
.m_int_addr(m_int_addr), // 中断发生器待写入地址!!!
.m_int_byteen(m_int_byteen),

//timer
.timer0_en(timer0_en),
.timer0_addr(timer0_addr),
.timer0_Din(timer0_Din),
.timer0_Dout(timer0_Dout),

.timer1_en(timer1_en),
.timer1_addr(timer1_addr),
.timer1_Din(timer1_Din),
.timer1_Dout(timer1_Dout)

);
TIMER timer0(
.clk(clk),
.reset(reset),
.Addr(timer0_addr[31:2]),
.WE(timer0_en),
.Din(timer0_Din),
.Dout(timer0_Dout),
.IRQ(timer0_IRQ)
);

TIMER timer1(
.clk(clk),
.reset(reset),
.Addr(timer1_addr[31:2]),
.WE(timer1_en),
.Din(timer1_Din),
.Dout(timer1_Dout),
.IRQ(timer1_IRQ)
);
CPU cpu(
.clk(clk),
.reset(reset),
.req(req),
.EPC(epc),
.CP0indata(CP0in),
.CP0outdata(CP0out),
.CP0en(CP0en),
.CP0addr(CP0addr),
.M_PC(m_pc),
.BD_IN(BD_IN),
.EXLClr(EXLClr),

/////////////////////////////////////////IM
.i_inst_addr(i_inst_addr),//pc
.i_inst_rdata(i_inst_rdata),//inster
///////////////////////////////////////////DATA
.cpu_data_addr(cpu_data_addr),
.cpu_data_wdata(cpu_data_wdata),
.cpu_data_byteen(cpu_data_byteen),
.cpu_data_rdata(cpu_data_rdata),
////////////////////////////////////////////grf
.w_grf_we(w_grf_we),
.w_grf_addr(w_grf_addr),
.w_grf_wdata(w_grf_wdata),
.w_inst_addr(w_pc),
.EXCcodeE_M(EXCcodeE_M),
.EXCcodeD_M(EXCcodeD_M),
.EXCcodeF_M(EXCcodeF_M),
.EXCcodeM_M(EXCcodeM_M)

);

endmodule

17.mips_tb

带中断版本会在第一次到0x3010产生一个中断信号。

verilog
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
`timescale 1ns/1ps

module mips_txt;

reg clk;
reg reset;
reg interrupt;

wire [31:0] macroscopic_pc;

wire [31:0] i_inst_addr;
wire [31:0] i_inst_rdata;

wire [31:0] m_data_addr;
wire [31:0] m_data_rdata;
wire [31:0] m_data_wdata;
wire [3 :0] m_data_byteen;

wire [31:0] m_int_addr;
wire [3 :0] m_int_byteen;

wire [31:0] m_inst_addr;

wire w_grf_we;
wire [4 :0] w_grf_addr;
wire [31:0] w_grf_wdata;

wire [31:0] w_inst_addr;

mips uut(
.clk(clk),
.reset(reset),
.interrupt(interrupt),
.macroscopic_pc(macroscopic_pc),

.i_inst_addr(i_inst_addr),
.i_inst_rdata(i_inst_rdata),

.m_data_addr(m_data_addr),
.m_data_rdata(m_data_rdata),
.m_data_wdata(m_data_wdata),
.m_data_byteen(m_data_byteen),

.m_int_addr(m_int_addr),
.m_int_byteen(m_int_byteen),

.m_inst_addr(m_inst_addr),

.w_grf_we(w_grf_we),
.w_grf_addr(w_grf_addr),
.w_grf_wdata(w_grf_wdata),

.w_inst_addr(w_inst_addr)
);

initial begin
clk <= 0;
reset <= 1;
interrupt <= 0;
#20 reset <= 0;
end

integer i;
reg [31:0] fixed_addr;
reg [31:0] fixed_wdata;
reg [31:0] data[0:4095];
reg [31:0] inst[0:5119];

// ----------- For Instructions -----------

assign m_data_rdata = data[(m_data_addr >> 2) % 5120];
assign i_inst_rdata = inst[((i_inst_addr - 32'h3000) >> 2) % 5120];

initial begin
$readmemh("code.txt", inst);
for (i = 0; i < 5120; i = i + 1) data[i] <= 0;
end

// ----------- For Data Memory -----------

always @(*) begin
fixed_wdata = data[(m_data_addr >> 2) & 4095];
fixed_addr = m_data_addr & 32'hfffffffc;
if (m_data_byteen[3]) fixed_wdata[31:24] = m_data_wdata[31:24];
if (m_data_byteen[2]) fixed_wdata[23:16] = m_data_wdata[23:16];
if (m_data_byteen[1]) fixed_wdata[15: 8] = m_data_wdata[15: 8];
if (m_data_byteen[0]) fixed_wdata[7 : 0] = m_data_wdata[7 : 0];
end

always @(posedge clk) begin
if (reset) for (i = 0; i < 4096; i = i + 1) data[i] <= 0;
else if (|m_data_byteen && fixed_addr >> 2 < 4096) begin
data[fixed_addr >> 2] <= fixed_wdata;
$display("%d@%h: *%h <= %h", $time, m_inst_addr, fixed_addr, fixed_wdata);
end
end

// ----------- For Registers -----------

always @(posedge clk) begin
if (~reset) begin
if (w_grf_we && (w_grf_addr != 0)) begin
$display("%d@%h: $%d <= %h", $time, w_inst_addr, w_grf_addr, w_grf_wdata);
end
end
end

// ----------- For Interrupt -----------

wire [31:0] fixed_macroscopic_pc;

assign fixed_macroscopic_pc = macroscopic_pc & 32'hfffffffc;

parameter target_pc = 32'h00003010;

integer count;

initial begin
count = 0;
end

always @(negedge clk) begin
if (reset) begin
interrupt = 0;
end
else begin
if (interrupt) begin
if (|m_int_byteen && (m_int_addr & 32'hfffffffc) == 32'h7f20) begin
interrupt = 0;
end
end
else if (fixed_macroscopic_pc == target_pc) begin
if (count == 0) begin
count = 1;
interrupt = 1;
end
end
end
end

always #2 clk <= ~clk;

endmodule

思路和要点

1.总体思路

  1. 将CPU的各个模块进行修改,使之可以产生各级异常信号,并将其通过流水寄存器一路流下去;
  2. 确定CP0的位置为M级,将各级异常信息流水至该级,并把CPU接收到的终端信号和CPU内产生的异常信息和CP0连接,使之可以判断当前是否需要跳转至异常处理指令,保存处理异常中断需要的各个状态信号,在CPU响应完跳转,处理完异常中断后,跳回正常程序。
  3. 将以上所有内容全部封装为一个 CPU.v,然后在 mips.v 里把CPU和两个计时器装进去,最后设计一个 Bridge 模块把两个计时器,数据存储器和中断发生器(这玩意在课程里被抽象成了 mips.v 的几个输入输出端口,类似IM和DM)的数据读写端口连进 Bridge 做处理,再让CPU通过 Bridge 获得信息。

总之,要干的三件事情是: 产生异常,处理异常中断,通过桥连接外设

产生异常:

接下来列出各级异常和异常码(字母表示判断产生的级,数字表示异常码)

异常与中断码 助记符与名称 指令与指令类型 描述
0 Int (外部中断) 所有指令 中断请求,来源于计时器与外部中断。
4M AdEL (取数异常) lw 取数地址未与 4 字节对齐。
4M AdEL (取数异常) lh 取数地址未与 2 字节对齐。
4M AdEL (取数异常) lh, lb 取 Timer 寄存器的值。
4M AdEL (取数异常) load 型指令 取数地址超出 DM、Timer0、Timer1、中断发生器的范围。
5M AdES (存数异常) sw 存数地址未 4 字节对齐。
5M AdES (存数异常) sh 存数地址未 2 字节对齐。
5M AdES (存数异常) sh, sb 存 Timer 寄存器的值。
5M AdES (存数异常) store 型指令 向计时器的 Count 寄存器存值。
5M AdES (存数异常) store 型指令 存数地址超出 DM、Timer0、Timer1、中断发生器的范围。
12E Ov(溢出异常) add, addi, sub 算术溢出。
4E AdEL (取数异常) load 型指令 计算地址时加法溢出。
5E AdES (存数异常) store 型指令 计算地址加法溢出。
8D Syscall (系统调用) syscall 系统调用。
10D RI(未知指令) - 未知的指令码。
4F AdEL (取指异常) 所有指令 PC 地址未字对齐。
4F AdEL (取指异常) 所有指令 PC 地址超过 0x3000 ~ 0x6ffc

EXCcode (异常与中断码)为 Int(外部中断)时,在课程内其含义实际上是此时没有异常发生,仅考虑中断是否发生。也正因为如此,在没有异常产生时,我们可以考虑给CP0传入 Int,让其根据实际中断信号判断是否发生中断,而无需考虑异常。

因此,我们可以给F级的NPC,D级的CTRL,E级的ALU和M级的LOADEXT各加一个输出端口,用于输出该时刻用该模块是否探查出异常。

我们规定一个原则:我们优先处理最早可以探查到的异常

  • 如果一条指令在E级,M级都会产生异常,那么我们认为这个指令首先触发的是E级的异常,因此传入CP0的异常必须是E级产生的异常。

  • 如果有两条指令在E级和M级都产生异常,那么我们认为M级的指令首先触发了M级的异常,因此传入CP0的异常必须是M级产生的异常。

verilog
1
2
3
4
assign ExcCodein=(EXCcodeF_M!==5'b0)?EXCcodeF_M:
(EXCcodeD_M!==5'b0)?EXCcodeD_M:
(EXCcodeE_M!==5'b0)?EXCcodeE_M:
(EXCcodeM_M!==5'b0)?EXCcodeM_M:5'b0;

在检测出异常/遇到中断时,我们不应该让M级与其之前的指令对其他模块产生任何影响

  1. 当PC探查出异常时(F级未对齐或超出范围,D级未知),我们必须把读取出的指令覆盖为NOP(但是PC和BD需要保留);
  2. 当req为1时,若此时存在一个可能会修改HI寄存器/LO寄存器的指令在E级,则乘除模块不应该对其进行任何响应(即不写入,不计算)
  3. 当req为1时,DATA的字节写使能信号必须全部为0,读取出的数据伴随的寄存器写使能必须为0
  4. 某级产生了异常,该级对应的使能信号也应该全部为0(例如在E级的SW地址计算溢出,则修改其写使能为0),让其流到M级产生异常处理。

处理异常中断:

在一个时钟周期内,

  1. CP0会先检查现在是否正在处理异常中断(课程组保证没有嵌套异常中断),再检查CP0所在流水级的指令是否存在异常,以及外部是否有未被禁用的中断(如果外部中断和内部异常同时出现,我们认为此时发生了一个中断而非异常)。
  2. 如果现在没有在处理异常中断,并且CP0所在流水级存在异常或外部产生了未被禁用的中断,那么CP0会向CPU发送一个“跳转至异常中断处理”的信号。
  3. CPU在接收到该信号之后,对CP0所在流水级及其之前的流水级进行“清空”(之后的流水级继续正常执行),并让PC直接跳转至异常中断处理地址(0x4180),此时CP0记录下处理完异常后需要返回的地址,以及出现异常的指令是否为延迟槽内指令。
CP0端口和内含物

再次列出cp0实现端口:

端口 方向 位数 解释
clk IN 1 时钟信号。
reset IN 1 复位信号。
en IN 1 写使能信号。
CP0Add IN 5 读取/写入目标寄存器地址。
CP0In IN 32 写入寄存器数据。
CP0Out OUT 32 读出寄存器数据。
VPC IN 32 当前异常中断发生时PC的值。
BD_IN IN 1 当前异常中断发生指令是否是延迟槽内指令。
ExcCodein IN 5 当前发生异常类型。
HWInt IN 6 外部产生的中断信号。
EXLClr IN 1 是否结束异常中断处理(复位 EXL)。
EPCout OUT 32 EPC 的值。
req OUT 1 进入处理程序请求。

CP0内需要保存的三个32位寄存器:

寄存器 编号 功能
SR 12 配置异常中断的功能。
Cause 13 记录异常中断发生的原因和情况。
EPC 14 记录异常中断处理结束后需要返回的 PC。

以及这些寄存器我们各自需要几位,分别在干什么:

寄存器 功能域 位域 解释
SR(State Register) IM(Interrupt Mask) 15:10 分别对应六个外部中断,相应位置 1 表示允许中断,置 0 表示禁止中断。这是一个被动的功能,只能通过 mtc0 这个指令修改,通过修改这个功能域,我们可以屏蔽一些中断。
SR(State Register) EXL(Exception Level) 1 任何异常中断发生时置位,这会强制进入核心态(也就是进入异常中断处理程序)并禁止再次触发异常中断。
SR(State Register) IE(Interrupt Enable) 0 全局中断使能,该位置 1 表示允许中断,置 0 表示禁止中断。
Cause BD(Branch Delay) 31 当该位置 1 的时候,EPC 指向当前指令的前一条指令(一定为跳转),否则指向当前指令。
Cause IP(Interrupt Pending) 15:10 为 6 位待决的中断位,分别对应 6 个外部中断,相应位置 1 表示有中断,置 0 表示无中断,将会每个周期被修改一次,修改的内容来自计时器和外部中断。
Cause ExcCode 6:2 异常中断编码,记录当前发生的是什么异常中断。
EPC EPC 31:0 记录异常中断处理结束后需要返回的 PC。
读写寄存器

mfc0,mtc0 实现了对上述三种寄存器的读写,我们仅仅需要用 enCP0AddCP0InCP0Out完成类似于GRF的操作即可。

Cause 寄存器的 IP 域每周期写入 HWint 对应位的值。

注意优先级,req取消CP0写入应该高于CP0写入使能en(防止M级为MTC0时来中断

verilog
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
always @(posedge clk) begin
if (reset) begin
......
end
else begin
Cause[15:10] <= HWInt;
if (req_reg) begin
......
end

else if (en) begin
......
end
else if (EXLClr) begin
......
end
else begin
......
end
end
end

进入异常中断处理程序

VPC 开始,到 HWInt 结束(EXLClr 不在内,这个端口后面会具体说明),这些是我们判断是否进入异常中断处理程序的所有输入端口。我们来根据这些端口,以及以上给出的功能域信号的表格,填一下“异常中断处理思路”里给出的思路。

  1. CP0会先检查现在 EXL是否为1(是否正在处理异常中断),再检查 ExcCodeIn是否不为0(当前是否存在异常)和 HWInt&IM是否不为0且IE不为0(存在未被禁用的中断)。
  2. 如果现在 EXL 为0,并且 ExcCodeIn 不为0或“HWInt&IM 不为0且IE不为0”,那么CP0会将 Req 置为1,同时记录一下 EPCBDEXLExcCode 的值,否则置为0。
  3. CPU在接收到 Req 为1之后,对CP0所在流水级及其之前的流水级进行“清空”(之后的流水级继续正常执行),并让PC直接跳转至异常中断处理地址(0x4180)。

上面没有说明的是,这里的 VPC 应该接入什么呢?是NPC寄存器当前的值吗?并不是。

我们在这里需要插入一个“宏观PC”的概念。实际上,不论是CP0在处理异常,还是外部给CPU一个中断,在CP0和外部眼里,你的CPU表现的应该像是“一个有延迟槽的单周期CPU”,每条指令只有两个状态:执行完了和没执行(而不会细化到执行到了哪一级流水线)。

(打个比方,这个概念有点类似于你在用Mars跑自己写的代码对拍P5P6的时候,,观察到的就是一个“有延迟槽的单周期CPU”。而当你观察Mars的PC时,看到的也不是5个流水线各自的PC是多少,而是一个“整体的PC值”。我们所引入的宏观PC就是这里的PC。)

由于我们的CP0设置在了M级,异常处理就只能在M级来做,所以这个宏观PC的值就等同于M级PC的值,在CPU处理异常中断时,我们就认为M级PC的值是当前时刻的PC,也就是我们传入的 VPC 的来源。

接下来我们细说当异常中断时CP0记录的都是什么值:

  • 记录 ExcCode 时,如果当前同时有异常和中断,那么我们不应该直接记录 ExcCodeIn,而是应该记录成一个 Int

  • BDIn 为1时,表明发生异常中断的指令为延迟槽内的指令,此时我们应该让 EPC 记录 VPC-4,即延迟槽前一条指令(某个分支跳转指令),否则正常记录 VPC

  • EXL 置为1。

  • BD 置为 BDIn

为什么 BDIn 为1时, EPC 应该记录 VPC-4 呢?

对绝大多数情况来说,EPC 就是 VPC ,这个没错。但问题在于,如果对于分支跳转指令和其延迟槽内的指令呢?

如果异常中断发生在了延迟槽内的指令,那么我们就要面对一个问题:我们无法单纯通过这条指令的运行结果判断分支跳转指令会把PC改成什么样。因此,我们必须让前一条分支跳转指令“重新跑一遍”,所以需要返回的地址也就变成了 VPC-4 。其余情况下,需要返回的地址就是 VPC

退出异常中断处理程序

这一个功能主要是用来实现 eret 的。

我们从D级的控制单元引出一个新的信号(记为 eret_if ),M级记为EXLClr后与 EXLClr 进行对接,当此时控制器所在级运行的指令为 eret 时,我们把这个信号置1,否则置0。

EXLClr 置为1时,我们需要修改 EXL 为0。

CPU的修改
  1. 程序运行到 eret 的时候跳回正常程序。
  2. 根据 req 信号清空M级与其之前的流水级,并跳入异常中断程序;

1很好实现,在NPC新添判断和端口即可。

关于2,首先需要强调的是,resetreqeret_ifstall 是四种信号,各个模块在接收到这些信号的表现是有不同的,有些时候不能进行粗暴的合并,这一点我们马上就会感觉到。

这就不得不提到一种特殊情况了。当我们产生阻塞信号时,D级到E级的流水寄存器会被清空一次,导致下一周期的E级会产生一个空泡,再下一个周期这个空泡就到了M级。而如果有一个中断恰好在空泡进入M级的时候产生,那么CP0就会选择处理这个中断,而此时CP0记录下的返回地址会是什么呢?

没错,如果你产生空泡的方式是完全的清空所有寄存器,包括传递PC的寄存器,那么此时你会把返回地址记录成 0x00000000(或者 0x00003000,或者什么别的你实现的东西),这显然不符合我们的期望。

同理,判断一条指令是否为延迟槽内指令的的信号也不能在阻塞的时候被暴力清空。

而这只是针对 stall 信号的特殊情况,对于 reset 后刚开始的几个周期,也有可能产生类似的错误。因此我们需要对这四种信号产生的时候流水寄存器的行为做一个规定。

信号 PC流水寄存器行为 BD流水寄存器行为 其他流水寄存器行为
reset 复位至 0x00003000 复位至 0 清空
req 设置为 0x00004180 设置为 0 清空
eret_if (仅对F级到D级流水寄存器起作用,且此时stall信号为0 设置为当前周期的 EPC 的值 不发生变化 清空
D_CLEAR(仅指对D级到E级流水寄存器起作用的阻塞信号) 不发生变化(接D 级) 不发生变化(接D 级) 清空

当这些信号中的某几个同时出现时,我们按照从上至下的优先级依次处理。

注意D 流水寄存器

verilog
1
2
3
else if (D_CLEAR) begin
PC_D <= PC_D_IN;//////
BD_D <= BD_D_IN;//////

而不是

verilog
1
2
3
else if (D_CLEAR) begin
PC_D <= PC_D;//////
BD_D <= BD_D;//////

相当于一个A指令在D级,B在E级,前者是阻塞时一直输出B的pc和bd,而后者是A的。

除此之外,我们还需要考虑一个问题:eret 在D级时就会发挥作用,而此时可能会出现一条 mtc0 将要写入 EPC 但未写入的情况。此时,我们应该增加一种阻塞情况,即当D级指令为 eret ,且E级或M级存在向 CP0 写入 EPC 的指令时,我们选择进行阻塞。

verilog
1
assign eret_after_mtc0=( eret && ((IR_E[31:21]===11'b010000_00100&&IR_E[15:11]===5'b01110)||(IR_M[31:21]===11'b010000_00100&&IR_M[15:11]===5'b01110 )) )?1'b1:1'b0;

通过桥连接外设:

这一步相对于前面的东西来说,实际上没啥好说的,首先导入教程里给的 Timer,然后写一个Bridge,最后在 mips.v 里把线连一下,没了。

我们需要的端口有:

  • CPU对外设的读写地址,字节写入使能,读取数据端口;
  • DM的读写地址,字节写入使能,读取数据端口;
  • Timer0和Timer1的读写地址,写入使能,读取数据端口;
  • 中断发生器的写入地址,字节写入使能端口。

2.要点分析

转发表:

供给者序号\需求者 D级grf的输出 E级alu的输入 M级mem的内存写入数据WD
0 AO_E_OUT r1_D_OUT/r2_D_OUT WD_E_OUT
1 rd1/rd2 AO_E_OUT realgrfdata(真实值)
2 / grfwritedata(包括memout和AO_M_OUT) /

mux暂时不用,改为assign选择。

AT法详表:

指令 T_use E_T_new M_T_new W_T_new
ADD/SUB/OR/AND/SLT/SLTU/ADDI/ORI/ANDI 1 1 0 0
LW/LB/LH/LBU/LHU 1 2 1 0
SW/SB/SH 1 (特殊) 0 0 0
BEQ/BNE 0 0 0 0
JR 0 0 0 0
LUI INF 1 0 0
J INF 0 0 0
JAL INF 1(用aluresult传入pc+8) 0 0
NOP INF 0 0 0
MFHI/MFLO(regwrite) INF 1 0 0
SYSCALL/ERET INF 0 0 0
MTHI/MTLO 1 0 0 0
MULT/MULTU/DIV/DIVU 1 0 0 0
MFC0 INF 2 1 0
MTC0 2(魔改) 0 0 0

对于sw

如果sw处于E级,lw处于M级,会产生write addr无法正确转发的错误,控制sw的T_use为1.

用grf魔改端口实现实时输出真实值,为上机做准备。

verilog
1
2
3
4
5
if (memwrite_M!==4'b0000) begin
memdata_sel = 0;//normal 1->grfextrain=>rdextra
end else begin
memdata_sel = 0;//normal
end

对于mtc0

用grf魔改端口实现实时输出真实值,为提供给mtc0.

测试方案

通过mars编写汇编程序,编写相关测试代码,将mars生成的机器码通过文件导入到verilog,通过向输出中间数据,和mars进行对拍,以此验证各代码是否运行正确。

通过at法表的观察,需要测试的有阻塞的四种情况,根据表格将所有组合搭配测试。

对于转发,将所有需要读寄存器的指令,以0,1,2的间隔在后方加入相同寄存器的写寄存器指令,即可完成转发的测试。

对于异常中断写一段异常处理,观察是否能正常跳转。

思考题

1.请查阅相关资料,说明鼠标和键盘的输入信号是如何被 CPU 知晓的?
键盘和鼠标本质上都是输入设备,其自身的内部有一些微处理器来控制自己与主机之间的信息交互。而在CPU看来,外部信号会经过很多层级传入到内部,而内部的信息也会经过很多层级传出至外部。这些层级由外至内大致可以分为主存->cache(->bridge)->CPU。

每个设备都需要驱动程序的,只不过驱动程序有的在电脑系统内,有的却需另外按装,比如:无线健鼠套装,驱动程序已经在USB头上,我们叫它免驱设备。如果没有这些指定驱动程序的话,电脑是无法识

2.请思考为什么我们的 CPU 处理中断异常必须是已经指定好的地址?如果你的 CPU 支持用户自定义入口地址,即处理中断异常的程序由用户提供,其还能提供我们所希望的功能吗?如果可以,请说明这样可能会出现什么问题?否则举例说明。(假设用户提供的中断处理程序合法)

只有先确定异常入口,才能保证无论何时有异常正确处理,如果支持自定义异常处理程序入口,在产生自定义地址的过程中可能发生错误,导致不能正确跳转。

3.为何与外设通信需要 Bridge?

对于CPU来说,所有外设具体实现应该是透明的,我们不关心外设的种类,因此通过bridge可以达到高内聚低耦合的目的,实现对不同外设的统一接口。

4.请阅读官方提供的定时器源代码,阐述两种中断模式的异同,并分别针对每一种模式绘制状态移图。

中断模式0:将计数器写使能变为0,并且保持中断信号持续有效,直到计数器写使能为1。该模式通常用于定时中断。

中断模式1:只保持一周期的中断信号,并重新载入计数器初值,再次倒计时。该模式通常用于产生周期性脉冲。

5.倘若中断信号流入的时候,在检测宏观 PC 的一级如果是一条空泡(你的 CPU 该级所有信息均为空)指令,此时会发生什么问题?在此例基础上请思考:在 P7 中,清空流水线产生的空泡指令应该保留原指令的哪些信息?

如果此时收到一个外部中断信号,空泡的PC和BD为空,会导致跳回错误,因此空泡应该保持其后第一条非空泡指令的pc和BD,在中断发生时可以指代其后的指令。

6.为什么 jalr 指令为什么不能写成 jalr $31, $31

如果 jalr $31 $31 的延迟槽内发生异常或需要响应中断。那么 $31 寄存器的值已经被 jalr 改变,但是处理异常结束后,会再次执行 jalr 指令,这就会跳转到不正确的 PC 地址。

附录:

cmd
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
0x0000000000003000:  00 00 E0 20    add   $gp, $zero, $zero
0x0000000000003004: 00 00 E8 20 add $sp, $zero, $zero
0x0000000000003008: 00 00 F0 20 add $fp, $zero, $zero
0x000000000000300c: 00 00 F8 20 add $ra, $zero, $zero
0x0000000000003010: 37 9C 00 04 ori $gp, $gp, 4
0x0000000000003014: 00 00 00 00 nop
0x0000000000003018: 00 00 00 00 nop
0x000000000000301c: 00 00 00 00 nop
0x0000000000003020: 3C 01 FF FF lui $at, 0xffff
0x0000000000003024: 34 21 AA 99 ori $at, $at, 0xaa99
0x0000000000003028: 3C 02 00 00 lui $v0, 0
0x000000000000302c: 34 42 78 7F ori $v0, $v0, 0x787f
0x0000000000003030: 00 00 00 00 nop
0x0000000000003034: 00 00 00 00 nop
0x0000000000003038: 00 00 00 00 nop
0x000000000000303c: 00 22 D0 20 add $k0, $at, $v0
0x0000000000003040: 00 00 00 00 nop
0x0000000000003044: 00 00 00 00 nop
0x0000000000003048: 00 00 00 00 nop
0x000000000000304c: AF BA 00 00 sw $k0, ($sp)
0x0000000000003050: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003054: 3C 00 30 5C lui $zero, 0x305c
0x0000000000003058: 00 00 00 00 nop
0x000000000000305c: 3C 04 FF FF lui $a0, 0xffff
0x0000000000003060: 34 84 85 DC ori $a0, $a0, 0x85dc
0x0000000000003064: 3C 05 FF FF lui $a1, 0xffff
0x0000000000003068: 34 A5 83 D3 ori $a1, $a1, 0x83d3
0x000000000000306c: 00 00 00 00 nop
0x0000000000003070: 00 00 00 00 nop
0x0000000000003074: 00 00 00 00 nop
0x0000000000003078: 00 85 00 20 add $zero, $a0, $a1
0x000000000000307c: 00 00 00 00 nop
0x0000000000003080: 00 00 00 00 nop
0x0000000000003084: 00 00 00 00 nop
0x0000000000003088: AF A0 00 00 sw $zero, ($sp)
0x000000000000308c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003090: 3C 00 30 98 lui $zero, 0x3098
0x0000000000003094: 00 00 00 00 nop
0x0000000000003098: 3C 10 FF FF lui $s0, 0xffff
0x000000000000309c: 36 10 D9 EF ori $s0, $s0, 0xd9ef
0x00000000000030a0: 3C 11 FF FF lui $s1, 0xffff
0x00000000000030a4: 36 31 8D CD ori $s1, $s1, 0x8dcd
0x00000000000030a8: 00 00 00 00 nop
0x00000000000030ac: 00 00 00 00 nop
0x00000000000030b0: 00 00 00 00 nop
0x00000000000030b4: 02 11 D8 22 sub $k1, $s0, $s1
0x00000000000030b8: 00 00 00 00 nop
0x00000000000030bc: 00 00 00 00 nop
0x00000000000030c0: 00 00 00 00 nop
0x00000000000030c4: AF BB 00 00 sw $k1, ($sp)
0x00000000000030c8: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000030cc: 3C 00 30 D4 lui $zero, 0x30d4
0x00000000000030d0: 00 00 00 00 nop
0x00000000000030d4: 3C 02 FF FF lui $v0, 0xffff
0x00000000000030d8: 34 42 F1 2E ori $v0, $v0, 0xf12e
0x00000000000030dc: 00 00 00 00 nop
0x00000000000030e0: 00 00 00 00 nop
0x00000000000030e4: 00 00 00 00 nop
0x00000000000030e8: 34 53 F0 AD ori $s3, $v0, 0xf0ad
0x00000000000030ec: 00 00 00 00 nop
0x00000000000030f0: 00 00 00 00 nop
0x00000000000030f4: 00 00 00 00 nop
0x00000000000030f8: AF B3 00 00 sw $s3, ($sp)
0x00000000000030fc: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003100: 3C 00 31 08 lui $zero, 0x3108
0x0000000000003104: 00 00 00 00 nop
0x0000000000003108: 3C 1A FF FF lui $k0, 0xffff
0x000000000000310c: 37 5A E2 B7 ori $k0, $k0, 0xe2b7
0x0000000000003110: 00 00 00 00 nop
0x0000000000003114: 00 00 00 00 nop
0x0000000000003118: 00 00 00 00 nop
0x000000000000311c: 37 40 D4 16 ori $zero, $k0, 0xd416
0x0000000000003120: 00 00 00 00 nop
0x0000000000003124: 00 00 00 00 nop
0x0000000000003128: 00 00 00 00 nop
0x000000000000312c: AF A0 00 00 sw $zero, ($sp)
0x0000000000003130: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003134: 3C 00 31 3C lui $zero, 0x313c
0x0000000000003138: 00 00 00 00 nop
0x000000000000313c: 3C 0E FF FF lui $t6, 0xffff
0x0000000000003140: 35 CE E5 04 ori $t6, $t6, 0xe504
0x0000000000003144: 00 00 00 00 nop
0x0000000000003148: 00 00 00 00 nop
0x000000000000314c: 00 00 00 00 nop
0x0000000000003150: 34 0F 08 5D ori $t7, $zero, 0x85d
0x0000000000003154: 00 00 00 00 nop
0x0000000000003158: 00 00 00 00 nop
0x000000000000315c: 00 00 00 00 nop
0x0000000000003160: 81 EE F7 BB lb $t6, -0x845($t7)
0x0000000000003164: 00 00 00 00 nop
0x0000000000003168: 00 00 00 00 nop
0x000000000000316c: 00 00 00 00 nop
0x0000000000003170: AF AE 00 00 sw $t6, ($sp)
0x0000000000003174: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003178: AF AF 00 00 sw $t7, ($sp)
0x000000000000317c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003180: 3C 00 31 88 lui $zero, 0x3188
0x0000000000003184: 00 00 00 00 nop
0x0000000000003188: 3C 13 FF FF lui $s3, 0xffff
0x000000000000318c: 36 73 D2 57 ori $s3, $s3, 0xd257
0x0000000000003190: 00 00 00 00 nop
0x0000000000003194: 00 00 00 00 nop
0x0000000000003198: 00 00 00 00 nop
0x000000000000319c: 34 08 75 72 ori $t0, $zero, 0x7572
0x00000000000031a0: 00 08 40 22 neg $t0, $t0
0x00000000000031a4: 00 00 00 00 nop
0x00000000000031a8: 00 00 00 00 nop
0x00000000000031ac: 00 00 00 00 nop
0x00000000000031b0: 81 13 75 AF lb $s3, 0x75af($t0)
0x00000000000031b4: 00 00 00 00 nop
0x00000000000031b8: 00 00 00 00 nop
0x00000000000031bc: 00 00 00 00 nop
0x00000000000031c0: AF B3 00 00 sw $s3, ($sp)
0x00000000000031c4: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000031c8: AF A8 00 00 sw $t0, ($sp)
0x00000000000031cc: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000031d0: 3C 00 31 D8 lui $zero, 0x31d8
0x00000000000031d4: 00 00 00 00 nop
0x00000000000031d8: 3C 17 FF FF lui $s7, 0xffff
0x00000000000031dc: 36 F7 83 95 ori $s7, $s7, 0x8395
0x00000000000031e0: 00 00 00 00 nop
0x00000000000031e4: 00 00 00 00 nop
0x00000000000031e8: 00 00 00 00 nop
0x00000000000031ec: 34 18 35 C9 ori $t8, $zero, 0x35c9
0x00000000000031f0: 00 18 C0 22 neg $t8, $t8
0x00000000000031f4: 00 00 00 00 nop
0x00000000000031f8: 00 00 00 00 nop
0x00000000000031fc: 00 00 00 00 nop
0x0000000000003200: 83 17 35 E7 lb $s7, 0x35e7($t8)
0x0000000000003204: 00 00 00 00 nop
0x0000000000003208: 00 00 00 00 nop
0x000000000000320c: 00 00 00 00 nop
0x0000000000003210: AF B7 00 00 sw $s7, ($sp)
0x0000000000003214: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003218: AF B8 00 00 sw $t8, ($sp)
0x000000000000321c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003220: 3C 00 32 28 lui $zero, 0x3228
0x0000000000003224: 00 00 00 00 nop
0x0000000000003228: 3C 0C 00 00 lui $t4, 0
0x000000000000322c: 35 8C 17 33 ori $t4, $t4, 0x1733
0x0000000000003230: 00 00 00 00 nop
0x0000000000003234: 00 00 00 00 nop
0x0000000000003238: 00 00 00 00 nop
0x000000000000323c: 34 04 5F 49 ori $a0, $zero, 0x5f49
0x0000000000003240: 00 00 00 00 nop
0x0000000000003244: 00 00 00 00 nop
0x0000000000003248: 00 00 00 00 nop
0x000000000000324c: 80 8C A0 FA lb $t4, -0x5f06($a0)
0x0000000000003250: 00 00 00 00 nop
0x0000000000003254: 00 00 00 00 nop
0x0000000000003258: 00 00 00 00 nop
0x000000000000325c: AF AC 00 00 sw $t4, ($sp)
0x0000000000003260: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003264: AF A4 00 00 sw $a0, ($sp)
0x0000000000003268: 03 BC E8 20 add $sp, $sp, $gp
0x000000000000326c: 3C 00 32 74 lui $zero, 0x3274
0x0000000000003270: 00 00 00 00 nop
0x0000000000003274: 3C 1B FF FF lui $k1, 0xffff
0x0000000000003278: 37 7B 98 F4 ori $k1, $k1, 0x98f4
0x000000000000327c: 00 00 00 00 nop
0x0000000000003280: 00 00 00 00 nop
0x0000000000003284: 00 00 00 00 nop
0x0000000000003288: 34 0B 40 38 ori $t3, $zero, 0x4038
0x000000000000328c: 00 0B 58 22 neg $t3, $t3
0x0000000000003290: 00 00 00 00 nop
0x0000000000003294: 00 00 00 00 nop
0x0000000000003298: 00 00 00 00 nop
0x000000000000329c: 81 7B 40 54 lb $k1, 0x4054($t3)
0x00000000000032a0: 00 00 00 00 nop
0x00000000000032a4: 00 00 00 00 nop
0x00000000000032a8: 00 00 00 00 nop
0x00000000000032ac: AF BB 00 00 sw $k1, ($sp)
0x00000000000032b0: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000032b4: AF AB 00 00 sw $t3, ($sp)
0x00000000000032b8: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000032bc: 3C 00 32 C4 lui $zero, 0x32c4
0x00000000000032c0: 00 00 00 00 nop
0x00000000000032c4: 3C 02 00 00 lui $v0, 0
0x00000000000032c8: 34 42 2E 29 ori $v0, $v0, 0x2e29
0x00000000000032cc: 00 00 00 00 nop
0x00000000000032d0: 00 00 00 00 nop
0x00000000000032d4: 00 00 00 00 nop
0x00000000000032d8: 34 15 56 C7 ori $s5, $zero, 0x56c7
0x00000000000032dc: 00 00 00 00 nop
0x00000000000032e0: 00 00 00 00 nop
0x00000000000032e4: 00 00 00 00 nop
0x00000000000032e8: 86 A2 A9 8F lh $v0, -0x5671($s5)
0x00000000000032ec: 00 00 00 00 nop
0x00000000000032f0: 00 00 00 00 nop
0x00000000000032f4: 00 00 00 00 nop
0x00000000000032f8: AF A2 00 00 sw $v0, ($sp)
0x00000000000032fc: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003300: AF B5 00 00 sw $s5, ($sp)
0x0000000000003304: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003308: 3C 00 33 10 lui $zero, 0x3310
0x000000000000330c: 00 00 00 00 nop
0x0000000000003310: 3C 16 FF FF lui $s6, 0xffff
0x0000000000003314: 36 D6 DB 7E ori $s6, $s6, 0xdb7e
0x0000000000003318: 00 00 00 00 nop
0x000000000000331c: 00 00 00 00 nop
0x0000000000003320: 00 00 00 00 nop
0x0000000000003324: 34 05 02 C9 ori $a1, $zero, 0x2c9
0x0000000000003328: 00 05 28 22 neg $a1, $a1
0x000000000000332c: 00 00 00 00 nop
0x0000000000003330: 00 00 00 00 nop
0x0000000000003334: 00 00 00 00 nop
0x0000000000003338: A0 B6 02 F5 sb $s6, 0x2f5($a1)
0x000000000000333c: 00 00 00 00 nop
0x0000000000003340: 00 00 00 00 nop
0x0000000000003344: 00 00 00 00 nop
0x0000000000003348: AF B6 00 00 sw $s6, ($sp)
0x000000000000334c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003350: AF A5 00 00 sw $a1, ($sp)
0x0000000000003354: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003358: 3C 00 33 60 lui $zero, 0x3360
0x000000000000335c: 00 00 00 00 nop
0x0000000000003360: 3C 19 00 00 lui $t9, 0
0x0000000000003364: 37 39 1B AC ori $t9, $t9, 0x1bac
0x0000000000003368: 00 00 00 00 nop
0x000000000000336c: 00 00 00 00 nop
0x0000000000003370: 00 00 00 00 nop
0x0000000000003374: 34 11 6C 61 ori $s1, $zero, 0x6c61
0x0000000000003378: 00 11 88 22 neg $s1, $s1
0x000000000000337c: 00 00 00 00 nop
0x0000000000003380: 00 00 00 00 nop
0x0000000000003384: 00 00 00 00 nop
0x0000000000003388: A2 39 6C DA sb $t9, 0x6cda($s1)
0x000000000000338c: 00 00 00 00 nop
0x0000000000003390: 00 00 00 00 nop
0x0000000000003394: 00 00 00 00 nop
0x0000000000003398: AF B9 00 00 sw $t9, ($sp)
0x000000000000339c: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000033a0: AF B1 00 00 sw $s1, ($sp)
0x00000000000033a4: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000033a8: 3C 00 33 B0 lui $zero, 0x33b0
0x00000000000033ac: 00 00 00 00 nop
0x00000000000033b0: 3C 07 00 00 lui $a3, 0
0x00000000000033b4: 34 E7 22 90 ori $a3, $a3, 0x2290
0x00000000000033b8: 00 00 00 00 nop
0x00000000000033bc: 00 00 00 00 nop
0x00000000000033c0: 00 00 00 00 nop
0x00000000000033c4: 34 03 19 41 ori $v1, $zero, 0x1941
0x00000000000033c8: 00 00 00 00 nop
0x00000000000033cc: 00 00 00 00 nop
0x00000000000033d0: 00 00 00 00 nop
0x00000000000033d4: A0 67 E7 65 sb $a3, -0x189b($v1)
0x00000000000033d8: 00 00 00 00 nop
0x00000000000033dc: 00 00 00 00 nop
0x00000000000033e0: 00 00 00 00 nop
0x00000000000033e4: AF A7 00 00 sw $a3, ($sp)
0x00000000000033e8: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000033ec: AF A3 00 00 sw $v1, ($sp)
0x00000000000033f0: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000033f4: 3C 00 33 FC lui $zero, 0x33fc
0x00000000000033f8: 00 00 00 00 nop
0x00000000000033fc: 3C 11 00 00 lui $s1, 0
0x0000000000003400: 36 31 0F 93 ori $s1, $s1, 0xf93
0x0000000000003404: 00 00 00 00 nop
0x0000000000003408: 00 00 00 00 nop
0x000000000000340c: 00 00 00 00 nop
0x0000000000003410: 34 14 12 DA ori $s4, $zero, 0x12da
0x0000000000003414: 00 00 00 00 nop
0x0000000000003418: 00 00 00 00 nop
0x000000000000341c: 00 00 00 00 nop
0x0000000000003420: A2 91 ED CD sb $s1, -0x1233($s4)
0x0000000000003424: 00 00 00 00 nop
0x0000000000003428: 00 00 00 00 nop
0x000000000000342c: 00 00 00 00 nop
0x0000000000003430: AF B1 00 00 sw $s1, ($sp)
0x0000000000003434: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003438: AF B4 00 00 sw $s4, ($sp)
0x000000000000343c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003440: 3C 00 34 48 lui $zero, 0x3448
0x0000000000003444: 00 00 00 00 nop
0x0000000000003448: 3C 0A 00 00 lui $t2, 0
0x000000000000344c: 35 4A 4C B4 ori $t2, $t2, 0x4cb4
0x0000000000003450: 00 00 00 00 nop
0x0000000000003454: 00 00 00 00 nop
0x0000000000003458: 00 00 00 00 nop
0x000000000000345c: 34 0D 0D F3 ori $t5, $zero, 0xdf3
0x0000000000003460: 00 00 00 00 nop
0x0000000000003464: 00 00 00 00 nop
0x0000000000003468: 00 00 00 00 nop
0x000000000000346c: A5 AA F2 89 sh $t2, -0xd77($t5)
0x0000000000003470: 00 00 00 00 nop
0x0000000000003474: 00 00 00 00 nop
0x0000000000003478: 00 00 00 00 nop
0x000000000000347c: AF AA 00 00 sw $t2, ($sp)
0x0000000000003480: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003484: AF AD 00 00 sw $t5, ($sp)
0x0000000000003488: 03 BC E8 20 add $sp, $sp, $gp
0x000000000000348c: 3C 00 34 94 lui $zero, 0x3494
0x0000000000003490: 00 00 00 00 nop
0x0000000000003494: 3C 09 00 00 lui $t1, 0
0x0000000000003498: 35 29 64 ED ori $t1, $t1, 0x64ed
0x000000000000349c: 00 00 00 00 nop
0x00000000000034a0: 00 00 00 00 nop
0x00000000000034a4: 00 00 00 00 nop
0x00000000000034a8: 34 0B 37 5C ori $t3, $zero, 0x375c
0x00000000000034ac: 00 00 00 00 nop
0x00000000000034b0: 00 00 00 00 nop
0x00000000000034b4: 00 00 00 00 nop
0x00000000000034b8: A5 69 C9 6E sh $t1, -0x3692($t3)
0x00000000000034bc: 00 00 00 00 nop
0x00000000000034c0: 00 00 00 00 nop
0x00000000000034c4: 00 00 00 00 nop
0x00000000000034c8: AF A9 00 00 sw $t1, ($sp)
0x00000000000034cc: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000034d0: AF AB 00 00 sw $t3, ($sp)
0x00000000000034d4: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000034d8: 3C 00 34 E0 lui $zero, 0x34e0
0x00000000000034dc: 00 00 00 00 nop
0x00000000000034e0: 3C 05 00 00 lui $a1, 0
0x00000000000034e4: 34 A5 2A 25 ori $a1, $a1, 0x2a25
0x00000000000034e8: 3C 16 FF FF lui $s6, 0xffff
0x00000000000034ec: 36 D6 9D F5 ori $s6, $s6, 0x9df5
0x00000000000034f0: 00 00 00 00 nop
0x00000000000034f4: 00 00 00 00 nop
0x00000000000034f8: 00 00 00 00 nop
0x00000000000034fc: 00 B6 78 20 add $t7, $a1, $s6
0x0000000000003500: 00 00 00 00 nop
0x0000000000003504: 00 00 00 00 nop
0x0000000000003508: 00 00 00 00 nop
0x000000000000350c: AF AF 00 00 sw $t7, ($sp)
0x0000000000003510: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003514: 3C 00 35 1C lui $zero, 0x351c
0x0000000000003518: 00 00 00 00 nop
0x000000000000351c: 3C 13 00 00 lui $s3, 0
0x0000000000003520: 36 73 5A B2 ori $s3, $s3, 0x5ab2
0x0000000000003524: 3C 04 00 00 lui $a0, 0
0x0000000000003528: 34 84 5F E4 ori $a0, $a0, 0x5fe4
0x000000000000352c: 00 00 00 00 nop
0x0000000000003530: 00 00 00 00 nop
0x0000000000003534: 00 00 00 00 nop
0x0000000000003538: 02 64 00 20 add $zero, $s3, $a0
0x000000000000353c: 00 00 00 00 nop
0x0000000000003540: 00 00 00 00 nop
0x0000000000003544: 00 00 00 00 nop
0x0000000000003548: AF A0 00 00 sw $zero, ($sp)
0x000000000000354c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003550: 3C 00 35 58 lui $zero, 0x3558
0x0000000000003554: 00 00 00 00 nop
0x0000000000003558: 3C 03 00 00 lui $v1, 0
0x000000000000355c: 34 63 05 95 ori $v1, $v1, 0x595
0x0000000000003560: 3C 12 FF FF lui $s2, 0xffff
0x0000000000003564: 36 52 D2 04 ori $s2, $s2, 0xd204
0x0000000000003568: 00 00 00 00 nop
0x000000000000356c: 00 00 00 00 nop
0x0000000000003570: 00 00 00 00 nop
0x0000000000003574: 00 72 10 22 sub $v0, $v1, $s2
0x0000000000003578: 00 00 00 00 nop
0x000000000000357c: 00 00 00 00 nop
0x0000000000003580: 00 00 00 00 nop
0x0000000000003584: AF A2 00 00 sw $v0, ($sp)
0x0000000000003588: 03 BC E8 20 add $sp, $sp, $gp
0x000000000000358c: 3C 00 35 94 lui $zero, 0x3594
0x0000000000003590: 00 00 00 00 nop
0x0000000000003594: 3C 0F 00 00 lui $t7, 0
0x0000000000003598: 35 EF 07 CE ori $t7, $t7, 0x7ce
0x000000000000359c: 3C 06 00 00 lui $a2, 0
0x00000000000035a0: 34 C6 6C 89 ori $a2, $a2, 0x6c89
0x00000000000035a4: 00 00 00 00 nop
0x00000000000035a8: 00 00 00 00 nop
0x00000000000035ac: 00 00 00 00 nop
0x00000000000035b0: 01 E6 00 22 sub $zero, $t7, $a2
0x00000000000035b4: 00 00 00 00 nop
0x00000000000035b8: 00 00 00 00 nop
0x00000000000035bc: 00 00 00 00 nop
0x00000000000035c0: AF A0 00 00 sw $zero, ($sp)
0x00000000000035c4: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000035c8: 3C 00 35 D0 lui $zero, 0x35d0
0x00000000000035cc: 00 00 00 00 nop
0x00000000000035d0: 3C 15 FF FF lui $s5, 0xffff
0x00000000000035d4: 36 B5 86 75 ori $s5, $s5, 0x8675
0x00000000000035d8: 3C 08 FF FF lui $t0, 0xffff
0x00000000000035dc: 35 08 AA 15 ori $t0, $t0, 0xaa15
0x00000000000035e0: 00 00 00 00 nop
0x00000000000035e4: 00 00 00 00 nop
0x00000000000035e8: 00 00 00 00 nop
0x00000000000035ec: 31 01 00 01 andi $at, $t0, 1
0x00000000000035f0: 00 00 00 00 nop
0x00000000000035f4: 00 00 00 00 nop
0x00000000000035f8: 00 00 00 00 nop
0x00000000000035fc: AF A1 00 00 sw $at, ($sp)
0x0000000000003600: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003604: 3C 00 36 0C lui $zero, 0x360c
0x0000000000003608: 00 00 00 00 nop
0x000000000000360c: 3C 14 FF FF lui $s4, 0xffff
0x0000000000003610: 36 94 8B 2C ori $s4, $s4, 0x8b2c
0x0000000000003614: 3C 0A FF FF lui $t2, 0xffff
0x0000000000003618: 35 4A 95 2B ori $t2, $t2, 0x952b
0x000000000000361c: 00 00 00 00 nop
0x0000000000003620: 00 00 00 00 nop
0x0000000000003624: 00 00 00 00 nop
0x0000000000003628: 31 40 00 1C andi $zero, $t2, 0x1c
0x000000000000362c: 00 00 00 00 nop
0x0000000000003630: 00 00 00 00 nop
0x0000000000003634: 00 00 00 00 nop
0x0000000000003638: AF A0 00 00 sw $zero, ($sp)
0x000000000000363c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003640: 3C 00 36 48 lui $zero, 0x3648
0x0000000000003644: 00 00 00 00 nop
0x0000000000003648: 3C 18 FF FF lui $t8, 0xffff
0x000000000000364c: 37 18 C5 28 ori $t8, $t8, 0xc528
0x0000000000003650: 3C 1B FF FF lui $k1, 0xffff
0x0000000000003654: 37 7B 8A 3E ori $k1, $k1, 0x8a3e
0x0000000000003658: 00 00 00 00 nop
0x000000000000365c: 00 00 00 00 nop
0x0000000000003660: 00 00 00 00 nop
0x0000000000003664: 33 63 00 19 andi $v1, $k1, 0x19
0x0000000000003668: 00 00 00 00 nop
0x000000000000366c: 00 00 00 00 nop
0x0000000000003670: 00 00 00 00 nop
0x0000000000003674: AF A3 00 00 sw $v1, ($sp)
0x0000000000003678: 03 BC E8 20 add $sp, $sp, $gp
0x000000000000367c: 3C 00 36 84 lui $zero, 0x3684
0x0000000000003680: 00 00 00 00 nop
0x0000000000003684: 3C 15 00 00 lui $s5, 0
0x0000000000003688: 36 B5 0B 42 ori $s5, $s5, 0xb42
0x000000000000368c: 3C 16 00 00 lui $s6, 0
0x0000000000003690: 36 D6 06 56 ori $s6, $s6, 0x656
0x0000000000003694: 00 00 00 00 nop
0x0000000000003698: 00 00 00 00 nop
0x000000000000369c: 00 00 00 00 nop
0x00000000000036a0: 02 B6 00 25 or $zero, $s5, $s6
0x00000000000036a4: 00 00 00 00 nop
0x00000000000036a8: 00 00 00 00 nop
0x00000000000036ac: 00 00 00 00 nop
0x00000000000036b0: AF A0 00 00 sw $zero, ($sp)
0x00000000000036b4: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000036b8: 3C 00 36 C0 lui $zero, 0x36c0
0x00000000000036bc: 00 00 00 00 nop
0x00000000000036c0: 3C 1B 00 00 lui $k1, 0
0x00000000000036c4: 37 7B 1C 84 ori $k1, $k1, 0x1c84
0x00000000000036c8: 3C 14 00 00 lui $s4, 0
0x00000000000036cc: 36 94 16 52 ori $s4, $s4, 0x1652
0x00000000000036d0: 00 00 00 00 nop
0x00000000000036d4: 00 00 00 00 nop
0x00000000000036d8: 00 00 00 00 nop
0x00000000000036dc: 03 74 B8 24 and $s7, $k1, $s4
0x00000000000036e0: 00 00 00 00 nop
0x00000000000036e4: 00 00 00 00 nop
0x00000000000036e8: 00 00 00 00 nop
0x00000000000036ec: AF B7 00 00 sw $s7, ($sp)
0x00000000000036f0: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000036f4: 3C 00 36 FC lui $zero, 0x36fc
0x00000000000036f8: 00 00 00 00 nop
0x00000000000036fc: 3C 05 FF FF lui $a1, 0xffff
0x0000000000003700: 34 A5 91 D1 ori $a1, $a1, 0x91d1
0x0000000000003704: 3C 07 00 00 lui $a3, 0
0x0000000000003708: 34 E7 14 A2 ori $a3, $a3, 0x14a2
0x000000000000370c: 00 00 00 00 nop
0x0000000000003710: 00 00 00 00 nop
0x0000000000003714: 00 00 00 00 nop
0x0000000000003718: 00 A7 00 24 and $zero, $a1, $a3
0x000000000000371c: 00 00 00 00 nop
0x0000000000003720: 00 00 00 00 nop
0x0000000000003724: 00 00 00 00 nop
0x0000000000003728: AF A0 00 00 sw $zero, ($sp)
0x000000000000372c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003730: 3C 00 37 38 lui $zero, 0x3738
0x0000000000003734: 00 00 00 00 nop
0x0000000000003738: 3C 06 00 00 lui $a2, 0
0x000000000000373c: 34 C6 21 95 ori $a2, $a2, 0x2195
0x0000000000003740: 3C 03 00 00 lui $v1, 0
0x0000000000003744: 34 63 32 04 ori $v1, $v1, 0x3204
0x0000000000003748: 00 00 00 00 nop
0x000000000000374c: 00 00 00 00 nop
0x0000000000003750: 00 00 00 00 nop
0x0000000000003754: 00 C3 98 25 or $s3, $a2, $v1
0x0000000000003758: 00 00 00 00 nop
0x000000000000375c: 00 00 00 00 nop
0x0000000000003760: 00 00 00 00 nop
0x0000000000003764: AF B3 00 00 sw $s3, ($sp)
0x0000000000003768: 03 BC E8 20 add $sp, $sp, $gp
0x000000000000376c: 3C 00 37 74 lui $zero, 0x3774
0x0000000000003770: 00 00 00 00 nop
0x0000000000003774: 3C 15 00 00 lui $s5, 0
0x0000000000003778: 36 B5 3B CD ori $s5, $s5, 0x3bcd
0x000000000000377c: 00 00 00 00 nop
0x0000000000003780: 00 00 00 00 nop
0x0000000000003784: 00 00 00 00 nop
0x0000000000003788: 22 AF E2 47 addi $t7, $s5, -0x1db9
0x000000000000378c: 00 00 00 00 nop
0x0000000000003790: 00 00 00 00 nop
0x0000000000003794: 00 00 00 00 nop
0x0000000000003798: AF AF 00 00 sw $t7, ($sp)
0x000000000000379c: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000037a0: 3C 00 37 A8 lui $zero, 0x37a8
0x00000000000037a4: 00 00 00 00 nop
0x00000000000037a8: 3C 01 FF FF lui $at, 0xffff
0x00000000000037ac: 34 21 DC AA ori $at, $at, 0xdcaa
0x00000000000037b0: 00 00 00 00 nop
0x00000000000037b4: 00 00 00 00 nop
0x00000000000037b8: 00 00 00 00 nop
0x00000000000037bc: 20 20 E2 E0 addi $zero, $at, -0x1d20
0x00000000000037c0: 00 00 00 00 nop
0x00000000000037c4: 00 00 00 00 nop
0x00000000000037c8: 00 00 00 00 nop
0x00000000000037cc: AF A0 00 00 sw $zero, ($sp)
0x00000000000037d0: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000037d4: 3C 00 37 DC lui $zero, 0x37dc
0x00000000000037d8: 00 00 00 00 nop
0x00000000000037dc: 3C 1B FF FF lui $k1, 0xffff
0x00000000000037e0: 37 7B E4 6B ori $k1, $k1, 0xe46b
0x00000000000037e4: 00 00 00 00 nop
0x00000000000037e8: 00 00 00 00 nop
0x00000000000037ec: 00 00 00 00 nop
0x00000000000037f0: 33 61 70 2D andi $at, $k1, 0x702d
0x00000000000037f4: 00 00 00 00 nop
0x00000000000037f8: 00 00 00 00 nop
0x00000000000037fc: 00 00 00 00 nop
0x0000000000003800: AF A1 00 00 sw $at, ($sp)
0x0000000000003804: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003808: 3C 00 38 10 lui $zero, 0x3810
0x000000000000380c: 00 00 00 00 nop
0x0000000000003810: 3C 10 FF FF lui $s0, 0xffff
0x0000000000003814: 36 10 A2 EF ori $s0, $s0, 0xa2ef
0x0000000000003818: 00 00 00 00 nop
0x000000000000381c: 00 00 00 00 nop
0x0000000000003820: 00 00 00 00 nop
0x0000000000003824: 32 1B 80 9D andi $k1, $s0, 0x809d
0x0000000000003828: 00 00 00 00 nop
0x000000000000382c: 00 00 00 00 nop
0x0000000000003830: 00 00 00 00 nop
0x0000000000003834: AF BB 00 00 sw $k1, ($sp)
0x0000000000003838: 03 BC E8 20 add $sp, $sp, $gp
0x000000000000383c: 3C 00 38 44 lui $zero, 0x3844
0x0000000000003840: 00 00 00 00 nop
0x0000000000003844: 3C 02 FF FF lui $v0, 0xffff
0x0000000000003848: 34 42 9C 8E ori $v0, $v0, 0x9c8e
0x000000000000384c: 00 00 00 00 nop
0x0000000000003850: 00 00 00 00 nop
0x0000000000003854: 00 00 00 00 nop
0x0000000000003858: 30 40 EB DA andi $zero, $v0, 0xebda
0x000000000000385c: 00 00 00 00 nop
0x0000000000003860: 00 00 00 00 nop
0x0000000000003864: 00 00 00 00 nop
0x0000000000003868: AF A0 00 00 sw $zero, ($sp)
0x000000000000386c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003870: 3C 00 38 78 lui $zero, 0x3878
0x0000000000003874: 00 00 00 00 nop
0x0000000000003878: 3C 0B 00 00 lui $t3, 0
0x000000000000387c: 35 6B 32 26 ori $t3, $t3, 0x3226
0x0000000000003880: 00 00 00 00 nop
0x0000000000003884: 00 00 00 00 nop
0x0000000000003888: 00 00 00 00 nop
0x000000000000388c: 35 61 49 13 ori $at, $t3, 0x4913
0x0000000000003890: 00 00 00 00 nop
0x0000000000003894: 00 00 00 00 nop
0x0000000000003898: 00 00 00 00 nop
0x000000000000389c: AF A1 00 00 sw $at, ($sp)
0x00000000000038a0: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000038a4: 3C 00 38 AC lui $zero, 0x38ac
0x00000000000038a8: 00 00 00 00 nop
0x00000000000038ac: 3C 0E 00 00 lui $t6, 0
0x00000000000038b0: 35 CE 2C B5 ori $t6, $t6, 0x2cb5
0x00000000000038b4: 3C 05 FF FF lui $a1, 0xffff
0x00000000000038b8: 34 A5 AF EF ori $a1, $a1, 0xafef
0x00000000000038bc: 00 00 00 00 nop
0x00000000000038c0: 00 00 00 00 nop
0x00000000000038c4: 00 00 00 00 nop
0x00000000000038c8: 01 C5 00 2A slt $zero, $t6, $a1
0x00000000000038cc: 00 00 00 00 nop
0x00000000000038d0: 00 00 00 00 nop
0x00000000000038d4: 00 00 00 00 nop
0x00000000000038d8: AF A0 00 00 sw $zero, ($sp)
0x00000000000038dc: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000038e0: 3C 00 38 E8 lui $zero, 0x38e8
0x00000000000038e4: 00 00 00 00 nop
0x00000000000038e8: 3C 10 FF FF lui $s0, 0xffff
0x00000000000038ec: 36 10 92 F5 ori $s0, $s0, 0x92f5
0x00000000000038f0: 00 00 00 00 nop
0x00000000000038f4: 00 00 00 00 nop
0x00000000000038f8: 00 00 00 00 nop
0x00000000000038fc: 02 10 88 2A slt $s1, $s0, $s0
0x0000000000003900: 00 00 00 00 nop
0x0000000000003904: 00 00 00 00 nop
0x0000000000003908: 00 00 00 00 nop
0x000000000000390c: AF B1 00 00 sw $s1, ($sp)
0x0000000000003910: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003914: 3C 00 39 1C lui $zero, 0x391c
0x0000000000003918: 00 00 00 00 nop
0x000000000000391c: 3C 06 FF FF lui $a2, 0xffff
0x0000000000003920: 34 C6 99 7E ori $a2, $a2, 0x997e
0x0000000000003924: 00 00 00 00 nop
0x0000000000003928: 00 00 00 00 nop
0x000000000000392c: 00 00 00 00 nop
0x0000000000003930: 00 CF 78 2B sltu $t7, $a2, $t7
0x0000000000003934: 00 00 00 00 nop
0x0000000000003938: 00 00 00 00 nop
0x000000000000393c: 00 00 00 00 nop
0x0000000000003940: AF AF 00 00 sw $t7, ($sp)
0x0000000000003944: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003948: 3C 00 39 50 lui $zero, 0x3950
0x000000000000394c: 00 00 00 00 nop
0x0000000000003950: 3C 09 FF FF lui $t1, 0xffff
0x0000000000003954: 35 29 97 83 ori $t1, $t1, 0x9783
0x0000000000003958: 00 00 00 00 nop
0x000000000000395c: 00 00 00 00 nop
0x0000000000003960: 00 00 00 00 nop
0x0000000000003964: 01 20 18 2B sltu $v1, $t1, $zero
0x0000000000003968: 00 00 00 00 nop
0x000000000000396c: 00 00 00 00 nop
0x0000000000003970: 00 00 00 00 nop
0x0000000000003974: AF A3 00 00 sw $v1, ($sp)
0x0000000000003978: 03 BC E8 20 add $sp, $sp, $gp
0x000000000000397c: 3C 00 39 84 lui $zero, 0x3984
0x0000000000003980: 00 00 00 00 nop
0x0000000000003984: 3C 15 00 00 lui $s5, 0
0x0000000000003988: 36 B5 0C 7A ori $s5, $s5, 0xc7a
0x000000000000398c: 00 00 00 00 nop
0x0000000000003990: 00 00 00 00 nop
0x0000000000003994: 00 00 00 00 nop
0x0000000000003998: 02 B5 00 2B sltu $zero, $s5, $s5
0x000000000000399c: 00 00 00 00 nop
0x00000000000039a0: 00 00 00 00 nop
0x00000000000039a4: 00 00 00 00 nop
0x00000000000039a8: AF A0 00 00 sw $zero, ($sp)
0x00000000000039ac: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000039b0: 3C 00 39 B8 lui $zero, 0x39b8
0x00000000000039b4: 00 00 00 00 nop
0x00000000000039b8: 3C 05 FF FF lui $a1, 0xffff
0x00000000000039bc: 34 A5 E4 41 ori $a1, $a1, 0xe441
0x00000000000039c0: 3C 0E 00 00 lui $t6, 0
0x00000000000039c4: 35 CE 18 76 ori $t6, $t6, 0x1876
0x00000000000039c8: 00 00 00 00 nop
0x00000000000039cc: 00 00 00 00 nop
0x00000000000039d0: 00 00 00 00 nop
0x00000000000039d4: 00 AE A8 2B sltu $s5, $a1, $t6
0x00000000000039d8: 00 00 00 00 nop
0x00000000000039dc: 00 00 00 00 nop
0x00000000000039e0: 00 00 00 00 nop
0x00000000000039e4: AF B5 00 00 sw $s5, ($sp)
0x00000000000039e8: 03 BC E8 20 add $sp, $sp, $gp
0x00000000000039ec: 3C 00 39 F4 lui $zero, 0x39f4
0x00000000000039f0: 00 00 00 00 nop
0x00000000000039f4: 3C 0D FF FF lui $t5, 0xffff
0x00000000000039f8: 35 AD 97 EB ori $t5, $t5, 0x97eb
0x00000000000039fc: 3C 07 00 00 lui $a3, 0
0x0000000000003a00: 34 E7 0A DB ori $a3, $a3, 0xadb
0x0000000000003a04: 00 00 00 00 nop
0x0000000000003a08: 00 00 00 00 nop
0x0000000000003a0c: 00 00 00 00 nop
0x0000000000003a10: 01 A7 00 2B sltu $zero, $t5, $a3
0x0000000000003a14: 00 00 00 00 nop
0x0000000000003a18: 00 00 00 00 nop
0x0000000000003a1c: 00 00 00 00 nop
0x0000000000003a20: AF A0 00 00 sw $zero, ($sp)
0x0000000000003a24: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003a28: 3C 00 3A 30 lui $zero, 0x3a30
0x0000000000003a2c: 00 00 00 00 nop
0x0000000000003a30: 3C 09 00 00 lui $t1, 0
0x0000000000003a34: 35 29 12 27 ori $t1, $t1, 0x1227
0x0000000000003a38: 3C 18 00 00 lui $t8, 0
0x0000000000003a3c: 37 18 6E 19 ori $t8, $t8, 0x6e19
0x0000000000003a40: 00 00 00 00 nop
0x0000000000003a44: 00 00 00 00 nop
0x0000000000003a48: 00 00 00 00 nop
0x0000000000003a4c: 15 38 3A 78 bne $t1, $t8, 0x12430
0x0000000000003a50: 00 00 00 00 nop
0x0000000000003a54: 00 00 00 00 nop
0x0000000000003a58: 00 00 00 00 nop
0x0000000000003a5c: 00 00 00 00 nop
0x0000000000003a60: AF A9 00 00 sw $t1, ($sp)
0x0000000000003a64: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003a68: AF B8 00 00 sw $t8, ($sp)
0x0000000000003a6c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003a70: 3C 00 3A 90 lui $zero, 0x3a90
0x0000000000003a74: 00 00 00 00 nop
0x0000000000003a78: 00 00 00 00 nop
0x0000000000003a7c: 00 00 00 00 nop
0x0000000000003a80: 00 00 00 00 nop
0x0000000000003a84: 00 00 00 00 nop
0x0000000000003a88: 3C 00 3A 54 lui $zero, 0x3a54
0x0000000000003a8c: 00 00 00 00 nop
0x0000000000003a90: 3C 0B 00 00 lui $t3, 0
0x0000000000003a94: 35 6B 10 E0 ori $t3, $t3, 0x10e0
0x0000000000003a98: 3C 0B FF FF lui $t3, 0xffff
0x0000000000003a9c: 35 6B AF 57 ori $t3, $t3, 0xaf57
0x0000000000003aa0: 00 00 00 00 nop
0x0000000000003aa4: 00 00 00 00 nop
0x0000000000003aa8: 00 00 00 00 nop
0x0000000000003aac: 15 6B 3A D8 bne $t3, $t3, 0x12610
0x0000000000003ab0: 00 00 00 00 nop
0x0000000000003ab4: 00 00 00 00 nop
0x0000000000003ab8: 00 00 00 00 nop
0x0000000000003abc: 00 00 00 00 nop
0x0000000000003ac0: AF AB 00 00 sw $t3, ($sp)
0x0000000000003ac4: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003ac8: AF AB 00 00 sw $t3, ($sp)
0x0000000000003acc: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003ad0: 3C 00 3A F0 lui $zero, 0x3af0
0x0000000000003ad4: 00 00 00 00 nop
0x0000000000003ad8: 00 00 00 00 nop
0x0000000000003adc: 00 00 00 00 nop
0x0000000000003ae0: 00 00 00 00 nop
0x0000000000003ae4: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003ae8: 3C 00 3A B4 lui $zero, 0x3ab4
0x0000000000003aec: 00 00 00 00 nop
0x0000000000003af0: 3C 1B 00 00 lui $k1, 0
0x0000000000003af4: 37 7B 5A 2E ori $k1, $k1, 0x5a2e
0x0000000000003af8: 00 00 00 00 nop
0x0000000000003afc: 00 00 00 00 nop
0x0000000000003b00: 00 00 00 00 nop
0x0000000000003b04: 10 1B 3B 28 beq $zero, $k1, 0x127a8
0x0000000000003b08: 00 00 00 00 nop
0x0000000000003b0c: 00 00 00 00 nop
0x0000000000003b10: 00 00 00 00 nop
0x0000000000003b14: 00 00 00 00 nop
0x0000000000003b18: AF BB 00 00 sw $k1, ($sp)
0x0000000000003b1c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003b20: 3C 00 3B 40 lui $zero, 0x3b40
0x0000000000003b24: 00 00 00 00 nop
0x0000000000003b28: 00 00 00 00 nop
0x0000000000003b2c: 00 00 00 00 nop
0x0000000000003b30: 00 00 00 00 nop
0x0000000000003b34: 00 00 00 00 nop
0x0000000000003b38: 3C 00 3B 0C lui $zero, 0x3b0c
0x0000000000003b3c: 00 00 00 00 nop
0x0000000000003b40: 3C 1B FF FF lui $k1, 0xffff
0x0000000000003b44: 37 7B 99 2F ori $k1, $k1, 0x992f
0x0000000000003b48: 00 00 00 00 nop
0x0000000000003b4c: 00 00 00 00 nop
0x0000000000003b50: 00 00 00 00 nop
0x0000000000003b54: 10 1B 3B 78 beq $zero, $k1, 0x12938
0x0000000000003b58: 00 00 00 00 nop
0x0000000000003b5c: 00 00 00 00 nop
0x0000000000003b60: 00 00 00 00 nop
0x0000000000003b64: 00 00 00 00 nop
0x0000000000003b68: AF BB 00 00 sw $k1, ($sp)
0x0000000000003b6c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003b70: 3C 00 3B 90 lui $zero, 0x3b90
0x0000000000003b74: 00 00 00 00 nop
0x0000000000003b78: 00 00 00 00 nop
0x0000000000003b7c: 00 00 00 00 nop
0x0000000000003b80: 00 00 00 00 nop
0x0000000000003b84: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003b88: 3C 00 3B 5C lui $zero, 0x3b5c
0x0000000000003b8c: 00 00 00 00 nop
0x0000000000003b90: 3C 00 00 00 lui $zero, 0
0x0000000000003b94: 34 00 7F 6E ori $zero, $zero, 0x7f6e
0x0000000000003b98: 00 00 00 00 nop
0x0000000000003b9c: 00 00 00 00 nop
0x0000000000003ba0: 00 00 00 00 nop
0x0000000000003ba4: 3C 00 3B C8 lui $zero, 0x3bc8
0x0000000000003ba8: 00 00 00 00 nop
0x0000000000003bac: 00 00 00 00 nop
0x0000000000003bb0: 00 00 00 00 nop
0x0000000000003bb4: 00 00 00 00 nop
0x0000000000003bb8: AF A0 00 00 sw $zero, ($sp)
0x0000000000003bbc: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003bc0: 3C 00 3B E0 lui $zero, 0x3be0
0x0000000000003bc4: 00 00 00 00 nop
0x0000000000003bc8: 00 00 00 00 nop
0x0000000000003bcc: 00 00 00 00 nop
0x0000000000003bd0: 00 00 00 00 nop
0x0000000000003bd4: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003bd8: 3C 00 3B AC lui $zero, 0x3bac
0x0000000000003bdc: 00 00 00 00 nop
0x0000000000003be0: 3C 14 00 00 lui $s4, 0
0x0000000000003be4: 36 94 4B 0D ori $s4, $s4, 0x4b0d
0x0000000000003be8: 00 00 00 00 nop
0x0000000000003bec: 00 00 00 00 nop
0x0000000000003bf0: 00 00 00 00 nop
0x0000000000003bf4: 14 14 3C 18 bne $zero, $s4, 0x12c58
0x0000000000003bf8: 00 00 00 00 nop
0x0000000000003bfc: 00 00 00 00 nop
0x0000000000003c00: 00 00 00 00 nop
0x0000000000003c04: 00 00 00 00 nop
0x0000000000003c08: AF B4 00 00 sw $s4, ($sp)
0x0000000000003c0c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003c10: 3C 00 3C 30 lui $zero, 0x3c30
0x0000000000003c14: 00 00 00 00 nop
0x0000000000003c18: 00 00 00 00 nop
0x0000000000003c1c: 00 00 00 00 nop
0x0000000000003c20: 00 00 00 00 nop
0x0000000000003c24: 00 00 00 00 nop
0x0000000000003c28: 3C 00 3B FC lui $zero, 0x3bfc
0x0000000000003c2c: 00 00 00 00 nop
0x0000000000003c30: 3C 14 FF FF lui $s4, 0xffff
0x0000000000003c34: 36 94 99 07 ori $s4, $s4, 0x9907
0x0000000000003c38: 00 00 00 00 nop
0x0000000000003c3c: 00 00 00 00 nop
0x0000000000003c40: 00 00 00 00 nop
0x0000000000003c44: 14 14 3C 68 bne $zero, $s4, 0x12de8
0x0000000000003c48: 00 00 00 00 nop
0x0000000000003c4c: 00 00 00 00 nop
0x0000000000003c50: 00 00 00 00 nop
0x0000000000003c54: 00 00 00 00 nop
0x0000000000003c58: AF B4 00 00 sw $s4, ($sp)
0x0000000000003c5c: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003c60: 3C 00 3C 80 lui $zero, 0x3c80
0x0000000000003c64: 00 00 00 00 nop
0x0000000000003c68: 00 00 00 00 nop
0x0000000000003c6c: 00 00 00 00 nop
0x0000000000003c70: 00 00 00 00 nop
0x0000000000003c74: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003c78: 3C 00 3C 4C lui $zero, 0x3c4c
0x0000000000003c7c: 00 00 00 00 nop
0x0000000000003c80: 3C 00 00 00 lui $zero, 0
0x0000000000003c84: 34 00 5E 4D ori $zero, $zero, 0x5e4d
0x0000000000003c88: 00 00 00 00 nop
0x0000000000003c8c: 00 00 00 00 nop
0x0000000000003c90: 00 00 00 00 nop
0x0000000000003c94: 14 00 00 08 bnez $zero, 0x3cb8
0x0000000000003c98: 00 00 00 00 nop
0x0000000000003c9c: 00 00 00 00 nop
0x0000000000003ca0: 00 00 00 00 nop
0x0000000000003ca4: 00 00 00 00 nop
0x0000000000003ca8: AF A0 00 00 sw $zero, ($sp)
0x0000000000003cac: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003cb0: 3C 00 3C D0 lui $zero, 0x3cd0
0x0000000000003cb4: 00 00 00 00 nop
0x0000000000003cb8: 00 00 00 00 nop
0x0000000000003cbc: 00 00 00 00 nop
0x0000000000003cc0: 00 00 00 00 nop
0x0000000000003cc4: 3C 00 3C 9C lui $zero, 0x3c9c
0x0000000000003cc8: 00 00 00 00 nop
0x0000000000003ccc: 3C 17 00 00 lui $s7, 0
0x0000000000003cd0: 36 F7 6B DA ori $s7, $s7, 0x6bda
0x0000000000003cd4: 00 00 00 00 nop
0x0000000000003cd8: 00 00 00 00 nop
0x0000000000003cdc: 00 00 00 00 nop
0x0000000000003ce0: 14 17 3D 08 bne $zero, $s7, 0x13104
0x0000000000003ce4: 00 00 00 00 nop
0x0000000000003ce8: 00 00 00 00 nop
0x0000000000003cec: 00 00 00 00 nop
0x0000000000003cf0: 00 00 00 00 nop
0x0000000000003cf4: AF B7 00 00 sw $s7, ($sp)
0x0000000000003cf8: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003cfc: 3C 00 3D 20 lui $zero, 0x3d20
0x0000000000003d00: 00 00 00 00 nop
0x0000000000003d04: 00 00 00 00 nop
0x0000000000003d08: 00 00 00 00 nop
0x0000000000003d0c: 00 00 00 00 nop
0x0000000000003d10: 00 00 00 00 nop
0x0000000000003d14: 3C 00 3C EC lui $zero, 0x3cec
0x0000000000003d18: 00 00 00 00 nop
0x0000000000003d1c: 3C 17 FF FF lui $s7, 0xffff
0x0000000000003d20: 36 F7 EB 69 ori $s7, $s7, 0xeb69
0x0000000000003d24: 00 00 00 00 nop
0x0000000000003d28: 00 00 00 00 nop
0x0000000000003d2c: 00 00 00 00 nop
0x0000000000003d30: 14 17 3D 58 bne $zero, $s7, 0x13294
0x0000000000003d34: 00 00 00 00 nop
0x0000000000003d38: 00 00 00 00 nop
0x0000000000003d3c: 00 00 00 00 nop
0x0000000000003d40: 00 00 00 00 nop
0x0000000000003d44: AF B7 00 00 sw $s7, ($sp)
0x0000000000003d48: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003d4c: 3C 00 3D 70 lui $zero, 0x3d70
0x0000000000003d50: 00 00 00 00 nop
0x0000000000003d54: 00 00 00 00 nop
0x0000000000003d58: 00 00 00 00 nop
0x0000000000003d5c: 00 00 00 00 nop
0x0000000000003d60: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003d64: 3C 00 3D 3C lui $zero, 0x3d3c
0x0000000000003d68: 00 00 00 00 nop
0x0000000000003d6c: 3C 00 00 00 lui $zero, 0
0x0000000000003d70: 34 00 78 4A ori $zero, $zero, 0x784a
0x0000000000003d74: 00 00 00 00 nop
0x0000000000003d78: 00 00 00 00 nop
0x0000000000003d7c: 00 00 00 00 nop
0x0000000000003d80: 14 00 00 08 bnez $zero, 0x3da4
0x0000000000003d84: 00 00 00 00 nop
0x0000000000003d88: 00 00 00 00 nop
0x0000000000003d8c: 00 00 00 00 nop
0x0000000000003d90: 00 00 00 00 nop
0x0000000000003d94: AF A0 00 00 sw $zero, ($sp)
0x0000000000003d98: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003d9c: 3C 00 3D C0 lui $zero, 0x3dc0
0x0000000000003da0: 00 00 00 00 nop
0x0000000000003da4: 00 00 00 00 nop
0x0000000000003da8: 00 00 00 00 nop
0x0000000000003dac: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003db0: 3C 00 3D 8C lui $zero, 0x3d8c
0x0000000000003db4: 00 00 00 00 nop
0x0000000000003db8: 3C 1A 00 00 lui $k0, 0
0x0000000000003dbc: 37 5A 2C 79 ori $k0, $k0, 0x2c79
0x0000000000003dc0: 00 00 00 00 nop
0x0000000000003dc4: 00 00 00 00 nop
0x0000000000003dc8: 00 00 00 00 nop
0x0000000000003dcc: 10 1A 3D F8 beq $zero, $k0, 0x135b0
0x0000000000003dd0: 00 00 00 00 nop
0x0000000000003dd4: 00 00 00 00 nop
0x0000000000003dd8: 00 00 00 00 nop
0x0000000000003ddc: 00 00 00 00 nop
0x0000000000003de0: AF BA 00 00 sw $k0, ($sp)
0x0000000000003de4: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003de8: 3C 00 3E 10 lui $zero, 0x3e10
0x0000000000003dec: 00 00 00 00 nop
0x0000000000003df0: 00 00 00 00 nop
0x0000000000003df4: 00 00 00 00 nop
0x0000000000003df8: 00 00 00 00 nop
0x0000000000003dfc: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003e00: 3C 00 3D DC lui $zero, 0x3ddc
0x0000000000003e04: 00 00 00 00 nop
0x0000000000003e08: 3C 1A FF FF lui $k0, 0xffff
0x0000000000003e0c: 37 5A F4 AA ori $k0, $k0, 0xf4aa
0x0000000000003e10: 00 00 00 00 nop
0x0000000000003e14: 00 00 00 00 nop
0x0000000000003e18: 00 00 00 00 nop
0x0000000000003e1c: 10 1A 3E 48 beq $zero, $k0, 0x13740
0x0000000000003e20: 00 00 00 00 nop
0x0000000000003e24: 00 00 00 00 nop
0x0000000000003e28: 00 00 00 00 nop
0x0000000000003e2c: 00 00 00 00 nop
0x0000000000003e30: AF BA 00 00 sw $k0, ($sp)
0x0000000000003e34: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003e38: 3C 00 3E 60 lui $zero, 0x3e60
0x0000000000003e3c: 00 00 00 00 nop
0x0000000000003e40: 00 00 00 00 nop
0x0000000000003e44: 00 00 00 00 nop
0x0000000000003e48: 00 00 00 00 nop
0x0000000000003e4c: 00 00 00 00 nop
0x0000000000003e50: 3C 00 3E 2C lui $zero, 0x3e2c
0x0000000000003e54: 00 00 00 00 nop
0x0000000000003e58: 3C 00 00 00 lui $zero, 0
0x0000000000003e5c: 34 00 77 A5 ori $zero, $zero, 0x77a5
0x0000000000003e60: 00 00 00 00 nop
0x0000000000003e64: 00 00 00 00 nop
0x0000000000003e68: 00 00 00 00 nop
0x0000000000003e6c: 3C 00 3E 98 lui $zero, 0x3e98
0x0000000000003e70: 00 00 00 00 nop
0x0000000000003e74: 00 00 00 00 nop
0x0000000000003e78: 00 00 00 00 nop
0x0000000000003e7c: 00 00 00 00 nop
0x0000000000003e80: AF A0 00 00 sw $zero, ($sp)
0x0000000000003e84: 03 BC E8 20 add $sp, $sp, $gp
0x0000000000003e88: 3C 00 3E B0 lui $zero, 0x3eb0
0x0000000000003e8c: 00 00 00 00 nop
0x0000000000003e90: 00 00 00 00 nop
0x0000000000003e94: 00 00 00 00 nop
0x0000000000003e98: 00 00 00 00 nop
0x0000000000003e9c: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003ea0: 3C 00 3E 7C lui $zero, 0x3e7c
0x0000000000003ea4: 00 00 00 00 nop
0x0000000000003ea8: 3C 00 3E D8 lui $zero, 0x3ed8
0x0000000000003eac: 00 00 00 00 nop
0x0000000000003eb0: 00 1F 68 20 add $t5, $zero, $ra
0x0000000000003eb4: 01 A0 00 08 jr $t5
0x0000000000003eb8: 00 00 00 00 nop
0x0000000000003ebc: 00 00 00 00 nop
0x0000000000003ec0: 00 00 00 00 nop
0x0000000000003ec4: 00 00 00 00 nop
0x0000000000003ec8: 3C 00 3E F8 lui $zero, 0x3ef8
0x0000000000003ecc: 00 00 00 00 nop
0x0000000000003ed0: 0C 00 0F AE jal 0x3eb8
0x0000000000003ed4: 00 00 00 00 nop
0x0000000000003ed8: 00 00 00 00 nop
0x0000000000003edc: 00 00 00 00 nop
0x0000000000003ee0: 00 00 00 00 nop
0x0000000000003ee4: 34 1E 00 08 ori $fp, $zero, 8
0x0000000000003ee8: 3C 00 3E C4 lui $zero, 0x3ec4
0x0000000000003eec: 00 00 00 00 nop
0x0000000000003ef0: 3C 01 24 F6 lui $at, 0x24f6
0x0000000000003ef4: 34 21 C6 7F ori $at, $at, 0xc67f
0x0000000000003ef8: 3C 1B 01 D5 lui $k1, 0x1d5
0x0000000000003efc: 37 7B D3 0E ori $k1, $k1, 0xd30e
0x0000000000003f00: 00 00 00 00 nop
0x0000000000003f04: 00 00 00 00 nop
0x0000000000003f08: 00 00 00 00 nop
0x0000000000003f0c: 00 3B 00 18 mult $at, $k1
0x0000000000003f10: 00 00 00 00 nop
0x0000000000003f14: 00 00 00 00 nop
0x0000000000003f18: 00 00 00 00 nop
0x0000000000003f1c: 3C 00 3F 2C lui $zero, 0x3f2c
0x0000000000003f20: 00 00 00 00 nop
0x0000000000003f24: 3C 0F 08 BD lui $t7, 0x8bd
0x0000000000003f28: 35 EF B6 CE ori $t7, $t7, 0xb6ce
0x0000000000003f2c: 3C 19 DE A9 lui $t9, 0xdea9
0x0000000000003f30: 37 39 89 CC ori $t9, $t9, 0x89cc
0x0000000000003f34: 00 00 00 00 nop
0x0000000000003f38: 00 00 00 00 nop
0x0000000000003f3c: 00 00 00 00 nop
0x0000000000003f40: 01 F9 00 19 multu $t7, $t9
0x0000000000003f44: 00 00 00 00 nop
0x0000000000003f48: 00 00 00 00 nop
0x0000000000003f4c: 00 00 00 00 nop
0x0000000000003f50: 3C 00 3F 60 lui $zero, 0x3f60
0x0000000000003f54: 00 00 00 00 nop
0x0000000000003f58: 3C 02 A5 24 lui $v0, 0xa524
0x0000000000003f5c: 34 42 AB DB ori $v0, $v0, 0xabdb
0x0000000000003f60: 3C 00 86 C9 lui $zero, 0x86c9
0x0000000000003f64: 34 00 94 1E ori $zero, $zero, 0x941e
0x0000000000003f68: 00 00 00 00 nop
0x0000000000003f6c: 00 00 00 00 nop
0x0000000000003f70: 00 00 00 00 nop
0x0000000000003f74: 00 40 00 11 mthi $v0
0x0000000000003f78: 00 00 00 00 nop
0x0000000000003f7c: 00 00 00 00 nop
0x0000000000003f80: 00 00 00 00 nop
0x0000000000003f84: 3C 00 3F 94 lui $zero, 0x3f94
0x0000000000003f88: 00 00 00 00 nop
0x0000000000003f8c: 3C 0A 97 30 lui $t2, 0x9730
0x0000000000003f90: 35 4A C5 4B ori $t2, $t2, 0xc54b
0x0000000000003f94: 3C 00 5F 99 lui $zero, 0x5f99
0x0000000000003f98: 34 00 C1 4A ori $zero, $zero, 0xc14a
0x0000000000003f9c: 00 00 00 00 nop
0x0000000000003fa0: 00 00 00 00 nop
0x0000000000003fa4: 00 00 00 00 nop
0x0000000000003fa8: 01 40 00 13 mtlo $t2
0x0000000000003fac: 00 00 00 00 nop
0x0000000000003fb0: 00 00 00 00 nop
0x0000000000003fb4: 00 00 00 00 nop
0x0000000000003fb8: 3C 00 3F C8 lui $zero, 0x3fc8
0x0000000000003fbc: 00 00 00 00 nop
0x0000000000003fc0: 3C 00 3F C8 lui $zero, 0x3fc8
0x0000000000003fc4: 00 00 00 00 nop
0x0000000000003fc8: 00 00 00 00 nop
0x0000000000003fcc: 00 00 00 00 nop
0x0000000000003fd0: 00 00 00 00 nop
0x0000000000003fd4: 00 00 00 00 nop
0x0000000000003fd8: 00 00 00 00 nop
0x0000000000003fdc: 00 00 00 00 nop
0x0000000000003fe0: 00 00 00 00 nop
0x0000000000003fe4: 00 00 00 00 nop
0x0000000000003fe8: 00 00 00 00 nop
0x0000000000003fec: 00 00 00 00 nop
0x0000000000003ff0: 00 00 00 00 nop
0x0000000000003ff4: 00 00 00 00 nop
0x0000000000003ff8: 00 00 00 00 nop
0x0000000000003ffc: 00 00 00 00 nop
0x0000000000004000: 00 00 00 00 nop
0x0000000000004004: 00 00 00 00 nop
0x0000000000004008: 00 00 00 00 nop
0x000000000000400c: 00 00 00 00 nop
0x0000000000004010: 00 00 00 00 nop
0x0000000000004014: 00 00 00 00 nop
0x0000000000004018: 00 00 00 00 nop
0x000000000000401c: 00 00 00 00 nop
0x0000000000004020: 00 00 00 00 nop
0x0000000000004024: 00 00 00 00 nop
0x0000000000004028: 00 00 00 00 nop
0x000000000000402c: 00 00 00 00 nop
0x0000000000004030: 00 00 00 00 nop
0x0000000000004034: 00 00 00 00 nop
0x0000000000004038: 00 00 00 00 nop
0x000000000000403c: 00 00 00 00 nop
0x0000000000004040: 00 00 00 00 nop
0x0000000000004044: 00 00 00 00 nop
0x0000000000004048: 00 00 00 00 nop
0x000000000000404c: 00 00 00 00 nop
0x0000000000004050: 00 00 00 00 nop
0x0000000000004054: 00 00 00 00 nop
0x0000000000004058: 00 00 00 00 nop
0x000000000000405c: 00 00 00 00 nop
0x0000000000004060: 00 00 00 00 nop
0x0000000000004064: 00 00 00 00 nop
0x0000000000004068: 00 00 00 00 nop
0x000000000000406c: 00 00 00 00 nop
0x0000000000004070: 00 00 00 00 nop
0x0000000000004074: 00 00 00 00 nop
0x0000000000004078: 00 00 00 00 nop
0x000000000000407c: 00 00 00 00 nop
0x0000000000004080: 00 00 00 00 nop
0x0000000000004084: 00 00 00 00 nop
0x0000000000004088: 00 00 00 00 nop
0x000000000000408c: 00 00 00 00 nop
0x0000000000004090: 00 00 00 00 nop
0x0000000000004094: 00 00 00 00 nop
0x0000000000004098: 00 00 00 00 nop
0x000000000000409c: 00 00 00 00 nop
0x00000000000040a0: 00 00 00 00 nop
0x00000000000040a4: 00 00 00 00 nop
0x00000000000040a8: 00 00 00 00 nop
0x00000000000040ac: 00 00 00 00 nop
0x00000000000040b0: 00 00 00 00 nop
0x00000000000040b4: 00 00 00 00 nop
0x00000000000040b8: 00 00 00 00 nop
0x00000000000040bc: 00 00 00 00 nop
0x00000000000040c0: 00 00 00 00 nop
0x00000000000040c4: 00 00 00 00 nop
0x00000000000040c8: 00 00 00 00 nop
0x00000000000040cc: 00 00 00 00 nop
0x00000000000040d0: 00 00 00 00 nop
0x00000000000040d4: 00 00 00 00 nop
0x00000000000040d8: 00 00 00 00 nop
0x00000000000040dc: 00 00 00 00 nop
0x00000000000040e0: 00 00 00 00 nop
0x00000000000040e4: 00 00 00 00 nop
0x00000000000040e8: 00 00 00 00 nop
0x00000000000040ec: 00 00 00 00 nop
0x00000000000040f0: 00 00 00 00 nop
0x00000000000040f4: 00 00 00 00 nop
0x00000000000040f8: 00 00 00 00 nop
0x00000000000040fc: 00 00 00 00 nop
0x0000000000004100: 00 00 00 00 nop
0x0000000000004104: 00 00 00 00 nop
0x0000000000004108: 00 00 00 00 nop
0x000000000000410c: 00 00 00 00 nop
0x0000000000004110: 00 00 00 00 nop
0x0000000000004114: 00 00 00 00 nop
0x0000000000004118: 00 00 00 00 nop
0x000000000000411c: 00 00 00 00 nop
0x0000000000004120: 00 00 00 00 nop
0x0000000000004124: 00 00 00 00 nop
0x0000000000004128: 00 00 00 00 nop
0x000000000000412c: 00 00 00 00 nop
0x0000000000004130: 00 00 00 00 nop
0x0000000000004134: 00 00 00 00 nop
0x0000000000004138: 00 00 00 00 nop
0x000000000000413c: 00 00 00 00 nop
0x0000000000004140: 00 00 00 00 nop
0x0000000000004144: 00 00 00 00 nop
0x0000000000004148: 00 00 00 00 nop
0x000000000000414c: 00 00 00 00 nop
0x0000000000004150: 00 00 00 00 nop
0x0000000000004154: 00 00 00 00 nop
0x0000000000004158: 00 00 00 00 nop
0x000000000000415c: 00 00 00 00 nop
0x0000000000004160: 00 00 00 00 nop
0x0000000000004164: 00 00 00 00 nop
0x0000000000004168: 00 00 00 00 nop
0x000000000000416c: 00 00 00 00 nop
0x0000000000004170: 00 00 00 00 nop
0x0000000000004174: 00 00 00 00 nop
0x0000000000004178: 00 00 00 00 nop
0x000000000000417c: 00 00 00 00 nop
0x0000000000004180: 00 00 00 00 nop
0x0000000000004184: 00 00 00 00 nop
0x0000000000004188: 00 00 00 00 nop
0x000000000000418c: 40 01 70 00 mfc0 $at, $t6, 0
0x0000000000004190: 00 00 08 24 and $at, $zero, $zero
0x0000000000004194: 34 01 30 00 ori $at, $zero, 0x3000
0x0000000000004198: 40 81 70 00 mtc0 $at, $t6, 0
0x000000000000419c: 42 00 00 18 eret