feat(CLINT): add new clint to match 1:1 ration between CLINT and HART (#4991)
EMU Test / Changes Detection (push) Has been cancelled
Details
Release Jobs / build-xsdev-image (push) Has been cancelled
Details
Nightly Regression / Nightly Regression(master) - Checkpoints (push) Has been cancelled
Details
Nightly Regression / Nightly Regression(kunminghu-v3) - Checkpoints (push) Has been cancelled
Details
EMU Test / Generate Verilog (push) Has been cancelled
Details
EMU Test / EMU - Basics (push) Has been cancelled
Details
EMU Test / EMU - CHI (push) Has been cancelled
Details
EMU Test / Docker Build (push) Has been cancelled
Details
EMU Test / EMU - Performance (push) Has been cancelled
Details
EMU Test / EMU - MC (push) Has been cancelled
Details
EMU Test / SIMV - Basics (push) Has been cancelled
Details
EMU Test / Upload Artifacts (push) Has been cancelled
Details
EMU Test / Check Submodules (push) Has been cancelled
Details
EMU Test / Check Format (push) Has been cancelled
Details
EMU Test / Changes Detection (push) Has been cancelled
Details
Release Jobs / build-xsdev-image (push) Has been cancelled
Details
Nightly Regression / Nightly Regression(master) - Checkpoints (push) Has been cancelled
Details
Nightly Regression / Nightly Regression(kunminghu-v3) - Checkpoints (push) Has been cancelled
Details
EMU Test / Generate Verilog (push) Has been cancelled
Details
EMU Test / EMU - Basics (push) Has been cancelled
Details
EMU Test / EMU - CHI (push) Has been cancelled
Details
EMU Test / Docker Build (push) Has been cancelled
Details
EMU Test / EMU - Performance (push) Has been cancelled
Details
EMU Test / EMU - MC (push) Has been cancelled
Details
EMU Test / SIMV - Basics (push) Has been cancelled
Details
EMU Test / Upload Artifacts (push) Has been cancelled
Details
EMU Test / Check Submodules (push) Has been cancelled
Details
EMU Test / Check Format (push) Has been cancelled
Details
1.Update Clint. Including two components: TIMER and SYSCNT. 2.TIMER is integrated inner XSTileWrap, while SYSCNT is integrated in soc. 3.add SeperateTLBusIO: when it is true, TL bus appears as XSTOP IO port. independent with new clint. SeperateTLBusIO can be deleted after new clint ST test pass. --------- Co-authored-by: good-circle <fenghaoyuan19@mails.ucas.ac.cn>
This commit is contained in:
parent
87aeac5924
commit
b4e2ef7988
|
@ -51,13 +51,13 @@ jobs:
|
|||
bash .github/workflows/check-usage.sh "BoringUtils" $GITHUB_WORKSPACE
|
||||
- name: generate standalone devices for TL
|
||||
run: |
|
||||
make StandAloneCLINT DEVICE_BASE_ADDR=0x38000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=1 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneSYSCNT DEVICE_BASE_ADDR=0x38040000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=1 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneDebugModule DEVICE_BASE_ADDR=0x38020000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=1 DEVICE_PREFIX=DM_
|
||||
make StandAlonePLIC DEVICE_BASE_ADDR=0x3C000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=1 DEVICE_PREFIX=PLIC_
|
||||
make clean
|
||||
- name: generate standalone devices for AXI4
|
||||
run: |
|
||||
make StandAloneCLINT DEVICE_BASE_ADDR=0x38000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneSYSCNT DEVICE_BASE_ADDR=0x38040000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneDebugModule DEVICE_BASE_ADDR=0x38020000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=DM_
|
||||
make StandAlonePLIC DEVICE_BASE_ADDR=0x3C000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=PLIC_
|
||||
make clean
|
||||
|
@ -465,7 +465,7 @@ jobs:
|
|||
run: python3 $GITHUB_WORKSPACE/scripts/xiangshan.py --clean
|
||||
- name: generate standalone devices for AXI4
|
||||
run: |
|
||||
make StandAloneCLINT DEVICE_BASE_ADDR=0x38000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneSYSCNT DEVICE_BASE_ADDR=0x38040000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneDebugModule DEVICE_BASE_ADDR=0x38020000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=DM_
|
||||
make StandAlonePLIC DEVICE_BASE_ADDR=0x3C000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=PLIC_
|
||||
- name: generate CHI Issue B XSNoCTop verilog with difftest and filelist
|
||||
|
@ -482,7 +482,7 @@ jobs:
|
|||
run: python3 $GITHUB_WORKSPACE/scripts/xiangshan.py --clean
|
||||
- name: generate standalone devices for AXI4
|
||||
run: |
|
||||
make StandAloneCLINT DEVICE_BASE_ADDR=0x38000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneSYSCNT DEVICE_BASE_ADDR=0x38040000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneDebugModule DEVICE_BASE_ADDR=0x38020000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=DM_
|
||||
make StandAlonePLIC DEVICE_BASE_ADDR=0x3C000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=PLIC_
|
||||
- name: generate CHI Issue E.b XSNoCTop verilog with difftest and filelist
|
||||
|
@ -499,7 +499,7 @@ jobs:
|
|||
run: python3 $GITHUB_WORKSPACE/scripts/xiangshan.py --clean
|
||||
- name: generate standalone devices for AXI4
|
||||
run: |
|
||||
make StandAloneCLINT DEVICE_BASE_ADDR=0x38000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneSYSCNT DEVICE_BASE_ADDR=0x38040000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=CLINT_
|
||||
make StandAloneDebugModule DEVICE_BASE_ADDR=0x38020000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=DM_
|
||||
make StandAlonePLIC DEVICE_BASE_ADDR=0x3C000000 DEVICE_ADDR_WIDTH=32 DEVICE_DATA_WIDTH=64 DEVICE_TL=0 DEVICE_PREFIX=PLIC_
|
||||
- name: generate CHI Issue E.b lowpower XSNoCTop verilog with difftest and filelist
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC)
|
||||
* Copyright (c) 2025 Institute of Computing Technology, Chinese Academy of Sciences
|
||||
*
|
||||
* XiangShan is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
package device
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.util.ShiftRegister
|
||||
import chisel3.util.ValidIO
|
||||
import freechips.rocketchip.devices.debug.RWNotify
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.regmapper._
|
||||
import freechips.rocketchip.regmapper.RegField
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
import org.chipsalliance.cde.config.Field
|
||||
import org.chipsalliance.cde.config.Parameters
|
||||
import scala.collection.immutable.Seq
|
||||
|
||||
object SYSCNTConsts {
|
||||
|
||||
def timeOffset = 0xbff8 // 0xbff8 base addr is 0x8000
|
||||
def timefreq = 0xc000 // 0xC000:0x8000+0x4000
|
||||
def timefreqReq = timefreq + 0x0008
|
||||
def timeswReq = timefreq + 0x0010
|
||||
def size = 0x10000
|
||||
def timeWidth = 64
|
||||
}
|
||||
|
||||
case class SYSCNTParams(baseAddress: BigInt = 0x02000000, intStages: Int = 0) {
|
||||
def address = AddressSet(baseAddress, SYSCNTConsts.size - 1)
|
||||
}
|
||||
|
||||
case object SYSCNTKey extends Field[Option[SYSCNTParams]](None)
|
||||
|
||||
case class SYSCNTAttachParams(
|
||||
slaveWhere: TLBusWrapperLocation = CBUS
|
||||
)
|
||||
|
||||
case object SYSCNTAttachKey extends Field(SYSCNTAttachParams())
|
||||
|
||||
class SYSCNT(params: SYSCNTParams, beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||
import SYSCNTConsts._
|
||||
|
||||
// clint0 => at most 4095 devices
|
||||
val device = new SimpleDevice("clint", Seq("riscv,clint0")) {
|
||||
override val alwaysExtended = true
|
||||
}
|
||||
|
||||
val node: TLRegisterNode = TLRegisterNode(
|
||||
address = Seq(params.address),
|
||||
device = device,
|
||||
beatBytes = beatBytes
|
||||
)
|
||||
|
||||
lazy val module = new Impl
|
||||
class Impl extends LazyModuleImp(this) {
|
||||
|
||||
val rtc_clock = IO(Input(Clock()))
|
||||
val rtc_reset = IO(Input(AsyncReset()))
|
||||
val bus_clock = IO(Input(Clock()))
|
||||
val bus_reset = IO(Input(AsyncReset()))
|
||||
val io = IO(new Bundle {
|
||||
val update_en = Input(Bool())
|
||||
val update_value = Input(UInt(timeWidth.W))
|
||||
val stop_en = Input(Bool())
|
||||
val time = Output(ValidIO(UInt(timeWidth.W)))
|
||||
})
|
||||
dontTouch(io)
|
||||
// increasing time define working on rtc_clock
|
||||
val time = withClockAndReset(rtc_clock, rtc_reset)(RegInit(0.U(timeWidth.W)))
|
||||
val time_sw = withClockAndReset(bus_clock, bus_reset)(RegInit(0.U(timeWidth.W))) // software config time register
|
||||
val time_sw_req = withClockAndReset(bus_clock, bus_reset)(RegInit(false.B))
|
||||
// register define working on bus clock
|
||||
// freqidx bit[1:0] is incr width 0: 1GHz,1:500MHz,2:250MHz,3:125MHz,4:62.5MHz,..
|
||||
val freqidx = withClockAndReset(bus_clock, bus_reset)(RegInit(0.U(3.W)))
|
||||
val freqidx_req = withClockAndReset(bus_clock, bus_reset)(RegInit(false.B))
|
||||
// async process about soc signal
|
||||
val update_sync = withClockAndReset(rtc_clock, rtc_reset)(AsyncResetSynchronizerShiftReg(io.update_en, 3, 0))
|
||||
val stop_sync = withClockAndReset(rtc_clock, rtc_reset)(AsyncResetSynchronizerShiftReg(io.stop_en, 3, 0))
|
||||
val freqidx_req_rtc = withClockAndReset(rtc_clock, rtc_reset)(AsyncResetSynchronizerShiftReg(freqidx_req, 3, 0))
|
||||
val time_sw_req_rtc = withClockAndReset(rtc_clock, rtc_reset)(AsyncResetSynchronizerShiftReg(time_sw_req, 3, 0))
|
||||
// generate freqidx_req_rtc's rising edge
|
||||
val freqidx_req_rtc_1f = withClockAndReset(rtc_clock, rtc_reset)(RegNext(freqidx_req_rtc, init = false.B))
|
||||
val inccfg_vld = freqidx_req_rtc & (!freqidx_req_rtc_1f)
|
||||
val time_req_rtc_1f = withClockAndReset(rtc_clock, rtc_reset)(RegNext(time_sw_req_rtc, init = false.B))
|
||||
val time_req_rtc_ris = time_sw_req_rtc & (!time_req_rtc_1f)
|
||||
// async process from rtc clock to bus clock
|
||||
val time_sw_update_bus =
|
||||
withClockAndReset(bus_clock, bus_reset)(AsyncResetSynchronizerShiftReg(time_req_rtc_ris, 3, 0))
|
||||
when(time_sw_update_bus)(time_sw_req := false.B)
|
||||
// inc freq will be active after freqidx request is set from 0 to 1.
|
||||
val incwidth = WireInit(0.U(3.W))
|
||||
incwidth := withClockAndReset(rtc_clock, rtc_reset)(RegEnable(freqidx, inccfg_vld))
|
||||
val inc_up_dis = withClockAndReset(rtc_clock, rtc_reset)(RegInit(false.B))
|
||||
// generate the low bit: time_low= time[incwidth-1:0]
|
||||
val time_low = Mux(incwidth === 0.U, 1.U, time & ((1.U << incwidth) - 1.U))
|
||||
|
||||
val inczero = incwidth === 0.U
|
||||
val timelow_zero = time_low === 0.U
|
||||
|
||||
val inc_update = inc_up_dis & (inczero | timelow_zero)
|
||||
// count step will not update before count arrive at 2^n,n is increg
|
||||
when(inccfg_vld) {
|
||||
inc_up_dis := true.B
|
||||
}.elsewhen(inc_update) {
|
||||
inc_up_dis := false.B
|
||||
}
|
||||
|
||||
// update the increasing step only when counter arrivals integer times of step config.
|
||||
val incr_width_value = withClockAndReset(rtc_clock, rtc_reset)(RegInit(0.U(3.W)))
|
||||
when(inc_update) {
|
||||
incr_width_value := incwidth
|
||||
}
|
||||
// async process about inc_update
|
||||
val inc_update_bus = withClockAndReset(bus_clock, bus_reset)(AsyncResetSynchronizerShiftReg(inc_update, 3, 0))
|
||||
when(inc_update_bus) {
|
||||
freqidx_req := false.B
|
||||
} // freqidx update cfg is cleared auto by hardware.
|
||||
val time_en = withClockAndReset(rtc_clock, rtc_reset)(RegInit(false.B))
|
||||
val incwidth_mux = Mux(inc_update, incwidth, incr_width_value)
|
||||
|
||||
when(stop_sync) {
|
||||
time_en := false.B
|
||||
}.otherwise {
|
||||
time_en := true.B
|
||||
}
|
||||
|
||||
when(time_req_rtc_ris) {
|
||||
time := time_sw
|
||||
}.elsewhen(stop_sync) {
|
||||
time := time
|
||||
}.elsewhen(update_sync) {
|
||||
time := io.update_value
|
||||
}.otherwise {
|
||||
time := time + (1.U << incwidth_mux)
|
||||
}
|
||||
io.time.bits := time
|
||||
io.time.valid := time_en
|
||||
// time working on rtc clock is to be synced with bus clock
|
||||
val timeasync = withClockAndReset(bus_clock, bus_reset)(Module(new TimeAsync()))
|
||||
val time_rpt_bus = timeasync.io.o_time.bits
|
||||
|
||||
timeasync.io.i_time := io.time
|
||||
/* 0000 msip hart 0
|
||||
* 0004 msip hart 1
|
||||
* 4000 mtimecmp hart 0 lo
|
||||
* 4004 mtimecmp hart 0 hi
|
||||
* 4008 mtimecmp hart 1 lo
|
||||
* bffc mtime hi
|
||||
*/
|
||||
// no use, only statement for syntax.
|
||||
val time_rpt_rd = WireInit(false.B)
|
||||
val time_sw_vld = WireInit(false.B)
|
||||
val freqidx_rd = WireInit(false.B)
|
||||
val freqidx_wr = WireInit(false.B)
|
||||
val freqidx_req_rd = WireInit(false.B)
|
||||
val freqidx_req_wr = WireInit(false.B)
|
||||
val mtime_req_rd = WireInit(false.B)
|
||||
val mtime_req_wr = WireInit(false.B)
|
||||
//
|
||||
node.regmap(
|
||||
timeOffset -> RegFieldGroup(
|
||||
"mtime",
|
||||
Some("Timer Register"),
|
||||
Seq(RWNotify(
|
||||
64,
|
||||
time_rpt_bus,
|
||||
time_sw,
|
||||
time_rpt_rd,
|
||||
time_sw_vld,
|
||||
Some(RegFieldDesc("timeswReq", "", reset = Some(0), volatile = true))
|
||||
))
|
||||
),
|
||||
timefreq -> RegFieldGroup(
|
||||
"freqidx",
|
||||
Some("mtime frequency Register"),
|
||||
Seq(RWNotify(
|
||||
3,
|
||||
freqidx,
|
||||
freqidx,
|
||||
freqidx_rd,
|
||||
freqidx_wr,
|
||||
Some(RegFieldDesc("freqidx", "", reset = Some(0), volatile = true))
|
||||
))
|
||||
),
|
||||
timefreqReq -> RegFieldGroup(
|
||||
"freqidxReq",
|
||||
Some("mtime frequency update Request Register"),
|
||||
Seq(RWNotify(
|
||||
1,
|
||||
freqidx_req,
|
||||
freqidx_req,
|
||||
freqidx_req_rd,
|
||||
freqidx_req_wr,
|
||||
Some(RegFieldDesc("freqidxReq", "", reset = Some(0), volatile = true))
|
||||
))
|
||||
),
|
||||
timeswReq -> RegFieldGroup(
|
||||
"mtimeReq",
|
||||
Some("mtime software update Request Register"),
|
||||
Seq(RWNotify(
|
||||
1,
|
||||
time_sw_req,
|
||||
time_sw_req,
|
||||
mtime_req_rd,
|
||||
mtime_req_wr,
|
||||
Some(RegFieldDesc("mtime_req", "", reset = Some(0), volatile = true))
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC)
|
||||
* Copyright (c) 2025 Institute of Computing Technology, Chinese Academy of Sciences
|
||||
*
|
||||
* XiangShan is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
package device
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.util.ShiftRegister
|
||||
import chisel3.util.ValidIO
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.regmapper._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tile.MaxHartIdBits
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
import org.chipsalliance.cde.config.Field
|
||||
import org.chipsalliance.cde.config.Parameters
|
||||
|
||||
object TIMERConsts {
|
||||
def msipOffset(hart: Int) = hart * msipBytes
|
||||
def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes
|
||||
def timeOffset = 0xbff8
|
||||
def msipBytes = 4
|
||||
def timecmpBytes = 8
|
||||
def size = 0x10000
|
||||
def timeWidth = 64
|
||||
def ipiWidth = 32
|
||||
def ints = 2
|
||||
}
|
||||
|
||||
case class TIMERParams(IsSelfTest: Boolean = false, baseAddress: BigInt = 0x02000000, intStages: Int = 0) {
|
||||
def address = AddressSet(baseAddress, TIMERConsts.size - 1)
|
||||
}
|
||||
|
||||
case object CLINTKey extends Field[Option[TIMERParams]](None)
|
||||
|
||||
case class CLINTAttachParams(
|
||||
slaveWhere: TLBusWrapperLocation = CBUS
|
||||
)
|
||||
|
||||
case object CLINTAttachKey extends Field(CLINTAttachParams())
|
||||
|
||||
class TIMER(params: TIMERParams, beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||
import TIMERConsts._
|
||||
|
||||
// clint0 => at most 4095 devices
|
||||
val device = new SimpleDevice("clint", Seq("riscv,clint0")) {
|
||||
override val alwaysExtended = true
|
||||
}
|
||||
|
||||
val node: TLRegisterNode = TLRegisterNode(
|
||||
address = Seq(params.address),
|
||||
device = device,
|
||||
beatBytes = beatBytes
|
||||
)
|
||||
|
||||
val intnode: IntNexusNode = IntNexusNode(
|
||||
sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(ints, Seq(Resource(device, "int"))))) },
|
||||
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) },
|
||||
outputRequiresInput = false
|
||||
)
|
||||
|
||||
lazy val module = new Impl
|
||||
class Impl extends LazyModuleImp(this) {
|
||||
require(intnode.edges.in.size == 0, "CLINT only produces interrupts; it does not accept them")
|
||||
|
||||
val io = IO(new Bundle {
|
||||
val time = Input(ValidIO(UInt(timeWidth.W)))
|
||||
val hartId = Input(UInt(p(MaxHartIdBits).W))
|
||||
})
|
||||
|
||||
val time = RegInit(0.U(timeWidth.W))
|
||||
when(io.time.valid)(time := io.time.bits)
|
||||
|
||||
// val nTiles = intnode.out.size
|
||||
val NumsHart = 1 << p(MaxHartIdBits)
|
||||
val nTiles = NumsHart // def the max hart satisfing kmhv2 spec
|
||||
val timecmp = Seq.fill(nTiles)(RegInit((BigInt(2).pow(timeWidth) - 1).asUInt(timeWidth.W)))
|
||||
val ipi = Seq.fill(nTiles)(RegInit(0.U(1.W)))
|
||||
|
||||
// only get interrupt from the current hart
|
||||
val (intnode_out, _) = intnode.out.unzip
|
||||
|
||||
intnode_out.zipWithIndex.foreach { case (int, i) =>
|
||||
if (params.IsSelfTest) {
|
||||
int(0) := ShiftRegister(ipi(i)(0), params.intStages) // msip
|
||||
int(1) := ShiftRegister(time.asUInt >= timecmp(i).asUInt, params.intStages) // mtip
|
||||
} else {
|
||||
int(0) := ShiftRegister(ipi(io.hartId)(0), params.intStages) // msip
|
||||
int(1) := ShiftRegister(time.asUInt >= timecmp(io.hartId).asUInt, params.intStages) // mtip
|
||||
}
|
||||
}
|
||||
|
||||
// io.time.valid := RegNext(io.rtcTick)
|
||||
// io.time.bits := time
|
||||
|
||||
/* 0000 msip hart 0
|
||||
* 0004 msip hart 1
|
||||
* 4000 mtimecmp hart 0 lo
|
||||
* 4004 mtimecmp hart 0 hi
|
||||
* 4008 mtimecmp hart 1 lo
|
||||
* 400c mtimecmp hart 1 hi
|
||||
* bff8 mtime lo
|
||||
* bffc mtime hi
|
||||
*/
|
||||
node.regmap(
|
||||
0 -> RegFieldGroup(
|
||||
"msip",
|
||||
Some("MSIP Bits"),
|
||||
ipi.zipWithIndex.flatMap { case (r, i) =>
|
||||
RegField(1, r, RegFieldDesc(s"msip_$i", s"MSIP bit for Hart $i", reset = Some(0))) :: RegField(
|
||||
ipiWidth - 1
|
||||
) :: Nil
|
||||
}
|
||||
),
|
||||
timecmpOffset(0) -> timecmp.zipWithIndex.flatMap { case (t, i) =>
|
||||
RegFieldGroup(
|
||||
s"mtimecmp_$i",
|
||||
Some(s"MTIMECMP for hart $i"),
|
||||
RegField.bytes(t, Some(RegFieldDesc(s"mtimecmp_$i", "", reset = None)))
|
||||
)
|
||||
},
|
||||
timeOffset -> Seq(RegField.r(64, time, RegFieldDesc("mtime", "", volatile = true)))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Trait that will connect a CLINT to a subsystem */
|
||||
trait CanHavePeripheryCLINT { this: BaseSubsystem =>
|
||||
val clintOpt = p(CLINTKey).map { params =>
|
||||
val tlbus = locateTLBusWrapper(p(CLINTAttachKey).slaveWhere)
|
||||
val clint = LazyModule(new TIMER(params, cbus.beatBytes))
|
||||
clint.node := tlbus.coupleTo("clint")(TLFragmenter(tlbus) := _)
|
||||
|
||||
// Override the implicit clock and reset -- could instead include a clockNode in the clint, and make it a RawModuleImp?
|
||||
InModuleBody {
|
||||
clint.module.clock := tlbus.module.clock
|
||||
clint.module.reset := tlbus.module.reset
|
||||
}
|
||||
clint
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC)
|
||||
* Copyright (c) 2025 Institute of Computing Technology, Chinese Academy of Sciences
|
||||
*
|
||||
* XiangShan is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
package device
|
||||
|
||||
import chisel3._
|
||||
import chisel3.Bundle
|
||||
import chisel3.Input
|
||||
import chisel3.Module
|
||||
import chisel3.Output
|
||||
import chisel3.UInt
|
||||
import chisel3.util.RegEnable
|
||||
import chisel3.util.ValidIO
|
||||
import freechips.rocketchip.util.AsyncResetSynchronizerShiftReg
|
||||
|
||||
class TimeAsync extends Module { // work with destination clock
|
||||
val io = IO(new Bundle {
|
||||
val i_time = Input(ValidIO(UInt(64.W)))
|
||||
val o_time = Output(ValidIO(UInt(64.W)))
|
||||
})
|
||||
// async for i_time vld
|
||||
val time_vld = AsyncResetSynchronizerShiftReg(io.i_time.valid, 3, 0)
|
||||
val time_vld_1dly = RegNext(time_vld, false.B)
|
||||
val time_vld_xor = time_vld ^ time_vld_1dly
|
||||
val time_vld_o = RegNext(time_vld_xor, false.B)
|
||||
val time_o = RegEnable(io.i_time.bits, 0.U(64.W), time_vld_xor)
|
||||
io.o_time.valid := time_vld_o
|
||||
io.o_time.bits := time_o
|
||||
}
|
||||
// code about timer vld gen : Q<=~D
|
||||
class TimeVldGen extends Module { // work with reference clock,sync with syscnt
|
||||
val io = IO(new Bundle {
|
||||
val i_time = Input(UInt(64.W))
|
||||
val o_time = Output(ValidIO(UInt(64.W)))
|
||||
})
|
||||
io.o_time.bits := io.i_time
|
||||
io.o_time.valid := io.i_time(0)
|
||||
}
|
|
@ -205,8 +205,8 @@ object ArgParser {
|
|||
require(addrWidth >= 0, "addrWidth not specified correctly")
|
||||
require(dataWidth >= 0, "dataWidth not specified correctly")
|
||||
val device: StandAloneDevice = module match {
|
||||
case "StandAloneCLINT" =>
|
||||
DisableMonitors(p => LazyModule(new StandAloneCLINT(
|
||||
case "StandAloneSYSCNT" =>
|
||||
DisableMonitors(p => LazyModule(new StandAloneSYSCNT(
|
||||
useTL, baseAddress, addrWidth, dataWidth, p(XSTileKey).size
|
||||
)(p)))(p)
|
||||
case "StandAlonePLIC" =>
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC)
|
||||
* Copyright (c) 2025 Institute of Computing Technology, Chinese Academy of Sciences
|
||||
*
|
||||
* XiangShan is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
package device.standalone
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import device.SYSCNT
|
||||
import device.SYSCNTParams
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
import org.chipsalliance.cde.config.Parameters
|
||||
import utility.IntBuffer
|
||||
|
||||
class StandAloneSYSCNT(
|
||||
useTL: Boolean = false,
|
||||
baseAddress: BigInt,
|
||||
addrWidth: Int,
|
||||
dataWidth: Int = 64,
|
||||
hartNum: Int
|
||||
)(implicit p: Parameters) extends StandAloneDevice(
|
||||
useTL,
|
||||
baseAddress,
|
||||
addrWidth,
|
||||
dataWidth,
|
||||
hartNum
|
||||
) {
|
||||
|
||||
private def clintParam = SYSCNTParams(baseAddress)
|
||||
def addressSet: AddressSet = clintParam.address
|
||||
|
||||
private val clint = LazyModule(new SYSCNT(clintParam, dataWidth / 8))
|
||||
clint.node := xbar
|
||||
|
||||
class StandAloneSYSCNTImp(outer: StandAloneSYSCNT)(implicit p: Parameters) extends StandAloneDeviceImp(outer) {
|
||||
val rtc_clock = IO(Input(Clock()))
|
||||
val rtc_reset = IO(Input(AsyncReset()))
|
||||
val io = IO(new Bundle {
|
||||
val update_en = Input(Bool())
|
||||
val update_value = Input(UInt(64.W))
|
||||
val stop_en = Input(Bool())
|
||||
val time = Output(ValidIO(UInt(64.W)))
|
||||
})
|
||||
outer.clint.module.rtc_clock := rtc_clock
|
||||
outer.clint.module.rtc_reset := rtc_reset
|
||||
outer.clint.module.bus_clock := clock
|
||||
outer.clint.module.bus_reset := reset
|
||||
outer.clint.module.io.stop_en := io.stop_en
|
||||
outer.clint.module.io.update_en := io.update_en
|
||||
outer.clint.module.io.update_value := io.update_value
|
||||
io.time := outer.clint.module.io.time
|
||||
}
|
||||
|
||||
override lazy val module = new StandAloneSYSCNTImp(this)
|
||||
|
||||
}
|
|
@ -4,7 +4,7 @@ DEBUG_ARGS += --xstop-prefix $(DEVICE_PREFIX)
|
|||
PLDM_ARGS += --xstop-prefix $(DEVICE_PREFIX)
|
||||
endif
|
||||
|
||||
STANDALONE_DEVICES = StandAloneCLINT StandAlonePLIC StandAloneDebugModule
|
||||
STANDALONE_DEVICES = StandAlonePLIC StandAloneDebugModule StandAloneSYSCNT
|
||||
STANDALONE_DEVICES_PATH = $(shell for module in $(STANDALONE_DEVICES); do echo $(RTL_DIR)/$$module/$(DEVICE_PREFIX)$$module.$(RTL_SUFFIX); done)
|
||||
|
||||
ifeq ($(DEVICE_TL),1)
|
||||
|
|
|
@ -19,7 +19,14 @@ package system
|
|||
import org.chipsalliance.cde.config.{Field, Parameters}
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import device.{DebugModule, TLPMA, TLPMAIO, AXI4MemEncrypt}
|
||||
import device.{AXI4MemEncrypt, DebugModule, SYSCNT, SYSCNTConsts, SYSCNTParams, TIMER, TIMERConsts, TIMERParams, TLPMA, TLPMAIO}
|
||||
|
||||
|
||||
import huancun._
|
||||
import utility.{ReqSourceKey, TLClientsMerger, TLEdgeBuffer, TLLogger}
|
||||
import coupledL2.{EnableCHI, L2Param}
|
||||
import coupledL2.tl2chi.CHIIssue
|
||||
import openLLC.OpenLLCParam
|
||||
import freechips.rocketchip.amba.axi4._
|
||||
import freechips.rocketchip.devices.debug.DebugModuleKey
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
|
@ -27,15 +34,11 @@ import freechips.rocketchip.diplomacy.{AddressSet, IdRange, InModuleBody, LazyMo
|
|||
import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple}
|
||||
import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup}
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util.AsyncQueueParams
|
||||
import huancun._
|
||||
import freechips.rocketchip.util.{AsyncQueueParams}
|
||||
import top.BusPerfMonitor
|
||||
import utility.{ReqSourceKey, TLClientsMerger, TLEdgeBuffer, TLLogger}
|
||||
import xiangshan.backend.fu.{MemoryRange, PMAConfigEntry, PMAConst}
|
||||
import xiangshan.{DebugOptionsKey, PMParameKey, XSTileKey}
|
||||
import coupledL2.{EnableCHI, L2Param}
|
||||
import coupledL2.tl2chi.CHIIssue
|
||||
import openLLC.OpenLLCParam
|
||||
import device.SYSCNTConsts.timeWidth
|
||||
|
||||
case object SoCParamsKey extends Field[SoCParameters]
|
||||
case object CVMParamsKey extends Field[CVMParameters]
|
||||
|
@ -70,7 +73,8 @@ case class SoCParameters
|
|||
PMAConfigEntry(0x10000000L, a = 1, w = true, r = true),
|
||||
PMAConfigEntry(0)
|
||||
),
|
||||
CLINTRange: AddressSet = AddressSet(0x38000000L, CLINTConsts.size - 1),
|
||||
TIMERRange: AddressSet = AddressSet(0x38000000L, TIMERConsts.size - 1),
|
||||
SYSCNTRange: AddressSet = AddressSet(0x38040000L, SYSCNTConsts.size - 1),
|
||||
BEURange: AddressSet = AddressSet(0x38010000L, 0xfff),
|
||||
PLICRange: AddressSet = AddressSet(0x3c000000L, PLICConsts.size(PLICConsts.maxMaxHarts) - 1),
|
||||
PLLRange: AddressSet = AddressSet(0x3a000000L, 0xfff),
|
||||
|
@ -112,7 +116,7 @@ case class SoCParameters
|
|||
HasTEEIMSIC = false
|
||||
),
|
||||
EnableCHIAsyncBridge: Option[AsyncQueueParams] = Some(AsyncQueueParams(depth = 16, sync = 3, safe = false)),
|
||||
EnableClintAsyncBridge: Option[AsyncQueueParams] = Some(AsyncQueueParams(depth = 1, sync = 3, safe = false)),
|
||||
EnableClintAsyncBridge: Option[AsyncQueueParams] = Some(AsyncQueueParams(depth = 8, sync = 3, safe = false)),
|
||||
SeperateTLAsyncBridge: Option[AsyncQueueParams] = Some(AsyncQueueParams(depth = 1, sync = 3, safe = false)),
|
||||
WFIClockGate: Boolean = false,
|
||||
EnablePowerDown: Boolean = false
|
||||
|
@ -198,7 +202,8 @@ trait HasPeripheralRanges {
|
|||
private def mmpma = pmParams.mmpma
|
||||
|
||||
def onChipPeripheralRanges: Map[String, AddressSet] = Map(
|
||||
"CLINT" -> soc.CLINTRange,
|
||||
"TIMER" -> soc.TIMERRange,
|
||||
"SYSCNT" -> soc.SYSCNTRange,
|
||||
"BEU" -> soc.BEURange,
|
||||
"PLIC" -> soc.PLICRange,
|
||||
"PLL" -> soc.PLLRange,
|
||||
|
@ -466,9 +471,15 @@ class MemMisc()(implicit p: Parameters) extends BaseSoC
|
|||
}
|
||||
}
|
||||
|
||||
val clint = LazyModule(new CLINT(CLINTParams(soc.CLINTRange.base), 8))
|
||||
if (enableCHI) { clint.node := device_xbar.get }
|
||||
else { clint.node := peripheralXbar.get }
|
||||
// instant syscnt
|
||||
val syscnt = (LazyModule(new SYSCNT(SYSCNTParams(soc.SYSCNTRange.base), 8)))
|
||||
// val clint = LazyModule(new CLINT(CLINTParams(soc.CLINTRange.base), 8))
|
||||
|
||||
if (enableCHI) { syscnt.node := device_xbar.get }
|
||||
else { syscnt.node := peripheralXbar.get }
|
||||
|
||||
// if (enableCHI) { clint.node := device_xbar.get }
|
||||
// else { clint.node := peripheralXbar.get }
|
||||
|
||||
class IntSourceNodeToModule(val num: Int)(implicit p: Parameters) extends LazyModule {
|
||||
val sourceNode = IntSourceNode(IntSourcePortSimple(num, ports = 1, sources = 1))
|
||||
|
@ -495,26 +506,38 @@ class MemMisc()(implicit p: Parameters) extends BaseSoC
|
|||
if (enableCHI) { pll_node := device_xbar.get }
|
||||
else { pll_node := peripheralXbar.get }
|
||||
|
||||
// instance timer
|
||||
val timer = LazyModule(new TIMER(TIMERParams(IsSelfTest = true, soc.TIMERRange.base), 8))
|
||||
val debugModule = LazyModule(new DebugModule(NumCores)(p))
|
||||
val debugModuleXbarOpt = Option.when(SeperateDM)(TLXbar())
|
||||
val SepTLXbarOpt = Option.when(SeperateTLBus)(TLXbar())
|
||||
if (enableCHI) {
|
||||
if (SeperateDM) {
|
||||
debugModule.debug.node := debugModuleXbarOpt.get
|
||||
debugModule.debug.node := SepTLXbarOpt.get
|
||||
} else {
|
||||
debugModule.debug.node := device_xbar.get
|
||||
}
|
||||
debugModule.debug.dmInner.dmInner.sb2tlOpt.foreach { sb2tl =>
|
||||
error_xbar.get := sb2tl.node
|
||||
}
|
||||
if(SeperateTLBus){
|
||||
timer.node := SepTLXbarOpt.get
|
||||
} else{
|
||||
timer.node := device_xbar.get
|
||||
}
|
||||
} else {
|
||||
if (SeperateDM) {
|
||||
debugModule.debug.node := debugModuleXbarOpt.get
|
||||
debugModule.debug.node := SepTLXbarOpt.get
|
||||
} else {
|
||||
debugModule.debug.node := peripheralXbar.get
|
||||
}
|
||||
debugModule.debug.dmInner.dmInner.sb2tlOpt.foreach { sb2tl =>
|
||||
l3_xbar.get := TLBuffer() := TLWidthWidget(1) := sb2tl.node
|
||||
}
|
||||
if(SeperateTLBus){
|
||||
timer.node := SepTLXbarOpt.get
|
||||
} else{
|
||||
timer.node := peripheralXbar.get
|
||||
}
|
||||
}
|
||||
|
||||
val pma = LazyModule(new TLPMA)
|
||||
|
@ -534,12 +557,19 @@ class MemMisc()(implicit p: Parameters) extends BaseSoC
|
|||
|
||||
val debug_module_io = IO(new debugModule.DebugModuleIO)
|
||||
val ext_intrs = IO(Input(UInt(NrExtIntr.W)))
|
||||
val rtc_clock = IO(Input(Bool()))
|
||||
val rtc_clock = IO(Input(Clock()))
|
||||
val rtc_reset = IO(Input(Reset()))
|
||||
val bus_clock = IO(Input(Clock()))
|
||||
val bus_reset = IO(Input(Reset()))
|
||||
val pll0_lock = IO(Input(Bool()))
|
||||
val pll0_ctrl = IO(Output(Vec(6, UInt(32.W))))
|
||||
val cacheable_check = IO(new TLPMAIO)
|
||||
val clintTime = IO(Output(ValidIO(UInt(64.W))))
|
||||
|
||||
val scntIO = IO(new Bundle {
|
||||
val update_en = Input(Bool())
|
||||
val update_value = Input(UInt(timeWidth.W))
|
||||
val stop_en = Input(Bool())
|
||||
})
|
||||
debugModule.module.io <> debug_module_io
|
||||
|
||||
// sync external interrupts
|
||||
|
@ -558,14 +588,26 @@ class MemMisc()(implicit p: Parameters) extends BaseSoC
|
|||
axi4memencrpty.get.module.io.random_data := cnt(0).asBool
|
||||
}
|
||||
// positive edge sampling of the lower-speed rtc_clock
|
||||
val rtcTick = RegInit(0.U(3.W))
|
||||
rtcTick := Cat(rtcTick(1, 0), rtc_clock)
|
||||
clint.module.io.rtcTick := rtcTick(1) && !rtcTick(2)
|
||||
// val rtcTick = RegInit(0.U(3.W))
|
||||
// rtcTick := Cat(rtcTick(1, 0), rtc_clock)
|
||||
// clint.module.io.rtcTick := rtcTick(1) && !rtcTick(2)
|
||||
|
||||
val pll_ctrl_regs = Seq.fill(6){ RegInit(0.U(32.W)) }
|
||||
val pll_lock = RegNext(next = pll0_lock, init = false.B)
|
||||
|
||||
clintTime := clint.module.io.time
|
||||
// timer instance
|
||||
clintTime := syscnt.module.io.time // syscnt ->timeasync
|
||||
timer.module.io.time <> syscnt.module.io.time
|
||||
timer.module.io.hartId := 0.U
|
||||
|
||||
// instance syscnt
|
||||
syscnt.module.rtc_clock := rtc_clock
|
||||
syscnt.module.rtc_reset := rtc_reset
|
||||
syscnt.module.bus_clock := bus_clock
|
||||
syscnt.module.bus_reset := bus_reset
|
||||
syscnt.module.io.update_en := scntIO.update_en
|
||||
syscnt.module.io.update_value := scntIO.update_value
|
||||
syscnt.module.io.stop_en := scntIO.stop_en
|
||||
|
||||
pll0_ctrl <> VecInit(pll_ctrl_regs)
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ class XSTop()(implicit p: Parameters) extends BaseXSSoc()
|
|||
val nmi = InModuleBody(nmiIntNode.makeIOs())
|
||||
|
||||
for (i <- 0 until NumCores) {
|
||||
core_with_l2(i).clint_int_node := misc.clint.intnode
|
||||
core_with_l2(i).clint_int_node := misc.timer.intnode
|
||||
core_with_l2(i).plic_int_node :*= misc.plic.intnode
|
||||
core_with_l2(i).debug_int_node := misc.debugModule.debug.dmOuter.dmOuter.intnode
|
||||
core_with_l2(i).nmi_int_node := nmiIntNode
|
||||
|
@ -175,17 +175,17 @@ class XSTop()(implicit p: Parameters) extends BaseXSSoc()
|
|||
println(s"Connecting Core_${i}'s L1 pf source to L3!")
|
||||
recv := core_with_l2(i).core_l3_pf_port.get
|
||||
})
|
||||
misc.debugModuleXbarOpt.foreach { debugModuleXbar =>
|
||||
misc.SepTLXbarOpt.foreach { SepTLXbarOpt =>
|
||||
// SeperateTlBus can only be connected to DebugModule now in non-XSNoCTop environment
|
||||
println(s"SeparateDM: ${SeperateDM}")
|
||||
println(s"misc.debugModuleXbarOpt: ${misc.debugModuleXbarOpt}")
|
||||
println(s"misc.SepTLXbarOpt: ${misc.SepTLXbarOpt}")
|
||||
require(core_with_l2(i).sep_tl_opt.isDefined)
|
||||
require(SeperateTLBusRanges.size == 1)
|
||||
require(SeperateTLBusRanges.head == p(DebugModuleKey).get.address)
|
||||
debugModuleXbar := core_with_l2(i).sep_tl_opt.get
|
||||
require(SeperateTLBusRanges.size >= 1)
|
||||
require(SeperateTLBusRanges.head.base <= p(DebugModuleKey).get.address.base)
|
||||
require(SeperateTLBusRanges.head.base <= p(SoCParamsKey).TIMERRange.base)
|
||||
SepTLXbarOpt := core_with_l2(i).sep_tl_opt.get
|
||||
}
|
||||
}
|
||||
|
||||
l3cacheOpt.map(_.ctlnode.map(_ := misc.peripheralXbar.get))
|
||||
l3cacheOpt.map(_.intnode.map(int => {
|
||||
misc.plic.intnode := IntBuffer() := int
|
||||
|
@ -276,7 +276,7 @@ class XSTop()(implicit p: Parameters) extends BaseXSSoc()
|
|||
val version = Input(UInt(4.W))
|
||||
}
|
||||
val debug_reset = Output(Bool())
|
||||
val rtc_clock = Input(Bool())
|
||||
val rtc_clock = Input(Clock())
|
||||
val cacheable_check = new TLPMAIO()
|
||||
val riscv_halt = Output(Vec(NumCores, Bool()))
|
||||
val riscv_critical_error = Output(Vec(NumCores, Bool()))
|
||||
|
@ -322,13 +322,22 @@ class XSTop()(implicit p: Parameters) extends BaseXSSoc()
|
|||
dontTouch(io)
|
||||
dontTouch(memory)
|
||||
misc.module.ext_intrs := io.extIntrs
|
||||
misc.module.rtc_clock := io.rtc_clock
|
||||
misc.module.pll0_lock := io.pll0_lock
|
||||
misc.module.cacheable_check <> io.cacheable_check
|
||||
|
||||
io.pll0_ctrl <> misc.module.pll0_ctrl
|
||||
|
||||
val msiInfo = WireInit(0.U.asTypeOf(ValidIO(UInt(soc.IMSICParams.MSI_INFO_WIDTH.W))))
|
||||
// syscnt io input descrip
|
||||
val ref_reset_sync = withClockAndReset(io.rtc_clock, io.reset) { ResetGen() }
|
||||
misc.module.scntIO.update_en := false.B
|
||||
misc.module.scntIO.update_value := 0.U
|
||||
misc.module.scntIO.stop_en := false.B
|
||||
misc.module.rtc_clock := io.rtc_clock // syscnt clock
|
||||
misc.module.rtc_reset := ref_reset_sync.asAsyncReset
|
||||
misc.module.bus_clock := io.clock
|
||||
misc.module.bus_reset := io.reset
|
||||
|
||||
|
||||
|
||||
for ((core, i) <- core_with_l2.zipWithIndex) {
|
||||
|
|
|
@ -83,9 +83,12 @@ trait HasAsyncClockImp { this: BaseXSSocImp =>
|
|||
val noc_reset = socParams.EnableCHIAsyncBridge.map(_ => IO(Input(AsyncReset())))
|
||||
val soc_clock = IO(Input(Clock()))
|
||||
val soc_reset = IO(Input(AsyncReset()))
|
||||
val clint_clock = IO(Input(Clock()))
|
||||
val clint_reset = IO(Input(AsyncReset()))
|
||||
|
||||
val noc_reset_sync = socParams.EnableCHIAsyncBridge.map(_ => withClockAndReset(noc_clock, noc_reset) { ResetGen(io.dft_reset) })
|
||||
val soc_reset_sync = withClockAndReset(soc_clock, soc_reset) { ResetGen(io.dft_reset) }
|
||||
val clint_reset_sync = withClockAndReset(clint_clock, clint_reset) { ResetGen(io.dft_reset) }
|
||||
}
|
||||
|
||||
trait HasCoreLowPowerImp[+L <: HasXSTile] { this: BaseXSSocImp with HasXSTileCHIImp[L] =>
|
||||
|
@ -133,11 +136,23 @@ trait HasCoreLowPowerImp[+L <: HasXSTile] { this: BaseXSSocImp with HasXSTileCHI
|
|||
val isNormal = lpState === sIDLE
|
||||
val wfiGateClock = withClockAndReset(clock, cpuReset_sync) {RegInit(false.B)}
|
||||
val flitpend = io_chi.rx.snp.flitpend | io_chi.rx.rsp.flitpend | io_chi.rx.dat.flitpend
|
||||
val msip_mux = socParams.SeperateTLBus match {
|
||||
case (true) =>
|
||||
core_with_l2.timer.get.intnode.out.head._1(0)
|
||||
case (false) =>
|
||||
core_with_l2.clintIntNode.get.out.head._1(0)
|
||||
}
|
||||
val mtip_mux = socParams.SeperateTLBus match {
|
||||
case (true) =>
|
||||
core_with_l2.timer.get.intnode.out.head._1(1)
|
||||
case (false) =>
|
||||
core_with_l2.clintIntNode.get.out.head._1(1)
|
||||
}
|
||||
|
||||
if (socParams.WFIClockGate) {
|
||||
// Interrupt sources collect
|
||||
val msip = withClockAndReset(clock, cpuReset_sync) {AsyncResetSynchronizerShiftReg(clint.head(0), 3, 0)}
|
||||
val mtip = withClockAndReset(clock, cpuReset_sync) {AsyncResetSynchronizerShiftReg(clint.head(1), 3, 0)}
|
||||
val msip = withClockAndReset(clock, cpuReset_sync) {AsyncResetSynchronizerShiftReg(msip_mux, 3, 0)}
|
||||
val mtip = withClockAndReset(clock, cpuReset_sync) {AsyncResetSynchronizerShiftReg(mtip_mux, 3, 0)}
|
||||
val meip = withClockAndReset(clock, cpuReset_sync) {AsyncResetSynchronizerShiftReg(plic.head(0), 3, 0)}
|
||||
val seip = withClockAndReset(clock, cpuReset_sync) {AsyncResetSynchronizerShiftReg(plic.last(0), 3, 0)}
|
||||
val nmi_31 = withClockAndReset(clock, cpuReset_sync) {AsyncResetSynchronizerShiftReg(nmi.head(0), 3, 0)}
|
||||
|
@ -187,19 +202,18 @@ trait HasXSTile { this: BaseXSSoc =>
|
|||
case XSCoreParamsKey => tiles.head
|
||||
case PerfCounterOptionsKey => up(PerfCounterOptionsKey).copy(perfDBHartID = tiles.head.HartId)
|
||||
})))
|
||||
|
||||
// interrupts
|
||||
val clintIntNode = IntSourceNode(IntSourcePortSimple(1, 1, 2))
|
||||
val clintIntNode = Option.when(!SeperateTLBus)(IntSourceNode(IntSourcePortSimple(1, 1, 2)))
|
||||
val debugIntNode = IntSourceNode(IntSourcePortSimple(1, 1, 1))
|
||||
val plicIntNode = IntSourceNode(IntSourcePortSimple(1, 2, 1))
|
||||
val nmiIntNode = IntSourceNode(IntSourcePortSimple(1, 1, (new NonmaskableInterruptIO).elements.size))
|
||||
val beuIntNode = IntSinkNode(IntSinkPortSimple(1, 1))
|
||||
core_with_l2.clintIntNode := clintIntNode
|
||||
core_with_l2.clintIntNode.map(_ := clintIntNode.get) //from soc
|
||||
core_with_l2.debugIntNode := debugIntNode
|
||||
core_with_l2.plicIntNode :*= plicIntNode
|
||||
core_with_l2.nmiIntNode := nmiIntNode
|
||||
beuIntNode := core_with_l2.beuIntNode
|
||||
val clint = InModuleBody(clintIntNode.makeIOs())
|
||||
val clint = InModuleBody(clintIntNode.map(_.makeIOs()))
|
||||
val debug = InModuleBody(debugIntNode.makeIOs())
|
||||
val plic = InModuleBody(plicIntNode.makeIOs())
|
||||
val nmi = InModuleBody(nmiIntNode.makeIOs())
|
||||
|
@ -261,9 +275,9 @@ trait HasXSTileCHIImp[+L <: HasXSTile] extends HasXSTileImp[L] {
|
|||
socParams.EnableCHIAsyncBridge match {
|
||||
case Some(param) =>
|
||||
withClockAndReset(noc_clock.get, noc_reset_sync.get) {
|
||||
val sink = Module(new CHIAsyncBridgeSink(param))
|
||||
sink.io.async <> core_with_l2.module.io.chi
|
||||
io_chi <> sink.io.deq
|
||||
val time_sink = Module(new CHIAsyncBridgeSink(param))
|
||||
time_sink.io.async <> core_with_l2.module.io.chi
|
||||
io_chi <> time_sink.io.deq
|
||||
}
|
||||
case None =>
|
||||
io_chi <> core_with_l2.module.io.chi
|
||||
|
@ -283,7 +297,7 @@ trait HasSeperatedTLBusOpt { this: BaseXSSoc with HasXSTile =>
|
|||
// The Manager Node is only used to make IO
|
||||
val tl = Option.when(SeperateTLBus)(TLManagerNode(Seq(
|
||||
TLSlavePortParameters.v1(
|
||||
managers = SeperateTLBusRanges map { address =>
|
||||
managers = SeperateTLBusRanges.filter(address => !address.overlaps(soc.TIMERRange)) map { address =>
|
||||
TLSlaveParameters.v1(
|
||||
address = Seq(address),
|
||||
regionType = RegionType.UNCACHED,
|
||||
|
@ -393,11 +407,11 @@ trait HasClintTimeImp[+L <: HasXSTile] { this: BaseXSSocImp with HasAsyncClockIm
|
|||
|
||||
socParams.EnableClintAsyncBridge match {
|
||||
case Some(param) =>
|
||||
withClockAndReset(soc_clock, soc_reset_sync) {
|
||||
val source = Module(new AsyncQueueSource(UInt(64.W), param))
|
||||
source.io.enq.valid := io_clintTime.valid
|
||||
source.io.enq.bits := io_clintTime.bits
|
||||
core_with_l2.module.io.clintTime <> source.io.async
|
||||
withClockAndReset(clint_clock, clint_reset_sync) {
|
||||
val time_source = Module(new AsyncQueueSource(UInt(64.W), param))
|
||||
time_source.io.enq.valid := io_clintTime.valid
|
||||
time_source.io.enq.bits := io_clintTime.bits
|
||||
core_with_l2.module.io.clintTime <> time_source.io.async
|
||||
}
|
||||
case None =>
|
||||
core_with_l2.module.io.clintTime <> io_clintTime
|
||||
|
|
|
@ -112,7 +112,8 @@ class L2TopInlined()(implicit p: Parameters) extends LazyModule
|
|||
case L2ParamKey => coreParams.L2CacheParamsOpt.get.copy(
|
||||
hartId = p(XSCoreParamsKey).HartId,
|
||||
FPGAPlatform = debugOpts.FPGAPlatform,
|
||||
hasMbist = hasMbist
|
||||
hasMbist = hasMbist,
|
||||
EnablePrivateClint = SeperateTLBus
|
||||
)
|
||||
case EnableCHI => p(EnableCHI)
|
||||
case CHIIssue => p(CHIIssue)
|
||||
|
|
|
@ -18,6 +18,7 @@ package xiangshan
|
|||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import device.{TIMER, TIMERParams, TimeAsync}
|
||||
import org.chipsalliance.cde.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
|
@ -42,12 +43,15 @@ class XSTileWrap()(implicit p: Parameters) extends LazyModule
|
|||
val tile = LazyModule(new XSTile())
|
||||
|
||||
// interrupts sync
|
||||
val clintIntNode = IntIdentityNode()
|
||||
val SeperateTLsync = SeperateTLBus && (!EnableSeperateTLAsync)
|
||||
val clintIntNode = Option.when(!SeperateTLBus)(IntIdentityNode()) // interrupt from CHI or (TL & async)
|
||||
val debugIntNode = IntIdentityNode()
|
||||
val plicIntNode = IntIdentityNode()
|
||||
val beuIntNode = IntIdentityNode()
|
||||
val nmiIntNode = IntIdentityNode()
|
||||
tile.clint_int_node := IntBuffer(3, cdc = true) := clintIntNode
|
||||
// instance clint timer
|
||||
val timer = Option.when(SeperateTLBus)(LazyModule(new TIMER(TIMERParams(IsSelfTest=false,soc.TIMERRange.base), 8))) // TL & sync
|
||||
tile.clint_int_node := IntBuffer(3, cdc = true) := clintIntNode.getOrElse(timer.get.intnode)
|
||||
tile.debug_int_node := IntBuffer(3, cdc = true) := debugIntNode
|
||||
tile.plic_int_node :*= IntBuffer(3, cdc = true) :*= plicIntNode
|
||||
tile.nmi_int_node := IntBuffer(3, cdc = true) := nmiIntNode
|
||||
|
@ -56,12 +60,15 @@ class XSTileWrap()(implicit p: Parameters) extends LazyModule
|
|||
// seperate TL bus
|
||||
println(s"SeperateTLBus = $SeperateTLBus")
|
||||
println(s"EnableSeperateTLAsync = $EnableSeperateTLAsync")
|
||||
val tlXbar = Option.when(SeperateTLBus)(TLXbar())
|
||||
tlXbar.map(_ := tile.sep_tl_opt.get) // TLXbar node in connect with tile master
|
||||
timer.map(_.node := tlXbar.get) // TLXbar node out connnect with timer mmio
|
||||
// asynchronous bridge source node
|
||||
val tlAsyncSourceOpt = Option.when(SeperateTLBus && EnableSeperateTLAsync)(LazyModule(new TLAsyncCrossingSource()))
|
||||
tlAsyncSourceOpt.foreach(_.node := tile.sep_tl_opt.get)
|
||||
tlAsyncSourceOpt.foreach(_.node := tlXbar.get)
|
||||
// synchronous source node
|
||||
val tlSyncSourceOpt = Option.when(SeperateTLBus && !EnableSeperateTLAsync)(TLTempNode())
|
||||
tlSyncSourceOpt.foreach(_ := tile.sep_tl_opt.get)
|
||||
val tlSyncSourceOpt = Option.when(SeperateTLBus && SeperateTLsync)(TLTempNode())
|
||||
tlSyncSourceOpt.foreach(_ := tlXbar.get)
|
||||
|
||||
class XSTileWrapImp(wrapper: LazyModule) extends LazyRawModuleImp(wrapper) {
|
||||
val clock = IO(Input(Clock()))
|
||||
|
@ -109,6 +116,11 @@ class XSTileWrap()(implicit p: Parameters) extends LazyModule
|
|||
childClock := clock
|
||||
childReset := reset_sync
|
||||
|
||||
timer.foreach { timerInst =>
|
||||
timerInst.module.io.hartId := io.hartId
|
||||
timerInst.module.io.time := tile.module.io.clintTime
|
||||
}
|
||||
|
||||
tile.module.io.hartId := io.hartId
|
||||
tile.module.io.msiInfo := io.msiInfo
|
||||
tile.module.io.reset_vector := io.reset_vector
|
||||
|
@ -134,11 +146,11 @@ class XSTileWrap()(implicit p: Parameters) extends LazyModule
|
|||
// CLINT Async Queue Sink
|
||||
EnableClintAsyncBridge match {
|
||||
case Some(param) =>
|
||||
val sink = withClockAndReset(clock, soc_reset_sync)(Module(new AsyncQueueSink(UInt(64.W), param)))
|
||||
sink.io.async <> io.clintTime
|
||||
sink.io.deq.ready := true.B
|
||||
tile.module.io.clintTime.valid := sink.io.deq.valid
|
||||
tile.module.io.clintTime.bits := sink.io.deq.bits
|
||||
val time_sink = withClockAndReset(clock, soc_reset_sync)(Module(new AsyncQueueSink(UInt(64.W), param)))
|
||||
time_sink.io.async <> io.clintTime
|
||||
time_sink.io.deq.ready := true.B
|
||||
tile.module.io.clintTime.valid := time_sink.io.deq.valid
|
||||
tile.module.io.clintTime.bits := time_sink.io.deq.bits
|
||||
case None =>
|
||||
tile.module.io.clintTime := io.clintTime
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ class SimTop(implicit p: Parameters) extends Module {
|
|||
when (rtcCounter === 0.U) {
|
||||
rtcClock := ~rtcClock
|
||||
}
|
||||
soc.io.rtc_clock := rtcClock
|
||||
soc.io.rtc_clock := rtcClock.asClock
|
||||
|
||||
val success = Wire(Bool())
|
||||
val jtag = Module(new SimJTAG(tickDelay = 3)(p))
|
||||
|
|
Loading…
Reference in New Issue