『動かしてわかるCPUの作り方10講』第9講までのCPUでLチカをする

クロックは10 kHzにしてある。すべての命令が実行に4クロックを要する。

 
 
ROMの初期化データである.mifファイルを生成するためのアセンブラのようなもの:

def generate_mif(file_name, width, depth, rom):
    f = open(file_name, "w")
    f.write("WIDTH=%d;\n" % width)
    f.write("DEPTH=%d;\n" % depth)
    f.write("ADDRESS_RADIX=UNS;\n")
    f.write("DATA_RADIX=BIN;\n")
    f.write("CONTENT BEGIN\n")
    format_of_code = "0" + str(width) + "b"
    for i in range(depth):
        machine_code = format(rom[i], format_of_code)
        f.write("%10d   :   %s;\n" % (i, machine_code))
    f.write("END;\n")
    f.close()
   
def mov(ra, rb):   return  0 << 11 | ra << 8 | rb << 5
def add(ra, rb):   return  1 << 11 | ra << 8 | rb << 5
def sub(ra, rb):   return  2 << 11 | ra << 8 | rb << 5
def _and(ra, rb):  return  3 << 11 | ra << 8 | rb << 5
def _or(ra, rb):   return  4 << 11 | ra << 8 | rb << 5
def sl(ra):        return  5 << 11 | ra << 8                 # 左シフト
def sr(ra):        return  6 << 11 | ra << 8                 # 右シフト
def sra(ra):       return  7 << 11 | ra << 8                 # 算術右シフト
def ldl(ra, ival): return  8 << 11 | ra << 8 | (ival & 0xFF) # 下位バイトに即値をロード
def ldh(ra, ival): return  9 << 11 | ra << 8 | (ival & 0xFF) # 上位バイトに即値をロード
def cmp(ra, rb):   return 10 << 11 | ra << 8 | rb << 5       # 一致したらフラグが立つ。
def je(addr):      return 11 << 11 | (addr & 0xFF)           # 一致フラグが立っていたらジャンプ
def jmp(addr):     return 12 << 11 | (addr & 0xFF)           # 無条件ジャンプ
def ld(ra, addr):  return 13 << 11 | ra << 8 | (addr & 0xFF) # RAMからレジスタへ値を持ってくる。
def st(ra, addr):  return 14 << 11 | ra << 8 | (addr & 0xFF) # レジスタの値をRAMへ格納する。
def hlt():         return 15 << 11

def _in(ra): return ld(ra, 65) # INポートからレジスタへ読み込む。
def out(ra): return st(ra, 64) # レジスタからOUTポートへ書き出す。

def nop(): return 0

r0, r1, r2, r3, r4, r5, r6, r7 = range(8) # 汎用レジスタ



FILE_NAME = "rom_init.mif"
WIDTH = 15
DEPTH = 256
_ = [0] * DEPTH


LED   = r0
INC   = r1
LOOPS = r2
COUNT = r3

_[0] = ldl(INC, 1) # 増分をセット

_[1] = ldh(LOOPS, 400 >> 8) # ループ回数をセット
_[2] = ldl(LOOPS, 400 & 0xFF)

_[3] = ldh(COUNT, 0) # カウンターを0にリセット
_[4] = ldl(COUNT, 0)

_[5] = ldl(LED, 0xFF) # ledを点灯
_[6] = out(LED)

_[7] = add(COUNT, INC)   # カウンターをインクリメントし、
_[8] = cmp(COUNT, LOOPS) # 指定したループ回数に達していたら、
_[9] = je(11)            # ビジーループを抜けるが、
_[10] = jmp(7)           # 達していなかったらビジーループを繰り返す。

_[11] = ldh(COUNT, 0) # カウンターを0にリセット
_[12] = ldl(COUNT, 0)

_[13] = ldl(LED, 0) # ledを消灯
_[14] = out(LED)

_[15] = add(COUNT, INC)   # カウンターをインクリメントし、
_[16] = cmp(COUNT, LOOPS) # 指定したループ回数に達していたら、
_[17] = je(3)             # ビジーループを抜けるが、
_[18] = jmp(15)           # 達していなかったらビジーループを繰り返す。

generate_mif(FILE_NAME, WIDTH, DEPTH, _)