xref: /XiangShan/src/main/scala/xiangshan/package.scala (revision 2225d46ebbe2fd16b9b29963c27a7d0385a42709)
1import chisel3._
2import chisel3.util._
3
4import chipsalliance.rocketchip.config.Parameters
5import freechips.rocketchip.tile.XLen
6import xiangshan.backend.fu._
7import xiangshan.backend.fu.fpu._
8import xiangshan.backend.exu._
9
10package object xiangshan {
11  object SrcType {
12    def reg = "b00".U
13    def pc  = "b01".U
14    def imm = "b01".U
15    def fp  = "b10".U
16
17    def DC = imm // Don't Care
18
19    def isReg(srcType: UInt) = srcType===reg
20    def isPc(srcType: UInt) = srcType===pc
21    def isImm(srcType: UInt) = srcType===imm
22    def isFp(srcType: UInt) = srcType===fp
23    def isPcImm(srcType: UInt) = isPc(srcType) || isImm(srcType)
24    def isRegFp(srcType: UInt) = isReg(srcType) || isFp(srcType)
25
26    def apply() = UInt(2.W)
27  }
28
29  object SrcState {
30    def busy    = "b0".U
31    def rdy     = "b1".U
32    // def specRdy = "b10".U // speculative ready, for future use
33    def apply() = UInt(1.W)
34  }
35
36  object FuType {
37    def jmp          = "b0000".U
38    def i2f          = "b0001".U
39    def csr          = "b0010".U
40    def alu          = "b0110".U
41    def mul          = "b0100".U
42    def div          = "b0101".U
43    def fence        = "b0011".U
44
45    def fmac         = "b1000".U
46    def fmisc        = "b1011".U
47    def fDivSqrt     = "b1010".U
48
49    def ldu          = "b1100".U
50    def stu          = "b1101".U
51    def mou          = "b1111".U // for amo, lr, sc, fence
52
53    def num = 13
54
55    def apply() = UInt(log2Up(num).W)
56
57    def isIntExu(fuType: UInt) = !fuType(3)
58    def isJumpExu(fuType: UInt) = fuType === jmp
59    def isFpExu(fuType: UInt) = fuType(3, 2) === "b10".U
60    def isMemExu(fuType: UInt) = fuType(3, 2) === "b11".U
61    def isLoadStore(fuType: UInt) = isMemExu(fuType) && !fuType(1)
62    def isStoreExu(fuType: UInt) = isMemExu(fuType) && fuType(0)
63    def isAMO(fuType: UInt) = fuType(1)
64
65    def jmpCanAccept(fuType: UInt) = !fuType(2)
66    def mduCanAccept(fuType: UInt) = fuType(2) && !fuType(1)
67    def aluCanAccept(fuType: UInt) = fuType(2) && fuType(1)
68
69    def fmacCanAccept(fuType: UInt) = !fuType(1)
70    def fmiscCanAccept(fuType: UInt) = fuType(1)
71
72    def loadCanAccept(fuType: UInt) = !fuType(0)
73    def storeCanAccept(fuType: UInt) = fuType(0)
74
75    def storeIsAMO(fuType: UInt) = fuType(1)
76
77    val functionNameMap = Map(
78      jmp.litValue() -> "jmp",
79      i2f.litValue() -> "int to float",
80      csr.litValue() -> "csr",
81      alu.litValue() -> "alu",
82      mul.litValue() -> "mul",
83      div.litValue() -> "div",
84      fence.litValue() -> "fence",
85      fmac.litValue() -> "fmac",
86      fmisc.litValue() -> "fmisc",
87      fDivSqrt.litValue() -> "fdiv/fsqrt",
88      ldu.litValue() -> "load",
89      stu.litValue() -> "store"
90    )
91
92  }
93
94  object FuOpType {
95    def apply() = UInt(6.W)
96  }
97
98  object CommitType {
99    def NORMAL = "b00".U  // int/fp
100    def BRANCH = "b01".U  // branch
101    def LOAD   = "b10".U  // load
102    def STORE  = "b11".U  // store
103
104    def apply() = UInt(2.W)
105    def isLoadStore(commitType: UInt) = commitType(1)
106    def lsInstIsStore(commitType: UInt) = commitType(0)
107    def isStore(commitType: UInt) = isLoadStore(commitType) && lsInstIsStore(commitType)
108    def isBranch(commitType: UInt) = commitType(0) && !commitType(1)
109  }
110
111  object RedirectLevel {
112    def flushAfter = "b0".U
113    def flush      = "b1".U
114
115    def apply() = UInt(1.W)
116    // def isUnconditional(level: UInt) = level(1)
117    def flushItself(level: UInt) = level(0)
118    // def isException(level: UInt) = level(1) && level(0)
119  }
120
121  object ExceptionVec {
122    def apply() = Vec(16, Bool())
123  }
124
125  object PMAMode {
126    def R = "b1".U << 0 //readable
127    def W = "b1".U << 1 //writeable
128    def X = "b1".U << 2 //executable
129    def I = "b1".U << 3 //cacheable: icache
130    def D = "b1".U << 4 //cacheable: dcache
131    def S = "b1".U << 5 //enable speculative access
132    def A = "b1".U << 6 //enable atomic operation, A imply R & W
133    def C = "b1".U << 7 //if it is cacheable is configable
134    def Reserved = "b0".U
135
136    def apply() = UInt(7.W)
137
138    def read(mode: UInt) = mode(0)
139    def write(mode: UInt) = mode(1)
140    def execute(mode: UInt) = mode(2)
141    def icache(mode: UInt) = mode(3)
142    def dcache(mode: UInt) = mode(4)
143    def speculate(mode: UInt) = mode(5)
144    def atomic(mode: UInt) = mode(6)
145    def configable_cache(mode: UInt) = mode(7)
146
147    def strToMode(s: String) = {
148      var result = 0.U(8.W)
149      if (s.toUpperCase.indexOf("R") >= 0) result = result + R
150      if (s.toUpperCase.indexOf("W") >= 0) result = result + W
151      if (s.toUpperCase.indexOf("X") >= 0) result = result + X
152      if (s.toUpperCase.indexOf("I") >= 0) result = result + I
153      if (s.toUpperCase.indexOf("D") >= 0) result = result + D
154      if (s.toUpperCase.indexOf("S") >= 0) result = result + S
155      if (s.toUpperCase.indexOf("A") >= 0) result = result + A
156      if (s.toUpperCase.indexOf("C") >= 0) result = result + C
157      result
158    }
159  }
160
161
162  object CSROpType {
163    def jmp  = "b000".U
164    def wrt  = "b001".U
165    def set  = "b010".U
166    def clr  = "b011".U
167    def wrti = "b101".U
168    def seti = "b110".U
169    def clri = "b111".U
170  }
171
172  // jump
173  object JumpOpType {
174    def jal  = "b00".U
175    def jalr = "b01".U
176    def auipc = "b10".U
177//    def call = "b11_011".U
178//    def ret  = "b11_100".U
179    def jumpOpisJalr(op: UInt) = op(0)
180    def jumpOpisAuipc(op: UInt) = op(1)
181  }
182
183  object FenceOpType {
184    def fence  = "b10000".U
185    def sfence = "b10001".U
186    def fencei = "b10010".U
187  }
188
189  object ALUOpType {
190    def add  = "b000000".U
191    def sll  = "b000001".U
192    def slt  = "b000010".U
193    def sltu = "b000011".U
194    def xor  = "b000100".U
195    def srl  = "b000101".U
196    def or   = "b000110".U
197    def and  = "b000111".U
198    def sub  = "b001000".U
199    def sra  = "b001101".U
200
201    def addw = "b100000".U
202    def subw = "b101000".U
203    def sllw = "b100001".U
204    def srlw = "b100101".U
205    def sraw = "b101101".U
206
207    def isAddSub(func: UInt) = {
208      func === add || func === sub || func === addw || func === subw
209    }
210
211    def isWordOp(func: UInt) = func(5)
212
213    def beq  = "b010000".U
214    def bne  = "b010001".U
215    def blt  = "b010100".U
216    def bge  = "b010101".U
217    def bltu = "b010110".U
218    def bgeu = "b010111".U
219
220    def isBranch(func: UInt) = func(4)
221    def getBranchType(func: UInt) = func(2, 1)
222    def isBranchInvert(func: UInt) = func(0)
223  }
224
225  object MDUOpType {
226    // mul
227    // bit encoding: | type (2bit) | isWord(1bit) | opcode(2bit) |
228    def mul    = "b00000".U
229    def mulh   = "b00001".U
230    def mulhsu = "b00010".U
231    def mulhu  = "b00011".U
232    def mulw   = "b00100".U
233
234    // div
235    // bit encoding: | type (2bit) | isWord(1bit) | isSign(1bit) | opcode(1bit) |
236    def div    = "b01000".U
237    def divu   = "b01010".U
238    def rem    = "b01001".U
239    def remu   = "b01011".U
240
241    def divw   = "b01100".U
242    def divuw  = "b01110".U
243    def remw   = "b01101".U
244    def remuw  = "b01111".U
245
246    // fence
247    // bit encoding: | type (2bit) | padding(1bit)(zero) | opcode(2bit) |
248    def fence    = "b10000".U
249    def sfence   = "b10001".U
250    def fencei   = "b10010".U
251
252    // the highest bits are for instruction types
253    def typeMSB = 4
254    def typeLSB = 3
255
256    def MulType     = "b00".U
257    def DivType     = "b01".U
258    def FenceType   = "b10".U
259
260    def isMul(op: UInt)     = op(typeMSB, typeLSB) === MulType
261    def isDiv(op: UInt)     = op(typeMSB, typeLSB) === DivType
262    def isFence(op: UInt)   = op(typeMSB, typeLSB) === FenceType
263
264    def isDivSign(op: UInt) = isDiv(op) && !op(1)
265    def isW(op: UInt) = op(2)
266    def isH(op: UInt) = (isDiv(op) && op(0)) || (isMul(op) && op(1,0)=/=0.U)
267    def getMulOp(op: UInt) = op(1,0)
268  }
269
270  object LSUOpType {
271    // normal load/store
272    // bit(1, 0) are size
273    def lb   = "b000000".U
274    def lh   = "b000001".U
275    def lw   = "b000010".U
276    def ld   = "b000011".U
277    def lbu  = "b000100".U
278    def lhu  = "b000101".U
279    def lwu  = "b000110".U
280    def sb   = "b001000".U
281    def sh   = "b001001".U
282    def sw   = "b001010".U
283    def sd   = "b001011".U
284
285    def isLoad(op: UInt): Bool = !op(3)
286    def isStore(op: UInt): Bool = op(3)
287
288    // atomics
289    // bit(1, 0) are size
290    // since atomics use a different fu type
291    // so we can safely reuse other load/store's encodings
292    def lr_w      = "b000010".U
293    def sc_w      = "b000110".U
294    def amoswap_w = "b001010".U
295    def amoadd_w  = "b001110".U
296    def amoxor_w  = "b010010".U
297    def amoand_w  = "b010110".U
298    def amoor_w   = "b011010".U
299    def amomin_w  = "b011110".U
300    def amomax_w  = "b100010".U
301    def amominu_w = "b100110".U
302    def amomaxu_w = "b101010".U
303
304    def lr_d      = "b000011".U
305    def sc_d      = "b000111".U
306    def amoswap_d = "b001011".U
307    def amoadd_d  = "b001111".U
308    def amoxor_d  = "b010011".U
309    def amoand_d  = "b010111".U
310    def amoor_d   = "b011011".U
311    def amomin_d  = "b011111".U
312    def amomax_d  = "b100011".U
313    def amominu_d = "b100111".U
314    def amomaxu_d = "b101011".U
315  }
316
317  object BTBtype {
318    def B = "b00".U  // branch
319    def J = "b01".U  // jump
320    def I = "b10".U  // indirect
321    def R = "b11".U  // return
322
323    def apply() = UInt(2.W)
324  }
325
326  object SelImm {
327    def IMM_X  = "b111".U
328    def IMM_S  = "b000".U
329    def IMM_SB = "b001".U
330    def IMM_U  = "b010".U
331    def IMM_UJ = "b011".U
332    def IMM_I  = "b100".U
333    def IMM_Z  = "b101".U
334    def INVALID_INSTR = "b110".U
335
336    def apply() = UInt(3.W)
337  }
338
339  def dividerGen(p: Parameters) = new SRT4Divider(p(XLen))(p)
340  def multiplierGen(p: Parameters) = new ArrayMultiplier(p(XLen) + 1, Seq(0, 2))(p)
341  def aluGen(p: Parameters) = new Alu()(p)
342  def jmpGen(p: Parameters) = new Jump()(p)
343  def fenceGen(p: Parameters) = new Fence()(p)
344  def csrGen(p: Parameters) = new CSR()(p)
345  def i2fGen(p: Parameters) = new IntToFP()(p)
346  def fmacGen(p: Parameters) = new FMA()(p)
347  def f2iGen(p: Parameters) = new FPToInt()(p)
348  def f2fGen(p: Parameters) = new FPToFP()(p)
349  def fdivSqrtGen(p: Parameters) = new FDivSqrt()(p)
350
351  def f2iSel(x: FunctionUnit): Bool = {
352    x.io.in.bits.uop.ctrl.rfWen
353  }
354
355  def i2fSel(x: FunctionUnit): Bool = {
356    x.io.in.bits.uop.ctrl.fpu.fromInt
357  }
358
359  def f2fSel(x: FunctionUnit): Bool = {
360    val ctrl = x.io.in.bits.uop.ctrl.fpu
361    ctrl.fpWen && !ctrl.div && !ctrl.sqrt
362  }
363
364  def fdivSqrtSel(x: FunctionUnit): Bool = {
365    val ctrl = x.io.in.bits.uop.ctrl.fpu
366    ctrl.div || ctrl.sqrt
367  }
368
369  val aluCfg = FuConfig(
370    fuGen = aluGen,
371    fuSel = _ => true.B,
372    fuType = FuType.alu,
373    numIntSrc = 2,
374    numFpSrc = 0,
375    writeIntRf = true,
376    writeFpRf = false,
377    hasRedirect = true,
378  )
379
380  val jmpCfg = FuConfig(
381    fuGen = jmpGen,
382    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp,
383    fuType = FuType.jmp,
384    numIntSrc = 1,
385    numFpSrc = 0,
386    writeIntRf = true,
387    writeFpRf = false,
388    hasRedirect = true,
389  )
390
391  val fenceCfg = FuConfig(
392    fuGen = fenceGen,
393    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence,
394    FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
395    UncertainLatency() // TODO: need rewrite latency structure, not just this value
396  )
397
398  val csrCfg = FuConfig(
399    fuGen = csrGen,
400    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr,
401    fuType = FuType.csr,
402    numIntSrc = 1,
403    numFpSrc = 0,
404    writeIntRf = true,
405    writeFpRf = false,
406    hasRedirect = false
407  )
408
409  val i2fCfg = FuConfig(
410    fuGen = i2fGen,
411    fuSel = i2fSel,
412    FuType.i2f,
413    numIntSrc = 1,
414    numFpSrc = 0,
415    writeIntRf = false,
416    writeFpRf = true,
417    hasRedirect = false,
418    UncertainLatency()
419  )
420
421  val divCfg = FuConfig(
422    fuGen = dividerGen,
423    fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType),
424    FuType.div,
425    2,
426    0,
427    writeIntRf = true,
428    writeFpRf = false,
429    hasRedirect = false,
430    UncertainLatency()
431  )
432
433  val mulCfg = FuConfig(
434    fuGen = multiplierGen,
435    fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType),
436    FuType.mul,
437    2,
438    0,
439    writeIntRf = true,
440    writeFpRf = false,
441    hasRedirect = false,
442    CertainLatency(3)
443  )
444
445  val fmacCfg = FuConfig(
446    fuGen = fmacGen,
447    fuSel = _ => true.B,
448    FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(4)
449  )
450
451  val f2iCfg = FuConfig(
452    fuGen = f2iGen,
453    fuSel = f2iSel,
454    FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
455  )
456
457  val f2fCfg = FuConfig(
458    fuGen = f2fGen,
459    fuSel = f2fSel,
460    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
461  )
462
463  val fdivSqrtCfg = FuConfig(
464    fuGen = fdivSqrtGen,
465    fuSel = fdivSqrtSel,
466    FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency()
467  )
468
469  val lduCfg = FuConfig(
470    null, // DontCare
471    null,
472    FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
473    UncertainLatency()
474  )
475
476  val stuCfg = FuConfig(
477    null,
478    null,
479    FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
480    UncertainLatency()
481  )
482
483  val mouCfg = FuConfig(
484    null,
485    null,
486    FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
487    UncertainLatency()
488  )
489
490  val AluExeUnitCfg = ExuConfig("AluExeUnit", Seq(aluCfg), 0, Int.MaxValue)
491  val JumpExeUnitCfg = ExuConfig("JmpExeUnit", Seq(jmpCfg, csrCfg, fenceCfg, i2fCfg), 2, Int.MaxValue)
492  val MulDivExeUnitCfg = ExuConfig("MulDivExeUnit", Seq(mulCfg, divCfg), 1, Int.MaxValue)
493  val FmacExeUnitCfg = ExuConfig("FmacExeUnit", Seq(fmacCfg), Int.MaxValue, 0)
494  val FmiscExeUnitCfg = ExuConfig(
495    "FmiscExeUnit",
496    Seq(f2iCfg, f2fCfg, fdivSqrtCfg),
497    Int.MaxValue, 1
498  )
499  val LdExeUnitCfg = ExuConfig("LoadExu", Seq(lduCfg), wbIntPriority = 0, wbFpPriority = 0)
500  val StExeUnitCfg = ExuConfig("StoreExu", Seq(stuCfg, mouCfg), wbIntPriority = Int.MaxValue, wbFpPriority = Int.MaxValue)
501}
502