summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/package.scala
blob: 16d10ff7d11e6b90e607404389f2084049f29a01 (plain)
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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
// See LICENSE for license details.

/** This package contains the main chisel3 API.
 */
package object chisel3 {    // scalastyle:ignore package.object.name
  import internal.firrtl.{Port, Width}
  import internal.sourceinfo.{SourceInfo, VecTransform}
  import internal.{Builder, chiselRuntimeDeprecated}

  import scala.language.implicitConversions

      /**
        * These implicit classes allow one to convert scala.Int|scala.BigInt to
        * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively.
        * The versions .asUInt(width)|.asSInt(width) are also available to explicitly
        * mark a width for the new literal.
        *
        * Also provides .asBool to scala.Boolean and .asUInt to String
        *
        * Note that, for stylistic reasons, one should avoid extracting immediately
        * after this call using apply, ie. 0.asUInt(1)(0) due to potential for
        * confusion (the 1 is a bit length and the 0 is a bit extraction position).
        * Prefer storing the result and then extracting from it.
        *
        * Implementation note: the empty parameter list (like `U()`) is necessary to prevent
        * interpreting calls that have a non-Width parameter as a chained apply, otherwise things like
        * `0.asUInt(16)` (instead of `16.W`) compile without error and produce undesired results.
        */
      implicit class fromBigIntToLiteral(bigint: BigInt) {
        /** Int to Bool conversion, allowing compact syntax like 1.B and 0.B
          */
        def B: Bool = bigint match { // scalastyle:ignore method.name
          case bigint if bigint == 0 => Bool.Lit(false)
          case bigint if bigint == 1 => Bool.Lit(true)
          case bigint => Builder.error(s"Cannot convert $bigint to Bool, must be 0 or 1"); Bool.Lit(false)
        }
        /** Int to UInt conversion, recommended style for constants.
          */
        def U: UInt = UInt.Lit(bigint, Width())  // scalastyle:ignore method.name
        /** Int to SInt conversion, recommended style for constants.
          */
        def S: SInt = SInt.Lit(bigint, Width())  // scalastyle:ignore method.name
        /** Int to UInt conversion with specified width, recommended style for constants.
          */
        def U(width: Width): UInt = UInt.Lit(bigint, width)  // scalastyle:ignore method.name
        /** Int to SInt conversion with specified width, recommended style for constants.
          */
        def S(width: Width): SInt = SInt.Lit(bigint, width)  // scalastyle:ignore method.name

        /** Int to UInt conversion, recommended style for variables.
          */
        def asUInt(): UInt = UInt.Lit(bigint, Width())
        /** Int to SInt conversion, recommended style for variables.
          */
        def asSInt(): SInt = SInt.Lit(bigint, Width())
        /** Int to UInt conversion with specified width, recommended style for variables.
          */
        def asUInt(width: Width): UInt = UInt.Lit(bigint, width)
        /** Int to SInt conversion with specified width, recommended style for variables.
          */
        def asSInt(width: Width): SInt = SInt.Lit(bigint, width)
      }

      implicit class fromIntToLiteral(int: Int) extends fromBigIntToLiteral(int)
      implicit class fromLongToLiteral(long: Long) extends fromBigIntToLiteral(long)

      implicit class fromStringToLiteral(str: String) {
        /** String to UInt parse, recommended style for constants.
          */
        def U: UInt = str.asUInt() // scalastyle:ignore method.name
        /** String to UInt parse with specified width, recommended style for constants.
          */
        def U(width: Width): UInt = str.asUInt(width) // scalastyle:ignore method.name

        /** String to UInt parse, recommended style for variables.
          */
        def asUInt(): UInt = {
          val bigInt = parse(str)
          UInt.Lit(bigInt, Width(bigInt.bitLength max 1))
        }
        /** String to UInt parse with specified width, recommended style for variables.
          */
        def asUInt(width: Width): UInt = UInt.Lit(parse(str), width)

        protected def parse(n: String) = {
          val (base, num) = n.splitAt(1)
          val radix = base match {
            case "x" | "h" => 16
            case "d" => 10
            case "o" => 8
            case "b" => 2
            case _ => Builder.error(s"Invalid base $base"); 2
          }
          BigInt(num.filterNot(_ == '_'), radix)
        }
      }

      implicit class fromBooleanToLiteral(boolean: Boolean) {
        /** Boolean to Bool conversion, recommended style for constants.
          */
        def B: Bool = Bool.Lit(boolean)  // scalastyle:ignore method.name

        /** Boolean to Bool conversion, recommended style for variables.
          */
        def asBool(): Bool = Bool.Lit(boolean)
      }

      // Fixed Point is experimental for now, but we alias the implicit conversion classes here
      //  to minimize disruption with existing code.
      implicit class fromDoubleToLiteral(double: Double) extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double)
      implicit class fromIntToBinaryPoint(int: Int) extends experimental.FixedPoint.Implicits.fromIntToBinaryPoint(int)

      implicit class fromIntToWidth(int: Int) {
        def W: Width = Width(int)  // scalastyle:ignore method.name
      }

  val WireInit = WireDefault

  implicit class AddDirectionToData[T<:Data](target: T) {
    @chiselRuntimeDeprecated
    @deprecated("Input(Data) should be used over Data.asInput", "chisel3")
    def asInput(implicit compileOptions: CompileOptions): T = Input(target)

    @chiselRuntimeDeprecated
    @deprecated("Output(Data) should be used over Data.asOutput", "chisel3")
    def asOutput(implicit compileOptions: CompileOptions): T = Output(target)

    @chiselRuntimeDeprecated
    @deprecated("Flipped(Data) should be used over Data.flip", "chisel3")
    def flip()(implicit compileOptions: CompileOptions): T = Flipped(target)
  }

  implicit class fromBitsable[T <: Data](data: T) {

    @chiselRuntimeDeprecated
    @deprecated("fromBits is deprecated, use asTypeOf instead", "chisel3")
    def fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
      that.asTypeOf(data)
    }
  }

  implicit class cloneTypeable[T <: Data](target: T) {
    @chiselRuntimeDeprecated
    @deprecated("chiselCloneType is deprecated, use chiselTypeOf(...) to get the Chisel Type of a hardware object", "chisel3") // scalastyle:ignore line.size.limit
    def chiselCloneType: T = {
      target.cloneTypeFull.asInstanceOf[T]
    }
  }

  object Vec extends VecFactory {
    import scala.language.experimental.macros

    @chiselRuntimeDeprecated
    @deprecated("Vec argument order should be size, t; this will be removed by the official release", "chisel3")
    def apply[T <: Data](gen: T, n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] =
      apply(n, gen)

    @chiselRuntimeDeprecated
    @deprecated("Vec.fill(n)(gen) is deprecated, use VecInit(Seq.fill(n)(gen)) instead", "chisel3")
    def fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] =
      apply(Seq.fill(n)(gen))

    def apply[T <: Data](elts: Seq[T]): chisel3.Vec[T] = macro VecTransform.apply_elts
    @chiselRuntimeDeprecated
    @deprecated("Vec(elts) is deprecated, use VecInit(elts) instead", "chisel3")
    def do_apply[T <: Data](elts: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] =
      chisel3.VecInit(elts)

    def apply[T <: Data](elt0: T, elts: T*): chisel3.Vec[T] = macro VecTransform.apply_elt0
    @chiselRuntimeDeprecated
    @deprecated("Vec(elt0, ...) is deprecated, use VecInit(elt0, ...) instead", "chisel3")
    def do_apply[T <: Data](elt0: T, elts: T*)
        (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] =
      VecInit(elt0 +: elts.toSeq)

    def tabulate[T <: Data](n: Int)(gen: (Int) => T): chisel3.Vec[T] = macro VecTransform.tabulate
    @chiselRuntimeDeprecated
    @deprecated("Vec.tabulate(n)(gen) is deprecated, use VecInit.tabulate(n)(gen) instead", "chisel3")
    def do_tabulate[T <: Data](n: Int)(gen: (Int) => T)
        (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] =
      chisel3.VecInit.tabulate(n)(gen)
  }

  // Some possible regex replacements for the literal specifier deprecation:
  // (note: these are not guaranteed to handle all edge cases! check all replacements!)
  // Bool\((true|false)\)
  //  => $1.B
  // UInt\(width\s*=\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
  //  => UInt($1.W)
  // (UInt|SInt|Bits).width\((\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
  //  => $1($2.W)
  // (U|S)Int\((-?\d+|0[xX][0-9a-fA-F]+)\)
  //  => $2.$1
  // UInt\((\d+|0[xX][0-9a-fA-F]+),\s*(?:width\s*=)?\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
  //  => $1.U($2.W)
  // (UInt|SInt|Bool)\(([_a-zA-Z][_0-9a-zA-Z]*)\)
  //  => $2.as$1
  // (UInt|SInt)\(([_a-zA-Z][_0-9a-zA-Z]*),\s*(?:width\s*=)?\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\)
  //  => $2.as$1($3.W)

  /** This contains literal constructor factory methods that are deprecated as of Chisel3.
    * These will be removed very soon. It's recommended you port your code ASAP.
    */
  trait UIntFactory extends UIntFactoryBase {
    /** Create a UInt literal with inferred width. */
    @chiselRuntimeDeprecated
    @deprecated("use n.U", "chisel3, will be removed by end of 2017")
    def apply(n: String): UInt = n.asUInt

    /** Create a UInt literal with fixed width. */
    @chiselRuntimeDeprecated
    @deprecated("use n.U(width.W)", "chisel3, will be removed by end of 2017")
    def apply(n: String, width: Int): UInt = n.asUInt(width.W)

    /** Create a UInt literal with specified width. */
    @chiselRuntimeDeprecated
    @deprecated("use value.U(width)", "chisel3, will be removed by end of 2017")
    def apply(value: BigInt, width: Width): UInt = value.asUInt(width)

    /** Create a UInt literal with fixed width. */
    @chiselRuntimeDeprecated
    @deprecated("use value.U(width.W)", "chisel3, will be removed by end of 2017")
    def apply(value: BigInt, width: Int): UInt = value.asUInt(width.W)

    /** Create a UInt literal with inferred width.- compatibility with Chisel2. */
    @chiselRuntimeDeprecated
    @deprecated("use value.U", "chisel3, will be removed by end of 2017")
    def apply(value: BigInt): UInt = value.asUInt

    /** Create a UInt with a specified width */
    @chiselRuntimeDeprecated
    @deprecated("use UInt(width.W)", "chisel3, will be removed by end of 2017")
    def width(width: Int): UInt = apply(width.W)

    /** Create a UInt port with specified width. */
    @chiselRuntimeDeprecated
    @deprecated("use UInt(width)", "chisel3, will be removed by end of 2017")
    def width(width: Width): UInt = apply(width)
  }

  /** This contains literal constructor factory methods that are deprecated as of Chisel3.
    * These will be removed very soon. It's recommended you move your code soon.
    */
  trait SIntFactory extends SIntFactoryBase {
    /** Create a SInt type or port with fixed width. */
    @chiselRuntimeDeprecated
    @deprecated("use SInt(width.W)", "chisel3, will be removed by end of 2017")
    def width(width: Int): SInt = apply(width.W)

    /** Create an SInt type with specified width. */
    @chiselRuntimeDeprecated
    @deprecated("use SInt(width)", "chisel3, will be removed by end of 2017")
    def width(width: Width): SInt = apply(width)

    /** Create an SInt literal with inferred width. */
    @chiselRuntimeDeprecated
    @deprecated("use value.S", "chisel3, will be removed by end of 2017")
    def apply(value: BigInt): SInt = value.asSInt

    /** Create an SInt literal with fixed width. */
    @chiselRuntimeDeprecated
    @deprecated("use value.S(width.W)", "chisel3, will be removed by end of 2017")
    def apply(value: BigInt, width: Int): SInt = value.asSInt(width.W)

    /** Create an SInt literal with specified width. */
    @chiselRuntimeDeprecated
    @deprecated("use value.S(width)", "chisel3, will be removed by end of 2017")
    def apply(value: BigInt, width: Width): SInt = value.asSInt(width)

    @chiselRuntimeDeprecated
    @deprecated("use value.S", "chisel3, will be removed by end of 2017")
    def Lit(value: BigInt): SInt = value.asSInt // scalastyle:ignore method.name

    @chiselRuntimeDeprecated
    @deprecated("use value.S(width)", "chisel3, will be removed by end of 2017")
    def Lit(value: BigInt, width: Int): SInt = value.asSInt(width.W) // scalastyle:ignore method.name
  }

  /** This contains literal constructor factory methods that are deprecated as of Chisel3.
    * These will be removed very soon. It's recommended you move your code soon.
    */
  trait BoolFactory extends BoolFactoryBase {
    /** Creates Bool literal.
     */
    @chiselRuntimeDeprecated
    @deprecated("use x.B", "chisel3, will be removed by end of 2017")
    def apply(x: Boolean): Bool = x.B
  }

  object Bits extends UIntFactory
  object UInt extends UIntFactory
  object SInt extends SIntFactory
  object Bool extends BoolFactory

  type InstanceId = internal.InstanceId

  @deprecated("Use 'SyncReadMem'", "chisel3")
  val SeqMem = chisel3.SyncReadMem
  @deprecated("Use 'SyncReadMem'", "chisel3")
  type SeqMem[T <: Data] = SyncReadMem[T]

  type Module = chisel3.experimental.LegacyModule

  /** Implicit for custom Printable string interpolator */
  implicit class PrintableHelper(val sc: StringContext) extends AnyVal {
    /** Custom string interpolator for generating Printables: p"..."
      * Will call .toString on any non-Printable arguments (mimicking s"...")
      */
    def p(args: Any*): Printable = {
      sc.checkLengths(args) // Enforce sc.parts.size == pargs.size + 1
      val pargs: Seq[Option[Printable]] = args map {
        case p: Printable => Some(p)
        case d: Data => Some(d.toPrintable)
        case any => for {
          v <- Option(any) // Handle null inputs
          str = v.toString
          if !str.isEmpty // Handle empty Strings
        } yield PString(str)
      }
      val parts = sc.parts map StringContext.treatEscapes
      // Zip sc.parts and pargs together ito flat Seq
      // eg. Seq(sc.parts(0), pargs(0), sc.parts(1), pargs(1), ...)
      val seq = for { // append None because sc.parts.size == pargs.size + 1
        (literal, arg) <- parts zip (pargs :+ None)
        optPable <- Seq(Some(PString(literal)), arg)
        pable <- optPable // Remove Option[_]
      } yield pable
      Printables(seq)
    }
  }

  implicit def string2Printable(str: String): Printable = PString(str)

  type ChiselException = internal.ChiselException

  // Debugger/Tester access to internal Chisel data structures and methods.
  def getDataElements(a: Aggregate): Seq[Element] = {
    a.allElements
  }
  def getModulePorts(m: Module): Seq[Port] = m.getPorts
  // Invalidate API - a DontCare element for explicit assignment to outputs,
  //  indicating the signal is intentionally not driven.
  val DontCare = chisel3.internal.InternalDontCare

  class BindingException(message: String) extends ChiselException(message)
  /** A function expected a Chisel type but got a hardware object
    */
  case class ExpectedChiselTypeException(message: String) extends BindingException(message)
  /**A function expected a hardware object but got a Chisel type
    */
  case class ExpectedHardwareException(message: String) extends BindingException(message)
  /** An aggregate had a mix of specified and unspecified directionality children
    */
  case class MixedDirectionAggregateException(message: String) extends BindingException(message)
  /** Attempted to re-bind an already bound (directionality or hardware) object
    */
  case class RebindingException(message: String) extends BindingException(message)
  // Connection exceptions.
  case class BiConnectException(message: String) extends ChiselException(message)
  case class MonoConnectException(message: String) extends ChiselException(message)
}