把项目移过来了

master
somny 2 years ago
parent 053aaf6edd
commit cfef673b97

@ -1,2 +1 @@
# architecture-2022 # 2022秋 高级计算机体系结构

@ -0,0 +1,26 @@
from hardware.hardware import Hardware
from execute.controller import Controller
from execute.debugger import Debugger
hw = Hardware()
ctrl = Controller(hw)
dbg = Debugger(hw)
prog = 'program/addiuTest.txt'
dbg.loadProgram(prog)
print('running...')
ctrl.run()
ctrl.run()
ctrl.run()
dbg.dumpGenReg()
print('running...')
ctrl.run()
ctrl.run()
ctrl.run()
dbg.dumpGenReg()
print('running...')
ctrl.run()
dbg.dumpGenReg()

@ -0,0 +1,72 @@
from hardware.hardware import Hardware
from instruction.nop import Nop
from instruction.ri.addiu import Addiu
from instruction.ldst.load import Load
from instruction.ldst.store import Store
from instruction.br.BEQ import Beq
from instruction.rr.addu import Addu
from instruction.j.j import J
class Controller:
opMap = {
0x09: Addiu,
0x20: Load,
0x28: Store,
0x04: Beq,
0x02: J,
}
funcMap = {
0x00: Nop,
0x21: Addu,
}
def __init__(self, hw):
self.hw = hw
#获取指令对象
#输入:
# instr为指令编码
#输出:
# instr表示的指令类型的对象
def getInstrObj(self, instr):
mask = (1 << 6) - 1
op = (instr >> 26) & mask
func = instr & mask
if op == 0x00:
if func in Controller.funcMap.keys():
return Controller.funcMap[func](self.hw)
else:
raise Exception('instruction does not exist')
else:
if op in Controller.opMap.keys():
return Controller.opMap[op](self.hw)
else:
raise Exception('instruction does not exist')
#取指令阶段
#效果:
# 将即将执行的指令编码写入instr寄存器pc+4
def instrFetch(self):
#从指令存储器中取指令
pc = self.hw.pc.read()
instr = self.hw.instrMem.read(pc)
self.hw.pplReg[1][0].write(instr)
#pc+4
self.hw.pc.write(pc + 4)
return instr
#无流水线的执行
#效果:
# 完整执行一条指令
def run(self):
#取指令,获取指令对象
instr = self.instrFetch()
instrObj = self.getInstrObj(instr)
self.hw.globalSync()
for i in range(len(instrObj.stages)):
instrObj.stages[i]()
self.hw.globalSync()

@ -0,0 +1,80 @@
from hardware.hardware import Hardware
class Debugger:
def __init__(self, hw):
self.hw = hw
#打印程序计数器
#效果:
# 打印当前pc寄存器的值
def dumpPC(self):
pc = self.hw.pc.read()
print('pc: {:08x}'.format(pc))
#打印通用寄存器
#效果:
# 打印当前所有通用寄存器的值
def dumpGenReg(self):
for i in range(self.hw.genRegCnt):
data = self.hw.genReg[i].read()
print('GR{:02}: {:08x}'.format(i, data))
#打印流水线寄存器
#效果:
# 打印当前所有流水线寄存器的值
def dumpPplReg(self):
for i in range(self.hw.stageCnt):
print('stage{}:'.format(i))
for j in range(self.hw.pplRegCnt):
data = self.hw.pplReg[i][j].read()
print('PR{}: {:08x}'.format(j, data))
#打印指令存储器
#输入:
# addr为地址
#效果:
# 打印当前指令存储器地址addr所在的一个字
def dumpInstrMem(self, addr):
data = self.hw.instrMem.read(addr)
print('IM{:08x}: {:08x}'.format(addr, data))
#打印数据存储器
#输入:
# addr为地址
#效果:
# 打印当前数据存储器地址addr所在的一个字
def dumpDataMem(self, addr):
data = self.hw.dataMem.read(addr)
print('DM{:08x}: {:08x}'.format(addr, data))
#获取指令列表
#输入:
# fileName为程序文件名
#输出:
# 程序中指令的列表
#约束:
# 程序文件的每一行是一个8位16进制数表示一条指令
def getListFromFile(fileName):
instrList = []
program = open(fileName, 'r')
for line in program:
instrList.append(int(line, 16))
return instrList
#加载程序
#输入:
# fileName为程序文件名
#效果:
# 将程序写入指令存储器地址从0开始并将pc置为0
def loadProgram(self, fileName):
instrList = Debugger.getListFromFile(fileName)
addr = 0
for instr in instrList:
self.hw.instrMem.write(addr, instr)
self.hw.globalSync()
addr = addr + 4
self.hw.pc.write(0)
self.hw.globalSync()

@ -0,0 +1,51 @@
from hardware.util import Register, Memory
#硬件资源
class Hardware:
def __init__(self):
#寄存器
self.pc = Register() #程序计数器
#通用寄存器
self.genRegCnt = 32 #通用寄存器数
self.genReg = [] #通用寄存器组
for i in range(self.genRegCnt):
self.genReg.append(Register())
#流水线寄存器
# 约定指令在第i个阶段可以读pplReg[i]中的寄存器、写pplReg[i+1]中的寄存器
self.pplRegCnt = 5 #流水线上每个阶段的寄存器数
self.stageCnt = 5 #流水线阶段数
self.pplReg = [] #流水线寄存器
for i in range(self.stageCnt):
stage = []
for j in range(self.pplRegCnt):
stage.append(Register())
self.pplReg.append(stage)
#存储器
self.instrMemSize = 1 << 32 #指令存储器字节数
self.dataMemSize = 1 << 32 #数据存储器字节数
self.instrMem = Memory(self.instrMemSize) #指令存储器
self.dataMem = Memory(self.dataMemSize) #数据存储器
#全局同步
#效果:
# 对所有寄存器和存储器进行同步
def globalSync(self):
#程序计数器同步
self.pc.sync()
#通用寄存器同步
for reg in self.genReg:
reg.sync()
#流水线寄存器同步
for stage in self.pplReg:
for reg in stage:
reg.sync()
#存储器同步
self.instrMem.sync()
self.dataMem.sync()

@ -0,0 +1,84 @@
#寄存器
# 约定寄存器为1word=32bit
class Register:
def __init__(self):
self.data = 0
self.buff = None
#读数据
#输出:
# 寄存器中的数据
def read(self):
return self.data
#写数据
#输入:
# data为写入的数据
#效果:
# 将data写入缓冲区
def write(self, data):
self.buff = data
#同步
#效果:
# 将缓冲区中的数据写入寄存器
def sync(self):
if self.buff is not None:
self.data = self.buff
self.buff = None
#存储器
# 约定每个存储单元为1byte=8bit但存取时需要按字对齐
class Memory:
def __init__(self, size):
self.size = size >> 2
self.dict = {}
self.addr = None
self.buff = None
#读数据
#输入:
# addr为读取的地址
#输出:
# 地址addr所在的一个字若addr不是4的整数倍将向下取整
def read(self, addr):
addr = addr >> 2
#检查地址是否越界
if addr < 0 or addr >= self.size:
raise Exception("memory address out of bounds")
if addr in self.dict.keys():
#该地址被访问过
return self.dict[addr]
else:
#该地址未被访问过
self.dict[addr] = 0
return 0
#写数据
#输入:
# addr为写入的地址
# data为写入的数据
#效果:
# 将data写入地址addr所在的一个字的缓冲区
#
#一个周期内只能写入一个数据
def write(self, addr, data):
addr = addr >> 2
#检查地址是否越界
if addr < 0 or addr >= self.size:
raise Exception("memory address out of bounds")
self.addr = addr
self.buff = data
#同步
#效果:
# 将缓冲区中的数据写入存储器
def sync(self):
if self.addr is not None:
self.dict[self.addr] = self.buff
self.addr = None
self.buff = None

@ -0,0 +1,27 @@
## 已实现的指令
### 1 br型
#### 1.1 beq 相等时跳转
TODO
### 2 j型
#### 2.1 j 跳转
TODO
### 3 rr型
#### 3.1 addu 无符号加
TODO
### 4 ri型
#### 4.1 addiu 无符号加立即数
TODO
### 5 ldst型
#### 5.1 load 加载字节
TODO
#### 5.2 store 存储字节
TODO
### 6 其他
#### 6.1 nop 空指令
TODO

@ -0,0 +1,37 @@
from instruction.instruction import Instruction
from hardware.hardware import Hardware
class Beq(Instruction):
def __init__(self, hw):
super().__init__(hw)
def instrDecode(self):
super().instrDecode()
instr = self.hw.pplReg[1][0].read()
mask1 = (1 << 5) - 1
rs = (instr >> 21) & mask1 # 这里的rs为base
rsData = self.hw.genReg[rs].read()
rt = (instr >> 16) & mask1
rtData = self.hw.genReg[rt].read()
mask2 = (1 << 16) - 1
offset = instr & mask2
self.hw.pplReg[2][0].write(rsData) # A <= Reg[base]
self.hw.pplReg[2][1].write(rtData) # B <= rt
self.hw.pplReg[2][2].write(offset) # C <= offset
def execute(self):
super().execute()
pc=self.hw.pc.read()
if self.hw.pplReg[2][0].read==self.hw.pplReg[2][1].read:
jpc=pc+4+self.hw.pplReg[2][2].read*4#offest后补两个0
else:
jpc=pc+4
self.hw.pplReg[3][0].write(jpc)
def memAccess(self):
super().memAccess()
Hardware.pc.write(self.hw.pplReg[3][0].read())
def writeBack(self):
super().writeBack()

@ -0,0 +1,27 @@
#指令抽象类
# 一条指令的实现应当继承这个类,并重写四个方法
class Instruction:
#指令译码阶段
def instrDecode(self):
pass
#运算阶段
def execute(self):
pass
#访问存储器阶段
def memAccess(self):
pass
#写回寄存器阶段
def writeBack(self):
pass
def __init__(self, hw):
self.hw = hw #指令关联的硬件结构
self.stages = [
self.instrDecode,
self.execute,
self.memAccess,
self.writeBack
] #每条指令包含四个阶段

@ -0,0 +1,28 @@
from instruction.instruction import Instruction
from hardware.hardware import Hardware
class J(Instruction):
def instrDecode(self):
super().instrDecode()
instr = self.hw.pplReg[1][0].read()
nextPC = str(bin(Hardware.pc.read() + 4))[2:6] # PC+4再取高4位
instr_index = str(bin(instr))[8:34] # instruction转换为字符串类型时0b需要去除然后取出其中的[25:0]
self.hw.pplReg[2][0].write(nextPC)
self.hw.pplReg[2][1].write(instr_index)
def execute(self):
super().execute()
jPC = int(self.hw.pplReg[2][0].read + self.hw.pplReg[2][1].read + 2*'0') # PC <-- PC[31:28] || instr_index || 00. (||为拼接操作)
self.hw.pplReg[3][0].write(jPC)
def memAccess(self):
super().memAccess()
Hardware.pc.write(self.hw.pplReg[3][0].read())
def writeBack(self):
super().writeBack()

@ -0,0 +1,28 @@
from instruction.instruction import Instruction
# 存取类指令
class Ldst(Instruction):
def __init__(self, hw):
super().__init__(hw)
def instrDecode(self):
super().instrDecode()
instr = self.hw.pplReg[1][0].read()
mask1 = (1 << 5) - 1
base = (instr >> 21) & mask1 # 这里的rs为base
baseData = self.hw.genReg[base].read()
rt = (instr >> 16) & mask1
mask2 = (1 << 16) - 1
offset = instr & mask2
self.hw.pplReg[2][0].write(baseData) # A <= Reg[base]
self.hw.pplReg[2][1].write(rt) # B <= rt
self.hw.pplReg[2][2].write(offset) # C <= offset
def execute(self):
super().execute()
rt = self.hw.pplReg[2][1].read()
addr = self.hw.pplReg[2][0].read() + self.hw.pplReg[2][2].read() # 计算地址 = baseData+offset
self.hw.pplReg[3][0].write(addr)
self.hw.pplReg[3][1].write(rt)

@ -0,0 +1,20 @@
from instruction.ldst.ldst import Ldst
class Load(Ldst):
def __init__(self, hw):
super().__init__(hw)
def memAccess(self):
super().memAccess()
addr = self.hw.pplReg[3][0].read()
memData = self.hw.dataMem.read(addr)
rt = self.hw.pplReg[3][1].read()
self.hw.pplReg[4][0].write(memData) # 取内存数据
self.hw.pplReg[4][1].write(rt)
def writeBack(self):
super().writeBack()
rt = self.hw.pplReg[4][1].read()
memData = self.hw.pplReg[4][0].read()
self.hw.genReg[rt].write(memData) # 数据写回目标寄存器

@ -0,0 +1,15 @@
from instruction.ldst.ldst import Ldst
class Store(Ldst):
def __init__(self, hw):
super().__init__(hw)
def memAccess(self):
super().memAccess()
addr = self.hw.pplReg[3][0].read()
rt = self.hw.pplReg[3][1].read()
regData = self.hw.genReg[rt].read() # 取寄存器数据
self.hw.dataMem.write(addr, regData) # 写入存储器

@ -0,0 +1,16 @@
from instruction.instruction import Instruction
#空指令
class Nop(Instruction):
#什么都不做
def instrDecode(self):
super().instrDecode()
def execute(self):
super().execute()
def memAccess(self):
super().memAccess()
def writeBack(self):
super().writeBack()

@ -0,0 +1,16 @@
from instruction.ri.riInstr import SignExtRegImmInstr
#无符号加立即数
class Addiu(SignExtRegImmInstr):
def execute(self):
super().execute()
op1 = self.hw.pplReg[2][0].read()
op2 = self.hw.pplReg[2][1].read()
rt = self.hw.pplReg[2][2].read()
mask = (1 << 32) - 1
res = (op1 + op2) & mask
self.hw.pplReg[3][0].write(res)
self.hw.pplReg[3][1].write(rt)

@ -0,0 +1,59 @@
from instruction.instruction import Instruction
#RI类指令
class RegImmInstr(Instruction):
def instrDecode(self):
super().instrDecode()
instr = self.hw.pplReg[1][0].read()
mask = (1 << 5) - 1
rs = (instr >> 21) & mask
rsData = self.hw.genReg[rs].read()
rt = (instr >> 16) & mask
self.hw.pplReg[2][0].write(rsData)
self.hw.pplReg[2][2].write(rt)
def memAccess(self):
super().memAccess()
res = self.hw.pplReg[3][0].read()
rt = self.hw.pplReg[3][1].read()
self.hw.genReg[rt].write(res)
#进行零扩展的RI类指令
class ZeroExtRegImmInstr(RegImmInstr):
def instrDecode(self):
super().instrDecode()
instr = self.hw.pplReg[1][0].read()
mask = (1 << 16) - 1
imm = instr & mask
self.hw.pplReg[2][1].write(imm)
#进行符号扩展的RI类指令
class SignExtRegImmInstr(RegImmInstr):
#符号扩展
#输入:
# imm为16bit数据
#输出:
# imm的32bit符号扩展
def signedExtend(imm):
mask = (1 << 16) - 1 << 16
if (imm >> 15) & 1:
return imm | mask
else:
return imm
def instrDecode(self):
super().instrDecode()
instr = self.hw.pplReg[1][0].read()
mask = (1 << 16) - 1
imm = instr & mask
imm = SignExtRegImmInstr.signedExtend(imm)
self.hw.pplReg[2][1].write(imm)

@ -0,0 +1,50 @@
from instruction.instruction import Instruction
#from hardware.hardware import Hardware
#RR类指令
class Addu(Instruction):
def __init__(self, hw):
super().__init__(hw)
def instrDecode(self):
super().instrDecode()
instr = self.hw.pplReg[1][0].read()
mask = (1 << 5) - 1
rs = (instr >> 21) & mask
rsData = self.hw.genReg[rs].read()
rt = (instr >> 16) & mask
rtData = self.hw.genReg[rs].read()
rd = (instr >> 11) & mask
self.hw.pplReg[2][0].write(rsData)
self.hw.pplReg[2][1].write(rtData)
self.hw.pplReg[2][3].write(rd)
def execute(self):
super().execute()
op1 = self.hw.pplReg[2][0].read()
op2 = self.hw.pplReg[2][1].read()
rd = self.hw.pplReg[2][3].read()
mask = (1 << 32) - 1
res = (op1 + op2) & mask
self.hw.pplReg[3][0].write(res)
self.hw.pplReg[3][1].write(rd)
def memAccess(self):
super().memAccess()
addr = self.hw.pplReg[3][0].read()
memData = self.hw.dataMem.read(addr)
rd = self.hw.pplReg[3][1].read()
self.hw.pplReg[4][0].write(memData) # 取内存数据
self.hw.pplReg[4][1].write(rd)
def writeBack(self):
super().writeBack()
rd = self.hw.pplReg[4][1].read()
memData = self.hw.pplReg[4][0].read()
self.hw.genReg[rd].write(memData) # 数据写回目标寄存器

@ -0,0 +1,20 @@
from hardware.hardware import Hardware
from execute.controller import Controller
from execute.debugger import Debugger
hw = Hardware()
ctrl = Controller(hw)
dbg = Debugger(hw)
prog = 'program/ldstTest.txt'
# Addiu r1,r1,3
# Store r1, 10(r0)
# Load r2, 10(r0)
dbg.loadProgram(prog)
ctrl.run()
ctrl.run()
ctrl.run()
dbg.dumpGenReg()
# dbg.dumpPplReg()
dbg.dumpDataMem(10)

@ -0,0 +1,7 @@
24210001
24210001
24210001
2421ffff
2421ffff
2421ffff
2421ffff

@ -0,0 +1,3 @@
24210003
A001000A
8002000A

@ -0,0 +1,3 @@
00001000
00002000
00003000

@ -0,0 +1,168 @@
#程序类
class Program:
def __init__(self):
self.instrList = [] #指令列表其中的元素或者是Instruction或者是Loop
#将中间表示转化为代码并输出到文件
def emit(self, stream, cnt):
for instr in self.instrList:
instr.emit(stream, cnt)
return cnt
#循环类
class Loop:
def __init__(self, iterator, times):
self.iter = iterator #循环变量,是一个寄存器
self.times = times #循环次数,是一个寄存器
self.instrList = [] #指令列表其中的元素是Instruction或Loop应该有如下的形式
'''
beq i, n, out
loop:
[loop body]
addi i, i, 1
bne i, n, loop
out:
'''
def emit(self, stream, cnt):
cnt = cnt + 1
for i in range(len(self.instrList)):
if i == 0:
self.instrList[0].emit(stream, cnt)
stream.write('loop' + str(cnt) + ':\n')
else:
self.instrList[i].emit(stream, cnt)
stream.write('out' + str(cnt) + ':\n')
return cnt
#指令类
class Instruction:
def __init__(self):
self.rs = [] #源寄存器,是一个列表,其中的元素是该指令读取的所有寄存器号
#注意这个列表里去掉了重复的元素
self.rt = None #目的寄存器,是该指令写入的寄存器号
self.instrStr = None #指令字符串
def emit(self, stream, cnt):
pass
#存储访问指令类
class MemInstr(Instruction):
def emit(self, stream, cnt):
stream.write(self.instrStr + '\n')
return cnt
#Load
class Load(MemInstr):
#load reg1, offset(reg2)
def __init__(self, reg1, offset, reg2):
super().__init__()
self.rt = reg1
self.rs.append(reg2)
self.offset = offset
self.instrStr = 'load r' + str(reg1) + ', ' + str(offset) + '(r' + str(reg2) + ')'
#Store
class Store(MemInstr):
#store reg1, imm(reg2)
def __init__(self, reg1, offset, reg2):
super().__init__()
#去掉重复的元素
self.rs.append(reg1)
if reg1 != reg2:
self.rs.append(reg2)
self.offset = offset
self.instrStr = 'store r' + str(reg1) + ', ' + str(offset) + '(r' + str(reg2) + ')'
#ALU型指令类
class AluInstr(Instruction):
def emit(self, stream, cnt):
stream.write(self.instrStr + '\n')
return cnt
#Nop
class Nop(AluInstr):
#nop
def __init__(self):
super().__init__()
self.instrStr = 'nop'
#Add
class Add(AluInstr):
#add reg1, reg2, reg3
def __init__(self, reg1, reg2, reg3):
super().__init__()
self.rt = reg1
#去掉重复的元素
self.rs.append(reg2)
if reg2 != reg3:
self.rs.append(reg3)
self.instrStr = 'add r' + str(reg1) + ', r' + str(reg2) + ', ' + str(reg3)
#Move
class Move(AluInstr):
#move reg1, reg2
def __init__(self, reg1, reg2):
super().__init__()
self.rt = reg1
self.rs.append(reg2)
self.instrStr = 'move r' + str(reg1) + ', r' + str(reg2)
#Addi
class Addi(AluInstr):
#addi reg1, reg2, imm
def __init__(self, reg1, reg2, imm):
super().__init__()
self.rt = reg1
self.rs.append(reg2)
self.imm = imm
self.instrStr = 'addi r' + str(reg1) + ', r' + str(reg2) + ', ' + str(imm)
#条件跳转指令类
class Condition(Instruction):
pass
#Bne
class Bne(Condition):
#bne reg1, reg2, label
def __init__(self, reg1, reg2):
#Bne对象的属性中不需要包含label它应该在将中间表示转化为代码时被加上
super().__init__()
#去掉重复的元素
self.rs.append(reg1)
if reg1 != reg2:
self.rs.append(reg2)
self.instrStr = 'bne r' + str(reg1) + ', r' + str(reg2)
def emit(self, stream, cnt):
instrStr = self.instrStr + ', out' + str(cnt)
stream.write(instrStr + '\n')
return cnt
#Beq
class Beq(Condition):
#beq reg1, reg2, label
def __init__(self, reg1, reg2):
super().__init__()
#去掉重复的元素
self.rs.append(reg1)
if reg1 != reg2:
self.rs.append(reg2)
self.instrStr = 'beq r' + str(reg1) + ', r' + str(reg2)
def emit(self, stream, cnt):
instrStr = self.instrStr + ', loop' + str(cnt)
stream.write(instrStr + '\n')
return cnt

@ -0,0 +1,11 @@
from ir.ir import *
#中间表示转化为代码
#输入:
# ir为中间表示
# fileName为目的代码的文件名
#效果:
# 将ir对应的汇编代码写入fileName文件若文件不存在则创建
def ir2code(ir, fileName):
fileStream = open(fileName, 'w')
ir.emit(fileStream, 0)

@ -0,0 +1,28 @@
from ir.ir import *
from ir.trans import ir2code
'''
beq r1, r2, out (1)
loop:
load r10, 0(r1) (2)
add r14, r10, r12 (3)
store r14, 0(r1) (4)
addi r1, r1, 1 (5)
bne r1, r2, loop (6)
out:
'''
prog = Program()
loop = Loop(1, 2)
loop.instrList.append(Beq(1, 2))
loop.instrList.append(Load(10, 0, 1))
loop.instrList.append(Add(14, 10, 12))
loop.instrList.append(Store(14, 0, 1))
loop.instrList.append(Addi(1, 1, 1))
loop.instrList.append(Bne(1, 2))
prog.instrList.append(loop)
fileName = 'program/irTest.txt'
ir2code(prog, fileName)

@ -0,0 +1,85 @@
# 循环展开
## 1 假设
关于源代码的形式,做如下的假设:
- 除了循环外源代码中不含其他分支或跳转指令比如if语句、goto语句、函数调用等
- 不区分浮点运算和整数运算
- 仅包含形如`for i = 0 to n - 1`的循环,其中循环变量`i`在循环体内不会被修改,`n`是变量
进一步假设源代码中仅包含以下要素:
- 标签:形如`label: [instruction]`,其中`label`是标签,`[instruction]`是某条指令
- 功能型指令:
- 加载:形如`load reg1, offset(reg2)`,其中`reg`是寄存器,`offset`是某个整数
- 存储:形如`store reg1, offset(reg2)`,其中`reg`是寄存器,`offset`是某个整数
- 加法:形如`add reg1, reg2, reg3`,其中`reg1`、`reg2`、`reg3`是寄存器
- 移动:形如`move reg1, reg2`,其中`reg1`、`reg2`是寄存器
- 加立即数:形如`addi reg1, reg2, imm`,其中`reg1`、`reg2`是寄存器,`imm`是某个整数
- 空指令:形如`nop`
- 条件跳转指令:
- 不相等时跳转:形如`bne reg1, reg2, label`,其中`reg1`、`reg2`是寄存器,`label`是标签
- 相等时跳转:形如`beq reg1, reg2, label`,其中`reg1`、`reg2`是寄存器,`label`是标签
关于寄存器的使用,做如下假设:
- 物理寄存器有32个
- 存储器中有一块专用区域作为虚拟寄存器的交换空间:
- 交换空间是一块起始地址为0的连续存储空间
- 交换空间足够大
关于指令排序的约束,做如下假设:
- 5阶段流水线
- 分支延迟1周期延迟槽中的指令无条件执行
- (其他假设由实现者自行补充在这里)
## 2 程序结构
整个程序的描述如下:
- 输入:源代码的中间表示
- 输出:经过循环展开和指令重排后的汇编代码
- 约束输出代码应当能够直接被CPU执行并且与输入代码等效
我们将整个程序划分为四个模块:
- 循环展开:将代码中的循环展开若干次,展开的次数应当作为参数输入
- 寄存器管理:将代码中使用的虚拟寄存器号转化为物理寄存器号,适当加入与存储器交换的指令
- 指令重排:将指令重新排列,以消除指令之间的冲突,并**尽可能地**提高执行效率
- 代码生成:将经过处理的中间表示转化为输出代码
### 2.1 中间表示的形式
- 一个程序是一个列表,其中每一项或者是一个功能型指令、或者是一个循环
- 仅考虑特定形式的for循环因此一个循环可以用如下结构表示
- 循环变量:一个寄存器
- 循环次数:一个寄存器
- 循环体:一个程序,即一列功能型指令或循环(允许循环的嵌套)
形式化的表达是这样的:
```
program ::= [item, item, ..., item]
item ::= function | loop
loop ::= [iterator, times, program]
```
具体的实现在`ir/ir.py`中,可以阅读一下
### 2.2 循环展开模块
循环展开模块的作用是将一个中间表示中的循环展开指定次数,输出也是一个中间表示
实现时注意边界条件,展开后的循环在跳出前的最后一次循环体可能有不一样的形式
实现者可以自行决定嵌套的循环如何展开:
- 展开最内层的循环
- 从内向外展开所有循环
- 将嵌套的循环展开成单层的循环
### 2.3 寄存器管理模块
在循环展开模块中,通常需要使用更多的寄存器,我们允许指令访问的寄存器号可以是任意的,虚拟寄存器模块负责将这些虚拟寄存器号转化为物理寄存器号
当物理寄存器不够用时,需要将寄存器中的数据移到存储器中,在适当的时候调回(参考虚拟内存中的调页)
寄存器管理模块的输入输出都是一个中间表示,输入中允许访问任意的虚拟寄存器号,输出中仅允许访问有限的物理寄存器号
### 2.4 指令重排
指令重排模块的作用是将指令重新排列,使其成为满足假设的程序,输入输出都是一个中间表示
在正确的基础上实现者可以自行决定优化到什么程度可以先无脑插入nop
### 2.5 代码生成模块
代码生成模块的作用是将一个中间表示转化为对应的汇编代码,并输出到指定文件
## 2 其他事项

@ -0,0 +1,8 @@
beq r1, r2, loop1
loop1:
load r10, 0(r1)
add r14, r10, 12
store r14, 0(r1)
addi r1, r1, 1
bne r1, r2, out1
out1:

@ -0,0 +1,62 @@
from ir.ir import *
#指令重排
#输入:
# ir为源代码对应的中间表示
#输出:
# ir中指令按约束重排后的中间表示
def reorder(ir):
# reorder list在列表中重排指令
ROL = ir
n = len(ROL)
i = 0
# 根据相关性插入stall
while i < n:
if i < n - 1:
if (ROL[i][0] == 'l') & (ROL[i+1][0] == 'a'):
if (ROL[i][6] == ROL[i+1][9]) or (ROL[i][6] == ROL[i+1][12]):
ROL.insert(i+1, 'Stall')
i = i + 2
n = n + 1
elif (ROL[i][0] == 'a') & (ROL[i+1][0] == 'a'):
if (ROL[i][5] == ROL[i+1][9]) or (ROL[i][5] == ROL[i+1].instrStr[12]):
j = i + 1
while j < i + 4:
ROL.insert(j, 'Stall')
i = i + 4
n = n + 3
elif (ROL[i][0] == 'a') & (ROL[i+1][0] == 's'):
if ROL[i][5] == ROL[i+1][7]:
k = i + 1
while k < i + 3:
ROL.insert(k, 'Stall')
k = k + 1
i = i + 3
n = n + 2
elif (ROL[i][0] == 'a') & (ROL[i+1][0] == 'b'):
if (ROL[i][6] == ROL[i+1][6]) or (ROL[i][6] == ROL[i+1][9]):
ROL.insert(i + 1, 'Stall')
i = i + 2
n = n + 1
elif (ROL[i][0] == 'b'):
ROL.insert(i + 1, 'Stall')
i = i + 2
n = n + 1
else:
i = i + 1
print(i)
elif ROL[i][0] == 'b':
ROL.insert(i + 1, 'Stall')
break
else:
break

@ -0,0 +1,221 @@
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

@ -0,0 +1,95 @@
from scoreboard import Scoreboard
class Runner:
#指令状态表项
class InstrItem:
def __init__(self):
self.issue = 0
self.read = 0
self.execute = 0
self.write = 0
#功能部件
class FuncUnit:
def __init__(self, num, execTime, instrStat, scoreboard):
self.num = num
self.execTime = execTime
self.instrStat = instrStat
self.scoreboard = scoreboard
self.clock = 0
self.localClock = 0
self.pc = 0
def issue(self, pc, clock):
self.clock = 1
self.pc = pc
instrItem = Runner.InstrItem()
instrItem.issue = clock
self.instrStat.append(instrItem)
def run(self, clock):
if self.clock == 1: #读操作数
if self.scoreboard.readControl(self.num):
self.instrStat[self.pc].read = clock
self.clock += 1
elif self.clock == 2: #执行
if self.localClock == 0: #未开始执行
if self.scoreboard.executeControl(self.num):
self.localClock = 1
else:
self.localClock += 1
if self.localClock == self.execTime:
self.localClock = 0
self.instrStat[self.pc].execute = clock
self.clock += 1
elif self.clock == 3: #写回结果
if self.scoreboard.writeControl(self.num):
self.instrStat[self.pc].write = clock
self.clock = 0
self.pc = 0
def __init__(self, program):
self.regCnt = 32
self.fuCnt = 4
self.scoreboard = Scoreboard(32, 4)
self.instrStat = []
self.clock = 0
self.fus = [
Runner.FuncUnit(0, 1, self.instrStat, self.scoreboard), #整数部件
Runner.FuncUnit(1, 10, self.instrStat, self.scoreboard), #乘法部件
Runner.FuncUnit(2, 2, self.instrStat, self.scoreboard), #加法部件
Runner.FuncUnit(3, 40, self.instrStat, self.scoreboard) #除法部件
]
self.program = program
self.pc = 0
def singleStepRun(self):
self.clock += 1
for i in range(4):
self.fus[i].run(self.clock)
if self.pc < len(self.program):
instr = self.program[self.pc]
if self.scoreboard.issueControl(instr):
self.fus[instr.fu].issue(self.pc, self.clock)
self.pc += 1
self.scoreboard.sync()
def run(self, circles):
for i in range(circles):
self.singleStepRun()
def dump(self):
print('{:<10}{:<10}{:<10}{:<10}'.format('issue', 'read', 'execute', 'write'))
for item in self.instrStat:
print('{:<10}{:<10}{:<10}{:<10}'.format(
item.issue,
item.read,
item.execute,
item.write
))
print('')
self.scoreboard.dump()

@ -0,0 +1,236 @@
from util import Register
#计分板
class Scoreboard:
#功能部件状态表项
class FuncUnitItem:
def __init__(self, fuCnt):
self.busy = Register(False)
self.op = Register('')
self.src1Valid = Register(False)
self.src1 = Register(0)
self.fu1 = Register(fuCnt)
self.ready1 = Register(False)
self.src2Valid = Register(False)
self.src2 = Register(0)
self.fu2 = Register(fuCnt)
self.ready2 = Register(False)
self.destValid = Register(False)
self.dest = Register(0)
#同步
def sync(self):
self.busy.sync()
self.op.sync()
self.src1Valid.sync()
self.src1.sync()
self.fu1.sync()
self.ready1.sync()
self.src2Valid.sync()
self.src2.sync()
self.fu2.sync()
self.ready2.sync()
self.destValid.sync()
self.dest.sync()
def __init__(self, regCnt, fuCnt):
self.regCnt = regCnt
self.fuCnt = fuCnt
self.regResStat = [Register(fuCnt) for i in range(regCnt)] #寄存器结果状态表
self.funcUnitStat = [Scoreboard.FuncUnitItem(fuCnt) for i in range(fuCnt)] #功能部件状态表
#同步
def sync(self):
for item in self.regResStat:
item.sync()
for item in self.funcUnitStat:
item.sync()
#检查功能部件号是否有效
#约定:功能部件号为功能部件总数表示无效
def fuValid(self, fu):
return fu < self.fuCnt
def issueControl(self, instr):
fuItem = self.funcUnitStat[instr.fu]
#检查功能部件忙碌
busy = fuItem.busy.read()
#检查写后写
waw = False
if instr.destValid:
waw |= self.fuValid(self.regResStat[instr.dest].read())
if busy or waw: #阻塞
return False
fuItem.busy.write(True) #占用功能部件
fuItem.op.write(instr.op) #记录操作
#记录操作数信息
fuItem.src1Valid.write(instr.src1Valid)
if instr.src1Valid:
fuItem.src1.write(instr.src1)
fu1 = self.regResStat[instr.src1].read()
fuItem.fu1.write(fu1)
fuItem.ready1.write(not self.fuValid(fu1))
fuItem.src2Valid.write(instr.src2Valid)
if instr.src2Valid:
fuItem.src2.write(instr.src2)
fu2 = self.regResStat[instr.src2].read()
fuItem.fu2.write(fu2)
fuItem.ready2.write(not self.fuValid(fu2))
#记录结果信息
fuItem.destValid.write(instr.destValid)
if instr.destValid:
fuItem.dest.write(instr.dest)
self.regResStat[instr.dest].write(instr.fu)
return True
def readControl(self, fu):
fuItem = self.funcUnitStat[fu]
src1Valid = fuItem.src1Valid.read()
src2Valid = fuItem.src2Valid.read()
#检查指令未发出
unissued = not fuItem.busy.read()
#检查写后读
raw = False
if src1Valid:
raw |= not fuItem.ready1.read()
if src2Valid:
raw |= not fuItem.ready2.read()
if unissued or raw: #阻塞
return False
#操作数已读取
if src1Valid:
fuItem.fu1.write(self.fuCnt)
fuItem.ready1.write(False)
if src2Valid:
fuItem.fu2.write(self.fuCnt)
fuItem.ready2.write(False)
return True
def executeControl(self, fu):
fuItem = self.funcUnitStat[fu]
#检查指令未发出
unissued = not fuItem.busy.read()
if unissued: #阻塞
return False
return True
def writeControl(self, fu):
fuItem = self.funcUnitStat[fu]
destValid = fuItem.destValid.read()
#检查指令未发出
unissued = not fuItem.busy.read()
#检查读后写
war = False
if destValid:
dest = fuItem.dest.read()
for f in self.funcUnitStat:
if f.src1Valid.read():
war |= (f.src1.read() == dest) and f.ready1.read()
if f.src2Valid.read():
war |= (f.src2.read() == dest) and f.ready2.read()
if unissued or war: #阻塞
return False
if destValid:
#所有依赖该结果的指令可以读操作数
for f in self.funcUnitStat:
if f.src1Valid.read() and f.fu1.read() == fu:
f.ready1.write(True)
if f.src2Valid.read() and f.fu2.read() == fu:
f.ready2.write(True)
#结果已写回
self.regResStat[fuItem.dest.read()].write(self.fuCnt)
#功能部件不再被占用
fuItem.busy.write(False)
fuItem.src1Valid.write(False)
fuItem.src2Valid.write(False)
fuItem.destValid.write(False)
return True
#打印
def dump(self):
#打印功能部件状态表
print('{:<10}{:<10}{:<10}{:<10}{:<10}{:<10}{:<10}{:<10}'.format(
'busy',
'dest',
'src1',
'src2',
'fu1',
'fu2',
'ready1',
'ready2'
))
for item in self.funcUnitStat:
busy = item.busy.read()
if item.destValid.read():
dest = item.dest.read()
else:
dest = ''
src1 = item.src1.read()
fu1 = item.fu1.read()
if not self.fuValid(fu1):
fu1 = ''
ready1 = item.ready1.read()
if not item.src1Valid.read():
src1 = ''
fu1 = ''
ready1 = ''
src2 = item.src2.read()
fu2 = item.fu2.read()
if not self.fuValid(fu2):
fu2 = ''
ready2 = item.ready2.read()
if not item.src2Valid.read():
src2 = ''
fu2 = ''
ready2 = ''
print('{:<10}{:<10}{:<10}{:<10}{:<10}{:<10}{:<10}{:<10}'.format(
busy,
dest,
src1,
src2,
fu1,
fu2,
ready1,
ready2
))
print('')
#打印寄存器结果状态表
for i in range(self.regCnt):
if i % 2 == 0:
print('F{:<3}'.format(i), end = ' ')
print('')
for i in range(self.regCnt):
if i % 2 == 0:
fu = self.regResStat[i].read()
if not self.fuValid(fu):
fu = ''
print('{:<4}'.format(fu), end = ' ')
print('')

@ -0,0 +1,16 @@
from run import Runner
from util import Instruction
program = []
program.append(Instruction('load', 0, True, 6, False, 0, True, 2))
program.append(Instruction('load', 0, True, 2, False, 0, True, 3))
program.append(Instruction('mult', 1, True, 0, True, 2, True, 4))
program.append(Instruction('sub', 2, True, 8, True, 6, True, 2))
program.append(Instruction('div', 3, True, 10, True, 0, True, 6))
program.append(Instruction('add', 2, True, 6, True, 8, True, 2))
runner = Runner(program)
runner.run(70)
runner.dump()
print('')
print('clk: {}'.format(runner.clock))

@ -0,0 +1,39 @@
#寄存器
class Register:
def __init__(self, initValue):
self.data = initValue
self.buff = None
#读数据
#输出:
# 寄存器中的数据
def read(self):
return self.data
#写数据
#输入:
# data为写入的数据
#效果:
# 将data写入缓冲区
def write(self, data):
self.buff = data
#同步
#效果:
# 将缓冲区中的数据写入寄存器
def sync(self):
if self.buff is not None:
self.data = self.buff
self.buff = None
#指令
class Instruction:
def __init__(self, op, fu, destValid, dest, src1Valid, src1, src2Valid, src2):
self.op = op #操作
self.fu = fu #所需的功能部件
self.destValid = destValid #目的寄存器是否有效
self.dest = dest #目的寄存器号
self.src1Valid = src1Valid #源寄存器1是否有效
self.src1 = src1 #源寄存器号1
self.src2Valid = src2Valid #源寄存器2是否有效
self.src2 = src2 #源寄存器号2

@ -0,0 +1,53 @@
# IS表中的元素
class Ins_Status:
def __init__(self):
self.issue = 'None'
self.oper = 'None'
self.comp = 'None'
self.result = 'None'
def __str__(self):
print_str = 'issue=' + str(self.issue) + ' '
print_str += 'oper=' + str(self.oper) + ' '
print_str += 'comp=' + str(self.comp) + ' '
print_str += 'result=' + str(self.result)
return print_str
# FUS表的元素
class FU_Status:
def __init__(self):
self.busy = 'No'
self.op = 'None'
self.fi = 'None'
self.fj = 'None'
self.fk = 'None'
self.qj = 'None'
self.qk = 'None'
self.rj = 'None'
self.rk = 'None'
def __str__(self):
print_str = 'busy=' + self.busy + ' '
print_str += 'op=' + str(self.op) + ' '
print_str += 'fi=' + self.fi + ' '
print_str += 'fj=' + self.fj + ' '
print_str += 'fk=' + self.fk + ' '
print_str += 'qj=' + str(self.qj) + ' '
print_str += 'qk=' + str(self.qk) + ' '
print_str += 'rj=' + self.rj + ' '
print_str += 'rk=' + self.rk
return print_str
def clear(self):
self.busy = 'No'
self.op = 'None'
self.fi = 'None'
self.fj = 'None'
self.fk = 'None'
self.qj = 'None'
self.qk = 'None'
self.rj = 'None'
self.rk = 'None'

@ -0,0 +1,245 @@
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()

@ -0,0 +1,234 @@
# 程序类
class Program:
def __init__(self):
self.instrList = [] # 指令列表其中的元素或者是Instruction或者是Loop
# 将中间表示转化为代码并输出到文件
def emit(self, stream, cnt):
for instr in self.instrList:
instr.emit(stream, cnt)
return cnt
# 循环类
class Loop:
def __init__(self, iterator, times):
self.iter = iterator # 循环变量,是一个寄存器
self.times = times # 循环次数,是一个寄存器
self.instrList = [] # 指令列表其中的元素是Instruction或Loop应该有如下的形式
'''
beq i, n, out
loop:
[loop body]
addi i, i, 1
bne i, n, loop
out:
'''
def emit(self, stream, cnt):
cnt = cnt + 1
for i in range(len(self.instrList)):
if i == 0:
self.instrList[0].emit(stream, cnt)
stream.write('loop' + str(cnt) + ':\n')
else:
self.instrList[i].emit(stream, cnt)
stream.write('out' + str(cnt) + ':\n')
return cnt
# 指令类
class Instruction:
def __init__(self):
self.rs = [] # 源寄存器,是一个列表,其中的元素是该指令读取的所有寄存器号
# 注意这个列表里去掉了重复的元素
self.rt = None # 目的寄存器,是该指令写入的寄存器号
self.instrStr = None # 指令字符串
def emit(self, stream, cnt):
pass
# 存储访问指令类
class MemInstr(Instruction):
def emit(self, stream, cnt):
stream.write(self.instrStr + '\n')
return cnt
# Load
class Load(MemInstr):
# load reg1, offset(reg2)
def __init__(self, reg1, offset, reg2):
super().__init__()
self.rt = reg1
self.rs.append('None')
self.rs.append(reg2)
self.offset = offset
self.instrStr = 'load r' + str(reg1) + ', ' + str(offset) + '(r' + str(reg2) + ')'
self.fu = 'Integer'
# Store
class Store(MemInstr):
# store reg1, imm(reg2)
def __init__(self, reg1, offset, reg2):
super().__init__()
# 去掉重复的元素
self.rs.append(reg1)
if reg1 != reg2:
self.rs.append(reg2)
self.offset = offset
self.instrStr = 'store r' + str(reg1) + ', ' + str(offset) + '(r' + str(reg2) + ')'
# ALU型指令类
class AluInstr(Instruction):
def emit(self, stream, cnt):
stream.write(self.instrStr + '\n')
return cnt
# Nop
class Nop(AluInstr):
# nop
def __init__(self):
super().__init__()
self.instrStr = 'nop'
# Add
class Add(AluInstr):
# add reg1, reg2, reg3
def __init__(self, reg1, reg2, reg3):
super().__init__()
self.rt = reg1
self.fu = 'Add'
# 去掉重复的元素
self.rs.append(reg2)
if reg2 != reg3:
self.rs.append(reg3)
self.instrStr = 'add r' + str(reg1) + ', r' + str(reg2) + ', ' + str(reg3)
# Sub
class Sub(AluInstr):
# add reg1, reg2, reg3
def __init__(self, reg1, reg2, reg3):
super().__init__()
self.rt = reg1
self.fu = 'Add'
# 去掉重复的元素
self.rs.append(reg2)
if reg2 != reg3:
self.rs.append(reg3)
self.instrStr = 'sub r' + str(reg1) + ', r' + str(reg2) + ', ' + str(reg3)
# Mul
class Mul(AluInstr):
# Mul reg1, reg2, reg3
def __init__(self, reg1, reg2, reg3):
super().__init__()
self.rt = reg1
self.fu = 'Mul'
# 去掉重复的元素
self.rs.append(reg2)
if reg2 != reg3:
self.rs.append(reg3)
self.instrStr = 'mul r' + str(reg1) + ', r' + str(reg2) + ', ' + str(reg3)
# Div
class Div(AluInstr):
# Div reg1, reg2, reg3
def __init__(self, reg1, reg2, reg3):
super().__init__()
self.rt = reg1
self.fu = 'Div'
# 去掉重复的元素
self.rs.append(reg2)
if reg2 != reg3:
self.rs.append(reg3)
self.instrStr = 'div r' + str(reg1) + ', r' + str(reg2) + ', ' + str(reg3)
# Move
class Move(AluInstr):
# move reg1, reg2
def __init__(self, reg1, reg2):
super().__init__()
self.rt = reg1
self.rs.append(reg2)
self.fu = 'Integer'
self.instrStr = 'move r' + str(reg1) + ', r' + str(reg2)
# Addi
class Addi(AluInstr):
# addi reg1, reg2, imm
def __init__(self, reg1, reg2, imm):
super().__init__()
self.rt = reg1
self.rs.append(reg2)
self.imm = imm
self.fu = 'Add'
self.instrStr = 'addi r' + str(reg1) + ', r' + str(reg2) + ', ' + str(imm)
# 条件跳转指令类
class Condition(Instruction):
pass
# Bne
class Bne(Condition):
# bne reg1, reg2, label
def __init__(self, reg1, reg2):
# Bne对象的属性中不需要包含label它应该在将中间表示转化为代码时被加上
super().__init__()
# 去掉重复的元素
self.rs.append(reg1)
if reg1 != reg2:
self.rs.append(reg2)
self.instrStr = 'bne r' + str(reg1) + ', r' + str(reg2)
def emit(self, stream, cnt):
instrStr = self.instrStr + ', out' + str(cnt)
stream.write(instrStr + '\n')
return cnt
# Beq
class Beq(Condition):
# beq reg1, reg2, label
def __init__(self, reg1, reg2):
super().__init__()
# 去掉重复的元素
self.rs.append(reg1)
if reg1 != reg2:
self.rs.append(reg2)
self.instrStr = 'beq r' + str(reg1) + ', r' + str(reg2)
def emit(self, stream, cnt):
instrStr = self.instrStr + ', loop' + str(cnt)
stream.write(instrStr + '\n')
return cnt

@ -0,0 +1,65 @@
# 数据相关性分析
def analyze_hazard(ins_list):
hazard = {'RAW': [],
'WAR': [],
'WAW': []}
write = [] # 记录所有的写操作
read = [] # 记录所有的读操作
# 分析数据相关性
for instr in ins_list: # 标记所有读取和写入的寄存器
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((i, 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((i, j))
# 检测读后读(WAW)
for i in range(len(write)):
for j in range(i + 1, len(write)):
if write[i] == write[j]:
hazard['WAW'].append((i, j))
return hazard
# 为指令分配功能部件如果没有空余返回None
def FU_allocate(fu, FUS):
if fu == 'Mul':
if not (FUS['Mul1'].busy == 'Yes' and FUS['Mul2'].busy == 'Yes'):
if FUS['Mul1'].busy == 'No':
return 'Mul1'
else:
return 'Mul2'
elif fu == 'Add':
if FUS['Add'].busy == 'No':
return 'Add'
elif fu == 'Div':
if FUS['Divide'].busy == 'No':
return 'Divide'
else:
if FUS['Integer'].busy == 'No':
return 'Integer'
return None
def Result_write(rs, RSS):
if RSS[rs] == 'None':
return True
return False
def RS_ready(rs, RSS):
try:
if RSS[rs] == 'None':
return True
else:
return False
except:
return True

@ -0,0 +1,130 @@
INT_REG_SIZE = 32 #整数寄存器数
FP_REG_SIZE = 32 #浮点寄存器数
PC_REG_SIZE = 1
BUF_REG_SIZE = 6
REG_SIZE = INT_REG_SIZE + FP_REG_SIZE + PC_REG_SIZE + BUF_REG_SIZE
REG_OFF = 0
INT_REG_OFF = REG_OFF
FP_REG_OFF = INT_REG_OFF + INT_REG_SIZE
PC_REG_OFF = FP_REG_OFF + FP_REG_SIZE
BUF_REG_OFF = PC_REG_OFF + PC_REG_SIZE
INSTR_MEM_SIZE = 32
DATA_MEM_SIZE = 32
MEM_SIZE = INSTR_MEM_SIZE + DATA_MEM_SIZE
MEM_OFF = 0
INSTR_MEM_OFF = MEM_OFF
DATA_MEM_OFF = INSTR_MEM_OFF + INSTR_MEM_SIZE
FU_SIZE = 4 #功能部件数
FU_OFF = 0
INT_FU_OFF = FU_OFF
ADD_FU_OFF = INT_FU_OFF + 1
MUL_FU_OFF = ADD_FU_OFF + 1
MEM_FU_OFF = MUL_FU_OFF + 1
INT_RS_SIZE = 1
ADD_RS_SIZE = 3 #浮点加法部件保留站数量
MUL_RS_SIZE = 2 #浮点乘法部件保留站数量
MEM_RS_SIZE = BUF_REG_SIZE
RS_SIZE = INT_RS_SIZE + ADD_RS_SIZE + MUL_RS_SIZE + MEM_RS_SIZE
RS_OFF = 1
INT_RS_OFF = RS_OFF
ADD_RS_OFF = INT_RS_OFF + INT_RS_SIZE
MUL_RS_OFF = ADD_RS_OFF + ADD_RS_SIZE
MEM_RS_OFF = MUL_RS_OFF + MUL_RS_SIZE
#寄存器
class Register:
def __init__(self):
self.val = 0
self.src = 0
return
def copy(self):
reg = Register()
reg.val = self.val
reg.src = self.src
return reg
#功能部件
class FuncUnit:
def __init__(self):
self.clk = 0
self.op = ''
self.res = 0
return
def copy(self):
fu = FuncUnit()
fu.clk = self.clk
fu.op = self.op
fu.res = self.res
return fu
#保留站
class ReservStation:
def __init__(self):
self.busy = False
self.op = ''
self.val1 = 0
self.src1 = 0
self.val2 = 0
self.src2 = 0
self.addr = 0
return
def copy(self):
rs = ReservStation()
rs.busy = self.busy
rs.op = self.op
rs.val1 = self.val1
rs.src1 = self.src1
rs.val2 = self.val2
rs.src2 = self.src2
rs.addr = self.addr
return rs
#指令
class Instruction:
def __init__(self):
self.op = ''
self.dest = 0
self.op1 = 0
self.op2 = 0
self.imm = 0
return
def copy(self):
instr = Instruction()
instr.op = self.op
instr.dest = self.dest
instr.op1 = self.op1
instr.op2 = self.op2
instr.imm = self.imm
return instr
#架构
class Architecture:
def __init__(self):
self.reg = [Register() for i in range(REG_OFF + REG_SIZE)]
self.mem = [0 for i in range(MEM_OFF + MEM_SIZE)]
self.fu = [FuncUnit() for i in range(FU_OFF + FU_SIZE)]
self.rs = [ReservStation() for i in range(RS_OFF + RS_SIZE)]
self.clk = 0 #时钟
self.bus = 0 #总线
return
def copy(self):
arch = Architecture()
for i in range(REG_SIZE):
arch.reg[i] = self.reg[i].copy()
for i in range(MEM_SIZE):
arch.mem[i] = self.mem[i]
for i in range(FU_SIZE):
arch.fu[i] = self.fu[i].copy()
for i in range(RS_SIZE):
arch.rs[i] = self.rs[i].copy()
arch.clk = self.clk
arch.bus = self.bus
return arch

@ -0,0 +1,176 @@
from architecture import *
def dump(arch):
dumpClk(arch)
print('')
dumpPC(arch)
print('')
dumpIntReg(arch)
print('')
dumpFpReg(arch)
print('')
dumpIntUnit(arch)
print('')
dumpAddUnit(arch)
print('')
dumpMulUnit(arch)
print('')
dumpMemUnit(arch)
print('')
dumpDataMem(arch)
return
def getInstr(op, dest, op1, op2, imm):
instr = Instruction()
instr.op = op
instr.dest = dest
instr.op1 = op1
instr.op2 = op2
instr.imm = imm
return instr
def program(arch, program):
arch1 = arch.copy()
print('{:<6}{:<6}{:<6}{:<6}{:<6}'.format(
'op',
'dest',
'op1',
'op2',
'imm'
))
for i in range(len(program)):
instr = program[i]
print('{:<6}{:<6}{:<6}{:<6}{:<6}'.format(
instr.op,
instr.dest,
instr.op1,
instr.op2,
instr.imm
))
arch1.mem[INSTR_MEM_OFF + i] = instr
return arch1
def valid(check, data):
if check:
return data
else:
return ''
def dumpClk(arch):
print('{:<6}{:<6}'.format('clk', 'bus'))
print('{:<6}{:<6}'.format(arch.clk, arch.bus))
return
def dumpPC(arch):
print('pc:\n{:<6}{:<6}'.format('value', arch.reg[PC_REG_OFF].val), end = '')
src = arch.reg[PC_REG_OFF].src
src = valid(src, src)
print('\n{:<6}{:<6}'.format('Qi', src), end = '')
print('')
return
def dumpReg(arch, offset, size):
print('{:<6}'.format(''), end = '')
for i in range(size):
print('{:<4}'.format(i), end = '')
print('\n{:<6}'.format('value'), end = '')
for i in range(size):
print('{:<4}'.format(arch.reg[offset + i].val), end = '')
print('\n{:<6}'.format('Qi'), end = '')
for i in range(size):
src = arch.reg[offset + i].src
src = valid(src, src)
print('{:<4}'.format(src), end = '')
print('')
return
def dumpIntReg(arch):
print('integer registers:')
dumpReg(arch, INT_REG_OFF, INT_REG_SIZE)
return
def dumpFpReg(arch):
print('floating point registers:')
dumpReg(arch, FP_REG_OFF, FP_REG_SIZE)
return
def dumpRS(arch, offset):
busy = arch.rs[offset].busy
op = valid(busy, arch.rs[offset].op)
val1 = valid(busy, arch.rs[offset].val1)
val2 = valid(busy, arch.rs[offset].val2)
src1 = valid(busy, arch.rs[offset].src1)
src2 = valid(busy, arch.rs[offset].src2)
addr = valid(busy, arch.rs[offset].addr)
src1 = valid(src1, src1)
src2 = valid(src2, src2)
addr = valid(addr, addr)
print('{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}'.format(
busy,
op,
val1,
val2,
src1,
src2,
addr))
return
def dumpFU(arch, fuOff, rsOff, rsSize):
print('{:<6}{:<6}{:<6}'.format('clk', 'op', 'res'))
print('{:<6}{:<6}{:<6}'.format(
arch.fu[fuOff].clk,
arch.fu[fuOff].op,
arch.fu[fuOff].res))
print('{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}'.format(
'busy',
'op',
'Vj',
'Vk',
'Qj',
'Qk',
'A'))
for i in range(rsSize):
dumpRS(arch, rsOff + i)
return
def dumpIntUnit(arch):
print('integer unit:')
dumpFU(arch, INT_FU_OFF, INT_RS_OFF, INT_RS_SIZE)
return
def dumpAddUnit(arch):
print('add unit:')
dumpFU(arch, ADD_FU_OFF, ADD_RS_OFF, ADD_RS_SIZE)
return
def dumpMulUnit(arch):
print('multiply unit:')
dumpFU(arch, MUL_FU_OFF, MUL_RS_OFF, MUL_RS_SIZE)
return
def dumpMemUnit(arch):
print('memory access unit:')
dumpFU(arch, MEM_FU_OFF, MEM_RS_OFF, MEM_RS_SIZE)
print('memory access buffer:')
print('{:<6}'.format('A'), end = '')
for i in range(BUF_REG_SIZE):
src = arch.reg[BUF_REG_OFF + i].src
addr = valid(src, arch.reg[BUF_REG_OFF + i].val)
print('{:<6}'.format(addr), end = '')
print('\n{:<6}'.format('Qi'), end = '')
for i in range(BUF_REG_SIZE):
src = arch.reg[BUF_REG_OFF + i].src
src = valid(src, src)
print('{:<6}'.format(src), end = '')
print('')
return
def dumpDataMem(arch):
print('data memory:')
for i in range(DATA_MEM_SIZE):
print('{:<4}'.format(i), end = '')
print('')
for i in range(DATA_MEM_SIZE):
print('{:<4}'.format(arch.mem[DATA_MEM_OFF + i]), end = '')
print('')
return

@ -0,0 +1,149 @@
from architecture import *
#执行一个周期
def run(arch):
arch1 = Architecture()
for i in range(INSTR_MEM_SIZE):
arch1.mem[INSTR_MEM_OFF + i] = arch.mem[INSTR_MEM_OFF + i]
arch1.clk = arch.clk + 1
arch1.reg[PC_REG_OFF] = runPC(arch)
'''
for i in range(INT_REG_SIZE):
arch1.reg[INT_REG_OFF + i] = runIntReg(arch, i)
for i in range(FP_REG_SIZE):
arch1.reg[FP_REG_OFF + i] = runFpReg(arch, i)
for i in range(DATA_MEM_SIZE):
arch1.mem[DATA_MEM_OFF + i] = runMem(arch, i)
arch1.fu[INT_FU_OFF] = runIntFU(arch)
arch1.fu[ADD_FU_OFF] = runAddFU(arch)
arch1.fu[MUL_FU_OFF] = runMulFU(arch)
arch1.fu[MEM_FU_OFF] = runMemFU(arch)
arch1.rs[INT_RS_OFF] = runIntRS(arch)
for i in range(ADD_RS_SIZE):
arch1.rs[ADD_RS_OFF + i] = runAddRS(arch, i)
for i in range(MUL_RS_SIZE):
arch1.rs[MUL_RS_OFF + i] = runMulRS(arch, i)
for i in range(MEM_RS_SIZE):
arch1.rs[MEM_RS_OFF + i] = runMemRS(arch, i)
for i in range(BUF_REG_SIZE):
arch1.reg[BUF_REG_OFF + i] = runBufReg(arch, i)
arch1.bus = runBus(arch)
'''
return arch1
def runPC(arch):
pc = Register()
if issue(arch):
pc.val = arch.reg[PC_REG_OFF].val + 1
instr = fetch(arch)
if instr.op == 'jump':
pc.src = INT_RS_OFF
else:
pc.src = arch.reg[PC_REG_OFF].src
elif arch.reg[PC_REG_OFF].src and not arch.fu[INT_FU_OFF].clk:
pc.val = arch.fu[INT_FU_OFF].res
pc.src = 0
else:
pc.val = arch.reg[PC_REG_OFF].val
pc.src = arch.reg[PC_REG_OFF].src
return pc
def runIntReg(arch, i):
reg = Register()
fuOff = writeReg(arch, INT_REG_OFF + i)
if fuOff:
reg.val = arch.fu[fuOff].res
else:
reg.val = arch.reg[INT_REG_OFF + i].val
rsOff = issue(arch)
if rsOff:
instr = fetch(arch)
if instr.op == 'addi':
#TODO
def runFpReg(arch, i):
pass
def runMem(arch, i):
pass
def runIntFU(arch):
pass
def runAddFU(arch):
pass
def runMulFU(arch):
pass
def runMemFU(arch):
pass
def runIntRS(arch):
pass
def runAddRS(arch, i):
pass
def runMulRS(arch, i):
pass
def runMemRS(arch, i):
pass
def runBufReg(arch, i):
pass
def runBus(arch, i):
pass
def issue(arch):
if not arch.reg[PC_REG_OFF].src:
instr = fetch(arch)
if instr:
rsMap = {
'addi': (INT_RS_OFF, INT_RS_SIZE),
'jump': (INT_RS_OFF, INT_RS_SIZE),
'fadd': (ADD_RS_OFF, ADD_RS_SIZE),
'fmul': (MUL_RS_OFF, MUL_RS_SIZE),
'load': (MEM_RS_OFF, MEM_RS_SIZE),
'store': (MEM_RS_OFF, MEM_RS_SIZE)
}
offset, size = rsMap[instr.op]
return first(arch, offset, size):
return 0
def fetch(arch):
return arch.mem[INSTR_MEM_OFF + arch.reg[PC_REG_OFF].val]
def first(arch, offset, size):
for i in range(size):
if not arch.rs[offset + i].busy:
return offset + i
return 0
def writeReg(arch, i):
src = arch.reg[i].src
if src == INT_RS_OFF:
return INT_FU_OFF
elif src >= ADD_RS_OFF and src < ADD_RS_OFF + ADD_RS_SIZE:
return ADD_FU_OFF
elif src >= MUL_RS_OFF and src < MUL_RS_OFF + MUL_RS_SIZE:
return MUL_FU_OFF
elif src >= MEM_RS_OFF and src < MEM_RS_OFF + MEM_RS_SIZE:
return MEM_FU_OFF
else:
return 0

@ -0,0 +1,19 @@
from architecture import *
from debug import *
from run import run
arch = Architecture()
prog = [
getInstr('load', 0, 1, 0, 0),
getInstr('fmul', 4, 0, 2, 0),
getInstr('store', 0, 4, 1, 0),
getInstr('addi', 1, 1, 0, -8),
getInstr('jump', 0, 0, 0, -4)
]
arch = program(arch, prog)
print('')
for i in range(6):
arch = run(arch)
dumpClk(arch)
print('')
dumpPC(arch)
Loading…
Cancel
Save