Skip to content

Latest commit

 

History

History
306 lines (244 loc) · 11.7 KB

README.md

File metadata and controls

306 lines (244 loc) · 11.7 KB

RISC-V Processor

Implementation of RISC-V Processor in System Verilog.

ISA

  • Unprivileged
    • RV32I (jump, branch, load/store, arithmetic/logical operations, ecall, ebreak)
    • RV32 Zicsr (CSR operations)
    • RV32M (mul, div, rem)
  • Privileged
    • Trap-Return Instructions (mret)

ISA is published in RISC-V official page.
Unprivileged Instructions are based on "Volume 1, Unprivileged Spec v. 20191213."
Privileged Instructions are based on "Volume 2, Privileged Spec v. 20190608."

Structure

processor

  • 4-stage pipeline (Fetch, Decode, Execute, Write)
  • Forwarding (E → D, W → D)
  • Branch prediction (Two-level adaptive predictor)
  • Register (32 entries, 32 bit)
  • Memory (1024 entries, 32 bit)
    • Use just registers for ease of implementation
  • CSR (Control and Status Register)
  • Exception/Interrupt handling (only User and Machine mode without Supervisor mode)
    • Exception
      • 2: Illegal instruction exception
      • 3: Breakpoint exception
      • 8: System call exception (from User mode)
      • 11: System call exception (from Machine mode)
    • Interrupt
      • 7: Machine timer interrupt
      • 11: Machine external interrupt

Registers

Register ABI Name Description
r0 zero hardwired zero
r1 ra return address
r2 sp stack pointer
r8 s0 / fp saved register / frame pointer
r9 s1 saved register
r10-11 a0-1 function arguments / return values
r12-17 a2-7 function arguments

Demo

  1. fib-csr

    • fib function with all exceptions, all interrupts, and CSR operations
    • r15 = fib(10)
    clocks       : 18613
    pc           :    43
    instructions : total 14587, normal   3809, exception   709, others 10069
    prediction   : total  1344, succeed  1130, fail        214
    register     :
    		r00:    0,    r01:   43,    r02: 2032,    r03:    0,
    		r04:    0,    r05:    0,    r06:    0,    r07:    0,
    		r08: 2048,    r09:    0,    r10:   89,    r11:    0,
    		r12:    0,    r13:    0,    r14:    0,    r15:   89
    
  2. fib-ebreak

    • fib function with exceptions and interrupts
    • r15 = fib(10)
    clocks       :  9385
    pc           :    43
    instructions : total  5267, normal   3809, exception   709, others   749
    prediction   : total   622, succeed   416, fail        206
    register     :
    		r00:    0,    r01:   43,    r02: 2032,    r03:    0,
    		r04:    0,    r05:    0,    r06:    0,    r07:    0,
    		r08: 2048,    r09:    0,    r10:   89,    r11:    0,
    		r12:    0,    r13:    0,    r14:    0,    r15:   89
    
  3. fib

    • fib function
    • r15 = fib(10)
    • 4222 [clocks] = 3809 [instructions] + (206-1) * 2 [stalls] + (4-1) [stages]
      • 206-1 is performed to ignore the prediction miss of the final instruction.
    clocks       :  4222
    pc           :    35
    instructions : total  3809, normal   3809, exception     0, others     0
    prediction   : total   622, succeed   416, fail        206
    register     :
    		r00:    0,    r01:   35,    r02: 2032,    r03:    0,
    		r04:    0,    r05:    0,    r06:    0,    r07:    0,
    		r08: 2048,    r09:    0,    r10:   89,    r11:    0,
    		r12:    0,    r13:    0,    r14:    0,    r15:   89
    
  4. memory

    • memory operations
    • r15 = a[0](=1) + a[1](=2)
    clocks       :    16
    pc           :    12
    instructions : total    13, normal     13, exception     0, others     0
    prediction   : total     2, succeed     1, fail          1
    register     :
    		r00:    0,    r01:    1,    r02: 2016,    r03:    0,
    		r04:    0,    r05:    0,    r06:    0,    r07:    0,
    		r08: 2048,    r09:    0,    r10:    0,    r11:    0,
    		r12:    0,    r13:    0,    r14:    1,    r15:    3
    

Installation

  1. This repository

    $ git clone https://github.com/hashi0203/riscv-processor.git
  2. RISC-V Cross Compiler

    If you just want to run the processor, you can skip this process.
    If you want to run your original test program, you should follow this process.

    We use riscv-gnu-toolchain as a cross compiler.
    Basically, you can follow the instructions on the GitHub page.

    $ git clone https://github.com/riscv/riscv-gnu-toolchain
    $ ./configure --prefix=/opt/riscv32 --with-arch=rv32ima --with-abi=ilp32d
    $ make linux

    You can change --prefix=/opt/riscv32 to the path you want to install this compiler.

    You also have to update PATH.

    export PATH=/opt/riscv32/bin:$PATH
    

Usage

If you just want to run the processor, you can skip 1 and 2.
If you want to run your original test program, you should follow 1 to 3.

  1. Make a test program for processor in test-programs.

    • Make a test program in C (e.g., fib.c, memory.c).
    • Compile the program by the following command (change "fib" to the file name (without extension) you have made).
    $ cd /path/to/test-programs
    $ make ARG=fib
  2. Change the test program for the processor.

    • Update instruction memory (instr_mem) in fetch.sv.
      • Make sure to change 63 in line 14 to the number of lines - 1.
    • Update MEM_SIZE, final_pc, privilege_jump_addr, exception_enabled, and interrupt_enabled in core.sv.
      • If you don't expect exception or interruption, you don't have to set privilege_jump_addr, and you have to set exception_enabled, and interrupt_enabled to zero.
    • Set max_clocks, max_reg_show, ext_intr and timer_intr in test_core.sv.
      • If max_clocks is small, the program may not finish.
      • If you don't expect external or timer interruption, you don't have to set ext_intr and timer_intr.
  3. Run the processor.

    • We use Vivado simulator commands (xvlog, xelab, and xsim).
    • You just have to run the following command.
      • All the .sv files in src will be compiled.
    $ cd /path/to/src
    $ make

Advanced Usage

  1. Compile from Assembly

    When you make test programs, you can also write or edit RISC-V assembly code.
    For example, fib-ebreak.S and fib-csr.S are obtained by editing fib.S.
    When editing assemblies, you have to make sure that the edited part should be above the following three lines.

    	.size	main, .-main
    	.ident	"GCC: (GNU) 10.2.0"
    	.section	.note.GNU-stack,"",@progbits
    

    After creating test programs in assembly, edit the Makefile by commenting out line 25 and 26.

    # $(ARG).S: $(ARG).c
    # 	$(CC) $(CFLAGS) -S -o $(ARG).S $(ARG).c
    

    Then, compile it by using make command.

    $ cd /path/to/test-programs
    $ make ARG=fib-ebreak

    Files in test-programs

    • start.S
      • disable default initial routine
      • no need to edit
    • link.ld
      • set start pc (program counter) to 0
      • no need to edit

    Explanation when using fib.c

    • fib.c
      • test program in C
    • fib.S
      • test program in assembly
      • automatically generated by make command
    • fib.bin
      • binary file of test program
      • automatically generated by make command
    • fib.hex
      • test program in hexadecimal
      • automatically generated by make command
    • fib.b
      • test program in binary for Verilog
      • used to test processor by editing fetch.sv
      • automatically generated by make command
    • fib.dump
      • disassembled test program (almost same as fib.S)
      • automatically generated by make command

    .hex and .dump are used for debugging.

  2. Simulation in Vivado

    • Start Vivado
    • Create Project
      • Create a New Vivado ProjectNext >
      • Project Name → Set any Project Name and Project locationNext >
      • Project TypeRTL Project (Default) → Next >
      • Add Sources → Add all .sv files in src (including test_core.sv) → Next >
      • Add Constraints (optional)Next >
      • Default PartNext >
      • New Project SummaryFinish
    • Run Simulation
      • Flow Navigator > PROJECT MANAGER > SIMULATION > Run Simulation > Run Behavioral Simulation
      • Click Yes or Save, if there are any pop-ups
      • Add wire or reg you want to check
        • Choose modules (e.g., _core) in Scope tab
        • wire and reg in the module appear in Objects tab
        • Choose wire or reg in Objects tab
        • Drag and drop it on Name in the wave orm area
      • Top bar > Run All
      • Check the waveform

    After updating source codes, you have to follow Run Simulation again.

Reference