from hw4.ir.ir import * VREG_NUM = 500 REG_NUM = 32 reg_status = {i: None for i in range(REG_NUM)} # 寄存器状态图,键为编号,值为使用该寄存器的指令,None表示空闲 vreg_status = {'v%d' % i: None for i in range(VREG_NUM)} # 虚拟寄存器状态图 class AllocateException(BaseException): def __init__(self, info): self.info = info def __str__(self): return self.info # 随机分配空闲虚拟寄存器 def allocate_vreg(ir): for vreg in vreg_status.keys(): if vreg_status[vreg] is None: vreg_status[vreg] = ir return vreg raise AllocateException('虚拟寄存器已满!') # 释放某一虚拟寄存器 def free_vreg(i): vreg_status[i] = None def free_reg(i): reg_status[i] = None def allocate_reg(ir): for reg in reg_status.keys(): if reg_status[reg] is None: reg_status[reg] = ir return reg # 若寄存器已满,分配虚拟寄存器 allocate_vreg(ir) # 数据相关性分析 def analyze_hazard(cycle): hazard = {'RAW': [], 'WAR': [], 'WAW': []} write = [] # 记录所有写操作 read = [] # 记录所有读操作 # 分析数据相关性 for instr in cycle.instrList: # 标记所有读取和写入的寄存器 if instr.rt is not None: write.append(instr.rt) if instr.rs is not None: read.append(instr.rs) # 检测写后读(RAW) for i in range(len(write)): for j in range(i + 1, len(read)): if write[i] in read[j]: hazard['RAW'].append((cycle.instrList[i], cycle.instrList[j])) # 检测读后写(WAR) for i in range(len(read)): for j in range(i + 1, len(write)): if write[j] in read[i]: hazard['WAR'].append((cycle.instrList[i], cycle.instrList[j])) # 检测读后读(WAW) for i in range(len(write)): for j in range(i + 1, len(write)): if write[i] == write[j]: hazard['WAW'].append((cycle.instrList[i], cycle.instrList[j])) return hazard # 判断两条指令是否相关 def judge_hazard(instr1, instr2, hazard): if (instr1, instr2) in hazard['RAW'] or (instr1, instr2) in hazard['WAR'] or (instr1, instr2) in hazard['WAW']: return True elif (instr2, instr1) in hazard['RAW'] or (instr2, instr1) in hazard['WAR'] or (instr2, instr1) in hazard['WAW']: return True return False # 延迟分析 def get_stall(op_this, op_next): if isinstance(op_this, AluInstr): if isinstance(op_next, AluInstr): return 3 elif isinstance(op_next, Store): return 2 elif isinstance(op_next, Condition): return 1 else: return 0 elif isinstance(op_this, Load): if isinstance(op_next, AluInstr): return 1 elif isinstance(op_next, Store): return 0 elif isinstance(op_next, Condition): return 1 else: raise ValueError('Error Instruction!') elif isinstance(op_this, Condition): return 1 else: return 0 # 在指令1和指令2之间插入一条不相关的指令 def insert_instr(cycle, hazard, instr1, instr2, isAllocated): for item in cycle.instrList: if not judge_hazard(instr1, instr2, hazard): if isAllocated[item] == 0: isAllocated[item] = 1 return item return None # 循环展开 # 输入: # ir为源代码的中间表示 # times为展开的次数 不少于2 # 输出: # ir中循环展开times次的中间表示 def unroll(ir, times): global ld_rt, ld_rs, ld_offset, st_rt, st_rs, add_rt, add_rs, addi_rt, addi_rs, addi_imm, cycle rlt = {'before': [], 'last': []} isAllocated = {} # 找到循环部分 for item in ir: if isinstance(item, Loop): cycle = item if cycle is None: raise ValueError('没有循环部分!') # 分析原始指令的操作数 for item in cycle.instrList: if isinstance(item, Load): ld_rt = item.rt ld_rs = item.rs ld_offset = item.offset elif isinstance(item, Store): st_rt = item.rt st_rs = item.rs elif isinstance(item, Add): add_rt = item.rt add_rs = item.rs elif isinstance(item, Addi): addi_rt = item.rt addi_rs = item.rs addi_imm = item.imm # 前若干次 rlt['before'].append(cycle.instrList[0]) # beq语句 for time in range(cycle.times): for item in cycle.instrList: flag_add = 0 flag_load = 0 add_rt_new = None load_rt_new = None if isinstance(item, Load): flag_add = 1 offset = addi_imm * (time + 1) # 每次offset增加一轮 try: load_rt_new = allocate_reg(item) # 分配虚拟寄存器 new_load = Load(reg1=load_rt_new, offset=offset, reg2=ld_rs) rlt['before'].append(new_load) except AllocateException as e: print(e) elif isinstance(item, Add): flag_load = 1 try: add_rt_new = allocate_reg(item) new_add = Add(reg1=add_rt_new, reg2=add_rs[0], reg3=add_rs[1]) rlt['before'].append(new_add) except AllocateException as e: print(e) elif isinstance(item, Store): if flag_add == 1 and flag_load == 1: # 找到与该stroe配套的load和add flag_add = 0 flag_load = 0 offset = addi_imm * (time + 1) try: new_store = Store(reg1=item.rt, offset=offset, reg2=st_rs) rlt['before'].append(new_store) # store结束后即可释放之前的寄存器 free_reg(add_rt_new) free_reg(load_rt_new) except AllocateException as e: print(e) cycle_iter_new = None for item in cycle.instrList: if isinstance(item, Addi): # 循环变量自增语句 cycle_iter_new = allocate_reg(item) new_addi = Addi(reg1=cycle_iter_new, reg2=cycle.iter, imm=cycle.times * addi_imm) rlt['before'].append(new_addi) break # 计算新的终止条件 new_reg_for_stop = allocate_reg(Addi(None, None, None)) new_addi_for_stop = Addi(reg1=new_reg_for_stop, reg2=cycle.times, imm=1 - times) rlt['before'].append(new_addi_for_stop) for item in cycle.instrList: if isinstance(item, Bne): # Bne 循环终止条件为cycle.iter = cycle.times-times+1 new_bne = Bne(reg1=cycle_iter_new, reg2=new_reg_for_stop) rlt['before'].append(new_bne) break # 最后一次 rlt['last'] = cycle return rlt