python模拟硬件实现btb和tomasulo算法
生活随笔
收集整理的這篇文章主要介紹了
python模拟硬件实现btb和tomasulo算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本程序在上一個tomasulo算法的基礎上添加了btb分支預測
代碼實現如下
# RISC-V # 小端模式# 硬件 Hardware = {# tag:還剩多久執行完畢; busy:0空閑,1不空閑; op:'lw' 'sw' 'mul' 'addi' 'bne'五條指令# 'addi'指令:'imm'用來存立即數# s1_vj和s2_vk:直接存數; rs_qj和rs_qk:存 'load1' 'mult2' 'add3'等# rs_qj和rs_qk:如果有數據,不需要指針,則這兩個指針置為數字0# 寄存器中,如果有結果直接存數,如果是指針,則同rs_qj和rs_qk存 'load1' 'mult2' 'add3'等# isinstance()函數可以判斷數據類型是不是指定類型,例如isinstance(Hardware['load1']['busy'],int)==True/False'load1': {'tag': 0,'busy': 0,'address': 0,'data': 0,'op' : 0},'load2': {'tag': 0,'busy': 0,'address': 0,'data': 0,'op' : 0},'load3': {'tag': 0,'busy': 0,'address': 0,'data': 0,'op' : 0},'store1': {'tag': 0,'busy': 0,'address': 0,'data': 0,'s1_vj': 0,'rs_qj': 0,'op' : 0},'store2': {'tag': 0,'busy': 0,'address': 0,'data': 0,'s1_vj': 0,'rs_qj': 0,'op' : 0},'store3': {'tag': 0,'busy': 0,'address': 0,'data': 0,'s1_vj': 0,'rs_qj': 0,'op' : 0},'add1': {'tag': 0,'busy': 0,'op': 0,'s1_vj': 0,'s2_vk': 0,'rs_qj': 0,'rs_qk': 0,'imm': 0,'data': 0},'add2': {'tag': 0,'busy': 0,'op': 0,'s1_vj': 0,'s2_vk': 0,'rs_qj': 0,'rs_qk': 0,'imm': 0,'data': 0},'add3': {'tag': 0,'busy': 0,'op': 0,'s1_vj': 0,'s2_vk': 0,'rs_qj': 0,'rs_qk': 0,'imm': 0,'data': 0},'mult1': {'tag': 0,'busy': 0,'op': 0,'s1_vj': 0,'s2_vk': 0,'rs_qj': 0,'rs_qk': 0,'data': 0},'mult2': {'tag': 0,'busy': 0,'op': 0,'s1_vj': 0,'s2_vk': 0,'rs_qj': 0,'rs_qk': 0,'data': 0} } # 調用方式 # Hardware['load1']['busy']='6' # print(Hardware['load1']['busy']) # print(isinstance(Hardware['load1']['busy'],int))'''for key in Hardware:print(Hardware[key]['tag'])pass'''# 寄存器類 X_ = 0x00000033 Register = {0b00000: 0x00000000,0b00001: 0x00000000,0b00010: 0x00000008,0b00011: 0x00000000,0b00100: 0x00000000,0b00101: 0x00000000,0b00110: 0x00000000,0b00111: 0x00000000,0b01000: 0x00000000,0b01001: 0x00000000,0b01010: 0x00000000,0b01011: 0x00000000,0b01100: 0x00000000,0b01101: 0x00000000,0b01110: 0x00000000,0b01111: 0x00000000,0b10000: 0x00000000,0b10001: 0x00000000,0b10010: 0x00000000,0b10011: 0x00000000,0b10100: 0x00000000,0b10101: 0x00000000,0b10110: 0x00000000,0b10111: 0x00000000,0b11000: 0x00000000,0b11001: 0x00000000,0b11010: 0x00000000,0b11011: 0x00000000,0b11100: 0x00000000,0b11101: 0x00000000,0b11110: 0x00000000,0b11111: 0x00000000} pc = 0x00000000 '''Register[0]=0 if(isinstance(Register[0],str)):print(type(Register[0]),'class')print('ss') elif(isinstance(Register[0],int)):print(type(Register[0]), 'int')print('ii')'''# 儲存器類 Memory = {0x00000000: 0x00 }# 控制BTB的執行 BTB={0x00000000:[0x00000000,0,0], #PC:[PC_predict,tag1,tag2];tag1為第一次判斷結果(yes:1/no:0),tag2為第二次判斷結果 }PC_Control = [0,0,0,0]#[PC,PC_IF,PC_ID,PC_EX],分階段存下該階段所執行指令對應的PC值# 初始化內存,大小為16KB def init_Mem():for i in range(2 ** 14):Memory[0x00000000 + i] = 0x00# *****************Tomasulo************** def Refresh(a): # 如果得到了某個數據,則利用這個函數,刷新需要這個數據的所有buffer和寄存器a1 = list(a)a1.pop()a1 = ''.join(a1)if a1 == 'store':Memory[Hardware[a]['address']] = Hardware[a]['data']returnfor key in Register: # 刷新寄存器if Register[key] == a:Register[key] = Hardware[a]['data']passpassfor key in Hardware: # 刷新bufferkey1 = list(key)key1.pop()key1 = ''.join(key1)if key1 == 'load':continueif key1 == 'store':if Hardware[key]['rs_qj'] == a:Hardware[key]['s1_vj'] = Hardware[a]['data']Hardware[key]['rs_qj'] = 0Hardware[key]['tag'] = 2continueif Hardware[key]['rs_qj'] == a or Hardware[key]['rs_qk'] == a:if Hardware[key]['rs_qj'] == a:Hardware[key]['s1_vj'] = Hardware[a]['data']Hardware[key]['rs_qj'] = 0if Hardware[key]['rs_qk'] == a:Hardware[key]['s2_vk'] = Hardware[a]['data']Hardware[key]['rs_qk'] = 0if Hardware[key]['rs_qj'] == 0 and Hardware[key]['rs_qk'] == 0: # 所需數據準備完畢,則進入執行階段if Hardware[key]['op'] == 'addi' or Hardware[key]['op'] == 'bne':Hardware[key]['tag'] = 2elif Hardware[key]['op'] == 'mul':Hardware[key]['tag'] = 10passpasspassIF_Found = False ID_Branch = Falsedef IF():global IF_Found# IF階段# 第一次判斷,PC_Control是否在BTB中global pcif pc== 64:print(pc)PC_Control[0] = pc# PC_Control[0] = PC_Control[0] + 1 # PC_Control[0]表示PC_Control值PC_Control[1] = PC_Control[0] + 1 # PC_Control_IF,IF階段的PC_Controlif PC_Control[0] in BTB:#BTB[PC_Control[1]][1] = 1IF_Found = Trueelse:#BTB[PC_Control[0]] = [0, 0, 0] # 如果沒有命中BTB,插入一條item方便后續操作IF_Found = Falsepassdef ID():global IF_Foundglobal ID_Branchglobal BTB# ID階段PC_Control[2] = PC_Control[1] # PC_Control_ID,ID階段指令對應的PC_Control#opcode = Memory[PC_Control[0]] & 0b1111111instru = 0x00000000for i in range(4):instru += Memory[PC_Control[0] + i] * (256 ** i)opcode = instru & 0b1111111if (IF_Found == False):if opcode == 0b1100011: # 如果是分支指令#這里需要知道當前正在執行的指令的下一條語句,稍后處理這一段ID_Branch = True# BTB[PC_Control[0]] = [48,1,0]else:ID_Branch = Falsereturnelse:pass"""if BTB[PC_Control[2]][1] == 1 and BTB[PC_Control[2]][2] == 1: # 是分支指令,并且命中BTB時,將預測地址賦值給PC_Control,因為PC_Control會自增,這里提前-1PC_Control[0] = BTB[PC_Control[2]][0]""""""if opcode == 0b1100011: # 如果是分支指令BTB[PC_Control[2]][2] = 1else:BTB[PC_Control[2]][2] = 0if BTB[PC_Control[2]][1] == 1 and BTB[PC_Control[2]][2] == 1: # 是分支指令,并且命中BTB時,將預測地址賦值給PC_Control,因為PC_Control會自增,這里提前-1PC_Control[0] = BTB[ PC_Control[2]][0]"""passdef Issue(): # 指令流出# 1 首先檢查是否可進行指令流出# 2 若可以進行指令流出則設置對應硬件的狀態# 3 若流出則安排pc加四的位置global IF_Foundglobal ID_BranchIF_Found = FalseID_Branch = FalseIF()ID()ISA()# 只修改了這次用到的幾個函數,將函數的實現改完,硬件狀態的改變以及是否流出passdef BTB_Exec():global IF_Foundglobal ID_Branchglobal pcif IF_Found == False and ID_Branch == False:returnelif IF_Found == False and ID_Branch == True:BTB[PC_Control[0]] = [pc, 1, 0]elif IF_Found == True:if BTB[PC_Control[0]][0] == pc:passelse:BTB.pop(PC_Control[0])"""# EX階段PC_Control[3] = PC_Control[2] # PC_Control_EX,EX階段指令對應的PC_Controlif BTB[PC_Control[3]][2] == 0: # 若不是分支指令,則刪除該PC_Control在BTB中的itemBTB.pop(PC_Control[3])elif BTB[PC_Control[3]][1] == 0: # 是分支指令,但沒有在BTB中時,將該PC_Control放入到BTB中# branch為該指令跳轉的地址,需要針對指令設置;branch = 0 # 該指令跳轉的地址,需要針對指令設置;BTB[PC_Control[3]][0] == branchprint(PC_Control)print(BTB)"""passdef Exec(): # 指令執行for key in Hardware:if Hardware[key]['busy'] == 1 and Hardware[key]['tag'] > 0:Hardware[key]['tag'] -= 1if Hardware[key]['tag'] == 0: # 執行結束,得到結果存到dataif Hardware[key]['op'] == 'lw': # 'sw' 'mul' 'addi' 'bne'Hardware[key]['data'] = Memory[Hardware[key]['address']] + (Memory[Hardware[key]['address'] + 1] << 8) + (Memory[Hardware[key]['address'] + 2] << 16) + (Memory[Hardware[key]['address'] + 3] << 24)passif Hardware[key]['op'] == 'sw': # 'sw' 'mul' 'addi' 'bne'#Memory[Hardware[key]['address']] = Hardware[key]['s1_vj']#Memory[Hardware[key]['address']] = Hardware[key]['s1_vj']Hardware[key]['data'] = Hardware[key]['s1_vj']passif Hardware[key]['op'] == 'mul': # 'sw' 'mul' 'addi' 'bne'if Hardware[key]['s1_vj'] < 2 ** 31:tag1 = Hardware[key]['s1_vj']else:tag1 = Hardware[key]['s1_vj'] - 2 ** 32if Hardware[key]['s2_vk'] < 2 ** 31:tag2 = Hardware[key]['s2_vk']else:tag2 = Hardware[key]['s2_vk'] - 2 ** 32tag3 = tag1 * tag2if tag3 < 2 ** 31:Hardware[key]['data'] = tag3elif tag3 < 2 ** 32:Hardware[key]['data'] = tag3 - 2 ** 32else:return Falsepassif Hardware[key]['op'] == 'addi': # 'sw' 'mul' 'addi' 'bne'imm = Hardware[key]['imm']if Hardware[key]['imm'] & 0b100000000000 == 0b100000000000:imm = Hardware[key]['imm'] + 0b11111111111111111111000000000000Hardware[key]['data'] = (Hardware[key]['s2_vk'] + imm) & 0xffffffffpassif Hardware[key]['op'] == 'bne': # 'sw' 'mul' 'addi' 'bne'if Hardware[key]['s1_vj'] != Hardware[key]['s2_vk']:global pcpc += (Hardware[key]['imm'] * 4) - 4BTB_Exec()passpasspasspassdef Write(): # 數據寫回for key in Hardware:if Hardware[key]['busy'] == 1 and Hardware[key]['tag'] == 0: # 如果該數據可以寫回Refresh(key) # 刷新需要這個數據的所有buffer和寄存器Hardware[key]['busy'] = 0passpasspass# ISA指令# ***************************Loads*************************** # 字節加載指令 def lb(rd, rs1, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000a = Memory[Register[rs1] + imm]if a & 0b10000000 == 0b10000000:a = a + 0b11111111111111111111111100000000Register[rd] = apass# 半字加載指令 def lh(rd, rs1, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8)if a & 0b1000000000000000 == 0b1000000000000000:a = a + 0b11111111111111110000000000000000Register[rd] = apass# 字加載指令 def lw(rd, rs1, imm):# 將原來的實現修改為硬件狀態的檢查和修改以及是否流出# 1 檢查是否有空閑的硬件,若沒有則停止流出# 2 若有則修改硬件狀態List = ['load1', 'load2', 'load3']for i in List:if Hardware[i]['busy'] == 0:# 若存在硬件是空閑的,則修改硬件狀態,然后返回Hardware[i]['tag'] = 2Hardware[i]['busy'] = 1Hardware[i]['op'] = 'lw'Hardware[i]['address'] = Register[rs1] + immRegister[rd] = ireturn# 若不存在空閑硬件,則停止流出global pcpc -= 4"""if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8) + (Memory[Register[rs1] + imm + 2] << 16) + (Memory[Register[rs1] + imm + 3] << 24)Register[rd] = a"""pass# 無符號字節加載指令 def lbu(rd, rs1, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000a = Memory[Register[rs1] + imm]Register[rd] = apass# 無符號半字加載指令 def lhu(rd, rs1, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8)Register[rd] = apass# ***************************Stores*************************** # 存字節指令 def sb(rs1, rs2, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111pass# 存半字指令 def sh(rs1, rs2, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111pass# 存字指令 # 存字指令 def sw(rs1, rs2, imm):# rs1表示內存地址,rs2表示存入寄存器List = ['store1', 'store2', 'store3']for i in List:if Hardware[i]['busy'] == 0:# 若存在硬件是空閑的,則修改硬件狀態,然后返回Hardware[i]['tag'] = 2Hardware[i]['busy'] = 1Hardware[i]['op'] = 'sw'Hardware[i]['address'] = Register[rs1] + immif isinstance(Register[rs2], int):Hardware[i]['s1_vj'] = Register[rs2]else:Hardware[i]['rs_qj'] = Register[rs2]Register[rs2] = Hardware[i]return# 若不存在空閑硬件,則停止流出global pcpc -= 4"""if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111Memory[Register[rs1] + imm + 2] = (Register[rs2] >> 16) & 0b11111111Memory[Register[rs1] + imm + 3] = Register[rs2] >> 24"""pass# ***************************Shifts*************************** # 邏輯左移指令 def sll(rd, rs1, rs2):Register[rd] = (Register[rs1] << (Register[rs2] & 0b11111)) & 0xffffffffpass# 立即數邏輯左移 def slli(rd, rs1, shamt):if shamt < 0b100000:Register[rd] = (Register[rs1] << shamt) & 0xffffffffpass# 邏輯右移指令 def srl(rd, rs1, rs2):Register[rd] = Register[rs1] >> (Register[rs2] & 0b11111)pass# 立即數邏輯右移 def srli(rd, rs1, shamt):if shamt < 0b100000:Register[rd] = Register[rs1] >> shamtpass# 算數右移指令 def sra(rd, rs1, rs2):Register[rd] = Register[rs1] >> (Register[rs2] & 0b11111)if (Register[rs1] >> 31) == 1:for i in range(0, Register[rs2] & 0b11111):Register[rd] = Register[rd] + 2 ** (31 - i)pass# 立即數算數右移指令 def srai(rd, rs1, shamt):Register[rd] = Register[rs1] >> (shamt & 0b11111)if (Register[rs1] >> 31) == 1:for i in range(0, shamt & 0b11111):Register[rd] = Register[rd] + 2 ** (31 - i)pass# ***************************Arithmetic*************************** # 加指令 def add(rd, rs1, rs2):Register[rd] = Register[rs1] + Register[rs2]pass# 加立即數指令 def addi(rd, rs1, imm):List = ['add1', 'add2', 'add3']for i in List:if Hardware[i]['busy'] == 0:# 若存在硬件是空閑的,則修改硬件狀態,然后返回Hardware[i]['tag'] = 2Hardware[i]['busy'] = 1Hardware[i]['op'] = 'addi'if isinstance(Register[rs1], int):Hardware[i]['s1_vj'] = Register[rs1]else:Hardware[i]['rs_qj'] = Register[rs1]Hardware[i]['imm'] = immRegister[rd] = Hardware[i]return# 若不存在空閑硬件,則停止流出global pcpc -= 4"""# print(Register[rd],Register[rs1],imm)print('指令addi')if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000Register[rd] = (Register[rs1] + imm) & 0xffffffffprint('x1:')print(Register[rd])"""pass# 減指令 def sub(rd, rs1, rs2):pass# 高位立即數加載指令 def lui(rd, imm):pass# PC加立即數指令 def auipc(rd, imm):pass# ***************************Logical*************************** # 異或指令 def xor(rd, rs1, rs2):pass# 立即數異或指令 def xori(rd, rs1, imm):pass# 取或指令 def or_(rd, rs1, rs2):pass# 立即數取或指令 def ori(rd, rs1, imm):pass# 與指令 def and_(rd, rs1, rs2):pass# 與立即數指令 def andi(rd, rs1, imm):Register[rd] = Register[rs1] + immpassdef mul(rd, rs1, rs2):List = ['mult1', 'mult2']for i in List:if Hardware[i]['busy'] == 0:# 若存在硬件是空閑的,則修改硬件狀態,然后返回Hardware[i]['tag'] = 10Hardware[i]['busy'] = 1Hardware[i]['op'] = 'mul'if isinstance(Register[rs1], int):Hardware[i]['s1_vj'] = Register[rs1]else:Hardware[i]['rs_qj'] = Register[rs1]if isinstance(Register[rs2], int):Hardware[i]['s2_vk'] = Register[rs2]else:Hardware[i]['rs_qk'] = Register[rs2]Register[rd] = Hardware[i]return# 若不存在空閑硬件,則停止流出global pcpc -= 4"""if Register[rs1] < 2 ** 31:tag1 = Register[rs1]else:tag1 = Register[rs1] - 2 ** 32if Register[rs2] < 2 ** 31:tag2 = Register[rs2]else:tag2 = Register[rs2] - 2 ** 32tag3 = tag1 * tag2if tag3 < 2 ** 31:Register[rd] = tag3elif tag3 < 2 ** 32:Register[rd] = tag3 - 2 ** 32else:return False"""pass# ***************************Compare*************************** # 小于則置位指令 def slt(rd, rs1, rs2):pass# 小于立即數則置位指令 def slti(rd, rs1, imm):pass# 無符號小于則置位指令 def sltu(rd, rs1, rs2):pass# 無符號小于立即數則置位指令 def sltiu(rd, rs1, imm):pass# ***************************Branches*************************** # 相等時分支指令 def beq(rs1, rs2, imm):pass# 不等式分支指令 def bne(rs1, rs2, imm):List = ['add1', 'add2', 'add3']for i in List:if Hardware[i]['busy'] == 0:# 若存在硬件是空閑的,則修改硬件狀態,然后返回Hardware[i]['tag'] = 1Hardware[i]['busy'] = 1Hardware[i]['op'] = 'bne'Hardware[i]['s1_vj'] = Register[rs1]Hardware[i]['s2_vk'] = Register[rs2]Hardware[i]['imm'] = immreturn# 若不存在空閑硬件,則停止流出global pcpc -= 4"""print('指令bne')global pcif (Register[rs1] != Register[rs2]):pc += (imm * 4) - 4"""pass# 小于時分支指令 def blt(rs1, rs2, imm):pass# 大于等于時分支指令 def bge(rs1, rs2, imm):pass# 無符號小于時分支指令 def bltu(rs1, rs2, imm):pass# 無符號大于等于時分支指令 def bgeu(rs1, rs2, imm):passdef jalr(rd, rs1, imm):passdef ecall(rd, rs1, imm):passdef ebreak(rd, rs1, imm):pass# ***************************Supplement*************************** # 浮點加載雙字 def fld(rd, rs1, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000# print(Register[rs1], imm)# mout(Register[rs1] + imm)a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8) + (Memory[Register[rs1] + imm + 2] << 16) + (Memory[Register[rs1] + imm + 3] << 24)Register[rd] = aimm = imm + 4a = Memory[Register[rs1] + imm] + (Memory[Register[rs1] + imm + 1] << 8) + (Memory[Register[rs1] + imm + 2] << 16) + (Memory[Register[rs1] + imm + 3] << 24)Register[rd + 1] = aprint('指令fld')print('內存:')print(((Register[rs1] + imm - 4) - 56) / 8)print('取數:')rout(rd)pass# 雙精度浮點加 def fadd_d(rd, rs1, rs2):tag1 = Register[rs1 + 1] >> 31index1 = ((Register[rs1 + 1] >> 20) & 0b11111111111) - 1023mantissa1 = 1 + ((Register[rs1 + 1] & 0xfffff) * (2 ** 32) + Register[rs1]) * (2 ** (-52))tag2 = Register[rs2 + 1] >> 31index2 = ((Register[rs2 + 1] >> 20) & 0b11111111111) - 1023mantissa2 = 1 + ((Register[rs2 + 1] & 0xfffff) * (2 ** 32) + Register[rs2]) * (2 ** (-52))a = ((-1) ** tag1) * mantissa1 * (2 ** index1) + ((-1) ** tag2) * mantissa2 * (2 ** index2)# print(a)if a >= 0:tag3 = 0else:tag3 = 1a = a * (-1)# print(a)index3 = 1023while a >= 2:a = a / 2index3 = index3 + 1mantissa3 = (int)((a - 1) * (2 ** 52))# print(bin(tag3),bin(index3),bin(mantissa3))Register[rd] = mantissa3 & 0xffffffff# print(bin(Register[rd]))Register[rd + 1] = tag3 * (2 ** 31) + index3 * (2 ** 20) + (mantissa3 >> 32)# print(bin(Register[rd]+1))print('指令fadd_d')rout(rs1)rout(rs2)rout(rd)pass'''Register[0]=0 Register[1]=0b01000000000010110110000000000000 Register[2]=0 Register[3]=0b11000000001001011000000000000000 Register[4]=0 Register[5]=0 fadd_d(4,0,2) print(bin(Register[4]),bin(Register[5])) print((0b11011011-0b1010110000)/(2**6),(0b111010101)/64)'''# 雙精度浮點存儲 def fsd(rs1, rs2, imm):if imm & 0b100000000000 == 0b100000000000:imm = imm + 0b11111111111111111111000000000000Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111Memory[Register[rs1] + imm + 2] = (Register[rs2] >> 16) & 0b11111111Memory[Register[rs1] + imm + 3] = Register[rs2] >> 24rs2 = rs2 + 1imm = imm + 4Memory[Register[rs1] + imm] = Register[rs2] & 0b11111111Memory[Register[rs1] + imm + 1] = (Register[rs2] >> 8) & 0b11111111Memory[Register[rs1] + imm + 2] = (Register[rs2] >> 16) & 0b11111111Memory[Register[rs1] + imm + 3] = Register[rs2] >> 24print('指令fsd')# rout(rs2-1)print('存入內存:')print(((Register[rs1] + imm - 4) - 56) / 8)print('存入數:')mout(Register[rs1] + imm - 4)passdef mout(addr):a = Memory[addr] + (Memory[addr + 1] << 8) + (Memory[addr + 2] << 16) + (Memory[addr + 3] << 24)addr = addr + 4b = Memory[addr] + (Memory[addr + 1] << 8) + (Memory[addr + 2] << 16) + (Memory[addr + 3] << 24)tag = b >> 31index = ((b >> 20) & 0b11111111111) - 1023mantissa = 1 + ((b & 0xfffff) * (2 ** 32) + a) * (2 ** (-52))flo = mantissa * (2 ** index) * ((-1) ** tag)print(flo)def rout(addr):a = Register[addr]addr = addr + 1b = Register[addr]tag = b >> 31index = ((b >> 20) & 0b11111111111) - 1023mantissa = 1 + ((b & 0xfffff) * (2 ** 32) + a) * (2 ** (-52))flo = mantissa * (2 ** index) * ((-1) ** tag)print(flo)# 指令集 class ISA:def __init__(self):instruction = self.defInstr()self.tellFormat(instruction)def defInstr(self): # 傳入參數為指令在內存的地址instru = 0x00000000if (pc == 68):print("breakpoint")for i in range(4):# print(hex(addr + i))# print(hex(Memory[addr + i]))instru += Memory[pc + i] * (256 ** i)# print(hex(instru))return instruinstruFormat = {0b0110011: 'RFormat', # 運算0b0010011: 'IFormat', # 運算0b0000011: 'IFormat', # load0b0100011: 'SFormat', # store0b1100011: 'SBFormat', # branch0b1101111: 'UJFormat', # jump(大立即數跳轉)0b1100111: 'IFormat', # jump0b0110111: 'UFormat', # rd = imm << 120b0010111: 'UFormat', # rd = pc + (imm << 12)0b1110011: 'IFormat', # transfer control0b0100111: 'SFormat', # fsd0b0000111: 'IFormat', # fld0b1010011: 'RFormat', # fadd_d}def getopfromins(self, instruction):return instruction & 0b1111111def tellFormat(self, instruction):opcode = self.getopfromins(instruction)switch = {0b0110011: 'RFormat', # 運算0b0010011: 'IFormat', # 運算0b0000011: 'IFormat', # load0b0100011: 'SFormat', # store0b1100011: 'SBFormat', # branch0b1101111: 'UJFormat', # jump(大立即數跳轉)0b1100111: 'IFormat', # jump0b0110111: 'UFormat', # rd = imm << 120b0010111: 'UFormat', # rd = pc + (imm << 12)0b1110011: 'IFormat', # transfer control0b0100111: 'SFormat', # fsd0b0000111: 'IFormat', # fld0b1010011: 'RFormat', # fadd_d}Format = switch.get(opcode, 'Invalid')# 這里pc加四,如果后面檢測到不可以流出,再進行減四global pcpc += 4if (Format == 'Invalid'):return Falseelif (Format == 'RFormat'):return self.decodeRFormat(instruction)elif (Format == 'IFormat'):return self.decodeIFormat(instruction)elif (Format == 'SFormat'):return self.decodeSFormat(instruction)elif (Format == 'SBFormat'):return self.decodeSBFormat(instruction)elif (Format == 'UFormat'):return self.decodeUFormat(instruction)elif (Format == 'UJFormat'):return self.decodeUJFormat(instruction)return Falsedef decodeRFormat(self, instruction):opcode = instruction & 0b1111111funct7 = instruction >> 25rs2 = instruction >> 20 & 0b11111rs1 = instruction >> 15 & 0b11111funct3 = instruction >> 12 & 0b111rd = instruction >> 7 & 0b11111if (funct7 == 0x00):if (funct3 == 0x0):return add(rd, rs1, rs2)elif (funct3 == 0x4):return xor(rd, rs1, rs2)elif (funct3 == 0x6):return or_(rd, rs1, rs2)elif (funct3 == 0x7):return and_(rd, rs1, rs2)elif (funct3 == 0x1):return sll(rd, rs1, rs2)elif (funct3 == 0x5):return srl(rd, rs1, rs2)elif (funct3 == 0x2):return slt(rd, rs1, rs2)elif (funct3 == 0x3):return sltu(rd, rs1, rs2)elif (funct7 == 0x20):if (funct3 == 0x0):return sub(rd, rs1, rs2)elif (funct3 == 0x5):return sra(rd, rs1, rs2)elif (funct7 == 0x01):if (opcode == 0b1010011):return fadd_d(rd, rs1, rs2)elif (funct3 == 0x0 and opcode == 0b0110011):return mul(rd, rs1, rs2)return Falsedef decodeIFormat(self, instruction):imm = instruction >> 20rs1 = instruction >> 15 & 0b11111funct3 = instruction >> 12 & 0b111rd = instruction >> 7 & 0b11111opcode = instruction & 0b1111111if (opcode == 0b0010011):if (funct3 == 0x0):return addi(rd, rs1, imm)elif (funct3 == 0x4):return xori(rd, rs1, imm)elif (funct3 == 0x6):return ori(rd, rs1, imm)elif (funct3 == 0x7):return andi(rd, rs1, imm)elif (funct3 == 0x1):return slti(rd, rs1, imm)elif (funct3 == 0x5):if (instruction >> 25 == 0b0000000):return srli(rd, rs1, imm)elif (instruction >> 25 == 0b0100000):return srai(rd, rs1, imm)elif (funct3 == 0x2):return slti(rd, rs1, imm)elif (funct3 == 0x3):return sltiu(rd, rs1, imm)elif (opcode == 0b0000011):if (funct3 == 0x0):return lb(rd, rs1, imm)elif (funct3 == 0x1):return lh(rd, rs1, imm)elif (funct3 == 0x2):return lw(rd, rs1, imm)elif (funct3 == 0x4):return lbu(rd, rs1, imm)elif (funct3 == 0x5):return lhu(rd, rs1, imm)elif (opcode == 0b1100111):if (funct3 == 0x0):return jalr(rd, rs1, imm)elif (opcode == 0b1110011):if (funct3 == 0x0 and imm == 0x0):return ecall(rd, rs1, imm)elif (funct3 == 0x0 and imm == 0x1):return ebreak(rd, rs1, imm)elif (opcode == 0b0000111):if (funct3 == 0b011):return fld(rd, rs1, imm)return Falsedef decodeSFormat(self, instruction):imm = (instruction >> 7) & 0b11111 + (instruction >> 25) * 0b100000immTemp = 0b000000000000# 這里的imm是十二位的二進制補碼,需要將其轉換為機器數if (imm >> 11 == 1):for i in range(11):immTemp += (1 - (imm >> i & 1)) * (2 ** i)immTemp += 1imm = 0 - immTempfunct3 = (instruction >> 12) & 0b111rs1 = (instruction >> 15) & 0b11111rs2 = (instruction >> 20) & 0b11111if funct3 == 0x0:return sb(rs1, rs2, imm)elif funct3 == 0x1:return sh(rs1, rs2, imm)elif funct3 == 0x2:return sw(rs1, rs2, imm)elif funct3 == 0x3:return fsd(rs1, rs2, imm)return Falsedef decodeSBFormat(self, instruction):a = (instruction >> 7) & 0b11111c = ((instruction >> 25) & 0b1111111) << 5imm = a + cimmTemp = 0b000000000000# 這里的imm是十二位的二進制補碼,需要將其轉換為機器數if (imm >> 11 == 1):for i in range(11):immTemp += (1 - (imm >> i & 1)) * (2 ** i)immTemp += 1imm = 0 - immTempfunct3 = (instruction >> 12) & 0b111rs1 = (instruction >> 15) & 0b11111rs2 = (instruction >> 20) & 0b11111if funct3 == 0x0:return beq(rs1, rs2, imm)elif funct3 == 0x1:return bne(rs1, rs2, imm)elif funct3 == 0x4:return blt(rs1, rs2, imm)elif funct3 == 0x5:return bge(rs1, rs2, imm)elif funct3 == 0x6:return bltu(rs1, rs2, imm)elif funct3 == 0x7:return bgeu(rs1, rs2, imm)return Falsedef decodeUFormat(self, instruction):opcode = instruction & 0b1111111rd = (instruction >> 7) & 0b11111imm = instruction >> 12immTemp = 0b000000000000# 這里的imm是十二位的二進制補碼,需要將其轉換為機器數if (imm >> 11 == 1):for i in range(11):immTemp += (1 - (imm >> i & 1)) * (2 ** i)immTemp += 1imm = 0 - immTempif opcode == 0b0110111:return lui(rd, imm)elif opcode == 0b0010111:return auipc(rd, imm)return Falsedef decodeUJFormat(self, instruction):return Falsedef main():global Registerglobal Memory# 初始化寄存器Register[0b00001] = 0x00000000 # 1,2寄存器用來存儲常量sRegister[0b00010] = 0x40180000 # s=6# Register[0b00011] = 0x00000300 # 用來存儲x1,即99,這里令其為96*8=768=0x300Register[0b00100] = 0x00000318 # 用來存儲x2,即99 * 8 =# 需要變址寄存器用來找到load和store指令中的內存地址,每四條指令使用同一個變址寄存器,通過改變立即數的大小來決定內存地址的變換Register[0b00101] = 0x00000000 # 用來存儲x1=0,用來表示load或者store指令的變址寄存器# 其余的寄存器用來存儲加載的數字以及計算結果,其初始值都是零# l1 fld# 內存中的指令數據# 1 fld f6 0x38()# load two word指令,立即數為0x38,轉化為二進制為0011 1000# imm[11:0] rs1 011 rd 0000111# 0000 0011 1000 0010 1 011 0011 0 000 0111# EA = A + (rs1)# 0x 03 82 B3 07Memory[0x00000030] = 0x07Memory[0x00000031] = 0xB3Memory[0x00000032] = 0x82Memory[0x00000033] = 0x03# l2 fadd# 這里rd(14\15)的地址為:0b01110,rs1(6、7數組中的元素)的地址為:0b00110,r2(1/2,常量s)的地址為:0b00001# funct7 rs2 rs1 funct3 rd opcode# 0000001 00001 00110 001 01110 1010011# 其中funct7和funct3的組合表示浮點加法運算# 16進制表示為0x 02 13 17 53Memory[0x00000034] = 0x53Memory[0x00000035] = 0x17Memory[0x00000036] = 0x13Memory[0x00000037] = 0x02# l3 fsd# 和第一條load指令相對應# 內存中的指令數據# 1 fld# load two word指令,立即數為0x38,轉化為二進制為0011 1000# imm[11:0] rs1 110 rd 0000011# 000000111000 00101 110 00110 0000011# rs2需要存儲的數據# rs1基址寄存器# imm[11:5] rs2 rs1 func3 imm[4:0] opcode# 0000001 01110 00101 011 11000 0100011# 這里的立即數和load指令中的立即數具有相同的作用,即數組在內存中的開始地址# 其十六進制表示為0x02 E2 BC 23Memory[0x00000038] = 0x23Memory[0x00000039] = 0xBCMemory[0x0000003A] = 0xE2Memory[0x0000003B] = 0x02# l4 addi# x1是存儲在第一條load指令的基址寄存器和imm產生的內存地址,初始值為96*4,最后的值為0# imm為8# imm[11:0] rs1 111 rd 0010011# 0000 0000 1000 0010 1 000 0010 1 001 0011# 十六進制表示為0x 00 82 82 93Memory[0x0000003C] = 0x93Memory[0x0000003D] = 0x82Memory[0x0000003E] = 0x82Memory[0x0000003F] = 0x00"""# l5 bne# 若x1和x2里面的內容不相等則進行分支轉移# 分支轉移中的立即數,令其為-6# imm[12|10:5] rs2 rs1 func3 imm[4:1|11] opcode# x1 x2# 1111111 00101 00100 001 11010 1100011# 16進制表示為0x FE 52 1D 63Memory[0x00000040] = 0x63Memory[0x00000041] = 0x1DMemory[0x00000042] = 0x52Memory[0x00000043] = 0xFE"""# l5 bne# 若x1和x2里面的內容不相等則進行分支轉移# 分支轉移中的立即數,令其為-4# imm[12|10:5] rs2 rs1 func3 imm[4:1|11] opcode# x1 x2# 1111111 00101 00100 001 11100 1100011# 16進制表示為0x FE 52 1E 63Memory[0x00000040] = 0x63Memory[0x00000041] = 0x1EMemory[0x00000042] = 0x52Memory[0x00000043] = 0xFE# 指令后面的位置用來存儲數組數據,從十進制56開始即0x38for i in range(100):Memory[0x00000044 + i * 8] = 0x00Memory[0x00000044 + i * 8 + 1] = 0x00Memory[0x00000044 + i * 8 + 2] = 0x00Memory[0x00000044 + i * 8 + 3] = 0x00m = (i + 1023) * 16Memory[0x00000044 + i * 8 + 4] = 0x00Memory[0x00000044 + i * 8 + 5] = 0x00Memory[0x00000044 + i * 8 + 6] = m & 0xffMemory[0x00000044 + i * 8 + 7] = (m >> 8) & 0xff"""for i in range(100):print('運行前內存%d:' % i)mout(0x00000044 + i * 8)"""global pcpc = 0x00000030clock = 0for clock in range(10000):print(pc)Issue()Exec()Write()clock += 1if pc == 0x00000044:pass"""for i in range(100):print('運行后內存%d:' % i)mout(0x00000038 + i * 8)"""main()總結
以上是生活随笔為你收集整理的python模拟硬件实现btb和tomasulo算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RAK7258 LoRaWAN 网关接入
- 下一篇: r语言 xueyi_R语言实用教程