summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/CompileOptions.scala
blob: aca00d1ff77f74826a5948e732f171edd04afa1d (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
// SPDX-License-Identifier: Apache-2.0

package chisel3

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

trait CompileOptions {

  /** Should Record connections require a strict match of fields.
    *
    * If true and the same fields aren't present in both source and sink, a MissingFieldException,
    * MissingLeftFieldException, or MissingRightFieldException will be thrown.
    */
  val connectFieldsMustMatch: Boolean

  /** When creating an object that takes a type argument, the argument must be unbound (a pure type). */
  val declaredTypeMustBeUnbound: Boolean

  /** If a connection operator fails, don't try the connection with the operands (source and sink) reversed. */
  val dontTryConnectionsSwapped: Boolean

  /** If connection directionality is not explicit, do not use heuristics to attempt to determine it. */
  val dontAssumeDirectionality: Boolean

  /** Check that referenced Data have actually been declared. */
  val checkSynthesizable: Boolean

  /** Require explicit assignment of DontCare to generate "x is invalid" */
  val explicitInvalidate: Boolean

  /** Should the reset type of Module be a Bool or a Reset */
  val inferModuleReset: Boolean

  /** If marked true, then any Module which consumes `inferModuleReset=false` must also mix in [[RequireSyncReset]] */
  def migrateInferModuleReset: Boolean = false

  /** Should connects emit as firrtl <= instead of <- */
  def emitStrictConnects: Boolean = true
}

object CompileOptions {
  // Provides a low priority Strict default. Can be overridden by importing the NotStrict option.
  // Implemented as a macro to prevent this from being used inside chisel core.
  implicit def materialize: CompileOptions = macro materialize_impl

  def materialize_impl(c: Context): c.Tree = {
    import c.universe._
    q"_root_.chisel3.ExplicitCompileOptions.Strict"
  }
}

object ExplicitCompileOptions {

  case class CompileOptionsClass(
    // Should Record connections require a strict match of fields.
    // If true and the same fields aren't present in both source and sink, a MissingFieldException,
    // MissingLeftFieldException, or MissingRightFieldException will be thrown.
    val connectFieldsMustMatch: Boolean,
    // When creating an object that takes a type argument, the argument must be unbound (a pure type).
    val declaredTypeMustBeUnbound: Boolean,
    // If a connection operator fails, don't try the connection with the operands (source and sink) reversed.
    val dontTryConnectionsSwapped: Boolean,
    // If connection directionality is not explicit, do not use heuristics to attempt to determine it.
    val dontAssumeDirectionality: Boolean,
    // Check that referenced Data have actually been declared.
    val checkSynthesizable: Boolean,
    // Require an explicit DontCare assignment to generate a firrtl DefInvalid
    val explicitInvalidate: Boolean,
    // Should the reset type of Module be a Bool or a Reset
    val inferModuleReset: Boolean)
      extends CompileOptions

  // Collection of "not strict" connection compile options.
  // These provide compatibility with existing code.
  implicit val NotStrict = new CompileOptionsClass(
    connectFieldsMustMatch = false,
    declaredTypeMustBeUnbound = false,
    dontTryConnectionsSwapped = false,
    dontAssumeDirectionality = false,
    checkSynthesizable = false,
    explicitInvalidate = false,
    inferModuleReset = false
  ) {
    override def migrateInferModuleReset = false
    override def emitStrictConnects = false
    override def copy(
      connectFieldsMustMatch:    Boolean = false,
      declaredTypeMustBeUnbound: Boolean = false,
      dontTryConnectionsSwapped: Boolean = false,
      dontAssumeDirectionality:  Boolean = false,
      checkSynthesizable:        Boolean = false,
      explicitInvalidate:        Boolean = false,
      inferModuleReset:          Boolean = false
    ) = new CompileOptionsClass(
      connectFieldsMustMatch,
      declaredTypeMustBeUnbound,
      dontTryConnectionsSwapped,
      dontAssumeDirectionality,
      checkSynthesizable,
      explicitInvalidate,
      inferModuleReset
    ) {
      override def migrateInferModuleReset = false
      override def emitStrictConnects = false
    }
  }

  // Collection of "strict" connection compile options, preferred for new code.
  implicit val Strict = new CompileOptionsClass(
    connectFieldsMustMatch = true,
    declaredTypeMustBeUnbound = true,
    dontTryConnectionsSwapped = true,
    dontAssumeDirectionality = true,
    checkSynthesizable = true,
    explicitInvalidate = true,
    inferModuleReset = true
  ) {

    override def migrateInferModuleReset = false
    override def emitStrictConnects = true

    override def copy(
      connectFieldsMustMatch:    Boolean = true,
      declaredTypeMustBeUnbound: Boolean = true,
      dontTryConnectionsSwapped: Boolean = true,
      dontAssumeDirectionality:  Boolean = true,
      checkSynthesizable:        Boolean = true,
      explicitInvalidate:        Boolean = true,
      inferModuleReset:          Boolean = true
    ) = new CompileOptionsClass(
      connectFieldsMustMatch,
      declaredTypeMustBeUnbound,
      dontTryConnectionsSwapped,
      dontAssumeDirectionality,
      checkSynthesizable,
      explicitInvalidate,
      inferModuleReset
    ) {
      override def migrateInferModuleReset = false
      override def emitStrictConnects = true
    }
  }
}