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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
|
// See LICENSE for license details.
package firrtl
import firrtl.ir._
import firrtl.Utils.{min, max, pow_minus_one}
import com.typesafe.scalalogging.LazyLogging
/** Definitions and Utility functions for [[ir.PrimOp]]s */
object PrimOps extends LazyLogging {
/** Addition */
case object Add extends PrimOp { override def toString = "add" }
/** Subtraction */
case object Sub extends PrimOp { override def toString = "sub" }
/** Multiplication */
case object Mul extends PrimOp { override def toString = "mul" }
/** Division */
case object Div extends PrimOp { override def toString = "div" }
/** Remainder */
case object Rem extends PrimOp { override def toString = "rem" }
/** Less Than */
case object Lt extends PrimOp { override def toString = "lt" }
/** Less Than Or Equal To */
case object Leq extends PrimOp { override def toString = "leq" }
/** Greater Than */
case object Gt extends PrimOp { override def toString = "gt" }
/** Greater Than Or Equal To */
case object Geq extends PrimOp { override def toString = "geq" }
/** Equal To */
case object Eq extends PrimOp { override def toString = "eq" }
/** Not Equal To */
case object Neq extends PrimOp { override def toString = "neq" }
/** Padding */
case object Pad extends PrimOp { override def toString = "pad" }
/** Interpret As UInt */
case object AsUInt extends PrimOp { override def toString = "asUInt" }
/** Interpret As SInt */
case object AsSInt extends PrimOp { override def toString = "asSInt" }
/** Interpret As Clock */
case object AsClock extends PrimOp { override def toString = "asClock" }
/** Interpret As AsyncReset */
case object AsAsyncReset extends PrimOp { override def toString = "asAsyncReset" }
/** Static Shift Left */
case object Shl extends PrimOp { override def toString = "shl" }
/** Static Shift Right */
case object Shr extends PrimOp { override def toString = "shr" }
/** Dynamic Shift Left */
case object Dshl extends PrimOp { override def toString = "dshl" }
/** Dynamic Shift Right */
case object Dshr extends PrimOp { override def toString = "dshr" }
/** Arithmetic Convert to Signed */
case object Cvt extends PrimOp { override def toString = "cvt" }
/** Negate */
case object Neg extends PrimOp { override def toString = "neg" }
/** Bitwise Complement */
case object Not extends PrimOp { override def toString = "not" }
/** Bitwise And */
case object And extends PrimOp { override def toString = "and" }
/** Bitwise Or */
case object Or extends PrimOp { override def toString = "or" }
/** Bitwise Exclusive Or */
case object Xor extends PrimOp { override def toString = "xor" }
/** Bitwise And Reduce */
case object Andr extends PrimOp { override def toString = "andr" }
/** Bitwise Or Reduce */
case object Orr extends PrimOp { override def toString = "orr" }
/** Bitwise Exclusive Or Reduce */
case object Xorr extends PrimOp { override def toString = "xorr" }
/** Concatenate */
case object Cat extends PrimOp { override def toString = "cat" }
/** Bit Extraction */
case object Bits extends PrimOp { override def toString = "bits" }
/** Head */
case object Head extends PrimOp { override def toString = "head" }
/** Tail */
case object Tail extends PrimOp { override def toString = "tail" }
/** Interpret as Fixed Point **/
case object AsFixedPoint extends PrimOp { override def toString = "asFixedPoint" }
/** Shift Binary Point Left **/
case object BPShl extends PrimOp { override def toString = "bpshl" }
/** Shift Binary Point Right **/
case object BPShr extends PrimOp { override def toString = "bpshr" }
/** Set Binary Point **/
case object BPSet extends PrimOp { override def toString = "bpset" }
private lazy val builtinPrimOps: Seq[PrimOp] =
Seq(Add, Sub, Mul, Div, Rem, Lt, Leq, Gt, Geq, Eq, Neq, Pad, AsUInt, AsSInt, AsClock,
AsAsyncReset, Shl, Shr, Dshl, Dshr, Neg, Cvt, Not, And, Or, Xor, Andr, Orr, Xorr, Cat, Bits,
Head, Tail, AsFixedPoint, BPShl, BPShr, BPSet)
private lazy val strToPrimOp: Map[String, PrimOp] = builtinPrimOps.map { case op : PrimOp=> op.toString -> op }.toMap
/** Seq of String representations of [[ir.PrimOp]]s */
lazy val listing: Seq[String] = builtinPrimOps map (_.toString)
/** Gets the corresponding [[ir.PrimOp]] from its String representation */
def fromString(op: String): PrimOp = strToPrimOp(op)
// Width Constraint Functions
def PLUS (w1:Width, w2:Width) : Width = (w1, w2) match {
case (IntWidth(i), IntWidth(j)) => IntWidth(i + j)
case _ => PlusWidth(w1, w2)
}
def MAX (w1:Width, w2:Width) : Width = (w1, w2) match {
case (IntWidth(i), IntWidth(j)) => IntWidth(max(i,j))
case _ => MaxWidth(Seq(w1, w2))
}
def MINUS (w1:Width, w2:Width) : Width = (w1, w2) match {
case (IntWidth(i), IntWidth(j)) => IntWidth(i - j)
case _ => MinusWidth(w1, w2)
}
def POW (w1:Width) : Width = w1 match {
case IntWidth(i) => IntWidth(pow_minus_one(BigInt(2), i))
case _ => ExpWidth(w1)
}
def MIN (w1:Width, w2:Width) : Width = (w1, w2) match {
case (IntWidth(i), IntWidth(j)) => IntWidth(min(i,j))
case _ => MinWidth(Seq(w1, w2))
}
// Borrowed from Stanza implementation
def set_primop_type (e:DoPrim) : DoPrim = {
//println-all(["Inferencing primop type: " e])
def t1 = e.args.head.tpe
def t2 = e.args(1).tpe
def t3 = e.args(2).tpe
def w1 = getWidth(e.args.head.tpe)
def w2 = getWidth(e.args(1).tpe)
def p1 = t1 match { case FixedType(w, p) => p } //Intentional
def p2 = t2 match { case FixedType(w, p) => p } //Intentional
def c1 = IntWidth(e.consts.head)
def c2 = IntWidth(e.consts(1))
e copy (tpe = e.op match {
case Add => (t1, t2) match {
case (_: UIntType, _: UIntType) => UIntType(PLUS(MAX(w1, w2), IntWidth(1)))
case (_: SIntType, _: SIntType) => SIntType(PLUS(MAX(w1, w2), IntWidth(1)))
case (_: FixedType, _: FixedType) => FixedType(PLUS(PLUS(MAX(p1, p2), MAX(MINUS(w1, p1), MINUS(w2, p2))), IntWidth(1)), MAX(p1, p2))
case _ => UnknownType
}
case Sub => (t1, t2) match {
case (_: UIntType, _: UIntType) => UIntType(PLUS(MAX(w1, w2), IntWidth(1)))
case (_: SIntType, _: SIntType) => SIntType(PLUS(MAX(w1, w2), IntWidth(1)))
case (_: FixedType, _: FixedType) => FixedType(PLUS(PLUS(MAX(p1, p2),MAX(MINUS(w1, p1), MINUS(w2, p2))),IntWidth(1)), MAX(p1, p2))
case _ => UnknownType
}
case Mul => (t1, t2) match {
case (_: UIntType, _: UIntType) => UIntType(PLUS(w1, w2))
case (_: SIntType, _: SIntType) => SIntType(PLUS(w1, w2))
case (_: FixedType, _: FixedType) => FixedType(PLUS(w1, w2), PLUS(p1, p2))
case _ => UnknownType
}
case Div => (t1, t2) match {
case (_: UIntType, _: UIntType) => UIntType(w1)
case (_: SIntType, _: SIntType) => SIntType(PLUS(w1, IntWidth(1)))
case _ => UnknownType
}
case Rem => (t1, t2) match {
case (_: UIntType, _: UIntType) => UIntType(MIN(w1, w2))
case (_: SIntType, _: SIntType) => SIntType(MIN(w1, w2))
case _ => UnknownType
}
case Lt => (t1, t2) match {
case (_: UIntType, _: UIntType) => Utils.BoolType
case (_: SIntType, _: SIntType) => Utils.BoolType
case (_: FixedType, _: FixedType) => Utils.BoolType
case _ => UnknownType
}
case Leq => (t1, t2) match {
case (_: UIntType, _: UIntType) => Utils.BoolType
case (_: SIntType, _: SIntType) => Utils.BoolType
case (_: FixedType, _: FixedType) => Utils.BoolType
case _ => UnknownType
}
case Gt => (t1, t2) match {
case (_: UIntType, _: UIntType) => Utils.BoolType
case (_: SIntType, _: SIntType) => Utils.BoolType
case (_: FixedType, _: FixedType) => Utils.BoolType
case _ => UnknownType
}
case Geq => (t1, t2) match {
case (_: UIntType, _: UIntType) => Utils.BoolType
case (_: SIntType, _: SIntType) => Utils.BoolType
case (_: FixedType, _: FixedType) => Utils.BoolType
case _ => UnknownType
}
case Eq => (t1, t2) match {
case (_: UIntType, _: UIntType) => Utils.BoolType
case (_: SIntType, _: SIntType) => Utils.BoolType
case (_: FixedType, _: FixedType) => Utils.BoolType
case _ => UnknownType
}
case Neq => (t1, t2) match {
case (_: UIntType, _: UIntType) => Utils.BoolType
case (_: SIntType, _: SIntType) => Utils.BoolType
case (_: FixedType, _: FixedType) => Utils.BoolType
case _ => UnknownType
}
case Pad => t1 match {
case _: UIntType => UIntType(MAX(w1, c1))
case _: SIntType => SIntType(MAX(w1, c1))
case _: FixedType => FixedType(MAX(w1, c1), p1)
case _ => UnknownType
}
case AsUInt => t1 match {
case _: UIntType => UIntType(w1)
case _: SIntType => UIntType(w1)
case _: FixedType => UIntType(w1)
case ClockType => UIntType(IntWidth(1))
case AnalogType(w) => UIntType(w1)
case AsyncResetType => UIntType(IntWidth(1))
case _ => UnknownType
}
case AsSInt => t1 match {
case _: UIntType => SIntType(w1)
case _: SIntType => SIntType(w1)
case _: FixedType => SIntType(w1)
case ClockType => SIntType(IntWidth(1))
case _: AnalogType => SIntType(w1)
case AsyncResetType => SIntType(IntWidth(1))
case _ => UnknownType
}
case AsFixedPoint => t1 match {
case _: UIntType => FixedType(w1, c1)
case _: SIntType => FixedType(w1, c1)
case _: FixedType => FixedType(w1, c1)
case ClockType => FixedType(IntWidth(1), c1)
case _: AnalogType => FixedType(w1, c1)
case AsyncResetType => FixedType(IntWidth(1), c1)
case _ => UnknownType
}
case AsClock => t1 match {
case _: UIntType => ClockType
case _: SIntType => ClockType
case ClockType => ClockType
case _: AnalogType => ClockType
case AsyncResetType => ClockType
case _ => UnknownType
}
case AsAsyncReset => t1 match {
case _: UIntType => AsyncResetType
case _: SIntType => AsyncResetType
case ClockType => AsyncResetType
case _: AnalogType => AsyncResetType
case AsyncResetType => AsyncResetType
case _ => UnknownType
}
case Shl => t1 match {
case _: UIntType => UIntType(PLUS(w1, c1))
case _: SIntType => SIntType(PLUS(w1, c1))
case _: FixedType => FixedType(PLUS(w1,c1), p1)
case _ => UnknownType
}
case Shr => t1 match {
case _: UIntType => UIntType(MAX(MINUS(w1, c1), IntWidth(1)))
case _: SIntType => SIntType(MAX(MINUS(w1, c1), IntWidth(1)))
case _: FixedType => FixedType(MAX(MAX(MINUS(w1,c1), IntWidth(1)), p1), p1)
case _ => UnknownType
}
case Dshl => t1 match {
case _: UIntType => UIntType(PLUS(w1, POW(w2)))
case _: SIntType => SIntType(PLUS(w1, POW(w2)))
case _: FixedType => FixedType(PLUS(w1, POW(w2)), p1)
case _ => UnknownType
}
case Dshr => t1 match {
case _: UIntType => UIntType(w1)
case _: SIntType => SIntType(w1)
case _: FixedType => FixedType(w1, p1)
case _ => UnknownType
}
case Cvt => t1 match {
case _: UIntType => SIntType(PLUS(w1, IntWidth(1)))
case _: SIntType => SIntType(w1)
case _ => UnknownType
}
case Neg => t1 match {
case _: UIntType => SIntType(PLUS(w1, IntWidth(1)))
case _: SIntType => SIntType(PLUS(w1, IntWidth(1)))
case _ => UnknownType
}
case Not => t1 match {
case _: UIntType => UIntType(w1)
case _: SIntType => UIntType(w1)
case _ => UnknownType
}
case And => (t1, t2) match {
case (_: SIntType | _: UIntType, _: SIntType | _: UIntType) => UIntType(MAX(w1, w2))
case _ => UnknownType
}
case Or => (t1, t2) match {
case (_: SIntType | _: UIntType, _: SIntType | _: UIntType) => UIntType(MAX(w1, w2))
case _ => UnknownType
}
case Xor => (t1, t2) match {
case (_: SIntType | _: UIntType, _: SIntType | _: UIntType) => UIntType(MAX(w1, w2))
case _ => UnknownType
}
case Andr => t1 match {
case (_: UIntType | _: SIntType) => Utils.BoolType
case _ => UnknownType
}
case Orr => t1 match {
case (_: UIntType | _: SIntType) => Utils.BoolType
case _ => UnknownType
}
case Xorr => t1 match {
case (_: UIntType | _: SIntType) => Utils.BoolType
case _ => UnknownType
}
case Cat => (t1, t2) match {
case (_: UIntType | _: SIntType | _: FixedType, _: UIntType | _: SIntType | _: FixedType) => UIntType(PLUS(w1, w2))
case (t1, t2) => UnknownType
}
case Bits => t1 match {
case (_: UIntType | _: SIntType) => UIntType(PLUS(MINUS(c1, c2), IntWidth(1)))
case _: FixedType => UIntType(PLUS(MINUS(c1, c2), IntWidth(1)))
case _ => UnknownType
}
case Head => t1 match {
case (_: UIntType | _: SIntType | _: FixedType) => UIntType(c1)
case _ => UnknownType
}
case Tail => t1 match {
case (_: UIntType | _: SIntType | _: FixedType) => UIntType(MINUS(w1, c1))
case _ => UnknownType
}
case BPShl => t1 match {
case _: FixedType => FixedType(PLUS(w1,c1), PLUS(p1, c1))
case _ => UnknownType
}
case BPShr => t1 match {
case _: FixedType => FixedType(MINUS(w1,c1), MINUS(p1, c1))
case _ => UnknownType
}
case BPSet => t1 match {
case _: FixedType => FixedType(PLUS(c1, MINUS(w1, p1)), c1)
case _ => UnknownType
}
})
}
}
|