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と一致させながら検証を実行していかないといけない。これは後日。