【深圳 IO 攻略】第 19 關(guān):智能電網(wǎng)控制路由

本文首發(fā)于 B 站《深圳 IO》文集(https://www.bilibili.com/read/readlist/rl569860)。原創(chuàng)不易,轉(zhuǎn)載請注明出處。
關(guān)卡展示


本關(guān)需要將從三個輸入口發(fā)出的數(shù)據(jù)包按照以下規(guī)則轉(zhuǎn)發(fā)到指定的輸出口中:
首數(shù)字小于鎖中的數(shù)字時,將數(shù)據(jù)包轉(zhuǎn)發(fā)到【較小輸出】端口;
首數(shù)字等于鎖中的數(shù)字時,將數(shù)據(jù)包轉(zhuǎn)發(fā)到【電表輸出】端口;
首數(shù)字大于鎖中的數(shù)字時,將數(shù)據(jù)包轉(zhuǎn)發(fā)到【較大輸出】端口。
數(shù)據(jù)包中的第二個數(shù)字是在此之后還剩余的數(shù)字?jǐn)?shù)量,也就是說數(shù)據(jù)包的總長度 = 第二個數(shù)字 + 2。
這一關(guān)我們需要將首數(shù)字讀入 dat,第二個數(shù)字讀入 acc 并倒數(shù),完成整個數(shù)據(jù)包的傳送。如果我們嘗試將所有邏輯寫在同一塊芯片里,會發(fā)現(xiàn)根本寫不下。我們現(xiàn)在只能退而求其次,用兩塊芯片來傳輸。第一塊芯片判定好數(shù)據(jù)方向后,將數(shù)據(jù)方向的值寫入 p 口通道,后面就只管給第二塊芯片傳數(shù)據(jù)了。具體往哪個方向傳,由第二塊芯片來操作。

我們先看左邊的“判斷方向并傳輸數(shù)據(jù)”的芯片。首先,等待 x1 口的數(shù)據(jù)包(slx x1),然后將前兩個數(shù)字分別存入 dat 和 acc 中(mov x1 dat, mov x1 acc)。我們在兩塊芯片中用可以反復(fù)讀取的 p 口來表示數(shù)據(jù)包的輸出方向,0 為【較小輸出】,50 為【電表輸出】,100 為【較大輸出】。我們首先假設(shè)首數(shù)字和鎖中的數(shù)字一樣,將輸出方向設(shè)為【電表輸出】(mov 50 p0)。然后我們判斷首數(shù)字和鎖中的數(shù)字的大?。╰cp dat x0),若首數(shù)字比鎖中的數(shù)字小,則將輸出方向改為【較小輸出】(- mov 0 p0);若首數(shù)字比鎖中的數(shù)字大,則將輸出方向改為【較大輸出】(+ mov 100?p0)。方向決定好后,我們只管往右邊的芯片傳數(shù)據(jù)。首先是把前兩個數(shù)字傳過去(mov dat x3, mov acc x3),對于剩下的 acc 個數(shù)字,我們使用循環(huán)來完成。傳一個(mov x1 x3),然后判斷剛才傳的數(shù)字是不是最后一個(tcp acc 1)。若不是最后一個,則令剩余數(shù)字?jǐn)?shù) -1(+ sub 1),并跳回到第 10 行繼續(xù)傳(+ jmp a),直到將所有的數(shù)字都傳給右邊的芯片后,回到第一行,等待下一個數(shù)據(jù)包(slx x1)。
然后我們看右邊的芯片。因為收到數(shù)據(jù)以后 p 口所表示的方向肯定是已經(jīng)確定下來的了,所以我們只需要 tcp 三態(tài)判定,并將收到的數(shù)字發(fā)送給指定方向的輸出口就行了。首先我們等待從左側(cè)芯片發(fā)來數(shù)字(slx x1)。如果指定的方向是【電表輸出】方向(teq p0 50),則將發(fā)來的數(shù)字傳入【電表輸出】端口(+ mov x1 x3)。如果指定的方向不是【電表輸出】方向,則判定是【較小輸出】還是【較大輸出】(tcp p0 50),并將發(fā)來的數(shù)字送入指定方向的端口(- mov x1 x2, + mov x1 x0)。
點擊左下角的【模擬】,稍等片刻,便會彈出結(jié)算界面:

優(yōu)化三項指標(biāo)
我們觀察到,數(shù)據(jù)包中的第一個數(shù)字一定是三位數(shù),其余數(shù)字則一定不是三位數(shù)。所以,當(dāng)我們收到一個三位數(shù)時,意味著這是一個新數(shù)據(jù)包的首數(shù)字。每當(dāng)收到一個新的首數(shù)字,我們就更換一下方向。如此便可大幅優(yōu)化三項指標(biāo)。

我們不斷等待 x1 發(fā)來新的數(shù)字(slx x1, mov x1 acc)。當(dāng)發(fā)來的是三位數(shù)時(tcp acc 99),說明是數(shù)據(jù)包的首數(shù)字。將該首數(shù)字放入 dat 中,作為將來判斷傳送方向的依據(jù)(+ mov acc dat)。如果首數(shù)字和鎖中的數(shù)字一致(teq dat x0),那么就把當(dāng)前數(shù)字發(fā)往【電表輸出】方向(+ mov acc x3)。如果首數(shù)字和鎖中的數(shù)字不一致(tcp dat x0),那么當(dāng)首數(shù)字小于鎖數(shù)字時,發(fā)往【較小輸出】方向(- mov acc x2);當(dāng)首數(shù)字大于鎖數(shù)字時,發(fā)往【較大輸出】方向(+ mov acc x0)。
以上的電路圖中,我們發(fā)現(xiàn) MC6000 的 x0 口既和鎖子相連,又和【較大輸出】相連。但兩者并不矛盾,因為鎖子是一個【只讀】口,而【較大輸出】是一個【只寫】口。當(dāng)我們從 x0 口讀數(shù)據(jù)時,數(shù)據(jù)只會從鎖子進(jìn)來;當(dāng)我們向 x0 口寫數(shù)據(jù)時,數(shù)據(jù)只會傳往【較大輸出】口。

成本 ¥10→¥5,電量 391→315,代碼行數(shù) 19→9。