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.

246 lines
8.3 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.

from utils import *
from ir import *
from ds import Ins_Status, FU_Status
INS_NUM = 6
# IS表 长度为指令条数
IS = [Ins_Status() for _ in range(INS_NUM)]
# FUS表
FUS = {'Integer': FU_Status(),
'Mul1': FU_Status(),
'Mul2': FU_Status(),
'Add': FU_Status(),
'Divide': FU_Status()
}
# RSS表
RSS = {'F%d' % (2 * i): 'None' for i in range(16)}
# 指令列表
ins_list = [Load(reg1='F6', offset=34, reg2='R2'),
Load(reg1='F2', offset=45, reg2='R3'),
Mul(reg1='F0', reg2='F2', reg3='F4'),
Sub(reg1='F8', reg2='F6', reg3='F2'),
Div(reg1='F10', reg2='F0', reg3='F6'),
Add(reg1='F6', reg2='F8', reg3='F2')]
# 指令流出阶段 避免结构冲突和WAR冲突
def Issue(ins_num):
fu = FU_allocate(ins_list[ins_num].fu, FUS)
if (fu is not None) and Result_write(ins_list[ins_num].rt, RSS): # 如果当前指令所需的部件空闲 and 记分牌中已经存在的指令不对当前指令的目的寄存器进行写操作
FUS_item = FUS[fu]
# 改写FUS表该部件行
FUS_item.busy = 'Yes'
FUS_item.op = type(ins_list[ins_num])
FUS_item.fi = ins_list[ins_num].rt
FUS_item.fj = ins_list[ins_num].rs[0]
FUS_item.fk = ins_list[ins_num].rs[1]
try: # 如果源操作数不来自任何一个部件则qj为空
FUS_item.qj = RSS[FUS_item.fj]
except:
FUS_item.qj = 'None'
try: # 如果源操作数不来自任何一个部件则qk为空
FUS_item.qk = RSS[FUS_item.fk]
except:
FUS_item.qk = 'None'
# 源操作数寄存器是否就绪
if FUS_item.fj != 'None':
if RS_ready(FUS_item.fj, RSS):
FUS_item.rj = 'Yes'
else:
FUS_item.rj = 'No'
else:
FUS_item.rj = 'None'
if RS_ready(FUS_item.fk, RSS):
FUS_item.rk = 'Yes'
else:
FUS_item.rk = 'No'
RSS[ins_list[ins_num].rt] = fu
# 发出指令
IS[ins_num].issue = clock
return fu
# 不满足条件则等待
else:
return 'Wait'
# 读操作数阶段 避免RAW冲突
def Read_Operands(ins_num, fu):
if (FUS[fu].rj != 'No') and (FUS[fu].rk != 'No'): # rj和rk就绪读操作数
# 检查RAW冲突
if FUS[fu] not in hazards['RAW']:
IS[ins_num].oper = clock
# if FUS[fu].rj != 'None':
# FUS[fu].rj = 'No'
# if FUS[fu].rk != 'None':
# FUS[fu].rk = 'No'
# FUS[fu].qj = 'None'
# FUS[fu].qk = 'None'
return 'Success'
else:
return 'Wait'
# 执行阶段 无需对表的任何操作
def Execution(ins_num, fu):
# 返回需要的时钟周期数
if FUS[fu].rj != 'None':
FUS[fu].rj = 'No'
if FUS[fu].rk != 'None':
FUS[fu].rk = 'No'
FUS[fu].qj = 'None'
FUS[fu].qk = 'None'
if isinstance(ins_list[ins_num], Mul):
return 10
elif isinstance(ins_list[ins_num], Div):
return 40
elif isinstance(ins_list[ins_num], Add) or isinstance(ins_list[ins_num], Sub):
return 2
else:
return 1
# 写结果阶段 避免WAR冲突
def Write_Resut(ins_num, fu):
# 在FUS表中的每一条指令进行逐一查看如果不存在任意一条指令的源操作数寄存器与当前指令的目的操作数寄存器相同 且对应的寄存器处于读就绪状态
for _, item in FUS.items():
if (item.fj == ins_list[ins_num].rt) and item.rj == 'Yes':
return 'Wait'
try:
if (item.fk == ins_list[ins_num].rt) and item.rk == 'Yes':
return 'Wait'
finally:
pass
# 则修改记分牌内容
# 检查FUS中每条指令的qj和qk域如果存在一条指令以当前指令的结果作为源操作数则将那一条指令对应的rj或rk设为Yes
for _, item in FUS.items():
if item.qj == fu:
item.rj = 'Yes'
if item.qk == fu:
item.rk = 'Yes'
# 将RSS中当前指令对应的元素设置为空
RSS[FUS[fu].fi] = 'None'
# 同时级联修改FUS中所有的qj和qk如果存在当前部件则释放
for _, value in FUS.items():
if value.qj == fu:
value.qj = 'None'
if value.qk == fu:
value.qk = 'None'
# ???? 将FUS中对应的部件的Busy域设置为No ????
# ???? FUS[fu].busy = 'No' ????
# 将FUS中对应的行清空
FUS[fu].clear()
IS[ins_num].result = clock
return 'Success'
def print_tables():
print('---------------------IS---------------------')
for item in IS:
print(item)
print('---------------------FUS---------------------')
for key, value in FUS.items():
print('{:7s}'.format(key), value)
print('---------------------RSS---------------------')
for key, _ in RSS.items():
print('{:7s}'.format(key), end=' ')
print('\n', end='')
for _, value in RSS.items():
print('{:7s}'.format(value), end=' ')
print('\n')
if __name__ == '__main__':
# 时钟
clock = 1
Uncomp_list = ins_list.copy()
# 初始阶段所有指令都等待Issue
IF_list = [i for i in range(len(ins_list))]
ID_list = [] # ID EX WB的元素都是元组 (指令,功能部件)
EX_list = []
WB_list = []
Comp_list = []
hazards = analyze_hazard(Uncomp_list)
ex_clock_list = {}
# 执行直到所有任务完成
while len(Comp_list) < len(ins_list):
print('################ CLOCK = %d ################ ' % clock)
fu = ''
issued = False
fetched = []
executed = []
written = []
if len(IF_list) != 0: # 发出指令若成功在IF中去除该指令在ID中添加该指令
fu = Issue(IF_list[0])
if fu != 'Wait':
issued = True
if len(ID_list) != 0:
for i in range(len(ID_list)):
if Read_Operands(ID_list[i][0], ID_list[i][1]) == 'Success': # 取操作数若成功在ID中去除该指令在EX中添加该指令
fetched.append(ID_list[i])
if len(EX_list) != 0:
for i in range(len(EX_list)):
# 如果该指令没有在“正在运行的指令”字典中,启动局部计数器
try:
if ex_clock_list[EX_list[i][0]] is not None:
pass
except:
ex_clock = Execution(EX_list[i][0], EX_list[i][1])
if ex_clock == 1: # 如果指令只需1个周期完成则不需要计数器
IS[EX_list[i][0]].comp = clock
executed.append(EX_list[i])
else:
ex_clock_list[EX_list[i][0]] = ex_clock - 1 # 该次循环结束后已经过一个周期
# 若某条指令的计数器终止,则认为已完成
for i in range(len(EX_list)):
try:
if ex_clock_list[EX_list[i][0]] == 0:
IS[EX_list[i][0]].comp = clock
executed.append(EX_list[i])
ex_clock_list.pop(EX_list[i][0])
except:
pass
if len(WB_list) != 0:
for i in range(len(WB_list)):
if Write_Resut(WB_list[i][0], WB_list[i][1]) == 'Success':
written.append(WB_list[i])
# 统计该周期完成的动作,并且更新下一步动作
if issued:
ID_list.append((IF_list[0], fu))
IF_list.remove(IF_list[0])
if len(fetched):
for item in fetched:
EX_list.append(item)
ID_list.remove(item)
if len(executed):
for item in executed:
WB_list.append(item)
EX_list.remove(item)
if len(written):
for item in written:
Comp_list.append(item)
Uncomp_list.remove(ins_list[item[0]]) # 一条指令结束后更新hazard表
WB_list.remove(item)
hazards = analyze_hazard(Uncomp_list)
clock += 1
for key, value in ex_clock_list.items(): # 局部时钟-1
print('局部时钟:', end=' ')
print(ins_list[key], value)
ex_clock_list[key] -= 1
print_tables()