xref: /XiangShan/src/main/scala/device/MemEncrypt.scala (revision 11269ca741bcbed259cf718605d4720728016f90)
18882eb68SXin Tian/***************************************************************************************
28882eb68SXin Tian* Copyright (c) 2024-2025 Institute of Information Engineering, Chinese Academy of Sciences
38882eb68SXin Tian*
48882eb68SXin Tian* XiangShan is licensed under Mulan PSL v2.
58882eb68SXin Tian* You can use this software according to the terms and conditions of the Mulan PSL v2.
68882eb68SXin Tian* You may obtain a copy of Mulan PSL v2 at:
78882eb68SXin Tian*          http://license.coscl.org.cn/MulanPSL2
88882eb68SXin Tian*
98882eb68SXin Tian* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
108882eb68SXin Tian* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
118882eb68SXin Tian* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
128882eb68SXin Tian*
138882eb68SXin Tian* See the Mulan PSL v2 for more details.
148882eb68SXin Tian***************************************************************************************/
158882eb68SXin Tian
168882eb68SXin Tianpackage device
178882eb68SXin Tian
188882eb68SXin Tianimport chisel3._
198882eb68SXin Tianimport chisel3.util._
208882eb68SXin Tianimport chisel3.util.HasBlackBoxResource
218882eb68SXin Tianimport org.chipsalliance.cde.config.Field
228882eb68SXin Tianimport org.chipsalliance.cde.config.Parameters
238882eb68SXin Tianimport freechips.rocketchip.amba.axi4._
248882eb68SXin Tianimport freechips.rocketchip.diplomacy._
258882eb68SXin Tianimport freechips.rocketchip.util._
268882eb68SXin Tianimport freechips.rocketchip.amba.apb._
278882eb68SXin Tianimport freechips.rocketchip.tilelink.AXI4TLState
288882eb68SXin Tianimport javax.xml.crypto.dsig.keyinfo.KeyInfo
298882eb68SXin Tianimport system._
308882eb68SXin Tian
318882eb68SXin Tiancase object MemcEdgeInKey extends Field[AXI4EdgeParameters]
328882eb68SXin Tiancase object MemcEdgeOutKey extends Field[AXI4EdgeParameters]
338882eb68SXin Tian
348882eb68SXin Tiantrait Memconsts {
358882eb68SXin Tian  val p: Parameters
368882eb68SXin Tian  val cvm = p(CVMParamskey)
378882eb68SXin Tian  val soc = p(SoCParamsKey)
388882eb68SXin Tian  val PAddrBits= soc.PAddrBits
398882eb68SXin Tian  val KeyIDBits= cvm.KeyIDBits
408882eb68SXin Tian  val MemencPipes = cvm.MemencPipes
418882eb68SXin Tian  lazy val MemcedgeIn = p(MemcEdgeInKey)
428882eb68SXin Tian  lazy val MemcedgeOut = p(MemcEdgeOutKey)
438882eb68SXin Tian  require (isPow2(MemencPipes), s"AXI4MemEncrypt: MemencPipes must be a power of two, not $MemencPipes")
448882eb68SXin Tian  require (PAddrBits > KeyIDBits, s"AXI4MemEncrypt: PAddrBits must be greater than KeyIDBits")
458882eb68SXin Tian  def HasDelayNoencryption = cvm.HasDelayNoencryption
468882eb68SXin Tian}
478882eb68SXin Tian
488882eb68SXin Tian
498882eb68SXin Tianabstract class MemEncryptModule(implicit val p: Parameters) extends Module with Memconsts
508882eb68SXin Tian
518882eb68SXin Tianclass TweakEncrptyQueue(implicit p: Parameters) extends MemEncryptModule
528882eb68SXin Tian{
538882eb68SXin Tian  val io = IO(new Bundle {
548882eb68SXin Tian    val enq = Flipped(DecoupledIO(new Bundle {
558882eb68SXin Tian      val addr = UInt(PAddrBits.W)
568882eb68SXin Tian      val len  = UInt(MemcedgeIn.bundle.lenBits.W)  // number of beats - 1
578882eb68SXin Tian    }))
588882eb68SXin Tian    val deq = DecoupledIO(new Bundle {
598882eb68SXin Tian      val keyid = UInt(KeyIDBits.W)
608882eb68SXin Tian      val tweak = UInt(MemcedgeIn.bundle.dataBits.W)
618882eb68SXin Tian      val addr = UInt(MemcedgeIn.bundle.addrBits.W)
628882eb68SXin Tian    })
638882eb68SXin Tian    val tweak_round_keys = Input(Vec(32, UInt(32.W)))
648882eb68SXin Tian  })
658882eb68SXin Tian    val tweak_in = Cat(0.U((128 - PAddrBits).W), Cat(io.enq.bits.addr(PAddrBits - 1, 6), 0.U(6.W)))
668882eb68SXin Tian
678882eb68SXin Tian    val tweak_enc_module = Module(new TweakEncrypt(opt = true))
688882eb68SXin Tian    val tweakgf128_module = Module(new TweakGF128())
698882eb68SXin Tian
708882eb68SXin Tian    tweak_enc_module.io.tweak_enc_req.valid           := io.enq.valid
718882eb68SXin Tian    tweak_enc_module.io.tweak_enc_resp.ready          := tweakgf128_module.io.req.ready
728882eb68SXin Tian    tweak_enc_module.io.tweak_enc_req.bits.tweak             := tweak_in
738882eb68SXin Tian    tweak_enc_module.io.tweak_enc_req.bits.addr_in           := io.enq.bits.addr
748882eb68SXin Tian    tweak_enc_module.io.tweak_enc_req.bits.len_in            := io.enq.bits.len
758882eb68SXin Tian    tweak_enc_module.io.tweak_enc_req.bits.id_in             := 0.U
768882eb68SXin Tian    tweak_enc_module.io.tweak_enc_req.bits.tweak_round_keys  := io.tweak_round_keys
778882eb68SXin Tian
788882eb68SXin Tian    io.enq.ready := tweak_enc_module.io.tweak_enc_req.ready
798882eb68SXin Tian
808882eb68SXin Tian    tweakgf128_module.io.req.bits.len      := tweak_enc_module.io.tweak_enc_resp.bits.len_out
818882eb68SXin Tian    tweakgf128_module.io.req.bits.addr     := tweak_enc_module.io.tweak_enc_resp.bits.addr_out
828882eb68SXin Tian    tweakgf128_module.io.req.bits.tweak_in := tweak_enc_module.io.tweak_enc_resp.bits.tweak_encrpty
838882eb68SXin Tian    tweakgf128_module.io.req.valid         := tweak_enc_module.io.tweak_enc_resp.valid
848882eb68SXin Tian    tweakgf128_module.io.resp.ready        := io.deq.ready
858882eb68SXin Tian
868882eb68SXin Tian    io.deq.bits.keyid := tweakgf128_module.io.resp.bits.keyid_out
878882eb68SXin Tian    io.deq.bits.tweak := tweakgf128_module.io.resp.bits.tweak_out
888882eb68SXin Tian    io.deq.bits.addr  := tweakgf128_module.io.resp.bits.addr_out
898882eb68SXin Tian    io.deq.valid      := tweakgf128_module.io.resp.valid
908882eb68SXin Tian}
918882eb68SXin Tian
928882eb68SXin Tianclass AXI4W_KT(opt:Boolean)(implicit val p: Parameters) extends Bundle with Memconsts
938882eb68SXin Tian{
948882eb68SXin Tian  val edgeUse = if (opt) MemcedgeIn else MemcedgeOut
958882eb68SXin Tian  val axi4 = new AXI4BundleW(edgeUse.bundle)
968882eb68SXin Tian  val keyid = UInt(KeyIDBits.W)
978882eb68SXin Tian  val tweak = UInt(edgeUse.bundle.dataBits.W)
988882eb68SXin Tian}
998882eb68SXin Tian
1008882eb68SXin Tian// Used to indicate the source of the req (L1I/L1D/PTW)
1018882eb68SXin Tiancase object ReqSourceKey extends ControlKey[UInt]("reqSource")
1028882eb68SXin Tian
1038882eb68SXin Tianclass AXI4WriteMachine(implicit p: Parameters) extends MemEncryptModule
1048882eb68SXin Tian{
1058882eb68SXin Tian  val io = IO(new Bundle {
1068882eb68SXin Tian    val in_w = Flipped(Irrevocable(new AXI4BundleW(MemcedgeOut.bundle)))
1078882eb68SXin Tian    val in_kt = Flipped(DecoupledIO(new Bundle {
1088882eb68SXin Tian      val keyid = UInt(KeyIDBits.W)
1098882eb68SXin Tian      val tweak = UInt(MemcedgeOut.bundle.dataBits.W)
1108882eb68SXin Tian      val addr = UInt(MemcedgeOut.bundle.addrBits.W)
1118882eb68SXin Tian    }))
1128882eb68SXin Tian    val out_ar = Irrevocable(new AXI4BundleAR(MemcedgeOut.bundle))
1138882eb68SXin Tian    val in_r = Flipped(Irrevocable(new AXI4BundleR(MemcedgeOut.bundle)))
1148882eb68SXin Tian    val out_w = DecoupledIO(new AXI4W_KT(true))
1158882eb68SXin Tian    val uncache_en = Output(Bool())
1168882eb68SXin Tian    val uncache_commit = Input(Bool())
1178882eb68SXin Tian  })
1188882eb68SXin Tian  // ----------------
1198882eb68SXin Tian  // s0 stage
1208882eb68SXin Tian  // ----------------
1218882eb68SXin Tian  val w_cacheable = io.in_w.bits.strb.andR
1228882eb68SXin Tian
1238882eb68SXin Tian  // ----------------
1248882eb68SXin Tian  // s1 stage
1258882eb68SXin Tian  // ----------------
1268882eb68SXin Tian  val in_w_v   = RegInit(false.B)
1278882eb68SXin Tian  val in_kt_v  = RegInit(false.B)
1288882eb68SXin Tian
1298882eb68SXin Tian  val in_w_req  = RegEnable(io.in_w.bits, io.in_w.fire)
1308882eb68SXin Tian  val in_kt_req = RegEnable(io.in_kt.bits, io.in_kt.fire)
1318882eb68SXin Tian  io.in_w.ready := !in_w_v || io.out_w.fire
1328882eb68SXin Tian  io.in_kt.ready := !in_kt_v || io.out_w.fire
1338882eb68SXin Tian
1348882eb68SXin Tian  when(io.in_w.fire) {
1358882eb68SXin Tian    in_w_v := true.B
1368882eb68SXin Tian  }.elsewhen(io.out_w.fire) {
1378882eb68SXin Tian    in_w_v := false.B
1388882eb68SXin Tian  }.otherwise {
1398882eb68SXin Tian    in_w_v := in_w_v
1408882eb68SXin Tian  }
1418882eb68SXin Tian
1428882eb68SXin Tian  when(io.in_kt.fire) {
1438882eb68SXin Tian    in_kt_v := true.B
1448882eb68SXin Tian  }.elsewhen(io.out_w.fire) {
1458882eb68SXin Tian    in_kt_v := false.B
1468882eb68SXin Tian  }.otherwise {
1478882eb68SXin Tian    in_kt_v := in_kt_v
1488882eb68SXin Tian  }
1498882eb68SXin Tian
1508882eb68SXin Tian  // -----------------------------
1518882eb68SXin Tian  // s2 stage only uncacheable use
1528882eb68SXin Tian  // -----------------------------
1538882eb68SXin Tian  val out_ar_v = RegInit(false.B)
1548882eb68SXin Tian  val out_ar_mask = RegInit(false.B)
1558882eb68SXin Tian  val in_r_v   = RegInit(false.B)
1568882eb68SXin Tian  val r_uncache_en = RegInit(false.B)
1578882eb68SXin Tian  when(io.in_r.fire) {
1588882eb68SXin Tian    in_r_v := true.B
1598882eb68SXin Tian  }.elsewhen(io.out_w.fire) {
1608882eb68SXin Tian    in_r_v := false.B
1618882eb68SXin Tian  }.otherwise {
1628882eb68SXin Tian    in_r_v := in_r_v
1638882eb68SXin Tian  }
1648882eb68SXin Tian
1658882eb68SXin Tian  when(io.in_r.fire) {
1668882eb68SXin Tian    r_uncache_en := true.B
1678882eb68SXin Tian  }.elsewhen(io.uncache_commit) {
1688882eb68SXin Tian    r_uncache_en := false.B
1698882eb68SXin Tian  }.otherwise {
1708882eb68SXin Tian    r_uncache_en := r_uncache_en
1718882eb68SXin Tian  }
1728882eb68SXin Tian
1738882eb68SXin Tian  io.in_r.ready := !r_uncache_en || io.uncache_commit
1748882eb68SXin Tian  io.uncache_en := r_uncache_en
1758882eb68SXin Tian
1768882eb68SXin Tian  val s1_w_cacheable = RegEnable(w_cacheable, io.in_w.fire)
1778882eb68SXin Tian
1788882eb68SXin Tian  when(in_w_v && in_kt_v && !s1_w_cacheable && !out_ar_mask) {
1798882eb68SXin Tian    out_ar_v := true.B
1808882eb68SXin Tian  }.elsewhen(io.out_ar.fire) {
1818882eb68SXin Tian    out_ar_v := false.B
1828882eb68SXin Tian  }.otherwise {
1838882eb68SXin Tian    out_ar_v := out_ar_v
1848882eb68SXin Tian  }
1858882eb68SXin Tian
1868882eb68SXin Tian  when(in_w_v && in_kt_v && !s1_w_cacheable && !out_ar_mask) {
1878882eb68SXin Tian    out_ar_mask := true.B
1888882eb68SXin Tian  }.elsewhen(io.out_w.fire) {
1898882eb68SXin Tian    out_ar_mask := false.B
1908882eb68SXin Tian  }.otherwise {
1918882eb68SXin Tian    out_ar_mask := out_ar_mask
1928882eb68SXin Tian  }
1938882eb68SXin Tian
1948882eb68SXin Tian  io.out_ar.valid := out_ar_v
1958882eb68SXin Tian  val ar = io.out_ar.bits
1968882eb68SXin Tian  ar.id    := 1.U << (MemcedgeOut.bundle.idBits - 1)
1978882eb68SXin Tian  ar.addr  := (in_kt_req.addr >> log2Ceil(MemcedgeOut.bundle.dataBits/8)) << log2Ceil(MemcedgeOut.bundle.dataBits/8)
1988882eb68SXin Tian  ar.len   := 0.U
1998882eb68SXin Tian  ar.size  := log2Ceil(MemcedgeOut.bundle.dataBits/8).U
2008882eb68SXin Tian  ar.burst := AXI4Parameters.BURST_INCR
2018882eb68SXin Tian  ar.lock  := 0.U // not exclusive (LR/SC unsupported b/c no forward progress guarantee)
2028882eb68SXin Tian  ar.cache := 0.U // do not allow AXI to modify our transactions
2038882eb68SXin Tian  ar.prot  := AXI4Parameters.PROT_PRIVILEGED
2048882eb68SXin Tian  ar.qos   := 0.U // no QoS
2058882eb68SXin Tian  if (MemcedgeOut.bundle.echoFields != Nil) {
2068882eb68SXin Tian    val ar_extra = ar.echo(AXI4TLState)
2078882eb68SXin Tian      ar_extra.source := 0.U
2088882eb68SXin Tian      ar_extra.size   := 0.U
2098882eb68SXin Tian  }
2108882eb68SXin Tian  if (MemcedgeOut.bundle.requestFields != Nil) {
2118882eb68SXin Tian    val ar_user = ar.user(ReqSourceKey)
2128882eb68SXin Tian      ar_user := 0.U
2138882eb68SXin Tian  }
2148882eb68SXin Tian
2158882eb68SXin Tian  def gen_wmask(strb: UInt): UInt = {
2168882eb68SXin Tian    val extendedBits = VecInit((0 until MemcedgeOut.bundle.dataBits/8).map(i => Cat(Fill(7, strb((MemcedgeOut.bundle.dataBits/8)-1-i)), strb((MemcedgeOut.bundle.dataBits/8)-1-i))))
2178882eb68SXin Tian    extendedBits.reduce(_ ## _)
2188882eb68SXin Tian  }
2198882eb68SXin Tian
2208882eb68SXin Tian  val new_data = Reg(UInt(MemcedgeOut.bundle.dataBits.W))
2218882eb68SXin Tian  val new_strb = ~0.U((MemcedgeOut.bundle.dataBits/8).W)
2228882eb68SXin Tian  val wmask = gen_wmask(in_w_req.strb)
2238882eb68SXin Tian
2248882eb68SXin Tian  when(io.in_r.fire) {
2258882eb68SXin Tian    new_data := (io.in_r.bits.data & ~wmask) | (in_w_req.data & wmask)
2268882eb68SXin Tian  }
2278882eb68SXin Tian
2288882eb68SXin Tian  when(s1_w_cacheable) {
2298882eb68SXin Tian    io.out_w.valid := in_w_v && in_kt_v
2308882eb68SXin Tian    io.out_w.bits.axi4 := in_w_req
2318882eb68SXin Tian    io.out_w.bits.keyid := in_kt_req.keyid
2328882eb68SXin Tian    io.out_w.bits.tweak := in_kt_req.tweak
2338882eb68SXin Tian  }.otherwise {
2348882eb68SXin Tian    io.out_w.valid := in_w_v && in_kt_v && in_r_v
2358882eb68SXin Tian    io.out_w.bits.axi4 := in_w_req
2368882eb68SXin Tian    io.out_w.bits.axi4.data := new_data
2378882eb68SXin Tian    io.out_w.bits.axi4.strb := new_strb
2388882eb68SXin Tian    io.out_w.bits.keyid := in_kt_req.keyid
2398882eb68SXin Tian    io.out_w.bits.tweak := in_kt_req.tweak
2408882eb68SXin Tian  }
2418882eb68SXin Tian
2428882eb68SXin Tian}
2438882eb68SXin Tian
2448882eb68SXin Tianclass WdataEncrptyPipe(implicit p: Parameters) extends MemEncryptModule
2458882eb68SXin Tian{
2468882eb68SXin Tian  val io = IO(new Bundle {
2478882eb68SXin Tian    val in_w = Flipped(DecoupledIO(new AXI4W_KT(true)))
2488882eb68SXin Tian    val out_w = Irrevocable(new AXI4BundleW(MemcedgeIn.bundle))
2498882eb68SXin Tian    val enc_keyids = Output(Vec(MemencPipes, UInt(KeyIDBits.W)))
2508882eb68SXin Tian    val enc_round_keys = Input(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
2518882eb68SXin Tian  })
2528882eb68SXin Tian  val reg_encdec_result_0 = Reg(Vec(MemencPipes, UInt(128.W)))
2538882eb68SXin Tian  val reg_encdec_result_1 = Reg(Vec(MemencPipes, UInt(128.W)))
2548882eb68SXin Tian  val reg_axi4_other_result = Reg(Vec(MemencPipes, new AXI4BundleWWithoutData(MemcedgeIn.bundle)))
2558882eb68SXin Tian  val reg_tweak_result_0 = Reg(Vec(MemencPipes, UInt(128.W)))
2568882eb68SXin Tian  val reg_tweak_result_1 = Reg(Vec(MemencPipes, UInt(128.W)))
2578882eb68SXin Tian  val reg_keyid = Reg(Vec(MemencPipes, UInt(KeyIDBits.W)))
2588882eb68SXin Tian  val reg_encdec_valid = RegInit(VecInit(Seq.fill(MemencPipes)(false.B)))
2598882eb68SXin Tian  val wire_ready_result = WireInit(VecInit(Seq.fill(MemencPipes)(false.B)))
2608882eb68SXin Tian
2618882eb68SXin Tian  val wire_axi4_other = Wire(new AXI4BundleWWithoutData(MemcedgeIn.bundle))
2628882eb68SXin Tian  wire_axi4_other.strb := io.in_w.bits.axi4.strb
2638882eb68SXin Tian  wire_axi4_other.last := io.in_w.bits.axi4.last
2648882eb68SXin Tian  wire_axi4_other.user := io.in_w.bits.axi4.user
2658882eb68SXin Tian
2668882eb68SXin Tian
2678882eb68SXin Tian  val pipes_first_data_0 = Wire(UInt(128.W))
2688882eb68SXin Tian  val pipes_first_data_1 = Wire(UInt(128.W))
2698882eb68SXin Tian  if (HasDelayNoencryption) {
2708882eb68SXin Tian    pipes_first_data_0 := io.in_w.bits.axi4.data(127,0)
2718882eb68SXin Tian    pipes_first_data_1 := io.in_w.bits.axi4.data(255,128)
2728882eb68SXin Tian  } else {
2738882eb68SXin Tian    pipes_first_data_0 := io.in_w.bits.axi4.data(127,0) ^ io.in_w.bits.tweak(127, 0)
2748882eb68SXin Tian    pipes_first_data_1 := io.in_w.bits.axi4.data(255,128) ^ io.in_w.bits.tweak(255,128)
2758882eb68SXin Tian  }
2768882eb68SXin Tian
2778882eb68SXin Tian  def configureModule(flag: Boolean, i: Int, keyId: UInt, dataIn: UInt, tweakIn: UInt, axi4In: AXI4BundleWWithoutData, roundKeys: UInt): OnePipeEncBase = {
2788882eb68SXin Tian      when(wire_ready_result(i) && (if (i == 0) io.in_w.valid else reg_encdec_valid(i-1))) {
2798882eb68SXin Tian        reg_encdec_valid(i) := true.B
2808882eb68SXin Tian      }.elsewhen(reg_encdec_valid(i) && (if (i == MemencPipes - 1) io.out_w.ready else wire_ready_result(i + 1))) {
2818882eb68SXin Tian        reg_encdec_valid(i) := false.B
2828882eb68SXin Tian      }.otherwise {
2838882eb68SXin Tian        reg_encdec_valid(i) := reg_encdec_valid(i)
2848882eb68SXin Tian      }
2858882eb68SXin Tian
2868882eb68SXin Tian      wire_ready_result(i) := !reg_encdec_valid(i) || (reg_encdec_valid(i) && (if (i == MemencPipes - 1) io.out_w.ready else wire_ready_result(i+1)))
2878882eb68SXin Tian
2888882eb68SXin Tian      val module: OnePipeEncBase = if (HasDelayNoencryption) Module(new OnePipeForEncNoEnc()) else Module(new OnePipeForEnc())
2898882eb68SXin Tian      module.io.onepipe_in.keyid := keyId
2908882eb68SXin Tian      module.io.onepipe_in.data_in := dataIn
2918882eb68SXin Tian      module.io.onepipe_in.tweak_in := tweakIn
2928882eb68SXin Tian      module.io.onepipe_in.axi4_other := axi4In
2938882eb68SXin Tian      for (i <- 0 until 32/MemencPipes) {
2948882eb68SXin Tian        module.io.onepipe_in.round_key_in(i) := roundKeys(i * 32 + 31, i * 32)
2958882eb68SXin Tian      }
2968882eb68SXin Tian      when((if (i == 0) io.in_w.valid else reg_encdec_valid(i-1)) && wire_ready_result(i)) {
2978882eb68SXin Tian        if (flag) {
2988882eb68SXin Tian          reg_encdec_result_0(i) := module.io.onepipe_out.result_out
2998882eb68SXin Tian          reg_tweak_result_0(i) := module.io.onepipe_out.tweak_out
3008882eb68SXin Tian          reg_axi4_other_result(i) := module.io.onepipe_out.axi4_other_out
3018882eb68SXin Tian          reg_keyid(i) := module.io.onepipe_out.keyid_out
3028882eb68SXin Tian        } else {
3038882eb68SXin Tian          reg_encdec_result_1(i) := module.io.onepipe_out.result_out
3048882eb68SXin Tian          reg_tweak_result_1(i) := module.io.onepipe_out.tweak_out
3058882eb68SXin Tian        }
3068882eb68SXin Tian      }
3078882eb68SXin Tian      io.enc_keyids(i) := module.io.onepipe_out.keyid_out
3088882eb68SXin Tian      module
3098882eb68SXin Tian  }
3108882eb68SXin Tian  val modules_0 = (0 until MemencPipes).map { i =>
3118882eb68SXin Tian    if (i == 0) {
3128882eb68SXin Tian      configureModule(true, i, io.in_w.bits.keyid, pipes_first_data_0, io.in_w.bits.tweak(127, 0), wire_axi4_other, io.enc_round_keys(i))
3138882eb68SXin Tian    } else {
3148882eb68SXin Tian      configureModule(true, i, reg_keyid(i-1), reg_encdec_result_0(i-1), reg_tweak_result_0(i-1), reg_axi4_other_result(i-1), io.enc_round_keys(i))
3158882eb68SXin Tian    }
3168882eb68SXin Tian  }
3178882eb68SXin Tian  val modules_1 = (0 until MemencPipes).map { i =>
3188882eb68SXin Tian    if (i == 0) {
3198882eb68SXin Tian      configureModule(false, i, io.in_w.bits.keyid, pipes_first_data_1, io.in_w.bits.tweak(255,128), wire_axi4_other, io.enc_round_keys(i))
3208882eb68SXin Tian    } else {
3218882eb68SXin Tian      configureModule(false, i, reg_keyid(i-1), reg_encdec_result_1(i-1), reg_tweak_result_1(i-1), reg_axi4_other_result(i-1), io.enc_round_keys(i))
3228882eb68SXin Tian    }
3238882eb68SXin Tian  }
3248882eb68SXin Tian  if (HasDelayNoencryption) {
3258882eb68SXin Tian    io.out_w.bits.data := Cat(reg_encdec_result_1.last, reg_encdec_result_0.last)
3268882eb68SXin Tian  } else {
3278882eb68SXin Tian    val enc_0_out = Cat(
3288882eb68SXin Tian      reg_encdec_result_0.last(31, 0),
3298882eb68SXin Tian      reg_encdec_result_0.last(63, 32),
3308882eb68SXin Tian      reg_encdec_result_0.last(95, 64),
3318882eb68SXin Tian      reg_encdec_result_0.last(127, 96)
3328882eb68SXin Tian    )
3338882eb68SXin Tian    val enc_1_out = Cat(
3348882eb68SXin Tian      reg_encdec_result_1.last(31, 0),
3358882eb68SXin Tian      reg_encdec_result_1.last(63, 32),
3368882eb68SXin Tian      reg_encdec_result_1.last(95, 64),
3378882eb68SXin Tian      reg_encdec_result_1.last(127, 96)
3388882eb68SXin Tian    )
3398882eb68SXin Tian    io.out_w.bits.data := Cat(enc_1_out ^ reg_tweak_result_1.last, enc_0_out ^ reg_tweak_result_0.last)
3408882eb68SXin Tian  }
3418882eb68SXin Tian
3428882eb68SXin Tian  io.out_w.bits.strb := reg_axi4_other_result.last.strb
3438882eb68SXin Tian  io.out_w.bits.last := reg_axi4_other_result.last.last
3448882eb68SXin Tian  io.out_w.bits.user := reg_axi4_other_result.last.user
3458882eb68SXin Tian  io.out_w.valid := reg_encdec_valid.last
3468882eb68SXin Tian  io.in_w.ready := wire_ready_result(0)
3478882eb68SXin Tian}
3488882eb68SXin Tian
3498882eb68SXin Tianclass TweakEncrptyTable(implicit p: Parameters) extends MemEncryptModule
3508882eb68SXin Tian{
3518882eb68SXin Tian  val io = IO(new Bundle {
3528882eb68SXin Tian    val enq = Flipped(DecoupledIO(new Bundle {
3538882eb68SXin Tian      val addr = UInt(PAddrBits.W)
3548882eb68SXin Tian      val len  = UInt(MemcedgeOut.bundle.lenBits.W)  // number of beats - 1
3558882eb68SXin Tian      val id  = UInt(MemcedgeOut.bundle.idBits.W)    // 7 bits
3568882eb68SXin Tian    }))
3578882eb68SXin Tian    val req = Flipped(DecoupledIO(new Bundle {
3588882eb68SXin Tian      val id  = UInt(MemcedgeOut.bundle.idBits.W)
3598882eb68SXin Tian    }))
3608882eb68SXin Tian    val resp = DecoupledIO(new Bundle {
3618882eb68SXin Tian      val keyid = UInt(KeyIDBits.W)
3628882eb68SXin Tian      val tweak = UInt(MemcedgeOut.bundle.dataBits.W)
3638882eb68SXin Tian    })
3648882eb68SXin Tian    val dec_r = new Bundle {
3658882eb68SXin Tian      val id = Input(UInt(MemcedgeOut.bundle.idBits.W))
3668882eb68SXin Tian      val mode = Output(Bool())
3678882eb68SXin Tian    }
3688882eb68SXin Tian    val dec_keyid = Output(UInt(KeyIDBits.W))
3698882eb68SXin Tian    val dec_mode = Input(Bool())
3708882eb68SXin Tian    val tweak_round_keys = Input(Vec(32, UInt(32.W)))
3718882eb68SXin Tian    val memenc_enable = Input(Bool())
3728882eb68SXin Tian  })
3738882eb68SXin Tian
3748882eb68SXin Tian  val tweak_in = Cat(0.U((128 - PAddrBits).W), Cat(io.enq.bits.addr(PAddrBits-1, 6), 0.U(6.W)))
3758882eb68SXin Tian  // query the dec_mode from the round key
3768882eb68SXin Tian  io.dec_keyid := io.enq.bits.addr(PAddrBits - 1, PAddrBits - KeyIDBits)
3778882eb68SXin Tian
3788882eb68SXin Tian  val tweak_enc_module = Module(new TweakEncrypt(opt = false))
3798882eb68SXin Tian  val tweak_table = Module(new TweakTable())
3808882eb68SXin Tian  val tweak_gf128 = Module(new GF128())
3818882eb68SXin Tian
3828882eb68SXin Tian  // updata mode table
3838882eb68SXin Tian  tweak_table.io.w_mode.bits.id       := io.enq.bits.id
3848882eb68SXin Tian  tweak_table.io.w_mode.bits.dec_mode := io.dec_mode && io.memenc_enable
3858882eb68SXin Tian  tweak_table.io.w_mode.valid         := io.enq.fire
3868882eb68SXin Tian
3878882eb68SXin Tian  tweak_enc_module.io.tweak_enc_resp.ready          := tweak_table.io.write.ready   // always true
3888882eb68SXin Tian  tweak_enc_module.io.tweak_enc_req.bits.tweak             := tweak_in
3898882eb68SXin Tian  tweak_enc_module.io.tweak_enc_req.bits.addr_in           := io.enq.bits.addr
3908882eb68SXin Tian  tweak_enc_module.io.tweak_enc_req.bits.len_in            := io.enq.bits.len
3918882eb68SXin Tian  tweak_enc_module.io.tweak_enc_req.bits.id_in             := io.enq.bits.id
3928882eb68SXin Tian  tweak_enc_module.io.tweak_enc_req.bits.tweak_round_keys  := io.tweak_round_keys
3938882eb68SXin Tian  tweak_enc_module.io.tweak_enc_req.valid                  := io.enq.valid && io.dec_mode && io.memenc_enable
3948882eb68SXin Tian
3958882eb68SXin Tian  io.enq.ready := tweak_enc_module.io.tweak_enc_req.ready
3968882eb68SXin Tian
3978882eb68SXin Tian  // write signal in tweak table
3988882eb68SXin Tian  tweak_table.io.write.valid       := tweak_enc_module.io.tweak_enc_resp.valid
3998882eb68SXin Tian  tweak_table.io.write.bits.id            := tweak_enc_module.io.tweak_enc_resp.bits.id_out
4008882eb68SXin Tian  tweak_table.io.write.bits.addr          := tweak_enc_module.io.tweak_enc_resp.bits.addr_out
4018882eb68SXin Tian  tweak_table.io.write.bits.len           := tweak_enc_module.io.tweak_enc_resp.bits.len_out
4028882eb68SXin Tian  tweak_table.io.write.bits.tweak_encrpty := tweak_enc_module.io.tweak_enc_resp.bits.tweak_encrpty
4038882eb68SXin Tian
4048882eb68SXin Tian  // read signal in tweak table
4058882eb68SXin Tian  tweak_table.io.req.valid   := io.req.valid
4068882eb68SXin Tian  tweak_table.io.resp.ready  := io.resp.ready
4078882eb68SXin Tian
4088882eb68SXin Tian  tweak_table.io.req.bits.read_id := io.req.bits.id
4098882eb68SXin Tian
4108882eb68SXin Tian  val tweak_encrpty = tweak_table.io.resp.bits.read_tweak
4118882eb68SXin Tian  val tweak_counter = tweak_table.io.resp.bits.read_sel_counter
4128882eb68SXin Tian  val keyid         = tweak_table.io.resp.bits.read_keyid
4138882eb68SXin Tian
4148882eb68SXin Tian  tweak_table.io.r_mode.id := io.dec_r.id
4158882eb68SXin Tian  val mode = tweak_table.io.r_mode.dec_mode
4168882eb68SXin Tian  io.dec_r.mode        := mode
4178882eb68SXin Tian
4188882eb68SXin Tian  tweak_gf128.io.tweak_in := tweak_encrpty
4198882eb68SXin Tian  io.resp.bits.tweak := Mux(tweak_counter, tweak_gf128.io.tweak_out(511, 256), tweak_gf128.io.tweak_out(255, 0))
4208882eb68SXin Tian  io.resp.bits.keyid := keyid
4218882eb68SXin Tian  io.resp.valid      := tweak_table.io.resp.valid
4228882eb68SXin Tian  io.req.ready       := tweak_table.io.req.ready
4238882eb68SXin Tian
4248882eb68SXin Tian}
4258882eb68SXin Tian
4268882eb68SXin Tianclass AXI4R_KT(opt:Boolean)(implicit val p: Parameters) extends Bundle with Memconsts
4278882eb68SXin Tian{
4288882eb68SXin Tian  val edgeUse = if (opt) MemcedgeIn else MemcedgeOut
4298882eb68SXin Tian  val axi4 = new AXI4BundleR(edgeUse.bundle)
4308882eb68SXin Tian  val keyid = UInt(KeyIDBits.W)
4318882eb68SXin Tian  val tweak = UInt(edgeUse.bundle.dataBits.W)
4328882eb68SXin Tian}
4338882eb68SXin Tian
4348882eb68SXin Tianclass AXI4ReadMachine(implicit p: Parameters) extends MemEncryptModule
4358882eb68SXin Tian{
4368882eb68SXin Tian  val io = IO(new Bundle {
4378882eb68SXin Tian    val in_r = Flipped(Irrevocable(new AXI4BundleR(MemcedgeOut.bundle)))
4388882eb68SXin Tian    val kt_req = DecoupledIO(new Bundle {
4398882eb68SXin Tian      val id  = UInt(MemcedgeOut.bundle.idBits.W)
4408882eb68SXin Tian    })
4418882eb68SXin Tian    val in_kt = Flipped(DecoupledIO(new Bundle {
4428882eb68SXin Tian      val keyid = UInt(KeyIDBits.W)
4438882eb68SXin Tian      val tweak = UInt(MemcedgeOut.bundle.dataBits.W)
4448882eb68SXin Tian    }))
4458882eb68SXin Tian    val out_r = DecoupledIO(new AXI4R_KT(false))
4468882eb68SXin Tian  })
4478882eb68SXin Tian  val s1_r_val = RegInit(false.B)
4488882eb68SXin Tian  val s1_r_req = RegEnable(io.in_r.bits, io.in_r.fire)
4498882eb68SXin Tian  val s1_r_out_rdy = Wire(Bool())
4508882eb68SXin Tian
4518882eb68SXin Tian  val s2_r_val = RegInit(false.B)
4528882eb68SXin Tian  val s2_r_in_rdy = Wire(Bool())
4538882eb68SXin Tian  val s2_r_req = RegEnable(s1_r_req, s1_r_val && s2_r_in_rdy)
4548882eb68SXin Tian
4558882eb68SXin Tian  // ----------------
4568882eb68SXin Tian  // s0 stage
4578882eb68SXin Tian  // ----------------
4588882eb68SXin Tian  io.in_r.ready := !s1_r_val || (s1_r_val && s1_r_out_rdy)
4598882eb68SXin Tian
4608882eb68SXin Tian  // ----------------
4618882eb68SXin Tian  // s1 stage
4628882eb68SXin Tian  // ----------------
4638882eb68SXin Tian  when(io.in_r.fire) {
4648882eb68SXin Tian    s1_r_val := true.B
4658882eb68SXin Tian  }.elsewhen(s1_r_val && s1_r_out_rdy) {
4668882eb68SXin Tian    s1_r_val := false.B
4678882eb68SXin Tian  }.otherwise {
4688882eb68SXin Tian    s1_r_val := s1_r_val
4698882eb68SXin Tian  }
4708882eb68SXin Tian
4718882eb68SXin Tian  s1_r_out_rdy := s2_r_in_rdy && io.kt_req.ready
4728882eb68SXin Tian  io.kt_req.valid := s1_r_val && s2_r_in_rdy
4738882eb68SXin Tian  io.kt_req.bits.id := s1_r_req.id
4748882eb68SXin Tian
4758882eb68SXin Tian  // ----------------
4768882eb68SXin Tian  // s2 stage
4778882eb68SXin Tian  // ----------------
4788882eb68SXin Tian  when(s1_r_val && s1_r_out_rdy) {
4798882eb68SXin Tian    s2_r_val := true.B
4808882eb68SXin Tian  }.elsewhen(s2_r_val && io.out_r.fire) {
4818882eb68SXin Tian    s2_r_val := false.B
4828882eb68SXin Tian  }.otherwise {
4838882eb68SXin Tian    s2_r_val := s2_r_val
4848882eb68SXin Tian  }
4858882eb68SXin Tian  s2_r_in_rdy := !s2_r_val || io.out_r.fire
4868882eb68SXin Tian
4878882eb68SXin Tian  io.in_kt.ready := io.out_r.fire
4888882eb68SXin Tian
4898882eb68SXin Tian  io.out_r.valid := s2_r_val && io.in_kt.valid
4908882eb68SXin Tian  io.out_r.bits.axi4 := s2_r_req
4918882eb68SXin Tian  io.out_r.bits.keyid := io.in_kt.bits.keyid
4928882eb68SXin Tian  io.out_r.bits.tweak := io.in_kt.bits.tweak
4938882eb68SXin Tian}
4948882eb68SXin Tian
4958882eb68SXin Tianclass RdataDecrptyPipe(implicit p: Parameters) extends MemEncryptModule
4968882eb68SXin Tian{
4978882eb68SXin Tian  val io = IO(new Bundle {
4988882eb68SXin Tian    val in_r = Flipped(DecoupledIO(new AXI4R_KT(false)))
4998882eb68SXin Tian    val out_r = Irrevocable(new AXI4BundleR(MemcedgeOut.bundle))
5008882eb68SXin Tian    val dec_keyids = Output(Vec(MemencPipes, UInt(KeyIDBits.W)))
5018882eb68SXin Tian    val dec_round_keys = Input(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
5028882eb68SXin Tian  })
5038882eb68SXin Tian
5048882eb68SXin Tian  val reg_encdec_result_0 = Reg(Vec(MemencPipes, UInt(128.W)))
5058882eb68SXin Tian  val reg_encdec_result_1 = Reg(Vec(MemencPipes, UInt(128.W)))
5068882eb68SXin Tian  val reg_axi4_other_result = Reg(Vec(MemencPipes, new AXI4BundleRWithoutData(MemcedgeOut.bundle)))
5078882eb68SXin Tian  val reg_tweak_result_0 = Reg(Vec(MemencPipes, UInt(128.W)))
5088882eb68SXin Tian  val reg_tweak_result_1 = Reg(Vec(MemencPipes, UInt(128.W)))
5098882eb68SXin Tian  val reg_keyid = Reg(Vec(MemencPipes, UInt(KeyIDBits.W)))
5108882eb68SXin Tian  val reg_encdec_valid = RegInit(VecInit(Seq.fill(MemencPipes)(false.B)))
5118882eb68SXin Tian  val wire_ready_result = WireInit(VecInit(Seq.fill(MemencPipes)(false.B)))
5128882eb68SXin Tian
5138882eb68SXin Tian
5148882eb68SXin Tian  val wire_axi4_other = Wire(new AXI4BundleRWithoutData(MemcedgeOut.bundle))
5158882eb68SXin Tian  wire_axi4_other.id := io.in_r.bits.axi4.id
5168882eb68SXin Tian  wire_axi4_other.resp := io.in_r.bits.axi4.resp
5178882eb68SXin Tian  wire_axi4_other.user := io.in_r.bits.axi4.user
5188882eb68SXin Tian  wire_axi4_other.echo := io.in_r.bits.axi4.echo
5198882eb68SXin Tian  wire_axi4_other.last := io.in_r.bits.axi4.last
5208882eb68SXin Tian
5218882eb68SXin Tian  val pipes_first_data_0 = Wire(UInt(128.W))
5228882eb68SXin Tian  val pipes_first_data_1 = Wire(UInt(128.W))
5238882eb68SXin Tian
5248882eb68SXin Tian  if (HasDelayNoencryption) {
5258882eb68SXin Tian    pipes_first_data_0 := io.in_r.bits.axi4.data(127,0)
5268882eb68SXin Tian    pipes_first_data_1 := io.in_r.bits.axi4.data(255,128)
5278882eb68SXin Tian  } else {
5288882eb68SXin Tian    pipes_first_data_0 := io.in_r.bits.axi4.data(127,0) ^ io.in_r.bits.tweak(127, 0)
5298882eb68SXin Tian    pipes_first_data_1 := io.in_r.bits.axi4.data(255,128) ^ io.in_r.bits.tweak(255,128)
5308882eb68SXin Tian  }
5318882eb68SXin Tian  def configureModule(flag: Boolean, i: Int, keyId: UInt, dataIn: UInt, tweakIn: UInt, axi4In: AXI4BundleRWithoutData, roundKeys: UInt): OnePipeDecBase = {
5328882eb68SXin Tian
5338882eb68SXin Tian    when(wire_ready_result(i) && (if (i == 0) io.in_r.valid else reg_encdec_valid(i-1))) {
5348882eb68SXin Tian      reg_encdec_valid(i) := true.B
5358882eb68SXin Tian    }.elsewhen(reg_encdec_valid(i) && (if (i == MemencPipes - 1) io.out_r.ready else wire_ready_result(i+1))) {
5368882eb68SXin Tian      reg_encdec_valid(i) := false.B
5378882eb68SXin Tian    }.otherwise {
5388882eb68SXin Tian      reg_encdec_valid(i) := reg_encdec_valid(i)
5398882eb68SXin Tian    }
5408882eb68SXin Tian
5418882eb68SXin Tian    wire_ready_result(i) := !reg_encdec_valid(i) || (reg_encdec_valid(i) && (if (i == MemencPipes - 1) io.out_r.ready else wire_ready_result(i+1)))
5428882eb68SXin Tian
5438882eb68SXin Tian    val module: OnePipeDecBase = if (HasDelayNoencryption) Module(new OnePipeForDecNoDec()) else Module(new OnePipeForDec())
5448882eb68SXin Tian    module.io.onepipe_in.keyid := keyId
5458882eb68SXin Tian    module.io.onepipe_in.data_in := dataIn
5468882eb68SXin Tian    module.io.onepipe_in.tweak_in := tweakIn
5478882eb68SXin Tian    module.io.onepipe_in.axi4_other := axi4In
5488882eb68SXin Tian    for (i <- 0 until 32/MemencPipes) {
5498882eb68SXin Tian      module.io.onepipe_in.round_key_in(i) := roundKeys(i * 32 + 31, i * 32)
5508882eb68SXin Tian    }
5518882eb68SXin Tian    when((if (i == 0) io.in_r.valid else reg_encdec_valid(i-1)) && wire_ready_result(i)) {
5528882eb68SXin Tian      if (flag) {
5538882eb68SXin Tian        reg_encdec_result_0(i) := module.io.onepipe_out.result_out
5548882eb68SXin Tian        reg_tweak_result_0(i) := module.io.onepipe_out.tweak_out
5558882eb68SXin Tian        reg_axi4_other_result(i) := module.io.onepipe_out.axi4_other_out
5568882eb68SXin Tian        reg_keyid(i) := module.io.onepipe_out.keyid_out
5578882eb68SXin Tian      } else {
5588882eb68SXin Tian        reg_encdec_result_1(i) := module.io.onepipe_out.result_out
5598882eb68SXin Tian        reg_tweak_result_1(i) := module.io.onepipe_out.tweak_out
5608882eb68SXin Tian      }
5618882eb68SXin Tian    }
5628882eb68SXin Tian    io.dec_keyids(i)  := module.io.onepipe_out.keyid_out
5638882eb68SXin Tian    module
5648882eb68SXin Tian  }
5658882eb68SXin Tian  val modules_0 = (0 until MemencPipes).map { i =>
5668882eb68SXin Tian    if (i == 0) {
5678882eb68SXin Tian      configureModule(true, i, io.in_r.bits.keyid, pipes_first_data_0, io.in_r.bits.tweak(127, 0), wire_axi4_other, io.dec_round_keys(i))
5688882eb68SXin Tian    } else {
5698882eb68SXin Tian      configureModule(true, i, reg_keyid(i-1), reg_encdec_result_0(i-1), reg_tweak_result_0(i-1), reg_axi4_other_result(i-1), io.dec_round_keys(i))
5708882eb68SXin Tian    }
5718882eb68SXin Tian  }
5728882eb68SXin Tian
5738882eb68SXin Tian  val modules_1 = (0 until MemencPipes).map { i =>
5748882eb68SXin Tian    if (i == 0) {
5758882eb68SXin Tian      configureModule(false, i, io.in_r.bits.keyid, pipes_first_data_1, io.in_r.bits.tweak(255,128), wire_axi4_other,  io.dec_round_keys(i))
5768882eb68SXin Tian    } else {
5778882eb68SXin Tian      configureModule(false, i, reg_keyid(i-1),reg_encdec_result_1(i-1), reg_tweak_result_1(i-1), reg_axi4_other_result(i-1), io.dec_round_keys(i))
5788882eb68SXin Tian    }
5798882eb68SXin Tian  }
5808882eb68SXin Tian  if (HasDelayNoencryption) {
5818882eb68SXin Tian    io.out_r.bits.data := Cat(reg_encdec_result_1.last, reg_encdec_result_0.last)
5828882eb68SXin Tian  } else {
5838882eb68SXin Tian    val enc_0_out = Cat(
5848882eb68SXin Tian      reg_encdec_result_0.last(31, 0),
5858882eb68SXin Tian      reg_encdec_result_0.last(63, 32),
5868882eb68SXin Tian      reg_encdec_result_0.last(95, 64),
5878882eb68SXin Tian      reg_encdec_result_0.last(127, 96)
5888882eb68SXin Tian    )
5898882eb68SXin Tian    val enc_1_out = Cat(
5908882eb68SXin Tian      reg_encdec_result_1.last(31, 0),
5918882eb68SXin Tian      reg_encdec_result_1.last(63, 32),
5928882eb68SXin Tian      reg_encdec_result_1.last(95, 64),
5938882eb68SXin Tian      reg_encdec_result_1.last(127, 96)
5948882eb68SXin Tian    )
5958882eb68SXin Tian    io.out_r.bits.data := Cat(enc_1_out ^ reg_tweak_result_1.last, enc_0_out ^ reg_tweak_result_0.last)
5968882eb68SXin Tian  }
5978882eb68SXin Tian
5988882eb68SXin Tian  io.out_r.bits.id := reg_axi4_other_result.last.id
5998882eb68SXin Tian  io.out_r.bits.resp := reg_axi4_other_result.last.resp
6008882eb68SXin Tian  io.out_r.bits.user := reg_axi4_other_result.last.user
6018882eb68SXin Tian  io.out_r.bits.echo := reg_axi4_other_result.last.echo
6028882eb68SXin Tian  io.out_r.bits.last := reg_axi4_other_result.last.last
6038882eb68SXin Tian  io.out_r.valid := reg_encdec_valid.last
6048882eb68SXin Tian  io.in_r.ready := wire_ready_result(0)
6058882eb68SXin Tian
6068882eb68SXin Tian}
6078882eb68SXin Tian
6088882eb68SXin Tianclass RdataRoute(implicit p: Parameters) extends MemEncryptModule
6098882eb68SXin Tian{
6108882eb68SXin Tian  val io = IO(new Bundle {
6118882eb68SXin Tian    val in_r = Flipped(Irrevocable(new AXI4BundleR(MemcedgeOut.bundle)))
6128882eb68SXin Tian    val out_r0 = Irrevocable(new AXI4BundleR(MemcedgeIn.bundle))
6138882eb68SXin Tian    val out_r1 = Irrevocable(new AXI4BundleR(MemcedgeIn.bundle))
6148882eb68SXin Tian  })
6158882eb68SXin Tian
6168882eb68SXin Tian  val r_sel = io.in_r.bits.id(MemcedgeOut.bundle.idBits - 1).asBool
6178882eb68SXin Tian
6188882eb68SXin Tian  io.out_r0.bits <> io.in_r.bits
6198882eb68SXin Tian  io.out_r1.bits <> io.in_r.bits
6208882eb68SXin Tian
6218882eb68SXin Tian  io.out_r0.valid := io.in_r.valid && !r_sel
6228882eb68SXin Tian  io.out_r1.valid := io.in_r.valid &&  r_sel
6238882eb68SXin Tian  io.in_r.ready := Mux(r_sel, io.out_r1.ready, io.out_r0.ready)
6248882eb68SXin Tian}
6258882eb68SXin Tian
6268882eb68SXin Tianclass MemEncryptCSR(implicit p: Parameters) extends MemEncryptModule
6278882eb68SXin Tian{
6288882eb68SXin Tian  val io = IO(new Bundle {
6298882eb68SXin Tian      val en    = Input(Bool())
6308882eb68SXin Tian      val wmode = Input(Bool())
6318882eb68SXin Tian      val addr  = Input(UInt(12.W))
6328882eb68SXin Tian      val wdata = Input(UInt(64.W))
6338882eb68SXin Tian      val wmask = Input(UInt(8.W))
6348882eb68SXin Tian      val rdata = Output(UInt(64.W))  // get rdata next cycle after en
6358882eb68SXin Tian      val memenc_enable = Output(Bool())
6368882eb68SXin Tian      val keyextend_req = DecoupledIO(new Bundle {
6378882eb68SXin Tian        val key = UInt(128.W)
6388882eb68SXin Tian        val keyid = UInt(KeyIDBits.W)
6398882eb68SXin Tian        val enc_mode = Bool()         // 1:this keyid open enc  0:this keyid close enc
6408882eb68SXin Tian        val tweak_flage = Bool()      // 1:extend tweak key  0:extend keyid key
6418882eb68SXin Tian      })
6428882eb68SXin Tian      val randomio = new Bundle {
6438882eb68SXin Tian        val random_req = Output(Bool())
6448882eb68SXin Tian        val random_val = Input(Bool())
6458882eb68SXin Tian        val random_data = Input(Bool())
6468882eb68SXin Tian      }
6478882eb68SXin Tian  })
6488882eb68SXin Tian  // CSR
6498882eb68SXin Tian  val key_id             = RegInit(0.U(5.W)) // [4:0]
6508882eb68SXin Tian  val mode               = RegInit(0.U(2.W)) // [6:5]
6518882eb68SXin Tian  val tweak_flage        = RegInit(0.U(1.W)) // [7]
6528882eb68SXin Tian  val memenc_enable      = if (HasDelayNoencryption) RegInit(true.B) else RegInit(false.B) // [8]
6538882eb68SXin Tian  val memenc_enable_lock = RegInit(false.B)
6548882eb68SXin Tian  val random_ready_flag  = Wire(Bool()) // [32]
6558882eb68SXin Tian  val key_expansion_idle = Wire(Bool()) // [33]
6568882eb68SXin Tian  val last_req_accepted  = RegInit(false.B) // [34]
6578882eb68SXin Tian  val cfg_succesd        = Wire(Bool()) // [35]
6588882eb68SXin Tian  val key_init_req       = RegInit(false.B) // [63]
6598882eb68SXin Tian  // KEY0&1
6608882eb68SXin Tian  val key0               = RegInit(0.U(64.W))
6618882eb68SXin Tian  val key1               = RegInit(0.U(64.W))
6628882eb68SXin Tian  // RelPaddrBitsMap
6638882eb68SXin Tian  val relpaddrbitsmap    = ~0.U((PAddrBits - KeyIDBits).W)
6648882eb68SXin Tian  // KeyIDBitsMap
6658882eb68SXin Tian  val keyidbitsmap       = ~0.U(PAddrBits.W) - ~0.U((PAddrBits - KeyIDBits).W)
6668882eb68SXin Tian  // Version
6678882eb68SXin Tian  val memenc_version_p0  = (0x0001).U(16.W)
6688882eb68SXin Tian  val memenc_version_p1  = (0x0001).U(16.W)
6698882eb68SXin Tian  val memenc_version_p2  = (0x00000002).U(32.W)
6708882eb68SXin Tian  val memenc_version     = Cat(memenc_version_p0, memenc_version_p1, memenc_version_p2)
6718882eb68SXin Tian
6728882eb68SXin Tian  // READ
6738882eb68SXin Tian  val rdata_reg = RegInit(0.U(64.W))
6748882eb68SXin Tian  when(io.en && !io.wmode && (io.addr(11,3) === 0.U)) {
6758882eb68SXin Tian    rdata_reg := Cat(0.U(28.W), cfg_succesd, last_req_accepted, key_expansion_idle, random_ready_flag, 0.U(23.W), memenc_enable, tweak_flage, mode, key_id)
6768882eb68SXin Tian  }.elsewhen(io.en && !io.wmode && (io.addr(11,3) === 3.U)) {
6778882eb68SXin Tian    rdata_reg := relpaddrbitsmap
6788882eb68SXin Tian  }.elsewhen(io.en && !io.wmode && (io.addr(11,3) === 4.U)) {
6798882eb68SXin Tian    rdata_reg := keyidbitsmap
6808882eb68SXin Tian  }.elsewhen(io.en && !io.wmode && (io.addr(11,3) === 5.U)) {
6818882eb68SXin Tian    rdata_reg := memenc_version
6828882eb68SXin Tian  }.otherwise {
6838882eb68SXin Tian    rdata_reg := 0.U
6848882eb68SXin Tian  }
6858882eb68SXin Tian
6868882eb68SXin Tian  io.rdata := rdata_reg
6878882eb68SXin Tian
6888882eb68SXin Tian  // WRITE
6898882eb68SXin Tian  val wmask_legal = (io.wmask === (0xff).U)
6908882eb68SXin Tian
6918882eb68SXin Tian  when(io.en && io.wmode && wmask_legal && (io.addr(11,3) === 0.U)) {
6928882eb68SXin Tian    key_id := io.wdata(4,0)
6938882eb68SXin Tian    mode := io.wdata(6,5)
6948882eb68SXin Tian    tweak_flage := io.wdata(7)
6958882eb68SXin Tian    key_init_req := io.wdata(63).asBool
6968882eb68SXin Tian  }.otherwise {
6978882eb68SXin Tian    key_init_req := false.B
6988882eb68SXin Tian  }
6998882eb68SXin Tian  when(io.en && io.wmode && wmask_legal && (io.addr(11,3) === 0.U) && (!memenc_enable_lock)) {
7008882eb68SXin Tian    memenc_enable := io.wdata(8)
7018882eb68SXin Tian    memenc_enable_lock := true.B
7028882eb68SXin Tian  }
7038882eb68SXin Tian  when(io.en && io.wmode && wmask_legal && (io.addr(11,3) === 1.U)) {
7048882eb68SXin Tian    key0 := io.wdata
7058882eb68SXin Tian  }
7068882eb68SXin Tian  when(io.en && io.wmode && wmask_legal && (io.addr(11,3) === 2.U)) {
7078882eb68SXin Tian    key1 := io.wdata
7088882eb68SXin Tian  }
7098882eb68SXin Tian  io.memenc_enable := memenc_enable
7108882eb68SXin Tian
7118882eb68SXin Tian  // RANDOM COLLECT
7128882eb68SXin Tian  val random_vec_data = RegInit(0.U(128.W))
7138882eb68SXin Tian  val random_cnt = RegInit(0.U(8.W))
7148882eb68SXin Tian  val random_key_init_done = Wire(Bool())
7158882eb68SXin Tian  io.randomio.random_req := random_cnt =/= 128.U(8.W)
7168882eb68SXin Tian  random_ready_flag := random_cnt === 128.U(8.W)
7178882eb68SXin Tian
7188882eb68SXin Tian  when(io.randomio.random_req && io.randomio.random_val) {
7198882eb68SXin Tian    random_vec_data := Cat(random_vec_data(127,1), io.randomio.random_data)
7208882eb68SXin Tian  }
7218882eb68SXin Tian
7228882eb68SXin Tian  when(random_ready_flag && random_key_init_done) {
7238882eb68SXin Tian    random_cnt := 0.U
7248882eb68SXin Tian  }.elsewhen(io.randomio.random_req && io.randomio.random_val) {
7258882eb68SXin Tian    random_cnt := random_cnt + 1.U
7268882eb68SXin Tian  }
7278882eb68SXin Tian
7288882eb68SXin Tian  // KEY Extend Req
7298882eb68SXin Tian  key_expansion_idle := io.keyextend_req.ready
7308882eb68SXin Tian  cfg_succesd := io.keyextend_req.ready
7318882eb68SXin Tian
7328882eb68SXin Tian  val keyextend_req_valid = RegInit(false.B)
7338882eb68SXin Tian  val req_leagl = Wire(Bool())
7348882eb68SXin Tian  req_leagl := (mode =/= 3.U(2.W)) && key_expansion_idle && ((mode =/= 2.U(2.W)) || random_ready_flag)
7358882eb68SXin Tian
7368882eb68SXin Tian  when(key_init_req && req_leagl) {
7378882eb68SXin Tian    keyextend_req_valid := true.B
7388882eb68SXin Tian  }.elsewhen(io.keyextend_req.fire) {
7398882eb68SXin Tian    keyextend_req_valid := false.B
7408882eb68SXin Tian  }.otherwise {
7418882eb68SXin Tian    keyextend_req_valid := keyextend_req_valid
7428882eb68SXin Tian  }
7438882eb68SXin Tian
7448882eb68SXin Tian  when(key_init_req && req_leagl) {
7458882eb68SXin Tian    last_req_accepted := true.B
7468882eb68SXin Tian  }.elsewhen(key_init_req) {
7478882eb68SXin Tian    last_req_accepted := false.B
7488882eb68SXin Tian  }.otherwise {
7498882eb68SXin Tian    last_req_accepted := last_req_accepted
7508882eb68SXin Tian  }
7518882eb68SXin Tian
7528882eb68SXin Tian  random_key_init_done := io.keyextend_req.fire && (mode === 2.U(2.W))
7538882eb68SXin Tian
7548882eb68SXin Tian  io.keyextend_req.valid := keyextend_req_valid
7558882eb68SXin Tian  io.keyextend_req.bits.key := Mux(mode === 1.U(2.W), Cat(key1, key0), random_vec_data)
7568882eb68SXin Tian  io.keyextend_req.bits.keyid := key_id
7578882eb68SXin Tian  io.keyextend_req.bits.enc_mode := mode =/= 0.U(2.W)
7588882eb68SXin Tian  io.keyextend_req.bits.tweak_flage := tweak_flage.asBool
7598882eb68SXin Tian}
7608882eb68SXin Tian
7618882eb68SXin Tianclass KeyTableEntry extends Bundle {
7628882eb68SXin Tian  val round_key_data = Vec(32, UInt(32.W))
7638882eb68SXin Tian  val encdec_mode = Bool()
7648882eb68SXin Tian}
7658882eb68SXin Tianclass KeyTable(implicit p: Parameters) extends MemEncryptModule {
7668882eb68SXin Tian  val io = IO(new Bundle {
7678882eb68SXin Tian    val write_req = Input(new Bundle {
7688882eb68SXin Tian      val keyid = UInt(KeyIDBits.W)
7698882eb68SXin Tian      val keyid_valid = Input(Bool())
7708882eb68SXin Tian      val enc_mode = Input(Bool())        // 1: this keyid open enc, 0: this keyid close enc
7718882eb68SXin Tian      val round_id = UInt(5.W)
7728882eb68SXin Tian      val data = Input(UInt(32.W))
7738882eb68SXin Tian    })
7748882eb68SXin Tian
7758882eb68SXin Tian  val enc_keyids = Input(Vec(MemencPipes, UInt(KeyIDBits.W)))
7768882eb68SXin Tian  val enc_round_keys = Output(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
7778882eb68SXin Tian  val dec_keyids = Input(Vec(MemencPipes, UInt(KeyIDBits.W)))
7788882eb68SXin Tian  val dec_round_keys = Output(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
7798882eb68SXin Tian  val dec = new Bundle {
7808882eb68SXin Tian    val keyid = Input(UInt(KeyIDBits.W))           // query dec_mode in advance in the AR channel
7818882eb68SXin Tian    val mode = Output(Bool())
7828882eb68SXin Tian  }
7838882eb68SXin Tian  val enc = new Bundle {
7848882eb68SXin Tian    val keyid = Input(UInt(KeyIDBits.W))           // query enc_mode in advance in the AW channel
7858882eb68SXin Tian    val mode = Output(Bool())
7868882eb68SXin Tian  }
7878882eb68SXin Tian})
7888882eb68SXin Tian
7898882eb68SXin Tian  val init_entry = Wire(new KeyTableEntry)
7908882eb68SXin Tian  init_entry.round_key_data := DontCare // Keep round_key_data as default (uninitialized)
7918882eb68SXin Tian  if (HasDelayNoencryption) {
7928882eb68SXin Tian    init_entry.encdec_mode := true.B
7938882eb68SXin Tian  } else {
7948882eb68SXin Tian    init_entry.encdec_mode := false.B
7958882eb68SXin Tian  }
7968882eb68SXin Tian  val table = RegInit(VecInit(Seq.fill(1 << KeyIDBits)(init_entry)))
7978882eb68SXin Tian  val wire_enc_round_keys = Wire(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
7988882eb68SXin Tian  val wire_dec_round_keys = Wire(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
7998882eb68SXin Tian
8008882eb68SXin Tian  // write and updata mode
8018882eb68SXin Tian  when(io.write_req.keyid_valid && io.write_req.enc_mode) {
8028882eb68SXin Tian    val entry = table(io.write_req.keyid)
8038882eb68SXin Tian    entry.encdec_mode := io.write_req.enc_mode
8048882eb68SXin Tian    entry.round_key_data(io.write_req.round_id) := io.write_req.data
8058882eb68SXin Tian  }
8068882eb68SXin Tian  when(io.write_req.keyid_valid && !io.write_req.enc_mode) {
8078882eb68SXin Tian    val entry = table(io.write_req.keyid)
8088882eb68SXin Tian    entry.encdec_mode := io.write_req.enc_mode
8098882eb68SXin Tian  }
8108882eb68SXin Tian
8118882eb68SXin Tian// read logic
8128882eb68SXin Tian  for (i <- 0 until MemencPipes) {
8138882eb68SXin Tian    val enc_entry = table(io.enc_keyids(i))
8148882eb68SXin Tian    val enc_round_key_parts = VecInit(Seq.fill(32 / MemencPipes)(0.U(32.W)))
8158882eb68SXin Tian    for (j <- 0 until (32 / MemencPipes)) {
8168882eb68SXin Tian      enc_round_key_parts((32 / MemencPipes) - 1 - j) := enc_entry.round_key_data(i.U * (32 / MemencPipes).U + j.U)
8178882eb68SXin Tian    }
8188882eb68SXin Tian    wire_enc_round_keys(i) := enc_round_key_parts.reduce(Cat(_, _))
8198882eb68SXin Tian
8208882eb68SXin Tian    val dec_entry = table(io.dec_keyids(i))
8218882eb68SXin Tian    val dec_round_key_parts = VecInit(Seq.fill(32 / MemencPipes)(0.U(32.W)))
8228882eb68SXin Tian    for (j <- 0 until (32 / MemencPipes)) {
8238882eb68SXin Tian      dec_round_key_parts((32 / MemencPipes) - 1 - j) := dec_entry.round_key_data(31.U - (i.U * (32 / MemencPipes).U + j.U))
8248882eb68SXin Tian    }
8258882eb68SXin Tian    wire_dec_round_keys(i) := dec_round_key_parts.reduce(Cat(_, _))
8268882eb68SXin Tian  }
8278882eb68SXin Tian  // output read data(round keys, enc/dec_mode, ar_mode, aw_mode)
8288882eb68SXin Tian  val dec_mode_entry = table(io.dec.keyid)
8298882eb68SXin Tian  io.dec.mode := dec_mode_entry.encdec_mode
8308882eb68SXin Tian
8318882eb68SXin Tian  val enc_mode_entry = table(io.enc.keyid)
8328882eb68SXin Tian  io.enc.mode := enc_mode_entry.encdec_mode
8338882eb68SXin Tian
8348882eb68SXin Tian  io.enc_round_keys := wire_enc_round_keys
8358882eb68SXin Tian  io.dec_round_keys := wire_dec_round_keys
8368882eb68SXin Tian
8378882eb68SXin Tian}
8388882eb68SXin Tian
8398882eb68SXin Tianclass KeyExtender(implicit p: Parameters) extends MemEncryptModule{
8408882eb68SXin Tian  val io = IO(new Bundle {
8418882eb68SXin Tian      val keyextend_req = Flipped(DecoupledIO(new Bundle {
8428882eb68SXin Tian        val key = UInt(128.W)
8438882eb68SXin Tian        val keyid = UInt(KeyIDBits.W)
8448882eb68SXin Tian        val enc_mode = Bool()         // 1:this keyid open enc  0:this keyid close enc
8458882eb68SXin Tian        val tweak_flage = Bool()      // 1:extend tweak key  0:extend keyid key
8468882eb68SXin Tian      }))
8478882eb68SXin Tian      val tweak_round_keys = Output(Vec(32, UInt(32.W)))
8488882eb68SXin Tian      val enc_keyids = Input(Vec(MemencPipes, UInt(KeyIDBits.W)))
8498882eb68SXin Tian      val enc_round_keys = Output(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
8508882eb68SXin Tian      val dec_keyids = Input(Vec(MemencPipes, UInt(KeyIDBits.W)))
8518882eb68SXin Tian      val dec_round_keys = Output(Vec(MemencPipes, UInt((32*32/MemencPipes).W)))
8528882eb68SXin Tian      val dec = new Bundle {
8538882eb68SXin Tian        val keyid = Input(UInt(KeyIDBits.W))           // query dec_mode in advance in the AR channel
8548882eb68SXin Tian        val mode = Output(Bool())
8558882eb68SXin Tian      }
8568882eb68SXin Tian      val enc = new Bundle {
8578882eb68SXin Tian        val keyid = Input(UInt(KeyIDBits.W))           // query enc_mode in advance in the AW channel
8588882eb68SXin Tian        val mode = Output(Bool())
8598882eb68SXin Tian      }
8608882eb68SXin Tian  })
8618882eb68SXin Tian
8628882eb68SXin Tian  val idle :: keyExpansion :: Nil = Enum(2)
8638882eb68SXin Tian  val current = RegInit(idle)
8648882eb68SXin Tian  val next = WireDefault(idle)
8658882eb68SXin Tian  current := next
8668882eb68SXin Tian
8678882eb68SXin Tian  val count_round = RegInit(0.U(5.W))
8688882eb68SXin Tian  val reg_count_round = RegNext(count_round)
8698882eb68SXin Tian  val reg_user_key = RegInit(0.U(128.W))
8708882eb68SXin Tian  val data_for_round = Wire(UInt(128.W))
8718882eb68SXin Tian  val data_after_round = Wire(UInt(128.W))
8728882eb68SXin Tian  val reg_data_after_round = RegInit(0.U(128.W))
8738882eb68SXin Tian  val key_exp_finished_out = RegInit(1.U)
8748882eb68SXin Tian  val reg_key_valid = RegNext(io.keyextend_req.valid, false.B)
8758882eb68SXin Tian  val reg_tweak_round_keys = Reg(Vec(32, UInt(32.W)))
8768882eb68SXin Tian
8778882eb68SXin Tian
8788882eb68SXin Tian  switch(current) {
8798882eb68SXin Tian    is(idle) {
8808882eb68SXin Tian      when(!reg_key_valid && io.keyextend_req.valid && io.keyextend_req.bits.enc_mode) {
8818882eb68SXin Tian        next := keyExpansion
8828882eb68SXin Tian      }
8838882eb68SXin Tian    }
8848882eb68SXin Tian    is(keyExpansion) {
8858882eb68SXin Tian      when(reg_count_round === 31.U) {
8868882eb68SXin Tian        next := idle
8878882eb68SXin Tian      }.otherwise {
8888882eb68SXin Tian        next := keyExpansion
8898882eb68SXin Tian      }
8908882eb68SXin Tian    }
8918882eb68SXin Tian  }
8928882eb68SXin Tian
8938882eb68SXin Tian  when(next === keyExpansion) {
8948882eb68SXin Tian    count_round := count_round + 1.U
8958882eb68SXin Tian  }.otherwise {
8968882eb68SXin Tian    count_round := 0.U
8978882eb68SXin Tian  }
8988882eb68SXin Tian
8998882eb68SXin Tian  when(!reg_key_valid && io.keyextend_req.valid && io.keyextend_req.bits.enc_mode) {
9008882eb68SXin Tian    reg_user_key := io.keyextend_req.bits.key
9018882eb68SXin Tian  }
9028882eb68SXin Tian
9038882eb68SXin Tian  when(current === keyExpansion && next === idle) {
9048882eb68SXin Tian    key_exp_finished_out := true.B
9058882eb68SXin Tian  }.elsewhen(io.keyextend_req.valid && io.keyextend_req.bits.enc_mode) {
9068882eb68SXin Tian    key_exp_finished_out := false.B
9078882eb68SXin Tian  }
9088882eb68SXin Tian  io.keyextend_req.ready := key_exp_finished_out
9098882eb68SXin Tian
9108882eb68SXin Tian  // Data for round calculation
9118882eb68SXin Tian  data_for_round := Mux(reg_count_round =/= 0.U, reg_data_after_round, reg_user_key)
9128882eb68SXin Tian  val cki = Module(new GetCKI)
9138882eb68SXin Tian  cki.io.countRoundIn := count_round
9148882eb68SXin Tian  val one_round = Module(new OneRoundForKeyExp)
9158882eb68SXin Tian  one_round.io.countRoundIn := reg_count_round
9168882eb68SXin Tian  one_round.io.dataIn := data_for_round
9178882eb68SXin Tian  one_round.io.ckParameterIn := cki.io.ckiOut
9188882eb68SXin Tian  data_after_round := one_round.io.resultOut
9198882eb68SXin Tian
9208882eb68SXin Tian  when(current === keyExpansion) {
9218882eb68SXin Tian    reg_data_after_round := data_after_round
9228882eb68SXin Tian  }
9238882eb68SXin Tian
9248882eb68SXin Tian  val keyTable = Module(new KeyTable())
9258882eb68SXin Tian    keyTable.io.write_req.keyid := io.keyextend_req.bits.keyid
9268882eb68SXin Tian    keyTable.io.write_req.enc_mode := io.keyextend_req.bits.enc_mode
9278882eb68SXin Tian    keyTable.io.write_req.round_id := reg_count_round
9288882eb68SXin Tian    keyTable.io.write_req.data := data_after_round(31, 0)
9298882eb68SXin Tian
9308882eb68SXin Tian    keyTable.io.enc_keyids := io.enc_keyids
9318882eb68SXin Tian    keyTable.io.dec_keyids := io.dec_keyids
9328882eb68SXin Tian    keyTable.io.dec.keyid := io.dec.keyid
9338882eb68SXin Tian    keyTable.io.enc.keyid := io.enc.keyid
9348882eb68SXin Tian    io.dec.mode := keyTable.io.dec.mode
9358882eb68SXin Tian    io.enc.mode := keyTable.io.enc.mode
9368882eb68SXin Tian    io.enc_round_keys := keyTable.io.enc_round_keys
9378882eb68SXin Tian    io.dec_round_keys := keyTable.io.dec_round_keys
9388882eb68SXin Tian
9398882eb68SXin Tian
9408882eb68SXin Tian  when(io.keyextend_req.bits.tweak_flage) {
9418882eb68SXin Tian    reg_tweak_round_keys(reg_count_round) := data_after_round(31, 0)
9428882eb68SXin Tian    keyTable.io.write_req.keyid_valid := false.B
9438882eb68SXin Tian  }.otherwise {
9448882eb68SXin Tian    keyTable.io.write_req.keyid_valid := current
9458882eb68SXin Tian  }
9468882eb68SXin Tian  io.tweak_round_keys := reg_tweak_round_keys
9478882eb68SXin Tian}
9488882eb68SXin Tian
9498882eb68SXin Tianclass AXI4MemEncrypt(address: AddressSet)(implicit p: Parameters) extends LazyModule with Memconsts
9508882eb68SXin Tian{
9518882eb68SXin Tian  require (isPow2(MemencPipes), s"AXI4MemEncrypt: MemencPipes must be a power of two, not $MemencPipes")
9528882eb68SXin Tian  require (PAddrBits > KeyIDBits, s"AXI4MemEncrypt: PAddrBits must be greater than KeyIDBits")
9538882eb68SXin Tian
9548882eb68SXin Tian  val node = AXI4AdapterNode(
9558882eb68SXin Tian    masterFn = { mp =>
9568882eb68SXin Tian      val new_idbits = log2Ceil(mp.endId) + 1
9578882eb68SXin Tian      // Create one new "master" per ID
9588882eb68SXin Tian      val masters = Array.tabulate(1 << new_idbits) { i => AXI4MasterParameters(
9598882eb68SXin Tian         name      = "",
9608882eb68SXin Tian         id        = IdRange(i, i+1),
9618882eb68SXin Tian         aligned   = true,
9628882eb68SXin Tian         maxFlight = Some(0))
9638882eb68SXin Tian      }
9648882eb68SXin Tian      // Accumulate the names of masters we squish
9658882eb68SXin Tian      val names = Array.fill(1 << new_idbits) { new scala.collection.mutable.HashSet[String]() }
9668882eb68SXin Tian      // Squash the information from original masters into new ID masters
9678882eb68SXin Tian      mp.masters.foreach { m =>
9688882eb68SXin Tian        for (i <- 0 until (1 << new_idbits)) {
9698882eb68SXin Tian          val accumulated = masters(i)
9708882eb68SXin Tian          names(i) += m.name
9718882eb68SXin Tian          masters(i) = accumulated.copy(
9728882eb68SXin Tian            aligned   = accumulated.aligned && m.aligned,
9738882eb68SXin Tian            maxFlight = accumulated.maxFlight.flatMap { o => m.maxFlight.map { n => o+n } })
9748882eb68SXin Tian        }
9758882eb68SXin Tian      }
9768882eb68SXin Tian      val finalNameStrings = names.map { n => if (n.isEmpty) "(unused)" else n.toList.mkString(", ") }
977*11269ca7STang Haojin      mp.copy(masters = masters.toIndexedSeq.zip(finalNameStrings.toIndexedSeq).map { case (m, n) => m.copy(name = n) })
9788882eb68SXin Tian    },
9798882eb68SXin Tian    slaveFn  = { sp => sp })
9808882eb68SXin Tian
9818882eb68SXin Tian  val device = new SimpleDevice("mem-encrypt-unit", Seq("iie,memencrypt0"))
9828882eb68SXin Tian  val ctrl_node = APBSlaveNode(Seq(APBSlavePortParameters(
9838882eb68SXin Tian    Seq(APBSlaveParameters(
9848882eb68SXin Tian      address       = List(address),
9858882eb68SXin Tian      resources     = device.reg,
9868882eb68SXin Tian      device        = Some(device),
9878882eb68SXin Tian      regionType    = RegionType.IDEMPOTENT)),
9888882eb68SXin Tian    beatBytes     = 8)))
9898882eb68SXin Tian
9908882eb68SXin Tian  lazy val module = new Impl
9918882eb68SXin Tian  class Impl extends LazyModuleImp(this) {
9928882eb68SXin Tian    val io = IO(new Bundle {
9938882eb68SXin Tian      val random_req = Output(Bool())
9948882eb68SXin Tian      val random_val = Input(Bool())
9958882eb68SXin Tian      val random_data = Input(Bool())
9968882eb68SXin Tian    })
9978882eb68SXin Tian
9988882eb68SXin Tian    val en    = Wire(Bool())
9998882eb68SXin Tian    val wmode = Wire(Bool())
10008882eb68SXin Tian    val addr  = Wire(UInt(12.W))
10018882eb68SXin Tian    val wdata = Wire(UInt(64.W))
10028882eb68SXin Tian    val wmask = Wire(UInt(8.W))
10038882eb68SXin Tian    val rdata = Wire(UInt(64.W))  // get rdata next cycle after en
10048882eb68SXin Tian
10058882eb68SXin Tian    (ctrl_node.in) foreach { case (ctrl_in, _) =>
10068882eb68SXin Tian      en    := ctrl_in.psel && !ctrl_in.penable
10078882eb68SXin Tian      wmode := ctrl_in.pwrite
10088882eb68SXin Tian      addr  := ctrl_in.paddr(11, 0)
10098882eb68SXin Tian      wdata := ctrl_in.pwdata
10108882eb68SXin Tian      wmask := ctrl_in.pstrb
10118882eb68SXin Tian      ctrl_in.pready  := true.B
10128882eb68SXin Tian      ctrl_in.pslverr := false.B
10138882eb68SXin Tian      ctrl_in.prdata  := rdata
10148882eb68SXin Tian    }
10158882eb68SXin Tian
10168882eb68SXin Tian    (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
10178882eb68SXin Tian      require (edgeIn.bundle.dataBits == 256, s"AXI4MemEncrypt: edgeIn dataBits must be 256")
10188882eb68SXin Tian      require (edgeOut.bundle.dataBits == 256, s"AXI4MemEncrypt: edgeOut dataBits must be 256")
10198882eb68SXin Tian
10208882eb68SXin Tian      val memencParams: Parameters = p.alterPartial {
10218882eb68SXin Tian        case MemcEdgeInKey => edgeIn
10228882eb68SXin Tian        case MemcEdgeOutKey => edgeOut
10238882eb68SXin Tian      }
10248882eb68SXin Tian      // -------------------------------------
10258882eb68SXin Tian      // MemEncrypt Config and State Registers
10268882eb68SXin Tian      // -------------------------------------
10278882eb68SXin Tian      val memenc_enable = Wire(Bool())
10288882eb68SXin Tian      val memencrypt_csr = Module(new MemEncryptCSR()(memencParams))
10298882eb68SXin Tian      memencrypt_csr.io.en    := en
10308882eb68SXin Tian      memencrypt_csr.io.wmode := wmode
10318882eb68SXin Tian      memencrypt_csr.io.addr  := addr
10328882eb68SXin Tian      memencrypt_csr.io.wdata := wdata
10338882eb68SXin Tian      memencrypt_csr.io.wmask := wmask
10348882eb68SXin Tian      memenc_enable := memencrypt_csr.io.memenc_enable
10358882eb68SXin Tian      rdata := memencrypt_csr.io.rdata
10368882eb68SXin Tian
10378882eb68SXin Tian      io.random_req := memencrypt_csr.io.randomio.random_req
10388882eb68SXin Tian      memencrypt_csr.io.randomio.random_val := io.random_val
10398882eb68SXin Tian      memencrypt_csr.io.randomio.random_data := io.random_data
10408882eb68SXin Tian
10418882eb68SXin Tian      // -------------------------------------
10428882eb68SXin Tian      // Key Extender & Round Key Lookup Table
10438882eb68SXin Tian      // -------------------------------------
10448882eb68SXin Tian      val key_extender = Module(new KeyExtender()(memencParams))
10458882eb68SXin Tian      key_extender.io.keyextend_req :<>= memencrypt_csr.io.keyextend_req
10468882eb68SXin Tian
10478882eb68SXin Tian      // -------------------
10488882eb68SXin Tian      // AXI4 chanel B
10498882eb68SXin Tian      // -------------------
10508882eb68SXin Tian      Connectable.waiveUnmatched(in.b, out.b) match {
10518882eb68SXin Tian        case (lhs, rhs) => lhs.squeezeAll :<>= rhs.squeezeAll
10528882eb68SXin Tian      }
10538882eb68SXin Tian
10548882eb68SXin Tian      val write_route = Module(new WriteChanelRoute()(memencParams))
10558882eb68SXin Tian      val aw_tweakenc = Module(new TweakEncrptyQueue()(memencParams))
10568882eb68SXin Tian      val waddr_q = Module(new IrrevocableQueue(chiselTypeOf(in.aw.bits), entries = MemencPipes+1))
10578882eb68SXin Tian      val wdata_q = Module(new IrrevocableQueue(chiselTypeOf(in.w.bits), entries = MemencPipes+1))
10588882eb68SXin Tian      val write_machine = Module(new AXI4WriteMachine()(memencParams))
10598882eb68SXin Tian      val axi4w_kt_q = Module(new Queue(new AXI4W_KT(false)(memencParams), entries = 2, flow = true))
10608882eb68SXin Tian      val wdata_encpipe = Module(new WdataEncrptyPipe()(memencParams))
10618882eb68SXin Tian      val write_arb = Module(new WriteChanelArbiter()(memencParams))
10628882eb68SXin Tian
10638882eb68SXin Tian      // -------------------
10648882eb68SXin Tian      // AXI4 Write Route
10658882eb68SXin Tian      // Unencrypt & Encrypt
10668882eb68SXin Tian      // -------------------
10678882eb68SXin Tian      write_route.io.memenc_enable := memenc_enable
10688882eb68SXin Tian      key_extender.io.enc.keyid := write_route.io.enc_keyid
10698882eb68SXin Tian      write_route.io.enc_mode := key_extender.io.enc.mode
10708882eb68SXin Tian
10718882eb68SXin Tian      write_route.io.in.aw :<>= in.aw
10728882eb68SXin Tian      write_route.io.in.w :<>= in.w
10738882eb68SXin Tian
10748882eb68SXin Tian      val unenc_aw = write_route.io.out0.aw
10758882eb68SXin Tian      val unenc_w = write_route.io.out0.w
10768882eb68SXin Tian      val pre_enc_aw = write_route.io.out1.aw
10778882eb68SXin Tian      val pre_enc_w = write_route.io.out1.w
10788882eb68SXin Tian
10798882eb68SXin Tian      // -------------------
10808882eb68SXin Tian      // AXI4 chanel AW
10818882eb68SXin Tian      // -------------------
10828882eb68SXin Tian      pre_enc_aw.ready := waddr_q.io.enq.ready && aw_tweakenc.io.enq.ready
10838882eb68SXin Tian      waddr_q.io.enq.valid := pre_enc_aw.valid && aw_tweakenc.io.enq.ready
10848882eb68SXin Tian      aw_tweakenc.io.enq.valid := pre_enc_aw.valid && waddr_q.io.enq.ready
10858882eb68SXin Tian
10868882eb68SXin Tian      waddr_q.io.enq.bits := pre_enc_aw.bits
10878882eb68SXin Tian      waddr_q.io.enq.bits.addr := pre_enc_aw.bits.addr(PAddrBits-KeyIDBits-1, 0)
10888882eb68SXin Tian      aw_tweakenc.io.enq.bits.addr := pre_enc_aw.bits.addr
10898882eb68SXin Tian      aw_tweakenc.io.enq.bits.len := pre_enc_aw.bits.len
10908882eb68SXin Tian      aw_tweakenc.io.tweak_round_keys := key_extender.io.tweak_round_keys
10918882eb68SXin Tian
10928882eb68SXin Tian      // -------------------
10938882eb68SXin Tian      // AXI4 chanel W
10948882eb68SXin Tian      // -------------------
10958882eb68SXin Tian      wdata_q.io.enq :<>= pre_enc_w
10968882eb68SXin Tian      write_machine.io.in_w :<>= wdata_q.io.deq
10978882eb68SXin Tian      write_machine.io.in_kt :<>= aw_tweakenc.io.deq
10988882eb68SXin Tian      axi4w_kt_q.io.enq :<>= write_machine.io.out_w
10998882eb68SXin Tian      wdata_encpipe.io.in_w :<>= axi4w_kt_q.io.deq
11008882eb68SXin Tian      key_extender.io.enc_keyids := wdata_encpipe.io.enc_keyids
11018882eb68SXin Tian      wdata_encpipe.io.enc_round_keys := key_extender.io.enc_round_keys
11028882eb68SXin Tian
11038882eb68SXin Tian      // -------------------
11048882eb68SXin Tian      // AXI4 Write Arbiter
11058882eb68SXin Tian      // Unencrypt & Encrypt
11068882eb68SXin Tian      // -------------------
11078882eb68SXin Tian      write_arb.io.in0.aw :<>= unenc_aw
11088882eb68SXin Tian      write_arb.io.in0.aw.bits.addr := unenc_aw.bits.addr(PAddrBits-KeyIDBits-1, 0)
11098882eb68SXin Tian      write_arb.io.in0.w :<>= unenc_w
11108882eb68SXin Tian
11118882eb68SXin Tian      write_arb.io.in1.aw.valid := waddr_q.io.deq.valid && (waddr_q.io.deq.bits.len =/=0.U || write_machine.io.uncache_en)
11128882eb68SXin Tian      waddr_q.io.deq.ready := write_arb.io.in1.aw.ready && (waddr_q.io.deq.bits.len =/=0.U || write_machine.io.uncache_en)
11138882eb68SXin Tian      write_machine.io.uncache_commit := write_arb.io.in1.aw.fire
11148882eb68SXin Tian      write_arb.io.in1.aw.bits := waddr_q.io.deq.bits
11158882eb68SXin Tian      write_arb.io.in1.w :<>= wdata_encpipe.io.out_w
11168882eb68SXin Tian
11178882eb68SXin Tian      out.aw :<>= write_arb.io.out.aw
11188882eb68SXin Tian      out.w  :<>= write_arb.io.out.w
11198882eb68SXin Tian
11208882eb68SXin Tian      val ar_arb = Module(new IrrevocableArbiter(chiselTypeOf(out.ar.bits), 2))
11218882eb68SXin Tian      val ar_tweakenc = Module(new TweakEncrptyTable()(memencParams))
11228882eb68SXin Tian      val read_machine = Module(new AXI4ReadMachine()(memencParams))
11238882eb68SXin Tian      val axi4r_kt_q = Module(new Queue(new AXI4R_KT(false)(memencParams), entries = 2, flow = true))
11248882eb68SXin Tian      val pre_dec_rdata_route = Module(new RdataChanelRoute()(memencParams))
11258882eb68SXin Tian      val rdata_decpipe = Module(new RdataDecrptyPipe()(memencParams))
11268882eb68SXin Tian      val r_arb = Module(new IrrevocableArbiter(chiselTypeOf(out.r.bits), 2))
11278882eb68SXin Tian      val post_dec_rdata_route = Module(new RdataRoute()(memencParams))
11288882eb68SXin Tian
11298882eb68SXin Tian      // -------------------
11308882eb68SXin Tian      // AXI4 chanel AR
11318882eb68SXin Tian      // -------------------
11328882eb68SXin Tian      ar_arb.io.in(0) :<>= write_machine.io.out_ar
11338882eb68SXin Tian      // DecoupledIO connect IrrevocableIO
11348882eb68SXin Tian      ar_arb.io.in(1).valid := in.ar.valid
11358882eb68SXin Tian      ar_arb.io.in(1).bits := in.ar.bits
11368882eb68SXin Tian      in.ar.ready := ar_arb.io.in(1).ready
11378882eb68SXin Tian
11388882eb68SXin Tian      ar_arb.io.out.ready := out.ar.ready && ar_tweakenc.io.enq.ready
11398882eb68SXin Tian
11408882eb68SXin Tian      ar_tweakenc.io.enq.valid := ar_arb.io.out.valid && out.ar.ready
11418882eb68SXin Tian      ar_tweakenc.io.enq.bits.addr := ar_arb.io.out.bits.addr
11428882eb68SXin Tian      ar_tweakenc.io.enq.bits.len := ar_arb.io.out.bits.len
11438882eb68SXin Tian      ar_tweakenc.io.enq.bits.id := ar_arb.io.out.bits.id
11448882eb68SXin Tian      ar_tweakenc.io.tweak_round_keys := key_extender.io.tweak_round_keys
11458882eb68SXin Tian      ar_tweakenc.io.memenc_enable := memenc_enable
11468882eb68SXin Tian      key_extender.io.dec.keyid := ar_tweakenc.io.dec_keyid
11478882eb68SXin Tian      ar_tweakenc.io.dec_mode := key_extender.io.dec.mode
11488882eb68SXin Tian
11498882eb68SXin Tian      out.ar.valid := ar_arb.io.out.valid && ar_tweakenc.io.enq.ready
11508882eb68SXin Tian      out.ar.bits := ar_arb.io.out.bits
11518882eb68SXin Tian      out.ar.bits.addr := ar_arb.io.out.bits.addr(PAddrBits-KeyIDBits-1, 0)
11528882eb68SXin Tian
11538882eb68SXin Tian      // -------------------
11548882eb68SXin Tian      // AXI4 Rdata Route
11558882eb68SXin Tian      // Unencrypt & Encrypt
11568882eb68SXin Tian      // -------------------
11578882eb68SXin Tian      pre_dec_rdata_route.io.in_r :<>= out.r
11588882eb68SXin Tian      ar_tweakenc.io.dec_r.id := pre_dec_rdata_route.io.dec_rid
11598882eb68SXin Tian      pre_dec_rdata_route.io.dec_mode := ar_tweakenc.io.dec_r.mode
11608882eb68SXin Tian
11618882eb68SXin Tian      val undec_r = pre_dec_rdata_route.io.out_r0
11628882eb68SXin Tian      val pre_dec_r = pre_dec_rdata_route.io.out_r1
11638882eb68SXin Tian
11648882eb68SXin Tian      // -------------------
11658882eb68SXin Tian      // AXI4 chanel R
11668882eb68SXin Tian      // -------------------
11678882eb68SXin Tian      read_machine.io.in_r :<>= pre_dec_r
11688882eb68SXin Tian      ar_tweakenc.io.req :<>= read_machine.io.kt_req
11698882eb68SXin Tian      read_machine.io.in_kt :<>= ar_tweakenc.io.resp
11708882eb68SXin Tian      axi4r_kt_q.io.enq :<>= read_machine.io.out_r
11718882eb68SXin Tian      rdata_decpipe.io.in_r :<>= axi4r_kt_q.io.deq
11728882eb68SXin Tian      key_extender.io.dec_keyids := rdata_decpipe.io.dec_keyids
11738882eb68SXin Tian      rdata_decpipe.io.dec_round_keys := key_extender.io.dec_round_keys
11748882eb68SXin Tian
11758882eb68SXin Tian      // -------------------
11768882eb68SXin Tian      // AXI4 Rdata Arbiter
11778882eb68SXin Tian      // Unencrypt & Encrypt
11788882eb68SXin Tian      // -------------------
11798882eb68SXin Tian      r_arb.io.in(0) :<>= undec_r
11808882eb68SXin Tian      r_arb.io.in(1) :<>= rdata_decpipe.io.out_r
11818882eb68SXin Tian
11828882eb68SXin Tian      post_dec_rdata_route.io.in_r :<>= r_arb.io.out
11838882eb68SXin Tian      write_machine.io.in_r :<>= post_dec_rdata_route.io.out_r1
11848882eb68SXin Tian      in.r :<>= post_dec_rdata_route.io.out_r0
11858882eb68SXin Tian    }
11868882eb68SXin Tian  }
11878882eb68SXin Tian}
11888882eb68SXin Tian
11898882eb68SXin Tianobject AXI4MemEncrypt
11908882eb68SXin Tian{
11918882eb68SXin Tian  def apply(address: AddressSet)(implicit p: Parameters): AXI4Node =
11928882eb68SXin Tian  {
11938882eb68SXin Tian    val axi4memenc = LazyModule(new AXI4MemEncrypt(address))
11948882eb68SXin Tian    axi4memenc.node
11958882eb68SXin Tian  }
11968882eb68SXin Tian}
1197