contributed by < Hotmercury
>
Learning jupyter
docker install
docker run -it --rm -p 8888:8888 ucbbar/chisel-bootcamp
git clone
git clone https://github.com/freechipsproject/chisel-bootcamp.git
vscode open
paste docker url
select scala
If i execute underlying code will error
ammonite.util.CompilationError: Failed to resolve ivy dependencies:/coursier_cache/.structure.lock (Permission denied)
Due to a Docker permission issue, we need to resolve it by either adjusting ownership using chown
or elevating privileges using chmod
.
If we dont want to use token, find dockerfile copy last line
sbt (Scala Build Tool), relies on Scala and need a JVM (Java Virtual Machine)
Add new PPA(Personal Package Archive) to system
Additional tests : ubuntu 18 using Apptainer
But we can't install, so need to make sandbox
Not successfull
do it later
val
: is derived from Scala : immutable
var
: mutable
Types | meaning |
---|---|
Bits |
Raw collection of bits |
SInt |
Signed integer number |
UInt |
Unsigned integer number |
Bool |
Boolean |
Chisel Bundles are used to represent groups of wires that have name fields, like struct
in c.
Now we can create instances of FIFOInput
Bundles are typically used to define the interface of modules. The Bundle "flip" operator is employed to create and "oppsite" Bundle concerning its direction : -> 'input to output'
Flip situation : two connect module have many smae input/output name
Note: Vec is not a memory array; it functions as a collection of wires (or registers).
Modules are employed to establish hierarchy within the generated circuit
Combinational Logic:
positive-edge-triggered register Sequential Logic:
Base on what i have lerned so for
correct version
Testing Your System First make sure that you have sbt (the scala build tool) installed. See details in sbt.
First i want to know how to use sbt example to start a hello-word example.
And successfully ran the 'Hello World' program
run hello.scala
Next, I proceeded to MyCPU, using $ sbt test
and it come up with six errors. Therefore, I systematically addressed and corrected each of these errors. I used individual tests for this process."
testOnly
The testOnly
task accepts a whitespace separated list of test names to run.
type
object : You cannot instantiate an object(no need to call new
); you can simply directly reference it. It like to Java static classes.
We need to handle program counter with two issues
Code can be found in
src/main/scala/riscv/core/InstructionFetch.scala
.
instruction_read_data
and instruction
how do they work correct
Decode: Understanding the meaning of the instruction and reading register data.
we can find some Syntax-related chisel org
Fill
fill(num, bit stream)
copy bit stream num timesMuxLookup
MuxLookup(idx, default)(Seq(0.U -> a, 1.U -> b))
We can broswer riscv manual,Searching for underlying binary information can yield relevant results.
b0000011
: loadb0010011
: immidiateb0100011
: storeb0110011
: R typeb1100011
: branchBased on the diagram below, we can see that only lui
discards rs1
.
Realized that what we need to do is to complete the judgment of memory_read_enble
and memory_write_enble
.
So we can fix this lab.
We need to compelete alu_control
input (base on func3 and func7, we can get instructionType like addi, slli and so on)
This part is connecting the circuits of all modules.
After we fixed all error, we can get underlying message
$ sbt run
[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
[info] loading settings for project ca2023-lab3-build from plugins.sbt …
[info] loading project definition from ca2023-lab3/project
[info] loading settings for project root from build.sbt …
[info] set current project to mycpu (in build file:ca2023-lab3/)
[info] running board.verilator.VerilogGenerator
[success] Total time: 3 s, completed Nov 24, 2023, 2:56:00 PM
Tracing all flow from c or asm to execution phase
do later
Run ByteAccessTest
We first run gtkwave
We can find that TestTopModule
provide some debug ports
And we can use poke
, and according to the waveform diagram below, we can verify that we are indeed manipulating the corresponding registers.
Next, we observe the waveform of MyCPU, starting from the instruction stage, that is when io_instruction_valid
is 1, the operation begins.
I noticed that the cycle frequencies in the above two waveforms are different. Therefore, I conducted a detailed analysis of the clock usage in ByteAccessTest
. Upon entering the TestTopModule
, I found additional cycles due to the use of withClock
. I will explore the different purposes of these two clock in the future.
Now we see that ByteAccessTest
use mem_debug_read_address and a for loop control, I want to know the meaning of this for loop.
We found that if set i range in 43, an error occurs.
[info] Single Cycle CPU
[info] - should store and load a single byte *** FAILED ***
[info] io_regs_debug_read_data=0 (0x0) did not equal expected=5615 (0x15ef) (lines in CPUTest.scala: 114, 104) (CPUTest.scala:114)
[info] *** 1 TEST FAILED ***
[error] Failed tests:
[error] riscv.singlecycle.ByteAccessTest
[error] (Test / testOnly) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 10 s, completed Dec 1, 2023, 12:12:19 PM
So, we can conclude that at least 44 cycles are needed, and how can I conculate this number.
Total 12
instructions need to be load to mem
in TestModule first, so is 12 cycle, after all instruction load in mem io.load_finished := valid
, now we can run MyCPU.
Base on the piece of code in TestTopModule
we can see that every for original clock will cause one CPU clock.
Now we can conculate the needed number of cycles, first we have 12 cycles to load instruction to mem, and the CPU needs to execute 8 necessary instructions (jmp and nop can be ignored as they won't affect the result).
So, we can calculate the required number of cycles.
Set mem_address_index
as index of (MSB) bit 1 and 0, because log2Up
will get log(4)
is 2, and then sub 1.
Because the normal lw
instruction fetches data in word alignment, when we use lb
, lbu
, and lh
we can decide which part of the specified index to fetch. For example, when we use lb
, we can determine which byte we want based on the index.
And alu_result
is come from CPU phase
And from EXE phase
Finally get value of result in ALU.
In-depth analysis of the TestTopModule
From the makefile, the {}.elf file is converted to {}.asmbin. Through readAsmBinary
in instructionROM.scala, the .asmbin file is placed into an inputStream. After converting the format of instructions, they are placed in /verilog/verilator/filename.txt. Finally, loadMemoryFromFileInline
is used to load the instructions into the memory.
Init flow
We can find that mem init e.g. 8192 x Vec(4,8)
File to InstructionROM in InstructionROM.scala
This ROMLoader module is a Chisel module designed for loading ROM data into RAM.
In src/main/scala/peripheral/ROMLoader.scala
step
csrc
and remove printf
sine.asbin
to BINS
of Makefilemake update
$ sbt "testOnly riscv.singlecycle.SineTest"
But the following error occurred. I dont know what it meaning. I fix it by fix one line code but i still dont know what it is.
riscv-none-elf-ld -o sine.elf -T link.lds –oformat=elf32-littleriscv sine.o init.o
riscv-none-elf-ld: sine.o: in function .L17': sine.c:(.text+0x45c): undefined reference to
__mulsi3'
make: *** [Makefile:19: sine.elf] Error 1
And it will be successful
We followed the C code approach and removed all the ecall instructions, and it worked.