最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

【邏輯門的奇妙冒險(xiǎn)】第6篇 見證第一個(gè)程序的誕生

2023-03-13 08:00 作者:-喵客信條-  | 我要投稿

本篇目標(biāo):

1.理解并實(shí)現(xiàn)寄存器間的加減運(yùn)算;

2.理解并實(shí)現(xiàn)加載立即數(shù)到寄存器;

3.理解指令:形式化記錄的操作序列;

4.實(shí)現(xiàn)指令的自動(dòng)化執(zhí)行,見證第一個(gè)程序的誕生;

5.算法初探:原地交換。

?

上一篇我們介紹了時(shí)序邏輯電路,拿到了通關(guān)獎(jiǎng)杯,一個(gè)寄存器文件RegFile,上上篇的組合邏輯電路,也有通關(guān)獎(jiǎng)杯,一個(gè)算術(shù)邏輯單元,ALU。這兩個(gè)模塊就是我們本篇要搞事情的重要器件,讀者如果對(duì)這兩個(gè)模塊有什么疑問(wèn)的話,建議回去閱讀前兩篇哦。

?

值得補(bǔ)充說(shuō)明的是,由于Logisim這個(gè)小軟件的能力有限,所有的模塊都從與或非基礎(chǔ)邏輯門開始搭建的話,運(yùn)行起來(lái)會(huì)非常的卡。所以,我暫時(shí)把一些器件,例如加法器和寄存器,都用Logisim軟件提供的現(xiàn)用模塊來(lái)代替,原理都是那個(gè)原理,接口都是那個(gè)接口,除了讓軟件運(yùn)行流暢一些之外,并沒(méi)有區(qū)別。

?

為了讓讀者可以順利地復(fù)現(xiàn)我的實(shí)驗(yàn),復(fù)現(xiàn)我當(dāng)初學(xué)習(xí)這種知識(shí)的“哇塞有意思哦”“這太美妙了”的體驗(yàn),我接下來(lái)展示一下ALU和RegFile的內(nèi)部實(shí)現(xiàn)和外部封裝。首先是ALU的內(nèi)部實(shí)現(xiàn),異或、相等、大小比較等邏輯使用了已有的模塊替換:

ALU外部的封裝是這樣的:

接下來(lái)是RegFile的內(nèi)部實(shí)現(xiàn),寄存器和大小比較用了已有的模塊,0號(hào)寄存器還是常量0:

最后是RegFile的外部封裝:


1.理解并實(shí)現(xiàn)寄存器間的加減運(yùn)算;

首先,我們觀察到,RegFile有倆輸出,讀數(shù)據(jù)嘛,ALU有兩個(gè)輸入,操作數(shù)嘛,看起來(lái)挺般配的,或許可以給它們牽個(gè)線?

我們將rdata1和A連接,rdata2和B連接,同時(shí)注意到wdata也是和Y也都是16比特,索性也連一塊好了,這樣一來(lái),電路就是這樣的:

簡(jiǎn)單思考一下,不難發(fā)現(xiàn),wen和clk還是常量0,這種狀態(tài)下的RegFile是不會(huì)發(fā)生變化的,我們可以把wen設(shè)置成1,clk接上真正的時(shí)鐘。然后把RegFile和ALU看作一個(gè)整體,整理一下它們的輸入:ALU的S,RegFile的waddr/raddr1/raddr2。電路變成這樣的:

這個(gè)大電路現(xiàn)在有了四個(gè)輸入了,只要指定一個(gè)輸入組合,例如:

S=011,waddr=011,raddr1=001,raddr=010

就是把1號(hào)寄存器和2號(hào)寄存器的值進(jìn)行加法,結(jié)果寫回3號(hào)寄存器。

?

這里為什么是加法呢?因?yàn)锳LU的選擇信號(hào)S等于3的時(shí)候,Y等于A加B嘛。同樣的,舉一反三,如果輸入組合是這樣的:

(1)S=100,waddr=110,raddr1=100,raddr2=101

(2)S=010,waddr=111,raddr1=111,raddr2=110

(3)S=011,waddr=110,raddr1=110,raddr2=110

輸入組合(1)的意思是把4號(hào)寄存器減去5號(hào)寄存器的結(jié)果寫回6號(hào)寄存器;輸入組合(2)的意思是把7號(hào)寄存器的值和6號(hào)寄存器的值作異或運(yùn)算,然后寫回7號(hào)寄存器;輸入組合(3)的意思是把6號(hào)寄存器的值加上6號(hào)寄存器的值,寫回6號(hào)寄存器。我們一般把raddr1和raddr2稱作“源寄存器號(hào)”,把waddr稱作“目的寄存器號(hào)”。通過(guò)輸入組合(2)(3)我們可以知道,源寄存器號(hào)和目標(biāo)寄存器之前沒(méi)有限制,他們可以都相同的?,F(xiàn)在,我們就可以實(shí)現(xiàn)任意兩個(gè)寄存器間的運(yùn)算,并且把結(jié)果寫回任意一個(gè)寄存器了~

?

2.理解并實(shí)現(xiàn)加載立即數(shù)到寄存器;

對(duì)于第一步實(shí)現(xiàn)的目標(biāo),很明顯還差點(diǎn)意思,硬件寄存器的初始值都是0,這些運(yùn)算雖然都是對(duì)的,但是都是0顯然太無(wú)趣了。我們能不能給寄存器加載進(jìn)不一樣的數(shù)呢?

?

我們注意到,現(xiàn)在RegFile的寫數(shù)據(jù)wdata是連接到ALU的輸出Y的,我們可以想辦法讓ALU輸出非零的數(shù)。一個(gè)可能的方案就是,我們讓0號(hào)寄存器加上一個(gè)我們想要的常數(shù),再寫回RegFile既可?,F(xiàn)在的ALU兩個(gè)輸入是RegFile的兩個(gè)輸入,我們?cè)趺瓷喜拍芗由弦粋€(gè)我們想要的常數(shù),又不破壞第一部分搭建的結(jié)構(gòu)呢?誒,我們可以用復(fù)用器,就像這樣:

現(xiàn)在這個(gè)電路的輸入多了兩個(gè),一個(gè)是否使用常數(shù)的選擇信號(hào)imm和一個(gè)常數(shù)IMM(這個(gè)數(shù)有一個(gè)專用的名字,立即數(shù),Immediate number,可以簡(jiǎn)寫IMM,至于IMM為什么是6位再擴(kuò)展到16位,這里留個(gè)坑,下篇解釋)?,F(xiàn)在我們可以試試新的輸入組合:

(1)S=011,waddr=001,raddr1=000,raddr2=xxx,imm=1,IMM=32

(2)S=011,waddr=011,raddr1=000,raddr2=xxx,imm=1,IMM=48

xxx的意思是無(wú)所謂,反正也用不到,這樣一來(lái),我們的電路就會(huì)變成這樣:


我們可以在RegFile拉出來(lái)的8個(gè)調(diào)試接口中看到,執(zhí)行了輸入組合(1)之后,1號(hào)寄存器成功地被寫入32了,再來(lái)一個(gè)時(shí)鐘,執(zhí)行了輸入組合(2)之后,3號(hào)寄存器成功地被寫入了48了~

?

3.理解指令:形式化記錄的操作組合;

我們剛剛上面兩篇,已經(jīng)有了兩套輸入組合的格式了,我們現(xiàn)在簡(jiǎn)單研究一下這些輸入組合:我們一般先關(guān)注這次輸入使用了ALU的哪一種運(yùn)算?然后ALU是否使用立即數(shù)?目的寄存器號(hào)?第一個(gè)源寄存器號(hào)?第二個(gè)源寄存器號(hào)?立即數(shù)是多少?為了關(guān)注這幾個(gè)問(wèn)題,我們先調(diào)整一下電路輸入,變成這樣:


當(dāng)我們回答了這些問(wèn)號(hào),也就是給出了一次輸入組合,相應(yīng)的,對(duì)電路的一次操作也就確定了。假如說(shuō)我們想要按照一些順序操作電路:

(1)1號(hào)寄存器寫入31

(2)2號(hào)寄存器寫入21

(3)3號(hào)寄存器等于1號(hào)加上2號(hào)

(4)4號(hào)寄存器等于1號(hào)減去2號(hào)

要完成這些操作,我們可以按順序給電路這樣的輸入組合:

(1)S=011,waddr=001,raddr1=000,raddr2=xxx,imm=1,IMM=31

(2)S=011,waddr=010,raddr1=000,raddr2=xxx,imm=1,IMM=21

(3)S=011,waddr=011,raddr1=001,raddr2=010,imm=0,IMM=xxx

(4)S=100,waddr=100,raddr1=001,raddr2=010,imm=0,IMM=xxx

?

老是這么寫也怪麻煩的,我們可以用一些符號(hào)來(lái)輔助記錄,例如:

用“ADD”來(lái)表示S=011,且不使用立即數(shù);

用“ADDI”來(lái)表示S=011,同時(shí)使用立即數(shù);

用“SUB”來(lái)表示S=100

剛剛這些叫做操作類型,然后約定寄存器號(hào)用xi來(lái)表示,例如1號(hào)寄存器就是x1,2號(hào)就是x2,3號(hào)x3,以此類推。這些寄存器號(hào)按照waddr,raddr1,raddr2的順序來(lái)寫。如果是xxx無(wú)所謂的輸入,我們就跳過(guò)不管,IMM就直接寫。這樣一來(lái),我們的剛剛操作序列就可以這樣寫:

ADDI x1 x0 31

ADDI x2 x0 21

ADD x3 x1 x2

SUB x4 x1 x2

每一行都是一次形式化記錄的操作組合,我們把它叫做“指令”。每一條指令都有它的二進(jìn)制形式,也就是這些符號(hào)對(duì)應(yīng)的二進(jìn)制碼,上面的這4條指令,二進(jìn)制形式就是這樣的:

011,1,001,000,011111

011,1,010,000,010101

011,0,011,001,010,000

100,0,100,001,010,000

后面兩條指令為了對(duì)齊,補(bǔ)上3個(gè)零。這里就可以填個(gè)坑了,為什么IMM是6位的?因?yàn)檫@樣一條指令正好16位。進(jìn)一步地我們可以寫出它們的十六進(jìn)制碼:

0x721f

0x7415

0x6650

0x8850

這種東西就叫做指令的機(jī)器碼。顯然機(jī)器是看不懂我們約定的符號(hào)的,那些是給人類看的,機(jī)器只認(rèn)機(jī)器碼的。

?

4.實(shí)現(xiàn)指令的自動(dòng)化執(zhí)行,見證第一個(gè)程序的誕生

現(xiàn)在我們知道了“指令”就是形式化記錄下來(lái)的操作組合,一條指令就是要對(duì)我們的電路進(jìn)行一次操作。這里我們可以約定,一次操作就占用一個(gè)時(shí)鐘周期,下一個(gè)時(shí)鐘周期我們就換一個(gè)操作。

?

顯然,這些操作序列手動(dòng)輸入肯定得累死,我們應(yīng)該讓它們自動(dòng)化地執(zhí)行。如果有什么器件可以按順序地給出這些指令作為電路的輸入,應(yīng)該就可以了。誒,我們之前玩計(jì)數(shù)器的時(shí)候,有一個(gè)器件可以做到,現(xiàn)在我們把指令的機(jī)器碼接入復(fù)用器的輸入


我們注意到,隨著計(jì)數(shù)器的變化,指令按序選擇出來(lái),然后被分解成具體的輸入組合。很自然地,如何我們把這個(gè)和完整電路對(duì)接起來(lái)會(huì)怎么樣呢:


果然符合我們的預(yù)期,1號(hào)、2號(hào)、3號(hào)、4號(hào)寄存器按照我們的預(yù)期被寫入正確的值了。自動(dòng)化地執(zhí)行一個(gè)指令序列,這就是一個(gè)程序,我們一起見證了在用與或非基礎(chǔ)邏輯門搭建起來(lái)的電路中,運(yùn)行了一個(gè)程序!而這個(gè)運(yùn)行程序的電路,就是一個(gè)處理器!一個(gè)玩具型的CPU和它的第一個(gè)程序,誕生了!


5.算法初探:原地交換

現(xiàn)在我們有了指令,有了程序,然后就可以有算法了。但是我們現(xiàn)在的指令還比較少,暫時(shí)沒(méi)法介紹復(fù)雜的算法。我們這里只是先暫時(shí)一個(gè)簡(jiǎn)單的操作:交換兩個(gè)數(shù)的值。

?

比如說(shuō),我們用這樣兩條指令,給兩個(gè)寄存器寫入不同的值:

ADDI x1 x0 31 (011 1 001 000 011111)(0x721f)

ADDI x2 x0 21(011 1 010 000 010101)(0x7415)

現(xiàn)在我們要交換他們,使得1號(hào)得到21,2號(hào)得到31。很明顯,不能將1號(hào)寄存器的值加上0寫回2號(hào)寄存器,然后2號(hào)寄存器的值加上0寫給1號(hào)。因?yàn)檫@個(gè)操作是有順序的,一個(gè)時(shí)鐘一條指令,第一次操作完成,2號(hào)寄存器的值就沒(méi)有了。于是很自然地,我們就想到可以用第三個(gè)寄存器先暫時(shí)中轉(zhuǎn)一下,指令就是:

ADD x3 x2 x0(011 0 011 010 000000)(0x6680)

ADD x2 x1 x0(011 0 010 001 000000)(0x6440)

ADD x1 x3 x0(011 0 001 011 000000)(0x62c0)

我們把這五條指令的十六進(jìn)制碼寫出來(lái),簡(jiǎn)單改造一下我們的復(fù)用器和計(jì)數(shù)器,試運(yùn)行一下:


沒(méi)有問(wèn)題,符合我的預(yù)期,但是還是差點(diǎn)意思,畢竟這個(gè)算法污染了第三個(gè)寄存器,清理污染還得再多來(lái)一條指令。我們有沒(méi)有什么辦法讓兩個(gè)寄存器原地交換呢?可以不用到第三個(gè)寄存器?

?

這個(gè)還真的可以。我們需要先介紹一下異或運(yùn)算(符號(hào)是“^”)的神奇性質(zhì):

如果A^B=C,那么C^B=A,C^A=B

這個(gè)性質(zhì)讀者可以自己證明一下,不難的。于是我們想到,利用這個(gè)性質(zhì),可以先讓1號(hào)寄存器的值和2號(hào)寄存器的值做異或運(yùn)算,結(jié)果寫回1號(hào);然后再讓1號(hào)寄存器的值和2號(hào)的再異或一次,寫到2號(hào),此時(shí)2號(hào)的值就是1號(hào)的舊值了;最后讓1號(hào)寄存器的值和2號(hào)再來(lái)一次異或,值寫回1號(hào),相當(dāng)于1號(hào)和1號(hào)的舊值異或,得到2號(hào)的舊值。至此,完成了交換。乍聽起來(lái)有點(diǎn)繞,直接看指令,然后結(jié)合上面的神奇性質(zhì),琢磨一下應(yīng)該可以理解。

ADDI x1 x0 31 (011 1 001 000 011111)(0x721f)

ADDI x2 x0 21(011 1 010 000 010101)(0x7415)

XOR x1 x1 x2(010 0 001 001 010000)(0x4250)

XOR x2 x1 x2(010 0 010 001 010000)(0x4450)

XOR x1 x1 x2(010 0 001 001 010000)(0x4250)

直接上機(jī)看看效果:


很完美,直接原地完成交換,不需要借用第三方寄存器來(lái)中轉(zhuǎn)。這其實(shí)就是更好的算法,用更漂亮的方式完成同樣的目標(biāo)。這一點(diǎn)將在后續(xù)兩篇中有進(jìn)一步探索~


【邏輯門的奇妙冒險(xiǎn)】第6篇 見證第一個(gè)程序的誕生的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
温泉县| 博兴县| 耒阳市| 孟州市| 泌阳县| 沧源| 沧州市| 保德县| 大埔县| 北海市| 抚松县| 华池县| 楚雄市| 曲松县| 河间市| 西乡县| 南宫市| 奉节县| 前郭尔| 宜州市| 平安县| 长葛市| 民县| 天长市| 文水县| 岐山县| 宝坻区| 定南县| 射洪县| 西昌市| 博罗县| 隆尧县| 闽侯县| 翼城县| 蚌埠市| 淄博市| 桐梓县| 慈溪市| 佛坪县| 中超| 凌云县|