import prettytable as pt import pandas as pd import numpy as np # 初始化寄存器(32R + 16F), 存储器(1024 units),简化运算,寄存器内容即填充为寄存器编号值 R = [i for i in range(32)] F = [2.0 * i for i in range(16)] MEM = [i for i in range(1024)] # print(R) # print(F) # print(MEM) label2pc = {} loopNum = 3 prgmSeq = [] # 初始化规则 op2fu = {"L.D": "Load", "S.D": "Store", "MUL.D": "Mult", "DADDUI": "Add", "BNE": "Add", "SUB.D": "Add", "DIV.D": "Mult", "ADD.D": "Add"} op2char = {"MUL.D": "*", "DADDUI": "+", "SUB.D": "-", "DIV.D": "/", "ADD.D": "+"} FUtime = {"L.D": "1", "S.D": "1", "MUL.D": "10", "DADDUI": "2", "BNE": "1", "SUB.D": "2", "DIV.D": "40", "ADD.D": "2"} FUname = ["Load1", "Load2", "Add1", "Add2", "Add3", "Mult1", "Mult2", "Store1", "Store2"] # 初始化 InstructionStatusTable, ReservationStations, RegisterStatusTable def init(prgm) : InsS = [] ResS = pd.DataFrame(np.empty([9, 9], str), index = FUname, columns = ["Busy", "Op", "Vj", "Vk", "Qj", "Qk", "A", "Time", "InsNum"]) ResS['Busy'] = "No" # 置空闲 # F0-F14 R0-R7 RegS = pd.DataFrame(np.empty([1, 16], str), index=["FU"], columns=["F" + str(i) for i in range(0, 16, 2)] + ["R" + str(i) for i in range(0, 8, 1)]) return 0, InsS, ResS, RegS # 译码,得到指令操作码、目的寄存器、源操作数寄存器 def decIns(ins): if ins.find("Loop: ") != -1: # 去Loop ins = ins.replace("Loop: ", "") ins = ins.replace(",", " ") ins = ins.replace("(", " ") ins = ins.replace(")", "") ins = ins.split(" ") op = ins[0] dest = ins[1] s1 = ins[2] s2 = ins[3] return op, dest, s1, s2 # 在ReservationStations中为该指令分配功能部件 def getFU(op, ResS): fu = op2fu[op] if fu == "Load": if ResS.loc["Load1", "Busy"] == "No": fu = "Load1" elif ResS.loc["Load2", "Busy"] == "No": fu = "Load2" else: fu = "" # 若无空闲部件,则返回空字符串,代表“Busy" elif fu == "Add": if ResS.loc["Add1", "Busy"] == "No": fu = "Add1" elif ResS.loc["Add2", "Busy"] == "No": fu = "Add2" elif ResS.loc["Add3", "Busy"] == "No": fu = "Add3" else: fu = "" elif fu == "Mult": if ResS.loc["Mult1", "Busy"] == "No": fu = "Mult1" elif ResS.loc["Mult2", "Busy"] == "No": fu = "Mult2" else: fu = "" else: if ResS.loc["Store1", "Busy"] == "No": fu = "Store1" elif ResS.loc["Store2", "Busy"] == "No": fu = "Store2" else: fu = "" return fu # 在ReservationStations中寻找该指令正在使用的功能部件(load1...) def getFUing(insnum, ResS): for name in FUname: if ResS.loc[name, "InsNum"] == insnum: fu = name return fu # 发射指令 def issue(ins, insnum, clk, InsS, ResS, RegS): op, dest, s1, s2 = decIns(ins) fu = getFU(op, ResS) if fu != "": InsS.append(["" for j in range(3)]) InsS[insnum][0] = clk # 登记该指令发射时间 # 登记指令在保留站状态 ResS.loc[fu, "InsNum"] = insnum ResS.loc[fu, "Busy"] = "Yes" ResS.loc[fu, "Op"] = op if fu.find("Store") != -1: # 计算store的内存地址 addr = int(dest) + R[int(R[int(s1.replace("R", ""))])] # 寄存器间接寻址 ResS.loc[fu, "Vj"] = "#%s" % addr # RAW if RegS.loc["FU", s2] == "": # ResS.loc[fu, "Qk"] = "Regs[%s]" % (s2) ResS.loc[fu, "Qk"] = "#%s" % F[int(s2.replace("F", "")) // 2] else: ResS.loc[fu, "Qk"] = RegS.loc["FU", s2] elif fu.find("Load") != -1: RegS.loc["FU", dest] = fu # 计算地址 addr = int(s1) + R[int(R[int(s2.replace("R", ""))])] # 寄存器间接寻址 ResS.loc[fu, "A"] = "#%s" % addr # 写地址立即数 elif ins.find("BNE") != -1: # 比较dest和s1,是否跳转s2 # dest是否有效 if RegS.loc["FU", dest] == "": if dest.find("F") != -1: # dest是F寄存器 ResS.loc[fu, "Vj"] = "#%s" % F[int(dest.replace("F", "")) // 2] elif dest.find("R") != -1: # dest是R寄存器 ResS.loc[fu, "Vj"] = "#%s" % R[int(dest.replace("R", ""))] else: ResS.loc[fu, "Qj"] = RegS.loc["FU", dest] # s1是否有效 if RegS.loc["FU", s1] == "": if s1.find("F") != -1: # s1是F寄存器 ResS.loc[fu, "Vk"] = "#%s" % F[int(s1.replace("F", "")) // 2] elif s1.find("R") != -1: # s1是R寄存器 ResS.loc[fu, "Vk"] = "#%s" % R[int(s1.replace("R", ""))] else: ResS.loc[fu, "Qk"] = RegS.loc["FU", s1] else: # 其他指令 # s1操作数是否有效 if RegS.loc["FU", s1] == "": if s1.find("F") != -1: # s1是F寄存器 ResS.loc[fu, "Vj"] = "#%s" % F[int(s1.replace("F", "")) // 2] elif s1.find("R") != -1: # s1是R寄存器 ResS.loc[fu, "Vj"] = "#%s" % R[int(s1.replace("R", ""))] else: ResS.loc[fu, "Qj"] = RegS.loc["FU", s1] # s2操作数是否有效 if s2.find("#") != -1: # s2是立即数 ResS.loc[fu, "Vk"] = s2 elif RegS.loc["FU", s2] == "": # s2是F寄存器值 ResS.loc[fu, "Vk"] = "#%s" % F[int(s2.replace("F", "")) // 2] else: ResS.loc[fu, "Qk"] = RegS.loc["FU", s2] # 寄存器状态表中写入功能部件 RegS.loc["FU", dest] = fu return InsS, ResS, RegS # 执行指令 def execute(ins, insnum, clk, InsS, ResS): op, dest, s1, s2 = decIns(ins) fu = getFUing(insnum, ResS) if ResS.loc[fu, "Time"] == "": # 指令未开始执行 # 操作数就绪,执行 if ResS.loc[fu, "Qj"] == "" and ResS.loc[fu, "Qk"] == "": ResS.loc[fu, "Time"] = FUtime[op] else: # 指令开始执行 ResS.loc[fu, "Time"] = str(int(ResS.loc[fu, "Time"]) - 1) if ResS.loc[fu, "Time"] == "0": InsS[insnum][1] = clk ResS.loc[fu, "Time"] = "" return InsS, ResS # 写回阶段 def writeResult(ins, insnum, clk, InsS, ResS, RegS, PC): op, dest, s1, s2 = decIns(ins) fu = getFUing(insnum, ResS) InsS[insnum][2] = clk # 登记时钟 ResS.loc[fu, "Busy"] = "No" # 释放所用功能部件 # 寄存器状态表写回 if fu.find("Load") != -1: RegS.loc["FU", dest] = "" F[int(dest.replace("F", "")) // 2] = MEM[int(float(ResS.loc[fu, "A"].replace("#", ""))//1)] result = "#%s" % str(F[int(dest.replace("F", "")) // 2]) elif fu.find("Store") != -1: MEM[int(ResS.loc[fu, "Vj"].replace("#", ""))] = float(ResS.loc[fu, "Vk"].replace("#", ""))//1 elif ins.find("BNE") != -1: if ResS.loc[fu, "Vj"] != ResS.loc[fu, "Vk"]: PC = label2pc[s2] # Loop -> #0 else: # 除load、store、bne的其他指令 RegS.loc["FU", dest] = "" if op2char[op] == "+": dest_result = float(ResS.loc[fu, "Vj"].replace("#", "")) + float(ResS.loc[fu, "Vk"].replace("#", "")) elif op2char[op] == "-": dest_result = float(ResS.loc[fu, "Vj"].replace("#", "")) - float( ResS.loc[fu, "Vk"].replace("#", "")) elif op2char[op] == "*": dest_result = float(ResS.loc[fu, "Vj"].replace("#", "")) * float( ResS.loc[fu, "Vk"].replace("#", "")) elif op2char[op] == "/": dest_result = float(ResS.loc[fu, "Vj"].replace("#", "")) / float( ResS.loc[fu, "Vk"].replace("#", "")) if dest.find("F") != -1: F[int(dest.replace("F", "")) // 2] = dest_result elif dest.find("R") != -1: R[int(dest.replace("R", ""))] = dest_result result = "#%s" % str(dest_result) ResS.loc[fu, "Op"] = "" ResS.loc[fu, "Vj"] = "" ResS.loc[fu, "Vk"] = "" ResS.loc[fu, "Oj"] = "" ResS.loc[fu, "Ok"] = "" ResS.loc[fu, "A"] = "" ResS.loc[fu, "Time"] = "" ResS.loc[fu, "InsNum"] = "" # 结果数据广播 for fuitem in FUname: # 遍历 ReservationStations if ResS.loc[fuitem, "Qj"] == fu: ResS.loc[fuitem, "Qj"] = "" ResS.loc[fuitem, "Vj"] = result # 广播结束,开始计时 if ResS.loc[fuitem, "Qk"] == "" and ResS.loc[fuitem, "Time"] == "": ResS.loc[fuitem, "Time"] = FUtime[ResS.loc[fuitem, "Op"]] if ResS.loc[fuitem, "Qk"] == fu: ResS.loc[fuitem, "Qk"] = "" ResS.loc[fuitem, "Vk"] = result # 广播结束,开始计时 if ResS.loc[fuitem, "Qj"] == "" and ResS.loc[fuitem, "Time"] == "": ResS.loc[fuitem, "Time"] = FUtime[ResS.loc[fuitem, "Op"]] return PC, InsS, ResS, RegS # 输出InstructionStatusTable, ReservationStations, RegisterStatusTable def printResult(prgm, InsS, ResS, RegS): # InstructionStatusTable InsST = pt.PrettyTable() InsST.field_names = ["Instruction", "issue", "execute", "Write result"] for i in range(min(len(InsS),loopNum*(len(prgm)-1))): line = [j for j in InsS[i]] line.insert(0, prgmSeq[i]) InsST.add_row(line) # ReservationStations ResST = pt.PrettyTable() ResST.field_names = ["Name", "Busy", "Op", "Vj", "Vk", "Qj", "Qk", "A", "Time", "InsNum"] ResList = ResS.values.tolist() for i in range(len(ResList)): line = ResList[i][:9] line.insert(0, FUname[i]) ResST.add_row(line) # RegisterStatusTable RegST = pt.PrettyTable() RegST.field_names = ["R&F", "F0", "F2", "F4", "F6", "F8", "F10", "F12", "F14", "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7"] line = RegS.values.tolist()[0] line.insert(0, "FU") RegST.add_row(line) print(InsST) print(ResST) print(RegST) # 判断指令是否全部执行完成 def PrgmFinish(InsS, prgm): # for i in range(len(prgmSeq)): for i in range(loopNum*(len(prgm)-1)): for j in range(3): if InsS[i][j] == "": return False return True # 主程序 if __name__ == '__main__': prgm = ["Loop: L.D F0,0(R1)", "MUL.D F4,F0,F2", "S.D 0(R1),F4", "DADDUI R1,R1,#-8", "BNE R1,R2,Loop", "End"] clk, InsS, ResS, RegS = init(prgm) PC = 0 while True: clk += 1 if prgm[PC].find("Loop") == 0: label2pc["Loop"] = PC # {'Loop': 0} prgm[PC] = prgm[PC].replace("Loop: ", "") # 第一个周期 只流出第一条指令 if clk == 1: # 发射指令 InsS, ResS, RegS = issue(prgm[PC], PC, clk, InsS, ResS, RegS) prgmSeq.append(prgm[PC]) PC += 1 else: for i in range(len(InsS) - 1, -1, -1): if InsS[i][1] == "": # 执行阶段 InsS, ResS = execute(prgmSeq[i], i, clk, InsS, ResS) elif InsS[i][2] == "": # 写回阶段 PC, InsS, ResS, RegS = writeResult(prgmSeq[i], i, clk, InsS, ResS, RegS, PC) # 发射新指令? if prgm[PC] != "End" and (PC == 0 or InsS[PC - 1][0] != ""): # 未执行完,(PC = 0 || 上一条指令已发射) InsS, ResS, RegS = issue(prgm[PC], len(InsS), clk, InsS, ResS, RegS) prgmSeq.append(prgm[PC]) PC += 1 print("clock:%d" % clk) print(label2pc) printResult(prgm, InsS, ResS, RegS) print(prgmSeq) if PrgmFinish(InsS, prgm): break