├── .clang-format ├── .github ├── FUNDING.yml └── workflows │ ├── clang-format.yml │ ├── docker-build.yml │ ├── docker-deploy.yml │ ├── linux-release.yml │ ├── mac-release.yml │ ├── release_setup.yml │ ├── scripts │ ├── run_tests.sh │ ├── set_version.sh │ └── svg2icns.sh │ ├── test.yml │ ├── wasm-release.yml │ └── windows-release.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── appdir └── usr │ └── share │ ├── applications │ └── Ripes.desktop │ ├── icons │ └── hicolor │ │ ├── 128x128 │ │ └── apps │ │ │ └── Ripes.png │ │ ├── 16x16 │ │ └── apps │ │ │ └── Ripes.png │ │ ├── 22x22 │ │ └── apps │ │ │ └── Ripes.png │ │ ├── 24x24 │ │ └── apps │ │ │ └── Ripes.png │ │ ├── 256x256 │ │ └── apps │ │ │ └── Ripes.png │ │ ├── 32x32 │ │ └── apps │ │ │ └── Ripes.png │ │ ├── 48x48 │ │ └── apps │ │ │ └── Ripes.png │ │ ├── 512x512 │ │ └── apps │ │ │ └── Ripes.png │ │ └── 64x64 │ │ └── apps │ │ └── Ripes.png │ └── metainfo │ └── io.github.mortbopet.Ripes.metainfo.xml ├── docker ├── README.md └── ripes.dockerfile ├── docs ├── README.md ├── c_programming.md ├── cache_sim.md ├── cli.md ├── compiler_explorer.md ├── ecalls.md ├── introduction.md ├── mmio.md ├── new_processor_models.md ├── release_notes.md └── webassembly.md ├── examples ├── C │ ├── consoleInput.c │ ├── leds.c │ ├── matrixmul.c │ ├── ranpi.c │ └── switchesAndLeds.c ├── ELF │ ├── README.md │ ├── RanPi-RV32 │ └── RanPi-RV64 ├── assembly │ ├── complexMul.s │ ├── consolePrinting.s │ ├── consoleReading.s │ ├── factorial.s │ └── leds.s └── examples.qrc ├── external ├── .gitignore ├── CMakeLists.txt └── fancytabbar │ ├── CMakeLists.txt │ ├── LICENSE │ ├── include │ └── fancytabbar │ │ ├── fancytab.h │ │ └── fancytabbar.h │ └── src │ ├── fancytab.cpp │ └── fancytabbar.cpp ├── main.cpp ├── prepareRelease.py ├── resources ├── fonts │ ├── Inconsolata │ │ ├── Inconsolata-Bold.ttf │ │ ├── Inconsolata-Regular.ttf │ │ └── OFL.txt │ └── fonts.qrc ├── icons │ ├── Credits.txt │ ├── analytics.svg │ ├── binary-code.svg │ ├── breakpoint_disabled.png │ ├── breakpoint_enabled.png │ ├── build.svg │ ├── cancel.svg │ ├── clear.svg │ ├── compass.svg │ ├── cpu.svg │ ├── crosshair.svg │ ├── crosshair_blue.svg │ ├── crosshair_gold.svg │ ├── delete.svg │ ├── documents.svg │ ├── exit.svg │ ├── expand.svg │ ├── file.svg │ ├── graph.svg │ ├── icons.qrc │ ├── info.svg │ ├── led.svg │ ├── loadfile.svg │ ├── logo.svg │ ├── notepad.svg │ ├── plus.svg │ ├── ram-memory.svg │ ├── reset.svg │ ├── reverse.svg │ ├── run.svg │ ├── save.svg │ ├── saveas.svg │ ├── server.svg │ ├── spreadsheet.svg │ ├── step-clock.svg │ ├── step.svg │ ├── stop-clock.svg │ ├── tile.svg │ ├── trace.svg │ ├── zoom-in.svg │ └── zoom-out.svg └── images │ ├── QtIcon.png │ ├── animation.gif │ ├── asmeditorpng.png │ ├── cacheanimation.gif │ ├── cacheconfig.png │ ├── cacheplot.png │ ├── cachetab.png │ ├── cacheview.png │ ├── cachewayexpl.svg │ ├── ccsettings.png │ ├── editortab.png │ ├── expandedprocessor.png │ ├── iotab.png │ ├── iotabpreview.png │ ├── logo.png │ ├── logo_banner.png │ ├── memorytab.png │ ├── portlabel.png │ ├── portselected.png │ ├── processorselection.png │ ├── processortab.png │ ├── processortab_static.png │ ├── ptable.PNG │ ├── settings_compiler.png │ ├── stagetable.png │ ├── stalled.png │ └── tooltip.png ├── src ├── CMakeLists.txt ├── STLExtras.h ├── addressdialog.cpp ├── addressdialog.h ├── addressdialog.ui ├── assembler │ ├── CMakeLists.txt │ ├── assembler.cpp │ ├── assembler.h │ ├── assembler_defines.h │ ├── assemblerbase.cpp │ ├── assemblerbase.h │ ├── directive.h │ ├── expreval.cpp │ ├── expreval.h │ ├── gnudirectives.cpp │ ├── gnudirectives.h │ ├── matcher.h │ ├── objdump.cpp │ ├── objdump.h │ ├── parserutilities.cpp │ ├── parserutilities.h │ ├── program.cpp │ └── program.h ├── binutils.h ├── cachesim │ ├── CMakeLists.txt │ ├── cacheconfigwidget.cpp │ ├── cacheconfigwidget.h │ ├── cacheconfigwidget.ui │ ├── cachegraphic.cpp │ ├── cachegraphic.h │ ├── cacheplotview.cpp │ ├── cacheplotview.h │ ├── cacheplotwidget.cpp │ ├── cacheplotwidget.h │ ├── cacheplotwidget.ui │ ├── cachesim.cpp │ ├── cachesim.h │ ├── cacheview.cpp │ ├── cacheview.h │ ├── cachewidget.cpp │ ├── cachewidget.h │ ├── cachewidget.ui │ ├── callout.cpp │ ├── callout.h │ ├── chartlinemarker.cpp │ ├── chartlinemarker.h │ ├── l1cacheshim.cpp │ └── l1cacheshim.h ├── cachetab.cpp ├── cachetab.h ├── cachetab.ui ├── cachetabwidget.cpp ├── cachetabwidget.h ├── cachetabwidget.ui ├── ccmanager.cpp ├── ccmanager.h ├── cli │ ├── CMakeLists.txt │ ├── clioptions.cpp │ ├── clioptions.h │ ├── clirunner.cpp │ ├── clirunner.h │ ├── programutilities.cpp │ ├── programutilities.h │ └── telemetry.h ├── colors.h ├── compilererrordialog.cpp ├── compilererrordialog.h ├── compilererrordialog.ui ├── console.cpp ├── console.h ├── consolewidget.cpp ├── consolewidget.h ├── consolewidget.ui ├── ctkrangeslider.cpp ├── ctkrangeslider.h ├── editor │ ├── CMakeLists.txt │ ├── codeeditor.cpp │ ├── codeeditor.h │ ├── csyntaxhighlighter.cpp │ ├── csyntaxhighlighter.h │ ├── highlightabletextedit.cpp │ ├── highlightabletextedit.h │ ├── rvsyntaxhighlighter.cpp │ ├── rvsyntaxhighlighter.h │ ├── syntaxhighlighter.cpp │ └── syntaxhighlighter.h ├── edittab.cpp ├── edittab.h ├── edittab.ui ├── elfinfostrings.h ├── enumcombobox.h ├── flowlayout.cpp ├── flowlayout.h ├── fonts.h ├── formattermanager.h ├── gotocombobox.cpp ├── gotocombobox.h ├── instructionmodel.cpp ├── instructionmodel.h ├── io │ ├── CMakeLists.txt │ ├── iobase.cpp │ ├── iobase.h │ ├── iodpad.cpp │ ├── iodpad.h │ ├── ioledmatrix.cpp │ ├── ioledmatrix.h │ ├── iomanager.cpp │ ├── iomanager.h │ ├── ioregistry.h │ ├── ioswitches.cpp │ ├── ioswitches.h │ ├── memorymapmodel.cpp │ ├── memorymapmodel.h │ ├── periphparammodel.cpp │ ├── periphparammodel.h │ ├── registermapmodel.cpp │ └── registermapmodel.h ├── ioperipheraltab.cpp ├── ioperipheraltab.h ├── ioperipheraltab.ui ├── iotab.cpp ├── iotab.h ├── iotab.ui ├── isa │ ├── CMakeLists.txt │ ├── instruction.h │ ├── isa_defines.h │ ├── isa_types.h │ ├── isainfo.h │ ├── mips32isainfo.h │ ├── mipsisainfo_common.cpp │ ├── mipsisainfo_common.h │ ├── pseudoinstruction.h │ ├── rv32isainfo.h │ ├── rv64isainfo.h │ ├── rv_c_ext.cpp │ ├── rv_c_ext.h │ ├── rv_i_ext.cpp │ ├── rv_i_ext.h │ ├── rv_m_ext.cpp │ ├── rv_m_ext.h │ ├── rvisainfo_common.cpp │ ├── rvisainfo_common.h │ ├── rvrelocations.h │ ├── symbolmap.cpp │ └── symbolmap.h ├── loaddialog.cpp ├── loaddialog.h ├── loaddialog.ui ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── memorymodel.cpp ├── memorymodel.h ├── memorytab.cpp ├── memorytab.h ├── memorytab.ui ├── memoryview.cpp ├── memoryview.h ├── memoryviewerwidget.cpp ├── memoryviewerwidget.h ├── memoryviewerwidget.ui ├── modernize.sh ├── pipelinediagrammodel.cpp ├── pipelinediagrammodel.h ├── pipelinediagramwidget.cpp ├── pipelinediagramwidget.h ├── pipelinediagramwidget.ui ├── processmanager.h ├── processorhandler.cpp ├── processorhandler.h ├── processorregistry.cpp ├── processorregistry.h ├── processors │ ├── CMakeLists.txt │ ├── RISC-V │ │ ├── riscv.h │ │ ├── rv5s │ │ │ ├── rv5s.h │ │ │ ├── rv5s_exmem.h │ │ │ ├── rv5s_extended_layout.json │ │ │ ├── rv5s_forwardingunit.h │ │ │ ├── rv5s_hazardunit.h │ │ │ ├── rv5s_idex.h │ │ │ ├── rv5s_memwb.h │ │ │ └── rv5s_standard_layout.json │ │ ├── rv5s_no_fw │ │ │ ├── rv5s_no_fw.h │ │ │ ├── rv5s_no_fw_extended_layout.json │ │ │ ├── rv5s_no_fw_hazardunit.h │ │ │ ├── rv5s_no_fw_idex.h │ │ │ └── rv5s_no_fw_standard_layout.json │ │ ├── rv5s_no_fw_hz │ │ │ ├── rv5s_no_fw_hz.h │ │ │ ├── rv5s_no_fw_hz_exmem.h │ │ │ ├── rv5s_no_fw_hz_extended_layout.json │ │ │ ├── rv5s_no_fw_hz_idex.h │ │ │ ├── rv5s_no_fw_hz_ifid.h │ │ │ ├── rv5s_no_fw_hz_memwb.h │ │ │ └── rv5s_no_fw_hz_standard_layout.json │ │ ├── rv5s_no_hz │ │ │ ├── rv5s_no_hz.h │ │ │ ├── rv5s_no_hz_extended_layout.json │ │ │ └── rv5s_no_hz_standard_layout.json │ │ ├── rv6s_dual │ │ │ ├── rv6s_dual.h │ │ │ ├── rv6s_dual_branch.h │ │ │ ├── rv6s_dual_common.h │ │ │ ├── rv6s_dual_control.h │ │ │ ├── rv6s_dual_exmem.h │ │ │ ├── rv6s_dual_extended_layout.json │ │ │ ├── rv6s_dual_forwardingunit.h │ │ │ ├── rv6s_dual_hazardunit.h │ │ │ ├── rv6s_dual_idii.h │ │ │ ├── rv6s_dual_ifid.h │ │ │ ├── rv6s_dual_iiex.h │ │ │ ├── rv6s_dual_instr_mem.h │ │ │ ├── rv6s_dual_memwb.h │ │ │ ├── rv6s_dual_registerfile.h │ │ │ ├── rv6s_dual_uncompress.h │ │ │ └── rv6s_dual_waycontrol.h │ │ ├── rv_alu.h │ │ ├── rv_branch.h │ │ ├── rv_control.h │ │ ├── rv_decode.h │ │ ├── rv_ecallchecker.h │ │ ├── rv_immediate.h │ │ ├── rv_instrparser.h │ │ ├── rv_memory.h │ │ ├── rv_registerfile.h │ │ ├── rv_uncompress.h │ │ └── rvss │ │ │ ├── rv_decodeRVC.h │ │ │ ├── rv_ss_extended_layout.json │ │ │ ├── rv_ss_standard_layout.json │ │ │ └── rvss.h │ ├── interface │ │ └── ripesprocessor.h │ ├── layouts.qrc │ └── ripesvsrtlprocessor.h ├── processorselectiondialog.cpp ├── processorselectiondialog.h ├── processorselectiondialog.ui ├── processortab.cpp ├── processortab.h ├── processortab.ui ├── programviewer.cpp ├── programviewer.h ├── radix.cpp ├── radix.h ├── radixselectorwidget.cpp ├── radixselectorwidget.h ├── radixselectorwidget.ui ├── registercontainerwidget.cpp ├── registercontainerwidget.h ├── registercontainerwidget.ui ├── registerinitializationwidget.cpp ├── registerinitializationwidget.h ├── registerinitializationwidget.ui ├── registermodel.cpp ├── registermodel.h ├── registerwidget.cpp ├── registerwidget.h ├── registerwidget.ui ├── ripessettings.cpp ├── ripessettings.h ├── ripestab.h ├── savedialog.cpp ├── savedialog.h ├── savedialog.ui ├── serializers.h ├── settingsdialog.cpp ├── settingsdialog.h ├── settingsdialog.ui ├── statusmanager.h ├── symbolnavigator.cpp ├── symbolnavigator.h ├── symbolnavigator.ui ├── syscall │ ├── CMakeLists.txt │ ├── control.h │ ├── file.h │ ├── print.h │ ├── ripes_syscall.cpp │ ├── ripes_syscall.h │ ├── riscv_syscall.h │ ├── syscall_time.h │ ├── syscallviewer.cpp │ ├── syscallviewer.h │ ├── syscallviewer.ui │ ├── systemio.cpp │ └── systemio.h ├── utilities │ ├── CMakeLists.txt │ ├── hexspinbox.h │ ├── scrolleventfilter.h │ ├── systemutils.cpp │ └── systemutils.h ├── version │ ├── .gitignore │ ├── CMakeLists.txt │ ├── version.cmake │ ├── version.cpp │ └── version.h └── wasmSupport.h └── test ├── CMakeLists.txt ├── programloader.h ├── riscv-tests-64 ├── add.S ├── addi.S ├── addiw.S ├── addw.S ├── and.S ├── andi.S ├── brk_syscall.S ├── ecall_file.S ├── lb.S ├── lbu.S ├── ld.S ├── lh.S ├── lhu.S ├── lui.S ├── lw.S ├── lwu.S ├── or.S ├── ori.S ├── sb.S ├── sd.S ├── sh.S ├── simple.S ├── sll.S ├── slli.S ├── slliw.S ├── sllw.S ├── slt.S ├── slti.S ├── sltiu.S ├── sltu.S ├── sra.S ├── srai.S ├── sraiw.S ├── sraw.S ├── srl.S ├── srli.S ├── srliw.S ├── srlw.S ├── sub.S ├── subw.S ├── sw.S ├── xor.S └── xori.S ├── riscv-tests-c-64 └── rvc.s ├── riscv-tests-c └── rvc.s ├── riscv-tests ├── .gitignore ├── LICENSE ├── add.s ├── addi.s ├── and.s ├── andi.s ├── brk_syscall.s ├── cc.sh ├── div.s ├── divu.s ├── ecall_file.s ├── fadd.s ├── faddd.s ├── fclass.s ├── fclassd.s ├── fcmp.s ├── fcmpd.s ├── fcvt.s ├── fcvt_w.s ├── fcvt_wd.s ├── fcvtd.s ├── fdiv.s ├── fdivd.s ├── fmadd.s ├── fmaddd.s ├── fmin.s ├── fmind.s ├── ldst.s ├── ldstd.s ├── lui.s ├── memory.s ├── move.s ├── mul.s ├── mulh.s ├── mulhsu.s ├── mulhu.s ├── or.s ├── ori.s ├── ranpi.c ├── readme.txt ├── recoding.s ├── recodingd.s ├── rem.s ├── remu.s ├── simple.s ├── sll.s ├── slli.s ├── slt.s ├── slti.s ├── sltiu.s ├── sltu.s ├── sra.s ├── srai.s ├── srl.s ├── srli.s ├── sub.s ├── xor.s └── xori.s ├── tst_assembler.cpp ├── tst_cosimulate.cpp ├── tst_expreval.cpp ├── tst_reverse.cpp ├── tst_riscv.cpp └── tst_riscv_common.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | AlwaysBreakTemplateDeclarations: Yes -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [mortbopet] 4 | ko_fi: mortbopet 5 | -------------------------------------------------------------------------------- /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Check code format 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | build: 8 | name: Check with clang-format 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Get Ripes 12 | uses: actions/checkout@v2 13 | with: 14 | submodules: recursive 15 | fetch-depth: 2 16 | - name: clang-format 17 | run: | 18 | # Run clang-format 19 | sudo apt-get install -y clang-format-15 20 | CHANGED_FILES=`git diff --name-only -r HEAD~ --diff-filter=d | grep -E '.(c|cpp|h|hpp)$' | xargs` 21 | echo "Changed files: $CHANGED_FILES" 22 | [ -z "$CHANGED_FILES" ] && exit 0 23 | clang-format-15 -i $CHANGED_FILES 24 | git diff > clang-format.patch 25 | if [ -s clang-format.patch ]; then 26 | echo "Clang-format found formatting problems in the following files. See diff in the clang-format.patch artifact." 27 | git diff --name-only 28 | exit 1 29 | fi 30 | echo "Clang-format found no formatting problems" 31 | exit 0 32 | - name: Upload clang-format patch 33 | uses: actions/upload-artifact@v4 34 | if: ${{ failure() }} 35 | # Unfortunately, artifact uploads are always zips :( 36 | with: 37 | name: clang-format-patch 38 | path: clang-format.patch 39 | - name: clang-format patch display 40 | if: ${{ failure() }} 41 | run: | 42 | # Display patch 43 | cat clang-format.patch 44 | -------------------------------------------------------------------------------- /.github/workflows/docker-build.yml: -------------------------------------------------------------------------------- 1 | name: Build docker image 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | docker: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - 9 | uses: actions/checkout@v2 10 | - 11 | name: Set up Docker Buildx 12 | uses: docker/setup-buildx-action@v1 13 | - 14 | name: Build and push 15 | uses: docker/build-push-action@v2 16 | with: 17 | file: "./docker/ripes.dockerfile" 18 | context: "./docker/" 19 | -------------------------------------------------------------------------------- /.github/workflows/docker-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and deploy docker image 2 | on: 3 | push: 4 | branches: 5 | - master 6 | workflow_dispatch: 7 | 8 | jobs: 9 | docker: 10 | if: github.repository == 'mortbopet/Ripes' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - 14 | uses: actions/checkout@v2 15 | - 16 | name: Set up Docker Buildx 17 | uses: docker/setup-buildx-action@v1 18 | - 19 | name: Login to DockerHub 20 | uses: docker/login-action@v1 21 | with: 22 | username: mortbopet 23 | password: ${{ secrets.DOCKERHUB_TOKEN }} 24 | - 25 | name: Build and push 26 | uses: docker/build-push-action@v2 27 | with: 28 | file: "./docker/ripes.dockerfile" 29 | context: "./docker/" 30 | push: true 31 | tags: mortbopet/ripes:latest 32 | -------------------------------------------------------------------------------- /.github/workflows/release_setup.yml: -------------------------------------------------------------------------------- 1 | name: Release setup 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | 8 | jobs: 9 | release-setup: 10 | if: github.repository == 'mortbopet/Ripes' 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - uses: "marvinpinto/action-automatic-releases@latest" 15 | if: github.ref == 'refs/heads/master' 16 | with: 17 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 18 | automatic_release_tag: "continuous" 19 | prerelease: true 20 | title: "Continuous release" 21 | -------------------------------------------------------------------------------- /.github/workflows/scripts/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fail on failing QTest execution 4 | set -e 5 | 6 | find . -executable -type f -name "tst_*" | while read line; do 7 | echo "Running unit test: " 8 | echo "${line}" 9 | ($line) 10 | done -------------------------------------------------------------------------------- /.github/workflows/scripts/set_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | # Get the last tag which is not the top-of-head continuous tag 5 | export RIPES_VERSION=$(git describe --tags --exclude "continuous") 6 | -------------------------------------------------------------------------------- /.github/workflows/scripts/svg2icns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | # From https://gist.github.com/adriansr/1da9b18a8076b0f8a977a5eea0ae41ef 4 | 5 | set -e 6 | 7 | SIZES=" 8 | 16,16x16 9 | 32,16x16@2x 10 | 32,32x32 11 | 64,32x32@2x 12 | 128,128x128 13 | 256,128x128@2x 14 | 256,256x256 15 | 512,256x256@2x 16 | 512,512x512 17 | 1024,512x512@2x 18 | " 19 | 20 | for SVG in "$@"; do 21 | BASE=$(basename "$SVG" | sed 's/\.[^\.]*$//') 22 | ICONSET="$BASE.iconset" 23 | mkdir -p "$ICONSET" 24 | for PARAMS in $SIZES; do 25 | SIZE=$(echo $PARAMS | cut -d, -f1) 26 | LABEL=$(echo $PARAMS | cut -d, -f2) 27 | svg2png -w $SIZE -h $SIZE "$SVG" "$ICONSET"/icon_$LABEL.png 28 | done 29 | 30 | iconutil -c icns "$ICONSET" 31 | rm -rf "$ICONSET" 32 | done 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | *.stash 3 | *.autosave 4 | *.o 5 | Makefile 6 | build* 7 | .vscode 8 | 9 | 10 | # Qt generated files 11 | moc_* 12 | *.moc 13 | ui_* 14 | qrc_* 15 | 16 | # Executables & libraries 17 | Ripes 18 | RipesTest 19 | libRipesLib.a -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/VSRTL"] 2 | path = external/VSRTL 3 | url = https://github.com/mortbopet/VSRTL 4 | [submodule "external/ELFIO"] 5 | path = external/ELFIO 6 | url = https://github.com/serge1/ELFIO 7 | [submodule "external/libelfin"] 8 | path = external/libelfin 9 | url = https://github.com/mortbopet/libelfin 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Morten Borup Petersen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /appdir/usr/share/applications/Ripes.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=Ripes 4 | Comment=A graphical processor simulator and assembly editor for the RISC-V ISA (https://github.com/mortbopet/Ripes) 5 | Exec=Ripes 6 | Icon=Ripes 7 | Categories=Education;Utility; 8 | -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/128x128/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/128x128/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/16x16/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/16x16/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/22x22/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/22x22/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/24x24/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/24x24/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/256x256/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/256x256/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/32x32/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/32x32/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/48x48/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/48x48/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/512x512/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/512x512/apps/Ripes.png -------------------------------------------------------------------------------- /appdir/usr/share/icons/hicolor/64x64/apps/Ripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/appdir/usr/share/icons/hicolor/64x64/apps/Ripes.png -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | ## Build docker image 2 | 3 | To build latest version of Ripes from `master` branch issue the command 4 | 5 | ```bash 6 | docker build --rm --tag ripes -f ripes.dockerfile . 7 | ``` 8 | 9 | Or to build from specific branch 10 | 11 | ```bash 12 | docker build --rm --build-arg BRANCH=my_branch --tag ripes:latest -f ripes.dockerfile . 13 | ``` 14 | 15 | ## Run docker container 16 | 17 | Enable external connection to your X server (run for each session) 18 | ```bash 19 | xhost local:root 20 | ``` 21 | **Note:** you may add this line to `~/.xsessionrc` file to avoid having to run it for each session 22 | 23 | After that, issue the command 24 | 25 | ```bash 26 | docker run --rm -it --net=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix ripes:latest 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Ripes Documentation 2 | 3 | Welcome to the Ripes docs! You'll find all Ripes documentation pages in the list below. If you find that any of the pages are lacking or out of date, please feel free to create an issue or submit a PR. 4 | 5 | Is this your first time using Ripes? check out the [introduction/tutorial](introduction.md). 6 | 7 | - [Ripes introduction/tutorial](introduction.md) 8 | - [Cache simulation with Ripes](cache_sim.md) 9 | - [Building and Executing C programs with Ripes](c_programming.md) 10 | - [Adapting Compiler Explorer generated RISC-V assembly code](compiler_explorer.md) 11 | - [Memory-mapped IO in Ripes](mmio.md) 12 | - [Supported ecalls](ecalls.md) 13 | - [Command-line interface](cli.md) 14 | - [Release notes](release_notes.md) 15 | -------------------------------------------------------------------------------- /docs/webassembly.md: -------------------------------------------------------------------------------- 1 | # Ripes on WebAssembly 2 | 3 | ## Developer notes 4 | 5 | ## Building Ripes for WebAssembly 6 | 7 | Some pointers: 8 | - [WASM CI pipeline](/home/mpetersen/Work/Ripes/docs/webassembly.md) 9 | - [Qt for WASM](https://doc.qt.io/qt-6/wasm.html) 10 | 11 | ### Debugging 12 | 13 | To debug the webassembly build, you can use the following workflow: 14 | 1. Checkout https://github.com/mortbopet/mortbopet.github.io (Site where Ripes is hosted from) 15 | 2. Copy the `Ripes.*` files to the `mortbopet.github.io` folder. The `Ripes.*` files are generated in the build folder. 16 | 3. Use `emrun` to serve the site: 17 | ```bash 18 | cd mortbopet.github.io 19 | emrun index.html --no_browser 20 | ``` -------------------------------------------------------------------------------- /examples/C/consoleInput.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float getf() { 5 | float f; 6 | char c; 7 | while (!scanf("%f", &f)) { 8 | while ((c = getchar()) != '\n' && c != EOF) { 9 | } // Clear input buffer 10 | printf("Invalid number, please try again.\n"); 11 | } 12 | return f; 13 | } 14 | 15 | /** 16 | * Program calculating the power of a number based on floating-point base 17 | * and exponent values input by the user. 18 | */ 19 | int main() { 20 | float base, exp, result; 21 | printf("Enter a base number: \n"); 22 | base = getf(); 23 | printf("Enter an exponent: \n"); 24 | exp = getf(); 25 | 26 | result = pow(base, exp); 27 | 28 | printf("Result: %.1lf^%.1lf = %.2lf\n", base, exp, result); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /examples/C/leds.c: -------------------------------------------------------------------------------- 1 | #include "ripes_system.h" 2 | 3 | /* LEDs 4 | * This program draws an animation on an LED matrix peripheral. 5 | * 6 | * To run this program, make sure that you have instantiated an "LED Matrix" 7 | * peripheral in the "I/O" tab. 8 | */ 9 | 10 | #define W LED_MATRIX_0_WIDTH 11 | #define H LED_MATRIX_0_HEIGHT 12 | unsigned* led_base = LED_MATRIX_0_BASE; 13 | 14 | void main() { 15 | unsigned v = 0; 16 | while (1) { 17 | for (int y = 0; y < H; y++) { 18 | for (int x = 0; x < W; x++) { 19 | char r = v + (0xFF * x) / W; 20 | char g = v + (0xFF * y) / H; 21 | char b = v + (0xFF * (x + y)) / (W + H); 22 | unsigned idx = y * W + x; 23 | *(led_base + idx) = r << 16 | g << 8 | b; 24 | } 25 | v++; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/C/matrixmul.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Compute the product of two WxW matricies. 3 | * NOTE: In this program, we provide our own startup code and do not rely on any 4 | * C standard library features. 5 | * As such, this program compiles safely with the "-nostdlib" linker flag. 6 | */ 7 | 8 | asm("li sp, 0x100000"); // SP set to 1 MB 9 | asm("jal main"); // call main 10 | asm("mv a1, a0"); // save return value in a1 11 | asm("li a7, 10"); // prepare ecall exit 12 | asm("ecall"); // now your simulator should stop 13 | 14 | #define W 20 // Matrix order 15 | 16 | void mmul(const int a[W][W], const int b[W][W], int c[W][W]) { 17 | for (int row = 0; row < W; row++) { 18 | for (int col = 0; col < W; col++) { 19 | for (int k = 0; k < W; k++) { 20 | c[row][col] += a[row][k] * b[k][col]; 21 | } 22 | } 23 | } 24 | } 25 | 26 | int main() { 27 | int A[W][W]; 28 | int B[W][W]; 29 | int C[W][W]; 30 | mmul(A, B, C); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /examples/C/switchesAndLeds.c: -------------------------------------------------------------------------------- 1 | #include "ripes_system.h" 2 | 3 | /* Switches and LEDs 4 | * This program will toggle an LED in an LED matrix when the corresponding 5 | * switch is toggled. 6 | * 7 | * To run this program, make sure that you have instantiated one of each of the 8 | * following peripherals in the I/O tab: 9 | * - "LED Matrix" 10 | * - "Switches" 11 | */ 12 | 13 | unsigned* led_base = LED_MATRIX_0_BASE; 14 | unsigned* switch_base = SWITCHES_0_BASE; 15 | 16 | void main() { 17 | unsigned v = 0; 18 | while (1) { 19 | for (int i = 0; i < SWITCHES_0_N; i++) { 20 | if ((*switch_base >> i) & 0x1) { 21 | *(led_base + i) = 0xFF << ((i % 3) * 8); 22 | } else { 23 | *(led_base + i) = 0x0; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/ELF/README.md: -------------------------------------------------------------------------------- 1 | # RISC-V Executable Examples 2 | 3 | - 'RanPi (ELF)`: A precompiled version of `test/riscv-tests/ranpi.c`. 4 | -------------------------------------------------------------------------------- /examples/ELF/RanPi-RV32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/examples/ELF/RanPi-RV32 -------------------------------------------------------------------------------- /examples/ELF/RanPi-RV64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/examples/ELF/RanPi-RV64 -------------------------------------------------------------------------------- /examples/assembly/consolePrinting.s: -------------------------------------------------------------------------------- 1 | # This example demonstrates how strings, integers, chars and floating point 2 | # values may be printed to the console 3 | 4 | .data 5 | str: .string "A string" 6 | newline: .string "\n" 7 | delimiter: .string ", " 8 | 9 | .text 10 | # ------ String printing ---------- 11 | la a0, str # Load the address of the string, placed in the static data segment 12 | li a7, 4 # Argument '4' for ecall instructs ecall to print to console 13 | ecall 14 | 15 | jal printNewline 16 | 17 | # ------ Integer printing --------- 18 | # Print numbers in the range [-10:10] 19 | li a0, -10 20 | li a1, 10 21 | li a2, 1 22 | jal loopPrint 23 | 24 | jal printNewline 25 | 26 | # -------- Float printing ---------- 27 | # Print an approximation of Pi (3.14159265359) 28 | li a0, 0x40490FDB 29 | li a7, 2 30 | ecall 31 | 32 | jal printNewline 33 | 34 | # ------ ASCII character printing --------- 35 | # Print ASCII characters in the range [33:53] 36 | li a0, 33 37 | li a1, 53 38 | li a2, 11 39 | jal loopPrint 40 | 41 | # Finish execution 42 | jal exit 43 | 44 | # ====== Helper routines ====== 45 | printNewline: 46 | la a0, newline 47 | li a7, 4 48 | ecall 49 | jr x1 50 | 51 | # --- LoopPrint --- 52 | # Loops in the range [a0;a1] and prints the loop invariant to console 53 | # a0: range start 54 | # a1: range stop 55 | # a2: print method (ecall argument) 56 | loopPrint: 57 | mv t0 a0 58 | mv t1 a1 59 | loop: 60 | # Print value in a0 as specified by argument a2 61 | mv a0 t0 62 | mv a7 a2 63 | ecall 64 | # Print a delimiter between the numbers 65 | li a7, 4 66 | la a0, delimiter 67 | ecall 68 | # Increment 69 | addi t0, t0, 1 70 | ble t0, t1, loop 71 | jr x1 72 | 73 | exit: 74 | # Exit program 75 | li a7, 10 76 | ecall 77 | -------------------------------------------------------------------------------- /examples/assembly/consoleReading.s: -------------------------------------------------------------------------------- 1 | # This program will continuously read from STDIN and print 2 | # the first character from the read buffer. 3 | 4 | .data 5 | prompt1: .string "\nEnter character " 6 | prompt2: .string "\nCharacter was " 7 | buffer: .zero 255 8 | 9 | .text 10 | readLoop: 11 | li a7 4 12 | la a0 prompt1 13 | ecall 14 | call getChar 15 | mv t0 a0 16 | li a7 4 17 | la a0 prompt2 18 | ecall 19 | mv a0 t0 20 | li a7 11 21 | ecall 22 | j readLoop 23 | 24 | getChar: 25 | # Use syscall "read" on file descriptor 0 (stdin) 26 | li a7 63 27 | li a0 0 28 | la a1 buffer 29 | li a2 255 30 | ecall 31 | # Read the first word of the buffer 32 | lw a0 0 a1 33 | # Mask the first char and return it 34 | andi a0 a0 255 35 | ret 36 | -------------------------------------------------------------------------------- /examples/assembly/factorial.s: -------------------------------------------------------------------------------- 1 | # This example shows an implementation of the mathematical 2 | # factorial function (! function) to find the factorial value of !7 = 5040. 3 | 4 | .data 5 | argument: .word 7 6 | str1: .string "Factorial value of " 7 | str2: .string " is " 8 | 9 | .text 10 | main: 11 | lw a0, argument # Load argument from static data 12 | jal ra, fact # Jump-and-link to the 'fact' label 13 | 14 | # Print the result to console 15 | mv a1, a0 16 | lw a0, argument 17 | jal ra, printResult 18 | 19 | # Exit program 20 | li a7, 10 21 | ecall 22 | 23 | fact: 24 | addi sp, sp, -16 25 | sw ra, 8(sp) 26 | sw a0, 0(sp) 27 | addi t0, a0, -1 28 | bge t0, zero, nfact 29 | 30 | addi a0, zero, 1 31 | addi sp, sp, 16 32 | jr x1 33 | 34 | nfact: 35 | addi a0, a0, -1 36 | jal ra, fact 37 | addi t1, a0, 0 38 | lw a0, 0(sp) 39 | lw ra, 8(sp) 40 | addi sp, sp, 16 41 | mul a0, a0, t1 42 | ret 43 | 44 | # --- printResult --- 45 | # a0: Value which factorial number was computed from 46 | # a1: Factorial result 47 | printResult: 48 | mv t0, a0 49 | mv t1, a1 50 | la a0, str1 51 | li a7, 4 52 | ecall 53 | mv a0, t0 54 | li a7, 1 55 | ecall 56 | la a0, str2 57 | li a7, 4 58 | ecall 59 | mv a0, t1 60 | li a7, 1 61 | ecall 62 | ret 63 | -------------------------------------------------------------------------------- /examples/assembly/leds.s: -------------------------------------------------------------------------------- 1 | # LEDs 2 | # This program draws an animation on an LED matrix peripheral. 3 | # 4 | # To run this program, make sure that you have instantiated an "LED Matrix" 5 | # peripheral in the "I/O" tab. 6 | 7 | 8 | li a0 LED_MATRIX_0_BASE 9 | li a1 LED_MATRIX_0_WIDTH 10 | li a2 LED_MATRIX_0_HEIGHT 11 | 12 | loop: 13 | addi sp, sp, -16 14 | sw s0, 12(sp) 15 | sw s1, 8(sp) 16 | mv t6, zero 17 | add t3, a2, a1 18 | slli a6, a1, 2 19 | lui a3, 16 20 | addi a7, a3, -256 21 | lui t0, 4080 22 | init: 23 | mv t4, zero 24 | mv t1, zero 25 | mv t2, a0 26 | nextRow: 27 | mv a4, zero 28 | slli a3, t1, 8 29 | sub a3, a3, t1 30 | divu a3, a3, a2 31 | add a3, a3, t6 32 | slli a3, a3, 8 33 | and t5, a3, a7 34 | mv a5, t2 35 | mv a3, a1 36 | nextPixel: 37 | divu s0, a4, a1 38 | add s0, s0, t6 39 | add s1, t4, a4 40 | divu s1, s1, t3 41 | add s1, s1, t6 42 | slli s0, s0, 16 43 | and s0, s0, t0 44 | or s0, t5, s0 45 | andi s1, s1, 255 46 | or s0, s0, s1 47 | sw s0, 0(a5) 48 | addi a3, a3, -1 49 | addi a5, a5, 4 50 | addi a4, a4, 255 51 | bnez a3, nextPixel 52 | addi t6, t6, 1 53 | addi t1, t1, 1 54 | add t2, t2, a6 55 | addi t4, t4, 255 56 | bne t1, a2, nextRow 57 | j init 58 | -------------------------------------------------------------------------------- /examples/examples.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | C/ranpi.c 4 | C/consoleInput.c 5 | C/matrixmul.c 6 | assembly/factorial.s 7 | assembly/complexMul.s 8 | assembly/consolePrinting.s 9 | C/leds.c 10 | C/switchesAndLeds.c 11 | assembly/leds.s 12 | ELF/RanPi-RV32 13 | ELF/RanPi-RV64 14 | assembly/consoleReading.s 15 | 16 | 17 | -------------------------------------------------------------------------------- /external/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore any build directories of the external projects, 2 | # if they are being built standalone. 3 | build-*/* 4 | -------------------------------------------------------------------------------- /external/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | ## External project subdirectories 3 | ###################################################################### 4 | 5 | include(FetchContent) 6 | 7 | # Fancy tab bar 8 | add_subdirectory(fancytabbar) 9 | 10 | # VSRTL 11 | set(VSRTL_BUILD_APP OFF) 12 | set(VSRTL_BUILD_TESTS OFF) 13 | add_subdirectory(VSRTL) 14 | 15 | # libelfin 16 | FetchContent_Declare( 17 | libelfin 18 | SYSTEM 19 | GIT_REPOSITORY https://github.com/mortbopet/libelfin.git 20 | GIT_TAG 93a424940dc6e721818c5634b1876c8800e3f980 21 | ) 22 | FetchContent_MakeAvailable(libelfin) 23 | 24 | # Make autoMOC and autoUIC happy about the generated libelfin files 25 | set(libelfin_src "${CMAKE_CURRENT_BINARY_DIR}/libelfin") 26 | set_property(SOURCE "${libelfin_src}/elf_to_string.cc" PROPERTY SKIP_AUTOGEN ON) 27 | set_property(SOURCE "${libelfin_src}/dwarf_to_string.cc" PROPERTY SKIP_AUTOGEN ON) 28 | 29 | # ELFIO 30 | FetchContent_Declare( 31 | ELFIO 32 | SYSTEM 33 | GIT_REPOSITORY https://github.com/serge1/ELFIO.git 34 | GIT_TAG 79fcd11595d0793dec593e9072e36c7923c57c1a 35 | ) 36 | FetchContent_MakeAvailable(ELFIO) 37 | -------------------------------------------------------------------------------- /external/fancytabbar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9) 2 | 3 | # Find Qt6 Core and Widgets 4 | find_package(Qt6 COMPONENTS Core Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 8 | set(CMAKE_AUTOUIC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | file(GLOB LIB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) 12 | file(GLOB LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/fancytabbar/*.h) 13 | 14 | add_library(fancytabbar STATIC ${LIB_SOURCES} ${LIB_HEADERS}) 15 | add_library(fancytabbar::fancytabbar ALIAS fancytabbar) 16 | target_link_libraries(fancytabbar Qt6::Core Qt6::Widgets) 17 | target_include_directories(fancytabbar PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) 18 | -------------------------------------------------------------------------------- /external/fancytabbar/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jan Šipr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /external/fancytabbar/include/fancytabbar/fancytab.h: -------------------------------------------------------------------------------- 1 | #ifndef FANCYTAB_H 2 | #define FANCYTAB_H 3 | 4 | #include 5 | #include 6 | 7 | /*! 8 | * \brief The FancyTab class is more like struct than class. It has constructor 9 | * to set tab icon and tab text and the the icon and tab are accesseble 10 | * directly. 11 | */ 12 | class FancyTab { 13 | public: 14 | FancyTab(const QIcon &icon, QString text); 15 | 16 | QString m_text; 17 | QIcon m_icon; 18 | }; 19 | 20 | #endif // FANCYTAB_H 21 | -------------------------------------------------------------------------------- /external/fancytabbar/include/fancytabbar/fancytabbar.h: -------------------------------------------------------------------------------- 1 | #ifndef FANCYTABBAR_H 2 | #define FANCYTABBAR_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fancytabbar/fancytab.h" 9 | 10 | /*! 11 | * \brief Goal of this class is TabBar similar to QtCreator left TabBarr. 12 | * TabBar usage is described in example folder. 13 | */ 14 | 15 | class FancyTabBar : public QWidget { 16 | Q_OBJECT 17 | public: 18 | enum Error { SUCESS = 0, INDEX_OUT_OF_RANGE }; 19 | 20 | FancyTabBar(); 21 | explicit FancyTabBar(QWidget *widget); 22 | virtual ~FancyTabBar(); 23 | 24 | qint32 addFancyTab(QIcon icon, QString text); 25 | 26 | qint32 getActiveIndex() const; 27 | Error setActiveIndex(qint32 index); 28 | 29 | protected: 30 | void paintEvent(QPaintEvent *event); 31 | void mousePressEvent(QMouseEvent *event); 32 | void mouseMoveEvent(QMouseEvent *event); 33 | void enterEvent(QEnterEvent *event); 34 | void leaveEvent(QEvent *event); 35 | 36 | QRect getTabRect(qint32 index); 37 | QRect getIconRect(qint32 index); 38 | QRect getTextRect(qint32 index); 39 | qint32 getTabYPos(qint32 index); 40 | 41 | qint32 getTabIndexByPoint(qint32 x, qint32 y); 42 | 43 | void drawTabContent(QPainter *painter, qint32 index, 44 | bool invertTextColor = false); 45 | 46 | signals: 47 | void activeIndexChanged(qint32 index); 48 | 49 | private: 50 | void init(); 51 | 52 | QVector tabVector; 53 | qint32 activeIndex; 54 | 55 | qint32 barWidth; 56 | qint32 iconSize; 57 | qint32 textHeight; 58 | qint32 textWidth; 59 | qint32 tabHeight; 60 | qint32 tabWidth; 61 | qint32 tabTopSpaceing; 62 | qint32 hower; 63 | }; 64 | 65 | #endif // FANCYTABBAR_H 66 | -------------------------------------------------------------------------------- /external/fancytabbar/src/fancytab.cpp: -------------------------------------------------------------------------------- 1 | #include "fancytabbar/fancytab.h" 2 | 3 | #include 4 | 5 | FancyTab::FancyTab(const QIcon &icon, QString text) { 6 | m_icon = icon; 7 | m_text = text; 8 | } 9 | -------------------------------------------------------------------------------- /resources/fonts/Inconsolata/Inconsolata-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/fonts/Inconsolata/Inconsolata-Bold.ttf -------------------------------------------------------------------------------- /resources/fonts/Inconsolata/Inconsolata-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/fonts/Inconsolata/Inconsolata-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/fonts.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | Inconsolata/Inconsolata-Regular.ttf 4 | Inconsolata/Inconsolata-Bold.ttf 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icons/Credits.txt: -------------------------------------------------------------------------------- 1 | Icons made by: 2 | ---------------- 3 | https://www.flaticon.com/authors/smashicons 4 | https://www.flaticon.com/authors/freepik 5 | https://www.flaticon.com/authors/vectors-market 6 | https://www.flaticon.com/authors/pixel-buddha 7 | ---------------- 8 | from www.flaticon.com -------------------------------------------------------------------------------- /resources/icons/analytics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 11 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /resources/icons/breakpoint_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/icons/breakpoint_disabled.png -------------------------------------------------------------------------------- /resources/icons/breakpoint_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/icons/breakpoint_enabled.png -------------------------------------------------------------------------------- /resources/icons/cancel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /resources/icons/crosshair.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /resources/icons/delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/icons/exit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /resources/icons/expand.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /resources/icons/file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /resources/icons/icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | breakpoint_disabled.png 4 | breakpoint_enabled.png 5 | cpu.svg 6 | graph.svg 7 | server.svg 8 | ram-memory.svg 9 | binary-code.svg 10 | info.svg 11 | loadfile.svg 12 | exit.svg 13 | expand.svg 14 | zoom-in.svg 15 | zoom-out.svg 16 | save.svg 17 | spreadsheet.svg 18 | documents.svg 19 | logo.svg 20 | file.svg 21 | stop-clock.svg 22 | step.svg 23 | step-clock.svg 24 | reverse.svg 25 | reset.svg 26 | run.svg 27 | cancel.svg 28 | saveas.svg 29 | notepad.svg 30 | plus.svg 31 | delete.svg 32 | analytics.svg 33 | crosshair.svg 34 | build.svg 35 | trace.svg 36 | compass.svg 37 | clear.svg 38 | led.svg 39 | tile.svg 40 | crosshair_blue.svg 41 | crosshair_gold.svg 42 | 43 | 44 | -------------------------------------------------------------------------------- /resources/icons/info.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /resources/icons/loadfile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /resources/icons/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/icons/reset.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /resources/icons/step-clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /resources/icons/step.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icons/zoom-in.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /resources/icons/zoom-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /resources/images/QtIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/QtIcon.png -------------------------------------------------------------------------------- /resources/images/animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/animation.gif -------------------------------------------------------------------------------- /resources/images/asmeditorpng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/asmeditorpng.png -------------------------------------------------------------------------------- /resources/images/cacheanimation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/cacheanimation.gif -------------------------------------------------------------------------------- /resources/images/cacheconfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/cacheconfig.png -------------------------------------------------------------------------------- /resources/images/cacheplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/cacheplot.png -------------------------------------------------------------------------------- /resources/images/cachetab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/cachetab.png -------------------------------------------------------------------------------- /resources/images/cacheview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/cacheview.png -------------------------------------------------------------------------------- /resources/images/ccsettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/ccsettings.png -------------------------------------------------------------------------------- /resources/images/editortab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/editortab.png -------------------------------------------------------------------------------- /resources/images/expandedprocessor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/expandedprocessor.png -------------------------------------------------------------------------------- /resources/images/iotab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/iotab.png -------------------------------------------------------------------------------- /resources/images/iotabpreview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/iotabpreview.png -------------------------------------------------------------------------------- /resources/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/logo.png -------------------------------------------------------------------------------- /resources/images/logo_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/logo_banner.png -------------------------------------------------------------------------------- /resources/images/memorytab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/memorytab.png -------------------------------------------------------------------------------- /resources/images/portlabel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/portlabel.png -------------------------------------------------------------------------------- /resources/images/portselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/portselected.png -------------------------------------------------------------------------------- /resources/images/processorselection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/processorselection.png -------------------------------------------------------------------------------- /resources/images/processortab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/processortab.png -------------------------------------------------------------------------------- /resources/images/processortab_static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/processortab_static.png -------------------------------------------------------------------------------- /resources/images/ptable.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/ptable.PNG -------------------------------------------------------------------------------- /resources/images/settings_compiler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/settings_compiler.png -------------------------------------------------------------------------------- /resources/images/stagetable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/stagetable.png -------------------------------------------------------------------------------- /resources/images/stalled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/stalled.png -------------------------------------------------------------------------------- /resources/images/tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/resources/images/tooltip.png -------------------------------------------------------------------------------- /src/addressdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "addressdialog.h" 2 | #include "ui_addressdialog.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "processorhandler.h" 8 | #include "radix.h" 9 | 10 | namespace Ripes { 11 | 12 | AddressDialog::AddressDialog(QWidget *parent) 13 | : QDialog(parent), m_ui(new Ui::AddressDialog) { 14 | m_ui->setupUi(this); 15 | 16 | QRegularExpressionValidator *validator = 17 | new QRegularExpressionValidator(this); 18 | setISADepRegex(validator); 19 | m_ui->address->setValidator(validator); 20 | m_ui->address->setText( 21 | "0x" + 22 | QString("0").repeated(ProcessorHandler::currentISA()->bytes() * 2)); 23 | setWindowTitle("Ripes"); 24 | 25 | connect(m_ui->address, &QLineEdit::textChanged, this, 26 | &AddressDialog::validateTargetAddress); 27 | } 28 | 29 | AddressDialog::~AddressDialog() { delete m_ui; } 30 | 31 | void AddressDialog::validateTargetAddress(const QString &address) { 32 | bool ok; 33 | 34 | AInt value; 35 | const auto isaBytes = ProcessorHandler::currentISA()->bytes(); 36 | if (isaBytes == 2) { 37 | value = address.toUShort(&ok, 16); 38 | } else if (isaBytes == 4) { 39 | value = address.toUInt(&ok, 16); 40 | } else if (isaBytes == 8) { 41 | value = address.toULongLong(&ok, 16); 42 | } else { 43 | Q_UNREACHABLE(); 44 | } 45 | 46 | if (ok) { 47 | m_address = value; 48 | m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); 49 | } else { 50 | m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); 51 | } 52 | } 53 | } // namespace Ripes 54 | -------------------------------------------------------------------------------- /src/addressdialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "isa/isa_types.h" 6 | 7 | namespace Ripes { 8 | 9 | namespace Ui { 10 | class AddressDialog; 11 | } 12 | 13 | class AddressDialog : public QDialog { 14 | Q_OBJECT 15 | 16 | public: 17 | friend class GoToComboBox; 18 | explicit AddressDialog(QWidget *parent = nullptr); 19 | ~AddressDialog() override; 20 | 21 | AInt getAddress() const { return m_address; } 22 | 23 | private: 24 | Ui::AddressDialog *m_ui = nullptr; 25 | AInt m_address = 0; 26 | void validateTargetAddress(const QString &address); 27 | }; 28 | } // namespace Ripes 29 | -------------------------------------------------------------------------------- /src/assembler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(assembler LINK_TO_RIPES_LIB LINK_ISA_LIB) 2 | -------------------------------------------------------------------------------- /src/assembler/assembler.cpp: -------------------------------------------------------------------------------- 1 | #include "assembler.h" 2 | 3 | namespace Ripes { 4 | namespace Assembler { 5 | 6 | std::shared_ptr 7 | constructAssemblerDynamic(std::shared_ptr isa) { 8 | if (auto rv32isa = std::dynamic_pointer_cast>(isa)) { 9 | return std::make_shared>(rv32isa); 10 | } else if (auto rv64isa = 11 | std::dynamic_pointer_cast>(isa)) { 12 | return std::make_shared>(rv64isa); 13 | } 14 | 15 | throw std::runtime_error( 16 | std::string("Cannot dynamically construct assembler for isa: ") + 17 | isa->name().toStdString()); 18 | return {}; 19 | } 20 | 21 | } // namespace Assembler 22 | } // namespace Ripes 23 | -------------------------------------------------------------------------------- /src/assembler/assembler_defines.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "isa/isa_defines.h" 12 | #include "program.h" 13 | 14 | namespace Ripes { 15 | namespace Assembler { 16 | 17 | using SymbolLinePair = std::pair; 18 | using SourceProgram = std::vector; 19 | using NoPassResult = std::monostate; 20 | using Section = QString; 21 | 22 | /** 23 | * @brief The Result struct 24 | * An assembly result is determined to be valid iff errors is empty. 25 | */ 26 | struct AssembleResult { 27 | Errors errors; 28 | Program program; 29 | }; 30 | 31 | struct DisassembleResult { 32 | Errors errors; 33 | QStringList program; 34 | }; 35 | 36 | } // namespace Assembler 37 | 38 | } // namespace Ripes 39 | -------------------------------------------------------------------------------- /src/assembler/expreval.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "assembler_defines.h" 4 | #include "isa/symbolmap.h" 5 | #include 6 | #include 7 | 8 | namespace Ripes { 9 | namespace Assembler { 10 | 11 | extern const QRegularExpression s_exprOperatorsRegex; 12 | extern const QString s_exprOperators; 13 | extern const QString s_exprTokens; 14 | using ExprEvalVT = int64_t; // Expression evaluation value type 15 | using ExprEvalRes = Result; 16 | 17 | /** 18 | * @brief evaluate 19 | * Very simple expression parser for evaluating a right-associative binary 20 | * (2-operand) mathematical expressions. For now, no operator precedence is 21 | * implemented - to ensure precedence, parentheses must be implemented. The 22 | * functionality is mainly intended to be used by the assembler to expand 23 | * complex pseudoinstructions and as such not by the user. 24 | */ 25 | ExprEvalRes evaluate(const Location &, const QString &, 26 | const AbsoluteSymbolMap *variables = nullptr); 27 | 28 | /** 29 | * @brief couldBeExpression 30 | * @returns true if we have probably cause that the string is an expression and 31 | * not 'just' a single variable. 32 | */ 33 | bool couldBeExpression(const QString &s); 34 | } // namespace Assembler 35 | } // namespace Ripes 36 | -------------------------------------------------------------------------------- /src/assembler/gnudirectives.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "directive.h" 4 | 5 | namespace Ripes { 6 | namespace Assembler { 7 | 8 | /** @brief 9 | * A collection of standard GNU assembler directives 10 | */ 11 | /** 12 | * @brief gnuDirectives 13 | * @returns a collection of all of the available directives 14 | */ 15 | DirectiveVec gnuDirectives(); 16 | 17 | Directive zeroDirective(); 18 | Directive stringDirective(); 19 | Directive ascizDirective(); 20 | 21 | Directive doubleDirective(); 22 | Directive wordDirective(); 23 | Directive halfDirective(); 24 | Directive shortDirective(); 25 | Directive byteDirective(); 26 | Directive twoByteDirective(); 27 | Directive fourByteDirective(); 28 | Directive longDirective(); 29 | Directive alignDirective(); 30 | 31 | Directive dummyDirective(const QString &name); 32 | 33 | Directive textDirective(); 34 | Directive dataDirective(); 35 | Directive bssDirective(); 36 | Directive equDirective(); 37 | 38 | } // namespace Assembler 39 | } // namespace Ripes 40 | -------------------------------------------------------------------------------- /src/assembler/objdump.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "binutils.h" 4 | #include "program.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace Ripes { 11 | namespace Assembler { 12 | 13 | /** 14 | * AddrOffsetMap 15 | * To preserve accurate mappings between the program viewers disassembled view - 16 | * which contains additional lines for marking symbols, and the addresses of the 17 | * current program, we provide the AddrOffsetMap. Keys represent the editor line 18 | * number of which an additional line was inserted, in addition to lines 19 | * corresponding to the disassembled program. The value is a pair containing: 20 | * first: # of offset lines up to (not including) the given offset 21 | * second: An optional QString() referencing the symbol displayed at the 22 | * offset. 23 | */ 24 | using AddrOffsetMap = std::map>; 25 | 26 | QString objdump(const std::shared_ptr &program, 27 | AddrOffsetMap &addrOffsetMap); 28 | QString binobjdump(const std::shared_ptr &program, 29 | AddrOffsetMap &addrOffsetMap); 30 | 31 | } // namespace Assembler 32 | } // namespace Ripes 33 | -------------------------------------------------------------------------------- /src/assembler/parserutilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "assembler_defines.h" 7 | #include "isa/isa_defines.h" 8 | #include "radix.h" 9 | 10 | namespace Ripes { 11 | namespace Assembler { 12 | 13 | /** 14 | * @brief joinParentheses takes a number of tokens and merges together tokens 15 | * contained within top-level parentheses. For example: [lw, x10, (B, +, 16 | * (3*2))(x10)] => [lw, x10, B + 3*2), x10] 17 | */ 18 | Result joinParentheses(const Location &location, 19 | const QStringList &tokens); 20 | 21 | /// Quote-aware string tokenization. 22 | Result tokenizeQuotes(const Location &location, 23 | const QString &line); 24 | } // namespace Assembler 25 | } // namespace Ripes 26 | -------------------------------------------------------------------------------- /src/cachesim/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(cachesim LINK_TO_RIPES_LIB) 2 | -------------------------------------------------------------------------------- /src/cachesim/cacheconfigwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cachesim.h" 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | namespace Ui { 9 | class CacheConfigWidget; 10 | } 11 | 12 | class CacheConfigWidget : public QWidget { 13 | Q_OBJECT 14 | 15 | public: 16 | CacheConfigWidget(QWidget *parent); 17 | ~CacheConfigWidget() override; 18 | 19 | void setCache(const std::shared_ptr &cache); 20 | 21 | signals: 22 | void configurationChanged(); 23 | 24 | public slots: 25 | void handleConfigurationChanged(); 26 | 27 | private: 28 | void setupPresets(); 29 | void showSizeBreakdown(); 30 | std::shared_ptr m_cache; 31 | Ui::CacheConfigWidget *m_ui = nullptr; 32 | std::vector m_configItems; 33 | void storePreset(); 34 | void removePreset(); 35 | 36 | /** 37 | * @brief m_justSetPreset 38 | * Small helper flag for not erasing the text displaying the currently set 39 | * preset. When false, this ensures that the preset combo box is cleared when 40 | * the user makes changes to the current cache configuration; such that we do 41 | * not give the impression that the preset is still in effect after a 42 | * configuration change. 43 | */ 44 | bool m_justSetPreset = false; 45 | }; 46 | 47 | } // namespace Ripes 48 | 49 | // Qt Metatypes for enum combo boxes 50 | Q_DECLARE_METATYPE(Ripes::WritePolicy); 51 | Q_DECLARE_METATYPE(Ripes::WriteAllocPolicy); 52 | Q_DECLARE_METATYPE(Ripes::ReplPolicy); 53 | Q_DECLARE_METATYPE(Ripes::CachePreset); 54 | -------------------------------------------------------------------------------- /src/cachesim/cacheview.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "isa/isa_types.h" 6 | 7 | namespace Ripes { 8 | 9 | class CacheView : public QGraphicsView { 10 | Q_OBJECT 11 | public: 12 | CacheView(QWidget *parent); 13 | void fitScene(); 14 | 15 | protected: 16 | void wheelEvent(QWheelEvent *) override; 17 | void mousePressEvent(QMouseEvent *event) override; 18 | 19 | signals: 20 | void cacheAddressSelected(Ripes::AInt); 21 | 22 | private slots: 23 | void setupMatrix(); 24 | void zoomIn(int level = 1); 25 | void zoomOut(int level = 1); 26 | 27 | private: 28 | qreal m_zoom; 29 | }; 30 | 31 | } // namespace Ripes 32 | -------------------------------------------------------------------------------- /src/cachesim/cachewidget.cpp: -------------------------------------------------------------------------------- 1 | #include "cachewidget.h" 2 | #include "ui_cachewidget.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "cachegraphic.h" 8 | #include "cacheview.h" 9 | #include "ripessettings.h" 10 | 11 | namespace Ripes { 12 | 13 | CacheWidget::CacheWidget(QWidget *parent) 14 | : QWidget(parent), m_ui(new Ui::CacheWidget) { 15 | m_ui->setupUi(this); 16 | 17 | m_scene = std::make_unique(this); 18 | m_cacheSim = std::make_shared(this); 19 | m_ui->cacheConfig->setCache(m_cacheSim); 20 | m_ui->cachePlot->setCache(m_cacheSim); 21 | 22 | auto *cacheGraphic = new CacheGraphic(*m_cacheSim); 23 | m_scene->addItem(cacheGraphic); 24 | connect(m_cacheSim.get(), &CacheSim::configurationChanged, this, [=] { 25 | RipesSettings::getObserver(RIPES_GLOBALSIGNAL_REQRESET)->trigger(); 26 | 27 | auto cacheViews = m_scene->views(); 28 | if (cacheViews.size() > 0) { 29 | static_cast(cacheViews.at(0))->fitScene(); 30 | } 31 | }); 32 | } 33 | 34 | void CacheWidget::setNextLevelCache(const std::shared_ptr &cache) { 35 | m_cacheSim.get()->setNextLevelCache(cache); 36 | } 37 | 38 | CacheWidget::~CacheWidget() { delete m_ui; } 39 | 40 | } // namespace Ripes 41 | -------------------------------------------------------------------------------- /src/cachesim/cachewidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cachesim.h" 4 | #include "processors/RISC-V/rv_memory.h" 5 | #include 6 | 7 | QT_FORWARD_DECLARE_CLASS(QGraphicsScene) 8 | 9 | using RVMemory = vsrtl::core::RVMemory<32, 32>; 10 | 11 | namespace Ripes { 12 | 13 | class CacheSim; 14 | 15 | namespace Ui { 16 | class CacheWidget; 17 | } 18 | 19 | class CacheWidget : public QWidget { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit CacheWidget(QWidget *parent = nullptr); 24 | ~CacheWidget(); 25 | 26 | void setNextLevelCache(const std::shared_ptr &cache); 27 | 28 | std::shared_ptr &getCacheSim() { return m_cacheSim; } 29 | QGraphicsScene *getScene() { return m_scene.get(); } 30 | 31 | private: 32 | Ui::CacheWidget *m_ui; 33 | std::shared_ptr m_cacheSim; 34 | std::unique_ptr m_scene; 35 | }; 36 | 37 | } // namespace Ripes 38 | -------------------------------------------------------------------------------- /src/cachesim/cachewidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ripes::CacheWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 561 10 | 575 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 0 24 | 0 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | CacheConfigWidget 39 | QWidget 40 |
cachesim/cacheconfigwidget.h
41 | 1 42 |
43 | 44 | CachePlotWidget 45 | QWidget 46 |
cachesim/cacheplotwidget.h
47 | 1 48 |
49 |
50 | 51 | 52 |
53 | -------------------------------------------------------------------------------- /src/cachesim/chartlinemarker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace Ripes { 9 | 10 | class ChartLineMarker : public QGraphicsObject { 11 | Q_OBJECT 12 | public: 13 | ChartLineMarker(QChart *parent, const QLineSeries *series); 14 | QRectF boundingRect() const override; 15 | void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override { 16 | } 17 | 18 | void move(const QPointF ¢er); 19 | void snapToLine(bool enabled); 20 | bool isSnapping() const { return m_snapToLine; } 21 | void updateLines(); 22 | 23 | QPointF getMarkerValuePos() const; 24 | QPointF getMarkerPos() const; 25 | 26 | signals: 27 | void snappedMarkerChanged(); 28 | 29 | private: 30 | /** 31 | * @brief m_snapToLine 32 | * If true, the center of the marker will snap to the closest x-axis point on 33 | * the passed QLineSeries object. Note: it is assumed that the points in the 34 | * series are in a sorted order! 35 | */ 36 | bool m_snapToLine = true; 37 | 38 | QPointF m_center; 39 | QChart *m_chart = nullptr; 40 | QLineSeries const *m_series = nullptr; 41 | QGraphicsLineItem *m_hzLine = nullptr; 42 | QGraphicsLineItem *m_vtLine = nullptr; 43 | }; 44 | } // namespace Ripes 45 | -------------------------------------------------------------------------------- /src/cachesim/l1cacheshim.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "cachesim.h" 6 | 7 | #include "VSRTL/core/vsrtl_memory.h" 8 | #include "isa/isa_types.h" 9 | 10 | namespace Ripes { 11 | 12 | /** 13 | * @brief The CacheShim class 14 | * Provides a wrapper around the current processor models' data- and instruction 15 | * memories, to be used in the cache simulator interface. 16 | */ 17 | class L1CacheShim : public CacheInterface { 18 | Q_OBJECT 19 | public: 20 | enum class CacheType { DataCache, InstrCache }; 21 | L1CacheShim(CacheType type, QObject *parent); 22 | void access(AInt address, MemoryAccess::Type type) override; 23 | 24 | void setType(CacheType type); 25 | 26 | private: 27 | void processorReset(); 28 | void processorWasClocked(); 29 | void processorReversed(); 30 | 31 | /** 32 | * @brief m_memory 33 | * The cache simulator may be attached to either a ROM or a Read/Write memory 34 | * element. Accessing the underlying VSRTL component signals are dependent on 35 | * the given type of the memory. 36 | */ 37 | CacheType m_type; 38 | }; 39 | 40 | } // namespace Ripes 41 | -------------------------------------------------------------------------------- /src/cachetab.cpp: -------------------------------------------------------------------------------- 1 | #include "cachetab.h" 2 | #include "ui_cachetab.h" 3 | 4 | #include "cachesim/cacheview.h" 5 | #include "cachesim/cachewidget.h" 6 | 7 | #include "processorhandler.h" 8 | 9 | namespace Ripes { 10 | 11 | CacheTab::CacheTab(QToolBar *toolbar, QWidget *parent) 12 | : RipesTab(toolbar, parent), m_ui(new Ui::CacheTab) { 13 | m_ui->setupUi(this); 14 | 15 | // During processor running, it should not be possible to interact with the 16 | // cache tab 17 | connect(ProcessorHandler::get(), &ProcessorHandler::runStarted, this, 18 | [=] { setEnabled(false); }); 19 | connect(ProcessorHandler::get(), &ProcessorHandler::runFinished, this, 20 | [=] { setEnabled(true); }); 21 | 22 | connect(m_ui->cacheView, &CacheView::cacheAddressSelected, this, 23 | &CacheTab::focusAddressChanged); 24 | 25 | connect(m_ui->cacheTabWidget, &CacheTabWidget::cacheFocusChanged, this, 26 | [=](CacheWidget *widget) { 27 | m_ui->cacheView->setScene(widget->getScene()); 28 | m_ui->cacheView->fitScene(); 29 | }); 30 | 31 | // CacheTabWidget has a tendency to expand, but we'd like to minimize its 32 | // size. Stretch the CacheView. 33 | m_ui->splitter->setStretchFactor(0, 0); 34 | m_ui->splitter->setStretchFactor(1, 10); 35 | m_ui->splitter->setSizes({1, 10000}); 36 | } 37 | 38 | void CacheTab::tabVisibilityChanged(bool visible) { 39 | /** 40 | * A hack to ensure that the cache view is resized to screen size _after_ Qt 41 | * has calculated widget sizes when the cache tab is first shown. 42 | */ 43 | if (!m_initialized && visible) { 44 | QTimer::singleShot(100, m_ui->cacheTabWidget, 45 | [&] { m_ui->cacheTabWidget->flipTabs(); }); 46 | m_initialized = visible; 47 | } 48 | } 49 | 50 | CacheTab::~CacheTab() { delete m_ui; } 51 | 52 | } // namespace Ripes 53 | -------------------------------------------------------------------------------- /src/cachetab.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ripestab.h" 4 | #include 5 | 6 | #include "isa/isa_types.h" 7 | 8 | namespace Ripes { 9 | 10 | namespace Ui { 11 | class CacheTab; 12 | } 13 | 14 | class CacheTab : public RipesTab { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit CacheTab(QToolBar *toolbar, QWidget *parent = nullptr); 19 | ~CacheTab() override; 20 | 21 | void tabVisibilityChanged(bool visible) override; 22 | 23 | signals: 24 | void focusAddressChanged(Ripes::AInt address); 25 | 26 | private: 27 | Ui::CacheTab *m_ui; 28 | bool m_initialized = false; 29 | }; 30 | 31 | } // namespace Ripes 32 | -------------------------------------------------------------------------------- /src/cachetabwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "cachesim/l1cacheshim.h" 5 | 6 | // #define N_CACHES_ENABLED 7 | 8 | namespace Ripes { 9 | class CacheWidget; 10 | 11 | namespace Ui { 12 | class CacheTabWidget; 13 | } 14 | 15 | class CacheTabWidget : public QWidget { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit CacheTabWidget(QWidget *parent = nullptr); 20 | ~CacheTabWidget(); 21 | 22 | /** 23 | * @brief flipTabs 24 | * switches the active tabs from 0->1->0. This is a "hack" to resize the cache 25 | * view to the screen size, when initially starting the application. 26 | */ 27 | void flipTabs(); 28 | 29 | signals: 30 | void focusAddressChanged(unsigned address); 31 | void cacheFocusChanged(Ripes::CacheWidget *cacheInFocus); 32 | 33 | private: 34 | enum FixedCacheIdx { DataCache, InstrCache }; 35 | void connectCacheWidget(CacheWidget *w); 36 | void handleTabIndexChanged(int index); 37 | void handleTabCloseRequest(int index); 38 | 39 | Ui::CacheTabWidget *m_ui; 40 | 41 | int m_addTabIdx = -1; 42 | int m_nextCacheLevel = 2; 43 | QSize m_defaultTabButtonSize; 44 | 45 | std::unique_ptr m_l1dShim; 46 | std::unique_ptr m_l1iShim; 47 | }; 48 | 49 | } // namespace Ripes 50 | -------------------------------------------------------------------------------- /src/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(CLI 2 | LINK_TO_RIPES_LIB 3 | LINK_LIBS elfio::elfio dwarf++ 4 | ) 5 | -------------------------------------------------------------------------------- /src/cli/clioptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "assembler/program.h" 4 | #include "processorregistry.h" 5 | #include "telemetry.h" 6 | #include 7 | #include 8 | 9 | namespace Ripes { 10 | 11 | struct CLIModeOptions { 12 | QString src; 13 | SourceType srcType; 14 | ProcessorID proc; 15 | QStringList isaExtensions; 16 | bool verbose = false; 17 | QString outputFile = ""; 18 | bool jsonOutput = false; 19 | int timeout = 0; 20 | RegisterInitialization regInit; 21 | 22 | // A list of enabled telemetry options. 23 | std::vector> telemetry; 24 | }; 25 | 26 | /// Adds Ripes CLI options to a parser. 27 | void addCLIOptions(QCommandLineParser &parser, Ripes::CLIModeOptions &options); 28 | 29 | /// Parses Ripes CLI mode options to a CLIModeOptions struct. Returns 30 | /// true if options were parsed successfully. 31 | bool parseCLIOptions(QCommandLineParser &parser, QString &errorMessage, 32 | CLIModeOptions &options); 33 | 34 | } // namespace Ripes 35 | -------------------------------------------------------------------------------- /src/cli/clirunner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "clioptions.h" 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | /// The CLIRunner class is used to run Ripes in CLI mode. 9 | /// Based on a CLIModeOptions struct, it will run the appropriate combination 10 | /// of source processing (assembler/compiler/...), processor model execution 11 | /// as well as telemetry gathering and reporting. 12 | class CLIRunner : public QObject { 13 | Q_OBJECT 14 | public: 15 | CLIRunner(const CLIModeOptions &options); 16 | 17 | /// Runs the CLI mode. 18 | int run(); 19 | 20 | private: 21 | /// Process the provided source file (assembling, compiling, loading, ...) 22 | int processInput(); 23 | 24 | /// Runs the processor model until the program is finished. 25 | int runModel(); 26 | 27 | /// Prints requested telemetry to the console/output file. 28 | int postRun(); 29 | void info(QString msg, bool alwaysPrint = false, bool header = false, 30 | const QString &prefix = "INFO"); 31 | void error(const QString &msg); 32 | 33 | CLIModeOptions m_options; 34 | }; 35 | 36 | } // namespace Ripes 37 | -------------------------------------------------------------------------------- /src/cli/programutilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "assembler/program.h" 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | /** 9 | * @brief loadFlatBinaryFile 10 | * Loads a flat binary file into the program's text section. 11 | * @param program The program object to load the binary file into. 12 | * @param filepath The string containing the path to the binary file. 13 | * @param entryPoint The entry point address of the program. 14 | * @param loadAt The address at which to load the binary file. 15 | * @return An error message if an error occurred during loading; otherwise, an 16 | * empty string. 17 | * 18 | */ 19 | QString loadFlatBinaryFile(Program &program, const QString &filepath, 20 | unsigned long entryPoint, unsigned long loadAt); 21 | 22 | /** 23 | * @brief loadElfFile 24 | * Loads an ELF file into the program object passed as parameter. 25 | * @param program The program object to load the ELF file into. 26 | * @param file The QFile object containing the ELF file. 27 | * @return True if the ELF file was loaded successfully; otherwise, false. 28 | */ 29 | bool loadElfFile(Program &program, QFile &file); 30 | 31 | } // namespace Ripes 32 | -------------------------------------------------------------------------------- /src/colors.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace Ripes { 8 | namespace Colors { 9 | 10 | constexpr QColor BerkeleyBlue = {0x00, 0x32, 0x62}; 11 | constexpr QColor FoundersRock = {0x3B, 0x7E, 0xA1}; 12 | constexpr QColor CaliforniaGold = {0xFD, 0xB5, 0x15}; 13 | constexpr QColor Medalist = {0xC4, 0x82, 0x0E}; 14 | constexpr QColor FlatGreen = {0x4c, 0xde, 0x75}; 15 | 16 | // Returns a function which returns a lighter color on each instantiation 17 | inline std::function incrementalColorGenerator(const QColor &start, 18 | unsigned steps) { 19 | auto color = std::make_shared(start); 20 | return [color = color, steps] { 21 | const int decRatio = 100 + 80 / steps; 22 | QColor oldColor = *color; 23 | *color = color->lighter(decRatio); 24 | return oldColor; 25 | }; 26 | } 27 | 28 | inline std::function incrementalRedGenerator(unsigned steps) { 29 | return incrementalColorGenerator(QColorConstants::Red.lighter(120), steps); 30 | } 31 | 32 | }; // namespace Colors 33 | } // namespace Ripes 34 | -------------------------------------------------------------------------------- /src/compilererrordialog.cpp: -------------------------------------------------------------------------------- 1 | #include "compilererrordialog.h" 2 | #include "ui_compilererrordialog.h" 3 | 4 | namespace Ripes { 5 | 6 | CompilerErrorDialog::CompilerErrorDialog(QWidget *parent) 7 | : QDialog(parent), m_ui(new Ui::CompilerErrorDialog) { 8 | m_ui->setupUi(this); 9 | 10 | setWindowTitle("Compilation error"); 11 | } 12 | 13 | void CompilerErrorDialog::setText(const QString &text) { 14 | m_ui->infoText->setText(text); 15 | } 16 | void CompilerErrorDialog::setErrorText(const QString &text) { 17 | m_ui->errorText->setPlainText(text); 18 | } 19 | 20 | CompilerErrorDialog::~CompilerErrorDialog() { delete m_ui; } 21 | 22 | } // namespace Ripes 23 | -------------------------------------------------------------------------------- /src/compilererrordialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace Ripes { 5 | namespace Ui { 6 | class CompilerErrorDialog; 7 | } 8 | 9 | /** 10 | * @brief The CompilerErrorDialog class 11 | * Small class for displaying a QRichTextEdit along with a label, to nicely 12 | * display a compiler output message. This class is used instead of QMessageBox 13 | * and its "set detailed text" functionality, due to the missing option of 14 | * manually resizing a QMessageBox. 15 | */ 16 | class CompilerErrorDialog : public QDialog { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit CompilerErrorDialog(QWidget *parent = nullptr); 21 | ~CompilerErrorDialog(); 22 | 23 | void setText(const QString &); 24 | void setErrorText(const QString &); 25 | 26 | private: 27 | Ui::CompilerErrorDialog *m_ui; 28 | }; 29 | 30 | } // namespace Ripes 31 | -------------------------------------------------------------------------------- /src/console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace Ripes { 9 | 10 | class Console : public QPlainTextEdit { 11 | Q_OBJECT 12 | 13 | signals: 14 | void sendData(const QByteArray &data); 15 | 16 | public: 17 | Console(QWidget *parent = nullptr); 18 | void putData(const QByteArray &data); 19 | void clearConsole(); 20 | 21 | protected: 22 | void keyPressEvent(QKeyEvent *e) override; 23 | 24 | private: 25 | void backspace(); 26 | 27 | bool m_localEchoEnabled = false; 28 | QFont m_font; 29 | QString m_buffer; 30 | }; 31 | 32 | } // namespace Ripes 33 | -------------------------------------------------------------------------------- /src/consolewidget.cpp: -------------------------------------------------------------------------------- 1 | #include "consolewidget.h" 2 | #include "ui_consolewidget.h" 3 | 4 | #include "console.h" 5 | #include "fonts.h" 6 | #include "ripessettings.h" 7 | #include "syscall/systemio.h" 8 | 9 | #include 10 | #include 11 | 12 | namespace Ripes { 13 | 14 | ConsoleWidget::ConsoleWidget(QWidget *parent) 15 | : QWidget(parent), m_ui(new Ui::ConsoleWidget) { 16 | m_ui->setupUi(this); 17 | 18 | connect(m_ui->clearConsoleButton, &QPushButton::clicked, m_ui->console, 19 | &Console::clearConsole); 20 | m_ui->clearConsoleButton->setIcon(QIcon(":/icons/clear.svg")); 21 | m_ui->clearConsoleButton->setToolTip("Clear console"); 22 | 23 | // Send input data from the console to the SystemIO stdin stream. 24 | connect(m_ui->console, &Console::sendData, &SystemIO::get(), 25 | &SystemIO::putStdInData); 26 | 27 | // Print output data from SystemIO in the console. 28 | connect(&SystemIO::get(), &SystemIO::doPrint, m_ui->console, 29 | [&](auto text) { m_ui->console->putData(text.toUtf8()); }); 30 | } 31 | 32 | ConsoleWidget::~ConsoleWidget() { delete m_ui; } 33 | 34 | void ConsoleWidget::putData(const QByteArray &d) { m_ui->console->putData(d); } 35 | 36 | void ConsoleWidget::clearConsole() { m_ui->console->clearConsole(); } 37 | 38 | } // namespace Ripes 39 | -------------------------------------------------------------------------------- /src/consolewidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | 7 | namespace Ui { 8 | class ConsoleWidget; 9 | } 10 | 11 | class ConsoleWidget : public QWidget { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit ConsoleWidget(QWidget *parent = nullptr); 16 | ~ConsoleWidget(); 17 | 18 | void putData(const QByteArray &data); 19 | void clearConsole(); 20 | 21 | private: 22 | Ui::ConsoleWidget *m_ui; 23 | }; 24 | 25 | } // namespace Ripes 26 | -------------------------------------------------------------------------------- /src/editor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(editor LINK_TO_RIPES_LIB) 2 | -------------------------------------------------------------------------------- /src/editor/csyntaxhighlighter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "syntaxhighlighter.h" 6 | 7 | /** Heavily based on QT's rich text syntax highlighter example. 8 | http://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html 9 | */ 10 | 11 | namespace Ripes { 12 | 13 | class CSyntaxHighlighter : public SyntaxHighlighter { 14 | public: 15 | CSyntaxHighlighter(QTextDocument *parent = nullptr, 16 | std::shared_ptr errors = {}); 17 | void syntaxHighlightBlock(const QString &text) override; 18 | 19 | private: 20 | struct HighlightingRule { 21 | QRegularExpression pattern; 22 | QTextCharFormat format; 23 | }; 24 | QVector highlightingRules; 25 | 26 | QRegularExpression commentStartExpression; 27 | QRegularExpression commentEndExpression; 28 | 29 | QTextCharFormat keywordFormat; 30 | QTextCharFormat typeFormat; 31 | QTextCharFormat singleLineCommentFormat; 32 | QTextCharFormat multiLineCommentFormat; 33 | QTextCharFormat preprocessorFormat; 34 | QTextCharFormat quotationFormat; 35 | QTextCharFormat functionFormat; 36 | }; 37 | 38 | } // namespace Ripes 39 | -------------------------------------------------------------------------------- /src/editor/rvsyntaxhighlighter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "syntaxhighlighter.h" 7 | 8 | namespace Ripes { 9 | 10 | class RVSyntaxHighlighter : public SyntaxHighlighter { 11 | public: 12 | RVSyntaxHighlighter(QTextDocument *parent, std::shared_ptr errors, 13 | const std::set &supportedOpcodes); 14 | void syntaxHighlightBlock(const QString &text) override; 15 | 16 | private: 17 | struct HighlightingRule { 18 | QRegularExpression pattern; 19 | QTextCharFormat format; 20 | }; 21 | QVector m_highlightingRules; 22 | 23 | QTextCharFormat registerFormat; 24 | QTextCharFormat labelFormat; 25 | QTextCharFormat directiveFormat; 26 | QTextCharFormat instructionFormat; 27 | QTextCharFormat stringFormat; 28 | QTextCharFormat commentFormat; 29 | QTextCharFormat immediateFormat; 30 | }; 31 | 32 | } // namespace Ripes 33 | -------------------------------------------------------------------------------- /src/editor/syntaxhighlighter.cpp: -------------------------------------------------------------------------------- 1 | #include "syntaxhighlighter.h" 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent, 7 | std::shared_ptr errors) 8 | : QSyntaxHighlighter(parent), m_errors(errors) { 9 | errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline); 10 | errorFormat.setUnderlineColor(Qt::red); 11 | } 12 | 13 | void SyntaxHighlighter::highlightBlock(const QString &text) { 14 | int row = currentBlock().firstLineNumber(); 15 | if (m_errors && m_errors->toMap().count(row) != 0) { 16 | setFormat(0, text.length(), errorFormat); 17 | } else { 18 | syntaxHighlightBlock(text); 19 | } 20 | } 21 | 22 | } // namespace Ripes 23 | -------------------------------------------------------------------------------- /src/editor/syntaxhighlighter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "isa/isa_defines.h" 7 | 8 | namespace Ripes { 9 | 10 | class SyntaxHighlighter : public QSyntaxHighlighter { 11 | Q_OBJECT 12 | 13 | public: 14 | SyntaxHighlighter(QTextDocument *parent = nullptr, 15 | std::shared_ptr errors = {}); 16 | 17 | /** 18 | * @brief highlightBlock 19 | * Performs language-independent highlighting, such as line-underlining upon 20 | * an error during assembly/compilation. 21 | */ 22 | void highlightBlock(const QString &text) override final; 23 | /** 24 | * @brief syntaxHighlightBlock 25 | * Performs language-specific highlighting 26 | */ 27 | virtual void syntaxHighlightBlock(const QString &text) = 0; 28 | 29 | protected: 30 | /** 31 | * @brief m_errors 32 | * The syntax highlighter may provide a tooltip error for each line in the 33 | * current text document. These tooltips will be displayed by the codeeditor 34 | * when a relevant tooltip event occurs. 35 | */ 36 | std::shared_ptr m_errors; 37 | QTextCharFormat errorFormat; 38 | }; 39 | } // namespace Ripes 40 | -------------------------------------------------------------------------------- /src/enumcombobox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace Ripes { 8 | 9 | template 10 | void setupEnumCombobox(QComboBox *combobox, 11 | const std::map &nameMap) { 12 | for (const auto &iter : nameMap) { 13 | combobox->addItem(iter.second, QVariant::fromValue(iter.first)); 14 | } 15 | } 16 | 17 | template 18 | void setEnumIndex(QComboBox *combobox, Enum enumItem) { 19 | for (int i = 0; i < combobox->count(); ++i) { 20 | if (qvariant_cast(combobox->itemData(i)) == enumItem) { 21 | combobox->setCurrentIndex(i); 22 | return; 23 | } 24 | } 25 | Q_ASSERT(false && "Index not found"); 26 | } 27 | 28 | template 29 | Enum getEnumValue(QComboBox *combobox) { 30 | return qvariant_cast(combobox->itemData(combobox->currentIndex())); 31 | } 32 | 33 | } // namespace Ripes 34 | -------------------------------------------------------------------------------- /src/fonts.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Ripes { 4 | namespace Fonts { 5 | 6 | constexpr auto monospace = "Inconsolata"; 7 | 8 | } // namespace Fonts 9 | } // namespace Ripes 10 | -------------------------------------------------------------------------------- /src/formattermanager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "processmanager.h" 6 | #include "ripessettings.h" 7 | 8 | namespace Ripes { 9 | 10 | class FormatterManager : public ProcessManager { 11 | friend class ProcessManager; 12 | 13 | private: 14 | bool verifyProgram(const QString & /*path*/) { return true; } 15 | QString getSettingsPath() { return RIPES_SETTING_FORMATTER_PATH; } 16 | QStringList getAlwaysArguments() { 17 | return RipesSettings::value(RIPES_SETTING_FORMATTER_ARGS) 18 | .toString() 19 | .split(" "); 20 | } 21 | QStringList getDefaultPaths() { return {"clang-format"}; } 22 | QString getWorkingDirectory() { 23 | return QCoreApplication::applicationDirPath(); 24 | } 25 | }; 26 | 27 | } // namespace Ripes 28 | -------------------------------------------------------------------------------- /src/gotocombobox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "isa/isa_types.h" 7 | 8 | namespace Ripes { 9 | 10 | enum class GoToFunction { Select, Address, Custom }; 11 | struct GoToUserData { 12 | GoToFunction func; 13 | unsigned arg; 14 | }; 15 | 16 | struct GoToRegisterValue : public GoToUserData { 17 | std::string_view regFileName; 18 | }; 19 | 20 | class GoToComboBox : public QComboBox { 21 | Q_OBJECT 22 | public: 23 | GoToComboBox(QWidget *parent = nullptr); 24 | void showPopup() override; 25 | 26 | signals: 27 | void indexChanged(); 28 | void jumpToAddress(Ripes::AInt address); 29 | 30 | private: 31 | void signalFilter(int index); 32 | virtual void addTargets() = 0; 33 | virtual AInt addrForIndex(int i) = 0; 34 | }; 35 | 36 | class GoToSectionComboBox : public GoToComboBox { 37 | public: 38 | GoToSectionComboBox(QWidget *parent = nullptr) : GoToComboBox(parent) {} 39 | 40 | private: 41 | void addTargets(); 42 | AInt addrForIndex(int i); 43 | }; 44 | 45 | class GoToRegisterComboBox : public GoToComboBox { 46 | public: 47 | GoToRegisterComboBox(QWidget *parent = nullptr) : GoToComboBox(parent) {} 48 | 49 | private: 50 | void addTargets(); 51 | AInt addrForIndex(int i); 52 | }; 53 | 54 | } // namespace Ripes 55 | 56 | Q_DECLARE_METATYPE(Ripes::GoToUserData); 57 | Q_DECLARE_METATYPE(Ripes::GoToRegisterValue); 58 | -------------------------------------------------------------------------------- /src/io/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(io LINK_TO_RIPES_LIB) 2 | -------------------------------------------------------------------------------- /src/io/iobase.cpp: -------------------------------------------------------------------------------- 1 | #include "iobase.h" 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | 7 | std::map> IOBase::s_peripheralIDs; 8 | 9 | IOBase::IOBase(unsigned IOType, QWidget *parent) 10 | : QWidget(parent), m_type(IOType) { 11 | m_id = claimPeripheralId(m_type); 12 | connect(this, &IOBase::scheduleUpdate, this, 13 | QOverload<>::of(&QWidget::update)); 14 | } 15 | 16 | QString cName(const QString &name) { 17 | QString cname = name; 18 | for (const auto &ch : {' ', '-'}) { 19 | cname.replace(ch, "_"); 20 | } 21 | return cname.toUpper(); 22 | } 23 | 24 | QString IOBase::name() const { 25 | return baseName() + " " + QString::number(m_id); 26 | } 27 | 28 | bool IOBase::setParameter(unsigned ID, const QVariant &value) { 29 | const auto preSize = byteSize(); 30 | m_parameters.at(ID).value = value; 31 | parameterChanged(ID); 32 | const auto postSize = byteSize(); 33 | if (preSize != postSize) { 34 | emit sizeChanged(); 35 | } 36 | 37 | emit paramsChanged(); 38 | return true; 39 | } 40 | 41 | void IOBase::unregister() { 42 | std::atomic sync; 43 | std::condition_variable cv; 44 | std::mutex cv_m; 45 | std::unique_lock lock(cv_m); 46 | 47 | // Signal to IO Manager that we're about to delete this peripheral, allowing 48 | // it to unregister this. 49 | emit aboutToDelete(sync); 50 | cv.wait(lock, [&sync] { return sync == 1; }); 51 | m_didUnregister = true; 52 | 53 | // Continue destruction process... 54 | } 55 | 56 | } // namespace Ripes 57 | -------------------------------------------------------------------------------- /src/io/iodpad.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | QT_FORWARD_DECLARE_CLASS(QAbstractButton); 8 | 9 | #include "iobase.h" 10 | 11 | namespace Ripes { 12 | 13 | class IODPad : public IOBase { 14 | Q_OBJECT 15 | 16 | enum IdxToDir { UP, DOWN, LEFT, RIGHT, DIRECTIONS }; 17 | 18 | public: 19 | IODPad(QWidget *parent); 20 | ~IODPad() { unregister(); }; 21 | 22 | virtual unsigned byteSize() const override; 23 | virtual QString description() const override; 24 | virtual QString baseName() const override { return "D-Pad"; }; 25 | 26 | virtual const std::vector ®isters() const override { 27 | return m_regDescs; 28 | }; 29 | 30 | /** 31 | * Hardware read/write functions 32 | */ 33 | virtual VInt ioRead(AInt offset, unsigned size) override; 34 | virtual void ioWrite(AInt offset, VInt value, unsigned size) override; 35 | 36 | protected: 37 | virtual void parameterChanged(unsigned) override{/* no parameters */}; 38 | void keyPressEvent(QKeyEvent *e) override; 39 | void keyReleaseEvent(QKeyEvent *e) override; 40 | 41 | private: 42 | constexpr static unsigned m_maxSideWidth = 256; 43 | std::vector m_regDescs; 44 | std::map m_buttons; 45 | }; 46 | } // namespace Ripes 47 | -------------------------------------------------------------------------------- /src/io/ioledmatrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "iobase.h" 8 | 9 | namespace Ripes { 10 | 11 | class IOLedMatrix : public IOBase { 12 | Q_OBJECT 13 | 14 | enum Parameters { HEIGHT, WIDTH, SIZE }; 15 | 16 | public: 17 | IOLedMatrix(QWidget *parent); 18 | ~IOLedMatrix() { unregister(); }; 19 | 20 | virtual unsigned byteSize() const override; 21 | virtual QString description() const override; 22 | virtual QString baseName() const override { return "LED Matrix"; } 23 | 24 | virtual const std::vector ®isters() const override { 25 | return m_regDescs; 26 | }; 27 | virtual const std::vector *extraSymbols() const override { 28 | return &m_extraSymbols; 29 | } 30 | 31 | /** 32 | * Hardware read/write functions 33 | */ 34 | virtual VInt ioRead(AInt offset, unsigned size) override; 35 | virtual void ioWrite(AInt offset, VInt value, unsigned size) override; 36 | 37 | virtual void reset() override { 38 | std::fill(m_ledRegs.begin(), m_ledRegs.end(), 0); 39 | } 40 | 41 | protected: 42 | virtual void parameterChanged(unsigned) override { updateLEDRegs(); }; 43 | 44 | /** 45 | * QWidget drawing 46 | */ 47 | void paintEvent(QPaintEvent *event) override; 48 | QSize minimumSizeHint() const override; 49 | 50 | private: 51 | VInt regRead(AInt offset) const; 52 | void updateLEDRegs(); 53 | 54 | unsigned m_maxSideWidth = 256; 55 | std::vector m_ledRegs; 56 | std::vector m_regDescs; 57 | std::vector m_extraSymbols; 58 | 59 | QPen m_pen; 60 | }; 61 | } // namespace Ripes 62 | -------------------------------------------------------------------------------- /src/io/ioregistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iobase.h" 4 | #include 5 | 6 | #include "iodpad.h" 7 | #include "ioledmatrix.h" 8 | #include "ioswitches.h" 9 | 10 | /** @brief IORegistry 11 | * 12 | * This is where all peripherals should be registerred to be made available in 13 | * the UI. The peripheral must be registerred three times: 14 | * - Add it to the IOType enum 15 | * - Add it to the IOTypeTitles map (Associate a name with the peripheral) 16 | * - Add it to the IOFactories map (Associate a constructor with the peripheral) 17 | */ 18 | 19 | namespace Ripes { 20 | 21 | enum IOType { LED_MATRIX, SWITCHES, DPAD, NPERIPHERALS }; 22 | 23 | template 24 | IOBase *createIO(QWidget *parent) { 25 | static_assert(std::is_base_of::value); 26 | return new T(parent); 27 | } 28 | 29 | using IOFactory = std::function; 30 | 31 | const static std::map IOTypeTitles = { 32 | {IOType::LED_MATRIX, "LED Matrix"}, 33 | {IOType::SWITCHES, "Switches"}, 34 | {IOType::DPAD, "D-Pad"}}; 35 | const static std::map IOFactories = { 36 | {IOType::LED_MATRIX, createIO}, 37 | {IOType::SWITCHES, createIO}, 38 | {IOType::DPAD, createIO}}; 39 | 40 | } // namespace Ripes 41 | 42 | Q_DECLARE_METATYPE(Ripes::IOType); 43 | -------------------------------------------------------------------------------- /src/io/memorymapmodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "radix.h" 7 | 8 | #include 9 | 10 | namespace Ripes { 11 | class IOBase; 12 | class IOManager; 13 | 14 | /** 15 | * @brief The MemoryMapModel class 16 | * A model for Qt's MVC framework, responsible for representing the current 17 | * state of the memory system of the simulator. 18 | */ 19 | class MemoryMapModel : public QAbstractTableModel { 20 | Q_OBJECT 21 | public: 22 | enum Column { Name, Size, AddressRange, NColumns }; 23 | MemoryMapModel(const IOManager *iomanager, QObject *parent = nullptr); 24 | 25 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 26 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 27 | 28 | QVariant data(const QModelIndex &index, 29 | int role = Qt::DisplayRole) const override; 30 | QVariant headerData(int section, Qt::Orientation orientation, 31 | int role = Qt::DisplayRole) const override; 32 | 33 | Qt::ItemFlags flags(const QModelIndex &index) const override; 34 | 35 | public slots: 36 | void memoryMapChanged(); 37 | 38 | private: 39 | IOManager const *m_ioManager = nullptr; 40 | }; 41 | } // namespace Ripes 42 | -------------------------------------------------------------------------------- /src/io/registermapmodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "radix.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace Ripes { 12 | class IOBase; 13 | 14 | /** 15 | * @brief The RegisterMapModel class 16 | * A model for Qt's MVC framework, responsible for representing the register map 17 | * exposed by a memory mapped peripheral. The model is read-only. 18 | */ 19 | class RegisterMapModel : public QAbstractTableModel { 20 | Q_OBJECT 21 | public: 22 | enum Column { Name, Address, RW, BitWidth, NColumns }; 23 | RegisterMapModel(QPointer peripheral, QObject *parent = nullptr); 24 | 25 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 26 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 27 | 28 | QVariant data(const QModelIndex &index, 29 | int role = Qt::DisplayRole) const override; 30 | QVariant headerData(int section, Qt::Orientation orientation, 31 | int role = Qt::DisplayRole) const override; 32 | 33 | Qt::ItemFlags flags(const QModelIndex &index) const override; 34 | 35 | public slots: 36 | void regMapChanged(); 37 | 38 | private: 39 | QPointer m_peripheral = nullptr; 40 | }; 41 | } // namespace Ripes 42 | -------------------------------------------------------------------------------- /src/ioperipheraltab.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace Ripes { 5 | class IOBase; 6 | 7 | namespace Ui { 8 | class IOPeripheralTab; 9 | } 10 | 11 | class IOPeripheralTab : public QWidget { 12 | Q_OBJECT 13 | 14 | public: 15 | IOPeripheralTab(QWidget *parent, IOBase *peripheral); 16 | ~IOPeripheralTab(); 17 | 18 | private: 19 | void updateExportsInfo(); 20 | 21 | Ui::IOPeripheralTab *m_ui = nullptr; 22 | IOBase *m_peripheral = nullptr; 23 | }; 24 | 25 | } // namespace Ripes 26 | -------------------------------------------------------------------------------- /src/isa/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(isa LINK_TO_RIPES_LIB) 2 | 3 | target_sources(isa_lib 4 | PRIVATE 5 | mipsisainfo_common.h mipsisainfo_common.cpp 6 | mips32isainfo.h 7 | ) 8 | 9 | target_link_libraries(isa_lib PUBLIC elfio::elfio vsrtl::vsrtl Signals::Signals) -------------------------------------------------------------------------------- /src/isa/isa_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | // Data types representing simulator memory addresses and simulator values. The 9 | // type should be wide enough to represent all ISAs supported by Ripes. AInt and 10 | // VInt are equal, but we discern between the two for code readability. 11 | using AInt = uint64_t; // Address type 12 | using VInt = uint64_t; // Value type 13 | using AIntS = typename std::make_signed::type; // Signed address type 14 | using VIntS = typename std::make_signed::type; // Signed value type 15 | 16 | } // namespace Ripes 17 | -------------------------------------------------------------------------------- /src/isa/mips32isainfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "isainfo.h" 4 | #include "mipsisainfo_common.h" 5 | 6 | namespace Ripes { 7 | 8 | template <> 9 | class ISAInfo : public MIPS_ISAInfoBase { 10 | public: 11 | ISAInfo(const QStringList extensions) { 12 | // Validate extensions 13 | for (const auto &ext : extensions) { 14 | if (supportsExtension(ext)) { 15 | m_enabledExtensions << ext; 16 | } 17 | } 18 | } 19 | 20 | ISA isaID() const override { return ISA::MIPS32I; } 21 | 22 | unsigned int bits() const override { return 32; } 23 | unsigned elfMachineId() const override { return EM_MIPS; } 24 | QString CCmarch() const override { 25 | QString march = "mips32i"; 26 | return march; 27 | } 28 | QString CCmabi() const override { return "ilp32"; } 29 | 30 | unsigned instrByteAlignment() const override { return 4; }; 31 | }; 32 | 33 | } // namespace Ripes 34 | -------------------------------------------------------------------------------- /src/isa/rv32isainfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "isainfo.h" 4 | #include "rvisainfo_common.h" 5 | 6 | namespace Ripes { 7 | 8 | template <> 9 | class ISAInfo : public RVISA::RV_ISAInfoBase { 10 | public: 11 | ISAInfo(const QStringList extensions) : RV_ISAInfoBase(extensions) { 12 | initialize(); 13 | } 14 | 15 | ISA isaID() const override { return ISA::RV32I; } 16 | 17 | unsigned int bits() const override { return 32; } 18 | unsigned elfMachineId() const override { return EM_RISCV; } 19 | QString CCmarch() const override { 20 | QString march = "rv32i"; 21 | 22 | return _CCmarch(march); 23 | } 24 | QString CCmabi() const override { return "ilp32"; } 25 | 26 | unsigned instrByteAlignment() const override { 27 | return extensionEnabled("C") ? 2 : 4; 28 | }; 29 | }; 30 | 31 | } // namespace Ripes 32 | -------------------------------------------------------------------------------- /src/isa/rv64isainfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "isainfo.h" 4 | #include "rvisainfo_common.h" 5 | 6 | namespace Ripes { 7 | 8 | template <> 9 | class ISAInfo : public RVISA::RV_ISAInfoBase { 10 | public: 11 | ISAInfo(const QStringList extensions) : RV_ISAInfoBase(extensions) { 12 | initialize( 13 | {RVISA::Option::shifts64BitVariant, RVISA::Option::LI64BitVariant}); 14 | } 15 | 16 | ISA isaID() const override { return ISA::RV64I; } 17 | 18 | unsigned int bits() const override { return 64; } 19 | QString CCmarch() const override { 20 | QString march = "rv64i"; 21 | 22 | return _CCmarch(march); 23 | } 24 | QString CCmabi() const override { return "lp64"; } 25 | 26 | unsigned instrByteAlignment() const override { 27 | return extensionEnabled("C") ? 2 : 4; 28 | }; 29 | }; 30 | 31 | } // namespace Ripes 32 | -------------------------------------------------------------------------------- /src/isa/rv_c_ext.cpp: -------------------------------------------------------------------------------- 1 | #include "rv_c_ext.h" 2 | 3 | namespace Ripes { 4 | namespace RVISA { 5 | namespace ExtC { 6 | 7 | void enableExt(const ISAInfoBase *isa, InstrVec &instructions, 8 | PseudoInstrVec &) { 9 | using namespace TypeCA; 10 | using namespace TypeCI; 11 | using namespace TypeCSS; 12 | using namespace TypeCL; 13 | using namespace TypeCS; 14 | using namespace TypeCJ; 15 | using namespace TypeCB; 16 | using namespace TypeCB2; 17 | using namespace TypeCIW; 18 | using namespace TypeCR; 19 | using namespace TypeCR2; 20 | 21 | enableInstructions(instructions); 25 | 26 | if (isa->bits() == 32) { 27 | enableInstructions(instructions); 28 | } else { 29 | enableInstructions(instructions); 30 | } 31 | 32 | if (isa->bits() == 64) { 33 | enableInstructions(instructions); 34 | } 35 | } 36 | 37 | } // namespace ExtC 38 | } // namespace RVISA 39 | } // namespace Ripes 40 | -------------------------------------------------------------------------------- /src/isa/rv_m_ext.cpp: -------------------------------------------------------------------------------- 1 | #include "rv_m_ext.h" 2 | namespace Ripes { 3 | namespace RVISA { 4 | namespace ExtM { 5 | 6 | void enableExt(const ISAInfoBase *isa, InstrVec &instructions, 7 | PseudoInstrVec &) { 8 | using namespace TypeR; 9 | 10 | enableInstructions( 11 | instructions); 12 | 13 | if (isa->bits() == 64) { 14 | enableInstructions(instructions); 15 | } 16 | } 17 | 18 | } // namespace ExtM 19 | } // namespace RVISA 20 | } // namespace Ripes 21 | -------------------------------------------------------------------------------- /src/isa/symbolmap.cpp: -------------------------------------------------------------------------------- 1 | #include "symbolmap.h" 2 | 3 | namespace Ripes { 4 | 5 | /// Adds a symbol to the current symbol mapping of this assembler. 6 | std::optional SymbolMap::addAbsSymbol(const unsigned &line, 7 | const Symbol &s, VInt v) { 8 | if (abs.count(s)) { 9 | return {Error(line, "Multiple definitions of symbol '" + s.v + "'")}; 10 | } 11 | abs[s] = v; 12 | return {}; 13 | } 14 | 15 | std::optional SymbolMap::addRelSymbol(const unsigned &line, 16 | const Symbol &s, VInt v) { 17 | assert(s.isLocal()); 18 | auto &it = rel[s.v.toInt()]; 19 | if (it.count(line)) 20 | return {Error(line, QString::fromStdString( 21 | "Multiple definitions of relative symbol '" + 22 | std::to_string(v) + "' on line '" + 23 | std::to_string(line)))}; 24 | it[line] = v; 25 | return {}; 26 | } 27 | 28 | AbsoluteSymbolMap SymbolMap::copyRelativeTo(unsigned line, 29 | const QString &beforeSuffix, 30 | const QString &afterSuffix) const { 31 | AbsoluteSymbolMap res = abs; 32 | 33 | for (auto &relSymbols : rel) { 34 | auto ub = relSymbols.second.upper_bound(line); 35 | if (ub != relSymbols.second.end()) 36 | res[QString::number(relSymbols.first) + afterSuffix] = ub->second; 37 | 38 | if (ub != relSymbols.second.begin()) { 39 | auto lb = ub; 40 | std::advance(lb, -1); 41 | res[QString::number(relSymbols.first) + beforeSuffix] = lb->second; 42 | } 43 | } 44 | 45 | return res; 46 | } 47 | 48 | } // namespace Ripes 49 | -------------------------------------------------------------------------------- /src/loaddialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | QT_FORWARD_DECLARE_CLASS(QButtonGroup); 5 | QT_FORWARD_DECLARE_CLASS(QFile); 6 | 7 | #include "assembler/program.h" 8 | 9 | namespace ELFIO { 10 | class elfio; 11 | } 12 | 13 | namespace Ripes { 14 | 15 | struct ELFInfo { 16 | bool valid; 17 | QString errorMessage; 18 | QString entryPoint; 19 | }; 20 | 21 | namespace Ui { 22 | class LoadDialog; 23 | } 24 | 25 | class LoadDialog : public QDialog { 26 | Q_OBJECT 27 | 28 | public: 29 | explicit LoadDialog(QWidget *parent = nullptr); 30 | ~LoadDialog(); 31 | 32 | void accept() override; 33 | const LoadFileParams &getParams() const { return m_params; } 34 | 35 | /** 36 | * @brief validateELFFile 37 | * Validates the given elf file @p file based on the currently loaded 38 | * processor 39 | */ 40 | static ELFInfo validateELFFile(const QFile &file); 41 | 42 | private slots: 43 | void validateCurrentFile(); 44 | void openFileButtonTriggered(); 45 | void inputTypeChanged(); 46 | 47 | void updateSourcePageState(); 48 | void updateBinaryPageState(); 49 | void updateELFPageState(); 50 | 51 | void loadFileError(const QString &filename); 52 | 53 | private: 54 | enum TypeButtonID { Source, Flatbinary, ELF }; 55 | static TypeButtonID s_typeIndex; 56 | static QString s_filePath; 57 | 58 | void setElfInfo(const ELFInfo &info); 59 | bool fileTypeValidate(const QFile &file); 60 | bool validateSourceFile(const QFile &file); 61 | bool validateBinaryFile(const QFile &file); 62 | 63 | void paletteValidate(QWidget *w, bool valid); 64 | 65 | TypeButtonID m_currentType = ELF; 66 | LoadFileParams m_params; 67 | 68 | Ui::LoadDialog *m_ui = nullptr; 69 | QButtonGroup *m_fileTypeButtons = nullptr; 70 | }; // namespace Ripes 71 | 72 | } // namespace Ripes 73 | -------------------------------------------------------------------------------- /src/mainwindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "assembler/program.h" 6 | #include "statusmanager.h" 7 | 8 | QT_FORWARD_DECLARE_CLASS(QToolBar) 9 | QT_FORWARD_DECLARE_CLASS(QStackedWidget) 10 | QT_FORWARD_DECLARE_CLASS(QActionGroup) 11 | 12 | namespace Ripes { 13 | namespace Ui { 14 | class MainWindow; 15 | } 16 | 17 | class EditTab; 18 | class MemoryTab; 19 | class ProcessorTab; 20 | class CacheTab; 21 | class IOTab; 22 | class ProcessorHandler; 23 | class RipesTab; 24 | struct LoadFileParams; 25 | 26 | struct TabWidgets { 27 | RipesTab *tab; 28 | QToolBar *toolbar; 29 | }; 30 | 31 | class MainWindow : public QMainWindow { 32 | Q_OBJECT 33 | 34 | enum TabIndex { 35 | EditTabID, 36 | ProcessorTabID, 37 | CacheTabID, 38 | MemoryTabID, 39 | IOTabID, 40 | NTabsID 41 | }; 42 | 43 | public: 44 | explicit MainWindow(QWidget *parent = nullptr); 45 | ~MainWindow() override; 46 | 47 | void closeEvent(QCloseEvent *event) override; 48 | void fitToView(); 49 | 50 | signals: 51 | void prepareSave(); 52 | 53 | private slots: 54 | void wiki(); 55 | void version(); 56 | 57 | void loadFileTriggered(); 58 | 59 | void saveFilesTriggered(); 60 | void saveFilesAsTriggered(); 61 | void newProgramTriggered(); 62 | void settingsTriggered(); 63 | void tabChanged(int index); 64 | 65 | private: 66 | void loadFile(const QString &filename, SourceType type); 67 | 68 | void setupStatusBar(); 69 | void setupMenus(); 70 | void setupExamplesMenu(QMenu *parent); 71 | 72 | Ui::MainWindow *m_ui = nullptr; 73 | QActionGroup *m_binaryStoreAction; 74 | QToolBar *m_toolbar = nullptr; 75 | 76 | // Tabs 77 | QStackedWidget *m_stackedTabs = nullptr; 78 | std::map m_tabWidgets; 79 | TabIndex m_currentTabID = ProcessorTabID; 80 | }; 81 | } // namespace Ripes 82 | -------------------------------------------------------------------------------- /src/memorymodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "radix.h" 6 | 7 | namespace Ripes { 8 | 9 | class MemoryModel : public QAbstractTableModel { 10 | Q_OBJECT 11 | public: 12 | enum Column { Address = 0, WordValue = 1, FIXED_COLUMNS_CNT }; 13 | MemoryModel(QObject *parent = nullptr); 14 | 15 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 16 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 17 | 18 | QVariant data(const QModelIndex &index, 19 | int role = Qt::DisplayRole) const override; 20 | QVariant headerData(int section, Qt::Orientation orientation, 21 | int role = Qt::DisplayRole) const override; 22 | 23 | Qt::ItemFlags flags(const QModelIndex &index) const override; 24 | 25 | void setRadix(Radix r); 26 | Radix getRadix() const { return m_radix; } 27 | 28 | public slots: 29 | void processorWasClocked(); 30 | void setRowsVisible(int rows); 31 | void offsetCentralAddress(int rowOffset); 32 | void setCentralAddress(Ripes::AInt address); 33 | 34 | private: 35 | QVariant addrData(AInt address, bool validAddress) const; 36 | QVariant byteData(AInt address, AInt byteOffset, bool validAddress) const; 37 | QVariant wordData(AInt address, bool validAddress) const; 38 | QVariant fgColorData(AInt address, AInt byteOffset, bool validAddress) const; 39 | 40 | Radix m_radix = Radix::Hex; 41 | 42 | AInt m_centralAddress = 0; // Memory address at the center of the model 43 | int m_rowsVisible = 0; // Number of rows currently visible in the view 44 | // associated with the model 45 | }; 46 | } // namespace Ripes 47 | -------------------------------------------------------------------------------- /src/memorytab.cpp: -------------------------------------------------------------------------------- 1 | #include "memorytab.h" 2 | #include "ui_memorytab.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "cachesim/cachesim.h" 9 | #include "io/iomanager.h" 10 | #include "io/memorymapmodel.h" 11 | #include "processorhandler.h" 12 | 13 | namespace Ripes { 14 | 15 | MemoryTab::MemoryTab(QToolBar *toolbar, QWidget *parent) 16 | : RipesTab(toolbar, parent), m_ui(new Ui::MemoryTab) { 17 | m_ui->setupUi(this); 18 | 19 | m_ui->memoryViewerWidget->updateModel(); 20 | m_ui->memoryViewerWidget->updateView(); 21 | 22 | m_ui->memoryMapView->setModel(new MemoryMapModel(&IOManager::get(), this)); 23 | m_ui->memoryMapView->horizontalHeader()->setSectionResizeMode( 24 | MemoryMapModel::Name, QHeaderView::ResizeToContents); 25 | m_ui->memoryMapView->horizontalHeader()->setSectionResizeMode( 26 | MemoryMapModel::AddressRange, QHeaderView::Stretch); 27 | m_ui->memoryMapView->horizontalHeader()->setSectionResizeMode( 28 | MemoryMapModel::Size, QHeaderView::ResizeToContents); 29 | m_ui->splitter->setStretchFactor(0, 2); 30 | m_ui->splitter->setStretchFactor(1, 1); 31 | } 32 | 33 | MemoryTab::~MemoryTab() { delete m_ui; } 34 | 35 | void MemoryTab::setCentralAddress(unsigned int address) { 36 | m_ui->memoryViewerWidget->setCentralAddress(address); 37 | } 38 | 39 | } // namespace Ripes 40 | -------------------------------------------------------------------------------- /src/memorytab.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "memorymodel.h" 8 | #include "ripestab.h" 9 | 10 | namespace Ripes { 11 | 12 | namespace Ui { 13 | class MemoryTab; 14 | } 15 | 16 | class MemoryTab : public RipesTab { 17 | friend class CacheTabWidget; 18 | Q_OBJECT 19 | 20 | public: 21 | MemoryTab(QToolBar *toolbar, QWidget *parent = nullptr); 22 | ~MemoryTab() override; 23 | 24 | void setCentralAddress(unsigned address); 25 | 26 | private: 27 | Ui::MemoryTab *m_ui = nullptr; 28 | }; 29 | } // namespace Ripes 30 | -------------------------------------------------------------------------------- /src/memoryview.cpp: -------------------------------------------------------------------------------- 1 | #include "memoryview.h" 2 | 3 | #include "memorymodel.h" 4 | 5 | #include 6 | 7 | #include "processorhandler.h" 8 | 9 | namespace Ripes { 10 | 11 | MemoryView::MemoryView(QWidget *parent) : QTableView(parent) {} 12 | 13 | void MemoryView::wheelEvent(QWheelEvent *event) { 14 | if (event->angleDelta().y() > 0) { 15 | emit scrolled(true); 16 | } else { 17 | emit scrolled(false); 18 | } 19 | } 20 | 21 | void MemoryView::resizeEvent(QResizeEvent *event) { 22 | QTableView::resizeEvent(event); 23 | emit resized(); 24 | } 25 | } // namespace Ripes 26 | -------------------------------------------------------------------------------- /src/memoryview.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | // Extension of QTableView - catches QWheelEvents and triggers the memory model 9 | // to shift its 10 | // central address 11 | 12 | class MemoryView : public QTableView { 13 | Q_OBJECT 14 | 15 | public: 16 | MemoryView(QWidget *parent = nullptr); 17 | 18 | void wheelEvent(QWheelEvent *event) override; 19 | 20 | protected: 21 | void resizeEvent(QResizeEvent *event) override; 22 | 23 | public slots: 24 | void setVisibleRows() {} 25 | 26 | signals: 27 | void scrolled(bool dir); 28 | void resized(); 29 | 30 | private: 31 | int m_rowHeight = 0; 32 | }; 33 | } // namespace Ripes 34 | -------------------------------------------------------------------------------- /src/memoryviewerwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "isa/isa_types.h" 6 | 7 | namespace Ripes { 8 | 9 | class RadixSelectorWidget; 10 | class GoToComboBox; 11 | class MemoryModel; 12 | 13 | namespace Ui { 14 | class MemoryViewerWidget; 15 | } 16 | 17 | class MemoryViewerWidget : public QWidget { 18 | Q_OBJECT 19 | 20 | public: 21 | MemoryViewerWidget(QWidget *parent = nullptr); 22 | ~MemoryViewerWidget(); 23 | 24 | void updateModel(); 25 | 26 | MemoryModel *m_memoryModel = nullptr; 27 | 28 | public slots: 29 | void updateView(); 30 | void setCentralAddress(Ripes::AInt address); 31 | 32 | private: 33 | void setupNavigationWidgets(); 34 | 35 | Ui::MemoryViewerWidget *m_ui = nullptr; 36 | 37 | RadixSelectorWidget *m_radixSelector = nullptr; 38 | GoToComboBox *m_goToSection = nullptr; 39 | GoToComboBox *m_goToRegister = nullptr; 40 | }; 41 | } // namespace Ripes 42 | -------------------------------------------------------------------------------- /src/memoryviewerwidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ripes::MemoryViewerWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 462 10 | 300 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Form 21 | 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 0 31 | 32 | 33 | 0 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 0 42 | 0 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | MemoryView 57 | QTableView 58 |
memoryview.h
59 |
60 |
61 | 62 | 63 |
64 | -------------------------------------------------------------------------------- /src/modernize.sh: -------------------------------------------------------------------------------- 1 | for file in ./*; do 2 | clang-tidy-6.0 -checks="modernize-avoid-bind,modernize-deprecated-headers,modernize-loop-convert,modernize-make-shared,modernize-make-unique,modernize-pass-by-value,modernize-raw-string-literal,modernize-redundant-void-arg,modernize-replace-auto-ptr,modernize-shrink-to-fit,modernize-use-auto,modernize-use-bool-literals,modernize-use-default,modernize-use-emplace,modernize-use-nullptr,modernize-use-override,modernize-use-using" -fix $file -- -std=c++11 3 | done -------------------------------------------------------------------------------- /src/pipelinediagrammodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "processors/interface/ripesprocessor.h" 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | class PipelineDiagramModel : public QAbstractTableModel { 9 | Q_OBJECT 10 | public: 11 | enum Column { Breakpoint = 0, PC = 1, Stage = 2, Instruction = 3, NColumns }; 12 | PipelineDiagramModel(QObject *parent = nullptr); 13 | 14 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 15 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 16 | 17 | QVariant data(const QModelIndex &index, 18 | int role = Qt::DisplayRole) const override; 19 | QVariant headerData(int section, Qt::Orientation orientation, 20 | int role = Qt::DisplayRole) const override; 21 | void prepareForView(); 22 | 23 | /// Returns a tab-separated stringified version of this pipeline diagram. 24 | QString toString() const; 25 | 26 | public slots: 27 | void processorWasClocked(); 28 | void reset(); 29 | 30 | private: 31 | void gatherStageInfo(); 32 | 33 | /** 34 | * @brief m_cycleStageInfos 35 | * map> 36 | */ 37 | std::map> m_cycleStageInfos; 38 | 39 | /** 40 | * @brief m_atMaxCycles 41 | * Records the state that we've crossed the threshold set for 42 | * RIPES_SETTING_PIPEDIAGRAM_MAXCYCLES. This is to speed up execution by not 43 | * having to check the settings value during each cycle of simulation, after 44 | * the value has been reached. 45 | */ 46 | bool m_atMaxCycles = false; 47 | }; 48 | } // namespace Ripes 49 | -------------------------------------------------------------------------------- /src/pipelinediagramwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "pipelinediagramwidget.h" 2 | #include "ui_pipelinediagramwidget.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "pipelinediagrammodel.h" 8 | #include "ripessettings.h" 9 | 10 | namespace Ripes { 11 | 12 | PipelineDiagramWidget::PipelineDiagramWidget(PipelineDiagramModel *model, 13 | QWidget *parent) 14 | : QDialog(parent), m_ui(new Ui::PipelineDiagramWidget) { 15 | m_ui->setupUi(this); 16 | 17 | m_stageModel = model; 18 | m_ui->pipelineDiagramView->setModel(m_stageModel); 19 | 20 | m_ui->pipelineDiagramView->resizeColumnsToContents(); 21 | m_ui->copy->setIcon(QIcon(":/icons/documents.svg")); 22 | 23 | m_stageModel->prepareForView(); 24 | } 25 | 26 | PipelineDiagramWidget::~PipelineDiagramWidget() { delete m_ui; } 27 | 28 | void PipelineDiagramWidget::on_copy_clicked() { 29 | // Copy entire table to clipboard, including headers 30 | Q_ASSERT(m_stageModel != nullptr); 31 | QString textualRepr; 32 | 33 | // Copy headers 34 | textualRepr.append('\t'); 35 | for (int j = 0; j < m_stageModel->columnCount(); j++) { 36 | textualRepr.append(m_stageModel->headerData(j, Qt::Horizontal).toString()); 37 | textualRepr.append('\t'); 38 | } 39 | textualRepr.append('\n'); 40 | // Copy data 41 | for (int i = 0; i < m_stageModel->rowCount(); ++i) { 42 | textualRepr.append(m_stageModel->headerData(i, Qt::Vertical).toString()); 43 | textualRepr.append('\t'); 44 | for (int j = 0; j < m_stageModel->columnCount(); j++) { 45 | textualRepr.append( 46 | m_stageModel->data(m_stageModel->index(i, j)).toString()); 47 | textualRepr.append('\t'); 48 | } 49 | textualRepr.append('\n'); 50 | } 51 | QApplication::clipboard()->setText(textualRepr); 52 | } 53 | } // namespace Ripes 54 | -------------------------------------------------------------------------------- /src/pipelinediagramwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | QT_FORWARD_DECLARE_CLASS(QAbstractItemModel) 6 | 7 | namespace Ripes { 8 | class PipelineDiagramModel; 9 | namespace Ui { 10 | class PipelineDiagramWidget; 11 | } 12 | 13 | class PipelineDiagramWidget : public QDialog { 14 | Q_OBJECT 15 | 16 | public: 17 | PipelineDiagramWidget(PipelineDiagramModel *model, QWidget *parent = nullptr); 18 | ~PipelineDiagramWidget() override; 19 | 20 | private slots: 21 | void on_copy_clicked(); 22 | 23 | private: 24 | Ui::PipelineDiagramWidget *m_ui = nullptr; 25 | PipelineDiagramModel *m_stageModel = nullptr; 26 | }; 27 | } // namespace Ripes 28 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv5s/rv5s_exmem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "VSRTL/core/vsrtl_register.h" 5 | 6 | #include "processors/RISC-V/riscv.h" 7 | 8 | #include "../rv5s_no_fw_hz/rv5s_no_fw_hz_exmem.h" 9 | 10 | namespace vsrtl { 11 | namespace core { 12 | using namespace Ripes; 13 | 14 | template 15 | class RV5S_EXMEM : public EXMEM { 16 | public: 17 | RV5S_EXMEM(const std::string &name, SimComponent *parent) 18 | : EXMEM(name, parent) { 19 | // We want stalling info to persist through clearing of the register, so 20 | // stalled register is always enabled and never cleared. 21 | CONNECT_REGISTERED_CLEN_INPUT(stalled, 0, 1); 22 | } 23 | 24 | REGISTERED_CLEN_INPUT(stalled, 1); 25 | }; 26 | 27 | } // namespace core 28 | } // namespace vsrtl 29 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv5s/rv5s_idex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "VSRTL/core/vsrtl_constant.h" 5 | #include "VSRTL/core/vsrtl_register.h" 6 | 7 | #include "processors/RISC-V/riscv.h" 8 | 9 | #include "../rv5s_no_fw_hz/rv5s_no_fw_hz_idex.h" 10 | 11 | namespace vsrtl { 12 | namespace core { 13 | using namespace Ripes; 14 | 15 | /** 16 | * @brief The RV5S_IDEX class 17 | * A specialization of the default IDEX stage separating register utilized by 18 | * the rv5s_no_fw_hz processor. Storage of register read indices is added, which 19 | * are required by the forwarding unit. 20 | */ 21 | template 22 | class RV5S_IDEX : public IDEX { 23 | public: 24 | RV5S_IDEX(const std::string &name, SimComponent *parent) 25 | : IDEX(name, parent) { 26 | CONNECT_REGISTERED_CLEN_INPUT(rd_reg1_idx, this->clear, this->enable); 27 | CONNECT_REGISTERED_CLEN_INPUT(rd_reg2_idx, this->clear, this->enable); 28 | CONNECT_REGISTERED_CLEN_INPUT(opcode, this->clear, this->enable); 29 | 30 | // We want stalling info to persist through clearing of the register, so 31 | // stalled register is always enabled and never cleared. 32 | CONNECT_REGISTERED_CLEN_INPUT(stalled, 0, 1); 33 | } 34 | 35 | REGISTERED_CLEN_INPUT(rd_reg1_idx, c_RVRegsBits); 36 | REGISTERED_CLEN_INPUT(rd_reg2_idx, c_RVRegsBits); 37 | REGISTERED_CLEN_INPUT(opcode, enumBitWidth()); 38 | 39 | REGISTERED_CLEN_INPUT(stalled, 1); 40 | }; 41 | 42 | } // namespace core 43 | } // namespace vsrtl 44 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv5s/rv5s_memwb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "VSRTL/core/vsrtl_register.h" 5 | 6 | #include "processors/RISC-V/riscv.h" 7 | 8 | #include "../rv5s_no_fw_hz/rv5s_no_fw_hz_memwb.h" 9 | 10 | namespace vsrtl { 11 | namespace core { 12 | using namespace Ripes; 13 | 14 | template 15 | class RV5S_MEMWB : public MEMWB { 16 | public: 17 | RV5S_MEMWB(const std::string &name, SimComponent *parent) 18 | : MEMWB(name, parent) { 19 | CONNECT_REGISTERED_INPUT(stalled); 20 | } 21 | 22 | REGISTERED_INPUT(stalled, 1); 23 | }; 24 | 25 | } // namespace core 26 | } // namespace vsrtl 27 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv5s_no_fw/rv5s_no_fw_idex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "VSRTL/core/vsrtl_constant.h" 5 | #include "VSRTL/core/vsrtl_register.h" 6 | 7 | #include "processors/RISC-V/riscv.h" 8 | 9 | #include "../rv5s_no_fw_hz/rv5s_no_fw_hz_idex.h" 10 | 11 | namespace vsrtl { 12 | namespace core { 13 | using namespace Ripes; 14 | 15 | /** 16 | * @brief The RV5S_NO_FW_IDEX class 17 | * A specialization of the default IDEX stage separating register utilized by 18 | * the rv5s_no_fw processor. 19 | */ 20 | template 21 | class RV5S_NO_FW_IDEX : public IDEX { 22 | public: 23 | RV5S_NO_FW_IDEX(const std::string &name, SimComponent *parent) 24 | : IDEX(name, parent) { 25 | CONNECT_REGISTERED_CLEN_INPUT(opcode, this->clear, this->enable); 26 | 27 | // We want stalling info to persist through clearing of the register, so 28 | // stalled register is always enabled and never cleared. 29 | CONNECT_REGISTERED_CLEN_INPUT(stalled, 0, 1); 30 | } 31 | 32 | REGISTERED_CLEN_INPUT(opcode, enumBitWidth()); 33 | REGISTERED_CLEN_INPUT(stalled, 1); 34 | }; 35 | 36 | } // namespace core 37 | } // namespace vsrtl 38 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz_ifid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "VSRTL/core/vsrtl_register.h" 5 | 6 | #include "processors/RISC-V/riscv.h" 7 | 8 | namespace vsrtl { 9 | namespace core { 10 | using namespace Ripes; 11 | 12 | template 13 | class IFID : public Component { 14 | public: 15 | IFID(const std::string &name, SimComponent *parent) 16 | : Component(name, parent) { 17 | setDescription( 18 | "Instruction fetch/Instruction decode stage separating register"); 19 | CONNECT_REGISTERED_CLEN_INPUT(pc4, clear, enable); 20 | CONNECT_REGISTERED_CLEN_INPUT(pc, clear, enable); 21 | CONNECT_REGISTERED_CLEN_INPUT(instr, clear, enable); 22 | CONNECT_REGISTERED_CLEN_INPUT(valid, clear, enable); 23 | } 24 | 25 | REGISTERED_CLEN_INPUT(pc4, XLEN); 26 | REGISTERED_CLEN_INPUT(instr, c_RVInstrWidth); 27 | REGISTERED_CLEN_INPUT(pc, XLEN); 28 | 29 | // Register controls 30 | INPUTPORT(enable, 1); 31 | INPUTPORT(clear, 1); 32 | 33 | // Valid signal. False when the register bank has been cleared. May be used by 34 | // UI to determine whether the NOP in the stage is a user-inserted nop or the 35 | // result of some pipeline action. 36 | REGISTERED_CLEN_INPUT(valid, 1); 37 | }; 38 | 39 | } // namespace core 40 | } // namespace vsrtl 41 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz_memwb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "VSRTL/core/vsrtl_register.h" 5 | 6 | #include "processors/RISC-V/riscv.h" 7 | 8 | namespace vsrtl { 9 | namespace core { 10 | using namespace Ripes; 11 | 12 | template 13 | class MEMWB : public Component { 14 | public: 15 | MEMWB(const std::string &name, SimComponent *parent) 16 | : Component(name, parent) { 17 | setDescription("Memory/write-back stage separating register"); 18 | CONNECT_REGISTERED_INPUT(pc); 19 | CONNECT_REGISTERED_INPUT(pc4); 20 | CONNECT_REGISTERED_INPUT(alures); 21 | CONNECT_REGISTERED_INPUT(mem_read); 22 | 23 | CONNECT_REGISTERED_INPUT(reg_wr_src_ctrl); 24 | CONNECT_REGISTERED_INPUT(wr_reg_idx); 25 | CONNECT_REGISTERED_INPUT(reg_do_write); 26 | 27 | CONNECT_REGISTERED_INPUT(valid); 28 | } 29 | 30 | // Data 31 | REGISTERED_INPUT(pc, XLEN); 32 | REGISTERED_INPUT(pc4, XLEN); 33 | REGISTERED_INPUT(alures, XLEN); 34 | REGISTERED_INPUT(mem_read, XLEN); 35 | 36 | // Control 37 | REGISTERED_INPUT(reg_wr_src_ctrl, enumBitWidth()); 38 | REGISTERED_INPUT(wr_reg_idx, c_RVRegsBits); 39 | REGISTERED_INPUT(reg_do_write, 1); 40 | 41 | // Valid signal. False when the register bank has been cleared. May be used by 42 | // UI to determine whether the NOP in the stage is a user-inserted nop or the 43 | // result of some pipeline action. 44 | REGISTERED_INPUT(valid, 1); 45 | }; 46 | 47 | } // namespace core 48 | } // namespace vsrtl 49 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv6s_dual/rv6s_dual_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "processors/RISC-V/riscv.h" 4 | 5 | namespace Ripes { 6 | enum class RegWrSrcDual { ALURES, PC4 }; 7 | enum class RegWrSrcDataDual { ALURES, MEM }; 8 | enum class PcSrcDual { PC4, PC8 }; 9 | enum class WaySrc { WAY1, WAY2 }; 10 | } // namespace Ripes 11 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv6s_dual/rv6s_dual_exmem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../rv5s/rv5s_exmem.h" 4 | #include "rv6s_dual_common.h" 5 | 6 | namespace vsrtl { 7 | namespace core { 8 | using namespace Ripes; 9 | 10 | template 11 | class RV5S_EXMEM_DUAL : public RV5S_EXMEM { 12 | public: 13 | RV5S_EXMEM_DUAL(const std::string &name, SimComponent *parent) 14 | : RV5S_EXMEM(name, parent) { 15 | CONNECT_REGISTERED_CLEN_INPUT(wr_reg_idx_data, this->clear, this->enable); 16 | CONNECT_REGISTERED_CLEN_INPUT(reg_do_write_data, this->clear, this->enable); 17 | CONNECT_REGISTERED_CLEN_INPUT(reg_wr_src_ctrl_dual, this->clear, 18 | this->enable); 19 | CONNECT_REGISTERED_CLEN_INPUT(reg_wr_src_ctrl_data, this->clear, 20 | this->enable); 21 | CONNECT_REGISTERED_CLEN_INPUT(pc_data, this->clear, this->enable); 22 | CONNECT_REGISTERED_CLEN_INPUT(alures_data, this->clear, this->enable); 23 | CONNECT_REGISTERED_CLEN_INPUT(exec_valid, this->clear, this->enable); 24 | CONNECT_REGISTERED_CLEN_INPUT(data_valid, this->clear, this->enable); 25 | } 26 | 27 | REGISTERED_CLEN_INPUT(wr_reg_idx_data, c_RVRegsBits); 28 | REGISTERED_CLEN_INPUT(reg_do_write_data, 1); 29 | REGISTERED_CLEN_INPUT(reg_wr_src_ctrl_dual, enumBitWidth()); 30 | REGISTERED_CLEN_INPUT(reg_wr_src_ctrl_data, enumBitWidth()); 31 | REGISTERED_CLEN_INPUT(pc_data, XLEN); 32 | 33 | REGISTERED_CLEN_INPUT(alures_data, XLEN); 34 | 35 | REGISTERED_CLEN_INPUT(exec_valid, 1); 36 | REGISTERED_CLEN_INPUT(data_valid, 1); 37 | }; 38 | 39 | } // namespace core 40 | } // namespace vsrtl 41 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv6s_dual/rv6s_dual_ifid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../rv5s_no_fw_hz/rv5s_no_fw_hz_ifid.h" 4 | 5 | #include "rv6s_dual_common.h" 6 | 7 | namespace vsrtl { 8 | namespace core { 9 | using namespace Ripes; 10 | 11 | template 12 | class IFID_DUAL : public IFID { 13 | public: 14 | IFID_DUAL(const std::string &name, SimComponent *parent) 15 | : IFID(name, parent) { 16 | CONNECT_REGISTERED_CLEN_INPUT(instr2, this->clear, this->enable); 17 | CONNECT_REGISTERED_CLEN_INPUT(instrsize1, this->clear, this->enable); 18 | CONNECT_REGISTERED_CLEN_INPUT(instrsize2, this->clear, this->enable); 19 | } 20 | 21 | REGISTERED_CLEN_INPUT(instr2, c_RVInstrWidth); 22 | REGISTERED_CLEN_INPUT(instrsize1, XLEN); 23 | REGISTERED_CLEN_INPUT(instrsize2, XLEN); 24 | }; 25 | 26 | } // namespace core 27 | } // namespace vsrtl 28 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv6s_dual/rv6s_dual_instr_mem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_memory.h" 4 | 5 | namespace vsrtl { 6 | namespace core { 7 | 8 | /** 9 | * @brief ROM_DUAL 10 | * Specialization of a rom, which outputs mem[addr] and mem[addr + addrWidth] on 11 | * each cycle. 12 | */ 13 | template 15 | class ROM_DUAL : public ROM { 16 | public: 17 | ROM_DUAL(const std::string &name, SimComponent *parent) 18 | : ROM(name, parent) { 19 | data_out2 << [=] { 20 | auto _addr = this->addr.uValue() + 4; 21 | auto val = this->read( 22 | _addr, dataWidth / CHAR_BIT, 23 | ceillog2((byteIndexed ? addrWidth : dataWidth) / CHAR_BIT)); 24 | return val; 25 | }; 26 | } 27 | 28 | OUTPUTPORT(data_out2, dataWidth); 29 | }; 30 | 31 | } // namespace core 32 | } // namespace vsrtl 33 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv6s_dual/rv6s_dual_memwb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../rv5s/rv5s_memwb.h" 4 | #include "rv6s_dual_common.h" 5 | 6 | #include "VSRTL/interface/vsrtl_interface.h" 7 | 8 | namespace vsrtl { 9 | namespace core { 10 | using namespace Ripes; 11 | 12 | template 13 | class RV5S_MEMWB_DUAL : public RV5S_MEMWB { 14 | public: 15 | RV5S_MEMWB_DUAL(const std::string &name, SimComponent *parent) 16 | : RV5S_MEMWB(name, parent) { 17 | CONNECT_REGISTERED_INPUT(wr_reg_idx_data); 18 | CONNECT_REGISTERED_INPUT(reg_do_write_data); 19 | CONNECT_REGISTERED_INPUT(reg_wr_src_ctrl_dual); 20 | CONNECT_REGISTERED_INPUT(reg_wr_src_ctrl_data); 21 | CONNECT_REGISTERED_INPUT(pc_data); 22 | CONNECT_REGISTERED_INPUT(exec_valid); 23 | CONNECT_REGISTERED_INPUT(data_valid); 24 | CONNECT_REGISTERED_INPUT(alures_data); 25 | } 26 | 27 | REGISTERED_INPUT(wr_reg_idx_data, c_RVRegsBits); 28 | REGISTERED_INPUT(reg_do_write_data, 1); 29 | REGISTERED_INPUT(reg_wr_src_ctrl_dual, enumBitWidth()); 30 | REGISTERED_INPUT(reg_wr_src_ctrl_data, enumBitWidth()); 31 | REGISTERED_INPUT(pc_data, XLEN); 32 | REGISTERED_INPUT(alures_data, XLEN); 33 | 34 | // Valid signals for each way (not register clearing) 35 | REGISTERED_INPUT(exec_valid, 1); 36 | REGISTERED_INPUT(data_valid, 1); 37 | }; 38 | 39 | } // namespace core 40 | } // namespace vsrtl 41 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv_branch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "riscv.h" 5 | 6 | namespace vsrtl { 7 | namespace core { 8 | using namespace Ripes; 9 | 10 | template 11 | class Branch : public Component { 12 | public: 13 | Branch(const std::string &name, SimComponent *parent) 14 | : Component(name, parent) { 15 | // clang-format off 16 | res << [=] { 17 | switch(comp_op.eValue()){ 18 | case CompOp::NOP: return false; 19 | case CompOp::EQ: return op1.uValue() == op2.uValue(); 20 | case CompOp::NE: return op1.uValue() != op2.uValue(); 21 | case CompOp::LT: return op1.sValue() < op2.sValue(); 22 | case CompOp::LTU: return op1.uValue() < op2.uValue(); 23 | case CompOp::GE: return op1.sValue() >= op2.sValue(); 24 | case CompOp::GEU: return op1.uValue() >= op2.uValue(); 25 | default: assert("Comparator: Unknown comparison operator"); return false; 26 | } 27 | }; 28 | // clang-format on 29 | } 30 | 31 | INPUTPORT_ENUM(comp_op, CompOp); 32 | INPUTPORT(op1, XLEN); 33 | INPUTPORT(op2, XLEN); 34 | OUTPUTPORT(res, 1); 35 | }; 36 | 37 | } // namespace core 38 | } // namespace vsrtl 39 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rv_instrparser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../binutils.h" 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Ripes { 9 | 10 | template 11 | using decode_functor = std::function(T)>; 12 | 13 | template 14 | decode_functor generateInstrParser(const std::vector &bitFields) { 15 | constexpr int size_bits = sizeof(T) * CHAR_BIT; 16 | static_assert(isPowerOf2(size_bits) && size_bits >= 32, 17 | "Invalid word size parameter"); 18 | // Generates functors that can decode a binary number based on the input 19 | // vector which is supplied upon generation 20 | assert(std::accumulate(bitFields.begin(), bitFields.end(), 0) == size_bits && 21 | "Requested word parsing format is not T-bits in length"); 22 | 23 | // Generate vector of 24 | std::vector> parseVector; 25 | 26 | // Generate bit masks and fill parse vector 27 | for (const auto &field : bitFields) { 28 | parseVector.emplace_back(field, vsrtl::generateBitmask(field)); 29 | } 30 | 31 | // Create parse functor 32 | decode_functor instrParser = [=](T word) { 33 | std::vector parsedWord; 34 | for (const auto &field : parseVector) { 35 | parsedWord.insert(parsedWord.begin(), word & field.second); 36 | word = word >> field.first; 37 | } 38 | return parsedWord; 39 | }; 40 | 41 | return instrParser; 42 | } 43 | 44 | } // namespace Ripes 45 | -------------------------------------------------------------------------------- /src/processors/RISC-V/rvss/rv_decodeRVC.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VSRTL/core/vsrtl_component.h" 4 | #include "processors/RISC-V/riscv.h" 5 | #include "processors/RISC-V/rv_decode.h" 6 | #include "processors/RISC-V/rv_uncompress.h" 7 | 8 | namespace vsrtl { 9 | namespace core { 10 | using namespace Ripes; 11 | 12 | template 13 | class DecodeRVC : public Component { 14 | public: 15 | void setISA(const std::shared_ptr &isa) { 16 | decode->setISA(isa); 17 | uncompress->setISA(isa); 18 | } 19 | 20 | DecodeRVC(std::string name, SimComponent *parent) : Component(name, parent) { 21 | instr >> uncompress->instr; 22 | 23 | uncompress->Pc_Inc >> Pc_Inc; 24 | uncompress->exp_instr >> decode->instr; 25 | uncompress->exp_instr >> exp_instr; 26 | 27 | decode->opcode >> opcode; 28 | decode->wr_reg_idx >> wr_reg_idx; 29 | decode->r1_reg_idx >> r1_reg_idx; 30 | decode->r2_reg_idx >> r2_reg_idx; 31 | } 32 | 33 | SUBCOMPONENT(decode, TYPE(Decode)); 34 | SUBCOMPONENT(uncompress, TYPE(Uncompress)); 35 | 36 | INPUTPORT(instr, c_RVInstrWidth); 37 | OUTPUTPORT_ENUM(opcode, RVInstr); 38 | OUTPUTPORT(wr_reg_idx, c_RVRegsBits); 39 | OUTPUTPORT(r1_reg_idx, c_RVRegsBits); 40 | OUTPUTPORT(r2_reg_idx, c_RVRegsBits); 41 | OUTPUTPORT(Pc_Inc, 1); 42 | OUTPUTPORT(exp_instr, c_RVInstrWidth); 43 | }; 44 | 45 | } // namespace core 46 | } // namespace vsrtl 47 | -------------------------------------------------------------------------------- /src/processors/layouts.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | RISC-V/rvss/rv_ss_extended_layout.json 4 | RISC-V/rvss/rv_ss_standard_layout.json 5 | RISC-V/rv5s/rv5s_standard_layout.json 6 | RISC-V/rv5s/rv5s_extended_layout.json 7 | RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz_standard_layout.json 8 | RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz_extended_layout.json 9 | RISC-V/rv5s_no_hz/rv5s_no_hz_standard_layout.json 10 | RISC-V/rv5s_no_hz/rv5s_no_hz_extended_layout.json 11 | RISC-V/rv5s_no_fw/rv5s_no_fw_standard_layout.json 12 | RISC-V/rv5s_no_fw/rv5s_no_fw_extended_layout.json 13 | RISC-V/rv6s_dual/rv6s_dual_extended_layout.json 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/processorselectiondialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "processorregistry.h" 7 | 8 | namespace Ripes { 9 | 10 | namespace Ui { 11 | class ProcessorSelectionDialog; 12 | } 13 | 14 | class ProcessorSelectionDialog : public QDialog { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit ProcessorSelectionDialog(QWidget *parent = nullptr); 19 | ~ProcessorSelectionDialog(); 20 | 21 | ProcessorID getSelectedId() const { return m_selectedID; } 22 | RegisterInitialization getRegisterInitialization() const; 23 | const Layout *getSelectedLayout() const; 24 | QStringList getEnabledExtensions() const; 25 | 26 | private slots: 27 | void selectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); 28 | 29 | private: 30 | bool isCPUItem(const QTreeWidgetItem *item) const; 31 | 32 | enum ProcessorTreeColums { ProcessorColumn, ColumnCount }; 33 | ProcessorID m_selectedID; 34 | Ui::ProcessorSelectionDialog *m_ui; 35 | std::map m_selectedExtensionsForID; 36 | }; 37 | } // namespace Ripes 38 | -------------------------------------------------------------------------------- /src/radix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "isa/isa_defines.h" 12 | #include "isa/isa_types.h" 13 | 14 | namespace Ripes { 15 | 16 | const static std::map s_radixName = { 17 | {Radix::Hex, "Hex"}, {Radix::Binary, "Binary"}, 18 | {Radix::Unsigned, "Unsigned"}, {Radix::Signed, "Signed"}, 19 | {Radix::ASCII, "ASCII"}, {Radix::Float, "Float"}}; 20 | 21 | static const auto hexRegex = QRegularExpression("0[xX][0-9a-fA-F]+"); 22 | static const auto hexRegex16 = QRegularExpression("0[xX][0-9a-fA-F]{0,4}"); 23 | static const auto hexRegex32 = QRegularExpression("0[xX][0-9a-fA-F]{0,8}"); 24 | static const auto hexRegex64 = QRegularExpression("0[xX][0-9a-fA-F]{0,16}"); 25 | static const auto binRegex = QRegularExpression("0[bB][0-1]+"); 26 | static const auto unsignedRegex = QRegularExpression("[0-9]+"); 27 | static const auto signedRegex = QRegularExpression("[-]*[0-9]+"); 28 | static const auto floatRegex = QRegularExpression("[-]*[0-9]+\\.[0-9]+"); 29 | 30 | void setISADepRegex(QRegularExpressionValidator *validator); 31 | QString encodeRadixValue(VInt value, const Radix type, unsigned byteWidth); 32 | VInt decodeRadixValue(QString value, bool *ok = nullptr); 33 | 34 | } // namespace Ripes 35 | 36 | Q_DECLARE_METATYPE(Ripes::Radix); 37 | -------------------------------------------------------------------------------- /src/radixselectorwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "radixselectorwidget.h" 2 | #include "ui_radixselectorwidget.h" 3 | 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | RadixSelectorWidget::RadixSelectorWidget(QWidget *parent) 9 | : QWidget(parent), m_ui(new Ui::RadixSelectorWidget) { 10 | m_ui->setupUi(this); 11 | setupRadixComboBox(); 12 | } 13 | 14 | RadixSelectorWidget::~RadixSelectorWidget() { delete m_ui; } 15 | 16 | void RadixSelectorWidget::setRadix(Radix r) { 17 | for (int i = 0; i < m_ui->displayType->count(); ++i) { 18 | const Radix itemRadix = 19 | qvariant_cast(m_ui->displayType->itemData(i)); 20 | if (r == itemRadix) { 21 | m_ui->displayType->setCurrentIndex(i); 22 | return; 23 | } 24 | } 25 | Q_UNREACHABLE(); 26 | } 27 | 28 | void RadixSelectorWidget::setupRadixComboBox() { 29 | for (const auto &rt : s_radixName) { 30 | m_ui->displayType->addItem(rt.second, QVariant::fromValue(rt.first)); 31 | } 32 | 33 | connect(m_ui->displayType, 34 | QOverload::of(&QComboBox::currentIndexChanged), this, 35 | [=](int index) { 36 | const Radix r = 37 | qvariant_cast(m_ui->displayType->itemData(index)); 38 | emit radixChanged(r); 39 | }); 40 | } 41 | } // namespace Ripes 42 | -------------------------------------------------------------------------------- /src/radixselectorwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "radix.h" 6 | 7 | namespace Ripes { 8 | 9 | namespace Ui { 10 | class RadixSelectorWidget; 11 | } 12 | 13 | class RadixSelectorWidget : public QWidget { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit RadixSelectorWidget(QWidget *parent = nullptr); 18 | ~RadixSelectorWidget(); 19 | void setupRadixComboBox(); 20 | void setRadix(Radix r); 21 | 22 | signals: 23 | void radixChanged(Ripes::Radix r); 24 | 25 | private: 26 | Ui::RadixSelectorWidget *m_ui = nullptr; 27 | }; 28 | } // namespace Ripes 29 | -------------------------------------------------------------------------------- /src/radixselectorwidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ripes::RadixSelectorWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 199 10 | 27 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | 33 | 34 | Display type: 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/registercontainerwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "registercontainerwidget.h" 2 | #include "ui_registercontainerwidget.h" 3 | 4 | #include "processorhandler.h" 5 | #include "registerwidget.h" 6 | 7 | namespace Ripes { 8 | 9 | RegisterContainerWidget::RegisterContainerWidget(QWidget *parent) 10 | : QWidget(parent), m_ui(new Ui::RegisterContainerWidget) { 11 | m_ui->setupUi(this); 12 | connect(ProcessorHandler::get(), &ProcessorHandler::procStateChangedNonRun, 13 | this, &RegisterContainerWidget::updateView); 14 | connect(ProcessorHandler::get(), &ProcessorHandler::processorChanged, this, 15 | &RegisterContainerWidget::initialize); 16 | initialize(); 17 | } 18 | 19 | RegisterContainerWidget::~RegisterContainerWidget() { delete m_ui; } 20 | 21 | void RegisterContainerWidget::initialize() { 22 | m_ui->tabWidget->clear(); 23 | 24 | for (const auto ®File : 25 | ProcessorHandler::getProcessor()->implementsISA()->regInfoMap()) { 26 | auto rfid = regFile.second->regFileName(); 27 | auto regDesc = regFile.second->regFileDesc(); 28 | auto registerWidget = new RegisterWidget(rfid, this); 29 | const unsigned tabIdx = m_ui->tabWidget->count(); 30 | m_ui->tabWidget->insertTab(tabIdx, registerWidget, QString(rfid.data())); 31 | m_ui->tabWidget->setTabToolTip(tabIdx, QString(regDesc.data())); 32 | registerWidget->initialize(); 33 | } 34 | updateView(); 35 | } 36 | 37 | void RegisterContainerWidget::updateView() { 38 | for (int i = 0; i < m_ui->tabWidget->count(); ++i) { 39 | if (auto *regWidget = 40 | dynamic_cast(m_ui->tabWidget->widget(i))) { 41 | regWidget->updateView(); 42 | } 43 | } 44 | } 45 | 46 | } // namespace Ripes 47 | -------------------------------------------------------------------------------- /src/registercontainerwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | 7 | namespace Ui { 8 | class RegisterContainerWidget; 9 | } 10 | 11 | class RegisterContainerWidget : public QWidget { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit RegisterContainerWidget(QWidget *parent = nullptr); 16 | ~RegisterContainerWidget(); 17 | 18 | private: 19 | void initialize(); 20 | void updateView(); 21 | Ui::RegisterContainerWidget *m_ui; 22 | }; 23 | 24 | } // namespace Ripes 25 | -------------------------------------------------------------------------------- /src/registercontainerwidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ripes::RegisterContainerWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | 33 | Tab 1 34 | 35 | 36 | 37 | 38 | Tab 2 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/registermodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "processors/interface/ripesprocessor.h" 9 | #include "radix.h" 10 | 11 | namespace Ripes { 12 | 13 | class RegisterModel : public QAbstractTableModel { 14 | Q_OBJECT 15 | public: 16 | enum Column { Name, Alias, Value, NColumns }; 17 | RegisterModel(const std::string_view &rft, QObject *parent = nullptr); 18 | 19 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 20 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 21 | 22 | QVariant data(const QModelIndex &index, 23 | int role = Qt::DisplayRole) const override; 24 | QVariant headerData(int section, Qt::Orientation orientation, 25 | int role = Qt::DisplayRole) const override; 26 | 27 | bool setData(const QModelIndex &index, const QVariant &value, 28 | int role) override; 29 | Qt::ItemFlags flags(const QModelIndex &index) const override; 30 | 31 | void setRadix(Radix r); 32 | Radix getRadix() const { return m_radix; } 33 | 34 | public slots: 35 | void processorWasClocked(); 36 | 37 | signals: 38 | /** 39 | * @brief registerChanged 40 | * Emitted whenever the value of register @param i changes 41 | */ 42 | void registerChanged(unsigned i); 43 | 44 | private: 45 | std::vector gatherRegisterValues(); 46 | 47 | QVariant nameData(unsigned idx) const; 48 | QVariant aliasData(unsigned idx) const; 49 | QVariant valueData(unsigned idx) const; 50 | QVariant tooltipData(unsigned idx) const; 51 | VInt registerData(unsigned idx) const; 52 | 53 | Radix m_radix = Radix::Hex; 54 | unsigned m_regBytes; 55 | std::string_view m_rft; 56 | 57 | int m_mostRecentlyModifiedReg = -1; 58 | std::vector m_regValues; 59 | }; 60 | } // namespace Ripes 61 | -------------------------------------------------------------------------------- /src/registerwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "processors/interface/ripesprocessor.h" 6 | 7 | namespace Ripes { 8 | class RegisterModel; 9 | 10 | namespace Ui { 11 | class RegisterWidget; 12 | } 13 | 14 | class RegisterWidget : public QWidget { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit RegisterWidget(const std::string_view ®FileID, 19 | QWidget *parent = nullptr); 20 | ~RegisterWidget(); 21 | 22 | void initialize(); 23 | 24 | public slots: 25 | void updateView(); 26 | void setRegisterviewCenterIndex(int index); 27 | 28 | private: 29 | void showContextMenu(const QPoint &pos); 30 | Ui::RegisterWidget *m_ui = nullptr; 31 | RegisterModel *m_model = nullptr; 32 | const std::string_view m_regFileName; 33 | }; 34 | } // namespace Ripes 35 | -------------------------------------------------------------------------------- /src/registerwidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ripes::RegisterWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | RadixSelectorWidget 32 | QWidget 33 |
radixselectorwidget.h
34 | 1 35 |
36 |
37 | 38 | 39 |
40 | -------------------------------------------------------------------------------- /src/ripestab.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | class RipesTab : public QWidget { 9 | public: 10 | RipesTab(QToolBar *toolbar, QWidget *parent = nullptr) 11 | : QWidget(parent), m_toolbar(toolbar) {} 12 | QToolBar *getToolbar() { return m_toolbar; } 13 | virtual void tabVisibilityChanged(bool visible) { Q_UNUSED(visible); }; 14 | 15 | protected: 16 | QToolBar *m_toolbar = nullptr; 17 | }; 18 | } // namespace Ripes 19 | -------------------------------------------------------------------------------- /src/savedialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "program.h" 4 | #include "ripessettings.h" 5 | #include 6 | 7 | namespace Ripes { 8 | 9 | namespace Ui { 10 | class SaveDialog; 11 | } 12 | 13 | class SaveDialog : public QDialog { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit SaveDialog(SourceType sourceType, QWidget *parent = nullptr); 18 | ~SaveDialog(); 19 | 20 | QString getPath() { 21 | return RipesSettings::value(RIPES_SETTING_SAVEPATH).toString(); 22 | } 23 | QString sourcePath() { 24 | return RipesSettings::value(RIPES_SETTING_SAVE_SOURCE).toBool() 25 | ? getPath() + (sourceType == SourceType::C ? ".c" : ".s") 26 | : QString(); 27 | } 28 | QString binaryPath() { 29 | return RipesSettings::value(RIPES_SETTING_SAVE_BINARY).toBool() 30 | ? getPath() + ".bin" 31 | : QString(); 32 | } 33 | 34 | void accept() override; 35 | 36 | private: 37 | void openFileButtonTriggered(); 38 | void pathChanged(); 39 | 40 | Ui::SaveDialog *m_ui = nullptr; 41 | SourceType sourceType; 42 | }; 43 | 44 | } // namespace Ripes 45 | -------------------------------------------------------------------------------- /src/serializers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cereal/cereal.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | void save(Archive &archive, const QVariant &v) { 11 | // Seems cumbersome but only easy way to serialize a QVariant in cereal 12 | QByteArray data; 13 | QDataStream ds(&data, QIODevice::WriteOnly); 14 | ds << v; 15 | std::vector dataVector( 16 | reinterpret_cast(std::begin(data)), 17 | reinterpret_cast(std::end(data))); 18 | archive(dataVector); 19 | } 20 | 21 | template 22 | void load(Archive &archive, QVariant &v) { 23 | // Seems cumbersome but only easy way to serialize a QVariant in cereal 24 | std::vector dataVector; 25 | archive(dataVector); 26 | QByteArray data = QByteArray( 27 | reinterpret_cast(dataVector.data()), dataVector.size()); 28 | QDataStream ds(&data, QIODevice::ReadOnly); 29 | ds >> v; 30 | } 31 | -------------------------------------------------------------------------------- /src/settingsdialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "ccmanager.h" 7 | 8 | QT_FORWARD_DECLARE_CLASS(QLineEdit); 9 | QT_FORWARD_DECLARE_CLASS(QLabel); 10 | QT_FORWARD_DECLARE_CLASS(QGridLayout); 11 | QT_FORWARD_DECLARE_CLASS(QGroupBox); 12 | 13 | namespace Ripes { 14 | 15 | namespace Ui { 16 | class SettingsDialog; 17 | } 18 | 19 | class SettingsDialog : public QDialog { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit SettingsDialog(QWidget *parent = nullptr); 24 | ~SettingsDialog() override; 25 | 26 | void accept() override; 27 | 28 | private: 29 | /** 30 | * @brief CCPathChanged 31 | * Rehighlightss the current CCPath if the CC is @param valid 32 | */ 33 | void CCPathChanged(CCManager::CCRes res); 34 | QLineEdit *m_ccpath = nullptr; 35 | QPlainTextEdit *m_compileInfo = nullptr; 36 | QLabel *m_compileInfoHeader = nullptr; 37 | 38 | QWidget *createCompilerPage(); 39 | QWidget *createSimulatorPage(); 40 | QWidget *createEnvironmentPage(); 41 | QWidget *createEditorPage(); 42 | 43 | Ui::SettingsDialog *m_ui; 44 | 45 | void addPage(const QString &name, QWidget *page); 46 | void appendToLayout(std::pair settingsWidgets, 47 | QGridLayout *pageLayout, 48 | const QString &description = QString()); 49 | void appendToLayout(QWidget *widget, QGridLayout *pageLayout, 50 | int colSpan = 2); 51 | void appendToLayout(QLayout *layout, QGridLayout *pageLayout, 52 | int colSpan = 2); 53 | 54 | std::map m_pageIndex; 55 | }; 56 | 57 | } // namespace Ripes 58 | -------------------------------------------------------------------------------- /src/symbolnavigator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "assembler/objdump.h" 6 | 7 | namespace Ripes { 8 | 9 | namespace Ui { 10 | class SymbolNavigator; 11 | } 12 | 13 | class SymbolNavigator : public QDialog { 14 | Q_OBJECT 15 | 16 | public: 17 | SymbolNavigator(const ReverseSymbolMap &symbolmap, QWidget *parent = nullptr); 18 | ~SymbolNavigator(); 19 | 20 | AInt getSelectedSymbolAddress() const; 21 | 22 | private: 23 | void addSymbol(const AInt address, const QString &label); 24 | 25 | Ui::SymbolNavigator *m_ui; 26 | }; 27 | } // namespace Ripes 28 | -------------------------------------------------------------------------------- /src/syscall/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(syscall LINK_TO_RIPES_LIB) 2 | -------------------------------------------------------------------------------- /src/syscall/ripes_syscall.cpp: -------------------------------------------------------------------------------- 1 | #include "ripes_syscall.h" 2 | 3 | #include "processorhandler.h" 4 | 5 | namespace Ripes { 6 | 7 | bool SyscallManager::execute(SyscallID id) { 8 | if (m_syscalls.count(id) == 0) { 9 | postToGUIThread([=] { 10 | if (auto reg = ProcessorHandler::currentISA()->syscallReg(); 11 | reg.has_value()) { 12 | QMessageBox::warning(nullptr, "Error", 13 | "Unknown system call in register '" + 14 | reg->file->regAlias(reg->index) + 15 | "': " + QString::number(id) + 16 | "\nRefer to \"Help->System calls\" for a list " 17 | "of support system " 18 | "calls."); 19 | } 20 | }); 21 | return false; 22 | } else { 23 | const auto &syscall = m_syscalls.at(id); 24 | const QString &syscallName = syscall->name(); 25 | postToGUIThread([=] { 26 | // We don't have a good way of making non-permanent status timers 27 | // pseudo-permanent until explicitly cleared... The best way to do so is 28 | // to just have a very large timeout. 29 | SyscallStatusManager::setStatusTimed( 30 | "Handling system call: " + syscallName + " (" + QString::number(id) + 31 | ")", 32 | 99999999); 33 | }); 34 | syscall->execute(); 35 | postToGUIThread([=] { SyscallStatusManager::clearStatus(); }); 36 | return true; 37 | } 38 | } 39 | 40 | } // namespace Ripes 41 | -------------------------------------------------------------------------------- /src/syscall/syscall_time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "processorhandler.h" 6 | #include "ripes_syscall.h" 7 | #include "systemio.h" 8 | 9 | #include 10 | 11 | namespace Ripes { 12 | template 13 | class CyclesSyscall : public BaseSyscall { 14 | static_assert(std::is_base_of::value); 15 | 16 | public: 17 | CyclesSyscall() 18 | : BaseSyscall("Cycles", 19 | "Get number of cycles elapsed since program start", {}, 20 | {{0, "low 32 bits of cycles elapsed"}, 21 | {1, "high 32 bits of cycles elapsed"}}) {} 22 | void execute() { 23 | long long cycleCount = ProcessorHandler::getProcessor()->getCycleCount(); 24 | BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, cycleCount & 0xFFFFFFFF); 25 | BaseSyscall::setRet(BaseSyscall::REG_FILE, 1, 26 | (cycleCount >> 32) & 0xFFFFFFFF); 27 | } 28 | }; 29 | 30 | template 31 | class TimeMsSyscall : public BaseSyscall { 32 | static_assert(std::is_base_of::value); 33 | 34 | public: 35 | TimeMsSyscall() 36 | : BaseSyscall("Time_msec", 37 | "Get the current time since epoch (milliseconds since 1 " 38 | "January 1970)", 39 | {}, 40 | {{0, "low 32 bits of milliseconds since epoch"}, 41 | {1, "high 32 bits of milliseconds since epoch"}}) {} 42 | void execute() { 43 | long long ms = QDateTime::currentMSecsSinceEpoch(); 44 | BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, ms & 0xFFFFFFFF); 45 | BaseSyscall::setRet(BaseSyscall::REG_FILE, 1, (ms >> 32) & 0xFFFFFFFF); 46 | } 47 | }; 48 | 49 | } // namespace Ripes 50 | -------------------------------------------------------------------------------- /src/syscall/syscallviewer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "ripes_syscall.h" 6 | 7 | namespace Ripes { 8 | 9 | namespace Ui { 10 | class SyscallViewer; 11 | } 12 | 13 | class SyscallViewer : public QDialog { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit SyscallViewer(QWidget *parent = nullptr); 18 | ~SyscallViewer(); 19 | 20 | private: 21 | void handleItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous); 22 | void addSyscall(unsigned id, const Syscall *syscall); 23 | void addItemToTable(QTableWidget *table, unsigned idx, 24 | const QString &description); 25 | void setCurrentSyscall(const Syscall *syscall); 26 | 27 | Ui::SyscallViewer *m_ui; 28 | }; 29 | } // namespace Ripes 30 | -------------------------------------------------------------------------------- /src/syscall/systemio.cpp: -------------------------------------------------------------------------------- 1 | #include "systemio.h" 2 | 3 | namespace Ripes { 4 | QString SystemIO::s_fileErrorString; 5 | 6 | std::map SystemIO::FileIOData::fileNames; 7 | std::map SystemIO::FileIOData::fileFlags; 8 | std::map SystemIO::FileIOData::streams; 9 | std::map SystemIO::FileIOData::files; 10 | QByteArray SystemIO::FileIOData::s_stdinBuffer; 11 | QMutex SystemIO::FileIOData::s_stdioMutex; 12 | QWaitCondition SystemIO::FileIOData::s_stdinBufferEmpty; 13 | bool SystemIO::s_abortSyscall = false; 14 | } // namespace Ripes 15 | -------------------------------------------------------------------------------- /src/utilities/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(utilities LINK_TO_RIPES_LIB) 2 | -------------------------------------------------------------------------------- /src/utilities/hexspinbox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | 7 | class HexSpinBox : public QSpinBox { 8 | public: 9 | HexSpinBox(QWidget *parent = 0) : QSpinBox(parent) { 10 | setPrefix("0x"); 11 | setDisplayIntegerBase(16); 12 | setRange(INT_MIN, INT_MAX); 13 | } 14 | 15 | protected: 16 | QString textFromValue(int value) const override { 17 | return QString::number(static_cast(value), 16) 18 | .rightJustified(8, '0') 19 | .toUpper(); 20 | } 21 | int valueFromText(const QString &text) const override { 22 | int v = sanitize(text).toUInt(nullptr, 16); 23 | return v; 24 | } 25 | QValidator::State validate(QString &input, int &) const override { 26 | bool okay; 27 | sanitize(input).toUInt(&okay, 16); 28 | if (!okay) 29 | return QValidator::Invalid; 30 | return QValidator::Acceptable; 31 | } 32 | 33 | private: 34 | QString sanitize(const QString &input) const { 35 | QString copy(input); 36 | if (copy.startsWith("0x")) 37 | copy.remove(0, 2); 38 | return copy; 39 | } 40 | }; 41 | 42 | } // namespace Ripes 43 | -------------------------------------------------------------------------------- /src/utilities/scrolleventfilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace Ripes { 7 | 8 | class ScrollEventFilter : public QObject { 9 | Q_OBJECT 10 | 11 | protected: 12 | bool eventFilter(QObject * /*obj*/, QEvent *event) override { 13 | return (event->type() == QEvent::Wheel); 14 | } 15 | }; 16 | 17 | } // namespace Ripes 18 | -------------------------------------------------------------------------------- /src/utilities/systemutils.cpp: -------------------------------------------------------------------------------- 1 | #include "systemutils.h" 2 | 3 | #include 4 | namespace Ripes { 5 | bool isExecutable(const QString &path, const QStringList &dummyArgs) { 6 | #ifdef RIPES_WITH_QPROCESS 7 | QProcess process; 8 | process.start(path, dummyArgs); 9 | process.waitForFinished(); 10 | return (process.error() != QProcess::FailedToStart); 11 | #else 12 | return false; 13 | #endif 14 | } 15 | 16 | } // namespace Ripes 17 | -------------------------------------------------------------------------------- /src/utilities/systemutils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | 7 | bool isExecutable(const QString &path, const QStringList &dummyArgs = {}); 8 | 9 | } // namespace Ripes 10 | -------------------------------------------------------------------------------- /src/version/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore generated version number file 2 | gen_* 3 | -------------------------------------------------------------------------------- /src/version/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | create_ripes_lib(version LINK_TO_RIPES_LIB) 2 | 3 | # ----------------------------------------------------------------------------- 4 | # Version control file 5 | # A file gen_versionnumber.h is generated by version.cmake, containing information 6 | # regarding the current .git revision. 7 | # This information is embedded into the binary for future reference, ie. for issue 8 | # reporting. 9 | add_custom_target( 10 | version_file ALL 11 | # Depend on the dummy file (which is not generated by the versioning script) 12 | # to ensure that the custom command is executed each time the project is built. 13 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp 14 | ) 15 | 16 | add_dependencies(version_lib version_file) 17 | 18 | add_custom_command( 19 | OUTPUT 20 | # Dummy file not generated by the sript, but may be used as a dependency 21 | ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp 22 | COMMAND 23 | ${CMAKE_COMMAND} 24 | -DRIPES_SRC_DIR=${CMAKE_SOURCE_DIR} 25 | -P ${CMAKE_CURRENT_SOURCE_DIR}/version.cmake) 26 | -------------------------------------------------------------------------------- /src/version/version.cmake: -------------------------------------------------------------------------------- 1 | set(ENV{GIT_DIR} ${RIPES_SRC_DIR}/.git) 2 | execute_process(COMMAND git describe --tags --exclude "continuous" 3 | OUTPUT_VARIABLE GIT_REV 4 | ERROR_QUIET) 5 | 6 | # Check whether we got any revision (which isn't 7 | # always the case, e.g. when someone downloaded a zip 8 | # file from Github instead of a checkout) 9 | if ("${GIT_REV}" STREQUAL "") 10 | set(RIPES_GIT_VERSION "N/A") 11 | else() 12 | string(STRIP "${GIT_REV}" RIPES_GIT_VERSION) 13 | endif() 14 | 15 | set(VERSION_FILE ${RIPES_SRC_DIR}/src/version/gen_versionnumber.h) 16 | 17 | # New version file content 18 | set(VERSION "#define RIPES_GIT_VERSION \"${RIPES_GIT_VERSION}\"") 19 | 20 | # Only rewrite the version file if a change is seen 21 | if(EXISTS ${VERSION_FILE}) 22 | file(READ ${VERSION_FILE} OLD_VERSION) 23 | else() 24 | set(OLD_VERSION "") 25 | endif() 26 | 27 | if (NOT "${VERSION}" STREQUAL "${OLD_VERSION}") 28 | file(WRITE ${VERSION_FILE} "${VERSION}") 29 | endif() -------------------------------------------------------------------------------- /src/version/version.cpp: -------------------------------------------------------------------------------- 1 | #include "version.h" 2 | 3 | // The following header file is autogenerated by version.cmake, and will export 4 | // a definition of the current git version for the build 5 | #include "gen_versionnumber.h" 6 | 7 | namespace Ripes { 8 | 9 | QString getRipesVersion() { return QString(RIPES_GIT_VERSION); } 10 | 11 | } // namespace Ripes 12 | -------------------------------------------------------------------------------- /src/version/version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | QString getRipesVersion(); 7 | } 8 | -------------------------------------------------------------------------------- /src/wasmSupport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Ripes { 6 | 7 | // Disable a widget if we are running in a wasm environment. 8 | template 9 | #ifdef __EMSCRIPTEN__ 10 | inline void disableIfWasm(T *widget) { 11 | widget->setEnabled(false); 12 | } 13 | #else 14 | inline void disableIfWasm(T *) { 15 | } 16 | #endif 17 | 18 | // Disables a list of widgets if we are running in a wasm environment. 19 | template 20 | inline void disableIfWasm(TList widgets) { 21 | for (auto *widget : widgets) 22 | disableIfWasm(widget); 23 | } 24 | 25 | } // namespace Ripes 26 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9) 2 | 3 | find_package(Qt6 COMPONENTS Test REQUIRED) 4 | 5 | # Point to bundled tests within source directory 6 | set(RISCV32_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/riscv-tests) 7 | set(RISCV64_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/riscv-tests-64) 8 | set(RISCV32_C_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/riscv-tests-c) 9 | set(RISCV64_C_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/riscv-tests-c-64) 10 | add_definitions(-DRISCV32_TEST_DIR="${RISCV32_TEST_DIR}") 11 | add_definitions(-DRISCV64_TEST_DIR="${RISCV64_TEST_DIR}") 12 | add_definitions(-DRISCV32_C_TEST_DIR="${RISCV32_C_TEST_DIR}") 13 | add_definitions(-DRISCV64_C_TEST_DIR="${RISCV64_C_TEST_DIR}") 14 | 15 | macro(create_qtest name) 16 | add_executable(${name} ${name}.cpp programloader.h) 17 | add_test(${name} ${name}) 18 | target_include_directories (${name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 19 | target_link_libraries(${name} Qt6::Core Qt6::Widgets Qt6::Test) 20 | target_link_libraries(${name} ripes_lib) 21 | endmacro() 22 | 23 | create_qtest(tst_riscv) 24 | create_qtest(tst_assembler) 25 | create_qtest(tst_expreval) 26 | create_qtest(tst_cosimulate) 27 | create_qtest(tst_reverse) 28 | -------------------------------------------------------------------------------- /test/programloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "edittab.h" 7 | #include "processorhandler.h" 8 | #include "processorregistry.h" 9 | 10 | #include 11 | 12 | namespace Ripes { 13 | 14 | /// Utility class around a Ripes EditTab which helps in loading and assembling 15 | /// programs from tests. 16 | class ProgramLoader : public QObject { 17 | Q_OBJECT 18 | 19 | public: 20 | ProgramLoader() { 21 | m_editTab = new EditTab(new QToolBar(), nullptr); 22 | connect(m_editTab, &EditTab::programChanged, ProcessorHandler::get(), 23 | &ProcessorHandler::loadProgram); 24 | } 25 | 26 | void loadTest(LoadFileParams params) { 27 | currentTestType = params.type; 28 | m_editTab->loadExternalFile(params); 29 | processNewTest(); 30 | } 31 | 32 | void loadTest(const QString &assembly) { 33 | currentTestType = SourceType::Assembly; 34 | m_editTab->loadSourceText(assembly); 35 | processNewTest(); 36 | } 37 | 38 | private: 39 | // Load a program through the edittab. This is not really suited for automatic 40 | // testing, since the edit tab will trigger assembling after some timeout. To 41 | // work around this, we allow for a bit of delay when loading the program. 42 | void processNewTest() { 43 | if (currentTestType == SourceType::Assembly) 44 | m_editTab->sourceCodeChanged(); 45 | 46 | int timeouts = 5; 47 | while (timeouts-- > 0 && !ProcessorHandler::getProgram()) { 48 | QCoreApplication::processEvents(QEventLoop::AllEvents, 500); 49 | } 50 | if (!ProcessorHandler::getProgram()) { 51 | QFAIL("No program was loaded!"); 52 | } 53 | if (m_editTab->errors() && !m_editTab->errors()->empty()) 54 | QFAIL("Errors during assembly!"); 55 | } 56 | 57 | SourceType currentTestType; 58 | EditTab *m_editTab = nullptr; 59 | }; 60 | 61 | } // namespace Ripes 62 | -------------------------------------------------------------------------------- /test/riscv-tests-64/brk_syscall.S: -------------------------------------------------------------------------------- 1 | .text 2 | .globl _start 3 | _start: nop 4 | 5 | #------------------------------------------------------------- 6 | # Stack-Heap Collision brk syscall Test 7 | #------------------------------------------------------------- 8 | 9 | test_0: # Test Ecall Return Value 10 | mv a0, sp # Assign the ecall parameter to the stack pointer value 11 | lw a7, BRK # Load the brk syscall immediate value 12 | ecall 13 | 14 | # If the return value of the ecall is zero, then the ecall 15 | # was executed successfully and therefore the test failed 16 | beqz a0, fail 17 | 18 | bne x0, gp, pass 19 | 20 | pass: 21 | li a0, 42 22 | li a7, 93 23 | ecall 24 | 25 | 26 | fail: 27 | li a0, 0 28 | li a7, 93 29 | ecall 30 | 31 | .data 32 | .align 4 33 | 34 | # Syscall immediate value 35 | BRK: .word 214 -------------------------------------------------------------------------------- /test/riscv-tests-64/ecall_file.S: -------------------------------------------------------------------------------- 1 | ../riscv-tests/ecall_file.s -------------------------------------------------------------------------------- /test/riscv-tests-64/lui.S: -------------------------------------------------------------------------------- 1 | .text 2 | .globl _start 3 | _start: nop 4 | 5 | #------------------------------------------------------------- 6 | # Basic tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: lui x1, 0x00000 10 | li x7, 0x0000000000000000 11 | li gp, 2 12 | bne x1, x7, fail 13 | 14 | test_3: lui x1, 0xfffff 15 | srai x1,x1,1 16 | li x7, 0xfffffffffffff800 17 | li gp, 3 18 | bne x1, x7, fail 19 | 20 | test_4: lui x1, 0x7ffff 21 | srai x1,x1,20 22 | li x7, 0x00000000000007ff 23 | li gp, 4 24 | bne x1, x7, fail 25 | 26 | test_5: lui x1, 0x80000 27 | srai x1,x1,20 28 | li x7, 0xfffffffffffff800 29 | li gp, 5 30 | bne x1, x7, fail 31 | 32 | 33 | test_6: lui x0, 0x80000 34 | li x7, 0 35 | li gp, 6 36 | bne x0, x7, fail 37 | 38 | 39 | bne x0, gp, pass 40 | fail: li a0, 0 41 | li a7, 93 42 | ecall 43 | pass: li a0, 42 44 | li a7, 93 45 | ecall 46 | 47 | 48 | 49 | .data 50 | .data 51 | .align 4 52 | .global begin_signature 53 | begin_signature: 54 | 55 | 56 | 57 | .align 4 58 | .global end_signature 59 | end_signature: 60 | -------------------------------------------------------------------------------- /test/riscv-tests-64/simple.S: -------------------------------------------------------------------------------- 1 | .text 2 | .globl _start 3 | _start: nop 4 | 5 | li a0, 42 6 | li a7, 93 7 | ecall 8 | 9 | 10 | 11 | .data 12 | .data 13 | .align 4 14 | .global begin_signature 15 | begin_signature: 16 | 17 | 18 | 19 | .align 4 20 | .global end_signature 21 | end_signature: 22 | -------------------------------------------------------------------------------- /test/riscv-tests/.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | -------------------------------------------------------------------------------- /test/riscv-tests/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2015, The Regents of the University of California (Regents). 2 | All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the Regents nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 16 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 17 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 18 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | 20 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 23 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 24 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | -------------------------------------------------------------------------------- /test/riscv-tests/and.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | #------------------------------------------------------------- 4 | # Logical tests 5 | #------------------------------------------------------------- 6 | 7 | test_2: 8 | li x1, 0xff00ff00 9 | li x2, 0x0f0f0f0f 10 | and x30, x1, x2 11 | li x29, 0x0f000f00 12 | li gp, 2 13 | bne x30, x29, fail 14 | 15 | 16 | test_3: 17 | li x1, 0x0ff00ff0 18 | li x2, 0xf0f0f0f0 19 | and x30, x1, x2 20 | li x29, 0x00f000f0 21 | li gp, 3 22 | bne x30, x29, fail 23 | 24 | 25 | test_4: 26 | li x1, 0x00ff00ff 27 | li x2, 0x0f0f0f0f 28 | and x30, x1, x2 29 | li x29, 0x000f000f 30 | li gp, 4 31 | bne x30, x29, fail 32 | 33 | 34 | test_5: 35 | li x1, 0xf00ff00f 36 | li x2, 0xf0f0f0f0 37 | and x30, x1, x2 38 | li x29, 0xf000f000 39 | li gp, 5 40 | bne x30, x29, fail 41 | 42 | 43 | 44 | #------------------------------------------------------------- 45 | # Source/Destination tests 46 | #------------------------------------------------------------- 47 | 48 | test_6: 49 | li x1, 0xff00ff00 50 | li x2, 0x0f0f0f0f 51 | and x1, x1, x2 52 | li x29, 0x0f000f00 53 | li gp, 6 54 | bne x1, x29, fail 55 | 56 | 57 | test_7: 58 | li x1, 0x0ff00ff0 59 | li x2, 0xf0f0f0f0 60 | and x2, x1, x2 61 | li x29, 0x00f000f0 62 | li gp, 7 63 | bne x2, x29, fail 64 | 65 | 66 | test_8: 67 | li x1, 0xff00ff00 68 | and x1, x1, x1 69 | li x29, 0xff00ff00 70 | li gp, 8 71 | bne x1, x29, fail 72 | 73 | 74 | 75 | pass: 76 | li a0, 42 77 | li a7, 93 78 | ecall 79 | fail: 80 | li a0, 0 81 | li a7, 93 82 | ecall 83 | -------------------------------------------------------------------------------- /test/riscv-tests/andi.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | #------------------------------------------------------------- 4 | # Logical tests 5 | #------------------------------------------------------------- 6 | 7 | test_2: 8 | li x1, 0xff00ff00 9 | andi x30, x1, 0xffffff0f 10 | li x29, 0xff00ff00 11 | li gp, 2 12 | bne x30, x29, fail 13 | 14 | 15 | test_3: 16 | li x1, 0x0ff00ff0 17 | andi x30, x1, 0x0f0 18 | li x29, 0x000000f0 19 | li gp, 3 20 | bne x30, x29, fail 21 | 22 | 23 | test_4: 24 | li x1, 0x00ff00ff 25 | andi x30, x1, 0x70f 26 | li x29, 0x0000000f 27 | li gp, 4 28 | bne x30, x29, fail 29 | 30 | 31 | test_5: 32 | li x1, 0xf00ff00f 33 | andi x30, x1, 0x0f0 34 | li x29, 0x00000000 35 | li gp, 5 36 | bne x30, x29, fail 37 | 38 | 39 | 40 | #------------------------------------------------------------- 41 | # Source/Destination tests 42 | #------------------------------------------------------------- 43 | 44 | test_6: 45 | li x1, 0xff00ff00 46 | andi x1, x1, 0x0f0 47 | li x29, 0x00000000 48 | li gp, 6 49 | bne x1, x29, fail 50 | 51 | test_13: 52 | andi x1, x0, 0x0f0 53 | li x29, 0 54 | li gp, 13 55 | bne x1, x29, fail 56 | 57 | 58 | test_14: 59 | li x1, 0x00ff00ff 60 | andi x0, x1, 0x70f 61 | li x29, 0 62 | li gp, 14 63 | bne x0, x29, fail 64 | 65 | pass: 66 | li a0, 42 67 | li a7, 93 68 | ecall 69 | fail: 70 | li a0, 0 71 | li a7, 93 72 | ecall 73 | -------------------------------------------------------------------------------- /test/riscv-tests/brk_syscall.s: -------------------------------------------------------------------------------- 1 | .text 2 | 3 | #------------------------------------------------------------- 4 | # Stack-Heap Collision brk syscall Test 5 | #------------------------------------------------------------- 6 | 7 | test_0: # Test Ecall Return Value 8 | mv a0, sp # Assign the ecall parameter to the stack pointer value 9 | li a7, 214 # Load the brk syscall immediate value 10 | ecall 11 | 12 | # If the return value of the ecall is zero, then the ecall 13 | # was executed successfully and therefore the test failed 14 | beqz a0, fail 15 | 16 | bne x0, gp, pass 17 | 18 | pass: 19 | li a0, 42 20 | li a7, 93 21 | ecall 22 | 23 | 24 | fail: 25 | li a0, 0 26 | li a7, 93 27 | ecall -------------------------------------------------------------------------------- /test/riscv-tests/cc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: bash compile.sh [-d] $program 4 | # -d : Disassemble 5 | 6 | FILE="" 7 | 8 | if [ "$1" == "-d" ]; then 9 | FILE=$2 10 | else 11 | FILE=$1 12 | fi 13 | 14 | riscv64-unknown-elf-gcc -march=rv32im -mabi=ilp32 $FILE -o $FILE.out 15 | 16 | if [ "$1" == "-d" ]; then 17 | riscv64-unknown-elf-objdump --disassemble $FILE.out > $FILE.dis 18 | fi 19 | -------------------------------------------------------------------------------- /test/riscv-tests/div.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Arithmetic tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li x1, 20 11 | li x2, 6 12 | div x30, x1, x2 13 | li x29, 3 14 | li gp, 2 15 | bne x30, x29, fail 16 | 17 | 18 | test_3: 19 | li x1, -20 20 | li x2, 6 21 | div x30, x1, x2 22 | li x29, -3 23 | li gp, 3 24 | bne x30, x29, fail 25 | 26 | 27 | test_4: 28 | li x1, 20 29 | li x2, -6 30 | div x30, x1, x2 31 | li x29, -3 32 | li gp, 4 33 | bne x30, x29, fail 34 | 35 | 36 | test_5: 37 | li x1, -20 38 | li x2, -6 39 | div x30, x1, x2 40 | li x29, 3 41 | li gp, 5 42 | bne x30, x29, fail 43 | 44 | 45 | 46 | test_6: 47 | li x1, 0x80000000 48 | li x2, 1 49 | div x30, x1, x2 50 | li x29, 0x80000000 51 | li gp, 6 52 | bne x30, x29, fail 53 | 54 | 55 | test_7: 56 | li x1, 0x80000000 57 | li x2, -1 58 | div x30, x1, x2 59 | li x29, 0x80000000 60 | li gp, 7 61 | bne x30, x29, fail 62 | 63 | 64 | 65 | test_8: 66 | li x1, 0x80000000 67 | li x2, 0 68 | div x30, x1, x2 69 | li x29, -1 70 | li gp, 8 71 | bne x30, x29, fail 72 | 73 | 74 | test_9: 75 | li x1, 1 76 | li x2, 0 77 | div x30, x1, x2 78 | li x29, -1 79 | li gp, 9 80 | bne x30, x29, fail 81 | 82 | 83 | test_10: 84 | li x1, 0 85 | li x2, 0 86 | div x30, x1, x2 87 | li x29, -1 88 | li gp, 10 89 | bne x30, x29, fail 90 | 91 | 92 | 93 | bne x0, gp, pass 94 | fail: li a0, 0 95 | li a7, 93 96 | ecall 97 | 98 | pass: li a0, 42 99 | li a7, 93 100 | ecall 101 | 102 | -------------------------------------------------------------------------------- /test/riscv-tests/divu.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Arithmetic tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li x1, 20 11 | li x2, 6 12 | divu x30, x1, x2 13 | li x29, 3 14 | li gp, 2 15 | bne x30, x29, fail 16 | 17 | 18 | test_3: 19 | li x1, -20 20 | li x2, 6 21 | divu x30, x1, x2 22 | li x29, 715827879 23 | li gp, 3 24 | bne x30, x29, fail 25 | 26 | 27 | test_4: 28 | li x1, 20 29 | li x2, -6 30 | divu x30, x1, x2 31 | li x29, 0 32 | li gp, 4 33 | bne x30, x29, fail 34 | 35 | 36 | test_5: 37 | li x1, -20 38 | li x2, -6 39 | divu x30, x1, x2 40 | li x29, 0 41 | li gp, 5 42 | bne x30, x29, fail 43 | 44 | 45 | 46 | test_6: 47 | li x1, 0x80000000 48 | li x2, 1 49 | divu x30, x1, x2 50 | li x29, 0x80000000 51 | li gp, 6 52 | bne x30, x29, fail 53 | 54 | 55 | test_7: 56 | li x1, 0x80000000 57 | li x2, -1 58 | divu x30, x1, x2 59 | li x29, 0 60 | li gp, 7 61 | bne x30, x29, fail 62 | 63 | 64 | 65 | test_8: 66 | li x1, 0x80000000 67 | li x2, 0 68 | divu x30, x1, x2 69 | li x29, -1 70 | li gp, 8 71 | bne x30, x29, fail 72 | 73 | 74 | test_9: 75 | li x1, 1 76 | li x2, 0 77 | divu x30, x1, x2 78 | li x29, -1 79 | li gp, 9 80 | bne x30, x29, fail 81 | 82 | 83 | test_10: 84 | li x1, 0 85 | li x2, 0 86 | divu x30, x1, x2 87 | li x29, -1 88 | li gp, 10 89 | bne x30, x29, fail 90 | 91 | 92 | 93 | bne x0, gp, pass 94 | fail: li a0, 0 95 | li a7, 93 96 | ecall 97 | 98 | pass: li a0, 42 99 | li a7, 93 100 | ecall 101 | 102 | -------------------------------------------------------------------------------- /test/riscv-tests/fclass.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Arithmetic tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li a0, 0xff800000 11 | fmv.s.x fa0, a0 12 | fclass.s a0, fa0 13 | li x29, 1 14 | li gp, 2 15 | bne a0, x29, fail 16 | 17 | test_3: 18 | li a0, 0xbf800000 19 | fmv.s.x fa0, a0 20 | fclass.s a0, fa0 21 | li x29, 2 22 | li gp, 3 23 | bne a0, x29, fail 24 | 25 | test_4: 26 | li a0, 0x807fffff 27 | fmv.s.x fa0, a0 28 | fclass.s a0, fa0 29 | li x29, 4 30 | li gp, 4 31 | bne a0, x29, fail 32 | 33 | test_5: 34 | li a0, 0x80000000 35 | fmv.s.x fa0, a0 36 | fclass.s a0, fa0 37 | li x29, 8 38 | li gp, 5 39 | bne a0, x29, fail 40 | 41 | test_6: 42 | li a0, 0x00000000 43 | fmv.s.x fa0, a0 44 | fclass.s a0, fa0 45 | li x29, 0x10 46 | li gp, 6 47 | bne a0, x29, fail 48 | 49 | test_7: 50 | li a0, 0x007fffff 51 | fmv.s.x fa0, a0 52 | fclass.s a0, fa0 53 | li x29, 0x20 54 | li gp, 7 55 | bne a0, x29, fail 56 | 57 | test_8: 58 | li a0, 0x3f800000 59 | fmv.s.x fa0, a0 60 | fclass.s a0, fa0 61 | li x29, 0x40 62 | li gp, 8 63 | bne a0, x29, fail 64 | 65 | test_9: 66 | li a0, 0x7f800000 67 | fmv.s.x fa0, a0 68 | fclass.s a0, fa0 69 | li x29, 0x80 70 | li gp, 9 71 | bne a0, x29, fail 72 | 73 | test_10: 74 | li a0, 0x7f800001 75 | fmv.s.x fa0, a0 76 | fclass.s a0, fa0 77 | li x29,0x100 78 | li gp, 10 79 | bne a0, x29, fail 80 | 81 | test_11: 82 | li a0, 0x7fc00000 83 | fmv.s.x fa0, a0 84 | fclass.s a0, fa0 85 | li x29,0x200 86 | li gp, 11 87 | bne a0, x29, fail 88 | 89 | 90 | bne x0, gp, pass 91 | fail: li a0, 0 92 | li a7, 93 93 | ecall 94 | 95 | pass: li a0, 42 96 | li a7, 93 97 | ecall 98 | 99 | -------------------------------------------------------------------------------- /test/riscv-tests/fcvt.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Arithmetic tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: li gp, 2 10 | la a0, test_2_data 11 | lw a3, 0(a0) 12 | li a0, 2 13 | fcvt.s.w f0, a0 14 | fsflags x0 15 | fmv.x.s a0, f0 16 | bne a0, a3, fail 17 | 18 | test_3: li gp, 3 19 | la a0, test_3_data 20 | lw a3, 0(a0) 21 | li a0, -2 22 | fcvt.s.w f0, a0 23 | fsflags x0 24 | fmv.x.s a0, f0 25 | bne a0, a3, fail 26 | 27 | test_4: li gp, 4 28 | la a0, test_4_data 29 | lw a3, 0(a0) 30 | li a0, 2 31 | fcvt.s.wu f0, a0 32 | fsflags x0 33 | fmv.x.s a0, f0 34 | bne a0, a3, fail 35 | 36 | test_5: li gp, 5 37 | la a0, test_5_data 38 | lw a3, 0(a0) 39 | li a0, -2 40 | fcvt.s.wu f0, a0 41 | fsflags x0 42 | fmv.x.s a0, f0 43 | bne a0, a3, fail 44 | 45 | bne x0, gp, pass 46 | fail: li a0, 0 47 | li a7, 93 48 | ecall 49 | 50 | pass: li a0, 42 51 | li a7, 93 52 | ecall 53 | 54 | 55 | .data 56 | test_2_data: .float 2.0 57 | 58 | test_3_data: .float -2.0 59 | 60 | test_4_data: .float 2.0 61 | 62 | test_5_data: .float 4.2949673e9 63 | 64 | -------------------------------------------------------------------------------- /test/riscv-tests/ldst.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | test_2: 6 | la a1, tdat 7 | flw f1, 4(a1) 8 | fsw f1, 20(a1) 9 | lw a0, 20(a1) 10 | li x29, 0x40000000 11 | li gp, 2 12 | bne a0, x29, fail 13 | 14 | test_3: 15 | la a1, tdat 16 | flw f1, 0(a1) 17 | fsw f1, 24(a1) 18 | lw a0, 24(a1) 19 | li x29, 0xbf800000 20 | li gp, 3 21 | bne a0, x29, fail 22 | 23 | 24 | bne x0, gp, pass 25 | fail: li a0, 0 26 | li a7, 93 27 | ecall 28 | 29 | pass: li a0, 42 30 | li a7, 93 31 | ecall 32 | 33 | 34 | .data 35 | 36 | tdat: 37 | .word 0xbf800000 38 | .word 0x40000000 39 | .word 0x40400000 40 | .word 0xc0800000 41 | .word 0xdeadbeef 42 | .word 0xcafebabe 43 | .word 0xabad1dea 44 | .word 0x1337d00d 45 | 46 | 47 | -------------------------------------------------------------------------------- /test/riscv-tests/ldstd.s: -------------------------------------------------------------------------------- 1 | .text 2 | 3 | la s0, tdat 4 | test_2: fld f2, 0(s0) 5 | fsd f2, 16(s0) 6 | lw a0, 16(s0) 7 | lw a1, 20(s0) 8 | la x15, test_2_data 9 | lw x29, 0(x15) 10 | lw x15, 4(x15) 11 | li gp, 2 12 | bne a0, x29, fail 13 | bne a1, x15, fail 14 | .data 15 | .align 3 16 | test_2_data: .word 0xbf800000, 0x40000000 17 | .text 18 | test_3: fld f2, 0(s0) 19 | fsw f2, 16(s0) 20 | lw a0, 16(s0) 21 | lw a1, 20(s0) 22 | la x15, test_3_data 23 | lw x29, 0(x15) 24 | lw x15, 4(x15) 25 | li gp, 3 26 | bne a0, x29, fail 27 | bne a1, x15, fail 28 | .data 29 | .align 3 30 | test_3_data: .word 0xbf800000, 0x40000000 31 | .text 32 | test_4: flw f2, 0(s0) 33 | fsw f2, 16(s0) 34 | lw a0, 16(s0) 35 | lw a1, 20(s0) 36 | la x15, test_4_data 37 | lw x29, 0(x15) 38 | lw x15, 4(x15) 39 | li gp, 4 40 | bne a0, x29, fail 41 | bne a1, x15, fail 42 | .data 43 | .align 3 44 | test_4_data: .word 0xbf800000, 0x40000000 45 | .text 46 | test_5: fld f2, 8(s0) 47 | fsd f2, 16(s0) 48 | lw a0, 16(s0) 49 | lw a1, 20(s0) 50 | la x15, test_5_data 51 | lw x29, 0(x15) 52 | lw x15, 4(x15) 53 | li gp, 5 54 | bne a0, x29, fail 55 | bne a1, x15, fail 56 | .data 57 | .align 3 58 | test_5_data: .word 0x40400000, 0xc0800000 59 | .text 60 | test_6: flw f2, 8(s0) 61 | fsd f2, 16(s0) 62 | lw a0, 16(s0) 63 | lw a1, 20(s0) 64 | la x15, test_6_data 65 | lw x29, 0(x15) 66 | lw x15, 4(x15) 67 | li gp, 6 68 | bne a0, x29, fail 69 | bne a1, x15, fail 70 | .data 71 | .align 3 72 | test_6_data: .word 0x40400000, 0xffffffff 73 | .text 74 | j success 75 | fail: 76 | li a0, 0 77 | li a7, 93 78 | ecall 79 | 80 | success: 81 | li a0, 42 82 | li a7, 93 83 | ecall 84 | 85 | .data 86 | tdat: 87 | .word 0xbf800000 88 | .word 0x40000000 89 | .word 0x40400000 90 | .word 0xc0800000 91 | .word 0xdeadbeef 92 | .word 0xcafebabe 93 | .word 0xabad1dea 94 | .word 0x1337d00d -------------------------------------------------------------------------------- /test/riscv-tests/lui.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | #------------------------------------------------------------- 4 | # Basic tests 5 | #------------------------------------------------------------- 6 | 7 | test_2: 8 | lui x1, 0x00000 9 | li x29, 0x00000000 10 | li gp, 2 11 | bne x1, x29, fail 12 | 13 | 14 | test_3: 15 | lui x1, 0xfffff 16 | srai x1,x1,1 17 | li x29, 0xfffff800 18 | li gp, 3 19 | bne x1, x29, fail 20 | 21 | 22 | test_4: 23 | lui x1, 0x7ffff 24 | srai x1,x1,20 25 | li x29, 0x000007ff 26 | li gp, 4 27 | bne x1, x29, fail 28 | 29 | 30 | test_5: 31 | lui x1, 0x80000 32 | srai x1,x1,20 33 | li x29, 0xfffff800 34 | li gp, 5 35 | bne x1, x29, fail 36 | 37 | 38 | 39 | test_6: 40 | lui x0, 0x80000 41 | li x29, 0 42 | li gp, 6 43 | bne x0, x29, fail 44 | 45 | pass: 46 | li a0, 42 47 | li a7, 93 48 | ecall 49 | 50 | fail: 51 | li a0, 0 52 | li a7, 93 53 | ecall 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /test/riscv-tests/memory.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | # Buffer 4 | li s0, 0x1000 5 | 6 | #------------------------------------------------------------- 7 | # Memory tests 8 | #------------------------------------------------------------- 9 | 10 | # word load/store 11 | test_2: 12 | jal reset 13 | li t0, 0x12341234 14 | sw t0, 0(s0) 15 | lw t1, 0(s0) 16 | li gp, 2 17 | bne t0, t1, fail 18 | 19 | # Half-word load/store 20 | test_3: 21 | jal reset 22 | li t0, -1234 23 | sh t0, 0(s0) 24 | lh t1, 0(s0) 25 | lhu t2, 0(s0) 26 | li gp, 3 27 | bne t0, t1, fail 28 | li t3, 64302 29 | bne t2, t3, fail 30 | 31 | # Byte load/store 32 | test_4: 33 | jal reset 34 | li t0, -123 35 | sh t0, 0(s0) 36 | lb t1, 0(s0) 37 | lbu t2, 0(s0) 38 | li gp, 4 39 | bne t0, t1, fail 40 | li t3, 133 41 | bne t2, t3, fail 42 | 43 | pass: 44 | li a0, 42 45 | li a7, 93 46 | ecall 47 | fail: 48 | li a0, 0 49 | li a7, 93 50 | ecall 51 | 52 | reset: 53 | li t0, 0 54 | li t1, 0 55 | li t2, 0 56 | li t3, 0 57 | sw zero, 0(s0) 58 | ret 59 | -------------------------------------------------------------------------------- /test/riscv-tests/or.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Logical tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li x1, 0xff00ff00 11 | li x2, 0x0f0f0f0f 12 | or x30, x1, x2 13 | li x29, 0xff0fff0f 14 | li gp, 2 15 | bne x30, x29, fail 16 | 17 | 18 | test_3: 19 | li x1, 0x0ff00ff0 20 | li x2, 0xf0f0f0f0 21 | or x30, x1, x2 22 | li x29, 0xfff0fff0 23 | li gp, 3 24 | bne x30, x29, fail 25 | 26 | 27 | test_4: 28 | li x1, 0x00ff00ff 29 | li x2, 0x0f0f0f0f 30 | or x30, x1, x2 31 | li x29, 0x0fff0fff 32 | li gp, 4 33 | bne x30, x29, fail 34 | 35 | 36 | test_5: 37 | li x1, 0xf00ff00f 38 | li x2, 0xf0f0f0f0 39 | or x30, x1, x2 40 | li x29, 0xf0fff0ff 41 | li gp, 5 42 | bne x30, x29, fail 43 | 44 | 45 | 46 | #------------------------------------------------------------- 47 | # Source/Destination tests 48 | #------------------------------------------------------------- 49 | 50 | test_6: 51 | li x1, 0xff00ff00 52 | li x2, 0x0f0f0f0f 53 | or x1, x1, x2 54 | li x29, 0xff0fff0f 55 | li gp, 6 56 | bne x1, x29, fail 57 | 58 | 59 | test_7: 60 | li x1, 0xff00ff00 61 | li x2, 0x0f0f0f0f 62 | or x2, x1, x2 63 | li x29, 0xff0fff0f 64 | li gp, 7 65 | bne x2, x29, fail 66 | 67 | 68 | test_8: 69 | li x1, 0xff00ff00 70 | or x1, x1, x1 71 | li x29, 0xff00ff00 72 | li gp, 8 73 | bne x1, x29, fail 74 | 75 | 76 | 77 | bne x0, gp, pass 78 | fail: li a0, 0 79 | li a7, 93 80 | ecall 81 | 82 | pass: li a0, 42 83 | li a7, 93 84 | ecall 85 | 86 | -------------------------------------------------------------------------------- /test/riscv-tests/ori.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | #------------------------------------------------------------- 4 | # Logical tests 5 | #------------------------------------------------------------- 6 | 7 | test_2: 8 | li x1, 0xff00ff00 9 | ori x30, x1, 0xffffff0f 10 | li x29, 0xffffff0f 11 | li gp, 2 12 | bne x30, x29, fail 13 | 14 | 15 | test_3: 16 | li x1, 0x0ff00ff0 17 | ori x30, x1, 0x0f0 18 | li x29, 0x0ff00ff0 19 | li gp, 3 20 | bne x30, x29, fail 21 | 22 | 23 | test_4: 24 | li x1, 0x00ff00ff 25 | ori x30, x1, 0x70f 26 | li x29, 0x00ff07ff 27 | li gp, 4 28 | bne x30, x29, fail 29 | 30 | 31 | test_5: 32 | li x1, 0xf00ff00f 33 | ori x30, x1, 0x0f0 34 | li x29, 0xf00ff0ff 35 | li gp, 5 36 | bne x30, x29, fail 37 | 38 | 39 | 40 | #------------------------------------------------------------- 41 | # Source/Destination tests 42 | #------------------------------------------------------------- 43 | 44 | test_6: 45 | li x1, 0xff00ff00 46 | ori x1, x1, 0x0f0 47 | li x29, 0xff00fff0 48 | li gp, 6 49 | bne x1, x29, fail 50 | 51 | 52 | 53 | bne x0, gp, pass 54 | fail: li a0, 0 55 | li a7, 93 56 | ecall 57 | 58 | pass: li a0, 42 59 | li a7, 93 60 | ecall 61 | 62 | -------------------------------------------------------------------------------- /test/riscv-tests/readme.txt: -------------------------------------------------------------------------------- 1 | The tests in this directory were generated and modified from the riscv-tests repository. They cover basic conformance of instructions to the specification. 2 | 3 | These tests have been modified by GitHub user TheThirdOne 4 | https://github.com/TheThirdOne/rars/tree/master/test/riscv-tests 5 | -------------------------------------------------------------------------------- /test/riscv-tests/recoding.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | # Make sure infinities with different mantissas compare as equal. 6 | flw f0, minf, a0 7 | flw f1, three, a0 8 | fmul.s f1, f1, f0 9 | test_2: 10 | feq.s a0, f0, f1 11 | li x29, 1 12 | li gp, 2 13 | bne a0, x29, fail 14 | 15 | test_3: 16 | fle.s a0, f0, f1 17 | li x29, 1 18 | li gp, 3 19 | bne a0, x29, fail 20 | 21 | test_4: 22 | flt.s a0, f0, f1 23 | li x29, 0 24 | li gp, 4 25 | bne a0, x29, fail 26 | 27 | 28 | # Likewise, but for zeroes. 29 | fcvt.s.w f0, x0 30 | li a0, 1 31 | fcvt.s.w f1, a0 32 | fmul.s f1, f1, f0 33 | test_5: 34 | feq.s a0, f0, f1 35 | li x29, 1 36 | li gp, 5 37 | bne a0, x29, fail 38 | 39 | test_6: 40 | fle.s a0, f0, f1 41 | li x29, 1 42 | li gp, 6 43 | bne a0, x29, fail 44 | 45 | test_7: 46 | flt.s a0, f0, f1 47 | li x29, 0 48 | li gp, 7 49 | bne a0, x29, fail 50 | 51 | 52 | bne x0, gp, pass 53 | fail: li a0, 0 54 | li a7, 93 55 | ecall 56 | 57 | pass: li a0, 42 58 | li a7, 93 59 | ecall 60 | 61 | 62 | .data 63 | minf: .float -Inf 64 | three: .float 3.0 65 | -------------------------------------------------------------------------------- /test/riscv-tests/recodingd.s: -------------------------------------------------------------------------------- 1 | .text 2 | 3 | # Make sure infinities with different mantissas compare as equal. 4 | fld f0, minf, a0 5 | fld f1, three, a0 6 | fmul.d f1, f1, f0 7 | test_2: feq.d a0, f0, f1 8 | li x29, 1 9 | li gp, 2 10 | bne a0, x29, fail 11 | 12 | test_3: fle.d a0, f0, f1 13 | li x29, 1 14 | li gp, 3 15 | bne a0, x29, fail 16 | 17 | test_4: flt.d a0, f0, f1 18 | li x29, 0 19 | li gp, 4 20 | bne a0, x29, fail 21 | 22 | 23 | # Likewise, but for zeroes. 24 | fcvt.d.w f0, x0 25 | li a0, 1 26 | fcvt.d.w f1, a0 27 | fmul.d f1, f1, f0 28 | test_5: feq.d a0, f0, f1 29 | li x29, 1 30 | li gp, 5 31 | bne a0, x29, fail 32 | 33 | test_6: fle.d a0, f0, f1 34 | li x29, 1 35 | li gp, 6 36 | bne a0, x29, fail 37 | 38 | test_7: flt.d a0, f0, f1 39 | li x29, 0 40 | li gp, 7 41 | bne a0, x29, fail 42 | 43 | 44 | # When converting small doubles to single-precision subnormals, 45 | # ensure that the extra precision is discarded. 46 | flw f0, big, a0 47 | fld f1, tiny, a0 48 | fcvt.s.d f1, f1 49 | fmul.s f0, f0, f1 50 | fmv.x.s a0, f0 51 | lw a1, small 52 | test_10: sub a0, a0, a1 53 | li x29, 0 54 | li gp, 10 55 | bne a0, x29, fail 56 | 57 | 58 | # Make sure FSD+FLD correctly saves and restores a single-precision value. 59 | flw f0, three, a0 60 | fadd.s f1, f0, f0 61 | fadd.s f0, f0, f0 62 | fsd f0, tiny, a0 63 | fld f0, tiny, a0 64 | test_20: feq.s a0, f0, f1 65 | li x29, 1 66 | li gp, 20 67 | bne a0, x29, fail 68 | 69 | j success 70 | fail: 71 | li a0, 0 72 | li a7, 93 73 | ecall 74 | 75 | success: 76 | li a0, 42 77 | li a7, 93 78 | ecall 79 | 80 | 81 | .data 82 | minf: .double -Inf 83 | three: .double 3.0 84 | big: .float 1221 85 | small: .float 2.9133121e-37 86 | tiny: .double 2.3860049081905093e-40 87 | -------------------------------------------------------------------------------- /test/riscv-tests/rem.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Arithmetic tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li x1, 20 11 | li x2, 6 12 | rem x30, x1, x2 13 | li x29, 2 14 | li gp, 2 15 | bne x30, x29, fail 16 | 17 | 18 | test_3: 19 | li x1, -20 20 | li x2, 6 21 | rem x30, x1, x2 22 | li x29, -2 23 | li gp, 3 24 | bne x30, x29, fail 25 | 26 | 27 | test_4: 28 | li x1, 20 29 | li x2, -6 30 | rem x30, x1, x2 31 | li x29, 2 32 | li gp, 4 33 | bne x30, x29, fail 34 | 35 | 36 | test_5: 37 | li x1, -20 38 | li x2, -6 39 | rem x30, x1, x2 40 | li x29, -2 41 | li gp, 5 42 | bne x30, x29, fail 43 | 44 | 45 | 46 | test_6: 47 | li x1, 0x80000000 48 | li x2, 1 49 | rem x30, x1, x2 50 | li x29, 0 51 | li gp, 6 52 | bne x30, x29, fail 53 | 54 | 55 | test_7: 56 | li x1, 0x80000000 57 | li x2, -1 58 | rem x30, x1, x2 59 | li x29, 0 60 | li gp, 7 61 | bne x30, x29, fail 62 | 63 | 64 | 65 | test_8: 66 | li x1, 0x80000000 67 | li x2, 0 68 | rem x30, x1, x2 69 | li x29, 0x80000000 70 | li gp, 8 71 | bne x30, x29, fail 72 | 73 | 74 | test_9: 75 | li x1, 1 76 | li x2, 0 77 | rem x30, x1, x2 78 | li x29, 1 79 | li gp, 9 80 | bne x30, x29, fail 81 | 82 | 83 | test_10: 84 | li x1, 0 85 | li x2, 0 86 | rem x30, x1, x2 87 | li x29, 0 88 | li gp, 10 89 | bne x30, x29, fail 90 | 91 | 92 | 93 | bne x0, gp, pass 94 | fail: li a0, 0 95 | li a7, 93 96 | ecall 97 | 98 | pass: li a0, 42 99 | li a7, 93 100 | ecall 101 | 102 | -------------------------------------------------------------------------------- /test/riscv-tests/remu.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Arithmetic tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li x1, 20 11 | li x2, 6 12 | remu x30, x1, x2 13 | li x29, 2 14 | li gp, 2 15 | bne x30, x29, fail 16 | 17 | 18 | test_3: 19 | li x1, -20 20 | li x2, 6 21 | remu x30, x1, x2 22 | li x29, 2 23 | li gp, 3 24 | bne x30, x29, fail 25 | 26 | 27 | test_4: 28 | li x1, 20 29 | li x2, -6 30 | remu x30, x1, x2 31 | li x29, 20 32 | li gp, 4 33 | bne x30, x29, fail 34 | 35 | 36 | test_5: 37 | li x1, -20 38 | li x2, -6 39 | remu x30, x1, x2 40 | li x29, -20 41 | li gp, 5 42 | bne x30, x29, fail 43 | 44 | 45 | 46 | test_6: 47 | li x1, 0x80000000 48 | li x2, 1 49 | remu x30, x1, x2 50 | li x29, 0 51 | li gp, 6 52 | bne x30, x29, fail 53 | 54 | 55 | test_7: 56 | li x1, 0x80000000 57 | li x2, -1 58 | remu x30, x1, x2 59 | li x29, 0x80000000 60 | li gp, 7 61 | bne x30, x29, fail 62 | 63 | 64 | 65 | test_8: 66 | li x1, 0x80000000 67 | li x2, 0 68 | remu x30, x1, x2 69 | li x29, 0x80000000 70 | li gp, 8 71 | bne x30, x29, fail 72 | 73 | 74 | test_9: 75 | li x1, 1 76 | li x2, 0 77 | remu x30, x1, x2 78 | li x29, 1 79 | li gp, 9 80 | bne x30, x29, fail 81 | 82 | 83 | test_10: 84 | li x1, 0 85 | li x2, 0 86 | remu x30, x1, x2 87 | li x29, 0 88 | li gp, 10 89 | bne x30, x29, fail 90 | 91 | 92 | 93 | bne x0, gp, pass 94 | fail: li a0, 0 95 | li a7, 93 96 | ecall 97 | 98 | pass: li a0, 42 99 | li a7, 93 100 | ecall 101 | 102 | -------------------------------------------------------------------------------- /test/riscv-tests/simple.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | li a0, 42 5 | li a7, 93 6 | ecall 7 | 8 | -------------------------------------------------------------------------------- /test/riscv-tests/xor.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Logical tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li x1, 0xff00ff00 11 | li x2, 0x0f0f0f0f 12 | xor x30, x1, x2 13 | li x29, 0xf00ff00f 14 | li gp, 2 15 | bne x30, x29, fail 16 | 17 | 18 | test_3: 19 | li x1, 0x0ff00ff0 20 | li x2, 0xf0f0f0f0 21 | xor x30, x1, x2 22 | li x29, 0xff00ff00 23 | li gp, 3 24 | bne x30, x29, fail 25 | 26 | 27 | test_4: 28 | li x1, 0x00ff00ff 29 | li x2, 0x0f0f0f0f 30 | xor x30, x1, x2 31 | li x29, 0x0ff00ff0 32 | li gp, 4 33 | bne x30, x29, fail 34 | 35 | 36 | test_5: 37 | li x1, 0xf00ff00f 38 | li x2, 0xf0f0f0f0 39 | xor x30, x1, x2 40 | li x29, 0x00ff00ff 41 | li gp, 5 42 | bne x30, x29, fail 43 | 44 | 45 | 46 | #------------------------------------------------------------- 47 | # Source/Destination tests 48 | #------------------------------------------------------------- 49 | 50 | test_6: 51 | li x1, 0xff00ff00 52 | li x2, 0x0f0f0f0f 53 | xor x1, x1, x2 54 | li x29, 0xf00ff00f 55 | li gp, 6 56 | bne x1, x29, fail 57 | 58 | 59 | test_7: 60 | li x1, 0xff00ff00 61 | li x2, 0x0f0f0f0f 62 | xor x2, x1, x2 63 | li x29, 0xf00ff00f 64 | li gp, 7 65 | bne x2, x29, fail 66 | 67 | 68 | test_8: 69 | li x1, 0xff00ff00 70 | xor x1, x1, x1 71 | li x29, 0x00000000 72 | li gp, 8 73 | bne x1, x29, fail 74 | 75 | 76 | 77 | bne x0, gp, pass 78 | fail: li a0, 0 79 | li a7, 93 80 | ecall 81 | 82 | pass: li a0, 42 83 | li a7, 93 84 | ecall 85 | 86 | -------------------------------------------------------------------------------- /test/riscv-tests/xori.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | 4 | 5 | #------------------------------------------------------------- 6 | # Logical tests 7 | #------------------------------------------------------------- 8 | 9 | test_2: 10 | li x1, 0x00ff0f00 11 | xori x30, x1, 0xffffff0f 12 | li x29, 0xff00f00f 13 | li gp, 2 14 | bne x30, x29, fail 15 | 16 | 17 | test_3: 18 | li x1, 0x0ff00ff0 19 | xori x30, x1, 0x0f0 20 | li x29, 0x0ff00f00 21 | li gp, 3 22 | bne x30, x29, fail 23 | 24 | 25 | test_4: 26 | li x1, 0x00ff08ff 27 | xori x30, x1, 0x70f 28 | li x29, 0x00ff0ff0 29 | li gp, 4 30 | bne x30, x29, fail 31 | 32 | 33 | test_5: 34 | li x1, 0xf00ff00f 35 | xori x30, x1, 0x0f0 36 | li x29, 0xf00ff0ff 37 | li gp, 5 38 | bne x30, x29, fail 39 | 40 | 41 | 42 | #------------------------------------------------------------- 43 | # Source/Destination tests 44 | #------------------------------------------------------------- 45 | 46 | test_6: 47 | li x1, 0xff00f700 48 | xori x1, x1, 0x70f 49 | li x29, 0xff00f00f 50 | li gp, 6 51 | bne x1, x29, fail 52 | 53 | 54 | 55 | bne x0, gp, pass 56 | fail: li a0, 0 57 | li a7, 93 58 | ecall 59 | 60 | pass: li a0, 42 61 | li a7, 93 62 | ecall 63 | 64 | -------------------------------------------------------------------------------- /test/tst_expreval.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "assembler/expreval.h" 4 | 5 | using namespace Ripes; 6 | using namespace Ripes::Assembler; 7 | 8 | class tst_ExprEval : public QObject { 9 | Q_OBJECT 10 | 11 | private slots: 12 | void tst_binops(); 13 | }; 14 | 15 | void expect(const ExprEvalRes &res, const ExprEvalVT &expected) { 16 | if (auto *err = std::get_if(&res)) { 17 | QString errstr = "Got error: " + err->toString(); 18 | QFAIL(errstr.toStdString().c_str()); 19 | } 20 | QCOMPARE(std::get(res), expected); 21 | } 22 | 23 | void tst_ExprEval::tst_binops() { 24 | expect(evaluate(Location::unknown(), "(0x2*(3+4))+4"), 18); 25 | expect(evaluate(Location::unknown(), "2+3*7*5"), 107); 26 | SymbolMap symbols; 27 | Location::unknown(), symbols.abs["B"] = 2; 28 | expect(evaluate(Location::unknown(), "(B *(3+ 4))+4", &symbols.abs), 18); 29 | } 30 | 31 | QTEST_APPLESS_MAIN(tst_ExprEval) 32 | #include "tst_expreval.moc" 33 | -------------------------------------------------------------------------------- /test/tst_riscv_common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mortbopet/Ripes/03df996b0cc6c7f981b58bbd73363f7235576a08/test/tst_riscv_common.h --------------------------------------------------------------------------------