rocketchip: use TileLink2 interrupts
This commit is contained in:
		| @@ -36,14 +36,9 @@ trait HasCoreplexParameters { | |||||||
|   lazy val outerMMIOParams = p.alterPartial({ case TLId => "L2toMMIO" }) |   lazy val outerMMIOParams = p.alterPartial({ case TLId => "L2toMMIO" }) | ||||||
|   lazy val globalAddrMap = p(rocketchip.GlobalAddrMap) |   lazy val globalAddrMap = p(rocketchip.GlobalAddrMap) | ||||||
|   lazy val nTiles = p(uncore.devices.NTiles) |   lazy val nTiles = p(uncore.devices.NTiles) | ||||||
|   lazy val nExtInterrupts = p(rocketchip.NExtInterrupts) |  | ||||||
|   lazy val nSlaves = p(rocketchip.NCoreplexExtClients) |   lazy val nSlaves = p(rocketchip.NCoreplexExtClients) | ||||||
|   lazy val nMemChannels = p(NMemoryChannels) |   lazy val nMemChannels = p(NMemoryChannels) | ||||||
|   lazy val hasSupervisor = p(rocket.UseVM) |   lazy val hasSupervisor = p(rocket.UseVM) | ||||||
|  |  | ||||||
|   lazy val nInterruptPriorities = if (nExtInterrupts <= 1) 0 else (nExtInterrupts min 7) |  | ||||||
|   lazy val plicKey = PLICConfig(nTiles, hasSupervisor, nExtInterrupts, nInterruptPriorities) |  | ||||||
|   lazy val clintKey = CoreplexLocalInterrupterConfig() |  | ||||||
| } | } | ||||||
|  |  | ||||||
| case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters | case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters | ||||||
| @@ -65,16 +60,29 @@ trait CoreplexNetwork extends HasCoreplexParameters { | |||||||
|   val cbus_beatBytes = p(XLen)/8 |   val cbus_beatBytes = p(XLen)/8 | ||||||
|   val cbus_lineBytes = l1tol2_lineBytes |   val cbus_lineBytes = l1tol2_lineBytes | ||||||
|  |  | ||||||
|  |   val mmio = TLOutputNode() | ||||||
|  |   val mmioInt = IntInputNode() | ||||||
|  |  | ||||||
|   cbus.node := |   cbus.node := | ||||||
|     TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata |     TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata | ||||||
|     TLWidthWidget(l1tol2_beatBytes)( |     TLWidthWidget(l1tol2_beatBytes)( | ||||||
|     TLBuffer()( |     TLBuffer()( | ||||||
|     l1tol2.node))) |     l1tol2.node))) | ||||||
|  |  | ||||||
|  |   mmio := | ||||||
|  |     TLBuffer()( | ||||||
|  |     TLWidthWidget(l1tol2_beatBytes)( | ||||||
|  |     l1tol2.node)) | ||||||
| } | } | ||||||
|  |  | ||||||
| trait CoreplexNetworkBundle extends HasCoreplexParameters { | trait CoreplexNetworkBundle extends HasCoreplexParameters { | ||||||
|     this: BareCoreplexBundle[BareCoreplex] => |   this: { | ||||||
|  |     val outer: CoreplexNetwork | ||||||
|  |   } => | ||||||
|  |  | ||||||
|   implicit val p = outer.p |   implicit val p = outer.p | ||||||
|  |   val mmio = outer.mmio.bundleOut | ||||||
|  |   val interrupts = outer.mmioInt.bundleIn | ||||||
| } | } | ||||||
|  |  | ||||||
| trait CoreplexNetworkModule extends HasCoreplexParameters { | trait CoreplexNetworkModule extends HasCoreplexParameters { | ||||||
| @@ -88,11 +96,11 @@ trait CoreplexRISCV { | |||||||
|   // Build a set of Tiles |   // Build a set of Tiles | ||||||
|   val lazyTiles = p(BuildTiles) map { _(p) } |   val lazyTiles = p(BuildTiles) map { _(p) } | ||||||
|   val legacy = LazyModule(new TLLegacy()(outerMMIOParams)) |   val legacy = LazyModule(new TLLegacy()(outerMMIOParams)) | ||||||
|  |   val tileIntNode = IntInternalOutputNode() // this should be moved into the Tile... | ||||||
|  |  | ||||||
|   val debug = LazyModule(new TLDebugModule()) |   val debug = LazyModule(new TLDebugModule()) | ||||||
|   val plic  = LazyModule(new TLPLIC(() => plicKey)) |   val plic  = LazyModule(new TLPLIC(hasSupervisor, maxPriorities = 7)) | ||||||
|   val clint = LazyModule(new CoreplexLocalInterrupter(clintKey)) |   val clint = LazyModule(new CoreplexLocalInterrupter) | ||||||
|   val mmio = TLOutputNode() |  | ||||||
|  |  | ||||||
|   // Kill this once we move TL2 into rocket |   // Kill this once we move TL2 into rocket | ||||||
|   l1tol2.node := |   l1tol2.node := | ||||||
| @@ -103,10 +111,8 @@ trait CoreplexRISCV { | |||||||
|   plic.node  := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) |   plic.node  := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) | ||||||
|   clint.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) |   clint.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) | ||||||
|  |  | ||||||
|   mmio := |   plic.intnode := mmioInt | ||||||
|     TLBuffer()( |   lazyTiles.foreach { _ => tileIntNode := plic.intnode } | ||||||
|     TLWidthWidget(l1tol2_beatBytes)( |  | ||||||
|     l1tol2.node)) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| trait CoreplexRISCVBundle { | trait CoreplexRISCVBundle { | ||||||
| @@ -114,13 +120,11 @@ trait CoreplexRISCVBundle { | |||||||
|     val outer: CoreplexRISCV |     val outer: CoreplexRISCV | ||||||
|   } => |   } => | ||||||
|  |  | ||||||
|   val mmio = outer.mmio.bundleOut |  | ||||||
|   val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outerMemParams)) |   val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outerMemParams)) | ||||||
|   val slave = Vec(nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip |   val slave = Vec(nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip | ||||||
|   val resetVector = UInt(INPUT, p(XLen)) |   val resetVector = UInt(INPUT, p(XLen)) | ||||||
|   val success = Bool(OUTPUT) // used for testing |   val success = Bool(OUTPUT) // used for testing | ||||||
|   val debug = new DebugBusIO().flip |   val debug = new DebugBusIO().flip | ||||||
|   val interrupts = Vec(nExtInterrupts, Bool()).asInput |  | ||||||
| } | } | ||||||
|  |  | ||||||
| trait CoreplexRISCVModule { | trait CoreplexRISCVModule { | ||||||
| @@ -134,7 +138,7 @@ trait CoreplexRISCVModule { | |||||||
|  |  | ||||||
|   // Create and export the ConfigString |   // Create and export the ConfigString | ||||||
|   val managers = outer.l1tol2.node.edgesIn(0).manager.managers |   val managers = outer.l1tol2.node.edgesIn(0).manager.managers | ||||||
|   val configString = rocketchip.GenerateConfigString(p, managers) |   val configString = rocketchip.GenerateConfigString(p, outer.clint, outer.plic, managers) | ||||||
|   println(s"\nGenerated Configuration String\n${configString}") |   println(s"\nGenerated Configuration String\n${configString}") | ||||||
|   ConfigStringOutput.contents = Some(configString) |   ConfigStringOutput.contents = Some(configString) | ||||||
|  |  | ||||||
| @@ -192,22 +196,16 @@ trait CoreplexRISCVModule { | |||||||
|   for ((tile, i) <- (uncoreTileIOs zipWithIndex)) { |   for ((tile, i) <- (uncoreTileIOs zipWithIndex)) { | ||||||
|     tile.hartid := UInt(i) |     tile.hartid := UInt(i) | ||||||
|     tile.resetVector := io.resetVector |     tile.resetVector := io.resetVector | ||||||
|     tile.interrupts <> outer.clint.module.io.tiles(i) |  | ||||||
|     tile.interrupts.meip := outer.plic.module.io.harts(plicKey.context(i, 'M')) |  | ||||||
|     tile.interrupts.seip.foreach(_ := outer.plic.module.io.harts(plicKey.context(i, 'S'))) |  | ||||||
|     tile.interrupts.debug := outer.debug.module.io.debugInterrupts(i) |     tile.interrupts.debug := outer.debug.module.io.debugInterrupts(i) | ||||||
|   } |     tile.interrupts.meip := outer.tileIntNode.bundleOut(i)(0) | ||||||
|  |     tile.interrupts.seip.foreach(_ := outer.tileIntNode.bundleOut(i)(1)) | ||||||
|   // Coreplex doesn't know when to stop running |  | ||||||
|   io.success := Bool(false) |  | ||||||
|   for (i <- 0 until io.interrupts.size) { |  | ||||||
|     val gateway = Module(new LevelGateway) |  | ||||||
|     gateway.io.interrupt := io.interrupts(i) |  | ||||||
|     outer.plic.module.io.devices(i) <> gateway.io.plic |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   outer.debug.module.io.db <> io.debug |   outer.debug.module.io.db <> io.debug | ||||||
|   outer.clint.module.io.rtcTick := Counter(p(rocketchip.RTCPeriod)).inc() |   outer.clint.module.io.rtcTick := Counter(p(rocketchip.RTCPeriod)).inc() | ||||||
|  |  | ||||||
|  |   // Coreplex doesn't know when to stop running | ||||||
|  |   io.success := Bool(false) | ||||||
| } | } | ||||||
|  |  | ||||||
| class BaseCoreplex(implicit p: Parameters) extends BareCoreplex | class BaseCoreplex(implicit p: Parameters) extends BareCoreplex | ||||||
|   | |||||||
| @@ -166,9 +166,12 @@ class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | |||||||
|   val flip = false // needed for blind nodes |   val flip = false // needed for blind nodes | ||||||
|   private def flipO(b: Vec[BO]) = if (flip) b.flip else b |   private def flipO(b: Vec[BO]) = if (flip) b.flip else b | ||||||
|   private def flipI(b: Vec[BI]) = if (flip) b      else b.flip |   private def flipI(b: Vec[BI]) = if (flip) b      else b.flip | ||||||
|  |   val wire = false // needed if you want to grab access to from inside a module | ||||||
|  |   private def wireO(b: Vec[BO]) = if (wire) Wire(b) else b | ||||||
|  |   private def wireI(b: Vec[BI]) = if (wire) Wire(b) else b | ||||||
|  |  | ||||||
|   lazy val bundleOut = flipO(outer.bundleO(edgesOut)) |   lazy val bundleOut = wireO(flipO(outer.bundleO(edgesOut))) | ||||||
|   lazy val bundleIn  = flipI(inner.bundleI(edgesIn)) |   lazy val bundleIn  = wireI(flipI(inner.bundleI(edgesIn))) | ||||||
|  |  | ||||||
|   // connects the outward part of a node with the inward part of this node |   // connects the outward part of a node with the inward part of this node | ||||||
|   override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit sourceInfo: SourceInfo): Option[LazyModule] = { |   override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit sourceInfo: SourceInfo): Option[LazyModule] = { | ||||||
| @@ -234,6 +237,20 @@ class BlindInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B]) | |||||||
|   override lazy val bundleIn = bundleOut |   override lazy val bundleIn = bundleOut | ||||||
| } | } | ||||||
|  |  | ||||||
|  | class InternalOutputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: PI) | ||||||
|  |   extends SimpleNode(imp)({case (0, _) => Seq()}, {case (n, Seq()) => Seq.fill(n)(pi)}, 0 to 0, 1 to 1) | ||||||
|  | { | ||||||
|  |   override val wire = true | ||||||
|  |   override lazy val bundleOut = bundleIn | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class InternalInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(po: PO) | ||||||
|  |   extends SimpleNode(imp)({case (n, Seq()) => Seq.fill(n)(po)}, {case (0, _) => Seq()}, 1 to 1, 0 to 0) | ||||||
|  | { | ||||||
|  |   override val wire = true | ||||||
|  |   override lazy val bundleIn = bundleOut | ||||||
|  | } | ||||||
|  |  | ||||||
| class InteriorNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B]) | class InteriorNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B]) | ||||||
|   (oFn: Seq[PO] => PO, iFn: Seq[PI] => PI, numPO: Range.Inclusive, numPI: Range.Inclusive) |   (oFn: Seq[PO] => PO, iFn: Seq[PI] => PI, numPO: Range.Inclusive, numPI: Range.Inclusive) | ||||||
|   extends SimpleNode(imp)({case (n,s) => Seq.fill(n)(oFn(s))}, {case (n,s) => Seq.fill(n)(iFn(s))}, numPO, numPI) |   extends SimpleNode(imp)({case (n,s) => Seq.fill(n)(oFn(s))}, {case (n,s) => Seq.fill(n)(iFn(s))}, numPO, numPI) | ||||||
|   | |||||||
| @@ -16,14 +16,12 @@ import coreplex._ | |||||||
| // the following parameters will be refactored properly with TL2 | // the following parameters will be refactored properly with TL2 | ||||||
| case object GlobalAddrMap extends Field[AddrMap] | case object GlobalAddrMap extends Field[AddrMap] | ||||||
| case object NCoreplexExtClients extends Field[Int] | case object NCoreplexExtClients extends Field[Int] | ||||||
| case object NExtInterrupts extends Field[Int] |  | ||||||
| /** Enable or disable monitoring of Diplomatic buses */ | /** Enable or disable monitoring of Diplomatic buses */ | ||||||
| case object TLEmitMonitors extends Field[Bool] | case object TLEmitMonitors extends Field[Bool] | ||||||
|  |  | ||||||
| /** Base Top with no Periphery */ | /** Base Top with no Periphery */ | ||||||
| abstract class BaseTop[+C <: BaseCoreplex](buildCoreplex: Parameters => C)(implicit q: Parameters) extends LazyModule { | abstract class BaseTop[+C <: BaseCoreplex](buildCoreplex: Parameters => C)(implicit q: Parameters) extends LazyModule { | ||||||
|   // the following variables will be refactored properly with TL2 |   // the following variables will be refactored properly with TL2 | ||||||
|   val pInterrupts = new RangeManager |  | ||||||
|   val pBusMasters = new RangeManager |   val pBusMasters = new RangeManager | ||||||
|  |  | ||||||
|   TLImp.emitMonitors = q(TLEmitMonitors) |   TLImp.emitMonitors = q(TLEmitMonitors) | ||||||
| @@ -31,11 +29,11 @@ abstract class BaseTop[+C <: BaseCoreplex](buildCoreplex: Parameters => C)(impli | |||||||
|   // Add a SoC and peripheral bus |   // Add a SoC and peripheral bus | ||||||
|   val socBus = LazyModule(new TLXbar) |   val socBus = LazyModule(new TLXbar) | ||||||
|   val peripheryBus = LazyModule(new TLXbar) |   val peripheryBus = LazyModule(new TLXbar) | ||||||
|  |   val intBus = LazyModule(new IntXbar) | ||||||
|  |  | ||||||
|   // Fill in the TL1 legacy parameters |   // Fill in the TL1 legacy parameters | ||||||
|   implicit val p = q.alterPartial { |   implicit val p = q.alterPartial { | ||||||
|     case NCoreplexExtClients => pBusMasters.sum |     case NCoreplexExtClients => pBusMasters.sum | ||||||
|     case NExtInterrupts => pInterrupts.sum |  | ||||||
|     case GlobalAddrMap => legacyAddrMap |     case GlobalAddrMap => legacyAddrMap | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -64,7 +62,6 @@ abstract class BaseTopModule[+B <: BaseTopBundle[BaseTop[BaseCoreplex]]](val io: | |||||||
|   val coreplexMem        : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.mem) |   val coreplexMem        : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.mem) | ||||||
|   val coreplexSlave      : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.slave) |   val coreplexSlave      : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.slave) | ||||||
|   val coreplexDebug      : DebugBusIO                    = Wire(outer.coreplex.module.io.debug) |   val coreplexDebug      : DebugBusIO                    = Wire(outer.coreplex.module.io.debug) | ||||||
|   val coreplexInterrupts : Vec[Bool]                     = Wire(outer.coreplex.module.io.interrupts) |  | ||||||
|  |  | ||||||
|   println("Generated Address Map") |   println("Generated Address Map") | ||||||
|   for (entry <- p(GlobalAddrMap).flatten) { |   for (entry <- p(GlobalAddrMap).flatten) { | ||||||
| @@ -79,17 +76,16 @@ abstract class BaseTopModule[+B <: BaseTopBundle[BaseTop[BaseCoreplex]]](val io: | |||||||
|     println(f"\t$name%s $start%x - $end%x, $protStr$cacheable") |     println(f"\t$name%s $start%x - $end%x, $protStr$cacheable") | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   println("\nGenerated Interrupt Vector") |  | ||||||
|   outer.pInterrupts.print |  | ||||||
|  |  | ||||||
|   io.success := outer.coreplex.module.io.success |   io.success := outer.coreplex.module.io.success | ||||||
| } | } | ||||||
|  |  | ||||||
| trait DirectConnection { | trait DirectConnection { | ||||||
|   val coreplex: BaseCoreplex |   val coreplex: BaseCoreplex | ||||||
|   val socBus: TLXbar |   val socBus: TLXbar | ||||||
|  |   val intBus: IntXbar | ||||||
|  |  | ||||||
|   socBus.node := coreplex.mmio |   socBus.node := coreplex.mmio | ||||||
|  |   coreplex.mmioInt := intBus.intnode | ||||||
| } | } | ||||||
|  |  | ||||||
| trait DirectConnectionModule { | trait DirectConnectionModule { | ||||||
| @@ -98,10 +94,8 @@ trait DirectConnectionModule { | |||||||
|   val coreplexMem        : Vec[ClientUncachedTileLinkIO] |   val coreplexMem        : Vec[ClientUncachedTileLinkIO] | ||||||
|   val coreplexSlave      : Vec[ClientUncachedTileLinkIO] |   val coreplexSlave      : Vec[ClientUncachedTileLinkIO] | ||||||
|   val coreplexDebug      : DebugBusIO |   val coreplexDebug      : DebugBusIO | ||||||
|   val coreplexInterrupts : Vec[Bool] |  | ||||||
|  |  | ||||||
|   coreplexMem <> outer.coreplex.module.io.mem |   coreplexMem <> outer.coreplex.module.io.mem | ||||||
|   coreplexInterrupts <> outer.coreplex.module.io.interrupts |  | ||||||
|   outer.coreplex.module.io.slave <> coreplexSlave |   outer.coreplex.module.io.slave <> coreplexSlave | ||||||
|   outer.coreplex.module.io.debug <> coreplexDebug |   outer.coreplex.module.io.debug <> coreplexDebug | ||||||
| } | } | ||||||
|   | |||||||
| @@ -129,28 +129,21 @@ trait PeripheryDebugModule { | |||||||
|  |  | ||||||
| trait PeripheryExtInterrupts extends LazyModule { | trait PeripheryExtInterrupts extends LazyModule { | ||||||
|   implicit val p: Parameters |   implicit val p: Parameters | ||||||
|   val pInterrupts: RangeManager |   val intBus: IntXbar | ||||||
|  |  | ||||||
|   pInterrupts.add("ext", p(NExtTopInterrupts)) |   val extInterrupts = IntBlindInputNode(p(NExtTopInterrupts)) | ||||||
|  |   val extInterruptXing = LazyModule(new IntXing) | ||||||
|  |  | ||||||
|  |   intBus.intnode := extInterruptXing.intnode | ||||||
|  |   extInterruptXing.intnode := extInterrupts | ||||||
| } | } | ||||||
|  |  | ||||||
| trait PeripheryExtInterruptsBundle { | trait PeripheryExtInterruptsBundle { | ||||||
|   implicit val p: Parameters |   val outer: PeripheryExtInterrupts | ||||||
|   val interrupts = Vec(p(NExtTopInterrupts), Bool()).asInput |   val interrupts = outer.extInterrupts.bundleIn | ||||||
| } | } | ||||||
|  |  | ||||||
| trait PeripheryExtInterruptsModule { | trait PeripheryExtInterruptsModule { | ||||||
|   implicit val p: Parameters |  | ||||||
|   val outer: PeripheryExtInterrupts |  | ||||||
|   val io: PeripheryExtInterruptsBundle |  | ||||||
|   val coreplexInterrupts: Vec[Bool] |  | ||||||
|  |  | ||||||
|   { |  | ||||||
|     val r = outer.pInterrupts.range("ext") |  | ||||||
|     ((r._1 until r._2) zipWithIndex) foreach { case (c, i) => |  | ||||||
|       coreplexInterrupts(c) := io.interrupts(i) |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| ///// | ///// | ||||||
| @@ -220,9 +213,7 @@ trait PeripheryMasterAXI4MMIO extends HasPeripheryParameters { | |||||||
| } | } | ||||||
|  |  | ||||||
| trait PeripheryMasterAXI4MMIOBundle extends HasPeripheryParameters { | trait PeripheryMasterAXI4MMIOBundle extends HasPeripheryParameters { | ||||||
|   implicit val p: Parameters |  | ||||||
|   val outer: PeripheryMasterAXI4MMIO |   val outer: PeripheryMasterAXI4MMIO | ||||||
|  |  | ||||||
|   val mmio_axi = outer.mmio_axi4.bundleOut |   val mmio_axi = outer.mmio_axi4.bundleOut | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ class TestHarness(q: Parameters) extends Module { | |||||||
|   require(dut.io.bus_clk.isEmpty) |   require(dut.io.bus_clk.isEmpty) | ||||||
|   require(dut.io.bus_rst.isEmpty) |   require(dut.io.bus_rst.isEmpty) | ||||||
|  |  | ||||||
|   for (int <- dut.io.interrupts) |   for (int <- dut.io.interrupts(0)) | ||||||
|     int := Bool(false) |     int := Bool(false) | ||||||
|  |  | ||||||
|   if (dut.io.mem_axi.nonEmpty) { |   if (dut.io.mem_axi.nonEmpty) { | ||||||
|   | |||||||
| @@ -88,21 +88,12 @@ object GenerateGlobalAddrMap { | |||||||
| } | } | ||||||
|  |  | ||||||
| object GenerateConfigString { | object GenerateConfigString { | ||||||
|   def apply(p: Parameters, peripheryManagers: Seq[TLManagerParameters]) = { |   def apply(p: Parameters, clint: CoreplexLocalInterrupter, plic: TLPLIC, peripheryManagers: Seq[TLManagerParameters]) = { | ||||||
|     val c = CoreplexParameters()(p) |     val c = CoreplexParameters()(p) | ||||||
|     val addrMap = p(GlobalAddrMap) |     val addrMap = p(GlobalAddrMap) | ||||||
|     val plicAddr = addrMap("TL2:plic").start |  | ||||||
|     val clint = CoreplexLocalInterrupterConfig() |  | ||||||
|     val xLen = p(XLen) |  | ||||||
|     val res = new StringBuilder |     val res = new StringBuilder | ||||||
|     res append  "plic {\n" |     res append plic.module.globalConfigString | ||||||
|     res append s"  priority 0x${plicAddr.toString(16)};\n" |     res append clint.module.globalConfigString | ||||||
|     res append s"  pending 0x${(plicAddr + PLICConsts.pendingBase).toString(16)};\n" |  | ||||||
|     res append s"  ndevs ${c.plicKey.nDevices};\n" |  | ||||||
|     res append  "};\n" |  | ||||||
|     res append  "rtc {\n" |  | ||||||
|     res append s"  addr 0x${clint.timeAddress.toString(16)};\n" |  | ||||||
|     res append  "};\n" |  | ||||||
|     if (addrMap contains "mem") { |     if (addrMap contains "mem") { | ||||||
|       res append  "ram {\n" |       res append  "ram {\n" | ||||||
|       res append  "  0 {\n" |       res append  "  0 {\n" | ||||||
| @@ -124,22 +115,8 @@ object GenerateConfigString { | |||||||
|       res append s"  $i {\n" |       res append s"  $i {\n" | ||||||
|       res append  "    0 {\n" |       res append  "    0 {\n" | ||||||
|       res append s"      isa $isa;\n" |       res append s"      isa $isa;\n" | ||||||
|       res append s"      timecmp 0x${clint.timecmpAddress(i).toString(16)};\n" |       res append clint.module.hartConfigStrings(i) | ||||||
|       res append s"      ipi 0x${clint.msipAddress(i).toString(16)};\n" |       res append plic.module.hartConfigStrings(i) | ||||||
|       res append s"      plic {\n" |  | ||||||
|       res append s"        m {\n" |  | ||||||
|       res append s"         ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'M')).toString(16)};\n" |  | ||||||
|       res append s"         thresh 0x${(plicAddr + c.plicKey.threshAddr(i, 'M')).toString(16)};\n" |  | ||||||
|       res append s"         claim 0x${(plicAddr + c.plicKey.claimAddr(i, 'M')).toString(16)};\n" |  | ||||||
|       res append s"        };\n" |  | ||||||
|       if (c.hasSupervisor) { |  | ||||||
|         res append s"        s {\n" |  | ||||||
|         res append s"         ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'S')).toString(16)};\n" |  | ||||||
|         res append s"         thresh 0x${(plicAddr + c.plicKey.threshAddr(i, 'S')).toString(16)};\n" |  | ||||||
|         res append s"         claim 0x${(plicAddr + c.plicKey.claimAddr(i, 'S')).toString(16)};\n" |  | ||||||
|         res append s"        };\n" |  | ||||||
|       } |  | ||||||
|       res append  "      };\n" |  | ||||||
|       res append  "    };\n" |       res append  "    };\n" | ||||||
|       res append  "  };\n" |       res append  "  };\n" | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -6,9 +6,11 @@ import Chisel._ | |||||||
| import Chisel.ImplicitConversions._ | import Chisel.ImplicitConversions._ | ||||||
|  |  | ||||||
| import junctions._ | import junctions._ | ||||||
|  | import diplomacy._ | ||||||
| import regmapper._ | import regmapper._ | ||||||
| import uncore.tilelink2._ | import uncore.tilelink2._ | ||||||
| import cde.Parameters | import cde.Parameters | ||||||
|  | import scala.math.min | ||||||
|  |  | ||||||
| class GatewayPLICIO extends Bundle { | class GatewayPLICIO extends Bundle { | ||||||
|   val valid = Bool(OUTPUT) |   val valid = Bool(OUTPUT) | ||||||
| @@ -49,48 +51,101 @@ object PLICConsts | |||||||
|   require(hartBase >= enableBase(maxHarts)) |   require(hartBase >= enableBase(maxHarts)) | ||||||
| } | } | ||||||
|  |  | ||||||
| case class PLICConfig(nHartsIn: Int, supervisor: Boolean, nDevices: Int, nPriorities: Int) { | /** Platform-Level Interrupt Controller */ | ||||||
|   import PLICConsts._ | class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC000000)(implicit val p: Parameters) extends LazyModule | ||||||
|  | { | ||||||
|  |   val contextsPerHart = if (supervisor) 2 else 1 | ||||||
|  |   require (maxPriorities >= 0) | ||||||
|  |  | ||||||
|  |   val node = TLRegisterNode( | ||||||
|  |     address   = AddressSet(address, PLICConsts.size-1), | ||||||
|  |     beatBytes = p(rocket.XLen)/8, | ||||||
|  |     undefZero = false) | ||||||
|  |  | ||||||
|  |   val intnode = IntAdapterNode( | ||||||
|  |     numSourcePorts = 0 to 1024, | ||||||
|  |     numSinkPorts   = 0 to 1024, | ||||||
|  |     sourceFn       = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart))) }, | ||||||
|  |     sinkFn         = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) | ||||||
|  |  | ||||||
|  |   lazy val module = new LazyModuleImp(this) { | ||||||
|  |     val io = new Bundle { | ||||||
|  |       val tl_in = node.bundleIn | ||||||
|  |       val devices = intnode.bundleIn | ||||||
|  |       val harts = intnode.bundleOut | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Assign all the devices unique ranges | ||||||
|  |     val sources = intnode.edgesIn.map(_.source) | ||||||
|  |     val flatSources = (sources zip sources.map(_.num).scanLeft(0)(_+_).init).map { | ||||||
|  |       case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) | ||||||
|  |     }.flatten | ||||||
|  |     // Compact the interrupt vector the same way | ||||||
|  |     val interrupts = (intnode.edgesIn zip io.devices).map { case (e, i) => i.take(e.source.num) }.flatten | ||||||
|  |     // This flattens the harts into an MSMSMSMSMS... or MMMMM.... sequence | ||||||
|  |     val harts = io.harts.flatten | ||||||
|  |  | ||||||
|  |     println("\nInterrupt map:") | ||||||
|  |     flatSources.foreach { s => | ||||||
|  |       println(s"  [${s.range.start}, ${s.range.end}) => ${s.name}") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     val nDevices = interrupts.size | ||||||
|  |     val nPriorities = min(maxPriorities, nDevices) | ||||||
|  |     val nHarts = harts.size | ||||||
|  |  | ||||||
|  |     require(nDevices <= PLICConsts.maxDevices) | ||||||
|  |     require(nHarts > 0 && nHarts <= PLICConsts.maxHarts) | ||||||
|  |  | ||||||
|   def contextsPerHart = if (supervisor) 2 else 1 |  | ||||||
|   def nHarts = contextsPerHart * nHartsIn |  | ||||||
|     def context(i: Int, mode: Char) = mode match { |     def context(i: Int, mode: Char) = mode match { | ||||||
|       case 'M' => i * contextsPerHart |       case 'M' => i * contextsPerHart | ||||||
|       case 'S' => require(supervisor); i * contextsPerHart + 1 |       case 'S' => require(supervisor); i * contextsPerHart + 1 | ||||||
|     } |     } | ||||||
|   def claimAddr(i: Int, mode: Char) = hartBase(context(i, mode)) + claimOffset |     def claimAddr(i: Int, mode: Char)  = address + PLICConsts.hartBase(context(i, mode)) + PLICConsts.claimOffset | ||||||
|   def threshAddr(i: Int, mode: Char) = hartBase(context(i, mode)) |     def threshAddr(i: Int, mode: Char) = address + PLICConsts.hartBase(context(i, mode)) | ||||||
|   def enableAddr(i: Int, mode: Char) = enableBase(context(i, mode)) |     def enableAddr(i: Int, mode: Char) = address + PLICConsts.enableBase(context(i, mode)) | ||||||
|  |  | ||||||
|   require(nDevices <= maxDevices) |     // Create the global PLIC config string | ||||||
|   require(nHarts > 0 && nHarts <= maxHarts) |     val globalConfigString = Seq( | ||||||
|   require(nPriorities >= 0 && nPriorities <= nDevices) |       s"plic {\n", | ||||||
| } |       s"  priority 0x${address.toString(16)};\n", | ||||||
|  |       s"  pending 0x${(address + PLICConsts.pendingBase).toString(16)};\n", | ||||||
|  |       s"  ndevs ${nDevices};\n", | ||||||
|  |       s"};\n").mkString | ||||||
|  |  | ||||||
| trait HasPLICParameters { |     // Create the per-Hart config string | ||||||
|   val params: (() => PLICConfig, Parameters) |     val hartConfigStrings = io.harts.zipWithIndex.map { case (_, i) => (Seq( | ||||||
|   val cfg = params._1 () |       s"      plic {\n", | ||||||
|   implicit val p = params._2 |       s"        m {\n", | ||||||
| } |       s"         ie 0x${enableAddr(i, 'M').toString(16)};\n", | ||||||
|  |       s"         thresh 0x${threshAddr(i, 'M').toString(16)};\n", | ||||||
|  |       s"         claim 0x${claimAddr(i, 'M').toString(16)};\n", | ||||||
|  |       s"        };\n") ++ (if (!supervisor) Seq() else Seq( | ||||||
|  |       s"        s {\n", | ||||||
|  |       s"         ie 0x${enableAddr(i, 'S').toString(16)};\n", | ||||||
|  |       s"         thresh 0x${threshAddr(i, 'S').toString(16)};\n", | ||||||
|  |       s"         claim 0x${claimAddr(i, 'S').toString(16)};\n", | ||||||
|  |       s"        };\n")) ++ Seq( | ||||||
|  |       s"      };\n")).mkString | ||||||
|  |     } | ||||||
|  |  | ||||||
| trait PLICBundle extends Bundle with HasPLICParameters { |     // For now, use LevelGateways for all TL2 interrupts | ||||||
|   val devices = Vec(cfg.nDevices, new GatewayPLICIO).flip |     val gateways = Vec(interrupts.map { case i => | ||||||
|   val harts = Vec(cfg.nHarts, Bool()).asOutput |       val gateway = Module(new LevelGateway) | ||||||
| } |       gateway.io.interrupt := i | ||||||
|  |       gateway.io.plic | ||||||
| trait PLICModule extends Module with HasRegMap with HasPLICParameters { |     }) | ||||||
|   val io: PLICBundle |  | ||||||
|  |  | ||||||
|     val priority = |     val priority = | ||||||
|     if (cfg.nPriorities > 0) Reg(Vec(cfg.nDevices+1, UInt(width=log2Up(cfg.nPriorities+1)))) |       if (nPriorities > 0) Reg(Vec(nDevices+1, UInt(width=log2Up(nPriorities+1)))) | ||||||
|     else Wire(init=Vec.fill(cfg.nDevices+1)(UInt(1))) |       else Wire(init=Vec.fill(nDevices+1)(UInt(1))) | ||||||
|     val threshold = |     val threshold = | ||||||
|     if (cfg.nPriorities > 0) Reg(Vec(cfg.nHarts, UInt(width = log2Up(cfg.nPriorities+1)))) |       if (nPriorities > 0) Reg(Vec(nHarts, UInt(width = log2Up(nPriorities+1)))) | ||||||
|     else Wire(init=Vec.fill(cfg.nHarts)(UInt(0))) |       else Wire(init=Vec.fill(nHarts)(UInt(0))) | ||||||
|   val pending = Reg(init=Vec.fill(cfg.nDevices+1){Bool(false)}) |     val pending = Reg(init=Vec.fill(nDevices+1){Bool(false)}) | ||||||
|   val enables = Reg(Vec(cfg.nHarts, Vec(cfg.nDevices+1, Bool()))) |     val enables = Reg(Vec(nHarts, Vec(nDevices+1, Bool()))) | ||||||
|  |  | ||||||
|   for ((p, g) <- pending.tail zip io.devices) { |     for ((p, g) <- pending.tail zip gateways) { | ||||||
|       g.ready := !p |       g.ready := !p | ||||||
|       g.complete := false |       g.complete := false | ||||||
|       when (g.valid) { p := true } |       when (g.valid) { p := true } | ||||||
| @@ -106,18 +161,18 @@ trait PLICModule extends Module with HasRegMap with HasPLICParameters { | |||||||
|       } else (x.head, UInt(0)) |       } else (x.head, UInt(0)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   val maxDevs = Reg(Vec(cfg.nHarts, UInt(width = log2Up(pending.size)))) |     val maxDevs = Reg(Vec(nHarts, UInt(width = log2Up(pending.size)))) | ||||||
|   for (hart <- 0 until cfg.nHarts) { |     for (hart <- 0 until nHarts) { | ||||||
|       val effectivePriority = |       val effectivePriority = | ||||||
|         for (((p, en), pri) <- (pending zip enables(hart) zip priority).tail) |         for (((p, en), pri) <- (pending zip enables(hart) zip priority).tail) | ||||||
|           yield Cat(p && en, pri) |           yield Cat(p && en, pri) | ||||||
|       val (maxPri, maxDev) = findMax((UInt(1) << priority(0).getWidth) +: effectivePriority) |       val (maxPri, maxDev) = findMax((UInt(1) << priority(0).getWidth) +: effectivePriority) | ||||||
|  |  | ||||||
|       maxDevs(hart) := maxDev |       maxDevs(hart) := maxDev | ||||||
|     io.harts(hart) := Reg(next = maxPri) > Cat(UInt(1), threshold(hart)) |       harts(hart) := Reg(next = maxPri) > Cat(UInt(1), threshold(hart)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   def priorityRegField(x: UInt) = if (cfg.nPriorities > 0) RegField(32, x) else RegField.r(32, x) |     def priorityRegField(x: UInt) = if (nPriorities > 0) RegField(32, x) else RegField.r(32, x) | ||||||
|     val priorityRegFields = Seq(PLICConsts.priorityBase -> priority.map(p => priorityRegField(p))) |     val priorityRegFields = Seq(PLICConsts.priorityBase -> priority.map(p => priorityRegField(p))) | ||||||
|     val pendingRegFields = Seq(PLICConsts.pendingBase  -> pending .map(b => RegField.r(1, b))) |     val pendingRegFields = Seq(PLICConsts.pendingBase  -> pending .map(b => RegField.r(1, b))) | ||||||
|  |  | ||||||
| @@ -125,7 +180,7 @@ trait PLICModule extends Module with HasRegMap with HasPLICParameters { | |||||||
|       PLICConsts.enableBase(i) -> e.map(b => RegField(1, b)) |       PLICConsts.enableBase(i) -> e.map(b => RegField(1, b)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   val hartRegFields = Seq.tabulate(cfg.nHarts) { i => |     val hartRegFields = Seq.tabulate(nHarts) { i => | ||||||
|       PLICConsts.hartBase(i) -> Seq( |       PLICConsts.hartBase(i) -> Seq( | ||||||
|         priorityRegField(threshold(i)), |         priorityRegField(threshold(i)), | ||||||
|         RegField(32, |         RegField(32, | ||||||
| @@ -138,7 +193,7 @@ trait PLICModule extends Module with HasRegMap with HasPLICParameters { | |||||||
|           }, |           }, | ||||||
|           RegWriteFn { (valid, data) => |           RegWriteFn { (valid, data) => | ||||||
|             when (valid && enables(i)(data)) { |             when (valid && enables(i)(data)) { | ||||||
|             io.devices(data - UInt(1)).complete := Bool(true) |               gateways(data - UInt(1)).complete := Bool(true) | ||||||
|             } |             } | ||||||
|             Bool(true) |             Bool(true) | ||||||
|           } |           } | ||||||
| @@ -146,16 +201,11 @@ trait PLICModule extends Module with HasRegMap with HasPLICParameters { | |||||||
|       ) |       ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   regmap((priorityRegFields ++ pendingRegFields ++ enableRegFields ++ hartRegFields):_*) |     node.regmap((priorityRegFields ++ pendingRegFields ++ enableRegFields ++ hartRegFields):_*) | ||||||
|  |  | ||||||
|     priority(0) := 0 |     priority(0) := 0 | ||||||
|     pending(0) := false |     pending(0) := false | ||||||
|     for (e <- enables) |     for (e <- enables) | ||||||
|       e(0) := false |       e(0) := false | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /** Platform-Level Interrupt Controller */ |  | ||||||
| class TLPLIC(c: () => PLICConfig, address: BigInt = 0xC000000)(implicit val p: Parameters) |  | ||||||
|   extends TLRegisterRouter(address, size = PLICConsts.size, beatBytes = p(rocket.XLen)/8, undefZero = false)( |  | ||||||
|   new TLRegBundle((c, p), _)    with PLICBundle)( |  | ||||||
|   new TLRegModule((c, p), _, _) with PLICModule) |  | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import Chisel._ | |||||||
| import junctions._ | import junctions._ | ||||||
| import junctions.NastiConstants._ | import junctions.NastiConstants._ | ||||||
| import regmapper._ | import regmapper._ | ||||||
|  | import diplomacy._ | ||||||
| import uncore.tilelink2._ | import uncore.tilelink2._ | ||||||
| import uncore.util._ | import uncore.util._ | ||||||
| import util._ | import util._ | ||||||
| @@ -20,22 +21,19 @@ class CoreplexLocalInterrupts extends Bundle { | |||||||
|   val msip = Bool() |   val msip = Bool() | ||||||
| } | } | ||||||
|  |  | ||||||
| case class CoreplexLocalInterrupterConfig(address: BigInt = 0x02000000) { | object ClintConsts | ||||||
|  | { | ||||||
|   def msipOffset(hart: Int) = hart * msipBytes |   def msipOffset(hart: Int) = hart * msipBytes | ||||||
|   def msipAddress(hart: Int) = address + msipOffset(hart) |  | ||||||
|   def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes |   def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes | ||||||
|   def timecmpAddress(hart: Int) = address + timecmpOffset(hart) |  | ||||||
|   def timeOffset = 0xbff8 |   def timeOffset = 0xbff8 | ||||||
|   def timeAddress = address + timeOffset |  | ||||||
|   def msipBytes = 4 |   def msipBytes = 4 | ||||||
|   def timecmpBytes = 8 |   def timecmpBytes = 8 | ||||||
|   def size = 0x10000 |   def size = 0x10000 | ||||||
| } | } | ||||||
|  |  | ||||||
| trait MixCoreplexLocalInterrupterParameters { | trait MixCoreplexLocalInterrupterParameters { | ||||||
|   val params: (CoreplexLocalInterrupterConfig, Parameters) |   val params: Parameters | ||||||
|   val c = params._1 |   implicit val p = params | ||||||
|   implicit val p = params._2 |  | ||||||
| } | } | ||||||
|  |  | ||||||
| trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters { | trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters { | ||||||
| @@ -45,6 +43,7 @@ trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterru | |||||||
|  |  | ||||||
| trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters { | trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters { | ||||||
|   val io: CoreplexLocalInterrupterBundle |   val io: CoreplexLocalInterrupterBundle | ||||||
|  |   val address: AddressSet | ||||||
|  |  | ||||||
|   val timeWidth = 64 |   val timeWidth = 64 | ||||||
|   val regWidth = 32 |   val regWidth = 32 | ||||||
| @@ -64,6 +63,15 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep | |||||||
|     tile.mtip := time.asUInt >= timecmp(i).asUInt |     tile.mtip := time.asUInt >= timecmp(i).asUInt | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   val globalConfigString = Seq( | ||||||
|  |     s"rtc {\n", | ||||||
|  |     s"  addr 0x${(address.base + ClintConsts.timeOffset).toString(16)};\n", | ||||||
|  |     s"};\n").mkString | ||||||
|  |   val hartConfigStrings = (0 until p(NTiles)).map { i => Seq( | ||||||
|  |     s"      timecmp 0x${(address.base + ClintConsts.timecmpOffset(i)).toString(16)};\n", | ||||||
|  |     s"      ipi 0x${(address.base + ClintConsts.msipOffset(i)).toString(16)};\n").mkString | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* 0000 msip hart 0 |   /* 0000 msip hart 0 | ||||||
|    * 0004 msip hart 1 |    * 0004 msip hart 1 | ||||||
|    * 4000 mtimecmp hart 0 lo |    * 4000 mtimecmp hart 0 lo | ||||||
| @@ -76,15 +84,15 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep | |||||||
|  |  | ||||||
|   regmap( |   regmap( | ||||||
|     0                            -> makeRegFields(ipi), |     0                            -> makeRegFields(ipi), | ||||||
|     c.timecmpOffset(0) -> makeRegFields(timecmp.flatten), |     ClintConsts.timecmpOffset(0) -> makeRegFields(timecmp.flatten), | ||||||
|     c.timeOffset       -> makeRegFields(time)) |     ClintConsts.timeOffset       -> makeRegFields(time)) | ||||||
|  |  | ||||||
|   def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r)) |   def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r)) | ||||||
| } | } | ||||||
|  |  | ||||||
| /** Power, Reset, Clock, Interrupt */ | /** Power, Reset, Clock, Interrupt */ | ||||||
| // Magic TL2 Incantation to create a TL2 Slave | // Magic TL2 Incantation to create a TL2 Slave | ||||||
| class CoreplexLocalInterrupter(c: CoreplexLocalInterrupterConfig)(implicit val p: Parameters) | class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit val p: Parameters) | ||||||
|   extends TLRegisterRouter(c.address, size = c.size, beatBytes = p(rocket.XLen)/8, undefZero = false)( |   extends TLRegisterRouter(address, size = ClintConsts.size, beatBytes = p(rocket.XLen)/8, undefZero = false)( | ||||||
|   new TLRegBundle((c, p), _)    with CoreplexLocalInterrupterBundle)( |   new TLRegBundle(p, _)    with CoreplexLocalInterrupterBundle)( | ||||||
|   new TLRegModule((c, p), _, _) with CoreplexLocalInterrupterModule) |   new TLRegModule(p, _, _) with CoreplexLocalInterrupterModule) | ||||||
|   | |||||||
| @@ -79,9 +79,6 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In | |||||||
| } | } | ||||||
|  |  | ||||||
| case class IntIdentityNode() extends IdentityNode(IntImp) | case class IntIdentityNode() extends IdentityNode(IntImp) | ||||||
| case class IntOutputNode() extends OutputNode(IntImp) |  | ||||||
| case class IntInputNode() extends InputNode(IntImp) |  | ||||||
|  |  | ||||||
| case class IntSourceNode(num: Int) extends SourceNode(IntImp)( | case class IntSourceNode(num: Int) extends SourceNode(IntImp)( | ||||||
|   IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1) |   IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1) | ||||||
| case class IntSinkNode() extends SinkNode(IntImp)( | case class IntSinkNode() extends SinkNode(IntImp)( | ||||||
| @@ -94,11 +91,20 @@ case class IntAdapterNode( | |||||||
|   numSinkPorts:   Range.Inclusive = 1 to 1) |   numSinkPorts:   Range.Inclusive = 1 to 1) | ||||||
|   extends InteriorNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts) |   extends InteriorNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts) | ||||||
|  |  | ||||||
|  | case class IntOutputNode() extends OutputNode(IntImp) | ||||||
|  | case class IntInputNode() extends InputNode(IntImp) | ||||||
|  |  | ||||||
|  | case class IntBlindOutputNode() extends BlindOutputNode(IntImp)(IntSinkPortParameters(Seq(IntSinkParameters()))) | ||||||
|  | case class IntBlindInputNode(num: Int) extends BlindInputNode(IntImp)(IntSourcePortParameters(Seq(IntSourceParameters(num)))) | ||||||
|  |  | ||||||
|  | case class IntInternalOutputNode() extends InternalOutputNode(IntImp)(IntSinkPortParameters(Seq(IntSinkParameters()))) | ||||||
|  | case class IntInternalInputNode(num: Int) extends InternalInputNode(IntImp)(IntSourcePortParameters(Seq(IntSourceParameters(num)))) | ||||||
|  |  | ||||||
| class IntXbar extends LazyModule | class IntXbar extends LazyModule | ||||||
| { | { | ||||||
|   val intnode = IntAdapterNode( |   val intnode = IntAdapterNode( | ||||||
|     numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink? |     numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink? | ||||||
|     numSinkPorts   = 1 to 128, |     numSinkPorts   = 0 to 128, | ||||||
|     sinkFn         = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, |     sinkFn         = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, | ||||||
|     sourceFn       = { seq => |     sourceFn       = { seq => | ||||||
|       IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map { |       IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map { | ||||||
| @@ -116,3 +122,17 @@ class IntXbar extends LazyModule | |||||||
|     io.out.foreach { _ := cat } |     io.out.foreach { _ := cat } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | class IntXing extends LazyModule | ||||||
|  | { | ||||||
|  |   val intnode = IntIdentityNode() | ||||||
|  |  | ||||||
|  |   lazy val module = new LazyModuleImp(this) { | ||||||
|  |     val io = new Bundle { | ||||||
|  |       val in = intnode.bundleIn | ||||||
|  |       val out = intnode.bundleOut | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     io.out := RegNext(RegNext(RegNext(io.in))) | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ object TLRegisterNode | |||||||
| // register mapped device from a totally abstract register mapped device. | // register mapped device from a totally abstract register mapped device. | ||||||
| // See GPIO.scala in this directory for an example | // See GPIO.scala in this directory for an example | ||||||
|  |  | ||||||
| abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean) extends LazyModule | abstract class TLRegisterRouterBase(val address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean) extends LazyModule | ||||||
| { | { | ||||||
|   val node = TLRegisterNode(address, concurrency, beatBytes, undefZero, executable) |   val node = TLRegisterNode(address, concurrency, beatBytes, undefZero, executable) | ||||||
|   val intnode = IntSourceNode(interrupts) |   val intnode = IntSourceNode(interrupts) | ||||||
| @@ -100,6 +100,7 @@ class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, r | |||||||
| { | { | ||||||
|   val io = bundleBuilder |   val io = bundleBuilder | ||||||
|   val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0) |   val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0) | ||||||
|  |   val address = router.address | ||||||
|   def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) |   def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user