数据转移指令完成

main
阳光少年 5 months ago
parent 950c72b8fd
commit b3a2852228

4608
ROM.bin

File diff suppressed because it is too large Load Diff

@ -18,14 +18,77 @@ ADD = 1 << pin.ADDR_2_SHIFT | pin.ADDR_2
NOP = 0b0
HLT = 0b11_1111
INSTRUCTIONS = {
2: {
MOV: { # 0b10000000
# mov X, 5
(pin.AM_REG, pin.AM_INS): [
# mov X任意寄存器, 5, 如果是mov a, 5 这个指令对应的前3个内存地址就是 1000_01_00 00000008(dst中保存的a寄存器编号是8) 00000101(src保存的数值是5, 等下SRC_OUT会输出到总线上)
(pin.AM_REG, pin.AM_INS): [ # 1000_01_00 这是IR寄存器上保存的指令
# 目的任意寄存器的控制线的编号X, 保存在了DST寄存器中中, 输出到读写控制器控制使X寄存器打开写
pin.DST_W | pin.SRC_OUT, # 0b10000000000111
]
# 写入 SRC寄存器中保存的立即数
# 这是控制读写寄存器操作寄存器控制器的值
pin.DST_W | pin.SRC_OUT,
],
(pin.AM_REG, pin.AM_REG): [ # mov a, b
pin.DST_W | pin.SRC_R
# SRC_R 和 SRC_OUT的区别是:
# - SRC_R 是被读写控制器控制的表示, SRC_R内保存的值是一个寄存器编号, 此时把这个编号传到 寄存器控制器中然后把这个指定的寄存器数据传到总线上
# - SRC_OUT 是把直接SRC寄存器中的数据输出到总线
],
(pin.AM_REG, pin.AM_DIR): [ # mov a, [0x5]
pin.SRC_OUT | pin.MAR_IN, # 把0x5从src寄存器, 通过偏移地址寄存器传到 内存控制器中
pin.DST_W | pin.RAM_OUT # 把上面传到内存控制器中的地址, 输出到DST_W中的a寄存器中
],
(pin.AM_REG, pin.AM_RAM): [ # mov a, [b]
pin.SRC_R | pin.MAR_IN, # 把SRC_R中的b寄存器编号, 通过偏移地址寄存器MAR传到 内存控制器中
pin.DST_W | pin.RAM_OUT
],
(pin.AM_DIR, pin.AM_INS): [ # mov [0x2f], 5
pin.DST_OUT | pin.MAR_IN, # 把0x2f这个地址, 从dst寄存器, 通过偏移地址寄存器传到 内存控制器中
pin.SRC_OUT | pin.RAM_IN
],
(pin.AM_DIR, pin.AM_REG): [ # mov [0x0], a
pin.DST_OUT | pin.MAR_IN,
pin.SRC_R | pin.RAM_IN
],
(pin.AM_DIR, pin.AM_DIR): [ # mov [0x0], [0x2f]
pin.SRC_OUT | pin.MAR_IN,
pin.T1_IN | pin.RAM_OUT,
pin.DST_OUT | pin.MAR_IN,
pin.T1_OUT | pin.RAM_IN
],
(pin. AM_DIR, pin.AM_RAM): [ # mov [0x0], [a]
pin.SRC_R | pin.MAR_IN,
pin.T1_IN | pin.RAM_OUT,
pin.DST_OUT | pin.MAR_IN,
pin.T1_OUT | pin.RAM_IN
],
(pin.AM_RAM, pin.AM_INS): [ # mov [a], 0x5
pin.DST_R | pin.MAR_IN,
pin.SRC_OUT | pin.RAM_IN
],
(pin.AM_RAM, pin.AM_REG): [ # mov [a], c
pin.DST_R | pin.MAR_IN,
pin.SRC_R | pin.RAM_IN
],
(pin.AM_RAM, pin.AM_DIR): [ # mov [a], [0x5]
pin.SRC_OUT | pin.MAR_IN,
pin.T1_IN | pin.RAM_OUT,
pin.DST_R | pin.MAR_IN,
pin.T1_OUT | pin.RAM_IN
],
(pin.AM_RAM, pin.AM_RAM): [ # mov [a], [b]
pin.SRC_R | pin.MAR_IN,
pin.T1_IN | pin.RAM_OUT,
pin.DST_R | pin.MAR_IN,
pin.T1_OUT | pin.RAM_IN
],
}
},
1: {

@ -0,0 +1,144 @@
import os
import re
import pin
import assembly as ASM
from controller import get_hex_str, save_hex_str
# 允许操作的寄存器
ALLOW_REGISTER_MAP = {
"a": pin.A,
"b": pin.B,
"c": pin.C,
"d": pin.D,
}
OP2_STR_MAP = {
"mov": ASM.MOV,
}
OP1_STR_MAP = {
}
OP0_STR_MAP = {
"nop": ASM.NOP,
"hlt": ASM.HLT,
}
OP2_VALUE_SET = set(OP2_STR_MAP.values())
OP1_VALUE_SET = set(OP1_STR_MAP.values())
OP0_VALUE_SET = set(OP0_STR_MAP.values())
class Code:
def __init__(self, number, source):
self.number: int = number # 行号
self.source: str = source # 源代码
self._op_str = self._src = self._dst = None
self.prepare_source()
def __repr__(self):
return f"[{self.number}] - op: {self._op_str}, dst: {self._dst}, src: {self._src} - '{self.source}'"
def prepare_source(self):
tup = self.source.split(",")
if len(tup) > 2:
raise Exception("指令格式错误")
if len(tup) == 2:
self._src = tup[1].strip()
tup = re.split(r" +", tup[0])
if len(tup) > 2:
raise Exception("指令格式错误")
if len(tup) == 2:
self._dst = tup[1].strip()
self._op_str = tup[0]
@property
def op(self):
# 根据 mov, add 等指令得到对应的操作二进制码
if self._op_str in OP2_STR_MAP:
op = OP2_STR_MAP[self._op_str]
elif self._op_str in OP1_STR_MAP:
op = OP1_STR_MAP[self._op_str]
else:
op = OP0_STR_MAP[self._op_str]
return op
def get_am(self, addr: str):
# 得到目的操作数和源操作数, 返回(寻址方式, 地址)
if addr is None:
return None, None
if addr in ALLOW_REGISTER_MAP: # 如果是寄存器寻址, 且必须是允许的寄存器
return pin.AM_REG, ALLOW_REGISTER_MAP[addr]
if re.match(r"^[0-9]+$", addr): # 如果是立即数
return pin.AM_INS, int(addr)
if re.match(r"^0[Xx][0-9A-Za-z]+$", addr): # 如果是16进制立即数
return pin.AM_INS, int(addr, 16)
if re.match(r"^\[[0-9]+\]$", addr): # 如果是立即数
return pin.AM_DIR, int(addr[1:-1])
if re.match(r"^\[0[Xx][0-9A-Za-z]+\]$", addr): # 如果是16进制立即数
return pin.AM_DIR, int(addr[1:-1], 16)
if re.match(r"^\[.+\]$", addr): # 如果是 [a]
reg = addr[1:-1]
if reg in ALLOW_REGISTER_MAP:
return pin.AM_RAM, ALLOW_REGISTER_MAP[reg]
raise Exception(f"操作数 地址错误: {self}")
def compile_code(self):
amd, dst = self.get_am(self._dst) # 目的操作数
ams, src = self.get_am(self._src) # 源操作数
# print(amd, dst, ams, src)
if src and (amd, ams) not in ASM.INSTRUCTIONS[2][self.op]:
raise Exception(f"操作数 地址错误: {self}")
elif src is None and dst and amd not in ASM.INSTRUCTIONS[1][self.op]:
raise Exception(f"操作数 地址错误: {self}")
elif src is None and dst is None and self.op not in ASM.INSTRUCTIONS[0]:
raise Exception(f"操作数 地址错误: {self}")
if not src and not dst:
amd = dst = ams = src = 0
# 根据op, 构建 ir寄存器
if self.op in OP2_VALUE_SET:
ir = self.op | amd << 2 | ams
elif self.op in OP1_VALUE_SET:
ir = self.op | amd
else:
ir = self.op
return ir, dst, src
def compile_program(input_file: str):
codes = []
with open(input_file, "r") as f:
lines = f.readlines()
for idx, line in enumerate(lines):
source = line.strip().split(";")[0] # 去掉空格和注释
if len(source) == 0:
continue
code = Code(idx + 1, source)
codes.append(code)
return codes
if __name__ == '__main__':
data_width = 8
addr_width = 16
input_file = "./test_mov.asm"
output_file = "test_mov.bin"
program_bin_data = []
for code in compile_program(input_file):
values = code.compile_code()
for value in values:
program_bin_data.append(value)
print(get_hex_str(program_bin_data, data_width / 4))
save_hex_str(get_hex_str(program_bin_data, data_width / 4), 8, "program.bin")

@ -19,7 +19,7 @@ def get_hex_str(codes, width):
return data
def save_hex_str(hex_str_lis, chunk_count: int):
def save_hex_str(hex_str_lis, chunk_count: int, outfile_name: str):
# 写入数据到 bin文件
lines = [META_DATA, ]
idx = 0
@ -36,8 +36,8 @@ def save_hex_str(hex_str_lis, chunk_count: int):
line += "\n"
lines.append(line)
idx += addr_chunk # 下一行的地址
with open("./ROM.bin", "w") as f:
idx += chunk_count # 下一行的地址
with open(outfile_name, "w") as f:
f.writelines(lines)
@ -69,7 +69,7 @@ def compile_addr2(addr, ir, psw, idx):
EXEC = INST[op][am]
# 当前指令周期 长度塞不下了
if idx < len(EXEC):
print(f"{hex(addr)} 写入指令: {bin(EXEC[idx])}")
# print(f"{hex(addr)} 写入指令: {bin(EXEC[idx])}")
base_bin_data[addr] = EXEC[idx]
else: # 这个指令周期放不下了
base_bin_data[addr] = pin.CYC # 当前指令周期清零, 执行下个指令周期吧
@ -83,7 +83,7 @@ def compile_addr1(addr, ir, psw, idx):
def compile_addr0(addr, ir, psw, idx):
# 00xxxxxx
op = ir & 0b1111_0000 # 需要进行的操作
op = ir # 需要进行的操作
INST = INSTRUCTIONS[0]
# 如果还未实现该指令
@ -92,7 +92,6 @@ def compile_addr0(addr, ir, psw, idx):
return
EXEC = INST[op]
# 当前指令周期 长度塞不下了
if idx < len(EXEC):
base_bin_data[addr] = EXEC[idx]
@ -106,7 +105,6 @@ if __name__ == "__main__":
addr_width = 16
# 我们现在只支持16个指令
# fetch_hex_str_lis = get_hex_str(FETCH, data_width / 4)
base_bin_data = [pin.HLT for _ in range(1 << addr_width)]
for addr in range(1 << addr_width):
# addr: 0b10000100_0000_0110
@ -122,15 +120,14 @@ if __name__ == "__main__":
idx = cyc - len(FETCH) # 从取指令周期之后开始计数, 直接减去去指令周期的大小即可, 因为cyc是 addr来的
# 数据都就位, 处理IR寄存器的值
if ir & 0b1000_0000 == pin.ADDR_2:
if ir & 0b1000_0000:
compile_addr2(addr, ir, psw, idx)
elif ir & 0b0100_0000 == pin.ADDR_2:
elif ir & 0b0100_0000:
compile_addr1(addr, ir, psw, idx)
else:
compile_addr0(addr, ir, psw, idx)
addr_chunk = int(64 / (32 / 4)) # bin文件每行有多少个数据
save_hex_str(get_hex_str(base_bin_data, data_width / 4), addr_chunk)
save_hex_str(get_hex_str(base_bin_data, data_width / 4), 8, "./ROM.bin")

2412
cpu.circ

File diff suppressed because it is too large Load Diff

@ -72,7 +72,7 @@ T1_IN = T1 << _DST_SHIFT
T2_IN = T2 << _DST_SHIFT
SRC_R = 1 << 10 # 读取 SRC 寄存器中的值的内代表的 寄存器
SRC_R = 1 << 10 # 读取 SRC 寄存器中的值, 这个值是寄存器编号
SRC_W = 1 << 11
DST_R = 1 << 12
DST_W = 1 << 13
@ -87,7 +87,7 @@ PC_IN = PC_CS | PC_WE
PC_INC = PC_CS | PC_WE | PC_EN
CYC = 1 << 30 # 当前指令周期 清零, 执行下一个指令周期
HLT = 1 << 31
HLT = 1 << 31 # 停止
ADDR_2 = 1 << 7 # 2指令标志 1xxx[aa][bb]
ADDR_1 = 1 << 6 # 1指令标志 01xxxx[aa]
@ -95,9 +95,9 @@ ADDR_1 = 1 << 6 # 1指令标志 01xxxx[aa]
ADDR_2_SHIFT = 4 # 指令需要左移4位 留出来操作数位
ADDR_1_SHIFT = 2
AM_INS = 0 # 立即数寻址
AM_REG = 1 # 寄存器寻址
AM_DIR = 2 # 直接寻址
AM_RAM = 3 # 寄存器间接寻址
AM_INS = 0b00 # 立即数 0x5
AM_REG = 0b01 # 寄存器 a
AM_DIR = 0b10 # 立即数寻址 [0x5]
AM_RAM = 0b11 # 寄存器间接寻址 [a]

@ -0,0 +1,29 @@
; 测试的代码
;mov a, 0x0f ; 写入0x0f到A寄存器
;mov d, a
;mov a, [0x05]
;mov b, [a]
;nop
; mov [0x0], 0xff
;mov a, 0xff
;mov [0x0], a
mov [0x33], 0x99
mov a, [0x33]
mov [0x2f], a
mov a, 0x2f
mov [0x0], [a]
mov a, 0x00
mov [a], 0x05 ; 0x00: 0x5
mov a, 0x01
mov [a], [0x00] ; 0x01: 0x5
mov b, 0x02
mov d, 0x00
mov [b], [d] ; 0x03: 0x5
hlt
Loading…
Cancel
Save