You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
4.5 KiB
Python

from assembly import FETCH, INSTRUCTIONS
import pin
META_DATA = "v3.0 hex words addressed\n"
def chunk(l, n):
for i in range(0, len(l), n):
yield l[i:i + n]
def get_hex_str(codes, width):
width = int(width)
data = []
for _code in codes:
hex_str = hex(_code)[2:]
zero_str = ""
for _ in range(width - len(hex_str)):
zero_str += "0"
data.append(zero_str + hex_str)
return data
def save_hex_str(hex_str_lis, chunk_count: int, outfile_name: str):
# 写入数据到 bin文件
lines = [META_DATA, ]
idx = 0
for slice in chunk(hex_str_lis, chunk_count):
hex_idx_str = hex(idx)[2:]
zero_str = ""
for _ in range(4 - len(hex_idx_str)):
zero_str += "0"
hex_idx_str = zero_str + hex_idx_str
line = f"{hex_idx_str}:"
for _ in slice:
line += f" {_}"
line += "\n"
lines.append(line)
idx += chunk_count # 下一行的地址
with open(outfile_name, "w") as f:
f.writelines(lines)
def compile_addr2(addr, ir, psw, idx):
# addr: 0b10000100_0000_0110
# ir psw cyc
# ir: 1xxx[aa][bb]
# idx: 当前指令周期的下标
global base_bin_data
op = ir & 0b1111_0000 # 需要进行的操作
amd = (ir >> 2) & 0b0000_0011 # 目的操作数 也是就是 aa
ams = ir & 0b0000_0011 # 原地址操作数 bb
INST = INSTRUCTIONS[2]
# 如果还未实现该指令
if op not in INST:
base_bin_data[addr] = pin.CYC # 当前指令周期清零, 执行下个指令周期吧
return
# print(bin(addr), hex(addr), bin(op), bin(list(INST.keys())[0]), list(INST.keys()))
am = (amd, ams) # 寻址方式判断 [aa][bb]
if am not in INST[op]:
base_bin_data[addr] = pin.CYC # 当前指令周期清零, 执行下个指令周期吧
return
# print(bin(addr), hex(addr), bin(op), bin(amd), bin(ams))
EXEC = INST[op][am]
# 当前指令周期 长度塞不下了
if idx < len(EXEC):
# print(f"{hex(addr)} 写入指令: {bin(EXEC[idx])}")
base_bin_data[addr] = EXEC[idx]
else: # 这个指令周期放不下了
base_bin_data[addr] = pin.CYC # 当前指令周期清零, 执行下个指令周期吧
return
def compile_addr1(addr, ir, psw, idx):
# 01xxxx[aa]
global base_bin_data
op = ir & 0b1111_1100 # 需要进行的操作
amd = ir & 0b0000_0011 # 目的操作数 也是就是 aa
INST = INSTRUCTIONS[1]
if op not in INST:
base_bin_data[addr] = pin.CYC
return
if amd not in INST[op]:
base_bin_data[addr] = pin.CYC
return
EXEC = INST[op][amd]
# 当前指令周期 长度塞不下了
if idx < len(EXEC):
# print(f"{hex(addr)} 写入指令: {bin(EXEC[idx])}")
base_bin_data[addr] = EXEC[idx]
else: # 这个指令周期放不下了
base_bin_data[addr] = pin.CYC # 当前指令周期清零, 执行下个指令周期吧
return
def compile_addr0(addr, ir, psw, idx):
# 00xxxxxx
op = ir # 需要进行的操作
INST = INSTRUCTIONS[0]
# 如果还未实现该指令
if op not in INST:
base_bin_data[addr] = pin.CYC # 当前指令周期清零, 执行下个指令周期吧
return
EXEC = INST[op]
# 当前指令周期 长度塞不下了
if idx < len(EXEC):
base_bin_data[addr] = EXEC[idx]
else: # 这个指令周期放不下了
base_bin_data[addr] = pin.CYC # 当前指令周期清零, 执行下个指令周期吧
return
if __name__ == "__main__":
data_width = 32
addr_width = 16
# 我们现在只支持16个指令
base_bin_data = [pin.HLT for _ in range(1 << addr_width)]
for addr in range(1 << addr_width):
# addr: 0b10000100_0000_0110
ir = addr >> 8
psw = (addr >> 4) & 0b1111
cyc = addr & 0b1111 # 最大支持2的4次方个指令
# 取指令周期
if cyc < len(FETCH):
base_bin_data[addr] = FETCH[cyc]
continue
idx = cyc - len(FETCH) # 从取指令周期之后开始计数, 直接减去去指令周期的大小即可, 因为cyc是 addr来的
# 数据都就位, 处理IR寄存器的值
if ir & 0b1000_0000:
compile_addr2(addr, ir, psw, idx)
elif ir & 0b0100_0000:
compile_addr1(addr, ir, psw, idx)
else:
compile_addr0(addr, ir, psw, idx)
save_hex_str(get_hex_str(base_bin_data, data_width / 4), 8, "./ROM.bin")