From 94cdc3f77214d223e2d91a605711ade53a8bde69 Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Wed, 24 Jul 2024 10:53:41 +0800 Subject: [PATCH] [rockett1] draft Tile --- rocketv/src/Bundle.scala | 29 +++ rocketv/src/RocketCore.scala | 129 +++++----- t1rocketv/src/T1RocketTile.scala | 423 +++++++++++++++++++++++++++++++ 3 files changed, 521 insertions(+), 60 deletions(-) create mode 100644 t1rocketv/src/T1RocketTile.scala diff --git a/rocketv/src/Bundle.scala b/rocketv/src/Bundle.scala index 2d9950261..28535335a 100644 --- a/rocketv/src/Bundle.scala +++ b/rocketv/src/Bundle.scala @@ -1398,3 +1398,32 @@ class FrontendBundle(vaddrBitsExtended: Int, vaddrBits: Int, asidBits: Int, entr val ptw = new TLBPTWIO(nPMPs, vpnBits, paddrBits, vaddrBits, pgLevels, xLen, maxPAddrBits, pgIdxBits) val errors = new ICacheErrors(hasCorrectable, hasUncorrectable, paddrBits) } + +// Interface between T1 <> Rocket integration +class RocketCoreToT1 extends Bundle { + val issue: Valid[T1Issue] = Valid(new T1Issue) + val retire: T1Retire = Flipped(new T1Retire) +} + +class T1Issue extends Bundle { + val instruction: UInt = UInt(32.W) + val rs1Data: UInt = UInt(32.W) + val rs2Data: UInt = UInt(32.W) + val vcsr: UInt = UInt(32.W) +} + +class T1RdRetire extends Bundle { + val rd: UInt = UInt(5.W) + val data: UInt = UInt(32.W) + val fp: Bool = Bool() +} + +class T1CSRRetire extends Bundle { + val vxsat: UInt = UInt(32.W) +} + +class T1Retire extends Bundle { + val rd = Valid(new T1RdRetire) + val csr = Valid(new T1CSRRetire) + val mem = Valid(new Bundle {}) +} \ No newline at end of file diff --git a/rocketv/src/RocketCore.scala b/rocketv/src/RocketCore.scala index b541b0a30..dd880d41c 100644 --- a/rocketv/src/RocketCore.scala +++ b/rocketv/src/RocketCore.scala @@ -9,7 +9,7 @@ import chisel3.experimental.hierarchy.{Instance, Instantiate, instantiable} import chisel3.experimental.{SerializableModule, SerializableModuleParameter} import chisel3.util.circt.ClockGate import chisel3.util.experimental.decode.DecodeBundle -import chisel3.util.{BitPat, Cat, Fill, MuxLookup, PriorityEncoder, PriorityMux, RegEnable, log2Ceil} +import chisel3.util.{BitPat, Cat, DecoupledIO, Fill, MuxLookup, PriorityEncoder, PriorityMux, Queue, RegEnable, log2Ceil, log2Up} import org.chipsalliance.rocketv.rvdecoderdbcompat.Causes import org.chipsalliance.rvdecoderdb.Instruction @@ -43,9 +43,12 @@ case class RocketParameter( fastLoadByte: Boolean, fastLoadWord: Boolean, dcacheNSets: Int, - flushOnFenceI: Boolean + flushOnFenceI: Boolean, + usingT1: Boolean ) extends SerializableModuleParameter { + // interface to T1 + def usingVector = hasInstructionSet("rv_v") // fixed for now def usingRVE = false @@ -135,8 +138,6 @@ case class RocketParameter( // static to false for now def usingNMI = hasInstructionSet("rv_smrnmi") - def usingVector = hasInstructionSet("rv_v") - // calculated parameter def fetchWidth: Int = 1 @@ -309,6 +310,7 @@ class RocketInterface(parameter: RocketParameter) extends Bundle { ) ) val fpu = parameter.fLen.map(fLen => Flipped(new FPUCoreIO(parameter.hartIdLen, parameter.xLen, fLen))) + val t1 = Option.when(parameter.usingT1)(new RocketCoreToT1) val bpwatch = Output(Vec(parameter.nBreakpoints, new BPWatch)) val cease = Output(Bool()) val wfi = Output(Bool()) @@ -1331,62 +1333,69 @@ class Rocket(val parameter: RocketParameter) fpu.keep_clock_enabled := false.B } -// @todo get back t1. -// t1Request.foreach { t1 => -// // Send instruction to T1 when write back. -// t1.valid := wbRegValid && !replayWbCommon && wbRegDecodeOutput(parameter.decoderParameter.vector) -// t1.bits.instruction := wbRegInstruction -// t1.bits.rs1Data := wbRegWdata -// t1.bits.rs2Data := wbRegRS2 -// val response: DecoupledIO[VectorResponse] = t1Response.get -// // TODO: make it configurable -// val maxCount: Int = 32 -// val countWidth = log2Up(maxCount) -// def counterManagement(size: Int, margin: Int = 0)(grant: Bool, release: Bool, flush: Option[Bool] = None) = { -// val counter: UInt = RegInit(0.U(size.W)) -// val nextCount = counter + Mux(grant, 1.U(size.W), (-1.S(size.W)).asUInt) -// val updateCounter = grant ^ release -// when(updateCounter) { -// counter := nextCount -// } -// flush.foreach(f => when(f)(counter := 0.U)) -// val empty = (updateCounter && nextCount === 0.U) || counter === 0.U -// val fullCounter: Int = (1 << size) - 1 - margin -// val full = (updateCounter && nextCount >= fullCounter.U) || counter >= fullCounter.U -// (empty, full) -// } -// // Maintain lsu counter -// val lsuGrant: Bool = t1.valid && wbRegDecodeOutput(parameter.decoderParameter.vectorLSU) -// val lsuRelease: Bool = response.fire && response.bits.mem -// val (lsuEmpty, _) = counterManagement(countWidth)(lsuGrant, lsuRelease) -// // Maintain vector counter -// // There may be 4 instructions in the pipe -// val (vectorEmpty, vectorFull) = counterManagement(countWidth, 4)(t1.valid, t1IssueQueueRelease.get) -// vectorLSUEmpty.foreach(_ := lsuEmpty) -// vectorQueueFull.foreach(_ := vectorFull) -// } -// // todo: vector change csr -// t1Response.foreach { vectorResponse => -// val vectorTryToWriteRd = vectorResponse.bits.rd.valid && !vectorResponse.bits.float -// val vectorTryToWriteFP = vectorResponse.bits.rd.valid && vectorResponse.bits.float -// vectorResponse.ready := (!(wbWxd || (dmemResponseReplay && dmemResponseXpu)) || !vectorTryToWriteRd) && -// (!(dmemResponseReplay && dmemResponseFpu) || !vectorTryToWriteFP) -// when(vectorResponse.fire && vectorTryToWriteRd) { -// longlatencyWdata := vectorResponse.bits.data -// longlatencyWaddress := vectorResponse.bits.rd.bits -// longLatencyWenable := true.B -// } -// fpu.foreach { fpu => -// when(!(dmemResponseValid && dmemResponseFpu)) { -// fpu.dmem_resp_val := vectorResponse.fire && vectorTryToWriteFP -// fpu.dmem_resp_data := vectorResponse.bits.data -// // todo: 32 bit only -// fpu.dmem_resp_type := 2.U -// // todo: connect tag -// fpu.dmem_resp_tag := 0.U -// } -// } -// } + io.t1.foreach { t1 => + // Send instruction to T1 when write back. + // TODO: make it configurable + val maxCount: Int = 32 + val t1IssueQueue = Module(new Queue(chiselTypeOf(t1.issue.bits), maxCount)) + t1IssueQueue.io.enq.valid := wbRegValid && !replayWbCommon && wbRegDecodeOutput(parameter.decoderParameter.vector) + t1IssueQueue.io.enq.bits.instruction := wbRegInstruction + t1IssueQueue.io.enq.bits.rs1Data := wbRegWdata + t1IssueQueue.io.enq.bits.rs2Data := wbRegRS2 + t1.issue.valid := t1IssueQueue.io.deq.valid + t1.issue.bits := t1IssueQueue.io.deq.bits + // TODO: really maintain 3 retire queues? we need to reduce it via a scoreboard. + val t1MemoryRetireQueue = Module(new Queue(chiselTypeOf(t1.retire.mem.bits), maxCount)) + val t1CSRRetireQueue = Module(new Queue(chiselTypeOf(t1.retire.csr.bits), maxCount)) + val t1XRDRetireQueue = Module(new Queue(chiselTypeOf(t1.retire.rd.bits), maxCount)) + + val countWidth = log2Up(maxCount) + def counterManagement(size: Int, margin: Int = 0)(grant: Bool, release: Bool, flush: Option[Bool] = None) = { + val counter: UInt = RegInit(0.U(size.W)) + val nextCount = counter + Mux(grant, 1.U(size.W), (-1.S(size.W)).asUInt) + val updateCounter = grant ^ release + when(updateCounter) { + counter := nextCount + } + flush.foreach(f => when(f)(counter := 0.U)) + val empty = (updateCounter && nextCount === 0.U) || counter === 0.U + val fullCounter: Int = (1 << size) - 1 - margin + val full = (updateCounter && nextCount >= fullCounter.U) || counter >= fullCounter.U + (empty, full) + } + // T1 Memory Scoreboard + val lsuGrant: Bool = t1.issue.valid && wbRegDecodeOutput(parameter.decoderParameter.vectorLSU) + val lsuRelease: Bool = t1.retire.mem.fire + val (lsuEmpty, _) = counterManagement(countWidth)(lsuGrant, lsuRelease) + // Maintain vector counter + // There may be 4 instructions in the pipe + val (vectorEmpty, vectorFull) = counterManagement(countWidth, 4)(t1.issue.valid, ???) + vectorLSUEmpty.foreach(_ := lsuEmpty) + vectorQueueFull.foreach(_ := vectorFull) + + val vectorTryToWriteRd = t1.retire.rd.valid && !t1.retire.rd.bits.fp + val vectorTryToWriteFP = t1.retire.rd.valid && t1.retire.rd.bits.fp + // TODO: maintain queue here? + t1XRDRetireQueue.io.deq.ready := (!(wbWxd || (dmemResponseReplay && dmemResponseXpu)) || !vectorTryToWriteRd) && (!(dmemResponseReplay && dmemResponseFpu) || !vectorTryToWriteFP) + t1CSRRetireQueue.io.deq.ready := (!(wbWxd || (dmemResponseReplay && dmemResponseXpu)) || !vectorTryToWriteRd) && (!(dmemResponseReplay && dmemResponseFpu) || !vectorTryToWriteFP) + t1MemoryRetireQueue.io.deq.ready := (!(wbWxd || (dmemResponseReplay && dmemResponseXpu)) || !vectorTryToWriteRd) && (!(dmemResponseReplay && dmemResponseFpu) || !vectorTryToWriteFP) + + when(t1.retire.rd.fire && vectorTryToWriteRd) { + longlatencyWdata := t1.retire.rd.bits.data + longlatencyWaddress := t1.retire.rd.bits.rd + longLatencyWenable := true.B + } + io.fpu.foreach { fpu => + when(!(dmemResponseValid && dmemResponseFpu)) { + fpu.dmem_resp_val := t1.retire.mem.fire && vectorTryToWriteFP + fpu.dmem_resp_data := t1.retire.rd.bits.data + // todo: 32 bit only + fpu.dmem_resp_type := 2.U + // todo: connect tag + fpu.dmem_resp_tag := 0.U + } + } + } io.dmem.req.valid := exRegValid && exRegDecodeOutput(parameter.decoderParameter.mem) val ex_dcache_tag = Cat(exWaddr, Option.when(usingFPU)(exRegDecodeOutput(parameter.decoderParameter.fp)).getOrElse(false.B)) diff --git a/t1rocketv/src/T1RocketTile.scala b/t1rocketv/src/T1RocketTile.scala new file mode 100644 index 000000000..1534592ba --- /dev/null +++ b/t1rocketv/src/T1RocketTile.scala @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2024 Jiuyang Liu +package org.chipsalliance.t1.tile + +import chisel3._ +import chisel3.experimental.hierarchy.{Instance, Instantiate} +import chisel3.experimental.{SerializableModule, SerializableModuleParameter} +import chisel3.util.experimental.BitSet +import chisel3.util.log2Ceil +import org.chipsalliance.amba.axi4.bundle.{AXI4BundleParameter, AXI4ROIrrevocable, AXI4RWIrrevocable} +import org.chipsalliance.rocketv.{BHTParameter, FPU, FPUParameter, Frontend, FrontendParameter, HellaCache, HellaCacheArbiter, HellaCacheArbiterParameter, HellaCacheParameter, PTW, PTWParameter, Rocket, RocketParameter, RocketTileParameter} +import org.chipsalliance.rvdecoderdb.Instruction +import org.chipsalliance.t1.rtl.{T1, T1Parameter} + +object T1RocketTileParameter { + implicit def bitSetP: upickle.default.ReadWriter[BitSet] = upickle.default + .readwriter[String] + .bimap[BitSet]( + bs => bs.terms.map("b" + _.rawString).mkString("\n"), + str => if (str.isEmpty) BitSet.empty else BitSet.fromString(str) + ) + + implicit def rwP: upickle.default.ReadWriter[T1RocketTileParameter] = upickle.default.macroRW[T1RocketTileParameter] +} + +case class T1RocketTileParameter( + useAsyncReset: Boolean, + clockGate: Boolean, + instructionSets: Set[String], + priv: String, + hartIdLen: Int, + useBPWatch: Boolean, + mcontextWidth: Int, + scontextWidth: Int, + asidBits: Int, + resetVectorBits: Int, + nBreakpoints: Int, + dtlbNWays: Int, + dtlbNSets: Int, + itlbNSets: Int, + itlbNWays: Int, + itlbNSectors: Int, + itlbNSuperpageEntries: Int, + nPTECacheEntries: Int, + nL2TLBWays: Int, + nL2TLBEntries: Int, + paddrBits: Int, + cacheBlockBytes: Int, + nPMPs: Int, + legal: BitSet, + cacheable: BitSet, + read: BitSet, + write: BitSet, + putPartial: BitSet, + logic: BitSet, + arithmetic: BitSet, + exec: BitSet, + sideEffects: BitSet, + btbEntries: Int, + btbNMatchBits: Int, + btbUpdatesOutOfOrder: Boolean, + nPages: Int, + nRAS: Int, + bhtParameter: Option[BHTParameter], + mulDivLatency: Int, + divUnroll: Int, + divEarlyOut: Boolean, + divEarlyOutGranularity: Int, + mulUnroll: Int, + mulEarlyOut: Boolean, + sfmaLatency: Int, + dfmaLatency: Int, + divSqrt: Boolean, + flushOnFenceI: Boolean, + fastLoadByte: Boolean, + fastLoadWord: Boolean, + dcacheNSets: Int, + dcacheNWays: Int, + dcacheRowBits: Int, + maxUncachedInFlight: Int, + separateUncachedResp: Boolean, + iCacheNSets: Int, + iCacheNWays: Int, + iCachePrefetch: Boolean) + extends SerializableModuleParameter { + + // calculate + def usingUser: Boolean = priv.contains("u") + + def usingSupervisor: Boolean = priv.contains("s") + + def vLen: Option[Int] = instructionSets.collectFirst { + case s"zvl${vlen}b" => vlen.toInt + } + + // static for now + def hasBeu: Boolean = false + def usingNMI: Boolean = false + def usingHypervisor: Boolean = false + def usingDataScratchpad: Boolean = false + def nLocalInterrupts: Int = 0 + def dcacheArbPorts: Int = 2 + def tagECC: Option[String] = None + def dataECC: Option[String] = None + def pgLevelBits: Int = 10 - log2Ceil(xLen / 32) + def instructions: Seq[Instruction] = + org.chipsalliance.rvdecoderdb + .instructions( + org.chipsalliance.rvdecoderdb.extractResource(getClass.getClassLoader) + ) + .filter(instruction => + ( + instructionSets ++ + // Four mandatory instruction sets. + Seq("rv_i", "rv_zicsr", "rv_zifencei", "rv_system") + ).contains(instruction.instructionSet.name) + ) + .toSeq + .filter { + // special case for rv32 pseudo from rv64 + case i if i.pseudoFrom.isDefined && Seq("slli", "srli", "srai").contains(i.name) => true + case i if i.pseudoFrom.isDefined => false + case _ => true + } + .sortBy(i => (i.instructionSet.name, i.name)) + private def hasInstructionSet(setName: String): Boolean = + instructions.flatMap(_.instructionSets.map(_.name)).contains(setName) + def usingBTB: Boolean = btbEntries > 0 + def xLen: Int = + (hasInstructionSet("rv32_i"), hasInstructionSet("rv64_i")) match { + case (true, true) => throw new Exception("cannot support both rv32 and rv64 together") + case (true, false) => 32 + case (false, true) => 64 + case (false, false) => throw new Exception("no basic instruction found.") + } + def fLen: Option[Int] = + ( + hasInstructionSet("rv_f") || hasInstructionSet("rv64_f"), + hasInstructionSet("rv_d") || hasInstructionSet("rv64_d") + ) match { + case (false, false) => None + case (true, false) => Some(32) + case (false, true) => Some(64) + case (true, true) => Some(64) + } + + def usingVM = hasInstructionSet("sfence.vma") + + def pgLevels: Int = xLen match { + case 32 => 2 + case 64 => 3 + } + + def usingAtomics = hasInstructionSet("rv_a") || hasInstructionSet("rv64_a") + + def usingCompressed = hasInstructionSet("rv_c") + + def minFLen: Option[Int] = + if (hasInstructionSet("rv_zfh") || hasInstructionSet("rv64_zfh") || hasInstructionSet("rv_d_zfh")) + Some(16) + else + fLen + + def rocketParameter: RocketParameter = RocketParameter( + useAsyncReset, + clockGate, + instructionSets, + vLen.getOrElse(0), + usingUser, + hartIdLen, + nPMPs, + asidBits, + nBreakpoints, + usingBTB, + useBPWatch, + mcontextWidth, + scontextWidth, + mulDivLatency, + divUnroll, + divEarlyOut, + divEarlyOutGranularity, + mulUnroll, + mulEarlyOut, + paddrBits, + cacheBlockBytes, + hasBeu, + fastLoadByte, + fastLoadWord, + dcacheNSets, + flushOnFenceI + ) + + def hellaCacheParameter: HellaCacheParameter = HellaCacheParameter( + useAsyncReset: Boolean, + clockGate: Boolean, + xLen: Int, + fLen.getOrElse(0): Int, + usingVM: Boolean, + paddrBits: Int, + cacheBlockBytes: Int, + dcacheNWays: Int, + dcacheNSets: Int, + dcacheRowBits: Int, + dtlbNSets: Int, + dtlbNWays: Int, + tagECC: Option[String], + dataECC: Option[String], + maxUncachedInFlight: Int, + separateUncachedResp: Boolean, + legal: BitSet, + cacheable: BitSet, + read: BitSet, + write: BitSet, + putPartial: BitSet, + logic: BitSet, + arithmetic: BitSet, + exec: BitSet, + sideEffects: BitSet + ) + + def hellaCacheArbiterParameter: HellaCacheArbiterParameter = HellaCacheArbiterParameter( + useAsyncReset: Boolean, + xLen: Int, + fLen.getOrElse(0): Int, + paddrBits: Int, + cacheBlockBytes: Int, + dcacheNSets: Int, + usingVM: Boolean, + separateUncachedResp: Boolean + ) + + def ptwParameter: PTWParameter = PTWParameter( + useAsyncReset: Boolean, + clockGate: Boolean, + usingVM: Boolean, + usingHypervisor: Boolean, + xLen: Int, + fLen.getOrElse(0): Int, + paddrBits: Int, + asidBits: Int, + pgLevels: Int, + nPTECacheEntries: Int, + nL2TLBWays: Int, + nL2TLBEntries: Int, + nPMPs: Int + ) + + def frontendParameter: FrontendParameter = FrontendParameter( + useAsyncReset: Boolean, + clockGate: Boolean, + xLen: Int, + usingAtomics: Boolean, + usingDataScratchpad: Boolean, + usingVM: Boolean, + usingCompressed: Boolean, + usingBTB: Boolean, + itlbNSets: Int, + itlbNWays: Int, + itlbNSectors: Int, + itlbNSuperpageEntries: Int, + cacheBlockBytes: Int, + iCacheNSets: Int, + iCacheNWays: Int, + iCachePrefetch: Boolean, + btbEntries: Int, + btbNMatchBits: Int, + btbUpdatesOutOfOrder: Boolean, + nPages: Int, + nRAS: Int, + nPMPs: Int, + paddrBits: Int, + pgLevels: Int, + asidBits: Int, + bhtParameter: Option[BHTParameter], + legal: BitSet, + cacheable: BitSet, + read: BitSet, + write: BitSet, + putPartial: BitSet, + logic: BitSet, + arithmetic: BitSet, + exec: BitSet, + sideEffects: BitSet + ) + + def fpuParameter: Option[FPUParameter] = fLen.zip(minFLen).map { + case (fLen, minFLen) => + FPUParameter( + useAsyncReset: Boolean, + clockGate: Boolean, + xLen: Int, + fLen: Int, + minFLen: Int, + sfmaLatency: Int, + dfmaLatency: Int, + divSqrt: Boolean, + hartIdLen: Int + ) + } + + def t1Parameter: T1Parameter = ??? + + def instructionFetchParameter: AXI4BundleParameter = frontendParameter.instructionFetchParameter + + def itimParameter: Option[AXI4BundleParameter] = frontendParameter.itimParameter + + def loadStoreParameter: AXI4BundleParameter = hellaCacheParameter.loadStoreParameter + + def dtimParameter: Option[AXI4BundleParameter] = hellaCacheParameter.dtimParameter +} + +class T1RocketTileInterface(parameter: T1RocketTileParameter) extends Bundle { + val clock = Input(Clock()) + val reset = Input(if (parameter.useAsyncReset) AsyncReset() else Bool()) + // todo: Const + val hartid = Flipped(UInt(parameter.hartIdLen.W)) + val resetVector = Input(Const(UInt(parameter.resetVectorBits.W))) + + val debug: Bool = Input(Bool()) + val mtip: Bool = Input(Bool()) + val msip: Bool = Input(Bool()) + val meip: Bool = Input(Bool()) + val seip: Option[Bool] = Option.when(parameter.usingSupervisor)(Bool()) + val lip: Vec[Bool] = Vec(parameter.nLocalInterrupts, Bool()) + val nmi = Option.when(parameter.usingNMI)(Bool()) + val nmiInterruptVector = Option.when(parameter.usingNMI)(UInt(parameter.resetVectorBits.W)) + val nmiIxceptionVector = Option.when(parameter.usingNMI)(UInt(parameter.resetVectorBits.W)) + // TODO: buserror should be handled by NMI + val buserror: Bool = Input(Bool()) + val wfi: Bool = Output(Bool()) + val halt: Bool = Output(Bool()) + + val instructionFetchAXI: AXI4ROIrrevocable = + org.chipsalliance.amba.axi4.bundle.AXI4ROIrrevocable(parameter.instructionFetchParameter) + val itimAXI: Option[AXI4RWIrrevocable] = + parameter.itimParameter.map(p => Flipped(org.chipsalliance.amba.axi4.bundle.AXI4RWIrrevocable(p))) + + val loadStoreAXI: AXI4RWIrrevocable = + org.chipsalliance.amba.axi4.bundle.AXI4RWIrrevocable(parameter.loadStoreParameter) + val dtimAXI: Option[AXI4RWIrrevocable] = + parameter.dtimParameter.map(p => Flipped(org.chipsalliance.amba.axi4.bundle.AXI4RWIrrevocable(p))) +} + +class RocketTile(val parameter: T1RocketTileParameter) + extends FixedIORawModule(new T1RocketTileInterface(parameter)) + with SerializableModule[T1RocketTileParameter] { + val rocket: Instance[Rocket] = Instantiate(new Rocket(parameter.rocketParameter)) + val frontend: Instance[Frontend] = Instantiate(new Frontend(parameter.frontendParameter)) + val hellaCache: Instance[HellaCache] = Instantiate(new HellaCache(parameter.hellaCacheParameter)) + val hellaCacheArbiter: Instance[HellaCacheArbiter] = Instantiate( + new HellaCacheArbiter(parameter.hellaCacheArbiterParameter) + ) + val ptw: Instance[PTW] = Instantiate(new PTW(parameter.ptwParameter)) + val fpu: Option[Instance[FPU]] = parameter.fpuParameter.map(fpuParameter => Instantiate(new FPU(fpuParameter))) + val t1: Instance[T1] = Instantiate(new T1(parameter.t1Parameter)) + + rocket.io.clock := io.clock + rocket.io.reset := io.reset + rocket.io.hartid := io.hartid + rocket.io.interrupts.debug := io.debug + rocket.io.interrupts.mtip := io.mtip + rocket.io.interrupts.msip := io.msip + rocket.io.interrupts.meip := io.meip + rocket.io.interrupts.seip.foreach(_ := io.seip.get) + rocket.io.interrupts.lip := io.lip + rocket.io.interrupts.nmi.foreach { nmi => + nmi.rnmi := io.nmi.get + nmi.rnmi_interrupt_vector := io.nmiInterruptVector.get + nmi.rnmi_exception_vector := io.nmiIxceptionVector.get + } + // @todo make it optional + rocket.io.buserror := io.buserror + io.wfi := rocket.io.wfi + io.loadStoreAXI <> hellaCache.io.loadStoreAXI + io.dtimAXI.zip(hellaCache.io.dtimAXI).foreach { case (io, hellaCache) => io <> hellaCache } + io.instructionFetchAXI <> frontend.io.instructionFetchAXI + io.itimAXI.zip(frontend.io.itimAXI).foreach { case (io, frontend) => io <> frontend } + // design for halt and beu, only use the halt function for now. + io.halt := Seq(frontend.io.nonDiplomatic.errors.uncorrectable, hellaCache.io.errors.uncorrectable) + .flatMap(_.map(_.valid)) + .foldLeft(false.B)(_ || _) + + // rocket core io + rocket.io.imem <> frontend.io.nonDiplomatic.cpu + hellaCacheArbiter.io.requestor(0) <> rocket.io.dmem + rocket.io.ptw <> ptw.io.dpath + rocket.io.fpu.zip(fpu.map(_.io.core)).foreach { case (core, fpu) => core <> fpu } + // used by trace module + rocket.io.bpwatch := DontCare + // don't use for now, this is design for report the custom cease status. + // rocket.io.cease + // it will be used in the future w/ trace support. + rocket.io.traceStall := false.B + + // frontend io + frontend.io.clock := io.clock + frontend.io.reset := io.reset + frontend.io.resetVector := io.resetVector + ptw.io.requestor(0) <> frontend.io.nonDiplomatic.ptw + + // hellacache io + hellaCache.io.clock := io.clock + hellaCache.io.reset := io.reset + ptw.io.requestor(1) <> hellaCache.io.ptw + hellaCache.io.cpu <> hellaCacheArbiter.io.mem + + // ptw io + ptw.io.clock := io.clock + ptw.io.reset := io.reset + hellaCacheArbiter.io.requestor(1) <> ptw.io.mem + + // hellacache arbiter io + hellaCacheArbiter.io.clock := io.clock + hellaCacheArbiter.io.reset := io.reset + + fpu.foreach { fpu => + fpu.io.clock := io.clock + fpu.io.reset := io.reset + // @todo: remove it from FPU. + fpu.io.cp_req <> DontCare + fpu.io.cp_resp <> DontCare + } +}