Vengineerの戯言

人生は短いけど、長いです。人生を楽しみましょう!

Tier IV、チップが上がってきた模様

はじめに

Twitterを眺めていたら、Tier IVがアクセルと共同開発していたチップが上げってきた模様です。

説明のために各ツイートを引用します。

Tier IV が開発しているチップとは?

ちょっと気になったので調べてみました。

HORNETといアーキテクチャのものを作っている。

Tier IV での職:ASIC、FPGA関連

16_完全自動運転向けハードウェアIP研究開発エンジニア(FPGA, ASIC)

無くなってしまうので、画像で引用します。

ここに、OpenCLというキーワードが

ちょっと前に開催された FPGA関連の勉強会での資料 (2022/4/25に開催した「TIER IV 自動運転向け RTL-FPGA 開発 テックミートアップ」)

東大(塩田研)でやっていること。

RISC-V のセミナーでの講演資料 : Out-of-order スーパスカラ・プロセッサ RSD と車載向け SIMT 型アクセラレータ HORNET について

RSDって、ここで公開されている RISC-V のプロセッサですよね。2019年12月に公開。3年近く経ちますね。

スライドの中から

  • アクセル と Tier IV での共同開発
  • 東大の塩田 sanがマイクロアーキテクチャに関与
  • 2021年は FPGA で検証中、その経緯は上記の講演資料に載っていた
  • 2022年にテストチップの予定 => それが先週上がってきた。。。

おわりに

2019年より前より開発していた RISC-V (RSD) が繋がっているのかどうかはわかりませんが、実際の商用の半導体につながるのって、なんか珍しい気がします。

HORNET、面白そうですね。

このくらいの規模なら、28nm でできそうかな? 16nm かな? 7nm までは必要なさそう。。。開発コスト考えると、28nm ぐらいが妥当だと思うけど。

28nmのようです

このTweetのスレッドを眺めると面白いですよ

Ayer Labsという会社

はじめに

Ayar Labsという会社。

チップ間通信技術を中心としたエコシステムを構築している会社

ayarlabs.com

2019年の Hot Chip での発表内容 : TeraPHY: A Chiplet Technology for LowPower, High-Bandwidth In-Package Optical I/O

112Gbs (100Gbs) の TeraPhy

www.nextplatform.com

Intel、HPE、NVIDIAが投資している

全体的なお話はここを読めばいい。インタービューに答えているのは、Mark Wade -san

https://news.yahoo.co.jp/articles/2baf6bd290af74220eb80fe11ed90c60ce8fd934news.yahoo.co.jp

Ayer Labsになる前のお話は、ここ。Optibit という会社が前身。

news.mit.edu

Intelとの関係

fuse.wikichip.org

fuse.wikichip.org

HPEのと関係 (HPEのGen-Zは、CXLに吸収されてしまった)

www.nextplatform.com

NVIDIAとの関係

ayarlabs.com

www.theregister.com

NVIDIA is Preparing Co-Packaged Photonics for NVLink

おわりに

Ayer Labs、Intel、HPE、NVIDIAから投資されているので、どこかに買収されるようなことはなさそうですが、どうなるんでしょうかね。

7nm/28nm/90nm/250nm の Wafer Cost

はじめに

SemiAnalysis の下記の記事、非常に興味深いです。

semianalysis.substack.com

Wafer Cost

上記の記事の下図(説明のために引用します)では、7nm/28nm/90nm/250nm の Wafer Cost と Wafer の枚数の関係を示しています。

  • 250nm では、3,000 枚作れば、ほぼコストは一定
  • 90nm では、6,000 枚作れば、ほぼコストは一定
  • 28nm では、25,000 枚作れば、ほぼコストは一定
  • 7nm では、100,000 枚作れば、ほぼコストは一定

グラフを見ると、250nm => 90nm で2倍のCostになっていますね。90nm => 28nm でも 2倍、28nm => 7nm でも 2倍。。。3世代で2倍?

Wafer 1枚で取れる die が 仮に300個だと、

  • 250nm では、300 * 3,000 = 900,000 (90万個)
  • 90nm では、300 * 6,000 = 1,800, 000 (180万個)
  • 28nm では、300 * 25,000 = 7,500,000 (750万個)
  • 7nm では、300 * 100,000 = 3,000,000 (3,000万個)

になりますね。

Apple iPhone

2021年のAppleiPhone の出荷数は、2.379億台 です。

Apple A13 : 98.48 mm2 Apple A14 : 88mm2 Apple A15 : 107.68mm2

仮に、30cm の Wafer で A13/14/A15 は 300個ぐらい取れそうなので、7nm => 5nm になり、倍になっても、6,000万個なので、Wafer Costは一定になっているんでしょうね。

大きな die は?

クライド学習用チップは、die size が大きいです。

仮に、最大露光範囲、26 mm * 33 mm = 858mm の die size を 300 mm Wafer で作ると、62個取れます。

全部良品としても、100枚のWaferで620個、1000枚で6200個。 半数の31個だと、100枚のWaferで310個、1000で3100個。

www.silicon-edge.co.uk

8個で1ノードを作るシステムだと、100枚でざっくり40 ノード、1000枚で 400 ノード。まー、このぐらいは作りそうですね。

100枚作っても、7nm でのコストは、0.2 - 0.3 の間。。。右側の コストが一定になる 0.07 に対しては、まだ、2-3倍ぐらいのコスト差がありますね。

おわりに

半導体プロセス、進化すれば単価も安くなると思っていましたが、数がでないと、なかなか難しい。7nm になって、それがかなり目立ってきた感じですね。

NVIDIAのNVLinkは、2種類あるんだ。

はじめに

NVIDIA Grace について、自分のブログを復習していたら、NVLink って、2種類あるのに気が付きました(いまさらかよ。。。)

vengineer.hatenablog.com

2つのNVLink

説明のために下図を引用します。

  • NVLink-C2C
  • PCIe/coherent NVLink

とあります。

Grace の die shot を眺めてみる

下記のツイートに Grace の die shot の鮮明なものがあるので、これを説明のために引用します。

  • NVLink-C2C : 右側
  • PCIe/coherent NVLink : 左側

っぽいです。

Grace Superchip を眺めてみると、下図を説明のために引用します。

外側が PCIe/coherent NVLink で 2つのGraceが対向しているのが NVLink-C2C っぽですよね。

ここの内容によると、

  • x12 clNVLINK/PCIe
  • x56 PCIe Gen5

になっていますね。ぱっと見、x16 が 4組だと思っていたのですが、x8 が 7組と、x8 + x4 が 1組って感じなんでしょか。

おわりに

と書いてから、いろいろと調べてみたら、自分のブログに

GRACE SuperChip になると、NVLINK - C2C は、GRACE間の接続で使うけど、もう一つの PCIe x56 + x12 cNVLINK/PCIe は何に使うのでしょうかね。

と書いてあった。

vengineer.hatenablog.com

NVIDIAのGraceは、Neoverse V2 なので、CMN-700が使えた

はじめに

下記のツイート、Gracdは、Neoverse V2 のようです。

Arm の Neoverse N2 発表

AnandTech に下記の記事

Neoverse V2は、2023年に出る感じですね。

ArmのNEWSROOM

www.arm.com

Poseidonの一つ前が Neoverse V2 という位置づけなんですね。

Arm CMN-700 は使えないのでは?

8月23日のブログの最後で Grace は、CMN-700ではなく、CMN-600 では?と書きましたが、

vengineer.hatenablog.com

Grace は Neoverse V2 ということで、CMN-700 になるんですね。

おわりに

Graceの2021年発表の時では、Neoverse V2があったかどうかはわかりませんが、Armのロードマップのこの部分のCPUを使うということなんでしょうね。 となると、2021年の発表時のベンチマークは他のCPUコアだったんでしょうね。そうなると、CMN-700 ではなく、CMN-600 。

Graceは、Neoverse V2の本番の前になんらかのプロトタイプ的なものもあったでしょうね。。

AMD の Chipset (X670)って、デイジーチェーンできるんだ。

はじめに

このツイートで、知りました。

AMDのX670のChipset側って、デイジーチェーンできるんですね。

X670 と X650

ここに詳しく書いてありました。

northwood.blog.fc2.com

X670 って、

  • PCIe Gen4 x4
  • PCIe Gen4 x4
  • PCIe Gen4 x4

があるので、2つの PCIe Gen4 x4 を使って、デイジーチェーンができるようです。

SATAとUSBをたくさんほしい人ようですかね。

おわりに

CPU側に、ITE Super I/O が付いているんですね。。。。

CPU側の PCIe Gen4 x4 を使って、Wifi/BLE を接続すれば、X670/X650って無くても、PCできるんですかね。

おわりに

RISC-VのBoot

はじめに

Zynq MPSoCで、コンピュータを学ぼう にて、「Xilinx社のZynqMP SoCのブートシーケンス」を説明しました。 また、まとめでは、RISC-Vでもほぼ同じですよ。と書きました。

vengineer.hatenablog.com

RISC-VのBootについては、ちゃんと確認していなかったので、確認しました。

RISC-VのBoot

下記のサイトの内容から確認しました。

github.com

  • Zero Stage Boot Loader : SoCの中にあるROM
  • First Stage Boot Loader : ここは、U-Boot SPL など
  • Second Stage Boot Loader : OpenSBI => U-Boot
  • Linux

OpenSBI は、ZynqMP の CPUコア、Armv8 の Arm Trusted Firmware に相当するものです。OpenSBIとLinuxについては、

にて、まとめたのでこちらを覗いてみてください。

OpenSBIより前はどうなっているのか?

上記の記事の中では、

のURLが貼っていましたので、そこを探ってみます。

Zero Stage Boot Loader

Zero Stage Boot Loader のソースコードは、こちら

start.S が最初に実行するコードです。prog_start から始まり、start に続きます。

  .section .text.init
  .globl _prog_start
_prog_start:
  .globl _start
_start:
  la t0, trap_entry
  csrw mtvec, t0

  smp_pause(s1, s2)

ずーと続いて、main を call します。

  smp_resume(s1, s2)

  // Allocate 4 KiB stack for each hart
  csrr t0, mhartid
  slli t0, t0, 12
  la sp, _sp
  sub sp, sp, t0

  call main

  li t0, CCACHE_SIDEBAND_ADDR
  csrr a0, mhartid
  la a1, _dtb
  jr t0

  .align 2
trap_entry:
  call handle_trap

  .section .rodata
_dtb:
  .incbin "zsbl/ux00_zsbl.dtb"
  //.incbin DEVICE_TREE

main.c の main関数の中で、ux00boot_load_gpt_partition にてCCACHE_SIDEBAND_ADDRにロードしています。

int main()
{
  if (read_csr(mhartid) == NONSMP_HART) {
    unsigned int peripheral_input_khz;
    if (UX00PRCI_REG(UX00PRCI_CLKMUXSTATUSREG) & CLKMUX_STATUS_TLCLKSEL) {
      peripheral_input_khz = CORE_CLK_KHZ; // perpheral_clk = tlclk
    } else {
      peripheral_input_khz = (CORE_CLK_KHZ / 2);
    }
    init_uart(peripheral_input_khz);
    ux00boot_load_gpt_partition((void*) CCACHE_SIDEBAND_ADDR, &gpt_guid_sifive_fsbl, peripheral_input_khz);
  }

  Barrier_Wait(&barrier, NUM_CORES);

  return 0;
}

ux00boot_load_gpt_partition は、ux00boot/ux00boot.c の中で次のように定義しています。

void ux00boot_load_gpt_partition(void* dst, const gpt_guid* partition_type_guid, unsigned int peripheral_input_khz)
{
  uint32_t mode_select = *((volatile uint32_t*) MODESELECT_MEM_ADDR);

  spi_ctrl* spictrl = NULL;
  void* spimem = NULL;

  int spi_device = get_boot_spi_device(mode_select);
  ux00boot_routine boot_routine = get_boot_routine(mode_select);

  switch (spi_device)
  {
    case 0:
      spictrl = (spi_ctrl*) SPI0_CTRL_ADDR;
      spimem = (void*) SPI0_MEM_ADDR;
      break;
    case 1:
      spictrl = (spi_ctrl*) SPI1_CTRL_ADDR;
      spimem = (void*) SPI1_MEM_ADDR;
      break;
    case 2:
      spictrl = (spi_ctrl*) SPI2_CTRL_ADDR;
      break;
    case 3:
      // MODESELECT_LOOP. Don't try to find spi device in debug mode.
      break;
    default:
      ux00boot_fail(ERROR_CODE_UNHANDLED_SPI_DEVICE, 0);
      break;
  }

  unsigned int error = 0;

  switch (boot_routine)
  {
    case UX00BOOT_ROUTINE_FLASH:
      error = initialize_spi_flash_direct(spictrl, peripheral_input_khz);
      if (!error) error = load_spiflash_gpt_partition(spictrl, dst, partition_type_guid);
      break;
    case UX00BOOT_ROUTINE_MMAP:
      error = initialize_spi_flash_mmap_single(spictrl, peripheral_input_khz);
      if (!error) error = load_mmap_gpt_partition(spimem, dst, partition_type_guid);
      break;
    case UX00BOOT_ROUTINE_MMAP_QUAD:
      error = initialize_spi_flash_mmap_quad(spictrl, peripheral_input_khz);
      if (!error) error = load_mmap_gpt_partition(spimem, dst, partition_type_guid);
      break;
    case UX00BOOT_ROUTINE_SDCARD:
    case UX00BOOT_ROUTINE_SDCARD_NO_INIT:
      {
        int skip_sd_init_commands = (boot_routine == UX00BOOT_ROUTINE_SDCARD) ? 0 : 1;
        error = initialize_sd(spictrl, peripheral_input_khz, skip_sd_init_commands);
        if (!error) error = load_sd_gpt_partition(spictrl, dst, partition_type_guid);
      }
      break;
    case UX00BOOT_ROUTINE_LOOP:
      error = 0;
      /**
       * Control transfer back to debugger.
       * Debugger can load next stage to PAYLOAD_DEST.
       */
      asm volatile ("ebreak");
      break;
    default:
      error = ERROR_CODE_UNHANDLED_BOOT_ROUTINE;
      break;
  }

  if (error) {
    ux00boot_fail(error, 0);
  }
}

SPI または SDCard から First Stage Boot Loader をロードしています。

start.S に戻って、ロードしたアドレス (CCACHE_SIDEBAND_ADDR) を t0、mhartid を a0、_dtb を a1 に設定して、t0 (CCACHE_SIDEBAND_ADDR) にジャンプします。これで、Zero Stage Boot Loader から First Stage Boot Loader に移行します。

  call main

  li t0, CCACHE_SIDEBAND_ADDR
  csrr a0, mhartid
  la a1, _dtb
  jr t0

ここによると、

x5   t0  一時レジスタ・リンクレジスタ  呼び出し側
x10-x11 a0-a1   引数・戻り値レジスタ  呼び出し側
x12-x17 a2-a7   引数レジスタ  呼び出し側

にあるように、t0 をリンクレジスタ、a0/a1 を引数レジスタとして使っています。

mhardid とは、Hart ID Register でリードオンリーなレジスタのようです。

The mhartid CSR is an MXLEN-bit read-only register containing the integer ID of the hardware thread running the code.

アドレスは、ux00_zsbl.lds にて、設定しています。

First Stage Boot Loader

FSBL のソースコードは、ここにあります。

start.S 内でいろいろやって、main 関数をコールします。

  call main
  tail exit

main.c の main 関数は、下記のような引数を持ちます。第一引数は mhartidの id、第二引数は dtbがストアされている アドレスです。しかしながら、この id は、main 関数内では使われていません。また、dtb も引数の値は使っていません。

int main(int id, unsigned long dtb)

ここで、

  • DDR の初期化
  • GEMGXL の初期化
  • dtbDRAM にコピーする

最後の方で、PAYLOAD_DEST に Second Boot Loader をダウンロードして、slave_main 関数を実行します。

  puts("Loading boot payload");
  ux00boot_load_gpt_partition((void*) PAYLOAD_DEST, &gpt_guid_sifive_bare_metal, peripheral_input_khz);

  puts("\r\n\n");
  slave_main(0, dtb);

slave_main 関数の中で

  • mtvec <= PAYLOAD_DEST
  • a0 <= id (値は 0)
  • a1 <= dtb or dtb_target

にして、mtvec に jump

int slave_main(int id, unsigned long dtb)
{
#ifdef BOARD_SETUP
  while (1)
    ;
#else
  // Wait for the DTB location to become known
  while (!dtb_target) {}

  //wait on barrier, disable sideband then trap to payload at PAYLOAD_DEST
  write_csr(mtvec,PAYLOAD_DEST);

  register int a0 asm("a0") = id;
#ifdef SKIP_DTB_DDR_RANGE
  register unsigned long a1 asm("a1") = dtb;
#else
  register unsigned long a1 asm("a1") = dtb_target;
#endif
  // These next two guys must get inlined and not spill a0+a1 or it is broken!
  Barrier_Wait(&barrier, NUM_CORES);
  ccache_enable_ways(CCACHE_CTRL_ADDR,14);
  asm volatile ("unimp" : : "r"(a0), "r"(a1));
#endif

  return 0;
}

おわりに

ZBSL => FSBL => SBL (Second Bootloader) までの流れがわかりました。

ちなみに、SBLは、OpenSBIになります。

再度、OpenSBI は、ZynqMP の CPUコア、Armv8 の Arm Trusted Firmware に相当するものです。OpenSBIとLinuxについては、

にて、まとめたのでこちらを覗いてみてください。