summaryrefslogtreecommitdiff
path: root/src/main/scala/chisel3/util/Math.scala
blob: 2a833e80be1a7d77b6cce2ab137fca67da75055e (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
// SPDX-License-Identifier: Apache-2.0

/** Scala-land math helper functions, like logs.
  */

package chisel3.util

import chisel3.internal

/** Compute the log2 of a Scala integer, rounded up, with min value of 1.
  * Useful for getting the number of bits needed to represent some number of states (in - 1),
  * To get the number of bits needed to represent some number n, use log2Up(n + 1).
  * with the minimum value preventing the creation of currently-unsupported zero-width wires.
  *
  * Note: prefer to use log2Ceil when in is known to be > 1 (where log2Ceil(in) > 0).
  * This will be deprecated when zero-width wires is supported.
  *
  * @example {{{
  * log2Up(1)  // returns 1
  * log2Up(2)  // returns 1
  * log2Up(3)  // returns 2
  * log2Up(4)  // returns 2
  * }}}
  */
object log2Up {
  // Do not deprecate until zero-width wires fully work:
  // https://github.com/freechipsproject/chisel3/issues/847
  //@chiselRuntimeDeprecated
  //@deprecated("Use log2Ceil instead", "chisel3")
  def apply(in: BigInt): Int = Chisel.log2Up(in)
}

/** Compute the log2 of a Scala integer, rounded up.
  * Useful for getting the number of bits needed to represent some number of states (in - 1).
  * To get the number of bits needed to represent some number n, use log2Ceil(n + 1).
  *
  * Note: can return zero, and should not be used in cases where it may generate unsupported
  * zero-width wires.
  *
  * @example {{{
  * log2Ceil(1)  // returns 0
  * log2Ceil(2)  // returns 1
  * log2Ceil(3)  // returns 2
  * log2Ceil(4)  // returns 2
  * }}}
  */
object log2Ceil {
  def apply(in: BigInt): Int = {
    require(in > 0)
    (in-1).bitLength
  }
  def apply(in: Int): Int = apply(BigInt(in))
}

/** Compute the log2 of a Scala integer, rounded down, with min value of 1.
  *
  * @example {{{
  * log2Down(1)  // returns 1
  * log2Down(2)  // returns 1
  * log2Down(3)  // returns 1
  * log2Down(4)  // returns 2
  * }}}
  */
object log2Down {
  // Do not deprecate until zero-width wires fully work:
  // https://github.com/freechipsproject/chisel3/issues/847
  //@chiselRuntimeDeprecated
  //@deprecated("Use log2Floor instead", "chisel3")
  def apply(in: BigInt): Int = Chisel.log2Down(in)
}

/** Compute the log2 of a Scala integer, rounded down.
  *
  * Can be useful in computing the next-smallest power of two.
  *
  * @example {{{
  * log2Floor(1)  // returns 0
  * log2Floor(2)  // returns 1
  * log2Floor(3)  // returns 1
  * log2Floor(4)  // returns 2
  * }}}
  */
object log2Floor {
  def apply(in: BigInt): Int = log2Ceil(in) - (if (isPow2(in)) 0 else 1)
  def apply(in: Int): Int = apply(BigInt(in))
}

/** Returns whether a Scala integer is a power of two.
  *
  * @example {{{
  * isPow2(1)  // returns true
  * isPow2(2)  // returns true
  * isPow2(3)  // returns false
  * isPow2(4)  // returns true
  * }}}
  */
object isPow2 {
  def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0)
  def apply(in: Int): Boolean = apply(BigInt(in))
}


object unsignedBitLength {
  /** Return the number of bits required to encode a specific value, assuming no sign bit is required.
    *
    * Basically, `n.bitLength`. NOTE: This will return 0 for a value of 0.
    * This reflects the Chisel assumption that a zero width wire has a value of 0.
    * @param in - the number to be encoded.
    * @return - an Int representing the number of bits to encode.
    */
  def apply(in: BigInt): Int = {
    require(in >= 0)
    in.bitLength
  }
}

object signedBitLength {
  /** Return the number of bits required to encode a specific value, assuming a sign bit is required.
    *
    * Basically, 0 for 0, 1 for -1, and `n.bitLength` + 1 for everything else.
    * This reflects the Chisel assumption that a zero width wire has a value of 0.
    * @param in - the number to be encoded.
    * @return - an Int representing the number of bits to encode.
    */
  def apply(in: BigInt): Int = {
    in.toInt match {
      case 0 => 0
      case -1 => 1
      case _ => in.bitLength + 1
    }

  }
}