From e8e709c941176462748840a9dd76741beb763177 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Fri, 30 Jun 2017 08:36:00 -0700 Subject: [PATCH 1/3] plic: Use same recoding technique on complete as well as claim --- src/main/scala/uncore/devices/Plic.scala | 32 +++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index 25009e60..2f73bdaa 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -176,18 +176,33 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule PLICConsts.enableBase(i) -> e.map(b => RegField(1, b)) } + // When a hart reads its claim/complete register, then the + // device which is currently its highest priority is no longer pending. + // This code expolits the fact that only one hart can claim a device at + // a time through the TL interface. + // Note: PLIC doesn't care which hart reads the register. val claimer = Wire(Vec(nHarts, Bool())) val claiming = Vec.tabulate(nHarts){i => Mux(claimer(i), UIntToOH(maxDevs(i), nDevices+1), UInt(0))} val claimedDevs = Vec(claiming.reduceLeft( _ | _ ).toBools) ((pending zip gateways) zip claimedDevs) foreach { case ((p, g), c) => g.ready := !p - g.complete := false - when(c) { - p := false - }.elsewhen (g.valid) { - p := true - } + when (c || g.valid) { p := !c } + } + + // When a hart writes a claim/complete register, then + // the written device (as long as it is actually enabled for that + // hart) is marked complete. + // This code expolits the fact that only one hart can complete a device at + // a time through the TL interface + // (Note -- PLIC doesn't care which hart writes the register) + val completer = Wire(Vec(nHarts, Bool())) + val completingDevs = Wire(Vec(nHarts, UInt(width = log2Up(pending.size)))) + val completing = Vec.tabulate(nHarts){i => Mux(completer(i), UIntToOH(completingDevs(i), nDevices+1), UInt(0))} + val completedDevs = Vec(completing.reduceLeft( _ | _ ).toBools) + + (gateways zip completedDevs) foreach { case (g, c) => + g.complete := c } val hartRegFields = Seq.tabulate(nHarts) { i => @@ -200,9 +215,8 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule }, RegWriteFn { (valid, data) => val irq = data.extract(log2Ceil(nDevices+1)-1, 0) - when (valid && enables(i)(irq)) { - gateways(irq).complete := Bool(true) - } + completingDevs(i) := irq + completer(i) := valid && enables(i)(irq) Bool(true) } ) From 4e9f65b2ef0c8d1b90ab3a8088943ce06e01945f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 30 Jun 2017 10:07:39 -0700 Subject: [PATCH 2/3] Simplify logic further and bugfix complete was being set unconditionally --- src/main/scala/uncore/devices/Plic.scala | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index 2f73bdaa..1815fe47 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -197,12 +197,9 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule // a time through the TL interface // (Note -- PLIC doesn't care which hart writes the register) val completer = Wire(Vec(nHarts, Bool())) - val completingDevs = Wire(Vec(nHarts, UInt(width = log2Up(pending.size)))) - val completing = Vec.tabulate(nHarts){i => Mux(completer(i), UIntToOH(completingDevs(i), nDevices+1), UInt(0))} - val completedDevs = Vec(completing.reduceLeft( _ | _ ).toBools) - - (gateways zip completedDevs) foreach { case (g, c) => - g.complete := c + val irq = data.extract(log2Ceil(nDevices+1)-1, 0) + when (completer.reduce(_ || _)) { + gateways(irq).complete := Bool(false) } val hartRegFields = Seq.tabulate(nHarts) { i => @@ -214,8 +211,6 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule (Bool(true), maxDevs(i)) }, RegWriteFn { (valid, data) => - val irq = data.extract(log2Ceil(nDevices+1)-1, 0) - completingDevs(i) := irq completer(i) := valid && enables(i)(irq) Bool(true) } From 367d4aebe6df6192749a17860e0488efb37a9395 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 30 Jun 2017 10:15:53 -0700 Subject: [PATCH 3/3] Set complete unconditionally --- src/main/scala/uncore/devices/Plic.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index 1815fe47..b56123e3 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -198,8 +198,9 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule // (Note -- PLIC doesn't care which hart writes the register) val completer = Wire(Vec(nHarts, Bool())) val irq = data.extract(log2Ceil(nDevices+1)-1, 0) - when (completer.reduce(_ || _)) { - gateways(irq).complete := Bool(false) + val completedDevs = Mux(completer.reduce(_ || _), UIntToOH(irq, nDevices+1), UInt(0)) + (gateways zip completedDevs.toBools) foreach { case (g, c) => + g.complete := c } val hartRegFields = Seq.tabulate(nHarts) { i =>