FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Chiselでビットコインマイナーを設計してみる(2. ScalaでSHA256の検証プログラムを書く)

f:id:msyksphinz:20180702001454p:plain

SHA256の回路をChiselで開発しようプロジェクト、とりあえず基本的な回路は記述したので、次に検証用のテストコードを書いていく。

検証用のテストコードはScalaで書く。その方がChiselと親和性が良いし、検証が行いやすいと思う。

という訳で、とりあえずScalaでSHA256のアルゴリズムを記述してみた。

ハマったのはScalaにはUnsigned Intが存在しないこと。とりあえず、BigIntで記述してそれを最後にすべて0xffffffffULで切り取ることでUnsigned Intと同等の処理になるように変換した。

  def scala_test() {
    val Ks = Array[BigInt](
...
    )

    val data = Array[BigInt](BigInt(0x61626380L), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

    def Rot(x: BigInt, rot: Int): BigInt = {
      return ((x << (32-rot)) | (x >> rot)) & BigInt(0x0ffffffffL)
    }
    def SIGMA_0(x: BigInt): BigInt = {
      return (Rot(x, 2) ^ Rot(x, 13) ^ Rot(x, 22)) & BigInt(0x0ffffffffL)
    }
    def SIGMA_1(x: BigInt): BigInt = {
      return (Rot(x, 6) ^ Rot(x, 11) ^ Rot(x, 25)) & BigInt(0x0ffffffffL)
    }
    def S_0(x: BigInt): BigInt = {
      return (Rot(x, 7) ^ Rot(x, 18) ^ (x >> 3)) & BigInt(0x0ffffffffL)
    }
    def S_1(x: BigInt): BigInt = {
      return (Rot(x, 17) ^ Rot(x, 19) ^ (x >> 10)) & BigInt(0x0ffffffffL)
    }
    def CH(x: BigInt, y: BigInt, z: BigInt): BigInt = {
      return ((x & y) ^ (~x & z)) & BigInt(0x0ffffffffL)
    }
    def MAJ(x: BigInt,y: BigInt, z: BigInt): BigInt = {
      return ((x & y) ^ (x & z) ^ (y & z)) & BigInt(0x0ffffffffL)
    }

    val w = new Array[BigInt](64)
    for (t <- 0 until 16) {
      w(t) = data(t)
    }
    for (t <- 16 until 64) {
      w(t) = S_1(w(t-2)) + w(t-7) + S_0(w(t-15)) + w(t-16)
    }

    var a: BigInt = BigInt(0x06a09e667L)
    var b: BigInt = BigInt(0x0bb67ae85L)
    var c: BigInt = BigInt(0x03c6ef372L)
    var d: BigInt = BigInt(0x0a54ff53aL)
    var e: BigInt = BigInt(0x0510e527fL)
    var f: BigInt = BigInt(0x09b05688cL)
    var g: BigInt = BigInt(0x01f83d9abL)
    var h: BigInt = BigInt(0x05be0cd19L)

    for (t <- 0 until 1) {
      val t1 = (h + SIGMA_1(e) + CH(e, f, g) + Ks(t) + w(t)) & BigInt(0x0ffffffffL)
      val t2 = (SIGMA_0(a) + MAJ(a, b, c)) & BigInt(0x0ffffffffL)

      h = g
      g = f
      f = e
      e = (d + t1) & BigInt(0x0ffffffffL)
      d = c
      c = b
      b = a
      a = (t1 + t2) & BigInt(0x0ffffffffL)

      printf("a = %x, b = %x, c = %x, d = %x, ", a, b, c, d)
      printf("e = %x, f = %x, g = %x, h = %x, ", e, f, g, h)
      printf("\n")
    }
  }

とりあえずここまでは良いが、次にChiselと一致させながら検証を実行していかないといけない。これは後日。