xref: /XiangShan/src/main/scala/xiangshan/package.scala (revision d4aca96cccdcdafa80dd344996e18d1978a01af7)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17import chisel3._
18import chisel3.util._
19
20import chipsalliance.rocketchip.config.Parameters
21import freechips.rocketchip.tile.XLen
22import xiangshan.backend.fu._
23import xiangshan.backend.fu.fpu._
24import xiangshan.backend.exu._
25
26package object xiangshan {
27  object SrcType {
28    def reg = "b00".U
29    def pc  = "b01".U
30    def imm = "b01".U
31    def fp  = "b10".U
32
33    def DC = imm // Don't Care
34
35    def isReg(srcType: UInt) = srcType===reg
36    def isPc(srcType: UInt) = srcType===pc
37    def isImm(srcType: UInt) = srcType===imm
38    def isFp(srcType: UInt) = srcType===fp
39    def isPcImm(srcType: UInt) = srcType(0)
40    def isRegFp(srcType: UInt) = !srcType(0)
41
42    def apply() = UInt(2.W)
43  }
44
45  object SrcState {
46    def busy    = "b0".U
47    def rdy     = "b1".U
48    // def specRdy = "b10".U // speculative ready, for future use
49    def apply() = UInt(1.W)
50  }
51
52  object FuType {
53    def jmp          = "b0000".U
54    def i2f          = "b0001".U
55    def csr          = "b0010".U
56    def alu          = "b0110".U
57    def mul          = "b0100".U
58    def div          = "b0101".U
59    def fence        = "b0011".U
60    def bmu          = "b0111".U
61
62    def fmac         = "b1000".U
63    def fmisc        = "b1011".U
64    def fDivSqrt     = "b1010".U
65
66    def ldu          = "b1100".U
67    def stu          = "b1101".U
68    def mou          = "b1111".U // for amo, lr, sc, fence
69
70    def num = 14
71
72    def apply() = UInt(log2Up(num).W)
73
74    def isIntExu(fuType: UInt) = !fuType(3)
75    def isJumpExu(fuType: UInt) = fuType === jmp
76    def isFpExu(fuType: UInt) = fuType(3, 2) === "b10".U
77    def isMemExu(fuType: UInt) = fuType(3, 2) === "b11".U
78    def isLoadStore(fuType: UInt) = isMemExu(fuType) && !fuType(1)
79    def isStoreExu(fuType: UInt) = isMemExu(fuType) && fuType(0)
80    def isAMO(fuType: UInt) = fuType(1)
81
82    def jmpCanAccept(fuType: UInt) = !fuType(2)
83    def mduCanAccept(fuType: UInt) = fuType(2) && !fuType(1) || fuType(2) && fuType(1) && fuType(0)
84    def aluCanAccept(fuType: UInt) = fuType(2) && fuType(1) && !fuType(0)
85
86    def fmacCanAccept(fuType: UInt) = !fuType(1)
87    def fmiscCanAccept(fuType: UInt) = fuType(1)
88
89    def loadCanAccept(fuType: UInt) = !fuType(0)
90    def storeCanAccept(fuType: UInt) = fuType(0)
91
92    def storeIsAMO(fuType: UInt) = fuType(1)
93
94    val functionNameMap = Map(
95      jmp.litValue() -> "jmp",
96      i2f.litValue() -> "int to float",
97      csr.litValue() -> "csr",
98      alu.litValue() -> "alu",
99      mul.litValue() -> "mul",
100      div.litValue() -> "div",
101      fence.litValue() -> "fence",
102      fmac.litValue() -> "fmac",
103      fmisc.litValue() -> "fmisc",
104      fDivSqrt.litValue() -> "fdiv/fsqrt",
105      ldu.litValue() -> "load",
106      stu.litValue() -> "store"
107    )
108
109  }
110
111  object FuOpType {
112    def apply() = UInt(8.W)
113  }
114
115  object CommitType {
116    def NORMAL = "b00".U  // int/fp
117    def BRANCH = "b01".U  // branch
118    def LOAD   = "b10".U  // load
119    def STORE  = "b11".U  // store
120
121    def apply() = UInt(2.W)
122    def isLoadStore(commitType: UInt) = commitType(1)
123    def lsInstIsStore(commitType: UInt) = commitType(0)
124    def isStore(commitType: UInt) = isLoadStore(commitType) && lsInstIsStore(commitType)
125    def isBranch(commitType: UInt) = commitType(0) && !commitType(1)
126  }
127
128  object RedirectLevel {
129    def flushAfter = "b0".U
130    def flush      = "b1".U
131
132    def apply() = UInt(1.W)
133    // def isUnconditional(level: UInt) = level(1)
134    def flushItself(level: UInt) = level(0)
135    // def isException(level: UInt) = level(1) && level(0)
136  }
137
138  object ExceptionVec {
139    def apply() = Vec(16, Bool())
140  }
141
142  object PMAMode {
143    def R = "b1".U << 0 //readable
144    def W = "b1".U << 1 //writeable
145    def X = "b1".U << 2 //executable
146    def I = "b1".U << 3 //cacheable: icache
147    def D = "b1".U << 4 //cacheable: dcache
148    def S = "b1".U << 5 //enable speculative access
149    def A = "b1".U << 6 //enable atomic operation, A imply R & W
150    def C = "b1".U << 7 //if it is cacheable is configable
151    def Reserved = "b0".U
152
153    def apply() = UInt(7.W)
154
155    def read(mode: UInt) = mode(0)
156    def write(mode: UInt) = mode(1)
157    def execute(mode: UInt) = mode(2)
158    def icache(mode: UInt) = mode(3)
159    def dcache(mode: UInt) = mode(4)
160    def speculate(mode: UInt) = mode(5)
161    def atomic(mode: UInt) = mode(6)
162    def configable_cache(mode: UInt) = mode(7)
163
164    def strToMode(s: String) = {
165      var result = 0.U(8.W)
166      if (s.toUpperCase.indexOf("R") >= 0) result = result + R
167      if (s.toUpperCase.indexOf("W") >= 0) result = result + W
168      if (s.toUpperCase.indexOf("X") >= 0) result = result + X
169      if (s.toUpperCase.indexOf("I") >= 0) result = result + I
170      if (s.toUpperCase.indexOf("D") >= 0) result = result + D
171      if (s.toUpperCase.indexOf("S") >= 0) result = result + S
172      if (s.toUpperCase.indexOf("A") >= 0) result = result + A
173      if (s.toUpperCase.indexOf("C") >= 0) result = result + C
174      result
175    }
176  }
177
178
179  object CSROpType {
180    def jmp  = "b000".U
181    def wrt  = "b001".U
182    def set  = "b010".U
183    def clr  = "b011".U
184    def wrti = "b101".U
185    def seti = "b110".U
186    def clri = "b111".U
187  }
188
189  // jump
190  object JumpOpType {
191    def jal  = "b00".U
192    def jalr = "b01".U
193    def auipc = "b10".U
194//    def call = "b11_011".U
195//    def ret  = "b11_100".U
196    def jumpOpisJalr(op: UInt) = op(0)
197    def jumpOpisAuipc(op: UInt) = op(1)
198  }
199
200  object FenceOpType {
201    def fence  = "b10000".U
202    def sfence = "b10001".U
203    def fencei = "b10010".U
204  }
205
206  object ALUOpType {
207    // misc & branch optype
208    def and         = "b0_00_00_000".U
209    def andn        = "b0_00_00_001".U
210    def or          = "b0_00_00_010".U
211    def orn         = "b0_00_00_011".U
212    def xor         = "b0_00_00_100".U
213    def xnor        = "b0_00_00_101".U
214
215    def sext_b      = "b0_00_01_000".U
216    def sext_h      = "b0_00_01_001".U
217    def zext_h      = "b0_00_01_010".U
218    def orc_b       = "b0_00_01_100".U
219    def rev8        = "b0_00_01_101".U
220
221    def beq         = "b0_00_10_000".U
222    def bne         = "b0_00_10_001".U
223    def blt         = "b0_00_10_100".U
224    def bge         = "b0_00_10_101".U
225    def bltu        = "b0_00_10_110".U
226    def bgeu        = "b0_00_10_111".U
227
228    def slt         = "b0_00_11_000".U
229    def sltu        = "b0_00_11_010".U
230    def max         = "b0_00_11_100".U
231    def min         = "b0_00_11_101".U
232    def maxu        = "b0_00_11_110".U
233    def minu        = "b0_00_11_111".U
234
235    // add & sub optype
236    def add         = "b0_01_00_000".U
237    def add_uw      = "b0_01_00_001".U
238    def sh1add      = "b0_01_00_010".U
239    def sh1add_uw   = "b0_01_00_011".U
240    def sh2add      = "b0_01_00_100".U
241    def sh2add_uw   = "b0_01_00_101".U
242    def sh3add      = "b0_01_00_110".U
243    def sh3add_uw   = "b0_01_00_111".U
244
245    def sub         = "b0_01_01_000".U
246
247    // shift optype
248    def sll         = "b0_10_00_000".U
249    def slli_uw     = "b0_10_00_001".U
250    def bclr        = "b0_10_00_100".U
251    def binv        = "b0_10_00_101".U
252    def bset        = "b0_10_00_110".U
253    def bext        = "b0_10_00_111".U
254
255    def srl         = "b0_10_01_010".U
256    def sra         = "b0_10_01_011".U
257
258    def rol         = "b0_10_10_000".U
259
260    def ror         = "b0_10_11_000".U
261
262    // count optype
263    def clz         = "b0_11_00_000".U
264    def ctz         = "b0_11_00_001".U
265    def cpop        = "b0_11_00_010".U
266
267    // RV64 32bit optype
268    def addw        = "b1_01_00_000".U
269    def subw        = "b1_01_01_000".U
270    def sllw        = "b1_10_00_000".U
271    def srlw        = "b1_10_01_010".U
272    def sraw        = "b1_10_01_011".U
273    def rolw        = "b1_10_10_000".U
274    def rorw        = "b1_10_11_000".U
275    def clzw        = "b1_11_00_000".U
276    def ctzw        = "b1_11_00_001".U
277    def cpopw       = "b1_11_00_010".U
278
279    def isWordOp(func: UInt) = func(7)
280    def isBranch(func: UInt) = func(6, 3) === "b0010".U
281    def getBranchType(func: UInt) = func(2, 1)
282    def isBranchInvert(func: UInt) = func(0)
283
284    def apply() = UInt(8.W)
285  }
286
287  object MDUOpType {
288    // mul
289    // bit encoding: | type (2bit) | isWord(1bit) | opcode(2bit) |
290    def mul    = "b00000".U
291    def mulh   = "b00001".U
292    def mulhsu = "b00010".U
293    def mulhu  = "b00011".U
294    def mulw   = "b00100".U
295
296    // div
297    // bit encoding: | type (2bit) | isWord(1bit) | isSign(1bit) | opcode(1bit) |
298    def div    = "b01000".U
299    def divu   = "b01010".U
300    def rem    = "b01001".U
301    def remu   = "b01011".U
302
303    def divw   = "b01100".U
304    def divuw  = "b01110".U
305    def remw   = "b01101".U
306    def remuw  = "b01111".U
307
308    // fence
309    // bit encoding: | type (2bit) | padding(1bit)(zero) | opcode(2bit) |
310    def fence    = "b10000".U
311    def sfence   = "b10001".U
312    def fencei   = "b10010".U
313
314    // the highest bits are for instruction types
315    def typeMSB = 4
316    def typeLSB = 3
317
318    def MulType     = "b00".U
319    def DivType     = "b01".U
320    def FenceType   = "b10".U
321
322    def isMul(op: UInt)     = op(typeMSB, typeLSB) === MulType
323    def isDiv(op: UInt)     = op(typeMSB, typeLSB) === DivType
324    def isFence(op: UInt)   = op(typeMSB, typeLSB) === FenceType
325
326    def isDivSign(op: UInt) = isDiv(op) && !op(1)
327    def isW(op: UInt) = op(2)
328    def isH(op: UInt) = (isDiv(op) && op(0)) || (isMul(op) && op(1,0)=/=0.U)
329    def getMulOp(op: UInt) = op(1,0)
330  }
331
332  object LSUOpType {
333    // normal load/store
334    // bit(1, 0) are size
335    def lb   = "b000000".U
336    def lh   = "b000001".U
337    def lw   = "b000010".U
338    def ld   = "b000011".U
339    def lbu  = "b000100".U
340    def lhu  = "b000101".U
341    def lwu  = "b000110".U
342    def sb   = "b001000".U
343    def sh   = "b001001".U
344    def sw   = "b001010".U
345    def sd   = "b001011".U
346
347    def isLoad(op: UInt): Bool = !op(3)
348    def isStore(op: UInt): Bool = op(3)
349
350    // atomics
351    // bit(1, 0) are size
352    // since atomics use a different fu type
353    // so we can safely reuse other load/store's encodings
354    def lr_w      = "b000010".U
355    def sc_w      = "b000110".U
356    def amoswap_w = "b001010".U
357    def amoadd_w  = "b001110".U
358    def amoxor_w  = "b010010".U
359    def amoand_w  = "b010110".U
360    def amoor_w   = "b011010".U
361    def amomin_w  = "b011110".U
362    def amomax_w  = "b100010".U
363    def amominu_w = "b100110".U
364    def amomaxu_w = "b101010".U
365
366    def lr_d      = "b000011".U
367    def sc_d      = "b000111".U
368    def amoswap_d = "b001011".U
369    def amoadd_d  = "b001111".U
370    def amoxor_d  = "b010011".U
371    def amoand_d  = "b010111".U
372    def amoor_d   = "b011011".U
373    def amomin_d  = "b011111".U
374    def amomax_d  = "b100011".U
375    def amominu_d = "b100111".U
376    def amomaxu_d = "b101011".U
377  }
378
379  object BMUOpType {
380
381    def clmul       = "b0000".U
382    def clmulh      = "b0010".U
383    def clmulr      = "b0100".U
384
385    def clz         = "b1000".U
386    def clzw        = "b1001".U
387    def ctz         = "b1010".U
388    def ctzw        = "b1011".U
389    def cpop        = "b1100".U
390    def cpopw       = "b1101".U
391  }
392
393  object BTBtype {
394    def B = "b00".U  // branch
395    def J = "b01".U  // jump
396    def I = "b10".U  // indirect
397    def R = "b11".U  // return
398
399    def apply() = UInt(2.W)
400  }
401
402  object SelImm {
403    def IMM_X  = "b0111".U
404    def IMM_S  = "b0000".U
405    def IMM_SB = "b0001".U
406    def IMM_U  = "b0010".U
407    def IMM_UJ = "b0011".U
408    def IMM_I  = "b0100".U
409    def IMM_Z  = "b0101".U
410    def INVALID_INSTR = "b0110".U
411    def IMM_B6 = "b1000".U
412
413    def apply() = UInt(4.W)
414  }
415
416  def dividerGen(p: Parameters) = new SRT4Divider(p(XLen))(p)
417  def multiplierGen(p: Parameters) = new ArrayMultiplier(p(XLen) + 1, Seq(0, 2))(p)
418  def aluGen(p: Parameters) = new Alu()(p)
419  def bmuGen(p: Parameters) = new Bmu()(p)
420  def jmpGen(p: Parameters) = new Jump()(p)
421  def fenceGen(p: Parameters) = new Fence()(p)
422  def csrGen(p: Parameters) = new CSR()(p)
423  def i2fGen(p: Parameters) = new IntToFP()(p)
424  def fmacGen(p: Parameters) = new FMA()(p)
425  def f2iGen(p: Parameters) = new FPToInt()(p)
426  def f2fGen(p: Parameters) = new FPToFP()(p)
427  def fdivSqrtGen(p: Parameters) = new FDivSqrt()(p)
428
429  def f2iSel(x: FunctionUnit): Bool = {
430    x.io.in.bits.uop.ctrl.rfWen
431  }
432
433  def i2fSel(x: FunctionUnit): Bool = {
434    x.io.in.bits.uop.ctrl.fpu.fromInt
435  }
436
437  def f2fSel(x: FunctionUnit): Bool = {
438    val ctrl = x.io.in.bits.uop.ctrl.fpu
439    ctrl.fpWen && !ctrl.div && !ctrl.sqrt
440  }
441
442  def fdivSqrtSel(x: FunctionUnit): Bool = {
443    val ctrl = x.io.in.bits.uop.ctrl.fpu
444    ctrl.div || ctrl.sqrt
445  }
446
447  val aluCfg = FuConfig(
448    fuGen = aluGen,
449    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.alu,
450    fuType = FuType.alu,
451    numIntSrc = 2,
452    numFpSrc = 0,
453    writeIntRf = true,
454    writeFpRf = false,
455    hasRedirect = true,
456  )
457
458  val jmpCfg = FuConfig(
459    fuGen = jmpGen,
460    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp,
461    fuType = FuType.jmp,
462    numIntSrc = 1,
463    numFpSrc = 0,
464    writeIntRf = true,
465    writeFpRf = false,
466    hasRedirect = true,
467  )
468
469  val fenceCfg = FuConfig(
470    fuGen = fenceGen,
471    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence,
472    FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
473    UncertainLatency() // TODO: need rewrite latency structure, not just this value
474  )
475
476  val csrCfg = FuConfig(
477    fuGen = csrGen,
478    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr,
479    fuType = FuType.csr,
480    numIntSrc = 1,
481    numFpSrc = 0,
482    writeIntRf = true,
483    writeFpRf = false,
484    hasRedirect = false
485  )
486
487  val i2fCfg = FuConfig(
488    fuGen = i2fGen,
489    fuSel = i2fSel,
490    FuType.i2f,
491    numIntSrc = 1,
492    numFpSrc = 0,
493    writeIntRf = false,
494    writeFpRf = true,
495    hasRedirect = false,
496    UncertainLatency()
497  )
498
499  val divCfg = FuConfig(
500    fuGen = dividerGen,
501    fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType),
502    FuType.div,
503    2,
504    0,
505    writeIntRf = true,
506    writeFpRf = false,
507    hasRedirect = false,
508    UncertainLatency()
509  )
510
511  val mulCfg = FuConfig(
512    fuGen = multiplierGen,
513    fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType),
514    FuType.mul,
515    2,
516    0,
517    writeIntRf = true,
518    writeFpRf = false,
519    hasRedirect = false,
520    CertainLatency(2)
521  )
522
523   val bmuCfg = FuConfig(
524   fuGen = bmuGen,
525   fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.bmu,
526   fuType = FuType.bmu,
527   numIntSrc = 2,
528   numFpSrc = 0,
529   writeIntRf = true,
530   writeFpRf = false,
531   hasRedirect = false,
532   CertainLatency(1)
533 )
534
535  val fmacCfg = FuConfig(
536    fuGen = fmacGen,
537    fuSel = _ => true.B,
538    FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(4)
539  )
540
541  val f2iCfg = FuConfig(
542    fuGen = f2iGen,
543    fuSel = f2iSel,
544    FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
545  )
546
547  val f2fCfg = FuConfig(
548    fuGen = f2fGen,
549    fuSel = f2fSel,
550    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
551  )
552
553  val fdivSqrtCfg = FuConfig(
554    fuGen = fdivSqrtGen,
555    fuSel = fdivSqrtSel,
556    FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency()
557  )
558
559  val lduCfg = FuConfig(
560    null, // DontCare
561    null,
562    FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
563    UncertainLatency()
564  )
565
566  val stuCfg = FuConfig(
567    null,
568    null,
569    FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
570    UncertainLatency()
571  )
572
573  val mouCfg = FuConfig(
574    null,
575    null,
576    FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
577    UncertainLatency()
578  )
579
580  val JumpExeUnitCfg = ExuConfig("JmpExeUnit", "Int", Seq(jmpCfg, i2fCfg), 2, Int.MaxValue)
581  val AluExeUnitCfg = ExuConfig("AluExeUnit", "Int", Seq(aluCfg), 0, Int.MaxValue)
582  val JumpCSRExeUnitCfg = ExuConfig("JmpCSRExeUnit", "Int", Seq(jmpCfg, csrCfg, fenceCfg, i2fCfg), 2, Int.MaxValue)
583  val MulDivExeUnitCfg = ExuConfig("MulDivExeUnit", "Int", Seq(mulCfg, divCfg, bmuCfg), 1, Int.MaxValue)
584  val FmacExeUnitCfg = ExuConfig("FmacExeUnit", "Fp", Seq(fmacCfg), Int.MaxValue, 0)
585  val FmiscExeUnitCfg = ExuConfig(
586    "FmiscExeUnit",
587    "Fp",
588    Seq(f2iCfg, f2fCfg, fdivSqrtCfg),
589    Int.MaxValue, 1
590  )
591  val LdExeUnitCfg = ExuConfig("LoadExu", "Mem", Seq(lduCfg), wbIntPriority = 0, wbFpPriority = 0)
592  val StExeUnitCfg = ExuConfig("StoreExu", "Mem", Seq(stuCfg, mouCfg), wbIntPriority = Int.MaxValue, wbFpPriority = Int.MaxValue)
593}