rocket-chipリセットベクトルの修正
7091 ワード
rocket-chipリセットベクトルの修正
rocket-chipシステムのリセット後はbootromから起動されます.この章では、rocket-chipがbootromモジュールをどのように呼び出すかを詳細に分析し、最後にリセットベクトルを修正します.つまり、rocket-chipがbootromから起動するのではなく、私たちが望んでいるアドレスから起動します.
bootromモジュールの呼び出し:まず注目するscalaファイルは/src/main/scala/system/ExampleRocketSystemである.scala
HasPeripheryBootROM&HasPeripheryBootROMModuleImpはbootromを呼び出す場所です.どこで見つけられますか?答えは/src/main/scala/devices/tilelink/BootROMです.scala
上のコードから分かるように、HasPeripheryBootROMModuleImpにはglobal_reset_vector := outer.resetVector.一方、HasPeripheryBootROMではdef resetVector:BigInt=paramsと定義する.最後にparamsまで追いかけたhangはBootROMParamsで定義され、hang=0 x 10040である.簡略化点はglobal_reset_vector = resetVector = params.hang = 0x10040.0 x 10040はbootromの開始アドレスであり、この値をglobal_に伝達するreset_vector、ではglobal_reset_vectorはどこで見つけましたか?
答えは/src/main/scala/subsystem/ResetVectorです.scala
ではglobal_reset_vectorはどのようにcpu内部に伝わりますか?答えは/src/main/scala/subsystem/RocketSubsystemscala
wire.reset_vectorはglobal_reset_vectorの値はcpu coreの内部に伝わります.ここまでrocket-chipがbootromから起動する大まかな状況は説明済みで、以下に私が自分で修正したリセットベクトルを紹介します.コードは以下のように変更されます.変更ファイルは(/src/main/scala/subsystem/RocketSubsystem/scala):
上記の方法でrocket-chipをbootromから起動するのではなく、私たちが入力したreset_から起動することができます.vectorが起動します.
rocket-chipシステムのリセット後はbootromから起動されます.この章では、rocket-chipがbootromモジュールをどのように呼び出すかを詳細に分析し、最後にリセットベクトルを修正します.つまり、rocket-chipがbootromから起動するのではなく、私たちが望んでいるアドレスから起動します.
bootromモジュールの呼び出し:まず注目するscalaファイルは/src/main/scala/system/ExampleRocketSystemである.scala
package freechips.rocketchip.system
import Chisel._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.util.DontTouch
/** Example Top with periphery devices and ports, and a Rocket subsystem */
class ExampleRocketSystem(implicit p: Parameters) extends RocketSubsystem
with HasAsyncExtInterrupts
with CanHaveMasterAXI4MemPort
with CanHaveMasterAXI4MMIOPort
with CanHaveSlaveAXI4Port
with HasPeripheryBootROM {
override lazy val module = new ExampleRocketSystemModuleImp(this)
// Error device used for testing and to NACK invalid front port transactions
val error = LazyModule(new TLError(p(ErrorDeviceKey), sbus.beatBytes))
// always buffer the error device because no one cares about its latency
sbus.coupleTo("slave_named_error"){ error.node := TLBuffer() := _ }
}
class ExampleRocketSystemModuleImp[+L <: examplerocketsystem="" l="" extends="" rocketsubsystemmoduleimp="" with="" hasrtcmoduleimp="" hasextinterruptsmoduleimp="" canhavemasteraxi4memportmoduleimp="" canhavemasteraxi4mmioportmoduleimp="" canhaveslaveaxi4portmoduleimp="" hasperipherybootrommoduleimp="" donttouch=""/>
HasPeripheryBootROM&HasPeripheryBootROMModuleImpはbootromを呼び出す場所です.どこで見つけられますか?答えは/src/main/scala/devices/tilelink/BootROMです.scala
package freechips.rocketchip.devices.tilelink
import Chisel._
import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.subsystem.{BaseSubsystem, HasResetVectorWire}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
import java.nio.{ByteBuffer, ByteOrder}
import java.nio.file.{Files, Paths}
/** Size, location and contents of the boot rom. */
case class BootROMParams(
address: BigInt = 0x10000,
size: Int = 0x10000,
hang: BigInt = 0x10040,
contentFileName: String)
case object BootROMParams extends Field[BootROMParams]
class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4,
resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule
{
val node = TLManagerNode(Seq(TLManagerPortParameters(
Seq(TLManagerParameters(
address = List(AddressSet(base, size-1)),
resources = resources,
regionType = RegionType.UNCACHED,
executable = executable,
supportsGet = TransferSizes(1, beatBytes),
fifoId = Some(0))),
beatBytes = beatBytes)))
lazy val module = new LazyModuleImp(this) {
val contents = contentsDelayed
val wrapSize = 1 << log2Ceil(contents.size)
require (wrapSize <= size)
val (in, edge) = node.in(0)
val words = (contents ++ Seq.fill(wrapSize-contents.size)(0.toByte)).grouped(beatBytes).toSeq
val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8})
val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes)))
in.d.valid := in.a.valid
in.a.ready := in.d.ready
val index = in.a.bits.address(log2Ceil(wrapSize)-1,log2Ceil(beatBytes))
val high = if (wrapSize == size) UInt(0) else in.a.bits.address(log2Ceil(size)-1, log2Ceil(wrapSize))
in.d.bits := edge.AccessAck(in.a.bits, Mux(high.orR, UInt(0), rom(index)))
// Tie off unused channels
in.b.valid := Bool(false)
in.c.ready := Bool(true)
in.e.ready := Bool(true)
}
}
/** Adds a boot ROM that contains the DTB describing the system's subsystem. */
trait HasPeripheryBootROM { this: BaseSubsystem =>
val dtb: DTB
private val params = p(BootROMParams)
private lazy val contents = {
val romdata = Files.readAllBytes(Paths.get(params.contentFileName))
val rom = ByteBuffer.wrap(romdata)
rom.array() ++ dtb.contents
}
def resetVector: BigInt = params.hang
val bootrom = LazyModule(new TLROM(params.address, params.size, contents, true, sbus.control_bus.beatBytes))
sbus.control_bus.toVariableWidthSlave(Some("bootrom")){ bootrom.node }
}
/** Subsystem will power-on running at 0x10040 (BootROM) */
trait HasPeripheryBootROMModuleImp extends LazyModuleImp
with HasResetVectorWire {
val outer: HasPeripheryBootROM
global_reset_vector := outer.resetVector.U
}
上のコードから分かるように、HasPeripheryBootROMModuleImpにはglobal_reset_vector := outer.resetVector.一方、HasPeripheryBootROMではdef resetVector:BigInt=paramsと定義する.最後にparamsまで追いかけたhangはBootROMParamsで定義され、hang=0 x 10040である.簡略化点はglobal_reset_vector = resetVector = params.hang = 0x10040.0 x 10040はbootromの開始アドレスであり、この値をglobal_に伝達するreset_vector、ではglobal_reset_vectorはどこで見つけましたか?
答えは/src/main/scala/subsystem/ResetVectorです.scala
package freechips.rocketchip.subsystem
import Chisel._
/** A single place for all tiles to find out the reset vector */
trait HasResetVectorWire {
def resetVectorBits: Int
val global_reset_vector = Wire(UInt(width = resetVectorBits))
}
ではglobal_reset_vectorはどのようにcpu内部に伝わりますか?答えは/src/main/scala/subsystem/RocketSubsystemscala
//
class RocketSubsystemModuleImp[+L <: rocketsubsystem="" l="" extends="" basesubsystemmoduleimp="" with="" hasrockettilesmoduleimp="" tile_inputs.zip="" case="" i="">
wire.clock := clock
wire.reset := reset
wire.hartid := UInt(i)
wire.reset_vector := global_reset_vector
}
}
wire.reset_vectorはglobal_reset_vectorの値はcpu coreの内部に伝わります.ここまでrocket-chipがbootromから起動する大まかな状況は説明済みで、以下に私が自分で修正したリセットベクトルを紹介します.コードは以下のように変更されます.変更ファイルは(/src/main/scala/subsystem/RocketSubsystem/scala):
class RocketSubsystemModuleImp[+L <: rocketsubsystem="" l="" extends="" basesubsystemmoduleimp="" with="" hasrockettilesmoduleimp="" tile_inputs.zip="" case="" i="">
wire.clock := clock
wire.reset := reset
wire.hartid := UInt(i)
wire.reset_vector := global_reset_vector
}
//xhunter_modify
// reset_vector ,Uint ,input,32
val reset_vector = IO(UInt(INPUT, width = 32))
// reset_vector global_reset_vector
// /src/main/scala/system/ExampleRocketSystem.scala HasPeripheryBootROM & HasPeripheryBootROMModuleImp
global_reset_vector := reset_vector
}
上記の方法でrocket-chipをbootromから起動するのではなく、私たちが入力したreset_から起動することができます.vectorが起動します.