Category: ECE391

  • ECE391 note

    Context Switch

    ra(x1) saved by _swtch,
    And _swtch should act like an ‘nop’
    And tp is never used by compiler

  • Build ECE391 Env on Win64

    On Msys2 MINGW64

    cf. https://wiki.qemu.org/Hosts/W32

    pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-glib2 mingw-w64-x86_64-gettext-runtime mingw-w64-x86_64-gcc mingw-w64-x86_64-binutils mingw-w64-x86_64-pixman mingw-w64-x86_64-SDL2 mingw-w64-x86_64-gtk3 mingw-w64-x86_64-riscv64-unknown-elf-gcc mingw-w64-x86_64-gdb-multiarch git diffutils zsh vim)

    Please enable Developer Mode to support soft link without Administrator permission, otherwise it prompts

    Found ninja-1.12.1 at D:/msys64/usr/bin/ninja.exe
    Running postconf script 'D:/ZJUI/ECE391/qemu/build/pyvenv/bin/python3.exe D:/ZJUI/ECE391/qemu/scripts/symlink-install-tree.py'
    Please enable Developer Mode to support soft link without Administrator permission
    error making symbolic link D:/msys64/opt/toolchains/riscv/lib/libfdt.a
    Traceback (most recent call last):
      File "D:/ZJUI/ECE391/qemu/scripts/symlink-install-tree.py", line 35, in <module>
        raise e
      File "D:/ZJUI/ECE391/qemu/scripts/symlink-install-tree.py", line 28, in <module>
        os.symlink(source, bundle_dest)
    OSError: [WinError 1314] 客户端没有所需的特权。: 'D:/ZJUI/ECE391/qemu/build/subprojects/dtc/libfdt/libfdt.a' -> 'qemu-bundle/msys64/opt/toolchains/riscv/lib/libfdt.a'
    

    ./configure --prefix=/opt/toolchains/riscv --target-list=riscv32-softmmu,riscv64-softmmu --enable-gtk --enable-system --disable-werror
    make -j
    make install

    Change zsh for MINGW session https://superuser.com/questions/961699/change-default-shell-on-msys2

    sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

    Set in mingw64.ini:

    SHELL=/usr/bin/zsh

    There is no PTS on windows so use telnet instead
    source:https://www.uni-koeln.de/~pbogusze/posts/QEMU_serial_console.html

    qemu-system-riscv64 -machine virt -bios none -kernel cp1.elf -m 8M -nographic -serial mon:stdio -serial telnet:localhost:4321,server,nowait

    Add D:\msys64\mingw64\bin to PATH of Windows
    Then telnet to attach to con1

    telnet localhost 4321
  • [RISC-V ECE391]MP2

    Some Programming/Reference Manuals

    • Volume 1, Unprivileged Specification version 20240411 PDF GitHub
    • Volume 2, Privileged Specification version 20240411 PDF GitHub
    • PLIC Specs v1.0.0
      For newest PLIC manual please refer to https://riscv.org/technical/specifications/ and https://github.com/riscv/riscv-plic-spec/releases
    • NS16550 UART(Texus Instrument)
      cf. Section 8.6 for register specification.

      Note on CSR instructions

      CSR can’t be accessed directly, thus those instructions are needed.
      Only 6 instructions, CSR[RS,RC,RW,RSI,RCI,RWI],I is immediate.
      S for set, C for clear, W for write, other mnemonic(e.g. CSRR/CSRW) are pseudo-instructions with either rs1=x0 or ds=x0.
      For both CSRRS and CSRRC, if rs1=x0, then the instruction will not write to the CSR at all
      For both CSRRSI and CSRRCI, if uimm[4:0] field is zero, then the instruction will not write to the CSR at all
      But CAVEAT LECTOR!, if rs1=x0 or uimm[4:0]=0 for CSRRW or CSRRWI, then csr will be CLEARED

      IRQ number(PLIC source no./id) and MMAP(Memory Mapping) in ECE391 FA24

      It is modified based on https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
      7 uarts are added and IRQ number of RTC is moved to 9

      Ext ASM in C code

      Reference How to Use Inline Assembly Language in C Code

    • Do not expect a sequence of asm statements to remain perfectly consecutive after compilation, even when you are using the volatile qualifier. If certain instructions need to remain consecutive in the output, put them in a single multi-instruction asm statement.
    • \n\t to seperate assembly instructions in a single Assembly Template
      Input: using , delimiter

      [ [asmSymbolicName] ] constraint (cexpression)

      Output:

      [ [asmSymbolicName] ] constraint (cvariablename)
    • asmSymbolicName
      Specifies a symbolic name for the operand. Reference the name in the assembler template by enclosing it in square brackets (i.e. %[Value]). The scope of the name is the asm statement that contains the definition. Any valid C variable name is acceptable, including names already defined in the surrounding code. No two operands within the same asm statement can use the same symbolic name.
      When not using an asmSymbolicName, use the (zero-based) position of the operand in the list of operands in the assembler template. For example if there are two output operands and three inputs, use %2 in the template to refer to the first input operand, %3 for the second, and %4 for the third.

    For example

    uint32_t Mask = 1234;
    uint32_t Index;
    asm ("bsfl %[aMask], %[aIndex]"
         : [aIndex] "=r" (Index)
         : [aMask] "r" (Mask)
         : "cc");

    if no asmSymbolicName

    __asm__ ("btsl %2,%1\n\t" // Turn on zero-based bit #Offset in Base.
             "sbb %0,%0"      // Use the CF to calculate old.
       : "=r" (old), "+rm" (*Base)
       : "Ir" (Offset)
       : "cc");
    return old;

    output registers begin with 0, the number of input regs are after output regs.

    If using I(immediate) as constraint, the input value must be known at assembly time or later.

    Control Status Registers(CSR)

    mstatus:
    mip:
    mie:
    mtvec:
    mcause:
    mepc:

    PLIC

    Each source has a priority(0 is disabled, higher for high prio).
    destination is a contex, which is a HART combined with mode(M/S)
    every context (e.g. context 0) has a source enable(not prio).
    PLIC Indicates which interrupt source raised the interrupt by

    Trap entry

    • Places current PC into mepc CSR
    • Sets mstatus.MPP to previous privilege mode (current privilege mode is decided by path)
    • Sets mstatus.MPIE to mstatus.MIE
    • Sets mstatus.MIE to 0 (interrupts disabled on entry)
    • Sets PC to mtvec.BASE (if mode 0) or mtvec.BASE + 4×cause

      Trap exit

    • Sets mstatus.mie to mstatus.MPP ; sets MPIE to 1
    • Changes privilege mode to mstatus.MPP; sets MPP to 0
    • Set PC to mepc
      You will get to the vector addr of Externel M-Mode Interrupt(mtvec[1:0]==2b’01) or just BASE(mtvec[1:0]==2b’00), then check which source issued the interrupt, then go to the corresponding ISR(interrupt service routine) or what so-called interrupt handler.
      A CPU claims the interrupt to identify source
    • CPU reads special per-context claim register on PLIC
    • PLIC returns highest priority source number on read
    • PLIC will not offer the interrupt source to other CPUs
    • CPU has committed to servicing it
      CPU can always read claim register to poll for highest priority interrupt

      End procedure for PLIC(Interrupt Completion)

      When CPU is finished servicing the itnerrupt, it signals completion to the PLIC

    • CPU writes source number to its claim register on PLIC
    • This indicates CPU is done servicing the interrupt source
  • vscode添加RISC-V调试支持

    vscode 前置

    1. 安装C/C++插件
    2. 开启Allow Breakpoints Everywhere Vscode 在汇编文件中添加调试断点
    3. Makefile中添加ASFLAGS = -g

      vscode文件设置

      在workspace下.vscode下新建启动文件与任务文件launch.json, tasks.json

      launch.json

      miDebuggerPath 填riscv-gdb绝对路径,program填要调的程序

      {
      // Use IntelliSense to learn about possible attributes.
      // Hover to view descriptions of existing attributes.
      // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
      "version": "0.2.0",
      "configurations": [
          {
              "name": "Debug RISC-V",
              "type": "cppdbg",
              "request": "launch",
              "program":"${workspaceFolder}/demo.elf",
              "cwd": "${workspaceFolder}",
              "miDebuggerPath": "/opt/toolchains/riscv/bin/riscv64-unknown-elf-gdb",
              "miDebuggerServerAddress": "localhost:1234",
              "stopOnEntry": true,
              "preLaunchTask": "Run QEMU"
          }
      ]
      }

      tasks.json

    command中修改调试器启动参数,修改对应启动elf文件。不要删除前面的一条命令echo 'QEMU started',这个是为了让vscode结束启动等待用

    {
        // See https://go.microsoft.com/fwlink/?LinkId=733558
        // for the documentation about the tasks.json format
        "version": "2.0.0",
        "tasks": [
            {
                "label": "Build",
                "type": "shell",
                "command": "make",
                "args": [
                    ""
                ],
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "problemMatcher": [
                    "$gcc"
                ]
            },
            {
                "label": "Run QEMU",
                "type": "shell",
                "command": "echo 'QEMU started';qemu-system-riscv64 -s -S -machine virt -bios none -kernel demo.elf -m 128M -serial mon:stdio -device bochs-display",
                "dependsOn": ["Build"],
                "args": [],
                "group": {
                    "kind": "test",
                    "isDefault": true
                },
                "isBackground": true,
                "problemMatcher": [
                    {
                        "pattern": [
                            {
                                "regexp": ".",
                                "file": 1,
                                "location": 2,
                                "message": 3
                            }
                        ],
                        "background": {
                            "activeOnStart": true,
                            "beginsPattern": ".",
                            "endsPattern": ".",
                        }
                    }
                ]
            }
        ]
    }