|
|
|
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")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|