|
|
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 |