@@ -489,17 +489,38 @@ class WithTraceIOPunchthrough extends OverrideLazyIOBinder({
489489 val chipyardSystem = system.asInstanceOf [ChipyardSystem ]
490490 val tiles = chipyardSystem.totalTiles.values
491491 val viewpointBus = system.asInstanceOf [HasConfigurableTLNetworkTopology ].viewpointBus
492+ val ignoreAddresses = Seq (
493+ BigInt (0x10000 ) // bootrom is handled specially
494+ )
495+ // The debug module goes in neither list: access is denied outside debug mode,
496+ // so spike having no device there is what makes both models fault.
497+ val debugAddresses = p(DebugModuleKey ).toSeq.map(_.address.base)
498+ val skipAddresses = ignoreAddresses ++ debugAddresses
499+ val memRegionTypes = Seq (RegionType .CACHED , RegionType .TRACKED ,
500+ RegionType .UNCACHED , RegionType .IDEMPOTENT )
492501 val mems = viewpointBus.unifyManagers.filter { m =>
493- val regionTypes = Seq (RegionType .CACHED , RegionType .TRACKED , RegionType .UNCACHED , RegionType .IDEMPOTENT )
494- val ignoreAddresses = Seq (
495- 0x10000 // bootrom is handled specially
496- )
497- regionTypes.contains(m.regionType) && ! ignoreAddresses.contains(m.address.map(_.base).min)
502+ memRegionTypes.contains(m.regionType) && ! skipAddresses.contains(m.address.map(_.base).min)
503+ }.map { m =>
504+ val base = m.address.map(_.base).min
505+ val size = m.address.map(_.max).max - base + 1
506+ (base, size)
507+ }
508+ // A device is anything in the map that is not memory. The complement, not a
509+ // list of region types: enumerating types silently omits any rocket adds or
510+ // renames, which is how RegionType.VOLATILE (rocket's TLError) was missed.
511+ val devices = viewpointBus.unifyManagers.filter { m =>
512+ ! memRegionTypes.contains(m.regionType) && ! skipAddresses.contains(m.address.map(_.base).min)
498513 }.map { m =>
499514 val base = m.address.map(_.base).min
500515 val size = m.address.map(_.max).max - base + 1
501516 (base, size)
502517 }
518+ // Asserted, not assumed: a later change to the address map, the region types
519+ // or the filter above fails elaboration instead of hiding a bug class.
520+ require(! devices.exists { case (base, size) =>
521+ debugAddresses.exists(d => d >= base && d < base + size) },
522+ s " cospike: the debug module must not be registered as a device " +
523+ s " (devices= $devices, debug= $debugAddresses) " )
503524 val useSimDTM = p(ExportDebug ).protocols.contains(DMI ) // assume that exposing clockeddmi means we will connect SimDTM
504525 val cfg = SpikeCosimConfig (
505526 isa = tiles.headOption.map(_.isaDTS).getOrElse(" " ),
@@ -510,6 +531,24 @@ class WithTraceIOPunchthrough extends OverrideLazyIOBinder({
510531 bootrom = chipyardSystem.bootROM.headOption.map(_.module.contents.toArray.mkString(" " )).getOrElse(" " ),
511532 has_dtm = useSimDTM,
512533 mems = mems,
534+ devices = devices,
535+ customCSRs = tiles.headOption.toSeq.flatMap { t =>
536+ // t.p, not p: CustomCSRs builds a CoreBundle, which needs p(TileKey).
537+ t.tileParams.core.customCSRs(t.p).decls.map(c =>
538+ (c.id, c.mask, c.init.getOrElse(BigInt (0 ))))
539+ },
540+ paddrBits = viewpointBus.busView.bundle.addressBits,
541+ // Mirrors HasTileParameters.{vaddrBits,vpnBitsExtended}, which tiles do
542+ // not mix in (BaseTile only gets HasNonDiplomaticTileParameters).
543+ vaddrBitsExtended = tiles.headOption.map { t =>
544+ val pa = viewpointBus.busView.bundle.addressBits
545+ val va = if (t.usingVM) t.maxHVAddrBits else ((pa + 1 ) min t.xLen)
546+ va + (if (va < t.xLen) 1 + (if (t.usingHypervisor) 1 else 0 ) else 0 )
547+ }.getOrElse(0 ),
548+ // The CSR count, not nPMPs: rocket fixes it at CSR.maxPMPs if any PMP exists.
549+ npmpcsrs = tiles.headOption.map(t =>
550+ if (t.tileParams.core.nPMPs > 0 ) freechips.rocketchip.rocket.CSR .maxPMPs
551+ else 0 ).getOrElse(0 ),
513552 // Connect using the legacy API for firesim only
514553 mem0_base = p(ExtMem ).map(_.master.base).getOrElse(BigInt (0 )),
515554 mem0_size = p(ExtMem ).map(_.master.size).getOrElse(BigInt (0 )),
0 commit comments