欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python代碼模擬CPU工作原理

 更新時(shí)間:2023年01月27日 16:16:23   投稿:yin  
Python代碼來(lái)實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的CPU。用代碼模擬大的部件,使大家從原理上理解CPU工作。使它可編程,支持加減法運(yùn)算、讀寫(xiě)內(nèi)存、無(wú)條件跳轉(zhuǎn)、條件跳轉(zhuǎn)的功能。

理解 CPU 工作原理,重要的是理解 pc 不停地自增地址,順序執(zhí)行程序指令。當(dāng)遇到跳轉(zhuǎn)指令時(shí),會(huì)將 pc 重置為新地址。在順序執(zhí)行程序指令的過(guò)程中,每一步都是解析程序指令、產(chǎn)生控制信號(hào),進(jìn)而控制所有 CPU 相關(guān)器件的工作狀態(tài),產(chǎn)生程序計(jì)算結(jié)果,保存進(jìn)各寄存器或者RAM 中。

本文使用四十行 Python 代碼來(lái)實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的 CPU。使它可編程,支持加減法運(yùn)算、讀寫(xiě)內(nèi)存、無(wú)條件跳轉(zhuǎn)、條件跳轉(zhuǎn)的功能。

Python層面的實(shí)驗(yàn)和書(shū)面上的概念,不足以支撐去論證從Python代碼到CPU執(zhí)行的復(fù)雜過(guò)程,也不足以支撐從CPU讀的內(nèi)存地址到Python內(nèi)存管理上的內(nèi)存地址之間復(fù)雜的關(guān)系,但算是針對(duì)此淺層現(xiàn)象的一個(gè)合理的猜想。

一、引言

從宏觀上,CPU 工作原理是讀取內(nèi)存數(shù)據(jù),在 ALU 中完成計(jì)算,然后保存進(jìn)內(nèi)存,輸入輸出系統(tǒng)完成了同其他外設(shè)交互;從中觀上看,CPU 工作原理就是本文講述的 pc 從 0 開(kāi)始,讀取程序指令寄存器,然后解析指令,控制各部件工作的具體過(guò)程;從微觀上看,pc 程序計(jì)數(shù)器、ALU 數(shù)字邏輯運(yùn)算單元,RAM 存儲(chǔ)器在內(nèi)的所有 CPU 相關(guān)部件,其實(shí)都是一個(gè)個(gè)三極管,這些三極管在電流作用下導(dǎo)通或者截止,完成了數(shù)字邏輯運(yùn)算、保持記憶狀態(tài)、產(chǎn)生脈沖信號(hào)的所有功能。

二、CPU工作原理

讓我們分別介紹各部件工作原理,之后介紹它們?cè)趺磪f(xié)同工作。

1 各部件工作原理

在真實(shí) CPU 中,都有相應(yīng)物理電路與其對(duì)應(yīng),它們的功能分別是:

    pc 計(jì)數(shù)器,從 0 開(kāi)始產(chǎn)生 0,1,2,……計(jì)數(shù)可以清零,也可以從外部輸入一個(gè)數(shù),從這個(gè)數(shù)從新開(kāi)始計(jì)數(shù),這被稱(chēng)為置位。用于指示程序和數(shù)據(jù)存取位置。

    RAM,存儲(chǔ)數(shù)據(jù)的隨機(jī)存儲(chǔ)器,支持根據(jù)地址(0x01 這種整形)讀取數(shù)據(jù),根據(jù)地址和寫(xiě)入信號(hào) w 寫(xiě)入數(shù)據(jù)。用于存儲(chǔ)程序和數(shù)據(jù)。

    寄存器,存儲(chǔ) 8 bit 信息的存儲(chǔ)器,根據(jù) w 信號(hào)為 1 寫(xiě)入當(dāng)前數(shù)據(jù),w 為 0 表示讀取。類(lèi)似 RAM,但只能存儲(chǔ) 8 bit 信息。常用于存儲(chǔ)指令、地址和計(jì)算中間量。

    加法器,完成兩數(shù)加減法運(yùn)算,sub 為 1 時(shí)表示減法,ci 為 1 時(shí)表示進(jìn)位。這個(gè)器件是核心器件,用于構(gòu)成 ALU(算數(shù)邏輯單元)。真實(shí) CPU 是采用邏輯門(mén)搭建,還有乘法器、邏輯運(yùn)算單元,等等。

    21選擇器,相當(dāng)于單刀雙擲開(kāi)關(guān),根據(jù) s21 信號(hào),決定 8 bit 輸出來(lái)自或左或右 8 bit 輸入端。

2 協(xié)同工作原理

整個(gè)數(shù)據(jù)通路從程序計(jì)數(shù)器 pc 開(kāi)始,計(jì)數(shù)器從 0 開(kāi)始輸出數(shù)字 0,1,2,3,4……。指令 RAM 和數(shù)據(jù) RAM 中分別存儲(chǔ)程序代碼和數(shù)據(jù)。RAM 采用數(shù)字表示的位置訪問(wèn)、存儲(chǔ)數(shù)據(jù)。根據(jù)計(jì)數(shù)器地址 0,1,2之類(lèi),將 RAM 中的數(shù)據(jù)分別放入指令寄存器 IR 和數(shù)據(jù)寄存器 DR。寄存器相當(dāng)于容器、變量,存儲(chǔ)了 RAM 給它的數(shù)據(jù)。

指令寄存器中的指令碼解碼產(chǎn)生 CPU 控制指令,這些 0 和 1 分別表示低電平和高電平信號(hào),而電平信號(hào)則控制諸如加法器進(jìn)位與否,是否打開(kāi)減法,是否使能寄存器寫(xiě)入,選擇 21選擇器哪一個(gè)輸入作輸出,是否重置計(jì)數(shù)器,等等。所以,指令其實(shí)是控制 CPU 各部件協(xié)同工作的電信號(hào)。

數(shù)據(jù)寄存器中的數(shù)據(jù)分別走向加法器 adder 來(lái)進(jìn)行加法、減法運(yùn)算后流向 21選擇器,也可能直接流向 21選擇器等待選擇。21選擇器選擇后,數(shù)據(jù)進(jìn)入累加寄存器 AC 。累加器的數(shù)據(jù)根據(jù) ac 信號(hào)是否為高電平 1 ,來(lái)決定寫(xiě)入與否。AC累加器的數(shù)據(jù)會(huì)參與下次計(jì)算或者根據(jù) w 信號(hào)存入數(shù)據(jù) RAM 中。

至此,我們完成了一次計(jì)算,程序計(jì)數(shù)器加 1,然后執(zhí)行下一次計(jì)算。如果本條指令是跳轉(zhuǎn)指令的話(huà),將跳轉(zhuǎn)目的地址直接賦值給程序計(jì)數(shù)器,程序重新地址開(kāi)始執(zhí)行。

三、 Python 實(shí)現(xiàn) CPU 各組成部分

1 RAM 存儲(chǔ)器

我們用 list 來(lái)存儲(chǔ)數(shù)據(jù)。這是一個(gè)很簡(jiǎn)單和直接的設(shè)計(jì)。

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

對(duì)存儲(chǔ)器的讀寫(xiě),根據(jù) pc 指針來(lái),ramc[pc]=data 表示寫(xiě)入內(nèi)存,讀就是 ramc[pc]。

2 Adder 加法器

def adder(a=0, b=0, ci=0, sub=0):
    return a-b+ci if sub == 1 else a+b+ci

真正的加法器使用邏輯門(mén),相當(dāng)于一堆開(kāi)關(guān)按某種關(guān)系堆疊在一起,這里我們用高級(jí)語(yǔ)言模擬,極大簡(jiǎn)化了實(shí)現(xiàn)。這個(gè)加法器實(shí)現(xiàn)了 a 和 b 的加法,同時(shí) ci 表示進(jìn)位,sub 表示減法。

3 Register 寄存器

寄存器采用 Python 的閉包概念來(lái)設(shè)計(jì),這是為了用自由變量記住寄存器上次的狀態(tài)。當(dāng)我們用 AC = register() 調(diào)用時(shí),AC 相相當(dāng)于返回的內(nèi)部函數(shù) register_inner,此時(shí) temp 作為自由變量和 register_inner 同屬一個(gè)閉包。所以此后對(duì) temp 變量讀、寫(xiě)都是一個(gè)持久的變量。相當(dāng)于維持住了狀態(tài)。

w 信號(hào)為 1 時(shí)寫(xiě)入,相當(dāng)于寄存器使能端 w。

def register():
    temp = 0
 
    def register_inner(data=0, w=0):
        nonlocal temp
        if w == 1:
            temp = data
        return temp
    return register_inner

    真實(shí) CPU 設(shè)計(jì)當(dāng)中,如何設(shè)計(jì)寄存器是一門(mén)大學(xué)問(wèn)。即使在微機(jī)原理課程粗淺的 CPU 模型學(xué)習(xí)中,理解繼電器和 三極管能記憶,也需要費(fèi)一番心思。本文用高級(jí)語(yǔ)言模擬底層硬件,我們只能再兜兜轉(zhuǎn)轉(zhuǎn)一次,所以此處需要深刻理解閉包概念。

4 8bit 21選擇器

21選擇器是在 sel 端為 1 時(shí),返回 b 。當(dāng) sel 為零時(shí),返回 a。也就是兩個(gè)輸入端選擇一個(gè)作為輸出。

def b8_21selector(a=0, b=0, sel=0):
    return a if sel == 0 else b

四、集成 CPU

當(dāng)我們集成 CPU 各部件時(shí),首先將各部件新建出來(lái),然后進(jìn)行初始化,最后將 pc 置零,開(kāi)始無(wú)限循環(huán)。

循環(huán)過(guò)程中,首先將程序指令 RAM 中的數(shù)據(jù)寫(xiě)入指令寄存器,根據(jù)指令寄存器解碼各控制信號(hào),此后操作都是在指令控制信號(hào)控制下進(jìn)行。

首先如果 IR 指令寄存器中是 HLt 停機(jī)指令的話(huà),那么系統(tǒng) Break。否則根據(jù) dr 決定是否將數(shù)據(jù)信號(hào)寫(xiě)入 DR 數(shù)據(jù)寄存器。

對(duì)加法器的操作,是自動(dòng)的,它的一個(gè)輸入是 AC 累加器存器,另一個(gè)輸入是 DR 數(shù)據(jù)寄存器,同時(shí)受到 sub 減法控制信號(hào)的控制。

加法運(yùn)算器運(yùn)算后,結(jié)果傳到 21選擇器,同數(shù)據(jù)總線(xiàn)上直接過(guò)來(lái)的數(shù)據(jù)一塊,等待 s21 信號(hào)選擇,再根據(jù) ac 信號(hào)存進(jìn) AC 累加寄存器,以備下一計(jì)算。

zf 作為零標(biāo)志位寄存器,如果 AC 累加器存起結(jié)果為零的話(huà),則 zf 為 1。此時(shí)如果 pre 為 1 的話(huà),那么就可以將 pc 設(shè)置為 DR 數(shù)據(jù)寄存器的值,實(shí)現(xiàn)了運(yùn)算結(jié)果為零跳轉(zhuǎn)功能。否則繼續(xù)向下執(zhí)行。

總體集成后,代碼如下:

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):
    #輔助函數(shù),整數(shù)轉(zhuǎn)換為二進(jìn)制字符串或者元祖。
    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 計(jì)數(shù)器從 0 開(kāi)始,無(wú)限循環(huán)。
    IR, DR, AC = register(), register(), register() # 新建寄存器
    ramc = [0x18, 0x19, 0x1d, 0x02, 0x31, 0x30, 0x00] # 初始化代碼
    ramd = [10, 2, 3, 0xff, 0x06, 0x02] # 初始化數(shù)據(jù)
 
    IR(0, w=1) # 初始化寄存器
    DR(0, w=1)
    AC(0, w=1)
    while True:
        IR(ramc[pc], w=1) # 指令讀寫(xiě)
        *_, pre, dr, ac, sub, w, s21 = int2bin(IR(), humanOrder=1) # 指令解碼
        if IR() == 0:
            break # HLT信號(hào)
        DR(ramd[pc], w=dr) # 數(shù)據(jù)讀寫(xiě)
        r = adder(AC(), DR(), sub=sub) # 加法器自動(dòng)加法
        AC(b8_21selector(DR(), r, s21), w=ac) # 選擇器選擇后,累加寄存器讀寫(xiě)
        ramd[pc] = AC() if w else ramd[pc] # 根據(jù) w 信號(hào),數(shù)據(jù)寫(xiě)入 RAM
        zf = (AC() == 0) # 零標(biāo)志位寄存器
        pc = DR() if (pre == 1 and zf == True and s21 == 1) else pc + 1 # Jz 指令跳轉(zhuǎn)
        pc = DR() if (pre == 1 and s21 == 0) else pc # 無(wú)條件跳轉(zhuǎn) Jmp
        print(AC()) 
if __name__ == '__main__':
    cpu()

到此這篇關(guān)于Python代碼模擬CPU工作原理的文章就介紹到這了,更多相關(guān)Python模擬CPU內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • flask后端request獲取參數(shù)的幾種方式整理

    flask后端request獲取參數(shù)的幾種方式整理

    這篇文章主要為大家介紹了flask后端request獲取參數(shù)的幾種方式整理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Python實(shí)現(xiàn)京東搶秒殺功能

    Python實(shí)現(xiàn)京東搶秒殺功能

    這篇文章主要介紹了Python實(shí)現(xiàn)京東搶秒殺功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • Python 的可變和不可變對(duì)象詳情

    Python 的可變和不可變對(duì)象詳情

    本文通過(guò)詳情描述Python 中的可變對(duì)象與不可變對(duì)象來(lái)看兩者的區(qū)別,剛興趣的朋友可以參考下文
    2021-08-08
  • Python3 獲取一大段文本之間兩個(gè)關(guān)鍵字之間的內(nèi)容方法

    Python3 獲取一大段文本之間兩個(gè)關(guān)鍵字之間的內(nèi)容方法

    今天小編就為大家分享一篇Python3 獲取一大段文本之間兩個(gè)關(guān)鍵字之間的內(nèi)容方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • Python input()函數(shù)案例教程

    Python input()函數(shù)案例教程

    在 Python 中,input() 函數(shù)用于獲取用于的輸入,并給出提示。input() 函數(shù),總是返回 string 類(lèi)型,因此,我們可以使用 input() 函數(shù),獲取用戶(hù)輸入的任何數(shù)據(jù)類(lèi)型 ,這篇文章主要介紹了Python input()函數(shù)案例詳解,需要的朋友可以參考下
    2023-01-01
  • Python中easy_install 和 pip 的安裝及使用

    Python中easy_install 和 pip 的安裝及使用

    本篇文章主要介紹了Python中easy_install 和 pip 的安裝及使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 介紹Python的Django框架中的QuerySets

    介紹Python的Django框架中的QuerySets

    這篇文章主要介紹了Python的Django框架中的QuerySets,QuerySet是Django中的一個(gè)內(nèi)置對(duì)象列表,經(jīng)常被用于數(shù)據(jù)庫(kù)操作,需要的朋友可以參考下
    2015-04-04
  • selenium在scrapy中的使用代碼

    selenium在scrapy中的使用代碼

    本文給大家分享selenium在scrapy中的使用代碼,使用selenium可以很好的幫助我們獲取一些重要數(shù)據(jù)信息,本文通過(guò)代碼給大家詳細(xì)介紹,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • python中使用urllib2偽造HTTP報(bào)頭的2個(gè)方法

    python中使用urllib2偽造HTTP報(bào)頭的2個(gè)方法

    這篇文章主要介紹了python中使用urllib2偽造HTTP報(bào)頭的2個(gè)方法,即偽造http頭信息,需要的朋友可以參考下
    2014-07-07
  • Python文件時(shí)間操作步驟代碼詳解

    Python文件時(shí)間操作步驟代碼詳解

    這篇文章主要介紹了Python文件時(shí)間操作步驟代碼詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04

最新評(píng)論