P6 习题分析
wtd
指令:
记temp1为GRF[rs]的32种循环移位的和 如: 123 + 231 + 321
temp2为GRF[rt]的32种循环移位的和
if (temp1 > temp2) 则 把1写入rd
else if (temp1 < temp2) 则 把 -1写入rd
else 把0写入rd
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 controller wire wtd = (opcode_DEin == 6'b0 && func_DEin == 6'b000011 ) ? 1 : 0 ;RegWrite_DEin = (wtd || ...) ? 1 : 0 ; RegDst_DEin = (wtd || ...) ? 2'b01 : ... wire isWtd_DEin = (wtd) ? 1 : 0 ;hazardStall wire wtd = (opcode_DEin == 6'b0 && func_DEin == 6'b000011 ) ? 1 : 0 ;Tuse_RS = (wtd || ...) ? 0 : ... Tuse_RT = (wtd || ...) ? 0 : ... Tnew_DEin = (wtd || ...) ? 1 : ... cauculate( input wire [31 :0 ] A, output wire [31 :0 ] B ) reg [31 :0 ] ans;reg [31 :0 ] temp;integer i;always @(*) begin ans = 32'b0 ; temp = A; for (i = 0 ; i < 32 ; i = i + 1 ) begin temp = {temp[0 ], temp[31 :1 ]}; ans = ans + temp; end end mips writeBack_DEin = (isWtd_DEin == 1 && (rs_sum > rt_sum)) ? 32'b1 : (isWtd_DEin == 1 && (rs_sum < rt_sum)) ? (32'b0 - 32'b1 ) : (isWtd_DEin == 1 && (rs_sum = rt_sum)) ? 32'b0 : ... writeBack_EMin = (isWtd_DEout == 1 || ...) ? writeBack_DEout : ...
btd
指令:
d = (GRF[rt] + GRF[rs])& 32’hfffffffe
d << 1
无条件跳转到pc + 4 + ( d[29:0] || 00 ) + offset
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 controller wire btd = (opcode_DEin == 6'b111110 ) ? 1 : 0 ;Branch_DEin = (btd || ...) ? 1 : 0 ; EXTOp = (btd || ...) ? 2'b01 : ... isBtd_DEin = (btd) ? 1 : 0 ; hazardStall wire btd = (opcode_DEin == 6'b111110 ) ? 1 : 0 ;Tuse_RS = (btd || ...) ? 1 : 0 ; Tuse_RT = (btd || ...) ? 1 : 0 ; Tnew_DEin = (btd || ...) ? `minTnew; cmp assign zero_DEin = (isBtd) ? 1 : 0 ;mips wire [31 :0 ] d = ((A1_DEin + A2_DEin)& 32'hfffffffe ) << 1 ;wire [31 :0 ] distance = {d[29 :0 ], 2'b0 };assign shift = (isBtd_DEin == 1 ) ? (distance + immExt_DEin);
lwz
指令:
和lw
一样读出WD,把它的低5位与GRF[rt]的低5位进行异或,其值为X
找到小于等于X的最大质数,记为Y
把WD写入GRF[Y]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 wire stall_E = (isLwz_DEout == 1 && (rs_DEin == 质数 || rt_DEin == 质数)) ? 1 : 0 ;wire stall_M = (isLwz_EMout == 1 && (RegAddr_MWin == rs_DEin || RegAddr_MWin == rt_DEin)) ? 1 : 0 ;wire [4 :0 ] xor_ans = WD[4 :0 ] ^ A2[4 :0 ];wire [4 :0 ] max_z = (xor_ans >= 31 ) ? 31 :(xor_ans >= 29 ) ? 29 : (xor_ans >= 23 ) ? 23 : (xor_ans >= 19 ) ? 19 : (xor_ans >= 17 ) ? 17 : (xor_ans >= 13 ) ? 13 : (xor_ans >= 11 ) ? 11 : (xor_ans >= 7 ) ? 7 : (xor_ans >= 5 ) ? 5 : (xor_ans >= 3 ) ? 3 : (xor_ans >= 2 ) ? 2 : 1 ; assign RegAddr_MWin = (isLwz_EMout == 1 ) ? max_z : ...
lwc
指令:
读出WD
,WD
是偶数则写入rt
寄存器 , WD
是奇数则写入31号寄存器
1 2 3 4 5 6 controller assign RegDst = (lwc|| ...) ? 2'b00 : mips assign stall_E = (isLwc_E == 1 &s& (rs_D == 31 || rt_D == 31 )) ? 1 : 0 ;assign stall_M = (isLwc_M == 1 && RegAddr_M == 31 && (rs_D == 31 || rt_D == 31 )) ? 1 : 0 ;
fmultu
指令:
R型指令。具体操作为进行一个需要在乘除模块计算3个周期的计算指令,操作细节如下:
首先,对 GPR[rs]
和 GPR[rt]
进行64位无符号乘法,结果记为 prod
。
若 prod
高32位为0,则把 prod[63:32]
保存到 HI
寄存器中,把 prod[31:0]
保存到 LO
寄存器中。
否则,我们找到 prod
中最高位1的出现位置 highbit_1
与 prod
中最低位0的出现位置 lowbit_0
(可以证明,这种情况下 prod
中必定存在至少一个1和一个0) 。之后,记 reverse_bit
为 highbit_1-lowbit_0
的绝对值,可以证明 reverse_bit
必定在 0∼63 内。最后,把 prod[reverse_bit]
进行翻转(0变成1,1变成0),将结果的高32位保存到 HI
寄存器中,将结果的低32位保存到 LO
寄存器中。
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 assign start_DEin = (fmultu) ? 1 : 0 ;assign isFmultu_DEin = (fmultu) ? 1 : 0 ;mult reg [63 :0 ] prod;reg [5 :0 ] highbit_1;reg [5 :0 ] lowbit_0;reg [5 :0 ] reverse_bit;integer i;always @(*) begin if (isFmultu_DEout == 1 ) begin hold_unsign = {{1'b0 }, A} * {{1'b0 }, B}; prod = hold_unsign[63 :0 ]; if (prod[63 :32 ] == 32'b0 ) begin hi_hold = prod[63 :32 ]; lo_hold = prod[31 :0 ]; end else begin for (i = 63 ; i >= 0 ; i = i - 1 ) begin if (prod[i] == 1 ) begin highbit_1 = i; break ; end end for (i = 0 ; i < 64 ; i = i + 1 ) begin if (prod[i] == 0 ) begin lowbit_0 = i; break ; end end reverse_bit = (highbit_1 - lowbit_0 > 0 ) ? highbit_1 - lowbit_0 : lowbit_0 - highbit_1; prod[reverse_bit] = !prod[reverse_bit]; hi_hold = prod[63 :32 ]; lo_hold = prod[31 :0 ]; end end end always @(posedge clk) begin if (isFmultu_DEout == 1 ) begin pause <= 3 ; end end
sbc
指令:
把GRF[rs]分成31-24,23-16,15-8,7-0四个部分,统计每个部分1的个数。如果GRF[rt]是奇数,则将这四个部分按照升序排序组成一个新的数字,写入rd寄存器;如果GRF[rt]是偶数,则将这四个部分按照降序排序组成一个新的数字写入rd寄存器。(排序是稳定排序)
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 module sort( input wire [31 :0 ] A, input wire way, output wire [31 :0 ] B ); reg [7 :0 ] A[4 ]; reg [4 :0 ] Num[4 ]; reg [7 :0 ] holdA; reg [4 :0 ] holdN; reg [31 :0 ] B1; reg [31 :0 ] B2; integer i; integer j; always @(*) begin A[3 ] = A[31 :24 ]; A[2 ] = A[23 :16 ]; A[1 ] = A[15 :8 ]; A[0 ] = A[7 :0 ]; Num[3 ] = A[3 ][0 ] + A[3 ][1 ] + A[3 ][2 ] + A[3 ][3 ] + A[3 ][4 ] + A[3 ][5 ] + A[3 ][6 ] + A[3 ][7 ]; Num[2 ] = A[2 ][0 ] + A[2 ][1 ] + A[2 ][2 ] + A[2 ][3 ] + A[2 ][4 ] + A[2 ][5 ] + A[2 ][6 ] + A[2 ][7 ]; Num[1 ] = A[1 ][0 ] + A[1 ][1 ] + A[1 ][2 ] + A[1 ][3 ] + A[1 ][4 ] + A[1 ][5 ] + A[1 ][6 ] + A[1 ][7 ]; Num[0 ] = A[0 ][0 ] + A[0 ][1 ] + A[0 ][2 ] + A[0 ][3 ] + A[0 ][4 ] + A[0 ][5 ] + A[0 ][6 ] + A[0 ][7 ]; for (i = 3 ; i > 0 ; i = i - 1 ) begin for (j = 3 ; j > 3 - i; j = j - 1 ) begin if (Num[j] < Num[j - 1 ]) begin holdN = Num[j]; holdA = A[j]; Num[j] = Num[j - 1 ]; A[j] = A[j - 1 ]; Num[j - 1 ] = holdN; A[j - 1 ] = holdA; end end end B1 = {A[3 ], A[2 ], A[1 ], A[0 ]}; for (i = 3 ; i > 0 ; i = i - 1 ) begin for (j = 3 ; j > 3 - i; j = j - 1 ) begin if (Num[j] > Num[j - 1 ]) begin holdN = Num[j]; holdA = A[j]; Num[j] = Num[j - 1 ]; A[j] = A[j - 1 ]; Num[j - 1 ] = holdN; A[j - 1 ] = holdA; end end end B2 = {A[3 ], A[2 ], A[1 ], A[0 ]}; assign B = (way == 1 ) ? B1 : B2; end
lwm
指令:
按照lw
的方式从内存中读出的数记作WD
,把WD
写入WD - GRF[rt]
号寄存器。
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 controller wire lwm = (opcode_DEin == 6'b111110 ) ? 1 : 0 ;RegWrite_DEin = (lwm || ...) ? 1 : 0 ; MemRead_DEin = (lwm || ...) ? 1 : 0 ; MemtoReg_DEin = (lwm || ...) ? 1 : 0 ; word_DEin = (lwm || ...) ? 1 : 0 ; EXTOp = (lwm || ...) ? 2'b01 : ... isLwm_DEin = (lwm) ? 1 : 0 ; HazardStall wire lwm = (opcode_DEin == 6'b111110 ) ? 1 : 0 ;Tuse_RS = (lwm || ...) ? 1 : ...; Tuse_RT = (lwm || ...) ? 2 : ...; Tnew_DEin = (lwm || ...) ? 3 : ...; mips stall_E = (isLwm_DEout === 1 ) ? 1 : 0 ; stall_M = (isLwm_EMout === 1 && RegAddr_MWin !== 5'b0 &&(RegAddr_MWin === rs_DEin || RegAddr_WMin === rt_DEin)) ? 1 : 0 ; wire [31 :0 ] lwm_sub = WD - A2_MWin;RegAddr_MWin = (isLwm_EMout === 1 ) ? lwm_sub[4 :0 ] : RegAddr_EMout;