diff --git a/src/main/scala/utility/HPMDocDump.scala b/src/main/scala/utility/HPMDocDump.scala new file mode 100644 index 0000000..4e503f3 --- /dev/null +++ b/src/main/scala/utility/HPMDocDump.scala @@ -0,0 +1,46 @@ +package utility + +import java.io.PrintWriter +import java.nio.file.{Files, Path, Paths} + +import scala.collection.mutable + +object HPMDocDump { + private case class EventSet(counterRange: String, events: Seq[PerfEventInfo]) + + private val setOrder = Seq( + "Frontend perfEvents Set", + "Backend perfEvents Set", + "MemBlock perfEvents Set", + "L2 Cache perfEvents Set", + ) + private val eventSets = mutable.Map.empty[String, EventSet] + + private def hpmCsvPath: Path = + Paths.get(sys.env.getOrElse("NOOP_HOME", ".")).resolve("build").resolve("hpm.csv") + + private def csvEscape(value: String): String = + "\"" + value.replace('\r', ' ').replace('\n', ' ').trim.replace("\"", "\"\"") + "\"" + + private def writeCSV(): Unit = { + val path = hpmCsvPath + Files.createDirectories(path.getParent) + val writer = new PrintWriter(path.toFile) + try { + writer.println(Seq("Event Set", "HPM Counters", "Event Number", "Event Name", "Description").map(csvEscape).mkString(",")) + setOrder.flatMap(name => eventSets.get(name).map(name -> _)).foreach { case (setName, eventSet) => + eventSet.events.zipWithIndex.foreach { case (event, index) => + val row = Seq(setName, eventSet.counterRange, index.toString, event.name, event.description) + writer.println(row.map(csvEscape).mkString(",")) + } + } + } finally { + writer.close() + } + } + + def register(setName: String, counterRange: String, events: Seq[PerfEventInfo]): Unit = { + eventSets(setName) = EventSet(counterRange, events) + writeCSV() + } +} diff --git a/src/main/scala/utility/HardwarePerfMonitor.scala b/src/main/scala/utility/HardwarePerfMonitor.scala index 10ef41d..765cf91 100644 --- a/src/main/scala/utility/HardwarePerfMonitor.scala +++ b/src/main/scala/utility/HardwarePerfMonitor.scala @@ -24,22 +24,25 @@ class PerfEvent extends Bundle { val value = UInt(6.W) } +case class PerfEventInfo(name: String, value: UInt, description: String) { + def withName(newName: String): PerfEventInfo = copy(name = newName) +} + trait HasPerfEvents { this: RawModule => - val perfEvents: Seq[(String, UInt)] + val perfEvents: Seq[PerfEventInfo] lazy val io_perf: Vec[PerfEvent] = IO(Output(Vec(perfEvents.length, new PerfEvent))) def generatePerfEvent(noRegNext: Option[Seq[Int]] = None): Unit = { - for (((out, (name, counter)), i) <- io_perf.zip(perfEvents).zipWithIndex) { - require(!name.contains("/")) - out.value := RegNext(RegNext(counter)) + for (((out, event), i) <- io_perf.zip(perfEvents).zipWithIndex) { + require(!event.name.contains("/")) + out.value := RegNext(RegNext(event.value)) if (noRegNext.isDefined && noRegNext.get.contains(i)) { - out.value := counter + out.value := event.value } } } - def getPerfEvents: Seq[(String, UInt)] = { - perfEvents.map(_._1).zip(io_perf).map(x => (x._1, x._2.value)) - } + def getPerfEventInfos: Seq[PerfEventInfo] = + perfEvents.zip(io_perf).map { case (event, port) => event.copy(value = port.value) } def getPerf: Vec[PerfEvent] = io_perf } @@ -73,7 +76,7 @@ class HPerfCounter(val numPCnt: Int)(implicit p: Parameters) extends Module with val event_step_1_reg = RegNext(event_step_1) val selected = combineEvents(event_step_0_reg, event_step_1_reg, event_op_2_reg) - val perfEvents = Seq(("selected", selected)) + val perfEvents = Seq(("selected", selected).withDescription("Combined increment selected by one mhpmevent register.")) generatePerfEvent() } @@ -83,12 +86,12 @@ class HPerfMonitor(numCSRPCnt: Int, numPCnt: Int)(implicit p: Parameters) extend val events_sets = Input(Vec(numPCnt, new PerfEvent)) }) - val perfEvents = io.hpm_event.zipWithIndex.map{ case (hpm, i) => + val perfEvents = io.hpm_event.zipWithIndex.map { case (hpm, i) => val hpc = Module(new HPerfCounter(numPCnt)) hpc.io.events_sets <> io.events_sets hpc.io.hpm_event := hpm - val selected = hpc.getPerfEvents.head - (s"${selected._1}_$i", selected._2) + val selected = hpc.getPerfEventInfos.head + selected.withName(s"${selected.name}_$i") } generatePerfEvent() } @@ -100,4 +103,4 @@ object HPerfMonitor { hpm.io.events_sets := events_sets hpm } -} \ No newline at end of file +} diff --git a/src/main/scala/utility/package.scala b/src/main/scala/utility/package.scala index c25c91f..d6d3bfb 100644 --- a/src/main/scala/utility/package.scala +++ b/src/main/scala/utility/package.scala @@ -1,4 +1,4 @@ -import chisel3.Data +import chisel3.{Data, UInt} package object utility { @deprecated @@ -15,4 +15,9 @@ package object utility { type SRAMWriteBus[T <: Data] = _root_.utility.sram.SRAMWriteBus[T] val PerfCCT = utility.TaggedTrace + + implicit class PerfEventDescription[T <: UInt](private val event: (String, T)) extends AnyVal { + def withDescription(description: String): PerfEventInfo = + PerfEventInfo(event._1, event._2, description) + } }