1package xiangshan.backend.fu.NewCSR 2 3import chisel3._ 4import chisel3.util._ 5import freechips.rocketchip.rocket.CSRs 6import difftest._ 7import org.chipsalliance.cde.config.Parameters 8import top.{ArgParser, Generator} 9import utility.{DataHoldBypass, SignExt, ZeroExt} 10import utils.OptionWrapper 11import xiangshan.backend.fu.NewCSR.CSRBundles.{CSRCustomState, PrivState, RobCommitCSR} 12import xiangshan.backend.fu.NewCSR.CSRDefines.{ContextStatus, PrivMode, SatpMode, VirtMode} 13import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ 14import xiangshan.backend.fu.NewCSR.CSREvents.{CSREvents, DretEventSinkBundle, EventUpdatePrivStateOutput, MretEventSinkBundle, SretEventSinkBundle, TrapEntryDEventSinkBundle, TrapEntryEventInput, TrapEntryHSEventSinkBundle, TrapEntryMEventSinkBundle, TrapEntryVSEventSinkBundle} 15import xiangshan.backend.fu.fpu.Bundles.Frm 16import xiangshan.backend.fu.vector.Bundles.{Vl, Vstart, Vxrm, Vxsat} 17import xiangshan.backend.fu.wrapper.CSRToDecode 18import xiangshan.{FrontendTdataDistributeIO, HasXSParameter, MemTdataDistributeIO, XSCoreParamsKey, XSTileKey} 19import xiangshan._ 20import xiangshan.backend.fu.util.CSRConst 21 22import scala.collection.immutable.SeqMap 23 24object CSRConfig { 25 final val GEILEN = 63 26 27 final val ASIDLEN = 16 // the length of ASID of XS implementation 28 29 final val ASIDMAX = 16 // the max value of ASIDLEN defined by spec 30 31 final val HIIDWidth = 12 // support Hvictl[27:16](IID) 32 33 final val VMIDLEN = 14 // the length of VMID of XS implementation 34 35 final val VMIDMAX = 14 // the max value of VMIDLEN defined by spec 36 37 // the width of VGEIN 38 final val VGEINWidth = 6 39 40 final val VaddrMaxWidth = 41 // only Sv39 and Sv39x4 41 42 final val XLEN = 64 // Todo: use XSParams 43 44 final val VLEN = 128 45 46 // Since we need macro to compute the width of CSR field, the input of macro should be the value that can be computed 47 // at compile time. The log2Up function cannot be used as meta-programming function, so we use litral value here 48 // log2Up(128 + 1), hold 0~128 49 final val VlWidth = 8 50 51 final val PAddrWidth = 36 52 53 final val AddrWidthInPage = 12 54 55 final val PMPAddrWidth = 36 56 57 final val PMPOffBits = 2 58 59 final val PMPAddrBits = PMPAddrWidth - PMPOffBits 60 61 // trigger 62 final val triggerNum = 4 // Todo: use XSParams 63 final val tselectWidth = 2 // log2Up(triggerNum) 64} 65 66class NewCSR(implicit val p: Parameters) extends Module 67 with HasXSParameter 68 with MachineLevel 69 with SupervisorLevel 70 with HypervisorLevel 71 with VirtualSupervisorLevel 72 with Unprivileged 73 with CSRAIA 74 with HasExternalInterruptBundle 75 with SupervisorMachineAliasConnect 76 with CSREvents 77 with DebugLevel 78 with CSRCustom 79 with CSRPMP 80{ 81 82 import CSRConfig._ 83 84 val io = IO(new Bundle { 85 val fromTop = Input(new Bundle { 86 val hartId = UInt(hartIdLen.W) 87 }) 88 val in = Input(new Bundle { 89 val wen = Bool() 90 val ren = Bool() 91 val addr = UInt(12.W) 92 val wdata = UInt(64.W) 93 }) 94 val fromMem = Input(new Bundle { 95 val excpVA = UInt(VaddrMaxWidth.W) 96 val excpGPA = UInt(VaddrMaxWidth.W) // Todo: use guest physical address width 97 }) 98 val fromRob = Input(new Bundle { 99 val trap = ValidIO(new Bundle { 100 val pc = UInt(VaddrMaxWidth.W) 101 val instr = UInt(32.W) 102 val trapVec = UInt(64.W) 103 val singleStep = Bool() 104 val triggerCf = new TriggerCf 105 val crossPageIPFFix = Bool() 106 val isInterrupt = Bool() 107 }) 108 val commit = Input(new RobCommitCSR) 109 }) 110 val mret = Input(Bool()) 111 val sret = Input(Bool()) 112 val dret = Input(Bool()) 113 val wfi = Input(Bool()) 114 val ebreak = Input(Bool()) 115 116 val out = Output(new Bundle { 117 val EX_II = Bool() 118 val EX_VI = Bool() 119 val flushPipe = Bool() 120 val rData = UInt(64.W) 121 val targetPc = UInt(VaddrMaxWidth.W) 122 val regOut = UInt(64.W) 123 val privState = new PrivState 124 val interrupt = Bool() 125 val wfiEvent = Bool() 126 val tvm = Bool() 127 val vtvm = Bool() 128 // fp 129 val fpState = new Bundle { 130 val off = Bool() 131 val frm = Frm() 132 } 133 // vec 134 val vecState = new Bundle { 135 val vstart = Vstart() 136 val vxsat = Vxsat() 137 val vxrm = Vxrm() 138 val vcsr = UInt(XLEN.W) 139 val vl = Vl() 140 val vtype = UInt(XLEN.W) 141 val vlenb = UInt(XLEN.W) 142 val off = Bool() 143 } 144 // perf 145 val isPerfCnt = Bool() 146 // debug 147 val debugMode = Bool() 148 val singleStepFlag = Bool() 149 // trigger 150 val frontendTrigger = new FrontendTdataDistributeIO() 151 val memTrigger = new MemTdataDistributeIO() 152 // custom 153 val custom = new CSRCustomState 154 }) 155 // tlb 156 val tlb = Output(new Bundle { 157 val satpASIDChanged = Bool() 158 val vsatpASIDChanged = Bool() 159 val hgatpVMIDChanged = Bool() 160 val satp = new SatpBundle 161 val vsatp = new SatpBundle 162 val hgatp = new HgatpBundle 163 val mxr = Bool() 164 val sum = Bool() 165 val vmxr = Bool() 166 val vsum = Bool() 167 val spvp = Bool() 168 val imode = UInt(2.W) 169 val dmode = UInt(2.W) 170 }) 171 172 val toDecode = new CSRToDecode 173 }) 174 175 val toAIA = IO(Output(new CSRToAIABundle)) 176 val fromAIA = IO(Flipped(Output(new AIAToCSRBundle))) 177 178 dontTouch(toAIA) 179 dontTouch(fromAIA) 180 181 val wen = io.in.wen 182 val addr = io.in.addr 183 val wdata = io.in.wdata 184 185 val ren = io.in.ren 186 val raddr = io.in.addr 187 188 val hasTrap = io.fromRob.trap.valid 189 val trapVec = io.fromRob.trap.bits.trapVec 190 val trapPC = io.fromRob.trap.bits.pc 191 val trapIsInterrupt = io.fromRob.trap.bits.isInterrupt 192 val trapIsCrossPageIPF = io.fromRob.trap.bits.crossPageIPFFix 193 val triggerCf = io.fromRob.trap.bits.triggerCf 194 195 // debug_intrrupt 196 val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable 197 val debugIntr = platformIRP.debugIP && debugIntrEnable 198 199 // CSR Privilege State 200 val PRVM = RegInit(PrivMode(0), PrivMode.M) 201 val V = RegInit(VirtMode(0), VirtMode.Off) 202 val debugMode = RegInit(false.B) 203 204 private val privState = Wire(new PrivState) 205 privState.PRVM := PRVM 206 privState.V := V 207 208 private val isModeM = privState.isModeM 209 private val (isModeHS, isModeHU) = (privState.isModeHS, privState.isModeHU) 210 private val (isModeVS, isModeVU) = (privState.isModeVS, privState.isModeVU) 211 212 val permitMod = Module(new CSRPermitModule) 213 214 private val wenLegal = permitMod.io.out.hasLegalWen 215 216 val legalSret = permitMod.io.out.hasLegalSret 217 val legalMret = permitMod.io.out.hasLegalMret 218 val isDret = io.dret // Todo: check permission 219 val isWfi = permitMod.io.out.hasLegalWfi 220 221 var csrRwMap: SeqMap[Int, (CSRAddrWriteBundle[_], Data)] = 222 machineLevelCSRMap ++ 223 supervisorLevelCSRMap ++ 224 hypervisorCSRMap ++ 225 virtualSupervisorCSRMap ++ 226 unprivilegedCSRMap ++ 227 debugCSRMap ++ 228 aiaCSRMap ++ 229 customCSRMap ++ 230 pmpCSRMap 231 232 val csrMods: Seq[CSRModule[_]] = 233 machineLevelCSRMods ++ 234 supervisorLevelCSRMods ++ 235 hypervisorCSRMods ++ 236 virtualSupervisorCSRMods ++ 237 unprivilegedCSRMods ++ 238 debugCSRMods ++ 239 aiaCSRMods ++ 240 customCSRMods ++ 241 pmpCSRMods 242 243 var csrOutMap: SeqMap[Int, UInt] = 244 machineLevelCSROutMap ++ 245 supervisorLevelCSROutMap ++ 246 hypervisorCSROutMap ++ 247 virtualSupervisorCSROutMap ++ 248 unprivilegedCSROutMap ++ 249 debugCSROutMap ++ 250 aiaCSROutMap ++ 251 customCSROutMap ++ 252 pmpCSROutMap 253 254 // interrupt 255 val intrMod = Module(new InterruptFilter) 256 intrMod.io.in.privState := privState 257 intrMod.io.in.mstatusMIE := mstatus.regOut.MIE.asBool 258 intrMod.io.in.sstatusSIE := mstatus.regOut.SIE.asBool 259 intrMod.io.in.vsstatusSIE := vsstatus.regOut.SIE.asBool 260 intrMod.io.in.mip := mip.rdata.asUInt 261 intrMod.io.in.mie := mie.rdata.asUInt 262 intrMod.io.in.mideleg := mideleg.rdata.asUInt 263 intrMod.io.in.sip := sip.rdata.asUInt 264 intrMod.io.in.sie := sie.rdata.asUInt 265 intrMod.io.in.hip := hip.rdata.asUInt 266 intrMod.io.in.hie := hie.rdata.asUInt 267 intrMod.io.in.hideleg := hideleg.rdata.asUInt 268 intrMod.io.in.vsip := vsip.rdata.asUInt 269 intrMod.io.in.vsie := vsie.rdata.asUInt 270 intrMod.io.in.hvictl := hvictl.rdata.asUInt 271 intrMod.io.in.hstatus := hstatus.rdata.asUInt 272 intrMod.io.in.mtopei := mtopei.rdata.asUInt 273 intrMod.io.in.stopei := stopei.rdata.asUInt 274 intrMod.io.in.vstopei := vstopei.rdata.asUInt 275 intrMod.io.in.hviprio1 := hviprio1.rdata.asUInt 276 intrMod.io.in.hviprio2 := hviprio2.rdata.asUInt 277 intrMod.io.in.miprios := Cat(miregiprios.map(_.rdata).reverse) 278 intrMod.io.in.hsiprios := Cat(siregiprios.map(_.rdata).reverse) 279 // val disableInterrupt = debugMode || (dcsr.rdata.STEP.asBool && !dcsr.rdata.STEPIE.asBool) 280 // val intrVec = Cat(debugIntr && !debugMode, mie.rdata.asUInt(11, 0) & mip.rdata.asUInt & intrVecEnable.asUInt) // Todo: asUInt(11,0) is ok? 281 282 val intrVec = RegEnable(intrMod.io.out.interruptVec.bits, 0.U, intrMod.io.out.interruptVec.valid) 283 284 val trapHandleMod = Module(new TrapHandleModule) 285 286 trapHandleMod.io.in.trapInfo.valid := hasTrap 287 trapHandleMod.io.in.trapInfo.bits.trapVec := trapVec.asUInt 288 trapHandleMod.io.in.trapInfo.bits.intrVec := intrVec 289 trapHandleMod.io.in.trapInfo.bits.isInterrupt := trapIsInterrupt 290 trapHandleMod.io.in.privState := privState 291 trapHandleMod.io.in.mideleg := mideleg.regOut 292 trapHandleMod.io.in.medeleg := medeleg.regOut 293 trapHandleMod.io.in.hideleg := hideleg.regOut 294 trapHandleMod.io.in.hedeleg := hedeleg.regOut 295 trapHandleMod.io.in.mtvec := mtvec.regOut 296 trapHandleMod.io.in.stvec := stvec.regOut 297 trapHandleMod.io.in.vstvec := vstvec.regOut 298 299 val entryPrivState = trapHandleMod.io.out.entryPrivState 300 301 // PMP 302 val pmpEntryMod = Module(new PMPEntryHandleModule) 303 pmpEntryMod.io.in.pmpCfg := cfgs.map(_.regOut.asInstanceOf[PMPCfgBundle]) 304 pmpEntryMod.io.in.pmpAddr := pmpaddr.map(_.regOut.asInstanceOf[PMPAddrBundle]) 305 pmpEntryMod.io.in.ren := ren 306 pmpEntryMod.io.in.wen := wen 307 pmpEntryMod.io.in.addr := addr 308 pmpEntryMod.io.in.wdata := wdata 309 310 for ((id, (wBundle, _)) <- csrRwMap) { 311 if (vsMapS.contains(id)) { 312 // VS access CSR by S: privState.isModeVS && addrMappedToVS === sMapVS(id).U 313 wBundle.wen := wenLegal && ((isModeVS && addr === vsMapS(id).U) || (!isModeVS && addr === id.U)) 314 wBundle.wdata := wdata 315 } else if (sMapVS.contains(id)) { 316 wBundle.wen := wenLegal && !isModeVS && addr === id.U 317 wBundle.wdata := wdata 318 } else { 319 wBundle.wen := wenLegal && addr === id.U 320 wBundle.wdata := wdata 321 } 322 } 323 324 // Todo: support set dirty only when fcsr has changed 325 private val writeFpState = wenLegal && Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _) 326 private val writeVecState = wenLegal && Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _) 327 328 permitMod.io.in.csrAccess.ren := ren 329 permitMod.io.in.csrAccess.wen := wen 330 permitMod.io.in.csrAccess.addr := addr 331 332 permitMod.io.in.privState := privState 333 permitMod.io.in.debugMode := debugMode 334 335 permitMod.io.in.mret := io.mret 336 permitMod.io.in.sret := io.sret 337 permitMod.io.in.wfi := io.wfi 338 339 permitMod.io.in.status.tsr := mstatus.regOut.TSR.asBool 340 permitMod.io.in.status.vtsr := hstatus.regOut.VTSR.asBool 341 342 permitMod.io.in.status.tw := mstatus.regOut.TW.asBool 343 permitMod.io.in.status.vtw := hstatus.regOut.VTW.asBool 344 345 permitMod.io.in.status.tvm := mstatus.regOut.TVM.asBool 346 permitMod.io.in.status.vtvm := hstatus.regOut.VTVM.asBool 347 348 miregiprios.foreach { mod => 349 mod.w.wen := (addr === mireg.addr.U) && (miselect.regOut.ALL.asUInt === mod.addr.U) 350 mod.w.wdata := wdata 351 } 352 353 siregiprios.foreach { mod => 354 mod.w.wen := (addr === sireg.addr.U) && (siselect.regOut.ALL.asUInt === mod.addr.U) 355 mod.w.wdata := wdata 356 } 357 358 mhartid.hartid := this.io.fromTop.hartId 359 360 cfgs.zipWithIndex.foreach { case (mod, i) => 361 mod.w.wen := wen && (addr === (0x3A0 + i / 8 * 2).U) 362 mod.w.wdata := pmpEntryMod.io.out.pmpCfgWData(8*((i%8)+1)-1,8*(i%8)) 363 } 364 365 pmpaddr.zipWithIndex.foreach{ case(mod, i) => 366 mod.w.wen := wen && (addr === (0x3B0 + i).U) 367 mod.w.wdata := pmpEntryMod.io.out.pmpAddrWData(i) 368 } 369 370 csrMods.foreach { mod => 371 mod match { 372 case m: HypervisorBundle => 373 m.hstatus := hstatus.regOut 374 m.hvip := hvip.regOut 375 m.hideleg := hideleg.regOut 376 m.hedeleg := hedeleg.regOut 377 m.hgeip := hgeip.regOut 378 m.hgeie := hgeie.regOut 379 m.hip := hip.regOut 380 m.hie := hie.regOut 381 case _ => 382 } 383 mod match { 384 case m: HasMachineInterruptBundle => 385 m.mvien := mvien.regOut 386 m.mvip := mvip.regOut 387 m.mip := mip.regOut 388 m.mie := mie.regOut 389 case _ => 390 } 391 mod match { 392 case m: HasMachineDelegBundle => 393 m.mideleg := mideleg.regOut 394 m.medeleg := medeleg.regOut 395 case _ => 396 } 397 mod match { 398 case m: HasMachineCounterControlBundle => 399 m.mcountinhibit := mcountinhibit.regOut 400 case _ => 401 } 402 mod match { 403 case m: HasExternalInterruptBundle => 404 m.platformIRP := this.platformIRP 405 case _ => 406 } 407 mod match { 408 case m: HasRobCommitBundle => 409 m.robCommit := io.fromRob.commit 410 m.robCommit.fsDirty := io.fromRob.commit.fsDirty || writeFpState 411 m.robCommit.vsDirty := io.fromRob.commit.vsDirty || writeVecState 412 case _ => 413 } 414 mod match { 415 case m: TrapEntryDEventSinkBundle => 416 m.trapToD := trapEntryDEvent.out 417 case _ => 418 } 419 mod match { 420 case m: TrapEntryMEventSinkBundle => 421 m.trapToM := trapEntryMEvent.out 422 case _ => 423 } 424 mod match { 425 case m: TrapEntryHSEventSinkBundle => 426 m.trapToHS := trapEntryHSEvent.out 427 case _ => 428 } 429 mod match { 430 case m: TrapEntryVSEventSinkBundle => 431 m.trapToVS := trapEntryVSEvent.out 432 case _ => 433 } 434 mod match { 435 case m: MretEventSinkBundle => 436 m.retFromM := mretEvent.out 437 case _ => 438 } 439 mod match { 440 case m: SretEventSinkBundle => 441 m.retFromS := sretEvent.out 442 case _ => 443 } 444 mod match { 445 case m: DretEventSinkBundle => 446 m.retFromD := dretEvent.out 447 case _ => 448 } 449 mod match { 450 case m: HasAIABundle => 451 m.aiaToCSR.rdata.valid := fromAIA.rdata.valid 452 m.aiaToCSR.rdata.bits.data := fromAIA.rdata.bits.data 453 m.aiaToCSR.rdata.bits.illegal := fromAIA.rdata.bits.illegal 454 m.aiaToCSR.mtopei.valid := fromAIA.mtopei.valid 455 m.aiaToCSR.stopei.valid := fromAIA.stopei.valid 456 m.aiaToCSR.vstopei.valid := fromAIA.vstopei.valid 457 m.aiaToCSR.mtopei.bits := fromAIA.mtopei.bits 458 m.aiaToCSR.stopei.bits := fromAIA.stopei.bits 459 m.aiaToCSR.vstopei.bits := fromAIA.vstopei.bits 460 case _ => 461 } 462 mod match { 463 case m: HasInterruptFilterSink => 464 m.topIR.mtopi := intrMod.io.out.mtopi 465 m.topIR.stopi := intrMod.io.out.stopi 466 m.topIR.vstopi := intrMod.io.out.vstopi 467 case _ => 468 } 469 mod match { 470 case m: HasISelectBundle => 471 m.privState := privState 472 m.miselect := miselect.regOut 473 m.siselect := siselect.regOut 474 m.mireg := mireg.regOut.asUInt 475 m.sireg := sireg.regOut.asUInt 476 case _ => 477 } 478 mod match { 479 case m: HasPMPAddrSink => 480 m.addrRData := pmpEntryMod.io.out.pmpAddrRData 481 case _ => 482 } 483 } 484 485 csrMods.foreach { mod => 486 println(s"${mod.modName}: ") 487 println(mod.dumpFields) 488 } 489 490 trapEntryMEvent .valid := hasTrap && entryPrivState.isModeM 491 trapEntryHSEvent.valid := hasTrap && entryPrivState.isModeHS 492 trapEntryVSEvent.valid := hasTrap && entryPrivState.isModeVS 493 494 Seq(trapEntryMEvent, trapEntryHSEvent, trapEntryVSEvent, trapEntryDEvent).foreach { eMod => 495 eMod.in match { 496 case in: TrapEntryEventInput => 497 in.causeNO := trapHandleMod.io.out.causeNO 498 in.trapPc := trapPC 499 in.isCrossPageIPF := trapIsCrossPageIPF 500 501 in.iMode.PRVM := PRVM 502 in.iMode.V := V 503 in.dMode.PRVM := Mux(mstatus.regOut.MPRV.asBool, mstatus.regOut.MPP, PRVM) 504 in.dMode.V := Mux(mstatus.regOut.MPRV.asBool, mstatus.regOut.MPV, V) 505 506 in.privState := privState 507 in.mstatus := mstatus.regOut 508 in.hstatus := hstatus.regOut 509 in.sstatus := mstatus.sstatus 510 in.vsstatus := vsstatus.regOut 511 in.pcFromXtvec := trapHandleMod.io.out.pcFromXtvec 512 513 in.satp := satp.regOut 514 in.vsatp := vsatp.regOut 515 in.hgatp := hgatp.regOut 516 517 in.memExceptionVAddr := io.fromMem.excpVA 518 in.memExceptionGPAddr := io.fromMem.excpGPA 519 } 520 } 521 522 mretEvent.valid := legalMret 523 mretEvent.in match { 524 case in => 525 in.mstatus := mstatus.regOut 526 in.mepc := mepc.regOut 527 } 528 529 sretEvent.valid := legalSret 530 sretEvent.in match { 531 case in => 532 in.privState := privState 533 in.sstatus := mstatus.sstatus 534 in.hstatus := hstatus.regOut 535 in.vsstatus := vsstatus.regOut 536 in.sepc := sepc.regOut 537 in.vsepc := vsepc.regOut 538 } 539 540 dretEvent.valid := isDret 541 dretEvent.in match { 542 case in => 543 in.dcsr := dcsr.regOut 544 in.dpc := dpc.regOut 545 in.mstatus := mstatus.regOut 546 } 547 548 PRVM := MuxCase( 549 PRVM, 550 events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map { 551 x => x.out match { 552 case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.PRVM) 553 } 554 } 555 ) 556 557 V := MuxCase( 558 V, 559 events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map { 560 x => x.out match { 561 case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.V) 562 } 563 } 564 ) 565 566 debugMode := MuxCase( 567 debugMode, 568 Seq( 569 dretEvent.out.debugMode.valid -> dretEvent.out.debugMode.bits, 570 trapEntryDEvent.out.debugMode.valid -> trapEntryDEvent.out.debugMode.bits 571 ) 572 ) 573 574 debugIntrEnable := MuxCase( 575 debugIntrEnable, 576 Seq( 577 dretEvent.out.debugIntrEnable.valid -> dretEvent.out.debugIntrEnable.bits, 578 trapEntryDEvent.out.debugIntrEnable.valid -> trapEntryDEvent.out.debugIntrEnable.bits 579 ) 580 ) 581 582 // perf 583 val addrInPerfCnt = (addr >= CSRs.mcycle.U) && (addr <= CSRs.mhpmcounter31.U) || 584 (addr >= mcountinhibit.addr.U) && (addr <= mhpmevents.last.addr.U) || 585 (addr >= CSRs.cycle.U) && (addr <= CSRs.hpmcounter31.U) || 586 (addr === CSRs.mip.U) || 587 (addr === CSRs.hip.U) || 588 Cat(aiaCSRMap.keys.toSeq.sorted.map(_.U === addr)).orR || 589 (addr === CSRs.stimecmp.U) || 590 (addr === CSRs.mcounteren.U) || 591 (addr === CSRs.scounteren.U) || 592 (addr === CSRs.menvcfg.U) 593 // Todo: may be vsip and sip 594 595 // flush 596 val resetSatp = Cat(Seq(satp, vsatp, hgatp).map(_.addr.U === addr)).orR && wenLegal // write to satp will cause the pipeline be flushed 597 598 val wFcsrChangeRM = addr === fcsr.addr.U && wenLegal && wdata(7, 5) =/= fcsr.frm 599 val wFrmChangeRM = addr === CSRs.frm.U && wenLegal && wdata(2, 0) =/= fcsr.frm 600 val frmChange = wFcsrChangeRM || wFrmChangeRM 601 602 val wVcsrChangeRM = addr === CSRs.vcsr.U && wenLegal && wdata(2, 1) =/= vcsr.vxrm 603 val wVxrmChangeRM = addr === CSRs.vxrm.U && wenLegal && wdata(1, 0) =/= vcsr.vxrm 604 val vxrmChange = wVcsrChangeRM || wVxrmChangeRM 605 606 val triggerFrontendChange = Wire(Bool()) 607 val flushPipe = resetSatp || frmChange || vxrmChange || triggerFrontendChange 608 609 // fence 610 val tvm = mstatus.regOut.TVM.asBool 611 val vtvm = hstatus.regOut.VTVM.asBool 612 613 private val rdata = Mux1H(csrRwMap.map { case (id, (_, rBundle)) => 614 (raddr === id.U) -> rBundle.asUInt 615 }) 616 617 private val regOut = Mux1H(csrOutMap.map { case (id, regOut) => 618 (raddr === id.U) -> regOut 619 }) 620 621 private val needTargetUpdate = mretEvent.out.targetPc.valid || sretEvent.out.targetPc.valid || dretEvent.out.targetPc.valid || 622 trapEntryMEvent.out.targetPc.valid || trapEntryHSEvent.out.targetPc.valid || trapEntryVSEvent.out.targetPc.valid || trapEntryDEvent.out.targetPc.valid 623 624 private val noCSRIllegal = (ren || wen) && Cat(csrRwMap.keys.toSeq.sorted.map(csrAddr => !(addr === csrAddr.U))).andR 625 626 io.out.EX_II := permitMod.io.out.EX_II || noCSRIllegal 627 io.out.EX_VI := permitMod.io.out.EX_VI 628 io.out.flushPipe := flushPipe 629 630 io.out.rData := Mux(ren, rdata, 0.U) 631 io.out.regOut := regOut 632 io.out.targetPc := DataHoldBypass( 633 Mux(trapEntryDEvent.out.targetPc.valid, 634 trapEntryDEvent.out.targetPc.bits, 635 Mux1H(Seq( 636 mretEvent.out.targetPc.valid -> mretEvent.out.targetPc.bits, 637 sretEvent.out.targetPc.valid -> sretEvent.out.targetPc.bits, 638 dretEvent.out.targetPc.valid -> dretEvent.out.targetPc.bits, 639 trapEntryMEvent.out.targetPc.valid -> trapEntryMEvent.out.targetPc.bits, 640 trapEntryHSEvent.out.targetPc.valid -> trapEntryHSEvent.out.targetPc.bits, 641 trapEntryVSEvent.out.targetPc.valid -> trapEntryVSEvent.out.targetPc.bits) 642 ) 643 ), 644 needTargetUpdate) 645 646 io.out.privState := privState 647 648 io.out.fpState.frm := fcsr.frm 649 io.out.fpState.off := mstatus.regOut.FS === ContextStatus.Off 650 io.out.vecState.vstart := vstart.rdata.asUInt 651 io.out.vecState.vxsat := vcsr.vxsat 652 io.out.vecState.vxrm := vcsr.vxrm 653 io.out.vecState.vcsr := vcsr.rdata.asUInt 654 io.out.vecState.vl := vl.rdata.asUInt 655 io.out.vecState.vtype := vtype.rdata.asUInt // Todo: check correct 656 io.out.vecState.vlenb := vlenb.rdata.asUInt 657 io.out.vecState.off := mstatus.regOut.VS === ContextStatus.Off 658 io.out.isPerfCnt := addrInPerfCnt 659 io.out.interrupt := intrMod.io.out.interruptVec.valid 660 io.out.wfiEvent := debugIntr || (mie.rdata.asUInt & mip.rdata.asUInt).orR 661 io.out.debugMode := debugMode 662 io.out.singleStepFlag := !debugMode && dcsr.regOut.STEP 663 io.out.tvm := tvm 664 io.out.vtvm := vtvm 665 666 /** 667 * debug_begin 668 */ 669 // debug_intr 670 val hasIntr = hasTrap && trapIsInterrupt 671 val hasDebugIntr = hasIntr && intrVec(CSRConst.IRQ_DEBUG) 672 673 // debug_exception_ebreak 674 val hasExp = hasTrap && !trapIsInterrupt 675 val breakPoint = trapVec(ExceptionNO.breakPoint).asBool 676 val hasBreakPoint = hasExp && breakPoint 677 val ebreakEnterDebugMode = 678 (privState.isModeM && dcsr.regOut.EBREAKM.asBool) || 679 (privState.isModeHS && dcsr.regOut.EBREAKS.asBool) || 680 (privState.isModeHU && dcsr.regOut.EBREAKU.asBool) 681 val hasDebugEbreakException = hasBreakPoint && ebreakEnterDebugMode 682 683 // debug_exception_trigger 684 val triggerFrontendHitVec = triggerCf.frontendHit 685 val triggerMemHitVec = triggerCf.backendHit 686 val triggerHitVec = triggerFrontendHitVec.asUInt | triggerMemHitVec.asUInt // Todo: update mcontrol.hit 687 val triggerFrontendCanFireVec = triggerCf.frontendCanFire.asUInt 688 val triggerMemCanFireVec = triggerCf.backendCanFire.asUInt 689 val triggerCanFireVec = triggerFrontendCanFireVec | triggerMemCanFireVec 690 val tdata1WireVec = tdata1RegVec.map{ mod => { 691 val tdata1Wire = Wire(new Tdata1Bundle) 692 tdata1Wire := mod.rdata 693 tdata1Wire 694 }} 695 val tdata2WireVec = tdata2RegVec.map{ mod => { 696 val tdata2Wire = Wire(new Tdata2Bundle) 697 tdata2Wire := mod.rdata 698 tdata2Wire 699 }} 700 val mcontrolWireVec = tdata1WireVec.map{ mod => { 701 val mcontrolWire = Wire(new Mcontrol) 702 mcontrolWire := mod.DATA.asUInt 703 mcontrolWire 704 }} 705 706 // More than one triggers can hit at the same time, but only fire one 707 // We select the first hit trigger to fire 708 val triggerFireOH = PriorityEncoderOH(triggerCanFireVec) 709 val triggerFireAction = PriorityMux(triggerFireOH, tdata1WireVec.map(_.getTriggerAction)).asUInt 710 val hasTriggerFire = hasExp && triggerCf.canFire 711 val hasDebugTriggerException = hasTriggerFire && (triggerFireAction === TrigAction.DebugMode.asUInt) 712 713 // debug_exception_single 714 val hasSingleStep = hasExp && io.fromRob.trap.bits.singleStep 715 716 val hasDebugException = hasDebugEbreakException || hasDebugTriggerException || hasSingleStep 717 val hasDebugTrap = hasDebugException || hasDebugIntr 718 719 trapEntryDEvent.valid := hasDebugTrap && !debugMode 720 trapEntryDEvent.in.hasDebugIntr := hasDebugIntr 721 trapEntryDEvent.in.debugMode := debugMode 722 trapEntryDEvent.in.hasTrap := hasTrap 723 trapEntryDEvent.in.hasSingleStep := hasSingleStep 724 trapEntryDEvent.in.hasTriggerFire := hasTriggerFire 725 trapEntryDEvent.in.hasDebugEbreakException := hasDebugEbreakException 726 trapEntryDEvent.in.breakPoint := breakPoint 727 728 trapHandleMod.io.in.trapInfo.bits.singleStep := hasSingleStep 729 trapHandleMod.io.in.trapInfo.bits.triggerFire := hasTriggerFire 730 731 intrMod.io.in.debugMode := debugMode 732 intrMod.io.in.debugIntr := debugIntr 733 intrMod.io.in.dcsr := dcsr.rdata.asUInt 734 735 val tselect1H = UIntToOH(tselect.rdata.asUInt, TriggerNum).asBools 736 val chainVec = mcontrolWireVec.map(_.CHAIN.asBool) 737 val newTriggerChainVec = tselect1H.zip(chainVec).map{case(a, b) => a | b} 738 val newTriggerChainIsLegal = TriggerUtil.TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength) 739 740 val tdata1Update = addr === tdata1.addr.U && wenLegal 741 val tdata2Update = addr === tdata2.addr.U && wenLegal 742 val triggerUpdate = tdata1Update || tdata2Update 743 744 tdata1RegVec.foreach { mod => 745 mod match { 746 case m: HasdebugModeBundle => 747 m.debugMode := debugMode 748 m.chainable := newTriggerChainIsLegal 749 case _ => 750 } 751 } 752 tdata1RegVec.zip(tdata2RegVec).zipWithIndex.map { case ((mod1, mod2), idx) => { 753 mod1.w.wen := tdata1Update && (tselect.rdata === idx.U) 754 mod1.w.wdata := wdata 755 mod2.w.wen := tdata2Update && (tselect.rdata === idx.U) 756 mod2.w.wdata := wdata 757 } 758 } 759 760 val tdata1Wdata = Wire(new Tdata1Bundle) 761 tdata1Wdata := wdata 762 val mcontrolWdata = Wire(new Mcontrol) 763 mcontrolWdata := tdata1Wdata.DATA.asUInt 764 val tdata1TypeWdata = tdata1Wdata.TYPE 765 766 val tdata1Selected = Wire(new Tdata1Bundle) 767 tdata1Selected := tdata1.rdata.asUInt 768 val mcontrolSelected = Wire(new Mcontrol) 769 mcontrolSelected := tdata1Selected.DATA.asUInt 770 val tdata2Selected = Wire(new Tdata2Bundle) 771 tdata2Selected := tdata2.rdata.asUInt 772 773 val frontendTriggerUpdate = 774 tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isFetchTrigger || 775 mcontrolSelected.isFetchTrigger && triggerUpdate 776 777 val memTriggerUpdate = 778 tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isMemAccTrigger || 779 mcontrolSelected.isMemAccTrigger && triggerUpdate 780 781 val triggerEnableVec = tdata1WireVec.zip(mcontrolWireVec).map { case(tdata1, mcontrol) => 782 tdata1.TYPE.isLegal && ( 783 mcontrol.M && privState.isModeM || 784 mcontrol.S && (privState.isModeHS) || 785 mcontrol.U && privState.isModeHU) 786 } 787 788 val fetchTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map { 789 case (tEnable, mod) => tEnable && mod.isFetchTrigger 790 } 791 val memAccTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map { 792 case (tEnable, mod) => tEnable && mod.isMemAccTrigger 793 } 794 795 triggerFrontendChange := frontendTriggerUpdate 796 797 io.out.frontendTrigger.tUpdate.valid := RegNext(RegNext(frontendTriggerUpdate)) 798 io.out.frontendTrigger.tUpdate.bits.addr := tselect.rdata.asUInt 799 io.out.frontendTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected) 800 io.out.frontendTrigger.tEnableVec := fetchTriggerEnableVec 801 io.out.memTrigger.tUpdate.valid := RegNext(RegNext(memTriggerUpdate)) 802 io.out.memTrigger.tUpdate.bits.addr := tselect.rdata.asUInt 803 io.out.memTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected) 804 io.out.memTrigger.tEnableVec := memAccTriggerEnableVec 805 /** 806 * debug_end 807 */ 808 809 /** 810 * [[io.out.custom]] connection 811 */ 812 io.out.custom.l1I_pf_enable := spfctl.regOut.L1I_PF_ENABLE.asBool 813 io.out.custom.l2_pf_enable := spfctl.regOut.L2_PF_ENABLE.asBool 814 io.out.custom.l1D_pf_enable := spfctl.regOut.L1D_PF_ENABLE.asBool 815 io.out.custom.l1D_pf_train_on_hit := spfctl.regOut.L1D_PF_TRAIN_ON_HIT.asBool 816 io.out.custom.l1D_pf_enable_agt := spfctl.regOut.L1D_PF_ENABLE_AGT.asBool 817 io.out.custom.l1D_pf_enable_pht := spfctl.regOut.L1D_PF_ENABLE_PHT.asBool 818 io.out.custom.l1D_pf_active_threshold := spfctl.regOut.L1D_PF_ACTIVE_THRESHOLD.asUInt 819 io.out.custom.l1D_pf_active_stride := spfctl.regOut.L1D_PF_ACTIVE_STRIDE.asUInt 820 io.out.custom.l1D_pf_enable_stride := spfctl.regOut.L1D_PF_ENABLE_STRIDE.asBool 821 io.out.custom.l2_pf_store_only := spfctl.regOut.L2_PF_STORE_ONLY.asBool 822 823 io.out.custom.icache_parity_enable := sfetchctl.regOut.ICACHE_PARITY_ENABLE.asBool 824 825 io.out.custom.lvpred_disable := slvpredctl.regOut.LVPRED_DISABLE.asBool 826 io.out.custom.no_spec_load := slvpredctl.regOut.NO_SPEC_LOAD.asBool 827 io.out.custom.storeset_wait_store := slvpredctl.regOut.STORESET_WAIT_STORE.asBool 828 io.out.custom.storeset_no_fast_wakeup := slvpredctl.regOut.STORESET_NO_FAST_WAKEUP.asBool 829 io.out.custom.lvpred_timeout := slvpredctl.regOut.LVPRED_TIMEOUT.asUInt 830 831 io.out.custom.bp_ctrl.ubtb_enable := sbpctl.regOut.UBTB_ENABLE .asBool 832 io.out.custom.bp_ctrl.btb_enable := sbpctl.regOut.BTB_ENABLE .asBool 833 io.out.custom.bp_ctrl.bim_enable := sbpctl.regOut.BIM_ENABLE .asBool 834 io.out.custom.bp_ctrl.tage_enable := sbpctl.regOut.TAGE_ENABLE .asBool 835 io.out.custom.bp_ctrl.sc_enable := sbpctl.regOut.SC_ENABLE .asBool 836 io.out.custom.bp_ctrl.ras_enable := sbpctl.regOut.RAS_ENABLE .asBool 837 io.out.custom.bp_ctrl.loop_enable := sbpctl.regOut.LOOP_ENABLE .asBool 838 839 io.out.custom.sbuffer_threshold := smblockctl.regOut.SBUFFER_THRESHOLD.asUInt 840 io.out.custom.ldld_vio_check_enable := smblockctl.regOut.LDLD_VIO_CHECK_ENABLE.asBool 841 io.out.custom.soft_prefetch_enable := smblockctl.regOut.SOFT_PREFETCH_ENABLE.asBool 842 io.out.custom.cache_error_enable := smblockctl.regOut.CACHE_ERROR_ENABLE.asBool 843 io.out.custom.uncache_write_outstanding_enable := smblockctl.regOut.UNCACHE_WRITE_OUTSTANDING_ENABLE.asBool 844 845 io.out.custom.fusion_enable := srnctl.regOut.FUSION_ENABLE.asBool 846 io.out.custom.wfi_enable := srnctl.regOut.WFI_ENABLE.asBool 847 848 // Todo: record the last address to avoid xireg is different with xiselect 849 toAIA.addr.valid := wenLegal && Seq(miselect, siselect, vsiselect).map( 850 _.addr.U === addr 851 ).reduce(_ || _) 852 toAIA.addr.bits.addr := addr 853 toAIA.addr.bits.prvm := PRVM 854 toAIA.addr.bits.v := V 855 toAIA.vgein := hstatus.regOut.VGEIN.asUInt 856 toAIA.wdata.valid := wenLegal && Seq(mireg, sireg, vsireg).map( 857 _.addr.U === addr 858 ).reduce(_ || _) 859 toAIA.wdata.bits.data := wdata 860 toAIA.mClaim := wenLegal && mtopei.addr.U === addr 861 toAIA.sClaim := wenLegal && stopei.addr.U === addr 862 toAIA.vsClaim := wenLegal && vstopei.addr.U === addr 863 864 // tlb 865 io.tlb.satpASIDChanged := wenLegal && addr === CSRs. satp.U && satp .regOut.ASID =/= wdata.asTypeOf(new SatpBundle).ASID 866 io.tlb.vsatpASIDChanged := wenLegal && addr === CSRs.vsatp.U && vsatp.regOut.ASID =/= wdata.asTypeOf(new SatpBundle).ASID 867 io.tlb.hgatpVMIDChanged := wenLegal && addr === CSRs.hgatp.U && hgatp.regOut.VMID =/= wdata.asTypeOf(new HgatpBundle).VMID 868 io.tlb.satp := satp.rdata 869 io.tlb.vsatp := vsatp.rdata 870 io.tlb.hgatp := hgatp.rdata 871 io.tlb.mxr := mstatus.regOut.MXR.asBool 872 io.tlb.sum := mstatus.regOut.SUM.asBool 873 io.tlb.vmxr := vsstatus.regOut.MXR.asBool 874 io.tlb.vsum := vsstatus.regOut.SUM.asBool 875 io.tlb.spvp := hstatus.regOut.SPVP.asBool 876 877 io.tlb.imode := PRVM.asUInt 878 io.tlb.dmode := Mux((debugMode && dcsr.regOut.MPRVEN.asBool || !debugMode) && mstatus.regOut.MPRV.asBool, mstatus.regOut.MPP.asUInt, PRVM.asUInt) 879 880 io.toDecode.illegalInst.sfenceVMA := isModeHS && mstatus.regOut.TVM || isModeHU 881 io.toDecode.virtualInst.sfenceVMA := isModeVS && hstatus.regOut.VTVM || isModeVU 882 io.toDecode.illegalInst.sfencePart := isModeHU 883 io.toDecode.virtualInst.sfencePart := isModeVU 884 io.toDecode.illegalInst.hfenceGVMA := isModeHS && mstatus.regOut.TVM || isModeHU 885 io.toDecode.illegalInst.hfenceVVMA := isModeHU 886 io.toDecode.virtualInst.hfence := isModeVS || isModeVU 887 io.toDecode.illegalInst.hlsv := isModeHU && hstatus.regOut.HU 888 io.toDecode.virtualInst.hlsv := isModeVS || isModeVU 889 890 // Always instantiate basic difftest modules. 891 if (env.AlwaysBasicDiff || env.EnableDifftest) { 892 val hartId = io.fromTop.hartId 893 val trapValid = io.fromRob.trap.valid 894 val trapNO = trapHandleMod.io.out.causeNO.ExceptionCode.asUInt 895 val interrupt = trapHandleMod.io.out.causeNO.Interrupt.asBool 896 val interruptNO = Mux(interrupt, trapNO, 0.U) 897 val exceptionNO = Mux(!interrupt, trapNO, 0.U) 898 val ivmHS = isModeHS && satp.regOut.MODE =/= SatpMode.Bare 899 val ivmVS = isModeVS && vsatp.regOut.MODE =/= SatpMode.Bare 900 // When enable virtual memory, the higher bit should fill with the msb of address of Sv39/Sv48/Sv57 901 val exceptionPC = Mux(ivmHS || ivmVS, SignExt(trapPC, XLEN), ZeroExt(trapPC, XLEN)) 902 903 val diffArchEvent = DifftestModule(new DiffArchEvent, delay = 3, dontCare = true) 904 diffArchEvent.coreid := hartId 905 diffArchEvent.valid := trapValid 906 diffArchEvent.interrupt := interruptNO 907 diffArchEvent.exception := exceptionNO 908 diffArchEvent.exceptionPC := exceptionPC 909 if (env.EnableDifftest) { 910 diffArchEvent.exceptionInst := io.fromRob.trap.bits.instr 911 } 912 913 val diffCSRState = DifftestModule(new DiffCSRState) 914 diffCSRState.coreid := hartId 915 diffCSRState.privilegeMode := privState.PRVM.asUInt 916 diffCSRState.mstatus := mstatus.rdata.asUInt 917 diffCSRState.sstatus := mstatus.sstatus.asUInt 918 diffCSRState.mepc := mepc.rdata.asUInt 919 diffCSRState.sepc := sepc.rdata.asUInt 920 diffCSRState.mtval := mtval.rdata.asUInt 921 diffCSRState.stval := stval.rdata.asUInt 922 diffCSRState.mtvec := mtvec.rdata.asUInt 923 diffCSRState.stvec := stvec.rdata.asUInt 924 diffCSRState.mcause := mcause.rdata.asUInt 925 diffCSRState.scause := scause.rdata.asUInt 926 diffCSRState.satp := satp.rdata.asUInt 927 diffCSRState.mip := mip.regOut.asUInt 928 diffCSRState.mie := mie.rdata.asUInt 929 diffCSRState.mscratch := mscratch.rdata.asUInt 930 diffCSRState.sscratch := sscratch.rdata.asUInt 931 diffCSRState.mideleg := mideleg.rdata.asUInt 932 diffCSRState.medeleg := medeleg.rdata.asUInt 933 934 val diffDebugMode = DifftestModule(new DiffDebugMode) 935 diffDebugMode.coreid := hartId 936 diffDebugMode.debugMode := debugMode 937 diffDebugMode.dcsr := dcsr.rdata.asUInt 938 diffDebugMode.dpc := dpc.rdata.asUInt 939 diffDebugMode.dscratch0 := dscratch0.rdata.asUInt 940 diffDebugMode.dscratch1 := dscratch1.rdata.asUInt 941 942 val diffVecCSRState = DifftestModule(new DiffVecCSRState) 943 diffVecCSRState.coreid := hartId 944 diffVecCSRState.vstart := vstart.rdata.asUInt 945 diffVecCSRState.vxsat := vcsr.vxsat.asUInt 946 diffVecCSRState.vxrm := vcsr.vxrm.asUInt 947 diffVecCSRState.vcsr := vcsr.rdata.asUInt 948 diffVecCSRState.vl := vl.rdata.asUInt 949 diffVecCSRState.vtype := vtype.rdata.asUInt 950 diffVecCSRState.vlenb := vlenb.rdata.asUInt 951 952 val diffHCSRState = DifftestModule(new DiffHCSRState) 953 diffHCSRState.coreid := hartId 954 diffHCSRState.virtMode := privState.V.asBool 955 diffHCSRState.mtval2 := mtval2.rdata.asUInt 956 diffHCSRState.mtinst := mtinst.rdata.asUInt 957 diffHCSRState.hstatus := hstatus.rdata.asUInt 958 diffHCSRState.hideleg := hideleg.rdata.asUInt 959 diffHCSRState.hedeleg := hedeleg.rdata.asUInt 960 diffHCSRState.hcounteren := hcounteren.rdata.asUInt 961 diffHCSRState.htval := htval.rdata.asUInt 962 diffHCSRState.htinst := htinst.rdata.asUInt 963 diffHCSRState.hgatp := hgatp.rdata.asUInt 964 diffHCSRState.vsstatus := vsstatus.rdata.asUInt 965 diffHCSRState.vstvec := vstvec.rdata.asUInt 966 diffHCSRState.vsepc := vsepc.rdata.asUInt 967 diffHCSRState.vscause := vscause.rdata.asUInt 968 diffHCSRState.vstval := vstval.rdata.asUInt 969 diffHCSRState.vsatp := vsatp.rdata.asUInt 970 diffHCSRState.vsscratch := vsscratch.rdata.asUInt 971 972 } 973} 974 975trait SupervisorMachineAliasConnect { self: NewCSR with MachineLevel with SupervisorLevel => 976 mip.fromMvip := mvip.toMip 977 mip.fromSip := sip.toMip 978 mie.fromSie := sie.toMie 979} 980 981object NewCSRMain extends App { 982 val (config, firrtlOpts, firtoolOpts) = ArgParser.parse( 983 args :+ "--disable-always-basic-diff" :+ "--dump-fir" :+ "--fpga-platform" :+ "--target" :+ "verilog") 984 985 val defaultConfig = config.alterPartial({ 986 // Get XSCoreParams and pass it to the "small module" 987 case XSCoreParamsKey => config(XSTileKey).head 988 }) 989 990 Generator.execute( 991 firrtlOpts :+ "--full-stacktrace" :+ "--target-dir" :+ "backend", 992 new NewCSR()(defaultConfig), 993 firtoolOpts 994 ) 995 996 println("done") 997}