2011-09-20 38 views
15

我正在設計TTL串行計算機,並且我正在努力選擇更適合LLVM編譯器後端的體系結構(我希望能夠在那裏運行任何C++軟件)。不會有MMU,不會有乘法/除法,沒有硬件堆棧,沒有中斷。爲LLVM/CLANG選擇CPU體系結構

我有2點主要的選擇:

1)8位存儲器,8位ALU,8位寄存器(〜12-16)。存儲器地址寬度24位。所以我需要使用3個寄存器作爲IP和3個寄存器來存儲任何內存位置。

不用說,任何地址計算都是在編譯器中實現的純痛苦。 2)24位存儲器,24位ALU,24位寄存器(〜6-8)。平坦的記憶,很好。缺點是由於設計的連續性,即使我們在一些布爾運算上運行,每個操作也會花費3倍的時鐘。 24位內存數據寬度很貴。一般來說,硬件實現起來比較困難。


的問題是:你認爲實現這個8位所有的C++功能,堆棧更少的硬件是可能的,或者我需要有更復雜的硬件有合理的質量&速度生成的代碼?

+0

這可能是一個天真的問題,但爲什麼你必須實現所有的C++的功能?難道你不能只用寫一個新的LLVM目標體系結構,並且Clang會毫無問題地編譯C++嗎? –

+0

@Dan Cecile這正是我要做的。但是您可以看到,爲具有24位內存空間的8位CPU編寫LLVM後端可能有點不重要。 – BarsMonster

+0

所以你有4個部分;弄清楚如何實現[LLVM彙編語言](http://llvm.org/docs/LangRef.html)與您的硬件一起工作,複製和修改[現有的LLVM目標](https://github.com/earl)/llvm-mirror/tree/master/lib/Target)與你的硬件一起工作,弄清楚如何讓Clang [產生8位LLVM字節碼](http://clang.llvm.org/doxygen/classclang_1_1TargetInfo.html )([指針大小是可配置的](http://clang-developers.42468.n3.nabble.com/Re-targeting-clang-to-a-new-architecture-tp761920p762813.html)),然後將您的硬件更改爲更合適。 –

回答

18

我第二個建議使用LCC。我在這個自制的16位RISC項目中使用它:http://fpgacpu.org/xsoc/cc.html

我認爲不管你是否構建8位變體並使用3個隨附攜帶來增加IP或24位變體並在硬件中完成整個事情,這應該會有很大的區別。你可以隱藏你的彙編器的差異。

如果你看看我上面的文章,或者更簡單的CPU:http://fpgacpu.org/papers/soc-gr0040-paper.pdf你會看到你真的不需要那麼多的操作符/指令來覆蓋整數C repetoire。事實上,有一個lcc實用程序(ops)可以打印給定機器的min操作符集。

欲瞭解更多信息,請參閱上LCC移植到新的機器在這裏我的文章:http://www.fpgacpu.org/usenet/lcc.html

有一次,我移植LCC,我寫了一個彙編程序,它的合成,從實驗室的基本指令的大repetoire。例如,我的機器有負載字節無符號而不是負載字節的簽名,所以我發出這個順序:

lbs rd,imm(rs) -> 
    lbu rd,imm(rs) 
    lea r1,0x80 
    xor rd,r1 
    sub rd,r1 

所以我認爲你可以操作這個分蓋度日:

registers 
    load register with constant 
    load rd = *rs 
    store *rs1 = rs2 
    + - (w/ w/o carry) // actually can to + with - and^
    >> 1     // << 1 is just + 
    &^     // (synthesize ~ from ^, | from & and ^) 
    jump-and-link rd,rs // rd = pc, pc = rs 
    skip-z/nz/n/nn rs  // skip next insn on rs==0, !=0, <0, >=0 

更簡單的是沒有寄存器(或者等效地將寄存器與內存模糊 - 所有寄存器都有內存地址)。

爲SP預留一個寄存器,並在編譯器中編寫函數prolog/epilog處理程序,您不必擔心堆棧指令。只有代碼存儲每個被調用者保存寄存器,按幀大小調整SP,等等。

中斷(以及從中斷返回)很簡單。你只需要在指令寄存器中強制一個跳轉鏈接指令。如果您選擇的位模式爲0,並將正確的地址放入源寄存器rs(特別是如果它是r0),則可以使用觸發器復位輸入或額外的力 - 0和門。我在上面的第二篇論文中使用了類似的技巧。

有趣的項目。我看到一個TTL/7400比賽正在進行中,我在想自己機器的簡單程度是否可以避免,並且將32 KB或128 KB的異步SRAM添加到機器以保存代碼和數據會是一種欺騙行爲。

無論如何,快樂的黑客!

p.s.

1)你會想要決定每個整數類型有多大。如果你願意的話,你可以使char,short,int,long,long long等等大小相同,一個24b的單詞,儘管它在最小表示範圍內不符合。

2)雖然我專注於lcc這裏,但您是在問C++。我建議首先說服C。一旦你想出了C,包括軟件中的*,/,%運算符等,無論是LLVM還是GCC,都應該更容易轉移到完整的C++。 C和C++之間的區別僅僅是「處理虛函數調用,指向成員解引用,動態轉換,靜態構造函數,異常處理所需的額外vtables和RTTI表和代碼序列(完全構建在原始C整數運算符repetoire之外)處理等。

+2

p.s.我剛在想。你應該建立24b變體而不是8b變體。這並不是因爲更廣泛的數據操作需要多條指令,而是因爲您確實需要線性24位地址空間的概念來獲取指令和數據。雖然您可以從3個8b負載中合成24b負載,但您需要24位地址(和24位地址增量)來處理硬件中的取指令,程序計數器和PC增量。如果您只有8b地址,如何處理大於256條指令的程序尚不清楚。 –

1

在我看來,無堆棧硬件已經不適合C和C++代碼。如果你有嵌套的函數調用,那麼無論如何你都需要用軟件模擬一個堆棧,這當然要慢得多。

當進入無堆棧路由時,您可能會將大部分變量分配爲「靜態」,並且沒有可重入功能。在這種情況下,6502風格的尋址模式可能會有效。例如,你可以有這些尋址模式:

  1. 立即地址(24位)爲操作碼
  2. 立即地址(24位)加上索引寄存器(8位)
  3. 間接訪問的部分:直接24位地址的內存,其中包含實際地址
  4. 間接訪問:24位地址到內存,8位索引寄存器添加到內存中的值。

上面概述的地址模式將允許有效訪問分配給常量地址(靜態分配)的數組,結構和對象。它們對於動態和堆棧分配的對象效率較低(但仍然可用)。

您也想從你的串行設計得到一些好處:通常24位+ 8位加法用不了24個週期,但你可以代替短路時搭載的是0.1

不是映射加IP作爲直接寄存器,你可以允許只通過goto/branch指令來改變它,使用與上面相同的地址模式。跳轉到動態計算的地址是非常罕見的,因此在操作碼中直接提供整個24位地址更有意義。

我認爲,如果您仔細設計CPU,可以非常高效地使用許多C++功能。但是,不要指望任何隨機的C++代碼在這種有限的CPU上運行得很快。

+0

是的,無堆棧代碼是無用的:我仍然希望能夠交叉編譯現有的代碼。所以我將不得不使用模擬堆棧。 – BarsMonster

+1

你可以實現一個硬件堆棧;它只需要兩條指令,增量/減量在串行體系結構中相當快速且簡單。 – jpa

1

該實現當然是可能的,但我懷疑它是可用的(至少對於C++代碼)。正如已經指出的那樣,第一個問題是缺乏堆棧。接下來,一羣C++嚴重依賴動態內存分配,C++「內部」結構也相當大。

所以,在我看來,這將是更好的,如果你:

  1. 擺脫C++要求(或者至少限制了自己的一些子集)
  2. 使用24位,不一切8個比特(用於寄存器以及)
  3. 添加硬件堆棧
+0

那麼,實現子集比整個C++更難。在後一種情況下,我只需要編寫clang/llvm後端。爲什麼缺少硬件堆棧這樣的關鍵問題?一個軟件可以做同樣的事嗎? – BarsMonster

+0

如果你不關心任何表現 - 那麼你很好,是的:) –

3

IMHO,這是可能的C編譯器。不過,我不確定C++。

LLVM/Clang的可能是8位計算機的硬盤選擇,

相反,第一次嘗試lcc,然後第二LLVM /等,心連心。

比爾Buzbee成功進行重新定位LCC編譯器爲他魔術-1(被稱爲homebrewcpu)。

雖然Magic-1的硬件設計和構造通常得到最多的關注,但項目最大的部分(到目前爲止)一直在開發/移植軟件。爲此,我不得不從頭開始編寫彙編器和鏈接器,重新編譯C編譯器,編寫和移植標準C庫,編寫簡化的操作系統,然後移植更復雜的操作系統。這是一個挑戰,但很有趣。我想我有點扭曲,但我碰巧喜歡調試困難的問題。而且,當您要追蹤的錯誤可能涉及以下一個或多個:硬件設計缺陷,線路鬆動或斷裂,TTL芯片鬆動或損壞,彙編器錯誤,鏈接器錯誤,編譯器錯誤,C運行時庫錯誤或最後有問題的程序中有一個錯誤,有很多樂趣。哦,而且我也沒有奢侈的責怪任何人的錯誤。

我總是驚訝於該死的東西在所有的運行,更少的運行,以及它的確如此。

-1

你不能在那裏運行「任何」C++代碼。例如fork(),system()等。任何明顯依賴於中斷的例子。當然,你可以在那裏找到很長的路要走。 現在你是指任何可以用C++編寫的程序,還是僅限於自己的語言,而不是通常與C/C++相關的庫?語言本身是一個更容易遵守的規則。

我覺得更簡單的問題/答案是,爲什麼不試試?你試過什麼了?有人可能會認爲x86是一個8位機器,不考慮對齊和許多8位指令。 msp430被移植到llvm以展示它可以如何輕鬆和快速地完成,我希望看到該平臺具有更好的支持(不是我的優勢所在,否則我會這麼做)一個16位的平臺。沒有mmu。確實有堆棧和中斷,不必使用它們,如果你刪除了庫規則,那麼剩下的需要中斷嗎?

我會看看llvm,但請注意,生成的文檔顯示它是多麼容易移植,過時和錯誤,並且您基本上必須從編譯器源自己弄清楚它。 llc有一本書,以此而着稱,沒有優化。信息來源在現代計算機上編譯得不好,總是必須及時倒退才能使用它,任何時候我在晚上過了一段時間後都會嘗試構建它,因爲我放棄了它。 vbcc,簡單,乾淨,有文件記錄,對小型處理器不是不友善。是C++嗎,不記得了。儘管如此,最容易讓編譯器運行起來。其中所有LLVM都是最有吸引力,最有用的。不要靠近海灣合作委員會,甚至沒有想到它,管道膠帶和甩絲裏面拿着它在一起。

你是否發明了你的指令集?你有模擬器和彙編器嗎?在github上查找lsasim來找到我的指令集。你可以爲我寫一個llvm後臺作爲你練習的練習......咧...(我的vbcc後端很糟糕,我需要重新開始)...

你必須對高級別將被實現,但你必須從一個指令集和一個指令集模擬器和某種彙編程序開始。然後開始將C/C++代碼轉換爲您的指令集的程序集,這應該很快讓您瞭解「我可以在沒有堆棧的情況下執行此操作」等。在此過程中定義您的調用約定,手動實現更多C/C++代碼使用你的調用約定。然後深入一個編譯器並做一個後端。我認爲你應該考慮vbcc作爲墊腳石,然後如果看起來像它(isa)將工作,然後前往LLVM。