From aee945fe0dc17d0ea8d23e93c3f68ac768468be7 Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Thu, 9 Jun 2022 15:35:40 +0800 Subject: [PATCH 1/8] support b_add_p inside montgomery --- arithmetic/src/crypto/modmul/Montgomery.scala | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index beb3794..802952d 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -10,11 +10,11 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val pPrime = IO(Input(Bool())) val a = IO(Input(UInt(pWidth.W))) val b = IO(Input(UInt(pWidth.W))) - val b_add_p = IO(Input(UInt((pWidth + 1).W))) // b + p val valid = IO(Input(Bool())) // input valid val out = IO(Output(UInt(pWidth.W))) val out_valid = IO(Output(Bool())) // output valid + val b_add_p = Reg(UInt((pWidth + 1).W)) val u = Reg(Bool()) val i = Reg(UInt((pWidth).W)) val nextT = Reg(UInt((pWidth + 2).W)) @@ -37,7 +37,7 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { } val state = RegInit(StateType.s0) - val isAdd = (state.asUInt & "b10101110".U).orR + val isAdd = (state.asUInt & "b10101111".U).orR adder.valid := isAdd val addDoneNext = RegInit(false.B) addDoneNext := addDone @@ -71,10 +71,11 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { TruthTable.fromString( Seq( to(s0, valid = N)(s0), - to(s0, valid = Y, a_i = Y, u = N)(s1), - to(s0, valid = Y, a_i = N, u = Y)(s2), - to(s0, valid = Y, a_i = Y, u = Y)(s3), - to(s0, valid = Y, a_i = N, u = N)(s7), + to(s0, valid = Y, addDone = N)(s0), + to(s0, valid = Y, addDone = Y, a_i = Y, u = N)(s1), + to(s0, valid = Y, addDone = Y, a_i = N, u = Y)(s2), + to(s0, valid = Y, addDone = Y, a_i = Y, u = Y)(s3), + to(s0, valid = Y, addDone = Y, a_i = N, u = N)(s7), to(s1, addDone = Y)(s4), to(s1, addDone = N)(s1), to(s2, addDone = Y)(s4), @@ -106,6 +107,8 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { ) ) + b_add_p := Mux(addDone & state.asUInt()(0), debounceAdd, b_add_p) + u := Mux1H( Map( state.asUInt()(0) -> (a(0).asUInt & b(0).asUInt & pPrime.asUInt), @@ -131,17 +134,22 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { ) ) - adder.a := nextT + adder.a := Mux1H( + Map( + state.asUInt()(0) -> p, + (state.asUInt & "b11111110".U).orR -> nextT + ) + ) adder.b := Mux1H( Map( - state.asUInt()(1) -> b, + (state.asUInt & "b00000011".U).orR -> b, state.asUInt()(2) -> p, state.asUInt()(3) -> b_add_p, state.asUInt()(7) -> 0.U, state.asUInt()(5) -> -p ) ) - val debounceAdd = Mux(addDone, adder.z, 0.U) + lazy val debounceAdd = Mux(addDone, adder.z, 0.U) when(addDone)(add_stable := debounceAdd) // output From b51deec1bd3752d8542e5fd02dfc361cad0c7910 Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Thu, 9 Jun 2022 16:35:56 +0800 Subject: [PATCH 2/8] support smaller bit-length to run in hardware with bigger bit-length --- arithmetic/src/crypto/modmul/Montgomery.scala | 19 +++++++++++-------- .../tests/src/crypto/MontgomerySpec.scala | 13 ++++++++----- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index 802952d..fd68362 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -10,6 +10,7 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val pPrime = IO(Input(Bool())) val a = IO(Input(UInt(pWidth.W))) val b = IO(Input(UInt(pWidth.W))) + val input_width = IO(Input(UInt(pWidth.W))) // input_width should be 2^(ceil(log2(p))-1) (i.e., if p = 0b100111, input_width = 0b100000) val valid = IO(Input(Bool())) // input valid val out = IO(Output(UInt(pWidth.W))) val out_valid = IO(Output(Bool())) // output valid @@ -44,9 +45,10 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { lazy val addDone = if (addPipe != 0) Counter(isAdd && (~addDoneNext), addPipe + 1)._2 else true.B val addSign = ((add_stable >> 1) < p.asUInt) val a_i = Reg(Bool()) + val iBreak = (i.asUInt >= input_width.asUInt) state := chisel3.util.experimental.decode .decoder( - state.asUInt() ## addDoneNext ## valid ## i.head(1) ## addSign ## u ## a_i, { + state.asUInt() ## addDoneNext ## valid ## i.head(1) ## iBreak ## addSign ## u ## a_i, { val Y = "1" val N = "0" val DC = "?" @@ -55,11 +57,12 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { addDone: String = DC, valid: String = DC, iHead: String = DC, + iBreak: String = DC, addSign: String = DC, u: String = DC, a_i: String = DC )(stateO: String - ) = s"$stateI$addDone$valid$iHead$addSign$u$a_i->$stateO" + ) = s"$stateI$addDone$valid$iHead$iBreak$addSign$u$a_i->$stateO" val s0 = "00000001" val s1 = "00000010" val s2 = "00000100" @@ -84,12 +87,12 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { to(s3, addDone = N)(s3), to(s7, addDone = Y)(s4), to(s7, addDone = N)(s7), - to(s4, iHead = Y, addSign = N)(s5), - to(s4, iHead = Y, addSign = Y)(s6), - to(s4, iHead = N, a_i = Y, u = N)(s1), - to(s4, iHead = N, a_i = N, u = Y)(s2), - to(s4, iHead = N, a_i = Y, u = Y)(s3), - to(s4, iHead = N, a_i = N, u = N)(s7), + to(s4, iBreak = Y, addSign = N)(s5), + to(s4, iBreak = Y, addSign = Y)(s6), + to(s4, iHead = N, iBreak = N, a_i = Y, u = N)(s1), + to(s4, iHead = N, iBreak = N, a_i = N, u = Y)(s2), + to(s4, iHead = N, iBreak = N, a_i = Y, u = Y)(s3), + to(s4, iHead = N, iBreak = N, a_i = N, u = N)(s7), to(s5, addDone = Y)(s6), to(s5, addDone = N)(s5), "????????" diff --git a/arithmetic/tests/src/crypto/MontgomerySpec.scala b/arithmetic/tests/src/crypto/MontgomerySpec.scala index c28632b..2382c59 100644 --- a/arithmetic/tests/src/crypto/MontgomerySpec.scala +++ b/arithmetic/tests/src/crypto/MontgomerySpec.scala @@ -7,24 +7,27 @@ import utest._ object MontgomerySpec extends TestSuite with ChiselUtestTester { def tests: Tests = Tests { test("Montgomery should pass") { - val u = new Utility() - val length = scala.util.Random.nextInt(20) + 10 // (10, 30) + var u = new Utility() + var length = scala.util.Random.nextInt(20) + 10 // (10, 30) var p = u.randPrime(length) var width = p.toBinaryString.length - var R_inv = u.modinv((scala.math.pow(2, width)).toInt, p) + var R = (scala.math.pow(2, width)).toInt + var R_inv = u.modinv(R, p) var addPipe = scala.util.Random.nextInt(10) + 1 var a = scala.util.Random.nextInt(p) var b = scala.util.Random.nextInt(p) val res = BigInt(a) * BigInt(b) * BigInt(R_inv) % BigInt(p) + var R_div_2 = (scala.math.pow(2, width-1)).toInt + var random_width = scala.util.Random.nextInt(20) + 10 // to test if bigger length hardware can support smaller length number - testCircuit(new Montgomery(width, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => + testCircuit(new Montgomery(width+random_width, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => dut.clock.setTimeout(0) dut.p.poke(p.U) dut.pPrime.poke(true.B) dut.a.poke(a.U) dut.b.poke(b.U) - dut.b_add_p.poke((p+b).U) + dut.input_width.poke(R_div_2.U) dut.clock.step() dut.clock.step() // delay two cycles then set valid = true From 4905f6faf7a4fc06e1b7f82c6e875cb24864ab87 Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Thu, 9 Jun 2022 17:00:05 +0800 Subject: [PATCH 3/8] reformat --- arithmetic/src/crypto/modmul/Montgomery.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index fd68362..964e04f 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -10,7 +10,10 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val pPrime = IO(Input(Bool())) val a = IO(Input(UInt(pWidth.W))) val b = IO(Input(UInt(pWidth.W))) - val input_width = IO(Input(UInt(pWidth.W))) // input_width should be 2^(ceil(log2(p))-1) (i.e., if p = 0b100111, input_width = 0b100000) + val input_width = + IO( + Input(UInt(pWidth.W)) + ) // input_width should be 2^(ceil(log2(p))-1) (i.e., if p = 0b100111, input_width = 0b100000) val valid = IO(Input(Bool())) // input valid val out = IO(Output(UInt(pWidth.W))) val out_valid = IO(Output(Bool())) // output valid From 16c526140d17c9906e09aff28cb44e93b4003fe9 Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Fri, 10 Jun 2022 13:51:37 +0800 Subject: [PATCH 4/8] replace when with Mux --- arithmetic/src/crypto/modmul/Montgomery.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index 964e04f..16e675d 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -156,7 +156,7 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { ) ) lazy val debounceAdd = Mux(addDone, adder.z, 0.U) - when(addDone)(add_stable := debounceAdd) + add_stable := Mux(addDone, debounceAdd, add_stable) // output out := nextT From 4aece41f2b5149559ad0558a24b1d12451a9a58c Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Thu, 28 Jul 2022 19:42:02 +0800 Subject: [PATCH 5/8] fix bug in adder, should connect to the same valid signal of mmm --- arithmetic/src/crypto/modmul/Montgomery.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index 16e675d..f283a60 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -45,7 +45,7 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { adder.valid := isAdd val addDoneNext = RegInit(false.B) addDoneNext := addDone - lazy val addDone = if (addPipe != 0) Counter(isAdd && (~addDoneNext), addPipe + 1)._2 else true.B + lazy val addDone = if (addPipe != 0) Counter(valid && isAdd && (~addDoneNext), addPipe + 1)._2 else true.B val addSign = ((add_stable >> 1) < p.asUInt) val a_i = Reg(Bool()) val iBreak = (i.asUInt >= input_width.asUInt) From 41f707acd025d46d2177c4a87a9ad9e257ed8c78 Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Sat, 20 Aug 2022 08:25:43 +0800 Subject: [PATCH 6/8] fix --- arithmetic/src/crypto/modmul/Montgomery.scala | 2 ++ .../tests/src/crypto/MontgomerySpec.scala | 35 ++++++++++++------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index f283a60..3c3f6b5 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -98,6 +98,8 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { to(s4, iHead = N, iBreak = N, a_i = N, u = N)(s7), to(s5, addDone = Y)(s6), to(s5, addDone = N)(s5), + to(s6, valid = N)(s0), + to(s6, valid = Y)(s6), "????????" ).mkString("\n") ) diff --git a/arithmetic/tests/src/crypto/MontgomerySpec.scala b/arithmetic/tests/src/crypto/MontgomerySpec.scala index 2382c59..0e8110f 100644 --- a/arithmetic/tests/src/crypto/MontgomerySpec.scala +++ b/arithmetic/tests/src/crypto/MontgomerySpec.scala @@ -9,19 +9,30 @@ object MontgomerySpec extends TestSuite with ChiselUtestTester { test("Montgomery should pass") { var u = new Utility() var length = scala.util.Random.nextInt(20) + 10 // (10, 30) - var p = u.randPrime(length) - - var width = p.toBinaryString.length - var R = (scala.math.pow(2, width)).toInt - var R_inv = u.modinv(R, p) - var addPipe = scala.util.Random.nextInt(10) + 1 - var a = scala.util.Random.nextInt(p) - var b = scala.util.Random.nextInt(p) - val res = BigInt(a) * BigInt(b) * BigInt(R_inv) % BigInt(p) - var R_div_2 = (scala.math.pow(2, width-1)).toInt - var random_width = scala.util.Random.nextInt(20) + 10 // to test if bigger length hardware can support smaller length number + // var p = u.randPrime(length) + // var a = scala.util.Random.nextInt(p) + // var b = scala.util.Random.nextInt(p) + var a = BigInt("643") + var b = BigInt("3249") + var p = BigInt("3323") - testCircuit(new Montgomery(width+random_width, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => + // var width = p.toBinaryString.length + var width = 64 + // var R = (scala.math.pow(2, width)).toInt + // var R_inv = u.modinv(R, p) + var R = BigInt("4294967296") + var R_inv = BigInt("806") + // var addPipe = scala.util.Random.nextInt(10) + 1 + var addPipe = 10 + println("addPipe", addPipe) + // val res = BigInt(a) * BigInt(b) * BigInt(R_inv) % BigInt(p) + val res = (a) * (b) * (R_inv) % (p) + // var R_div_2 = (scala.math.pow(2, width-1)).toInt + var R_div_2 = (R) / BigInt(2) + // var random_width = scala.util.Random.nextInt(20) + 10 // to test if bigger length hardware can support smaller length number + var random_width = 0 + println(width, random_width) + testCircuit(new Montgomery(64, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => dut.clock.setTimeout(0) dut.p.poke(p.U) dut.pPrime.poke(true.B) From da6114ca49bb93d66656935ef3f6c77bab3e97eb Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Sun, 21 Aug 2022 00:37:19 +0800 Subject: [PATCH 7/8] remove comparator --- arithmetic/src/crypto/modmul/Montgomery.scala | 80 +++++++----- .../tests/src/crypto/MontgomerySpec.scala | 119 +++++++++++------- 2 files changed, 122 insertions(+), 77 deletions(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index 3c3f6b5..5773081 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -3,7 +3,7 @@ package crypto.modmul import chisel3._ import chisel3.experimental.ChiselEnum import chisel3.util.experimental.decode.TruthTable -import chisel3.util.{Counter, Mux1H} +import chisel3.util.{Cat, Counter, Mux1H} class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val p = IO(Input(UInt(pWidth.W))) @@ -19,6 +19,8 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val out_valid = IO(Output(Bool())) // output valid val b_add_p = Reg(UInt((pWidth + 1).W)) + val invP = Reg(UInt((pWidth).W)) + val negP = Reg(UInt((pWidth + 2).W)) val u = Reg(Bool()) val i = Reg(UInt((pWidth).W)) val nextT = Reg(UInt((pWidth + 2).W)) @@ -28,30 +30,31 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val add_stable = RegInit(0.U((pWidth + 2).W)) // Control Path object StateType extends ChiselEnum { - val s0 = Value("b0000001".U) // nextT = 0, u = a(0)b(0)pPrime + val s0 = Value("b0000001".U) // nextT = 0, u = a(0)b(0)pPrime, b_add_p = b + p // loop val s1 = Value("b0000010".U) // nextT + b val s2 = Value("b0000100".U) // nextT + p val s3 = Value("b0001000".U) // nextT + b_add_p // loop done val s4 = Value("b0010000".U) // i << 1, u = (nextT(0) + a(i)b(0))pPrime, nextT / 2 - val s5 = Value("b0100000".U) // if-then + val s5 = Value("b0100000".U) // nextT - p val s6 = Value("b1000000".U) // done val s7 = Value("b10000000".U) // nextT + 0 + val s8 = Value("b100000000".U) // calculate ~p + val s9 = Value("b1000000000".U) // calculate ~p + 1 } val state = RegInit(StateType.s0) - val isAdd = (state.asUInt & "b10101111".U).orR + val isAdd = (state.asUInt & "b1010101111".U).orR adder.valid := isAdd val addDoneNext = RegInit(false.B) addDoneNext := addDone lazy val addDone = if (addPipe != 0) Counter(valid && isAdd && (~addDoneNext), addPipe + 1)._2 else true.B - val addSign = ((add_stable >> 1) < p.asUInt) val a_i = Reg(Bool()) val iBreak = (i.asUInt >= input_width.asUInt) state := chisel3.util.experimental.decode .decoder( - state.asUInt() ## addDoneNext ## valid ## i.head(1) ## iBreak ## addSign ## u ## a_i, { + state.asUInt() ## addDoneNext ## valid ## i.head(1) ## iBreak ## u ## a_i, { val Y = "1" val N = "0" val DC = "?" @@ -61,27 +64,31 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { valid: String = DC, iHead: String = DC, iBreak: String = DC, - addSign: String = DC, u: String = DC, a_i: String = DC )(stateO: String - ) = s"$stateI$addDone$valid$iHead$iBreak$addSign$u$a_i->$stateO" - val s0 = "00000001" - val s1 = "00000010" - val s2 = "00000100" - val s3 = "00001000" - val s4 = "00010000" - val s5 = "00100000" - val s6 = "01000000" - val s7 = "10000000" + ) = s"$stateI$addDone$valid$iHead$iBreak$u$a_i->$stateO" + val s0 = "0000000001" + val s1 = "0000000010" + val s2 = "0000000100" + val s3 = "0000001000" + val s4 = "0000010000" + val s5 = "0000100000" + val s6 = "0001000000" + val s7 = "0010000000" + val s8 = "0100000000" + val s9 = "1000000000" TruthTable.fromString( Seq( to(s0, valid = N)(s0), to(s0, valid = Y, addDone = N)(s0), - to(s0, valid = Y, addDone = Y, a_i = Y, u = N)(s1), - to(s0, valid = Y, addDone = Y, a_i = N, u = Y)(s2), - to(s0, valid = Y, addDone = Y, a_i = Y, u = Y)(s3), - to(s0, valid = Y, addDone = Y, a_i = N, u = N)(s7), + to(s0, valid = Y, addDone = Y)(s8), + to(s8)(s9), + to(s9, addDone = N)(s9), + to(s9, addDone = Y, a_i = Y, u = N)(s1), + to(s9, addDone = Y, a_i = N, u = Y)(s2), + to(s9, addDone = Y, a_i = Y, u = Y)(s3), + to(s9, addDone = Y, a_i = N, u = N)(s7), to(s1, addDone = Y)(s4), to(s1, addDone = N)(s1), to(s2, addDone = Y)(s4), @@ -90,8 +97,7 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { to(s3, addDone = N)(s3), to(s7, addDone = Y)(s4), to(s7, addDone = N)(s7), - to(s4, iBreak = Y, addSign = N)(s5), - to(s4, iBreak = Y, addSign = Y)(s6), + to(s4, iBreak = Y)(s5), to(s4, iHead = N, iBreak = N, a_i = Y, u = N)(s1), to(s4, iHead = N, iBreak = N, a_i = N, u = Y)(s2), to(s4, iHead = N, iBreak = N, a_i = Y, u = Y)(s3), @@ -100,7 +106,7 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { to(s5, addDone = N)(s5), to(s6, valid = N)(s0), to(s6, valid = Y)(s6), - "????????" + "??????????" ).mkString("\n") ) } @@ -111,7 +117,7 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { Map( state.asUInt()(0) -> 1.U, state.asUInt()(4) -> i.rotateLeft(1), - (state.asUInt & "b11101110".U).orR -> i + (state.asUInt & "b1111101110".U).orR -> i ) ) @@ -120,16 +126,16 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { u := Mux1H( Map( state.asUInt()(0) -> (a(0).asUInt & b(0).asUInt & pPrime.asUInt), - (state.asUInt & "b10001110".U).orR -> ((add_stable(1) + (((a & (i.rotateLeft(1))).orR) & b(0))) & pPrime.asUInt), - (state.asUInt & "b01110000".U).orR -> u + (state.asUInt & "b0010001110".U).orR -> ((add_stable(1) + (((a & (i.rotateLeft(1))).orR) & b(0))) & pPrime.asUInt), + (state.asUInt & "b1101110000".U).orR -> u ) ) a_i := Mux1H( Map( state.asUInt()(0) -> a(0), - (state.asUInt & "b10001110".U).orR -> (a & (i.rotateLeft(1))).orR, - (state.asUInt & "b01110000".U).orR -> a_i + (state.asUInt & "b0010001110".U).orR -> (a & (i.rotateLeft(1))).orR, + (state.asUInt & "b1101110000".U).orR -> a_i ) ) @@ -138,29 +144,37 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { state.asUInt()(0) -> 0.U, state.asUInt()(4) -> (add_stable >> 1), state.asUInt()(5) -> add_stable, - (state.asUInt & "b11001110".U).orR -> nextT + (state.asUInt & "b1111001110".U).orR -> nextT ) ) + val TWithoutSubControl = Reg(UInt(1.W)) + val TWithoutSub = Reg(UInt((pWidth + 2).W)) + TWithoutSubControl := Mux(state.asUInt()(5), 0.U, 1.U) + TWithoutSub := Mux(state.asUInt()(5) && (TWithoutSubControl === 1.U), nextT, TWithoutSub) + invP := Mux(state.asUInt()(8), ~p, invP) + negP := Mux(state.asUInt()(9), add_stable, negP) adder.a := Mux1H( Map( state.asUInt()(0) -> p, - (state.asUInt & "b11111110".U).orR -> nextT + state.asUInt()(9) -> 1.U, + (state.asUInt & "b0111111110".U).orR -> nextT ) ) adder.b := Mux1H( Map( - (state.asUInt & "b00000011".U).orR -> b, + (state.asUInt & "b0100000011".U).orR -> b, + state.asUInt()(9) -> Cat(3.U, invP), state.asUInt()(2) -> p, state.asUInt()(3) -> b_add_p, state.asUInt()(7) -> 0.U, - state.asUInt()(5) -> -p + state.asUInt()(5) -> negP ) ) lazy val debounceAdd = Mux(addDone, adder.z, 0.U) add_stable := Mux(addDone, debounceAdd, add_stable) // output - out := nextT + out := Mux(nextT.head(1).asBool, TWithoutSub, nextT) out_valid := state.asUInt()(6) } diff --git a/arithmetic/tests/src/crypto/MontgomerySpec.scala b/arithmetic/tests/src/crypto/MontgomerySpec.scala index 0e8110f..3fc27ba 100644 --- a/arithmetic/tests/src/crypto/MontgomerySpec.scala +++ b/arithmetic/tests/src/crypto/MontgomerySpec.scala @@ -7,54 +7,85 @@ import utest._ object MontgomerySpec extends TestSuite with ChiselUtestTester { def tests: Tests = Tests { test("Montgomery should pass") { - var u = new Utility() - var length = scala.util.Random.nextInt(20) + 10 // (10, 30) - // var p = u.randPrime(length) - // var a = scala.util.Random.nextInt(p) - // var b = scala.util.Random.nextInt(p) - var a = BigInt("643") - var b = BigInt("3249") - var p = BigInt("3323") - - // var width = p.toBinaryString.length - var width = 64 - // var R = (scala.math.pow(2, width)).toInt - // var R_inv = u.modinv(R, p) - var R = BigInt("4294967296") - var R_inv = BigInt("806") - // var addPipe = scala.util.Random.nextInt(10) + 1 - var addPipe = 10 - println("addPipe", addPipe) - // val res = BigInt(a) * BigInt(b) * BigInt(R_inv) % BigInt(p) - val res = (a) * (b) * (R_inv) % (p) - // var R_div_2 = (scala.math.pow(2, width-1)).toInt - var R_div_2 = (R) / BigInt(2) - // var random_width = scala.util.Random.nextInt(20) + 10 // to test if bigger length hardware can support smaller length number - var random_width = 0 - println(width, random_width) - testCircuit(new Montgomery(64, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => - dut.clock.setTimeout(0) - dut.p.poke(p.U) - dut.pPrime.poke(true.B) - dut.a.poke(a.U) - dut.b.poke(b.U) - dut.input_width.poke(R_div_2.U) - dut.clock.step() - dut.clock.step() - // delay two cycles then set valid = true - dut.valid.poke(true.B) - dut.clock.step() - var flag = false - for(a <- 1 to 1000) { + var specfic_test = false + if (specfic_test) { + var a = BigInt("643") + var b = BigInt("3249") + var p = BigInt("3323") + var width = 64 + var R = BigInt("4294967296") + var R_inv = BigInt("806") + var addPipe = 10 + var res = (a) * (b) * (R_inv) % (p) + var R_div_2 = (R) / BigInt(2) + var random_width = 0 + println("addPipe", addPipe) + println(width, random_width) + println("res = ", res) + testCircuit(new Montgomery(64, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => + dut.clock.setTimeout(0) + dut.p.poke(p.U) + dut.pPrime.poke(true.B) + dut.a.poke(a.U) + dut.b.poke(b.U) + dut.input_width.poke(R_div_2.U) + dut.clock.step() + dut.clock.step() + // delay two cycles then set valid = true + dut.valid.poke(true.B) + dut.clock.step() + var flag = false + for(a <- 1 to 1000) { + dut.clock.step() + if(dut.out_valid.peek().litValue == 1) { + flag = true + // need to wait a cycle because there is s5 -> s6 or s4 -> s6 in the state machine + dut.clock.step() + utest.assert(dut.out.peek().litValue == res) + } + } + utest.assert(flag) + } + } else { + var u = new Utility() + var length = scala.util.Random.nextInt(20) + 10 // (10, 30) + var p = u.randPrime(length) + var a = scala.util.Random.nextInt(p) + var b = scala.util.Random.nextInt(p) + var width = p.toBinaryString.length + var R = (scala.math.pow(2, width)).toInt + var R_inv = u.modinv(R, p) + var addPipe = scala.util.Random.nextInt(10) + 1 + var res = BigInt(a) * BigInt(b) * BigInt(R_inv) % BigInt(p) + var R_div_2 = (scala.math.pow(2, width-1)).toInt + var random_width = scala.util.Random.nextInt(20) + 10 // to test if bigger length hardware can support smaller length number + println("addPipe", addPipe) + println(width, random_width) + println("res = ", res) + testCircuit(new Montgomery(64, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => + dut.clock.setTimeout(0) + dut.p.poke(p.U) + dut.pPrime.poke(true.B) + dut.a.poke(a.U) + dut.b.poke(b.U) + dut.input_width.poke(R_div_2.U) + dut.clock.step() + dut.clock.step() + // delay two cycles then set valid = true + dut.valid.poke(true.B) dut.clock.step() - if(dut.out_valid.peek().litValue == 1) { - flag = true - // need to wait a cycle because there is s5 -> s6 or s4 -> s6 in the state machine + var flag = false + for(a <- 1 to 1000) { dut.clock.step() - utest.assert(dut.out.peek().litValue == res) + if(dut.out_valid.peek().litValue == 1) { + flag = true + // need to wait a cycle because there is s5 -> s6 or s4 -> s6 in the state machine + dut.clock.step() + utest.assert(dut.out.peek().litValue == res) + } } + utest.assert(flag) } - utest.assert(flag) } } } From 8a85a52a2f1c6d897f604468cf48db1b362beb4d Mon Sep 17 00:00:00 2001 From: Lucas-Wye Date: Sun, 21 Aug 2022 09:54:40 +0800 Subject: [PATCH 8/8] replace index counter --- arithmetic/src/crypto/modmul/Montgomery.scala | 55 +++++++++---------- .../tests/src/crypto/MontgomerySpec.scala | 18 ++---- 2 files changed, 31 insertions(+), 42 deletions(-) diff --git a/arithmetic/src/crypto/modmul/Montgomery.scala b/arithmetic/src/crypto/modmul/Montgomery.scala index 5773081..354a283 100644 --- a/arithmetic/src/crypto/modmul/Montgomery.scala +++ b/arithmetic/src/crypto/modmul/Montgomery.scala @@ -10,10 +10,8 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val pPrime = IO(Input(Bool())) val a = IO(Input(UInt(pWidth.W))) val b = IO(Input(UInt(pWidth.W))) - val input_width = - IO( - Input(UInt(pWidth.W)) - ) // input_width should be 2^(ceil(log2(p))-1) (i.e., if p = 0b100111, input_width = 0b100000) + val indexCountBit = 16 + val input_width = IO(Input(UInt(indexCountBit.W))) val valid = IO(Input(Bool())) // input valid val out = IO(Output(UInt(pWidth.W))) val out_valid = IO(Output(Bool())) // output valid @@ -21,8 +19,8 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val b_add_p = Reg(UInt((pWidth + 1).W)) val invP = Reg(UInt((pWidth).W)) val negP = Reg(UInt((pWidth + 2).W)) - val u = Reg(Bool()) - val i = Reg(UInt((pWidth).W)) + val loop_u = Reg(Bool()) + val index = Reg(UInt(indexCountBit.W)) val nextT = Reg(UInt((pWidth + 2).W)) // multicycle prefixadder @@ -30,13 +28,13 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { val add_stable = RegInit(0.U((pWidth + 2).W)) // Control Path object StateType extends ChiselEnum { - val s0 = Value("b0000001".U) // nextT = 0, u = a(0)b(0)pPrime, b_add_p = b + p + val s0 = Value("b0000001".U) // nextT = 0, loop_u = a(0)b(0)pPrime, b_add_p = b + p // loop val s1 = Value("b0000010".U) // nextT + b val s2 = Value("b0000100".U) // nextT + p val s3 = Value("b0001000".U) // nextT + b_add_p // loop done - val s4 = Value("b0010000".U) // i << 1, u = (nextT(0) + a(i)b(0))pPrime, nextT / 2 + val s4 = Value("b0010000".U) // index += 1, loop_u = (nextT(0) + a(index)b(0))pPrime, nextT / 2 val s5 = Value("b0100000".U) // nextT - p val s6 = Value("b1000000".U) // done val s7 = Value("b10000000".U) // nextT + 0 @@ -51,10 +49,10 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { addDoneNext := addDone lazy val addDone = if (addPipe != 0) Counter(valid && isAdd && (~addDoneNext), addPipe + 1)._2 else true.B val a_i = Reg(Bool()) - val iBreak = (i.asUInt >= input_width.asUInt) + val iBreak = (index.asUInt >= input_width.asUInt) state := chisel3.util.experimental.decode .decoder( - state.asUInt() ## addDoneNext ## valid ## i.head(1) ## iBreak ## u ## a_i, { + state.asUInt() ## addDoneNext ## valid ## iBreak ## loop_u ## a_i, { val Y = "1" val N = "0" val DC = "?" @@ -62,12 +60,11 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { stateI: String, addDone: String = DC, valid: String = DC, - iHead: String = DC, iBreak: String = DC, - u: String = DC, + loop_u: String = DC, a_i: String = DC )(stateO: String - ) = s"$stateI$addDone$valid$iHead$iBreak$u$a_i->$stateO" + ) = s"$stateI$addDone$valid$iBreak$loop_u$a_i->$stateO" val s0 = "0000000001" val s1 = "0000000010" val s2 = "0000000100" @@ -85,10 +82,10 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { to(s0, valid = Y, addDone = Y)(s8), to(s8)(s9), to(s9, addDone = N)(s9), - to(s9, addDone = Y, a_i = Y, u = N)(s1), - to(s9, addDone = Y, a_i = N, u = Y)(s2), - to(s9, addDone = Y, a_i = Y, u = Y)(s3), - to(s9, addDone = Y, a_i = N, u = N)(s7), + to(s9, addDone = Y, a_i = Y, loop_u = N)(s1), + to(s9, addDone = Y, a_i = N, loop_u = Y)(s2), + to(s9, addDone = Y, a_i = Y, loop_u = Y)(s3), + to(s9, addDone = Y, a_i = N, loop_u = N)(s7), to(s1, addDone = Y)(s4), to(s1, addDone = N)(s1), to(s2, addDone = Y)(s4), @@ -98,10 +95,10 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { to(s7, addDone = Y)(s4), to(s7, addDone = N)(s7), to(s4, iBreak = Y)(s5), - to(s4, iHead = N, iBreak = N, a_i = Y, u = N)(s1), - to(s4, iHead = N, iBreak = N, a_i = N, u = Y)(s2), - to(s4, iHead = N, iBreak = N, a_i = Y, u = Y)(s3), - to(s4, iHead = N, iBreak = N, a_i = N, u = N)(s7), + to(s4, iBreak = N, a_i = Y, loop_u = N)(s1), + to(s4, iBreak = N, a_i = N, loop_u = Y)(s2), + to(s4, iBreak = N, a_i = Y, loop_u = Y)(s3), + to(s4, iBreak = N, a_i = N, loop_u = N)(s7), to(s5, addDone = Y)(s6), to(s5, addDone = N)(s5), to(s6, valid = N)(s0), @@ -113,28 +110,28 @@ class Montgomery(pWidth: Int = 4096, addPipe: Int) extends Module { ) .asTypeOf(StateType.Type()) - i := Mux1H( + index := Mux1H( Map( - state.asUInt()(0) -> 1.U, - state.asUInt()(4) -> i.rotateLeft(1), - (state.asUInt & "b1111101110".U).orR -> i + state.asUInt()(0) -> 0.U, + state.asUInt()(4) -> (index + 1.U), + (state.asUInt & "b1111101110".U).orR -> index ) ) b_add_p := Mux(addDone & state.asUInt()(0), debounceAdd, b_add_p) - u := Mux1H( + loop_u := Mux1H( Map( state.asUInt()(0) -> (a(0).asUInt & b(0).asUInt & pPrime.asUInt), - (state.asUInt & "b0010001110".U).orR -> ((add_stable(1) + (((a & (i.rotateLeft(1))).orR) & b(0))) & pPrime.asUInt), - (state.asUInt & "b1101110000".U).orR -> u + (state.asUInt & "b0010001110".U).orR -> ((add_stable(1) + (a(index + 1.U) & b(0))) & pPrime.asUInt), + (state.asUInt & "b1101110000".U).orR -> loop_u ) ) a_i := Mux1H( Map( state.asUInt()(0) -> a(0), - (state.asUInt & "b0010001110".U).orR -> (a & (i.rotateLeft(1))).orR, + (state.asUInt & "b0010001110".U).orR -> a(index + 1.U), (state.asUInt & "b1101110000".U).orR -> a_i ) ) diff --git a/arithmetic/tests/src/crypto/MontgomerySpec.scala b/arithmetic/tests/src/crypto/MontgomerySpec.scala index 3fc27ba..e95e78e 100644 --- a/arithmetic/tests/src/crypto/MontgomerySpec.scala +++ b/arithmetic/tests/src/crypto/MontgomerySpec.scala @@ -13,22 +13,18 @@ object MontgomerySpec extends TestSuite with ChiselUtestTester { var b = BigInt("3249") var p = BigInt("3323") var width = 64 - var R = BigInt("4294967296") - var R_inv = BigInt("806") + var R = BigInt("4096") + var R_inv = BigInt("374") var addPipe = 10 var res = (a) * (b) * (R_inv) % (p) - var R_div_2 = (R) / BigInt(2) var random_width = 0 - println("addPipe", addPipe) - println(width, random_width) - println("res = ", res) testCircuit(new Montgomery(64, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => dut.clock.setTimeout(0) dut.p.poke(p.U) dut.pPrime.poke(true.B) dut.a.poke(a.U) dut.b.poke(b.U) - dut.input_width.poke(R_div_2.U) + dut.input_width.poke((11).U) dut.clock.step() dut.clock.step() // delay two cycles then set valid = true @@ -57,18 +53,14 @@ object MontgomerySpec extends TestSuite with ChiselUtestTester { var R_inv = u.modinv(R, p) var addPipe = scala.util.Random.nextInt(10) + 1 var res = BigInt(a) * BigInt(b) * BigInt(R_inv) % BigInt(p) - var R_div_2 = (scala.math.pow(2, width-1)).toInt var random_width = scala.util.Random.nextInt(20) + 10 // to test if bigger length hardware can support smaller length number - println("addPipe", addPipe) - println(width, random_width) - println("res = ", res) - testCircuit(new Montgomery(64, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => + testCircuit(new Montgomery(width, addPipe), Seq(chiseltest.internal.NoThreadingAnnotation, chiseltest.simulator.WriteVcdAnnotation)){dut: Montgomery => dut.clock.setTimeout(0) dut.p.poke(p.U) dut.pPrime.poke(true.B) dut.a.poke(a.U) dut.b.poke(b.U) - dut.input_width.poke(R_div_2.U) + dut.input_width.poke((width-1).U) dut.clock.step() dut.clock.step() // delay two cycles then set valid = true