|
1 | | -Chisel Project Template |
2 | | -======================= |
| 1 | +# MIT OpenCompute RISC-V Project |
3 | 2 |
|
4 | | -You've done the [Chisel Bootcamp](https://github.com/freechipsproject/chisel-bootcamp), and now you |
5 | | -are ready to start your own Chisel project. The following procedure should get you started |
6 | | -with a clean running [Chisel3](https://www.chisel-lang.org/) project. |
| 3 | +This is the MIT OpenCompute Laboratory’s RISC-V Project. |
| 4 | +We are designing a 32-bit CPU that implements the RV32I RISC-V ISA. |
7 | 5 |
|
8 | | -## Make your own Chisel3 project |
| 6 | +--- |
9 | 7 |
|
10 | | -### Dependencies |
| 8 | +## Project Structure |
11 | 9 |
|
12 | | -#### JDK 11 or newer |
| 10 | +CPU HDL files are stored in: ```main\scala\RISCV``` |
13 | 11 |
|
14 | | -We recommend using Java 11 or later LTS releases. While Chisel itself works with Java 8, our preferred build tool Mill requires Java 11. You can install the JDK as your operating system recommends, or use the prebuilt binaries from [Adoptium](https://adoptium.net/) (formerly AdoptOpenJDK). |
15 | 12 |
|
16 | | -#### SBT or mill |
| 13 | +### ALU.scala |
17 | 14 |
|
18 | | -SBT is the most common build tool in the Scala community. You can download it [here](https://www.scala-sbt.org/download.html). |
19 | | -Mill is another Scala/Java build tool preferred by Chisel's developers. |
20 | | -This repository includes a bootstrap script `./mill` so that no installation is necessary. |
21 | | -You can read more about Mill on its website: https://mill-build.org. |
| 15 | +Defines the Arithmetic Logic Unit (ALU) hardware. |
22 | 16 |
|
23 | | -#### Verilator |
| 17 | +The ALU takes two operands, `a` and `b`, and sends the result of the operation to `output`. |
| 18 | +It also accepts two control inputs: |
| 19 | +- A 4-bit operation code. |
| 20 | +- A sign-flag boolean, used only for comparisons. |
24 | 21 |
|
25 | | -The test with `svsim` needs Verilator installed. |
26 | | -See Verilator installation instructions [here](https://verilator.org/guide/latest/install.html). |
| 22 | +#### Operation Codes |
27 | 23 |
|
28 | | -### How to get started |
| 24 | +| Code | Operation | |
| 25 | +|-------|--------------------------| |
| 26 | +| 0000 | Addition | |
| 27 | +| 0001 | Multiplication | |
| 28 | +| 0010 | Comparison (gt, eq, lt) | |
| 29 | +| 0011 | Bitwise AND | |
| 30 | +| 0100 | Bitwise OR | |
| 31 | +| 0101 | Bitwise XOR | |
| 32 | +| 0110 | Bitwise NOT (outputs NOT a) | |
| 33 | +| 0111 | Logical shift left | |
| 34 | +| 1000 | Logical shift right | |
| 35 | +| 1001 | Arithmetic shift right | |
29 | 36 |
|
30 | | -#### Create a repository from the template |
| 37 | +The sign flag determines whether operands are treated as signed or unsigned values for comparison. |
31 | 38 |
|
32 | | -This repository is a Github template. You can create your own repository from it by clicking the green `Use this template` in the top right. |
33 | | -Please leave `Include all branches` **unchecked**; checking it will pollute the history of your new repository. |
34 | | -For more information, see ["Creating a repository from a template"](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template). |
| 39 | +--- |
35 | 40 |
|
36 | | -#### Wait for the template cleanup workflow to complete |
| 41 | +### Decoder.scala |
37 | 42 |
|
38 | | -After using the template to create your own blank project, please wait a minute or two for the `Template cleanup` workflow to run which will removes some template-specific stuff from the repository (like the LICENSE). |
39 | | -Refresh the repository page in your browser until you see a 2nd commit by `actions-user` titled `Template cleanup`. |
| 43 | +Implements the RISC-V instruction decoder that extracts key fields from a 32-bit instruction and formats them for downstream units such as the ALU, register file, or control logic. |
40 | 44 |
|
| 45 | +The decoder: |
| 46 | +- Identifies the instruction format (R, I, S, B, U, or J) based on the opcode (bits 6–0). |
| 47 | +- Outputs: |
| 48 | + - `rs1`, `rs2`, and `rd` register indices |
| 49 | + - The operation code (`operation`) |
| 50 | + - The immediate value (`immediate`) |
41 | 51 |
|
42 | | -#### Clone your repository |
| 52 | +For each format, the corresponding immediate field is assembled and sign-extended (or zero-filled) to 32 bits by left-shifting the extracted bits and padding with zeros as needed. |
| 53 | +This ensures that all immediates output by the decoder are consistently 32 bits wide, ready for arithmetic or address calculations without additional shifting logic later in the datapath. |
43 | 54 |
|
44 | | -Once you have created a repository from this template and the `Template cleanup` workflow has completed, you can click the green button to get a link for cloning your repository. |
45 | | -Note that it is easiest to push to a repository if you set up SSH with Github, please see the [related documentation](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh). SSH is required for pushing to a Github repository when using two-factor authentication. |
| 55 | +--- |
46 | 56 |
|
47 | | -```sh |
48 | | -git clone git@github.com:MIT-OpenCompute/RISC-V.git |
49 | | -cd RISC-V |
50 | | -``` |
| 57 | +### Registers.scala |
51 | 58 |
|
52 | | -#### Set project organization and name in build.sbt |
| 59 | +Defines the register file hardware. |
53 | 60 |
|
54 | | -The cleanup workflow will have attempted to provide sensible defaults for `ThisBuild / organization` and `name` in the `build.sbt`. |
55 | | -Feel free to use your text editor of choice to change them as you see fit. |
| 61 | +The CPU register file supports: |
| 62 | +- Dual independent combinational reads. |
| 63 | +- A single independent synchronous write. |
56 | 64 |
|
57 | | -#### Clean up the README.md file |
| 65 | +This allows two registers to be read in one clock cycle while a third register is written simultaneously. |
58 | 66 |
|
59 | | -Again, use you editor of choice to make the README specific to your project. |
| 67 | +The module also includes a third, debugging-only read port called the **C port**. |
| 68 | +This port is used exclusively for reading register values from testbenches. |
| 69 | +It is not part of the actual hardware and should not be used in the CPU datapath. |
60 | 70 |
|
61 | | -#### Add a LICENSE file |
| 71 | +--- |
62 | 72 |
|
63 | | -It is important to have a LICENSE for open source (or closed source) code. |
64 | | -This template repository has the Unlicense in order to allow users to add any license they want to derivative code. |
65 | | -The Unlicense is stripped when creating a repository from this template so that users do not accidentally unlicense their own work. |
| 73 | +## Running Testbenches |
66 | 74 |
|
67 | | -For more information about a license, check out the [Github Docs](https://docs.github.com/en/free-pro-team@latest/github/building-a-strong-community/adding-a-license-to-a-repository). |
| 75 | +This project uses `sbt`. |
68 | 76 |
|
69 | | -#### Commit your changes |
70 | | -```sh |
71 | | -git commit -m 'Starting RISC-V' |
72 | | -git push origin main |
| 77 | +To run a specific testbench, such as `ALUSpec.scala`, execute: |
| 78 | +```bash |
| 79 | +sbt "testOnly RISCV.ALUSpec" |
73 | 80 | ``` |
74 | 81 |
|
75 | | -### Did it work? |
76 | | - |
77 | | -You should now have a working Chisel3 project. |
78 | | - |
79 | | -You can run the included test with: |
80 | | -```sh |
81 | | -sbt test |
82 | | -``` |
| 82 | +## Writing a Testbench |
83 | 83 |
|
84 | | -Alternatively, if you use Mill: |
85 | | -```sh |
86 | | -./mill RISC-V.test |
87 | | -``` |
| 84 | +Use the following template as a guide for creating new testbenches: |
88 | 85 |
|
89 | | -You should see a whole bunch of output that ends with something like the following lines |
90 | | -``` |
91 | | -[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 |
92 | | -[info] All tests passed. |
93 | | -[success] Total time: 5 s, completed Dec 16, 2020 12:18:44 PM |
94 | 86 | ``` |
95 | | -If you see the above then... |
96 | | - |
97 | | -### It worked! |
98 | | - |
99 | | -You are ready to go. We have a few recommended practices and things to do. |
100 | | - |
101 | | -* Use packages and following conventions for [structure](https://www.scala-sbt.org/1.x/docs/Directories.html) and [naming](http://docs.scala-lang.org/style/naming-conventions.html) |
102 | | -* Package names should be clearly reflected in the testing hierarchy |
103 | | -* Build tests for all your work |
104 | | -* Read more about testing in SBT in the [SBT docs](https://www.scala-sbt.org/1.x/docs/Testing.html) |
105 | | -* This template includes a [test dependency](https://www.scala-sbt.org/1.x/docs/Library-Dependencies.html#Per-configuration+dependencies) on [ScalaTest](https://www.scalatest.org/). This, coupled with `svsim` (included with Chisel) and `verilator`, are a starting point for testing Chisel generators. |
106 | | - * You can remove this dependency in the build.sbt file if you want to |
107 | | -* Change the name of your project in the build.sbt file |
108 | | -* Change your README.md |
109 | | - |
110 | | -## Problems? Questions? |
111 | | - |
112 | | -Check out the [Chisel Users Community](https://www.chisel-lang.org/community.html) page for links to get in contact! |
| 87 | +package RISCV |
| 88 | +
|
| 89 | +import chisel3._ |
| 90 | +import chisel3.simulator.scalatest.ChiselSim |
| 91 | +import org.scalatest.freespec.AnyFreeSpec |
| 92 | +import org.scalatest.matchers.must.Matchers |
| 93 | +
|
| 94 | +class MainTemplateSpec extends AnyFreeSpec with Matchers with ChiselSim { |
| 95 | +
|
| 96 | + "Main should execute an instruction correctly (template)" in { |
| 97 | + simulate(new Main()) { dut => |
| 98 | + // 1. Initialize registers (example: write value to x1) |
| 99 | + dut.io.write_enable.poke(true.B) |
| 100 | + dut.io.write_addr.poke(1.U) |
| 101 | + dut.io.in.poke(42.U) |
| 102 | + dut.clock.step(1) |
| 103 | + dut.io.write_enable.poke(false.B) |
| 104 | +
|
| 105 | + // 2. Load an instruction (replace with your own encoding) |
| 106 | + val instr = "b000000000000_00000_000_00000_0000000".U(32.W) |
| 107 | + dut.io.instruction.poke(instr) |
| 108 | +
|
| 109 | + // 3. Step one clock to execute |
| 110 | + dut.clock.step(1) |
| 111 | +
|
| 112 | + // 4. Read back a register value to verify the result |
| 113 | + // Always use the C port of the register file for reading. |
| 114 | + dut.io.read_addr_C.poke(1.U) // Which register to read |
| 115 | + dut.io.out_C.expect(42.U) // Expected result (example) |
| 116 | + } |
| 117 | + } |
| 118 | +} |
| 119 | +``` |
0 commit comments