~ALU・バス・I/O・命令セットを一から構築~
このプロジェクトでは、Pythonを使ってシンプルな8ビットCPUのエミュレータを実装します。ALU、バス、I/Oデバイス、命令セットなど、CPUを構成する各要素を自作し、最終的には簡単なプログラムを実行させます。
構成概要
このエミュレータは以下の構成要素で構成されています:
- ALU(算術論理演算器):加算、減算、論理演算などを処理
- バス(Bus):レジスタやI/Oとのデータのやりとり
- レジスタ(Register):汎用レジスタAとB
- I/Oデバイス(IODevice):出力処理
- CPU(中央処理装置):命令の実行・管理
Pythonコード
# 8-bit CPU Emulator with ALU, Bus, I/O, and Instruction Set
# 8ビットCPUエミュレータ(ALU、バス、I/O、命令セットを含む)
class ALU:
def __init__(self):
self.result = 0 # 演算結果 / Result of ALU operation
self.zero_flag = False # ゼロフラグ / Zero flag
def operate(self, op, a, b):
# 各種演算を実行 / Perform operations based on opcode
if op == "ADD":
self.result = (a + b) & 0xFF # 8ビット加算 / 8-bit addition
elif op == "SUB":
self.result = (a - b) & 0xFF # 8ビット減算 / 8-bit subtraction
elif op == "AND":
self.result = a & b # 論理積 / Bitwise AND
elif op == "OR":
self.result = a | b # 論理和 / Bitwise OR
elif op == "MUL":
self.result = (a * b) & 0xFF # 8ビット乗算 / 8-bit multiplication
elif op == "CMP":
self.result = 0
self.zero_flag = (a == b) # 比較結果(等しいならZF=1)/ Set zero flag if equal
return None
self.zero_flag = (self.result == 0) # 結果が0ならZF=1 / Update zero flag
return self.result
def get_zero_flag(self):
return self.zero_flag # ZFを返す / Return zero flag
class Bus:
def __init__(self):
self.data = 0 # バス上のデータ / Data on the bus
def write(self, value):
self.data = value & 0xFF # 8ビットに制限 / Limit to 8-bit
def read(self):
return self.data # データ読み出し / Read data
class IODevice:
def __init__(self):
self.output = [] # 出力データの履歴 / History of outputs
def write(self, value):
self.output.append(value)
print(f"[I/O] Output Device Received: {value}") # 出力表示 / Show output
class Register:
def __init__(self):
self.value = 0 # レジスタの値 / Value of the register
def load(self, val):
self.value = val & 0xFF # 8ビット制限 / Limit to 8-bit
def read(self):
return self.value # 値の読み出し / Read value
class CPU:
def __init__(self):
# レジスタ、PC、メモリなどの初期化 / Initialize registers, PC, memory, etc.
self.regA = Register()
self.regB = Register()
self.PC = 0
self.memory = [0] * 256 # 256バイトメモリ / 256-byte memory
self.alu = ALU()
self.bus = Bus()
self.io = IODevice()
self.halt = False
def load_program(self, program):
self.memory[:len(program)] = program # プログラムのロード / Load program into memory
def fetch(self):
instr = self.memory[self.PC] # 命令の取得 / Fetch instruction
self.PC += 1
return instr
def execute(self, instr):
# 命令のデコードと実行 / Decode and execute instruction
if instr == 0x01: # LOAD A, imm
val = self.fetch()
self.regA.load(val)
elif instr == 0x02: # LOAD B, imm
val = self.fetch()
self.regB.load(val)
elif instr == 0x03: # ADD A, B
result = self.alu.operate("ADD", self.regA.read(), self.regB.read())
self.regA.load(result)
elif instr == 0x04: # MUL A, B
result = self.alu.operate("MUL", self.regA.read(), self.regB.read())
self.regA.load(result)
elif instr == 0x05: # CMP A, B
self.alu.operate("CMP", self.regA.read(), self.regB.read())
elif instr == 0x06: # OUT A
self.io.write(self.regA.read())
elif instr == 0x07: # MOV A to Bus
self.bus.write(self.regA.read())
elif instr == 0x08: # MOV Bus to B
self.regB.load(self.bus.read())
elif instr == 0x09: # SUB A, B
result = self.alu.operate("SUB", self.regA.read(), self.regB.read())
self.regA.load(result)
elif instr == 0x0A: # AND A, B
result = self.alu.operate("AND", self.regA.read(), self.regB.read())
self.regA.load(result)
elif instr == 0x0B: # OR A, B
result = self.alu.operate("OR", self.regA.read(), self.regB.read())
self.regA.load(result)
elif instr == 0xFF: # HALT
self.halt = True # プログラム終了 / Stop the program
# 現在の状態を表示 / Display current CPU state
print(f"PC: {self.PC-1}, A: {self.regA.read()}, B: {self.regB.read()}, Bus: {self.bus.read()}, ZF: {self.alu.get_zero_flag()}")
def run(self):
# 命令を連続的に実行 / Run until HALT instruction
while not self.halt:
instr = self.fetch()
self.execute(instr)
# サンプルプログラム:A=7, B=3, A=A*B → Aをバス経由でBにコピー → Aを出力 → 比較 → AND → OR → 停止
# Sample Program: A=7, B=3, A=A*B → Copy A to B via Bus → Output A → Compare → AND → OR → HALT
program = [
0x01, 0x07, # LOAD A, 7
0x02, 0x03, # LOAD B, 3
0x04, # MUL A, B
0x07, # MOV A to Bus
0x08, # MOV Bus to B
0x06, # OUT A
0x05, # CMP A, B
0x0A, # AND A, B
0x0B, # OR A, B
0xFF # HALT
]
# CPU実行 / Execute CPU
cpu = CPU()
cpu.load_program(program)
cpu.run()