Skip to content

Commit f1cc75f

Browse files
committed
Merge branch '3.1.x' into 3.1.0
2 parents 10751f5 + 01d10fa commit f1cc75f

File tree

8 files changed

+361
-21
lines changed

8 files changed

+361
-21
lines changed

build.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ def javacOptionsVersion(scalaVersion: String): Seq[String] = {
3030
}
3131
}
3232

33-
val defaultVersions = Map("firrtl" -> "1.1.0-RC1")
33+
val defaultVersions = Map("firrtl" -> "1.1.0-RC2")
3434

3535
lazy val commonSettings = Seq (
3636
organization := "edu.berkeley.cs",
37-
version := "3.1.0-RC1",
37+
version := "3.1.0-RC2",
3838
git.remoteRepo := "git@github.com:freechipsproject/chisel3.git",
3939
autoAPIMappings := true,
4040
scalaVersion := "2.11.12",

chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,10 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
589589
case (outerClass, _) => Some(outerClass)
590590
}
591591

592+
// For compatibility with pre-3.1, where null is tried as an argument to the constructor.
593+
// This stores potential error messages which may be used later.
594+
var outerClassError: Option[String] = None
595+
592596
// Check if this is an inner class, and if so, try to get the outer instance
593597
val outerClassInstance = enclosingClassOption.map { outerClass =>
594598
def canAssignOuterClass(x: Object) = outerClass.isAssignableFrom(x.getClass)
@@ -612,10 +616,14 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
612616
case outer :: Nil =>
613617
_outerInst = Some(outer) // record the guess for future use
614618
outer
615-
case Nil => autoClonetypeError(s"Unable to determine instance of outer class $outerClass," +
616-
s" no candidates assignable to outer class types; examined $allOuterCandidates")
617-
case candidates => autoClonetypeError(s"Unable to determine instance of outer class $outerClass," +
618-
s" multiple possible candidates $candidates assignable to outer class type")
619+
case Nil => // TODO: replace with fatal autoClonetypeError once compatibility period is dropped
620+
outerClassError = Some(s"Unable to determine instance of outer class $outerClass," +
621+
s" no candidates assignable to outer class types; examined $allOuterCandidates")
622+
null
623+
case candidates => // TODO: replace with fatal autoClonetypeError once compatibility period is dropped
624+
outerClassError = Some(s"Unable to determine instance of outer class $outerClass," +
625+
s" multiple possible candidates $candidates assignable to outer class type")
626+
null
619627
}
620628
}
621629
}
@@ -635,7 +643,12 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
635643
case (Nil, None) => // no arguments, no outer class, invoke constructor directly
636644
Some(ctor.newInstance().asInstanceOf[this.type])
637645
case (argType :: Nil, Some((_, outerInstance))) =>
638-
if (argType isAssignableFrom outerInstance.getClass) {
646+
if (outerInstance == null) {
647+
Builder.deprecated(s"chisel3.1 autoclonetype failed, falling back to 3.0 behavior using null as the outer instance." +
648+
s" Autoclonetype failure reason: ${outerClassError.get}",
649+
Some(s"$clazz"))
650+
Some(ctor.newInstance(outerInstance).asInstanceOf[this.type])
651+
} else if (argType isAssignableFrom outerInstance.getClass) {
639652
Some(ctor.newInstance(outerInstance).asInstanceOf[this.type])
640653
} else {
641654
None
@@ -738,6 +751,7 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
738751

739752
// Invoke ctor
740753
val classMirror = outerClassInstance match {
754+
case Some((_, null)) => autoClonetypeError(outerClassError.get) // deals with the null hack for 3.0 compatibility
741755
case Some((_, outerInstance)) => mirror.reflect(outerInstance).reflectClass(classSymbol)
742756
case _ => mirror.reflectClass(classSymbol)
743757
}

chiselFrontend/src/main/scala/chisel3/core/Mem.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ sealed class SyncReadMem[T <: Data](t: T, n: Int) extends MemBase[T](t, n) {
156156

157157
def do_read(addr: UInt, enable: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
158158
val a = Wire(UInt())
159+
a := DontCare
159160
var port: Option[T] = None
160161
when (enable) {
161162
a := addr

chiselFrontend/src/main/scala/chisel3/internal/Builder.scala

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ private[chisel3] class DynamicContext() {
173173
var currentClockAndReset: Option[ClockAndReset] = None
174174
val errors = new ErrorLog
175175
val namingStack = new internal.naming.NamingStack
176-
// Record the Bundle instance, class name, and reverse stack trace position of open Bundles
177-
val bundleStack: ArrayBuffer[(Bundle, String, Int)] = ArrayBuffer()
176+
// Record the Bundle instance, class name, method name, and reverse stack trace position of open Bundles
177+
val bundleStack: ArrayBuffer[(Bundle, String, String, Int)] = ArrayBuffer()
178178
}
179179

180180
private[chisel3] object Builder {
@@ -247,24 +247,29 @@ private[chisel3] object Builder {
247247
// Returns the current stack of open Bundles
248248
// Note: elt will NOT have finished construction, its elements cannot be accessed
249249
def updateBundleStack(elt: Bundle): Seq[Bundle] = {
250-
val stackClasses = Thread.currentThread().getStackTrace()
251-
.map(_.getClassName)
250+
val stackElts = Thread.currentThread().getStackTrace()
252251
.reverse // so stack frame numbers are deterministic across calls
252+
.dropRight(2) // discard Thread.getStackTrace and updateBundleStack
253+
254+
// Determine where we are in the Bundle stack
255+
val eltClassName = elt.getClass.getName
256+
val eltStackPos = stackElts.map(_.getClassName).lastIndexOf(eltClassName)
253257

254258
// Prune the existing Bundle stack of closed Bundles
255-
val pruneLength = dynamicContext.bundleStack.reverse.prefixLength { case (_, cname, pos) =>
256-
pos >= stackClasses.size || stackClasses(pos) != cname
259+
// If we know where we are in the stack, discard frames above that
260+
val stackEltsTop = if (eltStackPos >= 0) eltStackPos else stackElts.size
261+
val pruneLength = dynamicContext.bundleStack.reverse.prefixLength { case (_, cname, mname, pos) =>
262+
pos >= stackEltsTop || stackElts(pos).getClassName != cname || stackElts(pos).getMethodName != mname
257263
}
258264
dynamicContext.bundleStack.trimEnd(pruneLength)
259265

260266
// Return the stack state before adding the most recent bundle
261267
val lastStack = dynamicContext.bundleStack.map(_._1).toSeq
262268

263269
// Append the current Bundle to the stack, if it's on the stack trace
264-
val eltClassName = elt.getClass.getName
265-
val eltStackPos = stackClasses.lastIndexOf(eltClassName)
266270
if (eltStackPos >= 0) {
267-
dynamicContext.bundleStack.append((elt, eltClassName, eltStackPos))
271+
val stackElt = stackElts(eltStackPos)
272+
dynamicContext.bundleStack.append((elt, eltClassName, stackElt.getMethodName, eltStackPos))
268273
}
269274
// Otherwise discard the stack frame, this shouldn't fail noisily
270275

doc/style.md

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
# Chisel Style Guide
2+
3+
The Chisel style guide reflects the [Google Java style
4+
guide](http://https://google.github.io/styleguide/javaguide.html) and the [General Public Scala style
5+
guide](http://docs.scala-lang.org/style/). Specific rules below are to clarify
6+
the style used for the chisel3 repo and repos related to Chisel (Firrtl).
7+
8+
**Goal:** Readability and consistency are the main purposes of the style guide.
9+
Writing your code so someone else (or yourself) can grok it later is important
10+
to code health and quality.
11+
12+
## Filenames
13+
The source file name consists of the case-sensitive name of the top-level class
14+
it contains, plus ".scala".
15+
16+
## Packages
17+
18+
Package definitions must contain the full path to the package from scala. If
19+
you create a subpackage, it should go in a subdirectory.
20+
21+
package directory.name.to.get.you.to.your.source
22+
23+
As in Scala, packages follow the [Java package naming convention](https://google.github.io/styleguide/javaguide.html#s5.2.1-package-names).
24+
Note that these guidelines call for all lowercase, no underscores.
25+
26+
```scala
27+
// Do this
28+
package hardware.chips.topsecret.masterplan
29+
30+
// Not this
31+
package hardware.chips.veryObvious.bad_style
32+
```
33+
34+
We also suggest you do not use chisel3 as a package, and especially do not use it
35+
as the final (innermost) package.
36+
37+
```scala
38+
// Don't do this
39+
package hardware.chips.newchip.superfastcomponent.chisel3
40+
41+
// This will lead to instantiating package members like so:
42+
val module = Module(new chisel3.FastModule)
43+
44+
// Which collides with the chisel namespace
45+
import chisel3._
46+
```
47+
48+
## Imports
49+
Avoid wildcard ( ._ ) imports, with the exception of chisel3._
50+
All other imports must call out used methods.
51+
import chisel3._ must be first and separated from remaining imports with extra
52+
blank line.
53+
54+
**Reason:** This makes it clear where methods are defined.
55+
56+
Remaining imports must be listed alphabetically.
57+
58+
```scala
59+
import chisel3._
60+
61+
import the.other.thing.that.i.reference.inline
62+
import the.other.things.that.i.reference.{ClassOne, ClassTwo}
63+
64+
65+
val myInline = inline.MakeAnInline()
66+
val myClassOne = new ClassOne
67+
```
68+
69+
## Tests
70+
Test classes are named starting with the name of the class they are testing, and
71+
ending with "Test".
72+
Test files must start with the name of the class you are testing and end with
73+
"Test.scala".
74+
Test files should reside in a subdirectory called "tests".
75+
The tests package should be composed of the package class you are testing.
76+
77+
```scala
78+
package class.under.test.class
79+
package tests
80+
```
81+
82+
## Comments
83+
We use scaladoc to automatically generate documentation from the source code.
84+
85+
```scala
86+
/** Multiple lines of ScalaDoc text are written here,
87+
* wrapped normally...
88+
*/
89+
public int method(String p1) { ... }
90+
```
91+
92+
... or in this single-line example:
93+
94+
```scala
95+
/** An especially short bit of Javadoc. */
96+
```
97+
98+
Write documentation as if the person reading it knows more about Scala and
99+
Chisel than you. If you find comments in the code consider breaking them up
100+
into seperate methods.
101+
102+
## Module Classes and Instances
103+
104+
Modules can take different forms in Chisel. First, in the verilog sense where
105+
you instance the module and then hook it up. In this case Module(new MyMod()) is
106+
returning a reference to the module.
107+
108+
```scala
109+
val myMod = Module(new MyMod())
110+
myMod.io <> hookUp
111+
```
112+
113+
Second, in a more programmatic inline style with factory methods. In this case
114+
Queue is actually returning the part of the IO bundle representing the queue's
115+
output. The factory method takes the input IO to the queue and an optional param
116+
for depth.
117+
118+
```scala
119+
val queueOut = Queue(queueIn, depth=10)
120+
```
121+
122+
The latter can be used for composing multiple functions into a single line.
123+
124+
```scala
125+
val queueOut = Queue(
126+
Arbitrate.byRoundRobin(
127+
Queue(a), // depth assumed to be 1
128+
Queue(b, depth=3),
129+
Queue(c, depth=4)
130+
),
131+
depth=10
132+
)
133+
```
134+
135+
## Naming Conventions
136+
137+
Chisel follows the [Scala Naming Conventions](http://docs.scala-lang.org/style/naming-conventions.html).
138+
In general, Chisel code should use CamelCase for naming (ie. the first letter
139+
of each word is capitalized except sometimes the first word).
140+
141+
### Why CamelCase instead of Snake\_Case?
142+
143+
The compiler inserts underscores when splitting Chisel/FIRRTL aggregate types
144+
into Verilog types. The compiler uses underscores to preserve the original
145+
structure of the data in the resulting Verilog. Because of the special meaning
146+
of underscores in Chisel-generated Verilog, their use in naming is **strongly**
147+
discouraged.
148+
149+
Consider the following Chisel code:
150+
151+
```scala
152+
val msg = Wire(new Bundle {
153+
val valid = Bool()
154+
val addr = UInt(32)
155+
val data = UInt(64)
156+
})
157+
val msg_rec = Wire(Bool())
158+
```
159+
160+
Which compiles to the Verilog:
161+
162+
```verilog
163+
wire msg_valid;
164+
wire [31:0] msg_addr;
165+
wire [63:0] msg_data;
166+
wire msg_rec;
167+
```
168+
169+
The Verilog maintains the structure of the original aggregate wire `msg`.
170+
However, because we named another variable `msg_rec`, it appears in the Verilog
171+
as if `msg` had 4 fields instead of its actual 3! If we instead follow the
172+
lowerCamelCase for values naming convention, the resulting Verilog makes more
173+
sense:
174+
175+
```scala
176+
val msg = Wire(new Bundle {
177+
val valid = Bool()
178+
val addr = UInt(32)
179+
val data = UInt(64)
180+
})
181+
val msgRec = Wire(Bool())
182+
```
183+
184+
And its resulting Verilog:
185+
186+
```verilog
187+
wire msg_valid;
188+
wire [31:0] msg_addr;
189+
wire [63:0] msg_data;
190+
wire msgRec;
191+
```
192+
193+
Much better.
194+
195+
### Modules and Bundles (Classes, Traits, and Objects)
196+
197+
Modules are Scala classes and thus use UpperCamelCase.
198+
199+
```scala
200+
class ModuleNamingExample extends Module {
201+
...
202+
}
203+
```
204+
205+
Similarly, other classes (Chisel & Scala) should be UpperCamelCase as well.
206+
207+
```scala
208+
trait UsefulScalaUtilities {
209+
def isEven(n: Int): Boolean = (n % 2) == 0
210+
def isOdd(n: Int): Boolean = !isEven(n)
211+
}
212+
213+
class MyCustomBundle extends Bundle {
214+
...
215+
}
216+
// Companion object to MyCustomBundle
217+
object MyCustomBundle {
218+
...
219+
}
220+
221+
```
222+
223+
### Values and Methods
224+
225+
Values and methods should use lowerCamelCase. (Unless the value is a constant.)
226+
227+
```scala
228+
val mySuperReg = Reg(init = 0.asUInt(32))
229+
def myImportantMethod(a: UInt): Bool = a < 23.asUInt
230+
```
231+
232+
### Constants
233+
234+
Unlike the Google Java style, constants use UpperCamelCase, which is in line
235+
with the official [Scala Naming
236+
Conventions](https://docs.scala-lang.org/style/naming-conventions.html).
237+
Constants are final fields (val or object) whose contents are deeply immutable
238+
and belong to a package object or an object. Examples:
239+
240+
```scala
241+
// Constants
242+
object Constants {
243+
val Number = 5
244+
val Names = "Ed" :: "Ann" :: Nil
245+
val Ages = Map("Ed" -> 35, "Ann" -> 32)
246+
}
247+
248+
// Not constants
249+
class NonConstantsInClass {
250+
val inClass: String = "in-class"
251+
}
252+
253+
object nonConstantsInObject {
254+
var varString = "var-string"
255+
val mutableCollection: scala.collection.mutable.Set[String]
256+
val mutableElements = Set(mutable)
257+
}
258+
```
259+
260+
### UpperCamelCase vs. lowerCamelCase
261+
262+
There is more than one reasonable way to covert English prose into camel case.
263+
We follow the convention defined in the [Google Java style
264+
guide](https://google.github.io/styleguide/javaguide.html#s5.3-camel-case). The
265+
potentially non-obvious rule being to treat acronymns as words for the purpose
266+
of camel case.
267+
268+
Note that the casing of the original words is almost entirely disregarded.
269+
Example:
270+
271+
Prose form | UpperCamelCase | lowerCamelCase | Incorrect
272+
:------------- | :------------- | :------------- | :------------
273+
find GCD | FindGcd | findGcd | ~~findGCD~~
274+
state for FSM | StateForFsm | stateForFsm | ~~stateForFSM~~
275+
mock dut | MockDut | mockDut | ~~MockDUT~~
276+
FIFO Generator | FifoGenerator | fifoGenerator | ~~FIFOGenerator~~

0 commit comments

Comments
 (0)