广告位联系
返回顶部
分享到

Python代码模拟CPU工作原理的介绍

python 来源:互联网 作者:佚名 发布时间:2023-07-03 23:04:23 人浏览
摘要

理解 CPU 工作原理,重要的是理解 pc 不停地自增地址,顺序执行程序指令。当遇到跳转指令时,会将 pc 重置为新地址。在顺序执行程序指令的过程中,每一步都是解析程序指令、产生控

理解 CPU 工作原理,重要的是理解 pc 不停地自增地址,顺序执行程序指令。当遇到跳转指令时,会将 pc 重置为新地址。在顺序执行程序指令的过程中,每一步都是解析程序指令、产生控制信号,进而控制所有 CPU 相关器件的工作状态,产生程序计算结果,保存进各寄存器或者RAM 中。

本文使用四十行 Python 代码来实现一个最简单的 CPU。使它可编程,支持加减法运算、读写内存、无条件跳转、条件跳转的功能。

Python层面的实验和书面上的概念,不足以支撑去论证从Python代码到CPU执行的复杂过程,也不足以支撑从CPU读的内存地址到Python内存管理上的内存地址之间复杂的关系,但算是针对此浅层现象的一个合理的猜想。

一、引言

从宏观上,CPU 工作原理是读取内存数据,在 ALU 中完成计算,然后保存进内存,输入输出系统完成了同其他外设交互;从中观上看,CPU 工作原理就是本文讲述的 pc 从 0 开始,读取程序指令寄存器,然后解析指令,控制各部件工作的具体过程;从微观上看,pc 程序计数器、ALU 数字逻辑运算单元,RAM 存储器在内的所有 CPU 相关部件,其实都是一个个三极管,这些三极管在电流作用下导通或者截止,完成了数字逻辑运算、保持记忆状态、产生脉冲信号的所有功能。

二、CPU工作原理

让我们分别介绍各部件工作原理,之后介绍它们怎么协同工作。

1 各部件工作原理

在真实 CPU 中,都有相应物理电路与其对应,它们的功能分别是:

    pc 计数器,从 0 开始产生 0,1,2,……计数可以清零,也可以从外部输入一个数,从这个数从新开始计数,这被称为置位。用于指示程序和数据存取位置。

    RAM,存储数据的随机存储器,支持根据地址(0x01 这种整形)读取数据,根据地址和写入信号 w 写入数据。用于存储程序和数据。

    寄存器,存储 8 bit 信息的存储器,根据 w 信号为 1 写入当前数据,w 为 0 表示读取。类似 RAM,但只能存储 8 bit 信息。常用于存储指令、地址和计算中间量。

    加法器,完成两数加减法运算,sub 为 1 时表示减法,ci 为 1 时表示进位。这个器件是核心器件,用于构成 ALU(算数逻辑单元)。真实 CPU 是采用逻辑门搭建,还有乘法器、逻辑运算单元,等等。

    21选择器,相当于单刀双掷开关,根据 s21 信号,决定 8 bit 输出来自或左或右 8 bit 输入端。

2 协同工作原理

整个数据通路从程序计数器 pc 开始,计数器从 0 开始输出数字 0,1,2,3,4……。指令 RAM 和数据 RAM 中分别存储程序代码和数据。RAM 采用数字表示的位置访问、存储数据。根据计数器地址 0,1,2之类,将 RAM 中的数据分别放入指令寄存器 IR 和数据寄存器 DR。寄存器相当于容器、变量,存储了 RAM 给它的数据。

指令寄存器中的指令码解码产生 CPU 控制指令,这些 0 和 1 分别表示低电平和高电平信号,而电平信号则控制诸如加法器进位与否,是否打开减法,是否使能寄存器写入,选择 21选择器哪一个输入作输出,是否重置计数器,等等。所以,指令其实是控制 CPU 各部件协同工作的电信号。

数据寄存器中的数据分别走向加法器 adder 来进行加法、减法运算后流向 21选择器,也可能直接流向 21选择器等待选择。21选择器选择后,数据进入累加寄存器 AC 。累加器的数据根据 ac 信号是否为高电平 1 ,来决定写入与否。AC累加器的数据会参与下次计算或者根据 w 信号存入数据 RAM 中。

至此,我们完成了一次计算,程序计数器加 1,然后执行下一次计算。如果本条指令是跳转指令的话,将跳转目的地址直接赋值给程序计数器,程序重新地址开始执行。

三、 Python 实现 CPU 各组成部分

1 RAM 存储器

我们用 list 来存储数据。这是一个很简单和直接的设计。

1

ramc = [0x18, 0x19, 0x1d, 0x02, 0x31, 0x30, 0x00]

对存储器的读写,根据 pc 指针来,ramc[pc]=data 表示写入内存,读就是 ramc[pc]。

2 Adder 加法器

1

2

def adder(a=0, b=0, ci=0, sub=0):

    return a-b+ci if sub == 1 else a+b+ci

真正的加法器使用逻辑门,相当于一堆开关按某种关系堆叠在一起,这里我们用高级语言模拟,极大简化了实现。这个加法器实现了 a 和 b 的加法,同时 ci 表示进位,sub 表示减法。

3 Register 寄存器

寄存器采用 Python 的闭包概念来设计,这是为了用自由变量记住寄存器上次的状态。当我们用 AC = register() 调用时,AC 相相当于返回的内部函数 register_inner,此时 temp 作为自由变量和 register_inner 同属一个闭包。所以此后对 temp 变量读、写都是一个持久的变量。相当于维持住了状态。

w 信号为 1 时写入,相当于寄存器使能端 w。

1

2

3

4

5

6

7

8

9

def register():

    temp = 0

  

    def register_inner(data=0, w=0):

        nonlocal temp

        if w == 1:

            temp = data

        return temp

    return register_inner

    真实 CPU 设计当中,如何设计寄存器是一门大学问。即使在微机原理课程粗浅的 CPU 模型学习中,理解继电器和 三极管能记忆,也需要费一番心思。本文用高级语言模拟底层硬件,我们只能再兜兜转转一次,所以此处需要深刻理解闭包概念。

4 8bit 21选择器

21选择器是在 sel 端为 1 时,返回 b 。当 sel 为零时,返回 a。也就是两个输入端选择一个作为输出。

1

2

def b8_21selector(a=0, b=0, sel=0):

    return a if sel == 0 else b

四、集成 CPU

当我们集成 CPU 各部件时,首先将各部件新建出来,然后进行初始化,最后将 pc 置零,开始无限循环。

循环过程中,首先将程序指令 RAM 中的数据写入指令寄存器,根据指令寄存器解码各控制信号,此后操作都是在指令控制信号控制下进行。

首先如果 IR 指令寄存器中是 HLt 停机指令的话,那么系统 Break。否则根据 dr 决定是否将数据信号写入 DR 数据寄存器。

对加法器的操作,是自动的,它的一个输入是 AC 累加器存器,另一个输入是 DR 数据寄存器,同时受到 sub 减法控制信号的控制。

加法运算器运算后,结果传到 21选择器,同数据总线上直接过来的数据一块,等待 s21 信号选择,再根据 ac 信号存进 AC 累加寄存器,以备下一计算。

zf 作为零标志位寄存器,如果 AC 累加器存起结果为零的话,则 zf 为 1。此时如果 pre 为 1 的话,那么就可以将 pc 设置为 DR 数据寄存器的值,实现了运算结果为零跳转功能。否则继续向下执行。

总体集成后,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

def adder(a=0, b=0, ci=0, sub=0):

    return a-b+ci if sub == 1 else a+b+ci

def b8_21selector(a=0, b=0, sel=0):

    return a if sel == 0 else b

def register():

    temp = 0

    def register_inner(data=0, w=0):

        nonlocal temp

        if w == 1:

            temp = data

        return temp

    return register_inner

def int2bin(data=0, length=8, tuple_=1, string=0, humanOrder=0):

    #辅助函数,整数转换为二进制字符串或者元祖。

    r = bin(data)[2:].zfill(length)

    r = r[::-1] if humanOrder == 0 else r

    return r if string == 1 else tuple(int(c) for c in r)

def cpu():

    pc = 0 # pc 计数器从 0 开始,无限循环。

    IR, DR, AC = register(), register(), register() # 新建寄存器

    ramc = [0x18, 0x19, 0x1d, 0x02, 0x31, 0x30, 0x00] # 初始化代码

    ramd = [10, 2, 3, 0xff, 0x06, 0x02] # 初始化数据

  

    IR(0, w=1) # 初始化寄存器

    DR(0, w=1)

    AC(0, w=1)

    while True:

        IR(ramc[pc], w=1) # 指令读写

        *_, pre, dr, ac, sub, w, s21 = int2bin(IR(), humanOrder=1) # 指令解码

        if IR() == 0:

            break # HLT信号

        DR(ramd[pc], w=dr) # 数据读写

        r = adder(AC(), DR(), sub=sub) # 加法器自动加法

        AC(b8_21selector(DR(), r, s21), w=ac) # 选择器选择后,累加寄存器读写

        ramd[pc] = AC() if w else ramd[pc] # 根据 w 信号,数据写入 RAM

        zf = (AC() == 0) # 零标志位寄存器

        pc = DR() if (pre == 1 and zf == True and s21 == 1) else pc + 1 # Jz 指令跳转

        pc = DR() if (pre == 1 and s21 == 0) else pc # 无条件跳转 Jmp

        print(AC())

if __name__ == '__main__':

    cpu()


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 使用python实现md5加密的方法
    1、简介 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用于确保信息传输完整一致。
  • Python代码模拟CPU工作原理的介绍
    理解 CPU 工作原理,重要的是理解 pc 不停地自增地址,顺序执行程序指令。当遇到跳转指令时,会将 pc 重置为新地址。在顺序执行程序指令
  • python实现数组平移K位问题介绍
    python数组平移K位 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 def move(ls: list, offset): 元素原索引+位移数
  • Python利用wxPython实现长文本处理
    在文本编辑器和IDE等应用程序中,可以使用这个示例代码来处理长文本,以便用户更好地查看和编辑文本。 在数据分析和科学计算等领域中
  • Python爬虫之解析HTML页面
    用Python解析HTML页面 在网络爬取的过程中,我们通常需要对所爬取的页面进行解析,从中提取我们需要的数据。网页的结构通常是由 HTML 标签
  • 已解决不小心卸载pip后怎么处理(重新安装pip的两
    已解决:不小心卸载pip后(手动安装pip的两种方式) 报错问题 一个粉丝群的小伙伴提出的问题,不小心卸载了pip怎么重新安装呢?(当时他
  • Python基于Google Bard实现交互式聊天机器人

    Python基于Google Bard实现交互式聊天机器人
    现在我们想实现自动化,所以我用Python做一个交互式的聊天机器人。 获取Session ID 通过浏览器先拿到SessionID,它是一个cookie,名为__Secure-1
  • Python操作MongoDB数据库的方法(非 ODM)

    Python操作MongoDB数据库的方法(非 ODM)
    一、连接器的安装和配置 pymongo:MongoDB 官方提供的 Python 工具包。官方文档:https://pymongo.readthedocs.io/en/stable/pip安装,命令如下: 1 pip inst
  • python进程间通信的项目实践

    python进程间通信的项目实践
    进程间通信表示进程之间的数据交换。 为了开发并行应用程序,需要在进程间交换数据。 下图显示了多个子过程之间同步的各种通信机制
  • Python实现构建一个仪表板

    Python实现构建一个仪表板
    这将为我们的团队节省每天重复的数据处理时间...... 简介 如果你目前在一个数据或商业智能团队工作,你的任务之一可能是制作一些每日、
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计