1. 程式人生 > >RISC-V雙週簡報0x20:華米和嘉楠釋出基於RISC-V的自研晶片(2018-09-16)

RISC-V雙週簡報0x20:華米和嘉楠釋出基於RISC-V的自研晶片(2018-09-16)

RISC-V 雙週簡報 (2018-09-16)

要點新聞:

  • 華米和嘉楠科技各自發布了其基於RISC-V的自研晶片
  • RISC-V Day Tokyo和RISC-V Summit的議程出爐

RV新聞

RISC-V Day Tokyo和RISC-V Summit的議程出爐

本年度最後兩場官方舉辦的RISC-V研討會議程均已出爐,有機會參加的請不要錯過。

華米釋出其基於RISC-V的面向可穿戴領域的MCU晶片

華米最新的釋出會上,其創始人在釋出了新款手錶的同時,還發布了其基於RISC-V的可穿戴領域的AI晶片,黃山一號(MHS001)。

作為SiFive的最近一輪投資人之一,這顆晶片採用了SiFive的嵌入式RISC-V CPU,並且集成了NN加速模組,用於加速面向健康檢測的神經網路處理任務。

嘉楠科技釋出搭載RISC-V CPU的AI晶片

嘉楠科技最近釋出了其最新的端測AI晶片Kendryte K210,這顆晶片採用了基於rocket-chip的雙核RV64GCC RISC-V CPU,內建8M位元組的記憶體,應該沒有MMU,可以執行RTOS,輔以多種自研AI加速器。

這顆芯片面向端測,提供機器視覺與語音識別能力。

K210

MIT 和 UC Berkeley 聯合啟動 Keystone 計劃

Keystone: Open-source Secure Hardware Enclave 是 MIT 和 UC Berkeley 在2018年初聯合啟動的一個開源計劃,準備建立一個支援硬體隔離執行空間(hardware enclave)的可信執行環境(Trusted Execution Environment, TEE)。已經隔離的執行空間非常重要,基於它的安全計算將能保護私有資料在共有平臺上的安全執行,阻止第三方程式甚至作業系統對安全計算的窺探(confidentiality)和篡改(integrity)。在enclave方案中,當前已經有商業實現,比如Intel的SGX和ARM的TrustZone,但由於其封閉性生態並沒有大規模應用,在安全風險方面也存在無法有效審計的問題,早在 2016 年,MIT 的研究人員在

Sanctum 專案中嘗試使用 RISC-V 實現 Intel SGX 類似的功能基礎PoC最新版本的Sanctum使用Rocket開放核實現了PUF,attestation以及verifiedboot相關的構建信任鏈條的核心功能,Keystone作為Sanctum的後續版本在Sanctum的基礎上使用了PMP以增強monitor本身的安全性,同時也有計劃簡化使用者空間的開發庫。

Keystone的目標:

  1. 可信鏈 (Chain of Trust)
    • 可信啟動 (Secure boot)
    • 遠端認證 (Remote attestation)
    • 安全金鑰供給 (Secure key provisioning)
  2. 記憶體隔離 (Memory Isolation)
    • 記憶體的物理保護 (Physical memory protection)
    • 頁表隔離 (Page table isolation)
  3. 抵禦物理攻擊 (Defense against Physical Attack)
    • 記憶體加密 (Memory encryption)
    • 記憶體地址匯流排加密 (Memory address bus encryption)
  4. 抵禦測通道攻擊 (Defense against Side-channel Attack)
    • 基於隔離的體系結構 (Isolated architecture)
  5. 形式化驗證 (Formal Verification)
  6. 部署 (Deployment)
    • RISC-V QEMU 模擬
    • 基於FireSim的FPGA模擬 (FPGA-based deployment (FireSim))
    • 流片 (Tape out to chip)
  7. 安全供應鏈的管理 (Secure supply-chain management)

技術討論

RISC-V還缺少large code model

soberlsw-dev 郵件列表表示在基於Sv48編譯的時候碰到了Linking問題(用的是release 20180629 @ https://www.sifive.com/products/tools/ )原始碼如下

// b.c: 
int x[0x40000000];           // 4GB
int y;

// main.c:
extern int x[0x40000000];
extern int y;
__attribute__((noinline)) void fooA(long a, long b) {
    asm volatile(""::"r"(a), "r"(b));  // to notify gcc that a/b are depended
}

int main() {
    fooA((long)x, y);             // to try both address access and load on an address
    return 0;
}

用編譯命令riscv64-unknown-elf-gcc main.c b.c -mcmodel=medany -save-temps -Os會得到如下錯誤資訊

main.o: In function `main':
main.c:(.text.startup+0x0): relocation truncated to fit: R_RISCV_PCREL_HI20 against symbol `y' defined in COMMON section in b.o

main.o反編譯後看到lla a5,y轉成了auipc,但是得到的彙編比較奇怪

   0:   00000797                auipc   a5,0x0
   4:   00078793                mv      a5,a5

如果用-fPIC或者-fPIE選項(地址無關碼,見[1]和[2]),並且加上-nostdlib的話Linking可以通過,但是此時編譯器給出的是la a5,y,並且變成了auipcld

   100b0:       00001797                auipc   a5,0x1
   100b4:       0587b783                ld      a5,88(a5) # 11108 <_GLOBAL_OFFSET_TABLE_+0x10>

對此Andrew認為是預料之中的,如果需要用到超過2GiB的靜態資料,必須得用PIC(包括對library程式碼)。因為PIC會影響到程式碼大小和效能,在給大量靜態資料分配記憶體的時候,建議最好使用malloc或者mmap

soberl隨後貼出了另外一個例子(上例用了很大的陣列其實是為了說明問題方便),實際的Linker Script是這樣的,資料的實體地址從4GiB開始,並且Mbare模式下實體地址和虛擬地址相等。

MEMORY { 
    code :  ORIGIN = 0x00000000, LENGTH = 0x00010000 
    data :  ORIGIN = 0x100000000, LENGTH = 0x00010000 
} 

這樣的情況下,上例中的b.c哪怕是用“正常”大小的陣列

// b.c
int x[0x10]; 
int y;

編譯使用命令riscv64-unknown-elf-gcc main.c b.c -mcmodel=medany -save-temps -Os -march=rv64imafd -nostdlib -T test.ld,還是會有同樣的報錯

main.o: In function `main': 
main.c:(.text.startup+0x0): relocation truncated to fit: R_RISCV_PCREL_HI20 against symbol `y' defined in COMMON section in b.o

這樣是不是意味著,code和data的地址偏移必須都得放在2GiB的範圍之內?

Andrew Waterman表示的確如此,並且這個其實部分來自於RISC-V的基本設計理念。因為實現大跨度的相對PC定址(或者甚至是絕對定址)都需要比較多的指令,另外這種需求也被認為不是很多,所以目前RISC-V沒有做“大”code的模型。支援大code最終還是會做的,目前為了達到目的,可以把code和data相對放的靠近一些。使用PIC並不是最好的替代辦法, 因為對靜態變數的處理有可能和預期不一致(編譯器會生成相對PC定址,而不是用全域性位移表GOT, Global Offset Table)。

Yes, that’s right. Part of this is fundamental to RISC-V. It takes a bunch of instructions to implement PC-relative addressing (or even absolute addressing) with larger offsets. Because of this, and the perceived lack of need, we haven’t yet made a “large” code model.

We should do that eventually, but in the mean time, the best workaround is to put the code and the data closer together somehow. PIC is not a great workaround, because it won’t handle static variables the way you want (the compiler will use PC-relative addressing for these, rather than GOT-indirect addressing).

Links

關於 DDR3 控制器的使用

Andreas Dachsberger 希望可以在 Arty 板上使用外接 DDR3,問題是:

  1. 在 freedom-e-sdk 中是否已有支援 DDR3 記憶體控制器?
  2. 若有,如何使用?
  • Tommy Murphy 認為可以嘗試去 SiFive 論壇 找答案。

  • Bruce Hoult 認為用於 Arty 的 E31/E51 bitstreams 其目的是評估 MCU 中相應的核心,且只支援訪問 FPGA 內建的 16 - 64 KB SRAM 暫存器。 Vivado 包含的 DDR 記憶體控制器是用於他們的 Microblaze 核心,不一定可以用於其他軟核。

  • Samuel Falvo II 也認為 bitstreams 是綜合後的最終產物,內部邏輯無法改變,似乎沒有一個類似 Vivado 的工具可以允許你把現有的 bitstream (例如記憶體控制器等)拼接在一起。

  • Bruce Hoult 認為 SiFive 提供的 FPGA bitstream 是用於產品評估,而非 hacking。Freedom-e-sdk 並未提供任何 CPU 核或者與其他硬體互動有關的內容。建議如果要支援 DDR ,最好從完全開源的核心入手,比如 rocket-chip 或者 picorv32.

  • Michael Clark 提供瞭解決方案:

    1. 參考針對 Freedom E300 Arty 的Dev Kit
    2. 在 e300artydevkit 配置中新增記憶體控制器介面,可參考 rocket-chip、fpga-shells 和 unleashed 的配置
    3. Arty 中的記憶體控制器有一個 16-bit 匯流排,這個配置可能還沒測試過。使用者肯定要寫一些 Chisel 程式碼來把這些元件連起來,但是可以實現的。由於是 Scala 語言,所以有點像寫軟體,只是綜合過程比一般的編譯器耗時。
    1. 修改了 XML 中的 ,以及 Scala 語言級的 id field, 比如“val s_axi_awid = Bits(INPUT,1)”等等。

程式碼更新

SiFive開源Freedom U540 Bootloader

SiFive最近開源了Freedom U540晶片,也就是HiFive Unleashed上搭載的處理器晶片的Bootloader。

SiFive將此專案開源的目的之一是希望通過開源幫助使用者構建可靠的可信任的Bootloader,這一改過去其他廠商閉源Bootloader並且一定程度上掩蓋了問題的作風。

SiFive還發起了一項小的競賽,第一個構建出和U540一模一樣的ROM的PR發起者將會得到一塊Unleashed的開發板.

Links:

Chisel 增刊

Chisel 合併 Vec 物件的方法

Edmond Cote 在郵件列表裡問到,除了像下面的例子用 for 迴圈的方式逐個賦值之外,是否有更好的方式?

val storeTableWalkerRequest: Vec[Bool] = Wire(Vec(NumStorePorts, Bool()))

val loadTableWalkerRequest: Vec[Bool] = Wire(Vec(NumLoadPorts, Bool()))

// Concatenate all request vectors

val tableWalkerRequests: Vec[Bool] = Wire(Vec(NumStorePorts + NumLoadPorts, Bool()))

for (i <- 0 until NumStorePorts) {
  tableWalkerRequests(i) := storeTableWalkerRequest(i)
}

for (i <- NumStorePorts until NumStorePorts + NumLoadPorts) {
  tableWalkerRequests(i) := loadTableWalkerRequest(i - NumStorePorts)
}

Steve Burns 給出瞭解決方法:

VecInit(IndexedSeq((storeTableWalkerRequest ++ loadTableWalkerRequest):_*) )

小編對此的理解是, storeTableWalkerRequestloadTableWalkerRequest 是 Chisel 的 Vec 型別,它繼承自 Scala 的 IndexedSeq 型別,可以用 ++ 符號把兩個 Vec 合併,然後為了把合併後的 Vec 變成 IndexedSeq 型別,需要用 IndexedSeq() 進行轉換。IndexedSeq() 接受多個引數而不是一個集合,所以需要用 :_* 把一個集合引數變成多個引數,最後在用 VecInit() 變成 Vec 型別。

不過小編疑惑的是,既然 Chisel 的 Vec 型別繼承自 Scala 的 IndexedSeq 型別,可以用 ++ 符號合併,這樣應該就算是合併兩個 Vec 了,何必像上面那麼麻煩呢?

Chisel實驗性的支援將檔案內容載入Memeory

Chisel最近開始支援從檔案載入十六進位制或者二進位制的內容到Memeory中用於模擬。這一功能和verilog的$readmem實現類似的功能。

此功能將一定程度的方便開發者,以下是簡單的示例。

import chisel3.util.experimental.loadMemoryFromFile

val memory = Mem(memoryDepth, memoryType)

loadMemoryFromFile(memory, "/workspace/workdir/mem1.txt")

Links:

暴走事件

2018年10月

  • 2018年10月18日, RISC-V Day Tokyo將在Keio University舉辦,大會議程已經公佈。註冊網站

2018年12月

招聘簡訊

CNRV提供為行業公司提供公益性質的一句話的招聘資訊釋出,若有任何體系結構、IC設計、軟體開發的招聘資訊,歡迎聯絡我們!

整理編集: 宋威、黃柏瑋、汪平、林容威、傅煒、巍巍、郭雄飛、黃瑋、李健

特別感謝: Shawn

歡迎關注微信公眾號CNRV,接收最新最時尚的RISC-V訊息!

CNRV微信公眾號