Skip to content

Commit

Permalink
Chisel 3.6 update (#13)
Browse files Browse the repository at this point in the history
* basic files, much editing still needed
got a simple rendering script working

* More editing
block links at end of each file via include
redo connections based on connections doc

* updated readme

* Add output files to git for now, there's probably a better way to do this

* Get rid of html files, this is not the right way to build them

* Re-ogranized.
Source for cheat sheet is now a google doc which we need to provide community access for
latex remains but is in subdir latex
adoc was a candidate but looked too much like regular docs but
is kept aroundfor possible data mining the next time around

* ## Re-organized.
Source for cheat sheet is now a google slide
Todo: provide community access to this google slide
latex remains but is in subdir latex
adoc was an AsciiDoc candidate but looked too much like regular docs but
is kept around for possible data mining the next time around
  • Loading branch information
chick authored Apr 13, 2023
1 parent a3e24c4 commit 00dfbe2
Show file tree
Hide file tree
Showing 16 changed files with 556 additions and 21 deletions.
30 changes: 9 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
# chisel-cheatsheet
Cheatsheet for the Chisel hardware construction language: all the core functionality, on a single (double-sided) letter-sized sheet!
In this version the cheat sheet has been moved to a google docs slide for
easier editing. Unfortunately there's no way to store the google slides here
so if you are interested in playing around with the slides create an issue,
and we'll figure out a way to share.

## How to update the cheat sheet
## How to update the cheat sheet OLD-WAY

1. Make your edits to the file main.tex
2. Generate the pdf.
1. On linux I used `pdflatex main.tex` on linux
2. Make sure your version looks good
1. Be careful that you have not broken the layout
3. When you are happy with your change update the version in `main.tex` currently this is around line 45 and looks like
4. Run `pdflatex main.tex` again
5. `mv main.tex chisel_cheatsheet.pdf`
6. Create a PR with your changes
7. When the PR is merged
3. Release your new version
1. When you are happy with your changes, push changes
1. Create a PR with your changes
1. When the PR is merged
1. Release your new version
1. tag the new sheet version and push it, for example
1. `git tag 0.5.3 -a -m 'Added entry for RegInit with init'`
2. `git push origin --tags`
Expand All @@ -22,13 +19,4 @@ Cheatsheet for the Chisel hardware construction language: all the core functiona
2. On the next screen select `Draft a new release`
3. On the next screen select your tag from the `Choose a tag` button
4. Fill out the release stuff
5. Below the release description box click `Attach binaries`
6. In the box there, upload the `chisel_cheatsheet.pdf`
7. Click `Publish release`

## Alternative way to edit and regenerate
>This link may be stale
[View this project on Overleaf.](https://www.overleaf.com/read/xpgmbbgjqszd)
For edit access, ask one of the project maintainers.
We also accept pull requests on GitHub.
Binary file added chisel_cheatsheet-0.5.3-beta.pdf
Binary file not shown.
Binary file added chisel_cheatsheet-3.6.pdf
Binary file not shown.
Binary file modified chisel_cheatsheet.pdf
Binary file not shown.
7 changes: 7 additions & 0 deletions src/adoc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# ASCIIDOC attempt, not used but preserved for historical reasons

1. Make your edits to the files in `adoc/src`
1. Run the asciidoctor rendering program to convert `.adoc` files to `.html`
```bash
./src/scripts/build-doc.sh
```
101 changes: 101 additions & 0 deletions src/adoc/cheatsheet.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

= Chisel (3.5) Cheat Sheet

[%header,cols="1,1"]
|===
|*Notation In This Document:* | *Other sections*
| For Functions and Constructors: +
Arguments given as *kwd:type* (name and type(s)) Arguments in brackets *([...])* are optional. +
For Operators:
`c`, `x`, `y` are Chisel Data; `n`, `m` are Scala Ints
`w(x)`, `w(y)` are the widths of x, y +
(respectively) `minVal(x)`, `maxVal(x)` are the minimum or maximum possible values of x
|
- <<data-types.adoc#Data Types, Data types>> +
- <<connections.adoc#Connections, Connections>> +
- <<operators.adoc#Operators, Operators>> +
- <<hardware-generation.adoc#Hardware Generation, Hardware Generation>> +
- <<standard-library.adoc#Standard Library, Standard Library>> +
|===

== Basic Chisel Constructs

=== Chisel Wire Operators:
```
// Allocate a as wire of type UInt()
val x = Wire(UInt())
x := y //Connect wire y to wire x
```

=== Chisel *When*
`when` executes blocks conditionally depending on `Bool`, and is equivalent to Verilog `if`
```
when(condition1) {
// run this block if condition1 true and skip rest
} .elsewhen(condition2) {
// run this block if condition2 true and skip rest
} .otherwise {
// run this block if none of the above ran
}
```

=== Chisel *Switch*
`switch` executes blocks conditionally when x matchs is(value)
```
switch(x) {
is(value1) {
// run if x === value1
}
is(value2) {
// run if x === value2
}
}
```

=== Chisel *Enum*
Enum generates value literals for enumerations +
Declaring `Enums`
```
object Opcode extends ChiselEnum {
val load = Value(0x03.U)
val imm = Value(0x13.U)
val auipc = Value(0x17.U)
val store = Value(0x23.U)
val reg = Value(0x33.U)
val lui = Value(0x37.U)
val br = Value(0x63.U)
val jalr = Value(0x67.U)
val jal = Value(0x6f.U)
}
```
Using Enums
```
class LoadStoreExample extends Module {
val io = IO(new Bundle {
val opcode = Input(Opcode())
val load_or_store = Output(Bool())
})
io.load_or_store := io.opcode.isOneOf(Opcode.load, Opcode.store)
printf(p"${io.opcode}")
}
```

=== Math Helpers:
[%header,cols="1,1"]
|===
| Function | Description
| log2Ceil(in:Int): Int | log₂(in) rounded up
| log2Floor(in:Int): Int | log₂(in) rounded down
| isPow2(in:Int): Boolean | True if in is a power of 2
|===

// - <<data-types.adoc#Data Types, Data types>>
// - <<connections.adoc#Connections, Connections>>
// - <<operators.adoc#Operators, Operators>>
// - <<hardware-generation.adoc#Hardware Generation, Hardware Generation>>
// - <<standard-library.adoc#Standard Library, Standard Library>>

include::includes/navigation-links.adoc[]

// include::data-types.adoc[]

48 changes: 48 additions & 0 deletions src/adoc/connections.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
= Connections
:toc:


=== Connection operators
Connection operators can be confusing
Notion of producer and consumer
Of the form <LHS> <op> <RHS>
[%header,cols="2,2,5"]
|===
| Example | kind | Description
| `x := y` | basic connector | `y drives x`
|===
==== Turducken bulk connect operators
[cols="2,5"]
|===
| `c := p` | (mono-direction): connects all `p` members to `c`; requires `c` & `p` to not have any flipped members
| `c :#= p` | (coercing mono-direction): connects all `p` members to `c`; regardless of alignment
| `c :<= p` | (aligned-direction): connects all aligned (non-flipped) `c` members from `p`
| `c :>= p` | (flipped-direction): connects all flipped `p` members from `c`
| `c :<>= p` | (bi-direction operator): connects all aligned `c` members from `p`; all flipped `p` members from `c`
|===

These operators may appear to be a random collection of symbols; however, the characters are consistent between operators and self-describe the semantics of each operator:

* `:` always indicates the consumer, or left-hand-side, of the operator.
* `=` always indicates the producer, or right-hand-side, of the operator.
* Hence, `c := p` connects a consumer (`c`) and a producer (`p`).
* `<` always indicates that some members will be driven producer-to-consumer, or right-to-left.
* Hence, `c :<= p` drives members in producer (`p`) to members in consumer (`c`).
* `>` always indicates that some signals will be driven consumer-to-producer, or left-to-right.
* Hence, `c :>= p` drives members in consumer (`c`) to members producer (`p`).
* Hence, `c :<>= p` both drives members from `p` to `c` and from `c` to `p`.
* `#` always indicates to ignore member alignment and to drive producer-to-consumer.
* Hence, `c :#= p` always drives members from `p` to `c` ignoring direction.

==== Alignment: Flipped vs Aligned
A member's alignment is a relative property: a member is aligned/flipped relative to another member of the same component or Chisel type. Hence, one must always say whether a member is flipped/aligned with respect to (w.r.t) another member of that type (parent, sibling, child etc.).

In summary, a member is aligned or flipped w.r.t. another member of the hardware component. This means that the type of the consumer/producer is the only information needed to determine the behavior of any operator. Whether the consumer/producer is a member of a larger bundle is irrelevant; you ONLY need to know the type of the consumer/producer.

==== Input/Output
`Input(gen)`/`Output(gen)` are coercing operators. They perform two functions:
[start]
1. create a new Chisel type that has all flips removed from all recursive children members (still structurally equivalent to gen but no longer alignment type equivalent)
2. apply `Flipped` if `Input`, keep aligned (do nothing) if `Output`. E.g. if we imagine a function called `cloneChiselTypeButStripAllFlips`, then `Input(gen)` is structurally and alignment type equivalent to `Flipped(cloneChiselTypeButStripAllFlips(gen))`.

include::includes/navigation-links.adoc[]
138 changes: 138 additions & 0 deletions src/adoc/data-types.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
= Data Types
:toc:

`Bool`, `UInt`, `SInt`, `Bundle`, `Vec`, `ChiselEnum`

== Basic DataTypes

=== Constructors
[%header,cols="2,3,1"]
|===
| Constructor | Explanation |
| Bool() | Bool generator |
| true.B or false.B | Bool literals |
| UInt() | Unsigned integer |
| UInt(32.W) | Unsigned integer 32 bit |
| 77.U or "hdead".U | Unsigned integer literals |
| BigInt("12346789ABCDEF", 16).U | Make large UInt literal |
| 1.U(16.W) or "hdead".U | Literal 1 16 bits wide |
| SInt() | Signed integer |
| SInt(64.W) | Signed integer 64 bit |
| -3.S | Signed integer literals |
| 3.S(2.W) | Signed 2-bit value (-1) |
|===

=== Casts
Methods for converting between basic data types
[%header,cols="1,1,1"]
|===
| Constructor | Explanation |
| 1.U.asBool | cast UInt to Bool |
| 7.U.asBools | cast UInt to Seq of Bool |
| Unsigned integer | |
| Bool().asUInt | cast Bool as UInt |
| -88.S.asUInt | cast signed value as unsigned |
| 7.U(3.W).asSInt | cast UInt to SInt (zero-extend) |
| 3.S(2.W) | Signed 2-bit value (-1) |
|===
*Bits, UInt, SInt casts*: re-interpret cast except for
UInt -> SInt which Zero-extends to SInt

=== Aggregate Types
==== Bundles
*Bundle* contains ``Data`` types indexed by name +
*Defining*: subclass ``Bundle``, define components:
```
class MyBundle extends Bundle {
val a = Bool()
val b = UInt(32.W)
}
```
*Constructor*: instantiate `Bundle` subclass
```
val my_bundle = new MyBundle()
```
*Inline* defining: define a `Bundle` type
```
val my_bundle = new Bundle {
val a = Bool()
val b = UInt(32.W)
}
```

*Using*: access elements through dot notation:
```
val bundleVal = my_bundle.a
my_bundle.a := true.B
```

==== Vec
*Vec* is an indexable vector of `Data` types
```
val myVec = Vec(elts:Iterable[Data])
```
[%header, cols="3,2"]
|===
| Operator | Explanation
| `Vec(elts: Iterable[Data])` | `elts` initial `Data` (vector depth inferred)
| `VecInit(elts: Iterable[Data])` | `elts` initial `Data`
| `Vec.fill(n: Int) { gen: Data }` | `n` is vec depth `gen` initial `Data` called once per element
| `Vec.tabulate(n: Int) { gen(i: Int): Data }` | gen is passed the current index `n`
|===

*Using*: access elements by dynamic or static indexing:
[%header,cols="3,2"]
|===
| Dynamic Index | Static Index
| `readVal := myVec(ind: UInt)` | `readVal := myVec(1)`
| | `readVal := myVec(i)` where `i` is a Scala val
|===

[%header, cols="3,2"]
|===
| Function | Explanation
| `.forall(p:T=>Bool): Bool``| AND-reduce `p` on all elts
| `.exists(p:T=>Bool): Bool`| OR-reduce `p` on all elts
| `.contains(x:T): Bool` | `True` if this contains `x`
| `.count(p:T=>Bool): UInt` | count elts where `p` is `True`
|`.indexWhere(p:T=>Bool): UInt` | index where p is `true.B`
|`.lastIndexWhere(p:T=>Bool): UInt` | last index where p is `true.B`
|`.onlyIndexWhere(p:T=>Bool): UInt` | only index where p is `true.B`
|===


=== State Elements
Registers retain state until updated

[%header,cols="1,1"]
|===
| Constructor | Explanation
| val myReg = Reg(UInt()) | Create a reference `myReg` to a register of type UInt
| val myReg = RegInit(7.U(32.W)) | `myReg` is a Reg with initial value of 7
| val myReg = RegNext(nextValue) | Reg is updated at each rising clock, no initial value
| val myReg = RegNext(nextValue, init = 3.U(32.W)) | Reg is updated at each rising clock, with initial value
| val myReg = RegEnable(nextValue, enable)) | Reg is updated, use enable
|===
Updating: assign to latch new value on next clock: my_reg := next_val

=== Modules
*Defining*: subclass `Module` with elements, code:
```
class Accum(width:Int) extends Module
val io = IO(new Bundle {
val in = Input(UInt(width.W))
val out = Output(UInt(width.W))
})
val sum = Reg(UInt())
sum := sum + io.in
io.out := sum
}
```
*Usage*: access elements using dot notation: (code inside a `Module` is always running)
```
val my_module = Module(new Accum(32)) // Note required wrapping `Module` call
my_module.io.in := some_data val
sum := my_module.io.out
```

include::includes/navigation-links.adoc[]
25 changes: 25 additions & 0 deletions src/adoc/hardware-generation.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
= Hardware Generation
:toc:

== Functions
Functions provide block abstractions for code. Scala functions that instantiate or return Chisel types are code generators. +

Also: Scala’s `if` and `for` can be used to control hardware generation and are equivalent to Verilog's `if`/`for`
```
val number = Reg(if(canBeNegative) SInt() else UInt ())
```
will create a Register of type SInt or UInt depending on the value of a Scala variable

== Clock and reset
Domains using particular clock and reset references can be generated like this

```
withClockAndReset(mySpecialsClock, mySpecialReset) {
val specialReg = RegInit(32.W)
specialReg := specialReg +% 1
```

'''

include::includes/navigation-links.adoc[]

7 changes: 7 additions & 0 deletions src/adoc/includes/navigation-links.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'''
- <<data-types.adoc#Data Types, Data types>>
- <<connections.adoc#Connections, Connections>>
- <<operators.adoc#Operators, Operators>>
- <<hardware-generation.adoc#Hardware Generation, Hardware Generation>>
- <<standard-library.adoc#Standard Library, Standard Library>>
- <<cheatsheet.adoc#CheatSheet, CheatSheet>>
Loading

0 comments on commit 00dfbe2

Please sign in to comment.