FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

RocketChipの足回りを理解する(3. BootROM)

RocketChipのリセットが解除されると、まずはBootROMへのフェッチが始まる。 BootROMは、TestDriver/TestHarness/ExampleRocketTop/bootromに格納されている。

まずはこの周辺の波形を見てみよう。最初にBootROMにアクセスするのは、0x00010040 がアクセスされている。そもそも、このリセットベクタはどこから来てるのかね?

f:id:msyksphinz:20170715113801p:plain

RISCVPlatform.scalaにリセット時の初期値が書いてあった。

/** Adds a boot ROM that contains the DTB describing the system's coreplex. */
trait HasPeripheryBootROM extends HasSystemNetworks with HasCoreplexRISCVPlatform {
  val bootrom_address = 0x10000
  val bootrom_size    = 0x10000
  val bootrom_hang    = 0x10040
  private lazy val bootrom_contents = GenerateBootROM(coreplex.dtb)
  val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes))

  bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
}

/** Coreplex will power-on running at 0x10040 (BootROM) */
trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp {
  val outer: HasPeripheryBootROM
  outer.coreplex.module.io.resetVector := UInt(outer.bootrom_hang)
}

ちなみにこのbootromなのだが、Verilogの実装を見てみると、初期値がそのまま記述してある。

scalaでの記述はこちら。rocket-chip/src/main/scala/coreplex/Config.scalaを参照のこと。

class BaseCoreplexConfig extends Config ((site, here, up) => {
  case PAddrBits => 32
  case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */
  case ASIdBits => 0
  case XLen => 64 // Applies to all cores
  case ResetVectorBits => site(PAddrBits)
  case MaxHartIdBits => log2Up(site(RocketTilesKey).size)
  case BuildCore => (p: Parameters) => new Rocket()(p)
  case RocketCrossing => SynchronousCrossing()
  case RocketTilesKey =>  Nil
  case DMKey => DefaultDebugModuleConfig(site(XLen))
  case PLICKey => PLICParams()
  case ClintKey => ClintParams()
  case CBusConfig => TLBusConfig(beatBytes = site(XLen)/8)
  case L1toL2Config => TLBusConfig(beatBytes = site(XLen)/8) // increase for more PCIe bandwidth
  case BootROMFile => "./bootrom/bootrom.img"
  case BroadcastConfig => BroadcastConfig()
  case BankedL2Config => BankedL2Config()
  case CacheBlockBytes => 64
})

初期値が直打ちしてある。

  assign _GEN_1 = 10'h1 == index ? 32'h1f41413 : 32'h10041b;
  assign _GEN_2 = 10'h2 == index ? 32'hf1402573 : _GEN_1;
  assign _GEN_3 = 10'h3 == index ? 32'h597 : _GEN_2;
  assign _GEN_4 = 10'h4 == index ? 32'h7458593 : _GEN_3;
  assign _GEN_5 = 10'h5 == index ? 32'h8402 : _GEN_4;
  assign _GEN_6 = 10'h6 == index ? 32'h0 : _GEN_5;
  assign _GEN_7 = 10'h7 == index ? 32'h0 : _GEN_6;
  assign _GEN_8 = 10'h8 == index ? 32'h0 : _GEN_7;
  assign _GEN_9 = 10'h9 == index ? 32'h0 : _GEN_8;
  assign _GEN_10 = 10'ha == index ? 32'h0 : _GEN_9;
  assign _GEN_11 = 10'hb == index ? 32'h0 : _GEN_10;
  assign _GEN_12 = 10'hc == index ? 32'h0 : _GEN_11;
  assign _GEN_13 = 10'hd == index ? 32'h0 : _GEN_12;
  assign _GEN_14 = 10'he == index ? 32'h0 : _GEN_13;
  assign _GEN_15 = 10'hf == index ? 32'h0 : _GEN_14;
  assign _GEN_16 = 10'h10 == index ? 32'hf1402573 : _GEN_15;
  assign _GEN_17 = 10'h11 == index ? 32'h597 : _GEN_16;
  assign _GEN_18 = 10'h12 == index ? 32'h3c58593 : _GEN_17;
  assign _GEN_19 = 10'h13 == index ? 32'h10500073 : _GEN_18;
...