xref: /XiangShan/src/main/scala/device/MemEncryptUtil.scala (revision 8882eb685de93177da606ee717b5ec8e459a768a)
1*8882eb68SXin Tian/***************************************************************************************
2*8882eb68SXin Tian* Copyright (c) 2024-2025 Institute of Information Engineering, Chinese Academy of Sciences
3*8882eb68SXin Tian*
4*8882eb68SXin Tian* XiangShan is licensed under Mulan PSL v2.
5*8882eb68SXin Tian* You can use this software according to the terms and conditions of the Mulan PSL v2.
6*8882eb68SXin Tian* You may obtain a copy of Mulan PSL v2 at:
7*8882eb68SXin Tian*          http://license.coscl.org.cn/MulanPSL2
8*8882eb68SXin Tian*
9*8882eb68SXin Tian* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10*8882eb68SXin Tian* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11*8882eb68SXin Tian* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12*8882eb68SXin Tian*
13*8882eb68SXin Tian* See the Mulan PSL v2 for more details.
14*8882eb68SXin Tian***************************************************************************************/
15*8882eb68SXin Tian
16*8882eb68SXin Tianpackage device
17*8882eb68SXin Tian
18*8882eb68SXin Tianimport chisel3._
19*8882eb68SXin Tianimport chisel3.util._
20*8882eb68SXin Tianimport chisel3.util.HasBlackBoxResource
21*8882eb68SXin Tianimport org.chipsalliance.cde.config.Parameters
22*8882eb68SXin Tianimport freechips.rocketchip.amba.axi4._
23*8882eb68SXin Tianimport freechips.rocketchip.diplomacy._
24*8882eb68SXin Tianimport freechips.rocketchip.util._
25*8882eb68SXin Tianimport freechips.rocketchip.amba.apb._
26*8882eb68SXin Tianimport freechips.rocketchip.tilelink.AXI4TLState
27*8882eb68SXin Tian
28*8882eb68SXin Tianclass IrrevocableQueue[T <: Data](gen: T, entries: Int, flow: Boolean = false) extends Module {
29*8882eb68SXin Tian  val io = IO(new Bundle {
30*8882eb68SXin Tian    val enq = Flipped(Irrevocable(gen))
31*8882eb68SXin Tian    val deq = Irrevocable(gen)
32*8882eb68SXin Tian  })
33*8882eb68SXin Tian  val queue = Module(new Queue(gen, entries = entries, flow = flow))
34*8882eb68SXin Tian
35*8882eb68SXin Tian  queue.io.enq.valid := io.enq.valid
36*8882eb68SXin Tian  queue.io.enq.bits  := io.enq.bits
37*8882eb68SXin Tian  io.enq.ready := queue.io.enq.ready
38*8882eb68SXin Tian
39*8882eb68SXin Tian  io.deq.valid := queue.io.deq.valid
40*8882eb68SXin Tian  io.deq.bits  := queue.io.deq.bits
41*8882eb68SXin Tian  queue.io.deq.ready := io.deq.ready
42*8882eb68SXin Tian}
43*8882eb68SXin Tian
44*8882eb68SXin Tianclass IrrevocableArbiter[T <: Data](gen: T, n: Int) extends Module {
45*8882eb68SXin Tian  val io = IO(new Bundle {
46*8882eb68SXin Tian    val in = Flipped(Vec(n, Irrevocable(gen)))
47*8882eb68SXin Tian    val out = Irrevocable(gen)
48*8882eb68SXin Tian  })
49*8882eb68SXin Tian
50*8882eb68SXin Tian  val decoupledIn = io.in.map { irrevocable =>
51*8882eb68SXin Tian    val decoupled = Wire(Decoupled(gen))
52*8882eb68SXin Tian    decoupled.valid := irrevocable.valid
53*8882eb68SXin Tian    decoupled.bits  := irrevocable.bits
54*8882eb68SXin Tian    irrevocable.ready := decoupled.ready
55*8882eb68SXin Tian    decoupled
56*8882eb68SXin Tian  }
57*8882eb68SXin Tian
58*8882eb68SXin Tian  val arbiter = Module(new Arbiter(gen, n))
59*8882eb68SXin Tian  arbiter.io.in <> decoupledIn
60*8882eb68SXin Tian
61*8882eb68SXin Tian  io.out.valid := arbiter.io.out.valid
62*8882eb68SXin Tian  io.out.bits  := arbiter.io.out.bits
63*8882eb68SXin Tian  arbiter.io.out.ready := io.out.ready
64*8882eb68SXin Tian}
65*8882eb68SXin Tian
66*8882eb68SXin Tian// CKI (Cipher Key Input) is a constant input used in the SM4 encryption algorithm.
67*8882eb68SXin Tian// It is part of the key expansion process and participates in generating subkeys.
68*8882eb68SXin Tian// During each round of the key expansion, the CKI value is mixed with other constants and
69*8882eb68SXin Tian// the initial key to enhance the security of the encryption algorithm.
70*8882eb68SXin Tianclass GetCKI extends Module {
71*8882eb68SXin Tian  val io = IO(new Bundle {
72*8882eb68SXin Tian    val countRoundIn = Input(UInt(5.W))
73*8882eb68SXin Tian    val ckiOut = Output(UInt(32.W))
74*8882eb68SXin Tian  })
75*8882eb68SXin Tian  val ckiOutReg= RegInit(0.U(32.W))
76*8882eb68SXin Tian  // 32 32-bit CKI constant values
77*8882eb68SXin Tian  val ckiValuesVec = VecInit(Seq(
78*8882eb68SXin Tian    "h00070e15".U, "h1c232a31".U, "h383f464d".U, "h545b6269".U,
79*8882eb68SXin Tian    "h70777e85".U, "h8c939aa1".U, "ha8afb6bd".U, "hc4cbd2d9".U,
80*8882eb68SXin Tian    "he0e7eef5".U, "hfc030a11".U, "h181f262d".U, "h343b4249".U,
81*8882eb68SXin Tian    "h50575e65".U, "h6c737a81".U, "h888f969d".U, "ha4abb2b9".U,
82*8882eb68SXin Tian    "hc0c7ced5".U, "hdce3eaf1".U, "hf8ff060d".U, "h141b2229".U,
83*8882eb68SXin Tian    "h30373e45".U, "h4c535a61".U, "h686f767d".U, "h848b9299".U,
84*8882eb68SXin Tian    "ha0a7aeb5".U, "hbcc3cad1".U, "hd8dfe6ed".U, "hf4fb0209".U,
85*8882eb68SXin Tian    "h10171e25".U, "h2c333a41".U, "h484f565d".U, "h646b7279".U
86*8882eb68SXin Tian  ))
87*8882eb68SXin Tian  when(io.countRoundIn < 32.U) {
88*8882eb68SXin Tian    ckiOutReg := ckiValuesVec(io.countRoundIn)
89*8882eb68SXin Tian  }.otherwise {
90*8882eb68SXin Tian    ckiOutReg := 0.U
91*8882eb68SXin Tian  }
92*8882eb68SXin Tian  io.ckiOut := ckiOutReg
93*8882eb68SXin Tian}
94*8882eb68SXin Tian
95*8882eb68SXin Tian
96*8882eb68SXin Tian// S-box is used in SM4 for nonlinear transformations during encryption processes.
97*8882eb68SXin Tian// SM4 uses a fixed 256 byte S-box for byte replacement.
98*8882eb68SXin Tian// This replacement process is achieved by replacing the input 8-bit data
99*8882eb68SXin Tian// with the corresponding values in the S-box lookup table.
100*8882eb68SXin Tianclass SboxReplace extends Module {
101*8882eb68SXin Tian  val io = IO(new Bundle {
102*8882eb68SXin Tian    val dataIn = Input(UInt(8.W))
103*8882eb68SXin Tian    val resultOut = Output(UInt(8.W))
104*8882eb68SXin Tian  })
105*8882eb68SXin Tian  // A 256 element S-box lookup table, where each element is an 8-bit hexadecimal constant
106*8882eb68SXin Tian  val sbox = VecInit(Seq(
107*8882eb68SXin Tian    0xd6.U, 0x90.U, 0xe9.U, 0xfe.U, 0xcc.U, 0xe1.U, 0x3d.U, 0xb7.U, 0x16.U, 0xb6.U, 0x14.U, 0xc2.U, 0x28.U, 0xfb.U, 0x2c.U, 0x05.U,
108*8882eb68SXin Tian    0x2b.U, 0x67.U, 0x9a.U, 0x76.U, 0x2a.U, 0xbe.U, 0x04.U, 0xc3.U, 0xaa.U, 0x44.U, 0x13.U, 0x26.U, 0x49.U, 0x86.U, 0x06.U, 0x99.U,
109*8882eb68SXin Tian    0x9c.U, 0x42.U, 0x50.U, 0xf4.U, 0x91.U, 0xef.U, 0x98.U, 0x7a.U, 0x33.U, 0x54.U, 0x0b.U, 0x43.U, 0xed.U, 0xcf.U, 0xac.U, 0x62.U,
110*8882eb68SXin Tian    0xe4.U, 0xb3.U, 0x1c.U, 0xa9.U, 0xc9.U, 0x08.U, 0xe8.U, 0x95.U, 0x80.U, 0xdf.U, 0x94.U, 0xfa.U, 0x75.U, 0x8f.U, 0x3f.U, 0xa6.U,
111*8882eb68SXin Tian    0x47.U, 0x07.U, 0xa7.U, 0xfc.U, 0xf3.U, 0x73.U, 0x17.U, 0xba.U, 0x83.U, 0x59.U, 0x3c.U, 0x19.U, 0xe6.U, 0x85.U, 0x4f.U, 0xa8.U,
112*8882eb68SXin Tian    0x68.U, 0x6b.U, 0x81.U, 0xb2.U, 0x71.U, 0x64.U, 0xda.U, 0x8b.U, 0xf8.U, 0xeb.U, 0x0f.U, 0x4b.U, 0x70.U, 0x56.U, 0x9d.U, 0x35.U,
113*8882eb68SXin Tian    0x1e.U, 0x24.U, 0x0e.U, 0x5e.U, 0x63.U, 0x58.U, 0xd1.U, 0xa2.U, 0x25.U, 0x22.U, 0x7c.U, 0x3b.U, 0x01.U, 0x21.U, 0x78.U, 0x87.U,
114*8882eb68SXin Tian    0xd4.U, 0x00.U, 0x46.U, 0x57.U, 0x9f.U, 0xd3.U, 0x27.U, 0x52.U, 0x4c.U, 0x36.U, 0x02.U, 0xe7.U, 0xa0.U, 0xc4.U, 0xc8.U, 0x9e.U,
115*8882eb68SXin Tian    0xea.U, 0xbf.U, 0x8a.U, 0xd2.U, 0x40.U, 0xc7.U, 0x38.U, 0xb5.U, 0xa3.U, 0xf7.U, 0xf2.U, 0xce.U, 0xf9.U, 0x61.U, 0x15.U, 0xa1.U,
116*8882eb68SXin Tian    0xe0.U, 0xae.U, 0x5d.U, 0xa4.U, 0x9b.U, 0x34.U, 0x1a.U, 0x55.U, 0xad.U, 0x93.U, 0x32.U, 0x30.U, 0xf5.U, 0x8c.U, 0xb1.U, 0xe3.U,
117*8882eb68SXin Tian    0x1d.U, 0xf6.U, 0xe2.U, 0x2e.U, 0x82.U, 0x66.U, 0xca.U, 0x60.U, 0xc0.U, 0x29.U, 0x23.U, 0xab.U, 0x0d.U, 0x53.U, 0x4e.U, 0x6f.U,
118*8882eb68SXin Tian    0xd5.U, 0xdb.U, 0x37.U, 0x45.U, 0xde.U, 0xfd.U, 0x8e.U, 0x2f.U, 0x03.U, 0xff.U, 0x6a.U, 0x72.U, 0x6d.U, 0x6c.U, 0x5b.U, 0x51.U,
119*8882eb68SXin Tian    0x8d.U, 0x1b.U, 0xaf.U, 0x92.U, 0xbb.U, 0xdd.U, 0xbc.U, 0x7f.U, 0x11.U, 0xd9.U, 0x5c.U, 0x41.U, 0x1f.U, 0x10.U, 0x5a.U, 0xd8.U,
120*8882eb68SXin Tian    0x0a.U, 0xc1.U, 0x31.U, 0x88.U, 0xa5.U, 0xcd.U, 0x7b.U, 0xbd.U, 0x2d.U, 0x74.U, 0xd0.U, 0x12.U, 0xb8.U, 0xe5.U, 0xb4.U, 0xb0.U,
121*8882eb68SXin Tian    0x89.U, 0x69.U, 0x97.U, 0x4a.U, 0x0c.U, 0x96.U, 0x77.U, 0x7e.U, 0x65.U, 0xb9.U, 0xf1.U, 0x09.U, 0xc5.U, 0x6e.U, 0xc6.U, 0x84.U,
122*8882eb68SXin Tian    0x18.U, 0xf0.U, 0x7d.U, 0xec.U, 0x3a.U, 0xdc.U, 0x4d.U, 0x20.U, 0x79.U, 0xee.U, 0x5f.U, 0x3e.U, 0xd7.U, 0xcb.U, 0x39.U, 0x48.U
123*8882eb68SXin Tian  ))
124*8882eb68SXin Tian
125*8882eb68SXin Tian  io.resultOut := sbox(io.dataIn)
126*8882eb68SXin Tian}
127*8882eb68SXin Tian
128*8882eb68SXin Tian// Nonlinear Transformation in Data Encryption Process
129*8882eb68SXin Tianclass TransformForEncDec extends Module {
130*8882eb68SXin Tian  val io = IO(new Bundle {
131*8882eb68SXin Tian    val data_in = Input(UInt(32.W))
132*8882eb68SXin Tian    val result_out = Output(UInt(32.W))
133*8882eb68SXin Tian  })
134*8882eb68SXin Tian
135*8882eb68SXin Tian  val bytes_in = VecInit(Seq(io.data_in(7, 0), io.data_in(15, 8), io.data_in(23, 16), io.data_in(31, 24)))
136*8882eb68SXin Tian  val bytes_replaced = Wire(Vec(4, UInt(8.W)))
137*8882eb68SXin Tian  val word_replaced = Wire(UInt(32.W))
138*8882eb68SXin Tian
139*8882eb68SXin Tian  val sbox_replace_modules = VecInit(Seq.fill(4)(Module(new SboxReplace).io))
140*8882eb68SXin Tian  for (i <- 0 until 4) {
141*8882eb68SXin Tian    sbox_replace_modules(i).dataIn := bytes_in(i)
142*8882eb68SXin Tian    bytes_replaced(i) := sbox_replace_modules(i).resultOut
143*8882eb68SXin Tian  }
144*8882eb68SXin Tian
145*8882eb68SXin Tian  word_replaced := Cat(bytes_replaced.reverse)
146*8882eb68SXin Tian
147*8882eb68SXin Tian  io.result_out := ((word_replaced ^ Cat(word_replaced(29, 0), word_replaced(31, 30))) ^
148*8882eb68SXin Tian                      (Cat(word_replaced(21, 0), word_replaced(31, 22)) ^ Cat(word_replaced(13, 0), word_replaced(31, 14)))) ^
149*8882eb68SXin Tian                     Cat(word_replaced(7, 0), word_replaced(31, 8))
150*8882eb68SXin Tian}
151*8882eb68SXin Tian
152*8882eb68SXin Tian
153*8882eb68SXin Tian// Nonlinear Transformation in Key Expansion Process
154*8882eb68SXin Tianclass TransformForKeyExp extends Module {
155*8882eb68SXin Tian  val io = IO(new Bundle {
156*8882eb68SXin Tian    val data_in = Input(UInt(32.W))
157*8882eb68SXin Tian    val data_after_linear_key_out = Output(UInt(32.W))
158*8882eb68SXin Tian  })
159*8882eb68SXin Tian  val bytes_in = VecInit(Seq(io.data_in(7, 0), io.data_in(15, 8), io.data_in(23, 16), io.data_in(31, 24)))
160*8882eb68SXin Tian  val bytes_replaced = Wire(Vec(4, UInt(8.W)))
161*8882eb68SXin Tian  val word_replaced = Wire(UInt(32.W))
162*8882eb68SXin Tian
163*8882eb68SXin Tian  val sbox_replace_modules = VecInit(Seq.fill(4)(Module(new SboxReplace).io))
164*8882eb68SXin Tian  for (i <- 0 until 4) {
165*8882eb68SXin Tian    sbox_replace_modules(i).dataIn := bytes_in(i)
166*8882eb68SXin Tian    bytes_replaced(i) := sbox_replace_modules(i).resultOut
167*8882eb68SXin Tian  }
168*8882eb68SXin Tian
169*8882eb68SXin Tian  word_replaced := Cat(bytes_replaced.reverse)
170*8882eb68SXin Tian
171*8882eb68SXin Tian  io.data_after_linear_key_out := (word_replaced ^ Cat(word_replaced(18, 0), word_replaced(31, 19))) ^ Cat(word_replaced(8, 0), word_replaced(31, 9))
172*8882eb68SXin Tian}
173*8882eb68SXin Tian
174*8882eb68SXin Tian// The key expansion algorithm requires a total of 32 rounds of operations, including one round of operation
175*8882eb68SXin Tianclass OneRoundForKeyExp extends Module {
176*8882eb68SXin Tian  val io = IO(new Bundle {
177*8882eb68SXin Tian    val countRoundIn = Input(UInt(5.W))
178*8882eb68SXin Tian    val dataIn = Input(UInt(128.W))
179*8882eb68SXin Tian    val ckParameterIn = Input(UInt(32.W))
180*8882eb68SXin Tian    val resultOut = Output(UInt(128.W))
181*8882eb68SXin Tian  })
182*8882eb68SXin Tian  // In key expansion, the first step is to XOR each word of the original key with the system parameter to obtain four new words.
183*8882eb68SXin Tian  // system parameter: FK0, FK1, FK2, FK3.
184*8882eb68SXin Tian  val FK0 = "ha3b1bac6".U
185*8882eb68SXin Tian  val FK1 = "h56aa3350".U
186*8882eb68SXin Tian  val FK2 = "h677d9197".U
187*8882eb68SXin Tian  val FK3 = "hb27022dc".U
188*8882eb68SXin Tian
189*8882eb68SXin Tian  val word = VecInit(Seq(io.dataIn(127, 96), io.dataIn(95, 64), io.dataIn(63, 32), io.dataIn(31, 0)))
190*8882eb68SXin Tian
191*8882eb68SXin Tian  val k0 = word(0) ^ FK0
192*8882eb68SXin Tian  val k1 = word(1) ^ FK1
193*8882eb68SXin Tian  val k2 = word(2) ^ FK2
194*8882eb68SXin Tian  val k3 = word(3) ^ FK3
195*8882eb68SXin Tian
196*8882eb68SXin Tian
197*8882eb68SXin Tian  val dataForXor = io.ckParameterIn
198*8882eb68SXin Tian  val tmp0 = Mux(io.countRoundIn === 0.U, k1 ^ k2, word(1) ^ word(2))
199*8882eb68SXin Tian  val tmp1 = Mux(io.countRoundIn === 0.U, k3 ^ dataForXor, word(3) ^ dataForXor)
200*8882eb68SXin Tian  val dataForTransform = tmp0 ^ tmp1
201*8882eb68SXin Tian
202*8882eb68SXin Tian  val transformKey = Module(new TransformForKeyExp)
203*8882eb68SXin Tian  transformKey.io.data_in := dataForTransform
204*8882eb68SXin Tian
205*8882eb68SXin Tian  io.resultOut := Mux(io.countRoundIn === 0.U,
206*8882eb68SXin Tian                      Cat(k1, k2, k3, transformKey.io.data_after_linear_key_out ^ k0),
207*8882eb68SXin Tian                      Cat(word(1), word(2), word(3), transformKey.io.data_after_linear_key_out ^ word(0)))
208*8882eb68SXin Tian}
209*8882eb68SXin Tian
210*8882eb68SXin Tian// The SM4 encryption algorithm requires a total of 32 rounds of operations, including one round of operation
211*8882eb68SXin Tianclass OneRoundForEncDec  extends Module {
212*8882eb68SXin Tian  val io = IO(new Bundle {
213*8882eb68SXin Tian    val data_in = Input(UInt(128.W))
214*8882eb68SXin Tian    val round_key_in = Input(UInt(32.W))
215*8882eb68SXin Tian    val result_out = Output(UInt(128.W))
216*8882eb68SXin Tian  })
217*8882eb68SXin Tian
218*8882eb68SXin Tian  val word = VecInit(Seq(io.data_in(127, 96), io.data_in(95, 64), io.data_in(63, 32), io.data_in(31, 0)))
219*8882eb68SXin Tian
220*8882eb68SXin Tian  val tmp0 = word(1) ^ word(2)
221*8882eb68SXin Tian  val tmp1 = word(3) ^ io.round_key_in
222*8882eb68SXin Tian  val data_for_transform = tmp0 ^ tmp1
223*8882eb68SXin Tian
224*8882eb68SXin Tian  val transform_encdec = Module(new TransformForEncDec)
225*8882eb68SXin Tian  transform_encdec.io.data_in := data_for_transform
226*8882eb68SXin Tian
227*8882eb68SXin Tian  io.result_out := Cat(word(1), word(2), word(3), transform_encdec.io.result_out ^ word(0))
228*8882eb68SXin Tian}
229*8882eb68SXin Tian
230*8882eb68SXin Tian
231*8882eb68SXin Tian
232*8882eb68SXin Tianclass AXI4BundleWWithoutData(params: AXI4BundleParameters) extends Bundle {
233*8882eb68SXin Tian  val strb = UInt((params.dataBits/8).W)
234*8882eb68SXin Tian  val last = Bool()
235*8882eb68SXin Tian  val user = BundleMap(params.requestFields.filter(_.key.isData))
236*8882eb68SXin Tian}
237*8882eb68SXin Tian
238*8882eb68SXin Tianclass AXI4BundleRWithoutData(params: AXI4BundleParameters) extends Bundle {
239*8882eb68SXin Tian  val id   = UInt(params.idBits.W)
240*8882eb68SXin Tian  val resp = UInt(params.respBits.W)
241*8882eb68SXin Tian  val user = BundleMap(params.responseFields)
242*8882eb68SXin Tian  val echo = BundleMap(params.echoFields)
243*8882eb68SXin Tian  val last = Bool()
244*8882eb68SXin Tian}
245*8882eb68SXin Tian
246*8882eb68SXin Tian// OnePipeEncBase is an abstract class that defines the structure of a single-pipe encryption module.
247*8882eb68SXin Tian// The main purpose of this class is to standardize the input and output interfaces for encryption modules.
248*8882eb68SXin Tianabstract class OnePipeEncBase(implicit p: Parameters) extends MemEncryptModule {
249*8882eb68SXin Tian  val io = IO(new Bundle {
250*8882eb68SXin Tian    val onepipe_in = new Bundle {
251*8882eb68SXin Tian      val keyid = Input(UInt(KeyIDBits.W))
252*8882eb68SXin Tian      val data_in = Input(UInt(128.W))
253*8882eb68SXin Tian      val tweak_in = Input(UInt(128.W))
254*8882eb68SXin Tian      val axi4_other = Input(new AXI4BundleWWithoutData(MemcedgeIn.bundle))
255*8882eb68SXin Tian      val round_key_in = Input(Vec(32/MemencPipes, UInt(32.W)))
256*8882eb68SXin Tian    }
257*8882eb68SXin Tian    val onepipe_out = new Bundle {
258*8882eb68SXin Tian      val result_out = Output(UInt(128.W))
259*8882eb68SXin Tian      val axi4_other_out = Output(new AXI4BundleWWithoutData(MemcedgeIn.bundle))
260*8882eb68SXin Tian      val tweak_out = Output(UInt(128.W))
261*8882eb68SXin Tian      val keyid_out = Output(UInt(5.W))
262*8882eb68SXin Tian    }
263*8882eb68SXin Tian  })
264*8882eb68SXin Tian}
265*8882eb68SXin Tian
266*8882eb68SXin Tian// The OnePipeForEnc module needs to actually perform the encryption process for each
267*8882eb68SXin Tian// level of the pipeline in the encryption pipeline.
268*8882eb68SXin Tian// The flow level can be customized and configured.
269*8882eb68SXin Tianclass OnePipeForEnc(implicit p: Parameters) extends OnePipeEncBase {
270*8882eb68SXin Tian
271*8882eb68SXin Tian  val OneRoundForEncDecs = Seq.fill(32/MemencPipes)(Module(new OneRoundForEncDec))
272*8882eb68SXin Tian
273*8882eb68SXin Tian  for (i <- 0 until 32/MemencPipes) {
274*8882eb68SXin Tian    val mod = OneRoundForEncDecs(i)
275*8882eb68SXin Tian    mod.io.round_key_in := io.onepipe_in.round_key_in(i)
276*8882eb68SXin Tian    if (i == 0) mod.io.data_in := io.onepipe_in.data_in else mod.io.data_in := OneRoundForEncDecs(i - 1).io.result_out
277*8882eb68SXin Tian  }
278*8882eb68SXin Tian
279*8882eb68SXin Tian  io.onepipe_out.result_out := OneRoundForEncDecs.last.io.result_out
280*8882eb68SXin Tian  io.onepipe_out.keyid_out := io.onepipe_in.keyid
281*8882eb68SXin Tian  io.onepipe_out.axi4_other_out := io.onepipe_in.axi4_other
282*8882eb68SXin Tian  io.onepipe_out.tweak_out := io.onepipe_in.tweak_in
283*8882eb68SXin Tian
284*8882eb68SXin Tian}
285*8882eb68SXin Tian// The encryption process of each stage in the encryption pipeline does not require
286*8882eb68SXin Tian// the OnePipeForEnc module to actually execute the encryption process.
287*8882eb68SXin Tian// Test usage
288*8882eb68SXin Tianclass OnePipeForEncNoEnc(implicit p: Parameters) extends OnePipeEncBase {
289*8882eb68SXin Tian  io.onepipe_out.result_out := io.onepipe_in.data_in
290*8882eb68SXin Tian  io.onepipe_out.keyid_out := io.onepipe_in.keyid
291*8882eb68SXin Tian  io.onepipe_out.tweak_out := io.onepipe_in.tweak_in
292*8882eb68SXin Tian  io.onepipe_out.axi4_other_out := io.onepipe_in.axi4_other
293*8882eb68SXin Tian}
294*8882eb68SXin Tian
295*8882eb68SXin Tianabstract class OnePipeDecBase(implicit p: Parameters) extends MemEncryptModule {
296*8882eb68SXin Tian  val io = IO(new Bundle {
297*8882eb68SXin Tian    val onepipe_in = new Bundle {
298*8882eb68SXin Tian      val keyid = Input(UInt(KeyIDBits.W))
299*8882eb68SXin Tian      val data_in = Input(UInt(128.W))
300*8882eb68SXin Tian      val tweak_in = Input(UInt(128.W))
301*8882eb68SXin Tian      val axi4_other = Input(new AXI4BundleRWithoutData(MemcedgeOut.bundle))
302*8882eb68SXin Tian      val round_key_in = Input(Vec(32/MemencPipes, UInt(32.W)))
303*8882eb68SXin Tian    }
304*8882eb68SXin Tian    val onepipe_out = new Bundle {
305*8882eb68SXin Tian      val result_out = Output(UInt(128.W))
306*8882eb68SXin Tian      val axi4_other_out = Output(new AXI4BundleRWithoutData(MemcedgeOut.bundle))
307*8882eb68SXin Tian      val tweak_out = Output(UInt(128.W))
308*8882eb68SXin Tian      val keyid_out = Output(UInt(5.W))
309*8882eb68SXin Tian    }
310*8882eb68SXin Tian  })
311*8882eb68SXin Tian}
312*8882eb68SXin Tianclass OnePipeForDec(implicit p: Parameters) extends OnePipeDecBase {
313*8882eb68SXin Tian
314*8882eb68SXin Tian  val OneRoundForEncDecs = Seq.fill(32/MemencPipes)(Module(new OneRoundForEncDec))
315*8882eb68SXin Tian
316*8882eb68SXin Tian  for (i <- 0 until 32/MemencPipes) {
317*8882eb68SXin Tian    val mod = OneRoundForEncDecs(i)
318*8882eb68SXin Tian    mod.io.round_key_in := io.onepipe_in.round_key_in(i)
319*8882eb68SXin Tian    if (i == 0) mod.io.data_in := io.onepipe_in.data_in else mod.io.data_in := OneRoundForEncDecs(i - 1).io.result_out
320*8882eb68SXin Tian  }
321*8882eb68SXin Tian
322*8882eb68SXin Tian  io.onepipe_out.result_out := OneRoundForEncDecs.last.io.result_out
323*8882eb68SXin Tian  io.onepipe_out.keyid_out := io.onepipe_in.keyid
324*8882eb68SXin Tian  io.onepipe_out.axi4_other_out := io.onepipe_in.axi4_other
325*8882eb68SXin Tian  io.onepipe_out.tweak_out := io.onepipe_in.tweak_in
326*8882eb68SXin Tian
327*8882eb68SXin Tian}
328*8882eb68SXin Tianclass OnePipeForDecNoDec(implicit p: Parameters) extends OnePipeDecBase {
329*8882eb68SXin Tian  io.onepipe_out.result_out := io.onepipe_in.data_in
330*8882eb68SXin Tian  io.onepipe_out.keyid_out := io.onepipe_in.keyid
331*8882eb68SXin Tian  io.onepipe_out.axi4_other_out := io.onepipe_in.axi4_other
332*8882eb68SXin Tian  io.onepipe_out.tweak_out := io.onepipe_in.tweak_in
333*8882eb68SXin Tian}
334*8882eb68SXin Tian
335*8882eb68SXin Tian// Finite field operations after encrypting tweak (encryption adjustment value) in XTS confidential mode
336*8882eb68SXin Tian// Encryption adjustment value (tweak), This encryption adjustment utilizes finite fields and XOR operations to
337*8882eb68SXin Tian// ensure security by preventing the same ciphertext from being obtained even if the packet is identical each time.
338*8882eb68SXin Tian
339*8882eb68SXin Tian// Calculation process:
340*8882eb68SXin Tian// Move the logic one bit to the left. If the highest bit that is moved out is 1, XOR the lower 8 bits 0x87 three times,
341*8882eb68SXin Tian// generating four different sets of data for XOR before and after data encryption;
342*8882eb68SXin Tianclass GF128 extends Module{
343*8882eb68SXin Tian  val io = IO(new Bundle {
344*8882eb68SXin Tian    val tweak_in = Input(UInt(128.W))
345*8882eb68SXin Tian    val tweak_out = Output(UInt(512.W))
346*8882eb68SXin Tian  })
347*8882eb68SXin Tian
348*8882eb68SXin Tian  val gf_128_fdbk = "h87".U(8.W)
349*8882eb68SXin Tian  val tweak_1_isgf = io.tweak_in(127)
350*8882eb68SXin Tian  val tweak_2_isgf = io.tweak_in(126)
351*8882eb68SXin Tian  val tweak_3_isgf = io.tweak_in(125)
352*8882eb68SXin Tian  val tweak_1_shifted = Wire(UInt(128.W))
353*8882eb68SXin Tian  val tweak_2_shifted = Wire(UInt(128.W))
354*8882eb68SXin Tian  val tweak_3_shifted = Wire(UInt(128.W))
355*8882eb68SXin Tian  val tweak_1_out = Wire(UInt(128.W))
356*8882eb68SXin Tian  val tweak_2_out = Wire(UInt(128.W))
357*8882eb68SXin Tian  val tweak_3_out = Wire(UInt(128.W))
358*8882eb68SXin Tian
359*8882eb68SXin Tian  tweak_1_shifted := io.tweak_in << 1
360*8882eb68SXin Tian  tweak_2_shifted := tweak_1_out << 1
361*8882eb68SXin Tian  tweak_3_shifted := tweak_2_out << 1
362*8882eb68SXin Tian
363*8882eb68SXin Tian  tweak_1_out := Mux(tweak_1_isgf, tweak_1_shifted ^ gf_128_fdbk, tweak_1_shifted)
364*8882eb68SXin Tian  tweak_2_out := Mux(tweak_2_isgf, tweak_2_shifted ^ gf_128_fdbk, tweak_2_shifted)
365*8882eb68SXin Tian  tweak_3_out := Mux(tweak_3_isgf, tweak_3_shifted ^ gf_128_fdbk, tweak_3_shifted)
366*8882eb68SXin Tian
367*8882eb68SXin Tian  io.tweak_out := Cat(tweak_3_out, tweak_2_out, tweak_1_out, io.tweak_in)
368*8882eb68SXin Tian}
369*8882eb68SXin Tian
370*8882eb68SXin Tian// Perform finite field operations on the initial tweak during the request sending process,
371*8882eb68SXin Tian// and output according to the requirements (aw. len)
372*8882eb68SXin Tianclass TweakGF128(implicit p: Parameters) extends MemEncryptModule{
373*8882eb68SXin Tian    val io = IO(new Bundle {
374*8882eb68SXin Tian      val req = Flipped(DecoupledIO(new Bundle {
375*8882eb68SXin Tian        val len = UInt(MemcedgeIn.bundle.lenBits.W)
376*8882eb68SXin Tian        val addr = UInt(PAddrBits.W)
377*8882eb68SXin Tian        val tweak_in = UInt(128.W)
378*8882eb68SXin Tian      }))
379*8882eb68SXin Tian      val resp = DecoupledIO(new Bundle {
380*8882eb68SXin Tian        val tweak_out = UInt(256.W)
381*8882eb68SXin Tian        val keyid_out = UInt(KeyIDBits.W)
382*8882eb68SXin Tian        val addr_out = UInt(PAddrBits.W)
383*8882eb68SXin Tian      })
384*8882eb68SXin Tian    })
385*8882eb68SXin Tian    val tweak_gf128 = Module(new GF128())
386*8882eb68SXin Tian    tweak_gf128.io.tweak_in := io.req.bits.tweak_in
387*8882eb68SXin Tian
388*8882eb68SXin Tian    val reg_valid = RegInit(false.B)
389*8882eb68SXin Tian    val reg_counter = RegInit(0.U(2.W))
390*8882eb68SXin Tian    val reg_len = RegInit(0.U(MemcedgeIn.bundle.lenBits.W))
391*8882eb68SXin Tian    val reg_addr = RegInit(0.U(PAddrBits.W))
392*8882eb68SXin Tian    val reg_tweak_result = RegInit(0.U(512.W))
393*8882eb68SXin Tian
394*8882eb68SXin Tian    io.req.ready := !reg_valid || (reg_valid && io.resp.ready && (reg_len === 0.U || reg_counter =/= 0.U))
395*8882eb68SXin Tian
396*8882eb68SXin Tian    when(io.req.fire) {
397*8882eb68SXin Tian      reg_tweak_result := tweak_gf128.io.tweak_out
398*8882eb68SXin Tian      reg_len := io.req.bits.len
399*8882eb68SXin Tian      reg_addr := io.req.bits.addr
400*8882eb68SXin Tian      reg_valid := true.B
401*8882eb68SXin Tian      reg_counter := 0.U
402*8882eb68SXin Tian    }.elsewhen(reg_valid && io.resp.ready) {
403*8882eb68SXin Tian      when(reg_len === 0.U) {
404*8882eb68SXin Tian        reg_valid := false.B
405*8882eb68SXin Tian        reg_counter := 0.U
406*8882eb68SXin Tian      }.otherwise {
407*8882eb68SXin Tian        when(reg_counter === 0.U) {
408*8882eb68SXin Tian          reg_counter := reg_counter + 1.U
409*8882eb68SXin Tian        }.otherwise {
410*8882eb68SXin Tian          reg_valid := false.B
411*8882eb68SXin Tian          reg_counter := 0.U
412*8882eb68SXin Tian        }
413*8882eb68SXin Tian      }
414*8882eb68SXin Tian    }.otherwise {
415*8882eb68SXin Tian      reg_valid := reg_valid
416*8882eb68SXin Tian      reg_counter := reg_counter
417*8882eb68SXin Tian    }
418*8882eb68SXin Tian
419*8882eb68SXin Tian
420*8882eb68SXin Tian    io.resp.bits.addr_out  := reg_addr
421*8882eb68SXin Tian    io.resp.bits.keyid_out := reg_addr(PAddrBits - 1, PAddrBits - KeyIDBits)
422*8882eb68SXin Tian    io.resp.bits.tweak_out := Mux(reg_len === 0.U, Mux(reg_addr(5) === 0.U, reg_tweak_result(255, 0), reg_tweak_result(511, 256)),
423*8882eb68SXin Tian                                  Mux(reg_counter === 0.U, reg_tweak_result(255, 0), reg_tweak_result(511, 256)))
424*8882eb68SXin Tian    io.resp.valid          := reg_valid
425*8882eb68SXin Tian}
426*8882eb68SXin Tian
427*8882eb68SXin Tian// The encryption process in each stage of the pipeline during the initial tweak encryption process
428*8882eb68SXin Tianclass OnePipeForTweakEnc(implicit p: Parameters) extends MemEncryptModule {
429*8882eb68SXin Tian    val io = IO(new Bundle {
430*8882eb68SXin Tian      val in = new Bundle {
431*8882eb68SXin Tian        val data_in = Input(UInt(128.W))
432*8882eb68SXin Tian        val addr_in = Input(UInt(PAddrBits.W))
433*8882eb68SXin Tian        val len_in = Input(UInt(MemcedgeOut.bundle.lenBits.W))
434*8882eb68SXin Tian        val id_in = Input(UInt(MemcedgeOut.bundle.idBits.W))
435*8882eb68SXin Tian        val round_key_in = Input(Vec(32/MemencPipes, UInt(32.W)))
436*8882eb68SXin Tian      }
437*8882eb68SXin Tian      val out = new Bundle {
438*8882eb68SXin Tian        val result_out = Output(UInt(128.W))
439*8882eb68SXin Tian        val addr_out = Output(UInt(PAddrBits.W))
440*8882eb68SXin Tian        val len_out = Output(UInt(MemcedgeOut.bundle.lenBits.W))
441*8882eb68SXin Tian        val id_out = Output(UInt(MemcedgeOut.bundle.idBits.W))
442*8882eb68SXin Tian      }
443*8882eb68SXin Tian  })
444*8882eb68SXin Tian
445*8882eb68SXin Tian  val OneRoundForEncDecs = Seq.fill(32/MemencPipes)(Module(new OneRoundForEncDec))
446*8882eb68SXin Tian  for (i <- 0 until 32/MemencPipes) {
447*8882eb68SXin Tian    val mod = OneRoundForEncDecs(i)
448*8882eb68SXin Tian    mod.io.round_key_in := io.in.round_key_in(i)
449*8882eb68SXin Tian    if (i == 0) mod.io.data_in := io.in.data_in else mod.io.data_in := OneRoundForEncDecs(i - 1).io.result_out
450*8882eb68SXin Tian  }
451*8882eb68SXin Tian
452*8882eb68SXin Tian  io.out.result_out := OneRoundForEncDecs.last.io.result_out
453*8882eb68SXin Tian  io.out.addr_out   := io.in.addr_in
454*8882eb68SXin Tian  io.out.len_out    := io.in.len_in
455*8882eb68SXin Tian  io.out.id_out     := io.in.id_in
456*8882eb68SXin Tian}
457*8882eb68SXin Tian
458*8882eb68SXin Tian// Initial TWEAK encryption module.
459*8882eb68SXin Tian// The pipeline configuration is determined by the MemencPipes parameter
460*8882eb68SXin Tianclass TweakEncrypt(opt: Boolean)(implicit p: Parameters) extends MemEncryptModule{
461*8882eb68SXin Tian  val edgeUse = if (opt) MemcedgeIn else MemcedgeOut
462*8882eb68SXin Tian  val io = IO(new Bundle {
463*8882eb68SXin Tian    val tweak_enc_req = Flipped(DecoupledIO(new Bundle {
464*8882eb68SXin Tian      val tweak = UInt(128.W)
465*8882eb68SXin Tian      val addr_in = UInt(PAddrBits.W)
466*8882eb68SXin Tian      val len_in = UInt(edgeUse.bundle.lenBits.W)   // 6 bit
467*8882eb68SXin Tian      val id_in = UInt(edgeUse.bundle.idBits.W)
468*8882eb68SXin Tian      val tweak_round_keys = Vec(32, UInt(32.W))
469*8882eb68SXin Tian    }))
470*8882eb68SXin Tian    val tweak_enc_resp = DecoupledIO(new Bundle {
471*8882eb68SXin Tian      val tweak_encrpty = UInt(128.W)
472*8882eb68SXin Tian      val addr_out = UInt(PAddrBits.W)
473*8882eb68SXin Tian      val len_out = UInt(edgeUse.bundle.lenBits.W)
474*8882eb68SXin Tian      val id_out = UInt(edgeUse.bundle.idBits.W)
475*8882eb68SXin Tian    })
476*8882eb68SXin Tian  })
477*8882eb68SXin Tian
478*8882eb68SXin Tian  val reg_tweak = Reg(Vec(MemencPipes, UInt(128.W)))
479*8882eb68SXin Tian  val reg_addr = Reg(Vec(MemencPipes, UInt(PAddrBits.W)))
480*8882eb68SXin Tian  val reg_len = Reg(Vec(MemencPipes, UInt(edgeUse.bundle.lenBits.W)))
481*8882eb68SXin Tian  val reg_id = Reg(Vec(MemencPipes, UInt(edgeUse.bundle.idBits.W)))
482*8882eb68SXin Tian  val reg_tweak_valid = RegInit(VecInit(Seq.fill(MemencPipes)(false.B)))
483*8882eb68SXin Tian  // TWEAK encryption requires 32 rounds of encryption keys, grouped by pipeline level
484*8882eb68SXin Tian  val wire_round_key = Wire(Vec(MemencPipes, UInt((32 * 32 / MemencPipes).W)))
485*8882eb68SXin Tian
486*8882eb68SXin Tian  val keysPerPipe = 32 / MemencPipes
487*8882eb68SXin Tian  for (i <- 0 until MemencPipes) {
488*8882eb68SXin Tian    val keySegment = VecInit((0 until keysPerPipe).map(j => io.tweak_enc_req.bits.tweak_round_keys(i * keysPerPipe + j)))
489*8882eb68SXin Tian    wire_round_key(i) := Cat(keySegment.asUInt)
490*8882eb68SXin Tian  }
491*8882eb68SXin Tian
492*8882eb68SXin Tian  val wire_ready_result = WireInit(VecInit(Seq.fill(MemencPipes)(false.B)))
493*8882eb68SXin Tian  // The configuration method for each level of encryption module in tweak
494*8882eb68SXin Tian  def configureModule(i: Int, dataIn: UInt, addrIn: UInt, lenIn: UInt, idIn: UInt, roundKeys: UInt): OnePipeForTweakEnc = {
495*8882eb68SXin Tian
496*8882eb68SXin Tian    when(wire_ready_result(i) && (if (i == 0) io.tweak_enc_req.valid else reg_tweak_valid(i-1))) {
497*8882eb68SXin Tian      reg_tweak_valid(i) := true.B
498*8882eb68SXin Tian    }.elsewhen(reg_tweak_valid(i) && (if (i == MemencPipes - 1) io.tweak_enc_resp.ready else wire_ready_result(i+1))) {
499*8882eb68SXin Tian      reg_tweak_valid(i) := false.B
500*8882eb68SXin Tian    }.otherwise {
501*8882eb68SXin Tian      reg_tweak_valid(i) := reg_tweak_valid(i)
502*8882eb68SXin Tian    }
503*8882eb68SXin Tian    wire_ready_result(i) := !reg_tweak_valid(i) || (reg_tweak_valid(i) && (if (i == MemencPipes - 1) io.tweak_enc_resp.ready else wire_ready_result(i+1)))
504*8882eb68SXin Tian
505*8882eb68SXin Tian    val module = Module(new OnePipeForTweakEnc())
506*8882eb68SXin Tian    module.io.in.data_in := dataIn
507*8882eb68SXin Tian    module.io.in.addr_in := addrIn
508*8882eb68SXin Tian    module.io.in.len_in  := lenIn
509*8882eb68SXin Tian    module.io.in.id_in   := idIn
510*8882eb68SXin Tian    for (j <- 0 until 32/MemencPipes) {
511*8882eb68SXin Tian      module.io.in.round_key_in(j) := roundKeys(j * 32 + 31, j * 32)
512*8882eb68SXin Tian    }
513*8882eb68SXin Tian    when(wire_ready_result(i) && (if (i == 0) io.tweak_enc_req.valid else reg_tweak_valid(i-1))) {
514*8882eb68SXin Tian      reg_tweak(i) := module.io.out.result_out
515*8882eb68SXin Tian      reg_addr(i)  := module.io.out.addr_out
516*8882eb68SXin Tian      reg_len(i)   := module.io.out.len_out
517*8882eb68SXin Tian      reg_id(i)    := module.io.out.id_out
518*8882eb68SXin Tian    }
519*8882eb68SXin Tian    module
520*8882eb68SXin Tian  }
521*8882eb68SXin Tian  // Instantiate the tweak encryption module for each pipeline level
522*8882eb68SXin Tian  val tweak_enc_modules = (0 until MemencPipes).map { i =>
523*8882eb68SXin Tian      if (i == 0) {
524*8882eb68SXin Tian        configureModule(i, io.tweak_enc_req.bits.tweak, io.tweak_enc_req.bits.addr_in, io.tweak_enc_req.bits.len_in, io.tweak_enc_req.bits.id_in, wire_round_key(i))
525*8882eb68SXin Tian      } else {
526*8882eb68SXin Tian        configureModule(i, reg_tweak(i-1), reg_addr(i-1), reg_len(i-1), reg_id(i-1), wire_round_key(i))
527*8882eb68SXin Tian      }
528*8882eb68SXin Tian  }
529*8882eb68SXin Tian  val result_out = Cat(
530*8882eb68SXin Tian    reg_tweak.last(31, 0),
531*8882eb68SXin Tian    reg_tweak.last(63, 32),
532*8882eb68SXin Tian    reg_tweak.last(95, 64),
533*8882eb68SXin Tian    reg_tweak.last(127, 96)
534*8882eb68SXin Tian  )
535*8882eb68SXin Tian    io.tweak_enc_resp.bits.tweak_encrpty  := result_out
536*8882eb68SXin Tian    io.tweak_enc_resp.bits.addr_out       := reg_addr.last
537*8882eb68SXin Tian    io.tweak_enc_resp.bits.len_out        := reg_len.last
538*8882eb68SXin Tian    io.tweak_enc_resp.bits.id_out         := reg_id.last
539*8882eb68SXin Tian    io.tweak_enc_resp.valid           := reg_tweak_valid.last
540*8882eb68SXin Tian    io.tweak_enc_req.ready            := wire_ready_result(0)
541*8882eb68SXin Tian
542*8882eb68SXin Tian}
543*8882eb68SXin Tian
544*8882eb68SXin Tian
545*8882eb68SXin Tian// tweak table entry in AR Channel
546*8882eb68SXin Tianclass TweakTableEntry(implicit val p: Parameters) extends Bundle with Memconsts {
547*8882eb68SXin Tian  val v_flag        = Bool()
548*8882eb68SXin Tian  val keyid         = UInt(KeyIDBits.W)
549*8882eb68SXin Tian  val len           = UInt(MemcedgeOut.bundle.lenBits.W)
550*8882eb68SXin Tian  val tweak_encrpty = UInt(128.W)
551*8882eb68SXin Tian  val sel_counter   = Bool()
552*8882eb68SXin Tian}
553*8882eb68SXin Tianclass TweakTableModeEntry extends Bundle {
554*8882eb68SXin Tian  val dec_mode       = Bool()
555*8882eb68SXin Tian}
556*8882eb68SXin Tian// tweak table in AR Channel
557*8882eb68SXin Tianclass TweakTable(implicit p: Parameters) extends MemEncryptModule {
558*8882eb68SXin Tian  val io = IO(new Bundle {
559*8882eb68SXin Tian    // Write to tweak table
560*8882eb68SXin Tian    val write = Flipped(DecoupledIO(new Bundle {
561*8882eb68SXin Tian      val id      = UInt(MemcedgeOut.bundle.idBits.W)
562*8882eb68SXin Tian      val len     = UInt(MemcedgeOut.bundle.lenBits.W)
563*8882eb68SXin Tian      val addr    = UInt(PAddrBits.W)
564*8882eb68SXin Tian      val tweak_encrpty = UInt(128.W)
565*8882eb68SXin Tian    }))
566*8882eb68SXin Tian    // Read from the tweak table with the ID of channel R in AXI4 as the index
567*8882eb68SXin Tian    val req = Flipped(DecoupledIO(new Bundle {
568*8882eb68SXin Tian      val read_id = UInt(MemcedgeOut.bundle.idBits.W)
569*8882eb68SXin Tian    }))
570*8882eb68SXin Tian    // Tweak table read response
571*8882eb68SXin Tian    val resp = DecoupledIO(new Bundle {
572*8882eb68SXin Tian      val read_tweak       = UInt(128.W)
573*8882eb68SXin Tian      val read_keyid       = UInt(KeyIDBits.W)
574*8882eb68SXin Tian      val read_sel_counter = Bool()
575*8882eb68SXin Tian    })
576*8882eb68SXin Tian    val w_mode = Flipped(DecoupledIO(new Bundle {
577*8882eb68SXin Tian      val id       = UInt(MemcedgeOut.bundle.idBits.W)
578*8882eb68SXin Tian      val dec_mode = Input(Bool())
579*8882eb68SXin Tian    }))
580*8882eb68SXin Tian    val r_mode = new Bundle {
581*8882eb68SXin Tian      val id = Input(UInt(MemcedgeOut.bundle.idBits.W))
582*8882eb68SXin Tian      val dec_mode = Output(Bool())
583*8882eb68SXin Tian    }
584*8882eb68SXin Tian  })
585*8882eb68SXin Tian
586*8882eb68SXin Tian  val init_tweak_entry = Wire(new TweakTableEntry())
587*8882eb68SXin Tian    init_tweak_entry.v_flag := false.B
588*8882eb68SXin Tian    init_tweak_entry.keyid := DontCare
589*8882eb68SXin Tian    init_tweak_entry.len := DontCare
590*8882eb68SXin Tian    init_tweak_entry.tweak_encrpty := DontCare
591*8882eb68SXin Tian    init_tweak_entry.sel_counter := DontCare
592*8882eb68SXin Tian  val init_mode_entry = Wire(new TweakTableModeEntry)
593*8882eb68SXin Tian    init_mode_entry.dec_mode := false.B
594*8882eb68SXin Tian  val tweak_table = RegInit(VecInit(Seq.fill((1 << (MemcedgeOut.bundle.idBits - 1)) + 1)(init_tweak_entry)))
595*8882eb68SXin Tian  val tweak_mode_table = RegInit(VecInit(Seq.fill((1 << (MemcedgeOut.bundle.idBits - 1)) + 1)(init_mode_entry)))
596*8882eb68SXin Tian
597*8882eb68SXin Tian  // write tweak table entry logic
598*8882eb68SXin Tian  when(io.write.valid) {
599*8882eb68SXin Tian      val write_entry = tweak_table(io.write.bits.id)
600*8882eb68SXin Tian      write_entry.tweak_encrpty    := io.write.bits.tweak_encrpty
601*8882eb68SXin Tian      write_entry.keyid            := io.write.bits.addr(PAddrBits-1, PAddrBits-KeyIDBits)
602*8882eb68SXin Tian      write_entry.len              := io.write.bits.len
603*8882eb68SXin Tian      write_entry.v_flag           := true.B
604*8882eb68SXin Tian
605*8882eb68SXin Tian      when(io.write.bits.len === 1.U) {
606*8882eb68SXin Tian          write_entry.sel_counter := false.B
607*8882eb68SXin Tian      }.otherwise {
608*8882eb68SXin Tian          write_entry.sel_counter := Mux(io.write.bits.addr(5) === 0.U, false.B, true.B)
609*8882eb68SXin Tian      }
610*8882eb68SXin Tian  }
611*8882eb68SXin Tian  io.write.ready := true.B
612*8882eb68SXin Tian
613*8882eb68SXin Tian  // write mode table entry logic
614*8882eb68SXin Tian  when(io.w_mode.valid) {
615*8882eb68SXin Tian    val write_mode_entry = tweak_mode_table(io.w_mode.bits.id)
616*8882eb68SXin Tian    write_mode_entry.dec_mode := io.w_mode.bits.dec_mode
617*8882eb68SXin Tian  }
618*8882eb68SXin Tian  io.w_mode.ready := true.B
619*8882eb68SXin Tian
620*8882eb68SXin Tian  // Tweak table read response logic
621*8882eb68SXin Tian  val reg_read_valid    = RegInit(false.B)
622*8882eb68SXin Tian  val reg_tweak_encrpty = RegInit(0.U(128.W))
623*8882eb68SXin Tian  val reg_keyid = RegInit(0.U(KeyIDBits.W))
624*8882eb68SXin Tian  val reg_sel_counter = RegInit(false.B)
625*8882eb68SXin Tian
626*8882eb68SXin Tian  val read_entry = tweak_table(io.req.bits.read_id)
627*8882eb68SXin Tian  val read_mode_entry = tweak_mode_table(io.r_mode.id)
628*8882eb68SXin Tian  io.r_mode.dec_mode := read_mode_entry.dec_mode
629*8882eb68SXin Tian
630*8882eb68SXin Tian  io.req.ready := (!reg_read_valid || (reg_read_valid && io.resp.ready)) && read_entry.v_flag
631*8882eb68SXin Tian  when(io.req.fire) {
632*8882eb68SXin Tian      reg_read_valid          := true.B
633*8882eb68SXin Tian      reg_tweak_encrpty       := read_entry.tweak_encrpty
634*8882eb68SXin Tian      reg_keyid               := read_entry.keyid
635*8882eb68SXin Tian      reg_sel_counter         := read_entry.sel_counter
636*8882eb68SXin Tian      when(read_entry.len === 0.U) {
637*8882eb68SXin Tian          read_entry.v_flag := false.B
638*8882eb68SXin Tian      }.otherwise {
639*8882eb68SXin Tian          when(!read_entry.sel_counter) {
640*8882eb68SXin Tian              read_entry.sel_counter := true.B
641*8882eb68SXin Tian          }.otherwise {
642*8882eb68SXin Tian              read_entry.v_flag := false.B
643*8882eb68SXin Tian          }
644*8882eb68SXin Tian      }
645*8882eb68SXin Tian  }.elsewhen(reg_read_valid && io.resp.ready) {
646*8882eb68SXin Tian      reg_read_valid          := false.B
647*8882eb68SXin Tian  }.otherwise {
648*8882eb68SXin Tian      reg_read_valid          := reg_read_valid
649*8882eb68SXin Tian  }
650*8882eb68SXin Tian
651*8882eb68SXin Tian  io.resp.bits.read_tweak       := reg_tweak_encrpty
652*8882eb68SXin Tian  io.resp.bits.read_keyid       := reg_keyid
653*8882eb68SXin Tian  io.resp.bits.read_sel_counter := reg_sel_counter
654*8882eb68SXin Tian  io.resp.valid     := reg_read_valid
655*8882eb68SXin Tian
656*8882eb68SXin Tian}
657*8882eb68SXin Tian
658*8882eb68SXin Tian
659*8882eb68SXin Tian
660*8882eb68SXin Tian// AXI4Util
661*8882eb68SXin Tian// Bypass routing, Determine the encryption mode in the key expansion module.
662*8882eb68SXin Tian// write requests need to be encrypted ->io.out1;
663*8882eb68SXin Tian// Writing requests does not require encryption --->io.out0.
664*8882eb68SXin Tianclass WriteChanelRoute(implicit p: Parameters) extends MemEncryptModule
665*8882eb68SXin Tian{
666*8882eb68SXin Tian  val io = IO(new Bundle {
667*8882eb68SXin Tian    val in = new Bundle {
668*8882eb68SXin Tian      val aw = Flipped(Irrevocable(new AXI4BundleAW(MemcedgeIn.bundle)))
669*8882eb68SXin Tian      val w = Flipped(Irrevocable(new AXI4BundleW(MemcedgeIn.bundle)))
670*8882eb68SXin Tian    }
671*8882eb68SXin Tian    // Unencrypt Chanel
672*8882eb68SXin Tian    val out0 = new Bundle {
673*8882eb68SXin Tian      val aw = Irrevocable(new AXI4BundleAW(MemcedgeIn.bundle))
674*8882eb68SXin Tian      val w = Irrevocable(new AXI4BundleW(MemcedgeIn.bundle))
675*8882eb68SXin Tian    }
676*8882eb68SXin Tian    // Encrypt Chanel
677*8882eb68SXin Tian    val out1 = new Bundle {
678*8882eb68SXin Tian      val aw = Irrevocable(new AXI4BundleAW(MemcedgeIn.bundle))
679*8882eb68SXin Tian      val w = Irrevocable(new AXI4BundleW(MemcedgeIn.bundle))
680*8882eb68SXin Tian    }
681*8882eb68SXin Tian    val enc_keyid = Output(UInt(KeyIDBits.W))
682*8882eb68SXin Tian    val enc_mode = Input(Bool())
683*8882eb68SXin Tian    val memenc_enable = Input(Bool())
684*8882eb68SXin Tian  })
685*8882eb68SXin Tian  io.enc_keyid := io.in.aw.bits.addr(PAddrBits-1, PAddrBits-KeyIDBits)
686*8882eb68SXin Tian
687*8882eb68SXin Tian  val reg_idle = RegInit(true.B)
688*8882eb68SXin Tian  val reg_enc_mode = RegInit(false.B)
689*8882eb68SXin Tian
690*8882eb68SXin Tian  when(io.in.aw.fire) {
691*8882eb68SXin Tian    reg_idle := false.B
692*8882eb68SXin Tian    reg_enc_mode := io.enc_mode && io.memenc_enable
693*8882eb68SXin Tian  }
694*8882eb68SXin Tian  when(io.in.w.fire && io.in.w.bits.last) {
695*8882eb68SXin Tian    reg_idle := true.B
696*8882eb68SXin Tian  }
697*8882eb68SXin Tian
698*8882eb68SXin Tian  val used_enc_mode = Mux(io.in.aw.fire, io.enc_mode && io.memenc_enable, reg_enc_mode)
699*8882eb68SXin Tian
700*8882eb68SXin Tian  // Cut aw_queue.io.enq.ready from io.out*.awready
701*8882eb68SXin Tian  val aw_queue = Module(new IrrevocableQueue(chiselTypeOf(io.in.aw.bits), 1, flow = true))
702*8882eb68SXin Tian
703*8882eb68SXin Tian  io.in.aw.ready := reg_idle && aw_queue.io.enq.ready
704*8882eb68SXin Tian  aw_queue.io.enq.valid := io.in.aw.valid && reg_idle
705*8882eb68SXin Tian  aw_queue.io.enq.bits := io.in.aw.bits
706*8882eb68SXin Tian
707*8882eb68SXin Tian  val unencrypt_aw_queue = Module(new IrrevocableQueue(chiselTypeOf(io.in.aw.bits), MemencPipes+1, flow = true))
708*8882eb68SXin Tian  val unencrypt_w_queue = Module(new IrrevocableQueue(chiselTypeOf(io.in.w.bits), (MemencPipes+1)*2, flow = true))
709*8882eb68SXin Tian
710*8882eb68SXin Tian  aw_queue.io.deq.ready := Mux(used_enc_mode, io.out1.aw.ready, unencrypt_aw_queue.io.enq.ready)
711*8882eb68SXin Tian  io.in.w.ready := (io.in.aw.fire || !reg_idle) && Mux(used_enc_mode, io.out1.w.ready, unencrypt_w_queue.io.enq.ready)
712*8882eb68SXin Tian
713*8882eb68SXin Tian  unencrypt_aw_queue.io.enq.valid := !used_enc_mode && aw_queue.io.deq.valid
714*8882eb68SXin Tian  unencrypt_w_queue.io.enq.valid  := !used_enc_mode && io.in.w.valid  && (io.in.aw.fire || !reg_idle)
715*8882eb68SXin Tian
716*8882eb68SXin Tian  unencrypt_aw_queue.io.enq.bits := aw_queue.io.deq.bits
717*8882eb68SXin Tian  unencrypt_w_queue.io.enq.bits  := io.in.w.bits
718*8882eb68SXin Tian
719*8882eb68SXin Tian  io.out0.aw.valid := unencrypt_aw_queue.io.deq.valid
720*8882eb68SXin Tian  io.out0.w.valid := unencrypt_w_queue.io.deq.valid
721*8882eb68SXin Tian
722*8882eb68SXin Tian  io.out0.aw.bits := unencrypt_aw_queue.io.deq.bits
723*8882eb68SXin Tian  io.out0.w.bits  := unencrypt_w_queue.io.deq.bits
724*8882eb68SXin Tian
725*8882eb68SXin Tian  unencrypt_aw_queue.io.deq.ready := io.out0.aw.ready
726*8882eb68SXin Tian  unencrypt_w_queue.io.deq.ready  := io.out0.w.ready
727*8882eb68SXin Tian
728*8882eb68SXin Tian  io.out1.aw.valid :=  used_enc_mode && aw_queue.io.deq.valid
729*8882eb68SXin Tian  io.out1.w.valid  :=  used_enc_mode && io.in.w.valid  && (io.in.aw.fire || !reg_idle)
730*8882eb68SXin Tian
731*8882eb68SXin Tian  io.out1.aw.bits := aw_queue.io.deq.bits
732*8882eb68SXin Tian  io.out1.w.bits  := io.in.w.bits
733*8882eb68SXin Tian}
734*8882eb68SXin Tian
735*8882eb68SXin Tianclass WriteChanelArbiter(implicit p: Parameters) extends MemEncryptModule
736*8882eb68SXin Tian{
737*8882eb68SXin Tian  val io = IO(new Bundle {
738*8882eb68SXin Tian    // Unencrypt Chanel
739*8882eb68SXin Tian    val in0 = new Bundle {
740*8882eb68SXin Tian      val aw = Flipped(Irrevocable(new AXI4BundleAW(MemcedgeOut.bundle)))
741*8882eb68SXin Tian      val w = Flipped(Irrevocable(new AXI4BundleW(MemcedgeOut.bundle)))
742*8882eb68SXin Tian    }
743*8882eb68SXin Tian    // Encrypt Chanel
744*8882eb68SXin Tian    val in1 = new Bundle {
745*8882eb68SXin Tian      val aw = Flipped(Irrevocable(new AXI4BundleAW(MemcedgeOut.bundle)))
746*8882eb68SXin Tian      val w = Flipped(Irrevocable(new AXI4BundleW(MemcedgeOut.bundle)))
747*8882eb68SXin Tian    }
748*8882eb68SXin Tian    val out = new Bundle {
749*8882eb68SXin Tian      val aw = Irrevocable(new AXI4BundleAW(MemcedgeOut.bundle))
750*8882eb68SXin Tian      val w = Irrevocable(new AXI4BundleW(MemcedgeOut.bundle))
751*8882eb68SXin Tian    }
752*8882eb68SXin Tian  })
753*8882eb68SXin Tian
754*8882eb68SXin Tian  val validMask = RegInit(false.B) // 1:last send write req from Encrypt Chanel
755*8882eb68SXin Tian                                   // 0:last send write req from Unencrypt Chanel
756*8882eb68SXin Tian  val aw_choice = Wire(Bool())     // 1:Encrypt Chanel 0:Unencrypt Chanel
757*8882eb68SXin Tian  val w_choice = RegInit(false.B)  // 1:Encrypt Chanel 0:Unencrypt Chanel
758*8882eb68SXin Tian  val reg_idle = RegInit(true.B)
759*8882eb68SXin Tian  // Cut aw_queue.io.enq.ready from io.out*.awready
760*8882eb68SXin Tian  val aw_queue = Module(new IrrevocableQueue(chiselTypeOf(io.in0.aw.bits), 1, flow = true))
761*8882eb68SXin Tian
762*8882eb68SXin Tian  when(io.in1.aw.fire) {
763*8882eb68SXin Tian    validMask := true.B
764*8882eb68SXin Tian  }.elsewhen(io.in0.aw.fire) {
765*8882eb68SXin Tian    validMask := false.B
766*8882eb68SXin Tian  }.otherwise {
767*8882eb68SXin Tian    validMask := validMask
768*8882eb68SXin Tian  }
769*8882eb68SXin Tian
770*8882eb68SXin Tian  // --------------------------[Unencrypt pref]  [Encrypt pref]
771*8882eb68SXin Tian  aw_choice := Mux(validMask, !io.in0.aw.valid, io.in1.aw.valid)
772*8882eb68SXin Tian
773*8882eb68SXin Tian  when(aw_queue.io.enq.fire) {
774*8882eb68SXin Tian    reg_idle := false.B
775*8882eb68SXin Tian    w_choice := aw_choice
776*8882eb68SXin Tian  }
777*8882eb68SXin Tian  when(io.out.w.fire && io.out.w.bits.last) {
778*8882eb68SXin Tian    reg_idle := true.B
779*8882eb68SXin Tian  }
780*8882eb68SXin Tian
781*8882eb68SXin Tian  val used_w_choice = Mux(aw_queue.io.enq.fire, aw_choice, w_choice)
782*8882eb68SXin Tian
783*8882eb68SXin Tian  io.in0.aw.ready := reg_idle && !aw_choice && aw_queue.io.enq.ready
784*8882eb68SXin Tian  io.in1.aw.ready := reg_idle &&  aw_choice && aw_queue.io.enq.ready
785*8882eb68SXin Tian  aw_queue.io.enq.valid := (io.in0.aw.valid || io.in1.aw.valid) && reg_idle
786*8882eb68SXin Tian  aw_queue.io.enq.bits := Mux(aw_choice, io.in1.aw.bits, io.in0.aw.bits)
787*8882eb68SXin Tian
788*8882eb68SXin Tian  // DecoupledIO connect IrrevocableIO
789*8882eb68SXin Tian  io.out.aw.valid := aw_queue.io.deq.valid
790*8882eb68SXin Tian  io.out.aw.bits := aw_queue.io.deq.bits
791*8882eb68SXin Tian  aw_queue.io.deq.ready := io.out.aw.ready
792*8882eb68SXin Tian
793*8882eb68SXin Tian  io.in0.w.ready := (aw_queue.io.enq.fire || !reg_idle) && !used_w_choice && io.out.w.ready
794*8882eb68SXin Tian  io.in1.w.ready := (aw_queue.io.enq.fire || !reg_idle) &&  used_w_choice && io.out.w.ready
795*8882eb68SXin Tian
796*8882eb68SXin Tian  io.out.w.valid := (aw_queue.io.enq.fire || !reg_idle) && Mux(used_w_choice, io.in1.w.valid, io.in0.w.valid)
797*8882eb68SXin Tian  io.out.w.bits  := Mux(used_w_choice, io.in1.w.bits, io.in0.w.bits)
798*8882eb68SXin Tian}
799*8882eb68SXin Tian
800*8882eb68SXin Tianclass RdataChanelRoute(implicit p: Parameters) extends MemEncryptModule
801*8882eb68SXin Tian{
802*8882eb68SXin Tian  val io = IO(new Bundle {
803*8882eb68SXin Tian    val in_r = Flipped(Irrevocable(new AXI4BundleR(MemcedgeOut.bundle)))
804*8882eb68SXin Tian    // Unencrypt Chanel
805*8882eb68SXin Tian    val out_r0 = Irrevocable(new AXI4BundleR(MemcedgeOut.bundle))
806*8882eb68SXin Tian    // Encrypt Chanel
807*8882eb68SXin Tian    val out_r1 = Irrevocable(new AXI4BundleR(MemcedgeOut.bundle))
808*8882eb68SXin Tian    val dec_rid = Output(UInt(MemcedgeOut.bundle.idBits.W))
809*8882eb68SXin Tian    val dec_mode = Input(Bool())
810*8882eb68SXin Tian  })
811*8882eb68SXin Tian  io.dec_rid := io.in_r.bits.id
812*8882eb68SXin Tian
813*8882eb68SXin Tian  val r_sel = io.dec_mode
814*8882eb68SXin Tian
815*8882eb68SXin Tian  io.out_r0.bits <> io.in_r.bits
816*8882eb68SXin Tian  io.out_r1.bits <> io.in_r.bits
817*8882eb68SXin Tian
818*8882eb68SXin Tian  io.out_r0.valid := io.in_r.valid && !r_sel
819*8882eb68SXin Tian  io.out_r1.valid := io.in_r.valid &&  r_sel
820*8882eb68SXin Tian  io.in_r.ready := Mux(r_sel, io.out_r1.ready, io.out_r0.ready)
821*8882eb68SXin Tian}