计算机体系结构(二):使用 Python 模拟主存和寄存器文件系统

在计算机体系结构中,主存(内存)和寄存器是两种非常重要的存储设备。主存用于存储程序和数据,而寄存器则用于快速存取数据。为了更好地理解它们的工作原理,使用 Python 模拟一个简单的主存和寄存器文件系统。

一、实现思路

1. 主存模拟

主存是一个按字节编址的存储设备,每个字节可以存储 8 位二进制数据。使用 Python 的列表来模拟主存,列表的每个元素表示一个二进制位(0 1)。通过这种方式,模拟内存的读写操作。

2. 寄存器文件模拟

寄存器文件是 CPU 内部的高速存储设备,通常由多个寄存器组成。每个寄存器可以存储固定长度的二进制数据。使用 Python 的列表来模拟寄存器文件,列表的每个元素表示一个32 位的二进制字符串。

3. 功能实现

  • 主存:支持按字节读写内存,确保地址对齐和数据长度正确
  • 寄存器文件:支持按寄存器索引读写数据,确保数据长度为 32 位

二、技术细节

1. 主存模拟

主存的核心是一个字符数组mem,每个元素存储 01。我们实现了以下功能:

  • load 函数:根据指定的地址和字节数读取内存,返回二进制字符串
  • store 函数:将二进制字符串写入内存,确保地址对齐和数据长度正确
  • print_memory_range 函数:打印指定内存地址范围内的值
# 申请一个字符数组模拟内存,每个元素只存储 0 或 1
mem_size = 1 * 1024 * 1024 * 1024  # 1 GB
mem = ['0'] * mem_size  # 初始化内存,全部为 '0'

def load(address, byte_count):
    """根据指定的字节数(byte_count)读取内存并返回二进制字符串"""
    start = int(address, 2)  # 将地址从二进制字符串转换为整数
    end = start + byte_count * 8  # 计算结束位置(按比特)
    return ''.join(mem[start:end])  # 返回指定字节数的二进制字符串

def store(address, binary_value, byte_count):
    """
    将地址和二进制字符串写入内存
    :param address: 二进制字符串,表示写入的起始地址
    :param binary_value: 二进制字符串,表示要写入的数据
    :param byte_count: 写入的字节数
    """
    start = int(address, 2)  # 将地址从二进制字符串转换为整数

    # 检查地址是否对齐
    if start % 8 != 0:
        raise ValueError(f"地址 {address} 不是 8 的倍数,无法按字节编址写入。")

    # 检查二进制字符串的长度是否匹配字节数
    if len(binary_value) != byte_count * 8:
        raise ValueError(f"二进制字符串的长度必须是 {byte_count * 8} 位,当前长度为 {len(binary_value)} 位。")

    # 将二进制字符串逐位写入内存
    for i in range(len(binary_value)):
        mem[start + i] = binary_value[i]

def print_memory_range(start, byte_count):
    """打印指定内存地址范围内的值"""
    start = int(start, 2)  # 将起始地址转换为整数
    end = start + byte_count * 8  # 计算结束位置(按比特)
    print(f"Memory values (from Address {start} to {end - 1}):")
    for i in range(start, end, 32):  # 每次打印 32 位
        binary_value = load(format(i, '032b'), 4)  # 读取 32 位(4 字节)
        print(f"Address {format(i, '032b')}: {binary_value}")

测试程序

try:
    # 写入数据(地址和32位二进制字符串,4字节)
    store('00000000000000000000000000000000', '10010000000000000000000000000000', 4)
    store('00000000000000000000000000100000', '10010000001000000000000001100100', 4)
    store('00000000000000000000000001000000', '10010000010000000000000000000000', 4)

    # 打印内存范围
    print_memory_range('00000000000000000000000000000000', 4)  # 打印前 4 字节
except ValueError as e:
    print(e)

2. 寄存器文件模拟

寄存器文件的核心是一个列表regs,每个元素是一个 32 位的二进制字符串。我们实现了以下功能:

  • read 函数:读取指定寄存器的值,返回 32 位二进制字符串
  • write 函数:将 32 位二进制字符串写入指定寄存器
  • print_registers 函数:打印所有寄存器的值
# 模拟32个通用寄存器,每个寄存器为32位二进制字符串
reg_size = 32  # 寄存器数量
regs = ['0' * 32 for _ in range(reg_size)]  # 初始化32个寄存器,每个寄存器为32位二进制字符串


# 全局变量:指令寄存器IR、程序计数器PC、标志寄存器CF
ir = '0' * 32  # 指令寄存器
pc = '0' * 32  # 程序计数器
cf = '0' * 32  # 标志寄存器

def read(index_bin):
    """读取指定索引的寄存器,返回32位二进制字符串"""
    index = int(index_bin, 2)  # 将32位二进制字符串转换为整数
    if index < 0 or index >= reg_size:
        raise IndexError(f"寄存器索引 {index} 超出范围(0 到 {reg_size - 1})。")
    return regs[index]  # 返回寄存器的32位二进制字符串

def write(index_bin, binary_str):
    """将32位二进制字符串写入指定寄存器"""
    index = int(index_bin, 2)  # 将32位二进制字符串转换为整数
    if index < 0 or index >= reg_size:
        raise IndexError(f"寄存器索引 {index} 超出范围(0 到 {reg_size - 1})。")
    if len(binary_str) != 32:
        raise ValueError("输入的二进制字符串必须是32位。")
    regs[index] = binary_str  # 将32位二进制字符串写入寄存器

def get_register_value(index_bin):
    """返回指定寄存器的值(十进制和二进制)"""
    value = read(index_bin)
    return f"Register index {index_bin} : Decimal: {int(value, 2)}, Binary: {value}"

def print_registers():
    """打印所有寄存器的值,包括指令寄存器、程序计数器和标志寄存器"""
    print("Registers values:")
    for i in range(reg_size):
        index_bin = format(i, '032b')  # 以32位二进制格式获取寄存器编号
        value = read(index_bin)
        print(f"Register index {index_bin}  ({int(index_bin, 2):2d}): Decimal: {int(value, 2):10d}, Binary: {value}")
    print(f"Instruction Register (IR): Binary: {ir}")
    print(f"Program Counter (PC): Binary: {pc}, Decimal: {int(pc, 2)}")
    print(f"Flag Register (CF): Binary: {cf}")

测试程序

def run_tests():
    # 初始化寄存器
    print("Initial state:")
    print_registers()

    # 写入值到寄存器
    print("\nWriting values to registers...")
    write(format(0, '032b'), '00000000000000000000000000000001')  # 写入1到寄存器0
    write(format(1, '032b'), '00000000000000000000000000000010')  # 写入2到寄存器1
    write(format(2, '032b'), '00000000000000000000000000000011')  # 写入3到寄存器2

    # 读取并打印寄存器值
    print("\nAfter writing values:")
    print_registers()

    # 获取特定寄存器值
    print("\nGetting register values:")
    print(get_register_value(format(0, '032b')))  # 获取寄存器0的值
    print(get_register_value(format(1, '032b')))  # 获取寄存器1的值
    print(get_register_value(format(2, '032b')))  # 获取寄存器2的值

    # 尝试写入超出范围的寄存器
    try:
        write(format(32, '032b'), '00000000000000000000000000000100')  # 超出范围,写入到寄存器32
    except IndexError as e:
        print(f"Error: {e}")

    # 尝试写入非32位二进制字符串
    try:
        write(format(3, '032b'), '000000000000000000000000000001')  # 非32位二进制字符串
    except ValueError as e:
        print(f"Error: {e}")

三、示例程序

我们可以使用上述模拟器实现一个简单的汇编程序:

Load  r1, #0
Load  r2, #1
Add   r3, r1, r2
Store r3, #3
import ALU
import memory
import registerfile

print('=' * 55 + '初始状态' + '=' * 55)
registerfile.print_registers()
memory.print_memory_range('00000000000000000000000000100000', 4)

registerfile.write("00000000000000000000000000000000", "00000000000000000000000000000100")
registerfile.write("00000000000000000000000000000001", "00000000000000000000000000001001")
rs1_val = registerfile.read("00000000000000000000000000000000")
rs2_val = registerfile.read("00000000000000000000000000000001")
rd = ALU.add_binary(rs1_val, rs2_val)
registerfile.write("00000000000000000000000000000010", rd)
memory.store("00000000000000000000000000100000", rd, 4)

print('=' * 55 + '程序执行后状态' + '=' * 55)

registerfile.print_registers()
memory.print_memory_range('00000000000000000000000000100000', 4)

测试结果

=======================================================初始状态=======================================================
Registers values:
Register index 00000000000000000000000000000000  ( 0): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000001  ( 1): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000010  ( 2): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000011  ( 3): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000100  ( 4): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000101  ( 5): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000110  ( 6): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000111  ( 7): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001000  ( 8): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001001  ( 9): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001010  (10): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001011  (11): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001100  (12): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001101  (13): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001110  (14): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001111  (15): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010000  (16): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010001  (17): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010010  (18): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010011  (19): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010100  (20): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010101  (21): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010110  (22): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010111  (23): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011000  (24): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011001  (25): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011010  (26): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011011  (27): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011100  (28): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011101  (29): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011110  (30): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011111  (31): Decimal:          0, Binary: 00000000000000000000000000000000
Instruction Register (IR): Binary: 00000000000000000000000000000000
Program Counter (PC): Binary: 00000000000000000000000000000000, Decimal: 0
Flag Register (CF): Binary: 00000000000000000000000000000000
Memory values (from Address 32 to 63):
Address 00000000000000000000000000100000: 00000000000000000000000000000000
=======================================================程序执行后状态=======================================================
Registers values:
Register index 00000000000000000000000000000000  ( 0): Decimal:          4, Binary: 00000000000000000000000000000100
Register index 00000000000000000000000000000001  ( 1): Decimal:          9, Binary: 00000000000000000000000000001001
Register index 00000000000000000000000000000010  ( 2): Decimal:         13, Binary: 00000000000000000000000000001101
Register index 00000000000000000000000000000011  ( 3): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000100  ( 4): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000101  ( 5): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000110  ( 6): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000111  ( 7): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001000  ( 8): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001001  ( 9): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001010  (10): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001011  (11): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001100  (12): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001101  (13): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001110  (14): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001111  (15): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010000  (16): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010001  (17): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010010  (18): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010011  (19): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010100  (20): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010101  (21): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010110  (22): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010111  (23): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011000  (24): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011001  (25): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011010  (26): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011011  (27): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011100  (28): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011101  (29): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011110  (30): Decimal:          0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011111  (31): Decimal:          0, Binary: 00000000000000000000000000000000
Instruction Register (IR): Binary: 00000000000000000000000000000000
Program Counter (PC): Binary: 00000000000000000000000000000000, Decimal: 0
Flag Register (CF): Binary: 00000000000000000000000000000000
Memory values (from Address 32 to 63):
Address 00000000000000000000000000100000: 00000000000000000000000000001101

总结

通过 Python 模拟主存和寄存器文件系统,可以更好地理解计算机底层的工作原理。这个模拟器虽然简单,但涵盖了内存和寄存器的基本操作,为进一步学习计算机体系结构打下了基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值