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