데이터패스의 구성 요소 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

# 데이터패스 부품 하나하나의 동작 확인 (실제 하드웨어가 아니라 파이썬 흉내다)
# 실행: python3 23_datapath-elements_verify.py
MASK = 0xFFFFFFFF


def sign_extend16(x):
    """16비트 -> 32비트. 맨 위 비트(15번)를 위쪽 16칸에 복사한다."""
    return x | 0xFFFF0000 if x & 0x8000 else x


def to_signed(x, bits=32):
    return x - (1 << bits) if x >> (bits - 1) else x


def shift_left2(x):
    return (x << 2) & MASK


def mux(sel, in0, in1):
    return in1 if sel else in0


class RegisterFile:
    """읽기 구멍 둘(조합), 쓰기 구멍 하나(클록 가장자리). 0번은 늘 0이다."""
    def __init__(self):
        self.r = [0] * 32

    def read(self, n1, n2):
        return self.r[n1], self.r[n2]

    def clock(self, regwrite, n, data):
        if regwrite and n != 0:
            self.r[n] = data & MASK


if __name__ == "__main__":
    # 부호 확장: 16비트 값 65,536가지 모두에서 2의 보수로 읽은 값이 그대로다
    for x in range(1 << 16):
        assert to_signed(sign_extend16(x)) == to_signed(x, 16)
    assert sign_extend16(0x0008) == 0x00000008
    assert sign_extend16(0xFFFC) == 0xFFFFFFFC and to_signed(0xFFFFFFFC) == -4
    assert sign_extend16(0x8004) == 0xFFFF8004 and to_signed(0xFFFF8004) == -32764
    # 0으로만 채우면 음수가 큰 양수로 바뀐다
    assert 0x0000FFFC == 65532
    # 왼쪽으로 두 칸 밀기 = 4를 곱하기 (명령어 수를 바이트 수로)
    for x in (0, 1, 3, 0xFFFFFFFD, 0x3FFFFFFF):
        assert shift_left2(x) == (x * 4) & MASK
    assert shift_left2(3) == 12 and to_signed(shift_left2(sign_extend16(0xFFFD))) == -12
    # PC + 4, 분기 목표 = (PC + 4) + (오프셋 << 2)
    pc = 0x00400020
    assert pc + 4 == 0x00400024
    assert (pc + 4 + shift_left2(sign_extend16(3))) & MASK == 0x00400030
    assert (pc + 4 + shift_left2(sign_extend16(0xFFFD))) & MASK == 0x00400018
    # 점프 목표 = PC + 4의 위 4비트 | 주소 칸 26비트 | 00
    addr26 = 0x0100010
    assert ((pc + 4) & 0xF0000000) | (addr26 << 2) == 0x00400040
    # 멀티플렉서
    assert mux(0, 11, 22) == 11 and mux(1, 11, 22) == 22
    # 레지스터 파일: 쓰기 신호가 0이면 그대로, 0번은 늘 0, 쓴 값은 다음 읽기부터 보인다
    rf = RegisterFile()
    rf.clock(1, 8, 123); rf.clock(0, 9, 456); rf.clock(1, 0, 789)
    assert rf.read(8, 9) == (123, 0) and rf.read(0, 0) == (0, 0)
    # 명령어 하나가 32비트 = 4바이트라서 PC는 4씩 는다. 레지스터 번호 5비트로 32개를 가리킨다
    assert 32 // 8 == 4 and 2 ** 5 == 32
    print("ALL CHECKS PASSED")