---- 整理自B站UP主 踌躇月光 的视频
文章目录
- 1. 指令系统设计
- 2. MOV 指令
- 3. 实现
- 3.1 CPU 电路图
- 3.2 代码实现
- 3.3 实验过程
- 3.4 实验结果
- 3.5 实验工程
1. 指令系统设计
指令 IR 8 位 | 程序状态字 4 位 | 微程序周期 4 位 |
---|
2. MOV 指令
MOV A, 5; 立即寻址
MOV A, B; 寄存器寻址
MOV A, [5]; 直接寻址
MOV A, [B]; 寄存器间接寻址
MOV A, B
ADD A, 5
NOT A
HLT
- 二地址指令,MOV A,B
- 1xxx[aa][bb]
- 一地址指令,NOT A
- 01xxxx[aa]
- 零地址指令,HLT
- 00xxxxxx
立即寻址 = 0
寄存器寻址 = 1
直接寻址 = 2
寄存器间接寻址 = 3
3. 实现
3.1 CPU 电路图
3.2 代码实现
MSR = 1
MAR = 2
MDR = 3
RAM = 4
IR = 5
DST = 6
SRC = 7
A = 8
B = 9
C = 10
D = 11
DI = 12
SI = 13
SP = 14
BP = 15
CS = 16
DS = 17
SS = 18
ES = 19
VEC = 20
T1 = 21
T2 = 22
MSR_OUT = MSR
MAR_OUT = MAR
MDR_OUT = MDR
RAM_OUT = RAM
IR_OUT = IR
DST_OUT = DST
SRC_OUT = SRC
A_OUT = A
B_OUT = B
C_OUT = C
D_OUT = D
DI_OUT = DI
SI_OUT = SI
SP_OUT = SP
BP_OUT = BP
CS_OUT = CS
DS_OUT = DS
SS_OUT = SS
ES_OUT = ES
VEC_OUT = VEC
T1_OUT = T1
T2_OUT = T2
_DST_SHIFT = 5
MSR_IN = MSR << _DST_SHIFT
MAR_IN = MAR << _DST_SHIFT
MDR_IN = MDR << _DST_SHIFT
RAM_IN = RAM << _DST_SHIFT
IR_IN = IR << _DST_SHIFT
DST_IN = DST << _DST_SHIFT
SRC_IN = SRC << _DST_SHIFT
A_IN = A << _DST_SHIFT
B_IN = B << _DST_SHIFT
C_IN = C << _DST_SHIFT
D_IN = D << _DST_SHIFT
DI_IN = DI << _DST_SHIFT
SI_IN = SI << _DST_SHIFT
SP_IN = SP << _DST_SHIFT
BP_IN = BP << _DST_SHIFT
CS_IN = CS << _DST_SHIFT
DS_IN = DS << _DST_SHIFT
SS_IN = SS << _DST_SHIFT
ES_IN = ES << _DST_SHIFT
VEC_IN = VEC << _DST_SHIFT
T1_IN = T1 << _DST_SHIFT
T2_IN = T2 << _DST_SHIFT
SRC_R = 2 ** 10
SRC_W = 2 ** 11
DST_R = 2 ** 12
DST_W = 2 ** 13
PC_WE = 2 ** 14
PC_CS = 2 ** 15
PC_EN = 2 ** 16
PC_OUT = PC_CS
PC_IN = PC_CS | PC_WE
PC_INC = PC_CS | PC_WE | PC_EN
CYC = 2 ** 30
HLT = 2 ** 31
# - 二地址指令IR对应
# - 1xxx [aa][bb]
# - 一地址指令IR对应
# - 01xx xx[aa]
# - 零地址指令IR对应
# - 00xx xxxx
ADDR2 = 1 << 7
ADDR1 = 1 << 6
ADDR2_SHIFT = 4
ADDR1_SHIFT = 2
AM_INS = 0 # 立即寻址 instant
AM_REG = 1 # 寄存器寻址
AM_DIR = 2 # 直接寻址 direct
AM_RAM = 3 # 寄存器间接寻址
import pin
FETCH = [
pin.PC_OUT | pin.MAR_IN,
pin.RAM_OUT | pin.IR_IN | pin.PC_INC,
pin.PC_OUT | pin.MAR_IN,
pin.RAM_OUT | pin.DST_IN | pin.PC_INC,
pin.PC_OUT | pin.MAR_IN,
pin.RAM_OUT | pin.SRC_IN | pin.PC_INC,
]
MOV = 0 | pin.ADDR2 # MOV指令定义为 1000 xxxx
ADD = (1 << pin.ADDR2_SHIFT) | pin.ADDR2 # ADD指令定义为 1001 xxxx
NOP = 0
HLT = 0x3f
INSTRUCTIONS = {
2: { # 二地址指令
MOV: { # MOV指令寻址方式
(pin.AM_REG, pin.AM_INS): [ # (寄存器寻址,立即寻址) ==> MOV A,5
pin.DST_W | pin.SRC_OUT, # 微指令:DST(A)寄存器写,SRC(5)寄存器输出
]
}
},
1: {}, # 一地址指令
0: { # 零地址指令
NOP: [
pin.CYC, # 让指令周期清零,跳过这次指令
],
HLT: [
pin.HLT, # 指令停止
]
}
}
print(bin(MOV))
import os
import pin
import assembly as ASM
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'micro.bin')
micro = [pin.HLT for _ in range(0x10000)]
def compile_addr2(addr, ir, psw, index):
global micro
# addr ==> | IR | PSW | CYC |
# 二地址指令IR对应 ==> 1xxx [aa][bb]
op = ir & 0xf0
amd = (ir >> 2) & 3 # [aa] 寻址方式
ams = ir & 3 # [bb] 寻址方式
INST = ASM.INSTRUCTIONS[2]
if op not in INST:
micro[addr] = pin.CYC
return
am = (amd, ams)
if am not in INST[op]:
micro[addr] = pin.CYC
return
EXEC = INST[op][am] # 找到IR和寻址方式
if index < len(EXEC): # 补到FETCH后面
micro[addr] = EXEC[index]
else:
micro[addr] = pin.CYC
# 01xx xx[bb]
def compile_addr1(addr, ir, psw, index):
pass
# 00xx xxxx
def compile_addr0(addr, ir, psw, index):
global micro
op = ir
INST = ASM.INSTRUCTIONS[0]
if op not in INST:
micro[addr] = pin.CYC
return
EXEC = INST[op]
if index < len(EXEC):
micro[addr] = EXEC[index]
else:
micro[addr] = pin.CYC
for addr in range(0x10000): # 指令集处理
# | IR | PSW | CYC |
# 8 4 4
ir = addr >> 8
psw = (addr >> 4) & 0xf
cyc = addr & 0xf
# 先处理 取指指令FETCH
if cyc < len(ASM.FETCH):
micro[addr] = ASM.FETCH[cyc]
continue
addr2 = ir & (1 << 7) # 二地址
addr1 = ir & (1 << 6) # 一地址
index = cyc - len(ASM.FETCH) # FETCH占据了前面的位置,这里表示FETCH后面
if addr2:
compile_addr2(addr, ir, psw, index) # 处理二地址
elif addr1:
compile_addr1(addr, ir, psw, index) # 处理一地址
else:
compile_addr0(addr, ir, psw, index) # 处理零地址
with open(filename, 'wb') as file:
for var in micro:
value = var.to_bytes(4, byteorder='little')
file.write(value)
print('Compile micro instruction finish!!!')
3.3 实验过程
- 我们将编译完的 micro.bin 写入到 ROM 中
- 手动在 RAM 中写入 MOV A, 5 的机器码
- 二地址指令 MOV 对应 ==> 1xxx [aa][bb]
- 根据找到的
EXEC = INST[op][am] # 找到IR和寻址方式
,拼出 MOV 指令对应 1000 0100,即 84。[aa] = 01 是AM_REG = 1 # 寄存器寻址
,[bb] = 00 是AM_INS = 0 # 立即寻址 instant
。
即 84 - A 寄存器是 08
- 5 是 05
pin.DST_W | pin.SRC_OUT
,结合CPU 电路图,CPU 控制单元拿到 DST 寄存器的输出 08,通过 l2 传到 CPU 控制单元内部;拿到 SRC 寄存器的输出 05,通过 l3 传到 CPU 控制单元内部。最终控制 A 寄存器写入 5。
3.4 实验结果
3.5 实验工程
【25 - MOV 指令】