Skip to content

Commit f3a39af

Browse files
kevintownsendducky64
authored andcommitted
Adding a style guide (#790)
PiperOrigin-RevId: 187258707
1 parent a4aa392 commit f3a39af

File tree

1 file changed

+276
-0
lines changed

1 file changed

+276
-0
lines changed

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)