/
TriggerWiringModule.scala
151 lines (129 loc) · 5.31 KB
/
TriggerWiringModule.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//See LICENSE for license details.
package firesim.midasexamples
import midas.widgets.{RationalClockBridge, PeekPokeBridge, RationalClock}
import midas.targetutils.{TriggerSource, TriggerSink}
import freechips.rocketchip.util.{DensePrefixSum, ResetCatchAndSync}
import freechips.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import scala.collection.mutable
class TriggerSinkModule extends MultiIOModule {
val reference = IO(Input(Bool()))
// DOC include start: TriggerSink Usage
// Note: this can be any reference you wish to have driven by the trigger.
val sinkBool = WireDefault(true.B)
import midas.targetutils.TriggerSink
// Drives true.B if no TriggerSource credits exist in the design.
// Note: noSourceDefault defaults to true.B if unset, and can be omitted for brevity
TriggerSink(sinkBool, noSourceDefault = true.B)
// DOC include end: TriggerSink Usage
assert(reference === sinkBool)
}
class TriggerSourceModule extends MultiIOModule {
val referenceCredit = IO(Output(Bool()))
val referenceDebit = IO(Output(Bool()))
private val lfsr = random.LFSR(16)
// DOC include start: TriggerSource Usage
// Some arbitarily logic to drive the credit source and sink. Replace with your own!
val start = lfsr(1)
val stop = ShiftRegister(lfsr(0), 5)
// Now annotate the signals.
import midas.targetutils.TriggerSource
TriggerSource.credit(start)
TriggerSource.debit(stop)
// Note one could alternatively write: TriggerSource(start, stop)
// DOC include end: TriggerSource Usage
referenceCredit := ~reset.asBool && start
referenceDebit := ~reset.asBool && stop
}
class LevelSensitiveTriggerSourceModule extends MultiIOModule {
val referenceCredit = IO(Output(Bool()))
val referenceDebit = IO(Output(Bool()))
private val enable = random.LFSR(16)(0)
// DOC include start: TriggerSource Level-Sensitive Usage
import midas.targetutils.TriggerSource
TriggerSource.levelSensitiveEnable(enable)
// DOC include end: TriggerSource Level-Sensitive Usage
val enLast = RegNext(enable)
referenceCredit := !enLast && enable
referenceDebit := enLast && !enable
}
class ReferenceSourceCounters(numCredits: Int, numDebits: Int) extends MultiIOModule {
def counterType = UInt(16.W)
val inputCredits = IO(Input(Vec(numCredits, Bool())))
val inputDebits = IO(Input(Vec(numCredits, Bool())))
val totalCredit = IO(Output(counterType))
val totalDebit = IO(Output(counterType))
def doAccounting(values: Seq[Bool]): UInt = {
val total = Reg(counterType)
val update = total + PopCount(values)
total := update
update
}
totalCredit := doAccounting(inputCredits)
totalDebit := doAccounting(inputDebits)
def synchAndDiff(count: UInt): UInt = {
val sync = RegNext(count)
val syncLast = RegNext(sync)
sync - syncLast
}
def syncAndDiffCredits(): UInt = synchAndDiff(totalCredit)
def syncAndDiffDebits(): UInt = synchAndDiff(totalDebit)
}
object ReferenceSourceCounters {
def apply(credits: Seq[Bool], debits: Seq[Bool]): ReferenceSourceCounters = {
val m = Module(new ReferenceSourceCounters(credits.size, debits.size))
m.inputCredits := VecInit(credits)
m.inputDebits := VecInit(debits)
m
}
}
// This test target implements in Chisel what the Trigger Transformation should
// implement in FIRRTL. The test fails if the firrtl-generated trigger-enables,
// as seen by all nodes with a trigger sink, fail to match their references.
class TriggerWiringModule(implicit p: Parameters) extends RawModule {
val clockBridge = RationalClockBridge(RationalClock("HalfRate", 1, 2))
val refClock :: div2Clock :: _ = clockBridge.io.clocks.toList
val refSourceCounts = new mutable.ArrayBuffer[ReferenceSourceCounters]()
val refSinks = new mutable.ArrayBuffer[Bool]()
val reset = WireInit(false.B)
val resetHalfRate = ResetCatchAndSync(div2Clock, reset.asBool)
withClockAndReset(refClock, reset) {
val peekPokeBridge = PeekPokeBridge(refClock, reset)
val src = Module(new TriggerSourceModule)
val sink = Module(new TriggerSinkModule)
val levelSensitiveSrc = Module(new LevelSensitiveTriggerSourceModule)
// Reference Hardware
refSourceCounts += ReferenceSourceCounters(
Seq(src.referenceCredit, levelSensitiveSrc.referenceCredit),
Seq(src.referenceDebit, levelSensitiveSrc.referenceDebit))
refSinks += {
val syncReg = Reg(Bool())
sink.reference := syncReg
syncReg
}
}
withClockAndReset(div2Clock, resetHalfRate) {
val src = Module(new TriggerSourceModule)
val sink = Module(new TriggerSinkModule)
// Reference Hardware
refSourceCounts += ReferenceSourceCounters(Seq(src.referenceCredit), Seq(src.referenceDebit))
refSinks += {
val syncReg = Reg(Bool())
sink.reference := syncReg
syncReg
}
}
class ReferenceImpl {
val refTotalCredit = Reg(UInt(32.W))
val refTotalDebit = Reg(UInt(32.W))
val refCreditNext = refTotalCredit + DensePrefixSum(refSourceCounts.map(_.syncAndDiffCredits))(_ + _).last
val refDebitNext = refTotalDebit + DensePrefixSum(refSourceCounts.map(_.syncAndDiffDebits))(_ + _).last
refTotalCredit := refCreditNext
refTotalDebit := refDebitNext
val refTriggerEnable = refCreditNext =/= refDebitNext
refSinks foreach { _ := refTriggerEnable }
}
// Reference Trigger Enable
withClock(refClock) { new ReferenceImpl }
}