You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

329 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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