├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── scala.yml ├── .gitignore ├── .mergify.yml ├── .mill-version ├── .scala-steward.conf ├── .scalafix.conf ├── .scalafmt.conf ├── GTKWave ├── gtkwave.tcl ├── instruction_map.txt └── registers.txt ├── LICENSE ├── Makefile ├── README.md ├── build.sc ├── chiselv.core ├── chiselv ├── resources │ ├── pll_artya7-35t.v │ ├── pll_bypass.v │ ├── pll_qmtech_k325t.v │ └── pll_ulx3s.v ├── src │ ├── ALU.scala │ ├── Blink.scala │ ├── CPUSingleCycle.scala │ ├── Constants.scala │ ├── DataMemory.scala │ ├── Decoder.scala │ ├── GPIO.scala │ ├── InstructionMemory.scala │ ├── MemoryIOManager.scala │ ├── PLLBlackBox.scala │ ├── ProgramCounter.scala │ ├── RVFI_Wrapper.scala │ ├── RegisterBank.scala │ ├── SOC.scala │ ├── Syscon.scala │ ├── Timer.scala │ ├── Toplevel.scala │ └── Uart.scala └── test │ └── src │ ├── ALUSpec.scala │ ├── CPUDemoAppsSpec.scala │ ├── CPUSingleCycleAppsSpec.scala │ ├── CPUSingleCycleIOSpec.scala │ ├── CPUSingleCycleInstructionSpec.scala │ ├── DecoderSpec.scala │ ├── GPIOSpec.scala │ ├── MemorySpec.scala │ ├── ProgramCounterSpec.scala │ ├── RegisterBankSpec.scala │ ├── SysconSpec.scala │ ├── TimerSpec.scala │ └── UartSpec.scala ├── constraints ├── arty_a7.xdc ├── ecp5-ulx3s.lpf ├── qmtech-kintex7.xdc └── qmtech-zyjzgw.xdc ├── download_firtool.sh ├── gcc ├── blinkLED │ ├── Makefile │ ├── main-ram.mem │ ├── main-rom.mem │ ├── main.c │ ├── main.dump │ ├── main.hex │ └── main.map ├── helloUART │ ├── Makefile │ ├── banner.h │ ├── main-ram.mem │ ├── main-rom.mem │ ├── main.c │ ├── main.dump │ ├── main.hex │ └── main.map ├── lib │ ├── crt.s │ ├── io.h │ ├── riscv.ld │ ├── stdio.h │ └── uart.h ├── riscv64-crossbuild.dockerfile ├── simpleLED │ ├── Makefile │ ├── crt.s │ ├── main.c │ ├── main.dump │ ├── main.h │ ├── main.hex │ ├── main.map │ ├── main.mem │ └── riscv.ld └── test │ ├── Makefile │ ├── riscv.ld │ ├── test_addi.hex │ ├── test_addi.mem │ ├── test_addi.s │ ├── test_ascii.hex │ ├── test_ascii.mem │ ├── test_ascii.s │ ├── test_book.hex │ ├── test_book.mem │ ├── test_book.s │ ├── test_gpio.hex │ ├── test_gpio.mem │ └── test_gpio.s ├── mill ├── openocd ├── LFE5U-25F.cfg ├── LFE5U-45F.cfg ├── LFE5U-85F.cfg ├── LFE5UM-25F.cfg ├── LFE5UM-45F.cfg ├── LFE5UM-85F.cfg ├── LFE5UM5G-25F.cfg ├── LFE5UM5G-45F.cfg ├── LFE5UM5G-85F.cfg ├── digilent-hs1.cfg ├── ecp5-evn.cfg ├── ft231x.cfg └── xilinx-xc7.cfg ├── proginfo ├── artix7-template.txt ├── boardconfig.yaml ├── proginfo.py ├── qmtech_k325t-template.txt └── ulx3s-template.txt └── verilator ├── chiselv.cpp └── uart.c /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: carlosedp 4 | patreon: carlosedp 5 | 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | # Maintain dependencies for GitHub Actions 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | -------------------------------------------------------------------------------- /.github/workflows/scala.yml: -------------------------------------------------------------------------------- 1 | name: Scala CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Install Verilator 14 | run: sudo apt-get install -y verilator 15 | 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | 19 | - name: Setup Java 20 | uses: actions/setup-java@v4 21 | with: 22 | distribution: 'temurin' 23 | java-version: '11' 24 | 25 | - uses: coursier/cache-action@v6 26 | id: coursier-cache 27 | 28 | - name: Run automated tests 29 | run: make test 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Scala .gitignore 2 | # 3 | # other 4 | /out/ 5 | 6 | # intellij 7 | /src/intellij*/*.iml 8 | /src/intellij*/*.ipr 9 | /src/intellij*/*.iws 10 | **/.cache 11 | /.idea 12 | /.settings 13 | 14 | # vscode 15 | /.vscode 16 | 17 | # metals 18 | .metals 19 | .bloop 20 | project/**/metals.sbt 21 | project/metals.sbt 22 | 23 | # custom 24 | .bsp 25 | .addons-dont-touch 26 | .DS_Store 27 | generated 28 | docs/generated 29 | test_run_dir 30 | tmp 31 | ./MemoryTestFile.hex 32 | *.bin 33 | *.elf 34 | *.o 35 | /*.hex 36 | /*.json 37 | /*.fir 38 | /*.v 39 | /*.sv 40 | /*.f 41 | /*.vcd 42 | /obj_dir 43 | /*.mem 44 | /tmphex 45 | /chiselv.bin 46 | .genboard 47 | /firtool* 48 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: Automatic merge Dependabot PRs (for actions) on CI success 3 | conditions: 4 | - base=main 5 | - author=dependabot[bot] 6 | - files~=^.github/workflows/ 7 | - check-success=build 8 | - "#review-requested=0" 9 | actions: 10 | merge: 11 | method: squash 12 | -------------------------------------------------------------------------------- /.mill-version: -------------------------------------------------------------------------------- 1 | 0.11.7 2 | -------------------------------------------------------------------------------- /.scala-steward.conf: -------------------------------------------------------------------------------- 1 | updatePullRequests = "always" 2 | updates.ignore = [ { groupId = "org.scala-lang", artifactId = "scala-library" } ] -------------------------------------------------------------------------------- /.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | RemoveUnused, 3 | DisableSyntax, 4 | LeakingImplicitClassVal, 5 | NoAutoTupling, 6 | NoValInForComprehension, 7 | OrganizeImports, 8 | ProcedureSyntax, 9 | ] 10 | 11 | OrganizeImports { 12 | groupedImports = Merge, 13 | groups = ["javax?\\.", "scala.", "*"] 14 | coalesceToWildcardImportThreshold = 5 15 | expandRelative = true 16 | removeUnused = true 17 | } 18 | 19 | RemoveUnused { 20 | imports = false // handled by OrganizeImports 21 | } -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = 3.8.1 2 | 3 | runner.dialect = scala213 4 | maxColumn = 120 5 | 6 | align.preset = more 7 | assumeStandardLibraryStripMargin = true 8 | docstrings.style = Asterisk 9 | docstrings.wrapMaxColumn = 80 10 | lineEndings = preserve 11 | danglingParentheses.preset = true 12 | 13 | align.preset = most 14 | align.arrowEnumeratorGenerator = true 15 | align.openParenCallSite = false 16 | align.openParenDefnSite = false 17 | align.multiline = false 18 | danglingParentheses.exclude = [ 19 | "`trait`" 20 | ] 21 | align.tokens."+" = [ 22 | { 23 | code = ":" 24 | } 25 | {code = "=", owner = "(Enumerator.Val|Defn.(Va(l|r)|Def|Type|GivenAlias)|Term.Assign)"} 26 | ] 27 | newlines.source = keep 28 | newlines.beforeCurlyLambdaParams = false 29 | newlines.implicitParamListModifierForce = [before] 30 | rewrite.trailingCommas.style = "multiple" 31 | rewrite.trailingCommas.allowFolding = true 32 | rewrite.rules = [ 33 | RedundantBraces, 34 | RedundantParens, 35 | PreferCurlyFors, 36 | ] 37 | 38 | verticalMultiline.atDefnSite = true 39 | verticalMultiline.arityThreshold = 3 40 | -------------------------------------------------------------------------------- /GTKWave/gtkwave.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # GTKWave Grouping and colorizing script 3 | # 4 | # Load the trace with `gtkwave -S gtkwave.tcl yourtrace.vcd` 5 | # 6 | # Customize the inserted traces in the TOPlevel section below 7 | # and at the bottom in the add_signals function calls 8 | # 9 | 10 | # Customize this section as needed 11 | ## Add TOPLevel clock, reset and stall signals 12 | set top [list clock reset stall] 13 | 14 | ## This adds the signals based on a list of {"signal_name_filter" Color} 15 | set signals_to_add {{"PC.io_pcPort" Green ""} {"instructionMemory.io_memPort" Red ""} {"decoder.io_DecoderPort" Violet ""} {"ALU.io_ALUPort" Orange ""} {"registerBank.io_regPort" Green ""} {"registerBank.regs_" Green "regs_0_"} {"memoryIOManager.io_MemoryIOPort_" Red ""} {"dataMemory.io_dualPort_" Yellow ""}} 16 | 17 | ## For mapping values, add the translate files and the signals to map file 18 | # Format file as: "signal_value mapped_value" (one per line) 19 | set instructions [ gtkwave::setCurrentTranslateFile ./GTKWave/instruction_map.txt ] 20 | set insts [list "_inst"] 21 | set registers [ gtkwave::setCurrentTranslateFile ./GTKWave/registers.txt ] 22 | set regs [list "_rd" "_rs1" "_rs2"] 23 | array set reg_names [list {0[31:0]} {x0(Zero)} \ 24 | {1[31:0]} {x1(RA)} \ 25 | {2[31:0]} {x2(SP)} \ 26 | {3[31:0]} {x3(GP)} \ 27 | {4[31:0]} {x4(TP)} \ 28 | {5[31:0]} {x5(t0)} \ 29 | {6[31:0]} {x6(t1)} \ 30 | {7[31:0]} {x7(t2)} \ 31 | {8[31:0]} {x8-(s0/fp)} \ 32 | {9[31:0]} {x9(s1)} \ 33 | {10[31:0]} {x10(a0)} \ 34 | {11[31:0]} {x11(a1)} \ 35 | {12[31:0]} {x12(a2)} \ 36 | {13[31:0]} {x13(a3)} \ 37 | {14[31:0]} {x14(a4)} \ 38 | {15[31:0]} {x15(a5)} \ 39 | {16[31:0]} {x16(a6)} \ 40 | {17[31:0]} {x17(a7)} \ 41 | {18[31:0]} {x18(s2)} \ 42 | {19[31:0]} {x19(s3)} \ 43 | {20[31:0]} {x20(s4)} \ 44 | {21[31:0]} {x21(s5)} \ 45 | {22[31:0]} {x22(s6)} \ 46 | {23[31:0]} {x23(s7)} \ 47 | {24[31:0]} {x24(s8)} \ 48 | {25[31:0]} {x25(s9)} \ 49 | {26[31:0]} {x26(s10)} \ 50 | {27[31:0]} {x27(s11)} \ 51 | {28[31:0]} {x28(t3)} \ 52 | {29[31:0]} {x29(t4)} \ 53 | {30[31:0]} {x30(t5)} \ 54 | {31[31:0]} {x31(t6)} ] 55 | 56 | ################################################################################ 57 | # Don't touch from here down 58 | set tmpdir $::env(PATH) 59 | puts $tmpdir 60 | 61 | # Load all signals 62 | set nsigs [ gtkwave::getNumFacs ] 63 | set sigs [list] 64 | 65 | # Customize view settings 66 | gtkwave::nop 67 | gtkwave::/Edit/Set_Trace_Max_Hier 1 68 | gtkwave::/View/Show_Filled_High_Values 1 69 | gtkwave::/View/Show_Wave_Highlight 1 70 | gtkwave::/View/Show_Mouseover 1 71 | 72 | gtkwave::/Edit/Insert_Comment "Clock & Reset" 73 | gtkwave::addSignalsFromList $top 74 | gtkwave::highlightSignalsFromList $top 75 | gtkwave::/Edit/Color_Format/Indigo 76 | gtkwave::/Edit/UnHighlight_All 77 | gtkwave::/Edit/Insert_Blank 78 | 79 | proc translate {element_list element mapping_file} { 80 | set iselement 0 81 | foreach e $element_list { 82 | if {[ string first $e $element ] != -1} { 83 | set iselement 1 84 | } 85 | } 86 | if {$iselement == 1 } { 87 | gtkwave::highlightSignalsFromList "$element" 88 | gtkwave::installFileFilter $mapping_file 89 | gtkwave::/Edit/UnHighlight_All 90 | } 91 | # return $iselement 92 | } 93 | 94 | proc add_signals { filter color filterOut} { 95 | global nsigs 96 | global instructions 97 | global registers 98 | global reg_names 99 | global regs 100 | global insts 101 | 102 | set filterKeyword $filter 103 | set monitorSignals [list] 104 | for {set i 0} {$i < $nsigs } {incr i} { 105 | set facname [ gtkwave::getFacName $i ] 106 | set index [ string first $filterKeyword $facname ] 107 | set index2 [ string first $filterOut $facname ] 108 | 109 | if {$index != -1 && $index2 == -1} { 110 | lappend monitorSignals "$facname" 111 | } 112 | } 113 | gtkwave::/Edit/Insert_Comment $filter 114 | gtkwave::addSignalsFromList $monitorSignals 115 | gtkwave::/Edit/Insert_Blank 116 | foreach v $monitorSignals { 117 | set a [split $v .] 118 | set a [lindex $a end] 119 | gtkwave::highlightSignalsFromList $v 120 | } 121 | gtkwave::/Edit/Color_Format/$color 122 | gtkwave::/Edit/UnHighlight_All 123 | 124 | foreach v $monitorSignals { 125 | if {[info exists regs]} { 126 | translate $regs $v $registers 127 | } 128 | if {[info exists insts]} { 129 | translate $insts $v $instructions 130 | } 131 | } 132 | ## This sets the register signal names to be aliased to the register name 133 | foreach v $monitorSignals { 134 | if {[string first regs_ $v] != -1} { 135 | set name [string range [lsearch -inline [split $v .] {regs_*}] 5 end] 136 | gtkwave::highlightSignalsFromList "$v" 137 | gtkwave::/Edit/Alias_Highlighted_Trace $reg_names($name) 138 | gtkwave::/Edit/UnHighlight_All 139 | 140 | } 141 | } 142 | } 143 | 144 | # Zoom all 145 | gtkwave::/Time/Zoom/Zoom_Full 146 | 147 | # Add signals thru filters 148 | foreach s $signals_to_add { 149 | add_signals [lindex $s 0] [lindex $s 1] [lindex $s 2] 150 | } 151 | -------------------------------------------------------------------------------- /GTKWave/instruction_map.txt: -------------------------------------------------------------------------------- 1 | 00 ERR 2 | 01 ADD 3 | 02 ADDI 4 | 03 SUB 5 | 04 LUI 6 | 05 AUIPC 7 | 06 SLL 8 | 07 SLLI 9 | 08 SRL 10 | 09 SRLI 11 | 0A SRA 12 | 0B SRAI 13 | 0C XOR 14 | 0D XORI 15 | 0E OR 16 | 0F ORI 17 | 10 AND 18 | 11 ANDI 19 | 12 SLT 20 | 13 SLTI 21 | 14 SLTU 22 | 15 SLTIU 23 | 16 BEQ 24 | 17 BNE 25 | 18 BLT 26 | 19 BGE 27 | 1A BLTU 28 | 1B BGEU 29 | 1C JAL 30 | 1D JALR 31 | 1E FENCE 32 | 1F FENCEI 33 | 20 ECALL 34 | 21 EBREAK 35 | 22 CSRRW 36 | 23 CSRRS 37 | 24 CSRRC 38 | 25 CSRRWI 39 | 26 CSRRSI 40 | 27 CSRRCI 41 | 28 LB 42 | 29 LH 43 | 2A LBU 44 | 2B LHU 45 | 2C LW 46 | 2D SB 47 | 2E SH 48 | 2F SW 49 | 30 EQ 50 | 31 NEQ 51 | 32 GT 52 | 33 GTU -------------------------------------------------------------------------------- /GTKWave/registers.txt: -------------------------------------------------------------------------------- 1 | 00 x0(Zero) 2 | 01 x1(RA) 3 | 02 x2(SP) 4 | 03 x3(GP) 5 | 04 x4(TP) 6 | 05 x5(t0) 7 | 06 x6(t1) 8 | 07 x7(t2) 9 | 08 x8-(s0/fp) 10 | 09 x9(s1) 11 | 0A x10(a0) 12 | 0b x11(a1) 13 | 0c x12(a2) 14 | 0d x13(a3) 15 | 0e x14(a4) 16 | 0f x15(a5) 17 | 10 x16(a6) 18 | 11 x17(a7) 19 | 12 x18(s2) 20 | 13 x19(s3) 21 | 14 x20(s4) 22 | 15 x21(s5) 23 | 16 x22(s6) 24 | 17 x23(s7) 25 | 18 x24(s8) 26 | 19 x25(s9) 27 | 1a x26(s10) 28 | 1b x27(s11) 29 | 1c x28(t3) 30 | 1d x29(t4) 31 | 1e x30(t5) 32 | 1f x31(t6) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Carlos Eduardo de Paula 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Source and target files/directories 2 | project = chiselv 3 | scala_files = $(wildcard $(project)/src/*.scala) $(wildcard $(project)/resources/*.scala) $(wildcard $(project)/test/src/*.scala) 4 | generated_files = generated/$(wildcard *.sv) $(wildcard *.v) 5 | export PATH := $(PWD):$(PATH) 6 | 7 | # Toolchains and tools 8 | MILL = ./mill 9 | DOCKERARGS = run --rm -v $(PWD):/src -w /src 10 | 11 | # Define utility applications for simulation 12 | YOSYS = docker $(DOCKERARGS) hdlc/yosys yosys 13 | VERILATORLOCAL := $(shell command -v verilator 2> /dev/null) 14 | VERILATORARGS = --name verilator --hostname verilator --rm -it --entrypoint= -v $(PWD):/work -w /work 15 | ifndef VERILATORLOCAL 16 | VERILATOR = docker $(DOCKERARGS) $(VERILATORARGS) gcr.io/hdl-containers/verilator:latest 17 | else 18 | VERILATOR = 19 | endif 20 | 21 | # Set board PLL or bypass if not defined 22 | BOARD ?= bypass 23 | PLLFREQ ?= 50000000 24 | BOARDPARAMS=--board ${BOARD} --cpufreq ${PLLFREQ} 25 | # Check if generating for a different board/pll 26 | $(if $(findstring $(shell cat .genboard 2>/dev/null),$(BOARDPARAMS)),,$(shell echo ${BOARDPARAMS} > .genboard)) 27 | CHISELPARAMS = --target-dir generated --split-verilog 28 | 29 | # Targets 30 | all: chisel gcc 31 | 32 | chisel: $(generated_files) ## Generates Verilog code from Chisel sources (output to ./generated) 33 | $(generated_files): $(scala_files) build.sc Makefile .genboard firtool 34 | @test "$(BOARD)" != "bypass" || (printf "Generating design with bypass PLL (for simulation). If required, set BOARD and PLLFREQ variables to one of the supported boards: " ; test -f chiselv.core && cat chiselv.core|grep "\-board"|cut -d '-' -f 3 | grep -v bypass | sed s/board\ //g |tr -s ' \n' ','| sed 's/,$$/\n/'; echo "Eg. make chisel BOARD=ulx3s PLLFREQ=15000000"; echo) 35 | $(MILL) $(project).run $(BOARDPARAMS) $(CHISELPARAMS) 36 | @echo "Generated files in $(generated_files)" 37 | 38 | firtool: 39 | @./download_firtool.sh 40 | 41 | check: test 42 | .PHONY: test 43 | test:## Run Chisel tests 44 | $(MILL) Alias/run test 45 | 46 | .PHONY: lint 47 | lint: ## Formats code using scalafmt and scalafix 48 | $(MILL) Alias/run lint 49 | 50 | .PHONY: deps 51 | deps: ## Check for library version updates 52 | $(MILL) Alias/run deps 53 | 54 | rvfi: $(rvfi_files) ## Generates Verilog code for RISC-V Formal tests 55 | $(rvfi_files): $(scala_files) build.sc Makefile 56 | $(MILL) $(project)_rvfi.run $(CHISELPARAMS) 57 | 58 | # This section defines the Verilator simulation and demo application to be used 59 | # Below, I use -DENABLE_INITIAL_MEM_ to enable initial memory load on firtool from progload.mem and progload-RAM.mem 60 | binfile = chiselv.bin 61 | verilator: $(binfile) ## Generate Verilator simulation 62 | $(binfile): $(generated_files) 63 | @rm -rf obj_dir 64 | $(VERILATOR) verilator -O3 --timescale 1ns/1ps -DENABLE_INITIAL_MEM_ --assert $(foreach f,$(shell find ./generated -name "*.v" -o -name "*.sv"),--cc $(f)) --exe verilator/chiselv.cpp verilator/uart.c --top-module Toplevel -o $(binfile) 65 | make -C obj_dir -f VToplevel.mk -j`nproc` 66 | @cp obj_dir/$(binfile) . 67 | 68 | # Adjust the rom and ram files below to match the desired demo app 69 | romfile = gcc/helloUART/main-rom.mem 70 | ramfile = gcc/helloUART/main-ram.mem 71 | verirun: $(binfile) ## Run Verilator simulation with ROM and RAM files to be loaded 72 | @cp $(romfile) progload.mem 73 | @cp $(ramfile) progload-RAM.mem 74 | @echo "------------------------------------------------------" 75 | @bash -c "trap 'reset' EXIT; ./$(binfile)" 76 | 77 | MODULE ?= Toplevel 78 | dot: $(generated_files) ## Generate dot files for Core 79 | @echo "Generating graphviz dot file for module \"$(MODULE)\". For a different module, pass the argument as \"make dot MODULE=mymod\"." 80 | @touch progload.mem progload-RAM.mem 81 | @$(YOSYS) -p "read_verilog ./generated/*.v ./generated/*.sv; proc; opt; show -colors 2 -width -format dot -prefix $(MODULE) -signed $(MODULE)" 82 | @rm progload.mem progload-RAM.mem 83 | 84 | .PHONY: gcc 85 | gcc: ## Builds gcc sample code 86 | @for d in `find gcc -name Makefile`;do echo ----\\nBuilding $$d; pushd `dirname $$d`; make; popd; done 87 | 88 | .PHONY: clean 89 | clean: ## Clean all generated files 90 | $(MILL) clean 91 | @rm -rf obj_dir test_run_dir target 92 | @rm -rf $(generated_files) 93 | @rm -rf tmphex 94 | @rm -rf out 95 | @rm -f *.mem 96 | 97 | .PHONY: cleanall 98 | cleanall: clean ## Clean all downloaded dependencies and cache 99 | @rm -rf project/.bloop 100 | @rm -rf project/project 101 | @rm -rf project/target 102 | @rm -rf .bloop .bsp .metals .vscode 103 | 104 | .PHONY: help 105 | help: 106 | @echo "Makefile targets:" 107 | @echo "" 108 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = "[:##]"}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$4}' 109 | @echo "" 110 | 111 | .DEFAULT_GOAL := help 112 | -------------------------------------------------------------------------------- /build.sc: -------------------------------------------------------------------------------- 1 | import mill._, mill.scalalib._, mill.scalalib.publish._ 2 | import scalafmt._ 3 | import $ivy.`com.goyeau::mill-scalafix::0.4.1` 4 | import com.goyeau.mill.scalafix.ScalafixModule 5 | import $ivy.`com.carlosedp::mill-aliases::0.6.0` 6 | import com.carlosedp.aliases._ 7 | 8 | object versions { 9 | val scala = "2.13.16" 10 | val chisel = "6.7.0" 11 | val chiseltest = "6.0.0" 12 | val scalatest = "3.2.18" 13 | val riscvassembler = "1.9.1" 14 | val mainargs = "0.7.0" 15 | } 16 | 17 | trait BaseProject extends ScalaModule with ScalafixModule with ScalafmtModule { 18 | def scalaVersion = versions.scala 19 | def ivyDeps = Agg( 20 | ivy"org.chipsalliance::chisel:${versions.chisel}", 21 | ivy"com.lihaoyi::mainargs:${versions.mainargs}", 22 | ) 23 | 24 | def scalacPluginIvyDeps = Agg(ivy"org.chipsalliance:::chisel-plugin:${versions.chisel}") 25 | 26 | object test extends ScalaTests with TestModule.ScalaTest { 27 | def ivyDeps = Agg( 28 | ivy"org.scalatest::scalatest:${versions.scalatest}", 29 | ivy"edu.berkeley.cs::chiseltest:${versions.chiseltest}", 30 | ivy"com.carlosedp::riscvassembler:${versions.riscvassembler}", 31 | ) 32 | } 33 | 34 | override def scalacOptions = T { 35 | super.scalacOptions() ++ Seq( 36 | "-unchecked", 37 | "-deprecation", 38 | "-language:reflectiveCalls", 39 | "-encoding", 40 | "UTF-8", 41 | "-feature", 42 | "-Xcheckinit", 43 | "-Xfatal-warnings", 44 | "-Ywarn-dead-code", 45 | "-Ywarn-unused", 46 | "-Ymacro-annotations", 47 | ) 48 | } 49 | } 50 | 51 | object chiselv extends BaseProject { 52 | def mainClass = Some("chiselv.Toplevel") 53 | } 54 | object chiselv_rvfi extends BaseProject { 55 | def mainClass = Some("chiselv.RVFI") 56 | def sources = T.sources(millSourcePath / os.up / "chiselv" / "src") 57 | } 58 | 59 | // ----------------------------------------------------------------------------- 60 | // Command Aliases 61 | // ----------------------------------------------------------------------------- 62 | object MyAliases extends Aliases { 63 | def lint = alias("mill.scalalib.scalafmt.ScalafmtModule/reformatAll __.sources", "__.fix") 64 | def fmt = alias("mill.scalalib.scalafmt.ScalafmtModule/reformatAll __.sources") 65 | def checkfmt = alias("mill.scalalib.scalafmt.ScalafmtModule/checkFormatAll __.sources") 66 | def deps = alias("mill.scalalib.Dependency/showUpdates") 67 | def test = alias("__.test") 68 | } 69 | -------------------------------------------------------------------------------- /chiselv.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name: carlosedp:chiselv:singlecycle:0 4 | description: ChiselV is a RV32I core written in Chisel 5 | 6 | filesets: 7 | # These are the demo filesets, use the `&demofiles` tag for the one to be used 8 | gpiodemo: 9 | files: 10 | - gcc/blinkLED/main-rom.mem: { copyto: progload.mem, file_type: user } 11 | - gcc/blinkLED/main-ram.mem: { copyto: progload-RAM.mem, file_type: user } 12 | 13 | uartdemo: &demofiles 14 | files: 15 | - gcc/helloUART/main-rom.mem: { copyto: progload.mem, file_type: user } 16 | - gcc/helloUART/main-ram.mem: 17 | { copyto: progload-RAM.mem, file_type: user } 18 | 19 | # This is the fileset to be programmed into the FPGA 20 | progload: 21 | <<: *demofiles 22 | 23 | # Show the programming info for the FPGAs 24 | proginfo: 25 | files: 26 | - proginfo/proginfo.py: { file_type: user, copyto: proginfo.py } 27 | - proginfo/boardconfig.yaml: { file_type: user, copyto: boardconfig.yaml } 28 | 29 | base: 30 | depend: ["fusesoc:utils:generators"] 31 | 32 | # Files specific to each FPGA board 33 | ulx3s-85: 34 | files: 35 | - constraints/ecp5-ulx3s.lpf: { file_type: LPF } 36 | - openocd/ft231x.cfg: { file_type: user } 37 | - openocd/LFE5U-85F.cfg: { file_type: user } 38 | - proginfo/ulx3s-template.txt: { file_type: user } 39 | 40 | artya7-35t: 41 | files: 42 | - constraints/arty_a7.xdc: { file_type: xdc } 43 | - openocd/digilent-hs1.cfg: { file_type: user } 44 | - openocd/xilinx-xc7.cfg: { file_type: user } 45 | - proginfo/artix7-template.txt: { file_type: user } 46 | 47 | qmtech_k325t: 48 | files: 49 | - constraints/qmtech-kintex7.xdc: { file_type: XDC } 50 | - proginfo/qmtech_k325t-template.txt: { file_type: user } 51 | 52 | qmtech_k325t_zyjzgw: 53 | files: 54 | - constraints/qmtech-zyjzgw.xdc: { file_type: XDC } 55 | - proginfo/qmtech_k325t-template.txt: { file_type: user } 56 | 57 | verilator: 58 | files: 59 | - verilator/chiselv.cpp: { file_type: cppSource } 60 | - verilator/uart.c: { file_type: cSource } 61 | 62 | generate: 63 | default-chisel: 64 | generator: chisel 65 | parameters: &baseparam 66 | extraargs: "--board bypass --cpufreq 15000000" 67 | buildtool: mill 68 | chiselproject: chiselv 69 | copy_core: true 70 | output: 71 | files: 72 | - generated/ALU.sv: { file_type: systemVerilogSource } 73 | - generated/Blinky.sv: { file_type: systemVerilogSource } 74 | - generated/CPUSingleCycle.sv: { file_type: systemVerilogSource } 75 | - generated/Decoder.sv: { file_type: systemVerilogSource } 76 | - generated/DualPortRAM.sv: { file_type: systemVerilogSource } 77 | - generated/extern_modules.sv: { file_type: systemVerilogSource } 78 | - generated/GPIO.sv: { file_type: systemVerilogSource } 79 | - generated/InstructionMemory.sv: { file_type: systemVerilogSource } 80 | - generated/mem_2048x32.sv: { file_type: systemVerilogSource } 81 | - generated/mem_2048x32_0.sv: { file_type: systemVerilogSource } 82 | - generated/MemoryIOManager.sv: { file_type: systemVerilogSource } 83 | - generated/ProgramCounter.sv: { file_type: systemVerilogSource } 84 | - generated/Queue128_UInt8.sv: { file_type: systemVerilogSource } 85 | - generated/ram_128x8.sv: { file_type: systemVerilogSource } 86 | - generated/RegisterBank.sv: { file_type: systemVerilogSource } 87 | - generated/SOC.sv: { file_type: systemVerilogSource } 88 | - generated/Syscon.sv: { file_type: systemVerilogSource } 89 | - generated/Timer.sv: { file_type: systemVerilogSource } 90 | - generated/Toplevel.sv: { file_type: systemVerilogSource } 91 | - generated/Uart.sv: { file_type: systemVerilogSource } 92 | - generated/PLL.v: { file_type: verilogSource } 93 | - generated/GPIOInOut.v: { file_type: verilogSource } 94 | 95 | bypass: 96 | generator: chisel 97 | parameters: 98 | <<: *baseparam 99 | extraargs: "--board bypass --cpufreq 50000000 --split-verilog" 100 | 101 | ulx3s: 102 | generator: chisel 103 | parameters: 104 | <<: *baseparam 105 | extraargs: "--board ulx3s --cpufreq 15000000 --invreset true --split-verilog" 106 | 107 | artya7-35t: 108 | generator: chisel 109 | parameters: 110 | <<: *baseparam 111 | extraargs: "--board artya7-35t --cpufreq 25000000 --invreset true --split-verilog" 112 | 113 | qmtech_k325t: 114 | generator: chisel 115 | parameters: 116 | <<: *baseparam 117 | extraargs: "--board qmtech_k325t --cpufreq 50000000 --invreset true --split-verilog" 118 | 119 | targets: 120 | lint: 121 | default_tool: verilator 122 | description: Lint the RTL. Uses Verilator by default 123 | filesets: [base] 124 | generate: [bypass] 125 | tools: 126 | verilator: 127 | mode: lint-only 128 | verilator_options: ["--timescale 1ns/1ps"] 129 | toplevel: Toplevel 130 | parameters: 131 | - ENABLE_INITIAL_MEM_ 132 | 133 | verilator: 134 | default_tool: verilator 135 | description: Runs the Verilator simulation 136 | filesets: [base, verilator, progload] 137 | generate: [bypass] 138 | tools: 139 | verilator: 140 | mode: cc 141 | verilator_options: [--timescale 1ns/1ps, -O3, --assert] 142 | toplevel: Toplevel 143 | parameters: 144 | - ENABLE_INITIAL_MEM_ 145 | 146 | ulx3s_85: 147 | default_tool: trellis 148 | description: ULX3S 85k version 149 | filesets: [base, ulx3s-85, proginfo, progload] 150 | generate: [ulx3s] 151 | hooks: 152 | post_run: [ulx3s-85f] 153 | tools: 154 | diamond: 155 | part: LFE5U-85F-6BG381C 156 | trellis: 157 | nextpnr_options: [--package, CABGA381, --85k, --lpf-allow-unconstrained] 158 | yosys_synth_options: [-abc9, -nowidelut] 159 | parameters: 160 | - ENABLE_INITIAL_MEM_ 161 | toplevel: Toplevel 162 | 163 | artya7-35t: 164 | default_tool: vivado 165 | description: Digilent ArtyA7-35T Board using Vivado 166 | filesets: [base, artya7-35t, progload] 167 | generate: [artya7-35t] 168 | tools: 169 | vivado: 170 | part: xc7a35ticsg324-1L 171 | toplevel: Toplevel 172 | parameters: 173 | - ENABLE_INITIAL_MEM_ 174 | 175 | artya7-35t-oss: 176 | default_tool: symbiflow 177 | description: Digilent ArtyA7-35T Board using Symbiflow OSS Toolchain 178 | filesets: [base, artya7-35t, proginfo, progload] 179 | generate: [artya7-35t] 180 | hooks: 181 | post_run: [artya7-35t] 182 | tools: 183 | symbiflow: 184 | part: xc7a35t 185 | package: csg324-1 186 | vendor: xilinx 187 | pnr: vtr 188 | toplevel: Toplevel 189 | parameters: 190 | - ENABLE_INITIAL_MEM_ 191 | 192 | qmtech_k325t: &qmtech_k325t 193 | default_tool: xray 194 | description: QMTech Kintex 7 K325T Board using Project X-Ray OSS Toolchain 195 | filesets: [base, qmtech_k325t, proginfo, progload] 196 | generate: [qmtech_k325t] 197 | hooks: 198 | post_run: [qmtech_k325t] 199 | tools: 200 | xray: 201 | part: xc7k325t 202 | package: ffg676-1 203 | yosys_synth_options: [-abc9, -flatten] 204 | nextpnr_options: [--verbose, --debug] 205 | toplevel: Toplevel 206 | parameters: 207 | - ENABLE_INITIAL_MEM_ 208 | 209 | qmtech_k325t_zyjzgw: 210 | <<: *qmtech_k325t 211 | description: QMTech Kintex 7 K325T ZYJZGW Board using Project X-Ray OSS Toolchain 212 | filesets: [base, qmtech_k325t_zyjzgw, proginfo, progload] 213 | 214 | parameters: 215 | # Used by firtool so the memories are initialized with readmemh. Ref https://github.com/llvm/circt/pull/5237 216 | ENABLE_INITIAL_MEM_: 217 | datatype: bool 218 | default: true 219 | paramtype: vlogdefine 220 | 221 | scripts: 222 | artya7-35t: 223 | cmd: [python3, proginfo.py, artya7-35t] 224 | ulx3s-85f: 225 | cmd: [python3, proginfo.py, ulx3s-85f] 226 | qmtech_k325t: 227 | cmd: [python3, proginfo.py, qmtech_k325t] 228 | -------------------------------------------------------------------------------- /chiselv/resources/pll_artya7-35t.v: -------------------------------------------------------------------------------- 1 | `timescale 1ps/1ps 2 | 3 | module PLL0 4 | 5 | ( 6 | output clko, 7 | output lock, 8 | input clki 9 | ); 10 | // Input buffering 11 | //------------------------------------ 12 | wire clki_clk_wiz_0; 13 | IBUF clkin1_ibufg 14 | (.O (clki_clk_wiz_0), 15 | .I (clki)); 16 | 17 | // Clocking PRIMITIVE 18 | //------------------------------------ 19 | 20 | // Instantiation of the MMCM PRIMITIVE 21 | // * Unused inputs are tied off 22 | // * Unused outputs are labeled unused 23 | 24 | wire clko_clk_wiz_0; 25 | wire clk_out2_clk_wiz_0; 26 | wire clk_out3_clk_wiz_0; 27 | wire clk_out4_clk_wiz_0; 28 | wire clk_out5_clk_wiz_0; 29 | wire clk_out6_clk_wiz_0; 30 | wire clk_out7_clk_wiz_0; 31 | 32 | wire [15:0] do_unused; 33 | wire drdy_unused; 34 | wire psdone_unused; 35 | wire lock_int; 36 | wire clkfbout_clk_wiz_0; 37 | wire clkfbout_buf_clk_wiz_0; 38 | wire clkfboutb_unused; 39 | wire clkout1_unused; 40 | wire clkout2_unused; 41 | wire clkout3_unused; 42 | wire clkout4_unused; 43 | wire clkout5_unused; 44 | wire clkout6_unused; 45 | wire clkfbstopped_unused; 46 | wire clkinstopped_unused; 47 | 48 | PLLE2_ADV 49 | #(.BANDWIDTH ("OPTIMIZED"), 50 | .COMPENSATION ("ZHOLD"), 51 | .STARTUP_WAIT ("FALSE"), 52 | .DIVCLK_DIVIDE (4), 53 | .CLKFBOUT_MULT (33), 54 | .CLKFBOUT_PHASE (0.000), 55 | .CLKOUT0_DIVIDE (33), 56 | .CLKOUT0_PHASE (0.000), 57 | .CLKOUT0_DUTY_CYCLE (0.500), 58 | .CLKIN1_PERIOD (10.000), 59 | .CLKIN2_PERIOD (10.312)) 60 | plle2_adv_inst 61 | // Output clocks 62 | ( 63 | .CLKFBOUT (clkfbout_clk_wiz_0), 64 | .CLKOUT0 (clko_clk_wiz_0), 65 | .CLKOUT1 (clkout1_unused), 66 | .CLKOUT2 (clkout2_unused), 67 | .CLKOUT3 (clkout3_unused), 68 | .CLKOUT4 (clkout4_unused), 69 | .CLKOUT5 (clkout5_unused), 70 | // Input clock control 71 | .CLKFBIN (clkfbout_buf_clk_wiz_0), 72 | .CLKIN1 (clki_clk_wiz_0), 73 | .CLKIN2 (clki_clk_wiz_0), 74 | .CLKINSEL (1'b1), 75 | // Ports for dynamic reconfiguration 76 | .DADDR (7'h0), 77 | .DCLK (1'b0), 78 | .DEN (1'b0), 79 | .DI (16'h0), 80 | .DO (do_unused), 81 | .DRDY (drdy_unused), 82 | .DWE (1'b0), 83 | // Other control and status signals 84 | .LOCKED (lock_int), 85 | .PWRDWN (1'b0), 86 | .RST (1'b0)); 87 | 88 | assign lock = lock_int; 89 | // Clock Monitor clock assigning 90 | //-------------------------------------- 91 | // Output buffering 92 | //----------------------------------- 93 | 94 | BUFG clkf_buf 95 | (.O (clkfbout_buf_clk_wiz_0), 96 | .I (clkfbout_clk_wiz_0)); 97 | 98 | BUFG clkout1_buf 99 | (.O (clko), 100 | .I (clko_clk_wiz_0)); 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /chiselv/resources/pll_bypass.v: -------------------------------------------------------------------------------- 1 | `timescale 1ps/1ps 2 | 3 | module PLL0 4 | 5 | ( 6 | output reg clko, 7 | output reg lock, 8 | input clki 9 | ); 10 | 11 | always @* begin 12 | lock = 1; 13 | clko = clki; 14 | end 15 | 16 | endmodule 17 | -------------------------------------------------------------------------------- /chiselv/resources/pll_qmtech_k325t.v: -------------------------------------------------------------------------------- 1 | module PLL0 2 | 3 | // This is just a bypass for the PLL0. 4 | // Input clock is 50Mhz 5 | 6 | ( 7 | input clki, 8 | output reg clko, 9 | output reg lock 10 | ); 11 | 12 | always @* begin 13 | lock = 1; 14 | clko = clki; 15 | end 16 | 17 | endmodule 18 | -------------------------------------------------------------------------------- /chiselv/resources/pll_ulx3s.v: -------------------------------------------------------------------------------- 1 | `timescale 1ps/1ps 2 | // diamond 3.7 accepts this PLL 3 | // diamond 3.8-3.9 is untested 4 | // diamond 3.10 or higher is likely to abort with error about unable to use feedback signal 5 | // cause of this could be from wrong CPHASE/FPHASE parameters 6 | module PLL0 7 | ( 8 | input clki, // 25 MHz, 0 deg 9 | output clko, // 15 MHz, 0 deg 10 | output lock 11 | ); 12 | (* FREQUENCY_PIN_CLKI="25" *) 13 | (* FREQUENCY_PIN_CLKOP="15" *) 14 | (* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *) 15 | EHXPLLL #( 16 | .PLLRST_ENA("DISABLED"), 17 | .INTFB_WAKE("DISABLED"), 18 | .STDBY_ENABLE("DISABLED"), 19 | .DPHASE_SOURCE("DISABLED"), 20 | .OUTDIVIDER_MUXA("DIVA"), 21 | .OUTDIVIDER_MUXB("DIVB"), 22 | .OUTDIVIDER_MUXC("DIVC"), 23 | .OUTDIVIDER_MUXD("DIVD"), 24 | .CLKI_DIV(5), 25 | .CLKOP_ENABLE("ENABLED"), 26 | .CLKOP_DIV(40), 27 | .CLKOP_CPHASE(19), 28 | .CLKOP_FPHASE(0), 29 | .FEEDBK_PATH("CLKOP"), 30 | .CLKFB_DIV(3) 31 | ) pll_i ( 32 | .RST(1'b0), 33 | .STDBY(1'b0), 34 | .CLKI(clki), 35 | .CLKOP(clko), 36 | .CLKFB(clko), 37 | .CLKINTFB(), 38 | .PHASESEL0(1'b0), 39 | .PHASESEL1(1'b0), 40 | .PHASEDIR(1'b1), 41 | .PHASESTEP(1'b1), 42 | .PHASELOADREG(1'b1), 43 | .PLLWAKESYNC(1'b0), 44 | .ENCLKOP(1'b0), 45 | .LOCK(lock) 46 | ); 47 | endmodule 48 | -------------------------------------------------------------------------------- /chiselv/src/ALU.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.{is, switch} 5 | import chiselv.Instruction._ 6 | 7 | class ALUPort(bitWidth: Int = 32) extends Bundle { 8 | val inst = Input(Instruction()) 9 | val a = Input(UInt(bitWidth.W)) 10 | val b = Input(UInt(bitWidth.W)) 11 | val x = Output(UInt(bitWidth.W)) 12 | } 13 | class ALU(bitWidth: Int = 32) extends Module { 14 | val io = IO(new ALUPort(bitWidth)) 15 | val out = WireDefault(0.U(bitWidth.W)) 16 | 17 | // For RV32I the shift amount is 5 bits, for RV64I is 6 bits 18 | val shamt = (if (bitWidth == 32) 5 else if (bitWidth == 64) 6 else 0) - 1 19 | 20 | switch(io.inst) { 21 | // Arithmetic 22 | is(ADD, ADDI)(out := io.a + io.b) 23 | is(SUB)(out := io.a - io.b) 24 | // Shifts 25 | is(SRA, SRAI)(out := (io.a.asSInt >> io.b(shamt, 0)).asUInt) // Signed 26 | is(SRL, SRLI)(out := io.a >> io.b(shamt, 0)) 27 | is(SLL, SLLI)(out := io.a << io.b(shamt, 0)) 28 | // Logical 29 | is(AND, ANDI)(out := io.a & io.b) 30 | is(OR, ORI)(out := io.a | io.b) 31 | is(XOR, XORI)(out := io.a ^ io.b) 32 | // Compare 33 | is(SLT, SLTI)(out := Mux(io.a.asSInt < io.b.asSInt, 1.U, 0.U)) // Signed 34 | is(SLTU, SLTIU)(out := Mux(io.a < io.b, 1.U, 0.U)) 35 | // Auxiliary 36 | is(EQ)(out := Mux(io.a === io.b, 1.U, 0.U)) 37 | is(NEQ)(out := Mux(io.a =/= io.b, 1.U, 0.U)) 38 | is(GTE)(out := Mux(io.a.asSInt >= io.b.asSInt, 1.U, 0.U)) 39 | is(GTEU)(out := Mux(io.a >= io.b, 1.U, 0.U)) 40 | } 41 | 42 | io.x := out 43 | } 44 | -------------------------------------------------------------------------------- /chiselv/src/Blink.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.Counter 5 | 6 | /** 7 | * The blinking LED module. 8 | * 9 | * @constructor 10 | * creates a new blinking LED module that flashes every second. 11 | * @param freq 12 | * the frequency of the core in Hertz. 13 | * @param startOn 14 | * if true, the LED is initially on. 15 | * @param io_led0 16 | * (Output) is the led output 17 | */ 18 | class Blinky(freq: Int, startOn: Boolean = false) extends Module { 19 | val io = IO(new Bundle { 20 | val led0 = Output(Bool()) 21 | }) 22 | 23 | // Blink leds every second (start on) 24 | val led = RegInit(startOn.B) 25 | val (_, counterWrap) = Counter(true.B, freq / 2) 26 | when(counterWrap) { 27 | led := ~led 28 | } 29 | 30 | io.led0 := led 31 | } 32 | -------------------------------------------------------------------------------- /chiselv/src/CPUSingleCycle.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.experimental.Analog 5 | import chisel3.util.{Cat, Fill, is, switch} 6 | import chiselv.Instruction._ 7 | 8 | class CPUSingleCycle( 9 | cpuFrequency: Int, 10 | entryPoint: Long, 11 | bitWidth: Int = 32, 12 | instructionMemorySize: Int = 1 * 1024, 13 | dataMemorySize: Int = 1 * 1024, 14 | numGPIO: Int = 8, 15 | ) extends Module { 16 | val io = IO(new Bundle { 17 | val GPIO0External = Analog(numGPIO.W) // GPIO external port 18 | 19 | val UART0Port = Flipped(new UARTPort) // UART0 data port 20 | val SysconPort = Flipped(new SysconPort(bitWidth)) 21 | val instructionMemPort = Flipped(new InstructionMemPort(bitWidth, instructionMemorySize)) 22 | val dataMemPort = Flipped(new MemoryPortDual(bitWidth, dataMemorySize)) 23 | }) 24 | 25 | val stall = WireDefault(false.B) 26 | 27 | // Instantiate and initialize the Register Bank 28 | val registerBank = Module(new RegisterBank(bitWidth)) 29 | registerBank.io.writeEnable := false.B 30 | registerBank.io.regwr_data := 0.U 31 | registerBank.io.stall := stall 32 | 33 | // Instantiate and initialize the Program Counter 34 | val PC = Module(new ProgramCounter(bitWidth, entryPoint)) 35 | PC.io.writeEnable := false.B 36 | PC.io.dataIn := 0.U 37 | PC.io.writeAdd := false.B 38 | 39 | // Instantiate and initialize the ALU 40 | val ALU = Module(new ALU(bitWidth)) 41 | ALU.io.inst := ERR_INST 42 | ALU.io.a := 0.U 43 | ALU.io.b := 0.U 44 | 45 | // Instantiate and initialize the Instruction Decoder 46 | val decoder = Module(new Decoder(bitWidth)) 47 | decoder.io.op := 0.U 48 | 49 | // Instantiate and initialize the Memory IO Manager 50 | val memoryIOManager = Module(new MemoryIOManager(bitWidth, dataMemorySize)) 51 | memoryIOManager.io.MemoryIOPort.readRequest := false.B 52 | memoryIOManager.io.MemoryIOPort.writeRequest := false.B 53 | memoryIOManager.io.MemoryIOPort.readAddr := 0.U 54 | memoryIOManager.io.MemoryIOPort.writeAddr := 0.U 55 | memoryIOManager.io.MemoryIOPort.writeData := 0.U 56 | memoryIOManager.io.MemoryIOPort.dataSize := 0.U 57 | memoryIOManager.io.MemoryIOPort.writeMask := 0.U 58 | // Connect MMIO to the devices 59 | memoryIOManager.io.DataMemPort <> io.dataMemPort 60 | memoryIOManager.io.UART0Port <> io.UART0Port 61 | memoryIOManager.io.SysconPort <> io.SysconPort 62 | 63 | // Instantiate and connect GPIO 64 | val GPIO0 = Module(new GPIO(bitWidth, numGPIO)) 65 | memoryIOManager.io.GPIO0Port <> GPIO0.io.GPIOPort 66 | if (numGPIO > 0) { 67 | GPIO0.io.externalPort <> io.GPIO0External 68 | } 69 | 70 | // Instantiate and connect the Timer 71 | val timer0 = Module(new Timer(bitWidth, cpuFrequency)) 72 | memoryIOManager.io.Timer0Port <> timer0.io 73 | 74 | // --------------- CPU Control --------------- // 75 | // State of the CPU Stall 76 | stall := memoryIOManager.io.stall 77 | when(!stall) { 78 | // If CPU is stalled, do not advance PC 79 | PC.io.writeEnable := true.B 80 | PC.io.dataIn := PC.io.PC4 81 | } 82 | 83 | // Connect PC output to instruction memory 84 | when(io.instructionMemPort.ready) { 85 | io.instructionMemPort.readAddr := PC.io.PC 86 | }.otherwise( 87 | io.instructionMemPort.readAddr := DontCare 88 | ) 89 | 90 | // Connect the instruction memory to the decoder 91 | decoder.io.op := io.instructionMemPort.readData 92 | 93 | // Connect the decoder output to register bank inputs 94 | registerBank.io.regwr_addr := decoder.io.rd 95 | registerBank.io.rs1_addr := decoder.io.rs1 96 | registerBank.io.rs2_addr := decoder.io.rs2 97 | 98 | // ----- CPU Operations ----- // 99 | 100 | // ALU Operations 101 | when(decoder.io.toALU) { 102 | ALU.io.inst := decoder.io.inst 103 | ALU.io.a := registerBank.io.rs1 104 | ALU.io.b := Mux( 105 | decoder.io.use_imm, 106 | decoder.io.imm.asUInt, 107 | registerBank.io.rs2, 108 | ) 109 | 110 | registerBank.io.writeEnable := true.B 111 | registerBank.io.regwr_data := ALU.io.x 112 | } 113 | 114 | // Branch Operations 115 | when(decoder.io.branch) { 116 | ALU.io.a := registerBank.io.rs1 117 | ALU.io.b := registerBank.io.rs2 118 | switch(decoder.io.inst) { 119 | is(BEQ)(ALU.io.inst := EQ) 120 | is(BNE)(ALU.io.inst := NEQ) 121 | is(BLT)(ALU.io.inst := SLT) 122 | is(BGE)(ALU.io.inst := GTE) 123 | is(BLTU)(ALU.io.inst := SLTU) 124 | is(BGEU)(ALU.io.inst := GTEU) 125 | } 126 | when(ALU.io.x === 1.U) { 127 | PC.io.writeEnable := true.B 128 | PC.io.writeAdd := true.B 129 | PC.io.dataIn := decoder.io.imm.asUInt 130 | } 131 | } 132 | 133 | // Jump Operations 134 | when(decoder.io.jump) { 135 | // Write next instruction address to rd 136 | registerBank.io.writeEnable := true.B 137 | // Use the ALU to get the result 138 | ALU.io.inst := ADD 139 | ALU.io.a := PC.io.PC 140 | ALU.io.b := 4.U 141 | registerBank.io.regwr_data := ALU.io.x 142 | 143 | PC.io.writeEnable := true.B 144 | when(decoder.io.inst === JAL) { 145 | // Set PC to jump address 146 | PC.io.writeAdd := true.B 147 | PC.io.dataIn := decoder.io.imm.asUInt 148 | } 149 | when(decoder.io.inst === JALR) { 150 | // Set PC to jump address 151 | PC.io.dataIn := Cat( 152 | (registerBank.io.rs1 + decoder.io.imm.asUInt)(31, 1), 153 | 0.U, 154 | ) 155 | } 156 | } 157 | 158 | // LUI 159 | when(decoder.io.inst === LUI) { 160 | registerBank.io.writeEnable := true.B 161 | registerBank.io.regwr_data := decoder.io.imm.asUInt 162 | } 163 | 164 | // AUIPC 165 | when(decoder.io.inst === AUIPC) { 166 | registerBank.io.writeEnable := true.B 167 | ALU.io.inst := ADD 168 | ALU.io.a := PC.io.PC 169 | ALU.io.b := 170 | decoder.io.imm.asUInt 171 | registerBank.io.regwr_data := ALU.io.x 172 | } 173 | 174 | // Loads & Stores 175 | when(decoder.io.is_load || decoder.io.is_store) { 176 | // Use the ALU to get the resulting address 177 | ALU.io.inst := ADD 178 | ALU.io.a := registerBank.io.rs1 179 | ALU.io.b := decoder.io.imm.asUInt 180 | 181 | memoryIOManager.io.MemoryIOPort.writeAddr := ALU.io.x 182 | memoryIOManager.io.MemoryIOPort.readAddr := ALU.io.x 183 | } 184 | 185 | when(decoder.io.is_load) { 186 | val dataSize = WireDefault(0.U(2.W)) // Data size, 1 = byte, 2 = halfword, 3 = word 187 | val dataOut = WireDefault(0.U(32.W)) 188 | 189 | // Load Word 190 | when(decoder.io.inst === LW) { 191 | dataSize := 3.U 192 | dataOut := memoryIOManager.io.MemoryIOPort.readData 193 | } 194 | // Load Halfword 195 | when(decoder.io.inst === LH) { 196 | dataSize := 2.U 197 | dataOut := Cat( 198 | Fill(16, memoryIOManager.io.MemoryIOPort.readData(15)), 199 | memoryIOManager.io.MemoryIOPort.readData(15, 0), 200 | ) 201 | } 202 | // Load Halfword Unsigned 203 | when(decoder.io.inst === LHU) { 204 | dataSize := 2.U 205 | dataOut := Cat(Fill(16, 0.U), memoryIOManager.io.MemoryIOPort.readData(15, 0)) 206 | } 207 | // Load Byte 208 | when(decoder.io.inst === LB) { 209 | dataSize := 1.U 210 | dataOut := Cat( 211 | Fill(24, memoryIOManager.io.MemoryIOPort.readData(7)), 212 | memoryIOManager.io.MemoryIOPort.readData(7, 0), 213 | ) 214 | } 215 | // Load Byte Unsigned 216 | when(decoder.io.inst === LBU) { 217 | dataSize := 1.U 218 | dataOut := Cat(Fill(24, 0.U), memoryIOManager.io.MemoryIOPort.readData(7, 0)) 219 | } 220 | memoryIOManager.io.MemoryIOPort.readRequest := decoder.io.is_load 221 | memoryIOManager.io.MemoryIOPort.dataSize := dataSize 222 | registerBank.io.writeEnable := true.B 223 | registerBank.io.regwr_data := dataOut 224 | } 225 | 226 | when(decoder.io.is_store) { 227 | // Define if operation is a load or store 228 | memoryIOManager.io.MemoryIOPort.writeRequest := decoder.io.is_store 229 | 230 | // Stores 231 | val dataOut = WireDefault(0.U(32.W)) 232 | val dataSize = WireDefault(0.U(2.W)) // Data size, 1 = byte, 2 = halfword, 3 = word 233 | 234 | // Store Word 235 | when(decoder.io.inst === SW) { 236 | dataOut := registerBank.io.rs2 237 | dataSize := 3.U 238 | } 239 | // Store Halfword 240 | when(decoder.io.inst === SH) { 241 | dataOut := Cat(Fill(16, 0.U), registerBank.io.rs2(15, 0)) 242 | dataSize := 2.U 243 | } 244 | // Store Byte 245 | when(decoder.io.inst === SB) { 246 | dataOut := Cat(Fill(24, 0.U), registerBank.io.rs2(7, 0)) 247 | dataSize := 1.U 248 | } 249 | memoryIOManager.io.MemoryIOPort.dataSize := dataSize 250 | memoryIOManager.io.MemoryIOPort.writeData := dataOut 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /chiselv/src/Constants.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3.ChiselEnum 4 | 5 | object Instruction extends ChiselEnum { 6 | val ERR_INST, 7 | // RV32I 8 | ADD, ADDI, SUB, LUI, AUIPC, // Arithmetic 9 | SLL, SLLI, SRL, SRLI, SRA, SRAI, // Shifts 10 | AND, ANDI, OR, ORI, XOR, XORI, // Logical 11 | SLT, SLTI, SLTU, SLTIU, // Compare 12 | BEQ, BNE, BLT, BGE, BLTU, BGEU, // Branches 13 | JAL, JALR, // Jump & Link 14 | FENCE, FENCEI, // Sync 15 | ECALL, EBREAK, // Environment 16 | CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI, // CSR 17 | LB, LH, LBU, LHU, LW, // Loads 18 | SB, SH, SW, // Stores 19 | EQ, NEQ, GTE, GTEU // Not instructions but auxiliaries 20 | = Value 21 | } 22 | 23 | object InstructionType extends ChiselEnum { 24 | val IN_ERR, INST_R, INST_I, INST_S, INST_B, INST_U, INST_J, INST_Z = Value 25 | } 26 | -------------------------------------------------------------------------------- /chiselv/src/DataMemory.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.experimental.loadMemoryFromFileInline 5 | import chisel3.util.log2Ceil 6 | 7 | class MemoryPortDual(val bitWidth: Int, val addressSize: Long) extends Bundle { 8 | val readAddress = Input(UInt(log2Ceil(addressSize).W)) 9 | val readData = Output(UInt(bitWidth.W)) 10 | val writeAddress = Input(UInt(log2Ceil(addressSize).W)) 11 | val writeData = Input(UInt(bitWidth.W)) 12 | val writeMask = Input(UInt((bitWidth / 8).W)) 13 | val dataSize = Input(UInt(2.W)) 14 | val writeEnable = Input(Bool()) 15 | } 16 | class DualPortRAM( 17 | bitWidth: Int = 32, 18 | sizeBytes: Long = 1, 19 | memoryFile: String = "", 20 | debugMsg: Boolean = false, 21 | ) extends Module { 22 | val words = sizeBytes / bitWidth 23 | val io = IO(new MemoryPortDual(bitWidth, sizeBytes)) 24 | 25 | if (debugMsg) { 26 | println(s"Dual-port Memory Parameters:") 27 | println(s" Words: $words") 28 | println(s" Size: " + words * bitWidth + " bytes") 29 | println(s" Bit width: $bitWidth bit") 30 | println(s" Addr Width: " + io.readAddress.getWidth + " bit") 31 | } 32 | 33 | val mem = SyncReadMem(words, UInt(bitWidth.W)) 34 | 35 | // Divide memory address by 4 to get the word due to pc+4 addressing 36 | val readAddress = io.readAddress >> 2 37 | val writeAddress = io.writeAddress >> 2 38 | 39 | if (memoryFile.trim().nonEmpty) { 40 | if (debugMsg) println(s" Load memory file: " + memoryFile) 41 | loadMemoryFromFileInline(mem, memoryFile) 42 | } 43 | 44 | io.readData := mem.read(readAddress) 45 | 46 | when(io.writeEnable === true.B) { 47 | mem.write(writeAddress, io.writeData) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /chiselv/src/GPIO.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.experimental.Analog 5 | import chisel3.util.HasBlackBoxInline // For Analog type 6 | 7 | class GPIOPort(bitWidth: Int = 32) extends Bundle { 8 | val dataIn = Input(UInt(bitWidth.W)) 9 | val valueOut = Output(UInt(bitWidth.W)) 10 | val directionOut = Output(UInt(bitWidth.W)) 11 | val writeValue = Input(Bool()) 12 | val writeDirection = Input(Bool()) 13 | val stall = Output(Bool()) // >1 => Stall, 0 => Run 14 | } 15 | 16 | class GPIO(bitWidth: Int = 32, numGPIO: Int = 8) extends Module { 17 | require( 18 | numGPIO <= bitWidth, 19 | "Number of GPIOs must be less than or equal to the bitwidth, if needed, create another GPIO bank.", 20 | ) 21 | val io = IO(new Bundle { 22 | val GPIOPort = new GPIOPort(bitWidth) 23 | val externalPort = Analog(numGPIO.W) 24 | }) 25 | 26 | val GPIO = RegInit(0.U(bitWidth.W)) 27 | val direction = RegInit(0.U(bitWidth.W)) // 0 = input, 1 = output 28 | 29 | io.GPIOPort.stall := false.B 30 | io.GPIOPort.directionOut := direction 31 | 32 | // Only instantiate GPIO external interface if needed 33 | // this avoids using Verilator backend on tests that don't need it 34 | if (numGPIO > 0) { 35 | val InOut = Module(new GPIOInOut(numGPIO)) 36 | io.GPIOPort.valueOut := InOut.io.dataOut 37 | InOut.io.dataIn := GPIO 38 | InOut.io.dir := direction 39 | io.externalPort <> InOut.io.dataIO 40 | } else { 41 | io.GPIOPort.valueOut := 0.U 42 | io.externalPort := DontCare 43 | } 44 | 45 | when(io.GPIOPort.writeValue) { 46 | GPIO := io.GPIOPort.dataIn 47 | } 48 | when(io.GPIOPort.writeDirection) { 49 | direction := io.GPIOPort.dataIn 50 | } 51 | } 52 | 53 | class GPIOInOut(numGPIO: Int) extends BlackBox with HasBlackBoxInline { 54 | val io = IO(new Bundle { 55 | val dataIn = Input(UInt(numGPIO.W)) 56 | val dataOut = Output(UInt(numGPIO.W)) 57 | val dir = Input(UInt(numGPIO.W)) 58 | val dataIO = Analog(numGPIO.W) 59 | }) 60 | setInline( 61 | "GPIOInOut.v", 62 | s"""|// This module is inspired by Lucas Teske's Riscow digital port 63 | |// https://github.com/racerxdl/riskow/blob/main/devices/digital_port.v 64 | |// 65 | |module GPIOInOut ( 66 | | inout [${numGPIO - 1}:0] dataIO, 67 | | input [${numGPIO - 1}:0] dataIn, 68 | | output [${numGPIO - 1}:0] dataOut, 69 | | input [${numGPIO - 1}:0] dir); 70 | | 71 | | generate 72 | | genvar idx; 73 | | for(idx = 0; idx < $numGPIO; idx = idx+1) begin: register 74 | | `ifdef SIMULATION 75 | | assign dataIO[idx] = dir[idx] ? dataIn[idx] : 1'b0; 76 | | `else 77 | | assign dataIO [idx]= dir[idx] ? dataIn[idx] : 1'bZ; 78 | | `endif 79 | | end 80 | | endgenerate 81 | | assign dataOut = dataIO; 82 | | 83 | |endmodule 84 | |""".stripMargin, 85 | ) 86 | } 87 | -------------------------------------------------------------------------------- /chiselv/src/InstructionMemory.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.experimental.loadMemoryFromFileInline 5 | import chisel3.util.log2Ceil 6 | 7 | class InstructionMemPort(val bitWidth: Int, val sizeBytes: Long) extends Bundle { 8 | val readAddr = Input(UInt(log2Ceil(sizeBytes).W)) 9 | val readData = Output(UInt(bitWidth.W)) 10 | val ready = Output(Bool()) 11 | } 12 | 13 | class InstructionMemory( 14 | bitWidth: Int = 32, 15 | sizeBytes: Long = 1, 16 | memoryFile: String = "", 17 | ) extends Module { 18 | val words = sizeBytes / bitWidth 19 | val io = IO(new InstructionMemPort(bitWidth, sizeBytes)) 20 | 21 | val mem = Mem(words, UInt(bitWidth.W)) 22 | // Divide memory address by 4 to get the word due to pc+4 addressing 23 | val readAddress = io.readAddr >> 2 24 | if (memoryFile.trim().nonEmpty) { 25 | loadMemoryFromFileInline(mem, memoryFile) 26 | } 27 | 28 | io.readData := mem.read(readAddress) 29 | io.ready := true.B 30 | } 31 | -------------------------------------------------------------------------------- /chiselv/src/PLLBlackBox.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import scala.io.Source 4 | 5 | import chisel3._ 6 | import chisel3.util.HasBlackBoxInline 7 | 8 | class PLL0(board: String) extends BlackBox with HasBlackBoxInline { 9 | val io = IO(new Bundle { 10 | val clki = Input(Clock()) 11 | val clko = Output(Clock()); 12 | val lock = Output(Clock()) 13 | }) 14 | 15 | val filename = "pll_" + board + ".v" 16 | val verilog = Source.fromResource(filename).getLines().mkString("\n") 17 | setInline("PLL.v", verilog) 18 | } 19 | -------------------------------------------------------------------------------- /chiselv/src/ProgramCounter.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | 5 | class PCPort(bitWidth: Int = 32) extends Bundle { 6 | val dataIn = Input(UInt(bitWidth.W)) 7 | val PC = Output(UInt(bitWidth.W)) 8 | val PC4 = Output(UInt(bitWidth.W)) 9 | val writeEnable = Input(Bool()) 10 | val writeAdd = Input(Bool()) // 1 => Add dataIn to PC, 0 => Set dataIn to PC 11 | } 12 | 13 | class ProgramCounter(regWidth: Int = 32, entryPoint: Long = 0) extends Module { 14 | val io = IO(new PCPort(regWidth)) 15 | 16 | val pc = RegInit(entryPoint.U(regWidth.W)) 17 | when(io.writeEnable) { 18 | pc := Mux(io.writeAdd, (pc.asSInt + io.dataIn.asSInt).asUInt, io.dataIn) 19 | } 20 | io.PC4 := pc + 4.U 21 | io.PC := pc 22 | } 23 | -------------------------------------------------------------------------------- /chiselv/src/RVFI_Wrapper.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.{is, switch} 5 | import circt.stage.ChiselStage 6 | import mainargs.{Leftover, ParserForMethods, arg, main} 7 | 8 | // Chisel Bundle implementation of RISC-V Formal Interface (RVFI) 9 | class RVFIPort extends Bundle { 10 | val valid = Output(Bool()) 11 | val order = Output(UInt(64.W)) 12 | val insn = Output(UInt(32.W)) 13 | val trap = Output(Bool()) 14 | val halt = Output(Bool()) 15 | val intr = Output(Bool()) 16 | val ixl = Output(UInt(2.W)) 17 | val mode = Output(UInt(2.W)) 18 | val rs1_addr = Output(UInt(5.W)) 19 | val rs1_rdata = Output(UInt(32.W)) 20 | val rs2_addr = Output(UInt(5.W)) 21 | val rs2_rdata = Output(UInt(32.W)) 22 | val rd_addr = Output(UInt(5.W)) 23 | val rd_wdata = Output(UInt(32.W)) 24 | val pc_rdata = Output(UInt(32.W)) 25 | val pc_wdata = Output(UInt(32.W)) 26 | val mem_addr = Output(UInt(32.W)) 27 | val mem_rmask = Output(UInt(4.W)) 28 | val mem_wmask = Output(UInt(4.W)) 29 | val mem_rdata = Output(UInt(32.W)) 30 | val mem_wdata = Output(UInt(32.W)) 31 | } 32 | 33 | class RVFICPUWrapper( 34 | cpuFrequency: Int = 50000000, 35 | bitWidth: Int = 32, 36 | instructionMemorySize: Int = 64 * 1024, 37 | dataMemorySize: Int = 64 * 1024, 38 | ) extends CPUSingleCycle( 39 | cpuFrequency = cpuFrequency, 40 | entryPoint = 0x0, 41 | bitWidth = bitWidth, 42 | instructionMemorySize = instructionMemorySize, 43 | dataMemorySize = dataMemorySize, 44 | numGPIO = 0, 45 | ) { 46 | val rvfi = IO(new RVFIPort) // RVFI interface for RISCV-Formal 47 | 48 | // RVFI Interface 49 | val rvfi_valid = RegInit(false.B) 50 | val rvfi_order = RegInit(0.U(64.W)) 51 | val rvfi_insn = RegInit(0.U(32.W)) 52 | 53 | val rvfi_halt = RegInit(false.B) 54 | 55 | val rvfi_intr = RegInit(false.B) 56 | val rvfi_mode = RegInit(3.U(2.W)) 57 | 58 | val rvfi_mem_size_mask = WireDefault(0.U(2.W)) 59 | switch(memoryIOManager.io.DataMemPort.dataSize) { 60 | is(1.U)(rvfi_mem_size_mask := 1.U) 61 | is(2.U)(rvfi_mem_size_mask := 3.U) 62 | is(3.U)(rvfi_mem_size_mask := 15.U) 63 | } 64 | 65 | // Connect RVFI interface outputs 66 | rvfi_valid := !reset.asBool && !stall 67 | when(rvfi_valid) { 68 | rvfi_order := rvfi_order + 1.U 69 | } 70 | rvfi.valid := rvfi_valid 71 | rvfi.order := rvfi_order 72 | rvfi.insn := decoder.io.op 73 | 74 | rvfi.rs1_addr := registerBank.io.rs1_addr 75 | rvfi.rs1_rdata := registerBank.io.rs1 76 | rvfi.rs2_addr := registerBank.io.rs2_addr 77 | rvfi.rs2_rdata := registerBank.io.rs2 78 | rvfi.rd_addr := registerBank.io.regwr_addr 79 | rvfi.rd_wdata := registerBank.io.regwr_data 80 | 81 | rvfi.pc_rdata := PC.io.PC 82 | rvfi.pc_wdata := Mux( 83 | PC.io.writeAdd, 84 | (PC.io.PC.asSInt + PC.io.dataIn.asSInt).asUInt, 85 | PC.io.PC4, 86 | ) 87 | 88 | rvfi.mem_addr := Mux(decoder.io.is_load || decoder.io.is_store, ALU.io.x, 0.U) 89 | rvfi.mem_rdata := Mux(decoder.io.is_load, memoryIOManager.io.DataMemPort.readData, 0.U) 90 | rvfi.mem_rmask := Mux(decoder.io.is_load, rvfi_mem_size_mask, 0.U) 91 | 92 | rvfi.mem_wdata := Mux(decoder.io.is_store, memoryIOManager.io.DataMemPort.writeData, 0.U) 93 | rvfi.mem_wmask := Mux(decoder.io.is_store, rvfi_mem_size_mask, 0.U) 94 | 95 | rvfi.mode := rvfi_mode 96 | rvfi.trap := false.B 97 | when(decoder.io.inst === Instruction.ERR_INST) { 98 | rvfi.trap := true.B 99 | } 100 | 101 | rvfi.halt := rvfi_halt 102 | rvfi.intr := rvfi_intr 103 | rvfi.ixl := 1.U 104 | } 105 | 106 | // This is the Topmodule used in RISCV-Formal 107 | class RVFI( 108 | bitWidth: Int = 32 109 | ) extends Module { 110 | val io = IO(new Bundle { 111 | val imem_addr = Output(UInt(bitWidth.W)) 112 | val imem_ready = Input(Bool()) 113 | val imem_rdata = Input(UInt(bitWidth.W)) 114 | 115 | val dmem_rdata = Input(UInt(bitWidth.W)) 116 | val dmem_raddr = Output(UInt(bitWidth.W)) 117 | val dmem_waddr = Output(UInt(bitWidth.W)) 118 | val dmem_wdata = Output(UInt(bitWidth.W)) 119 | val dmem_wen = Output(Bool()) 120 | }) 121 | val rvfi = IO(new RVFIPort) // RVFI interface for RISCV-Formal 122 | 123 | // Instantiate the wrapped CPU with RVFI interface 124 | val CPU = Module( 125 | new RVFICPUWrapper(bitWidth) 126 | ) 127 | 128 | // Initialize unused IO 129 | CPU.io.UART0Port.rxQueue.bits := 0.U 130 | CPU.io.UART0Port.rxEmpty := true.B 131 | CPU.io.UART0Port.txQueue.ready := true.B 132 | CPU.io.UART0Port.txFull := false.B 133 | CPU.io.UART0Port.txEmpty := true.B 134 | CPU.io.UART0Port.rxFull := false.B 135 | CPU.io.UART0Port.rxQueue.valid := false.B 136 | CPU.io.SysconPort.DataOut := 0.U 137 | 138 | // Connect RVFI port 139 | rvfi <> CPU.rvfi 140 | 141 | // Connect instruction memory 142 | io.imem_addr := CPU.io.instructionMemPort.readAddr 143 | CPU.io.instructionMemPort.readData := io.imem_rdata 144 | CPU.io.instructionMemPort.ready := io.imem_ready 145 | 146 | // Connect data memory 147 | io.dmem_waddr := CPU.io.dataMemPort.writeAddress 148 | io.dmem_wdata := CPU.io.dataMemPort.writeData 149 | io.dmem_wen := CPU.io.dataMemPort.writeEnable 150 | 151 | io.dmem_raddr := CPU.io.dataMemPort.readAddress 152 | CPU.io.dataMemPort.readData := io.dmem_rdata 153 | } 154 | 155 | object RVFI { 156 | @main 157 | def run(@arg(short = 'c', doc = "Chisel arguments") chiselArgs: Leftover[String]) = 158 | // Generate SystemVerilog 159 | ChiselStage.emitSystemVerilogFile( 160 | new RVFI, 161 | chiselArgs.value.toArray, 162 | Array( 163 | // Removes debug information from the generated Verilog 164 | "--strip-debug-info", 165 | // Disables reg and memory randomization on initialization 166 | "--disable-all-randomization", 167 | // Creates memories with write masks in a single reg. Ref. https://github.com/llvm/circt/pull/4275 168 | "--lower-memories", 169 | // Avoids "unexpected TOK_AUTOMATIC" errors in Yosys. Ref. https://github.com/llvm/circt/issues/4751 170 | "--lowering-options=disallowLocalVariables,disallowPackedArrays", 171 | // Splits the generated Verilog into multiple files 172 | // "--split-verilog", 173 | // Generates the Verilog files in the specified directory 174 | "-o=./generated/Toplevel_RVFI.sv", 175 | ), 176 | ) 177 | 178 | def main(args: Array[String]): Unit = 179 | ParserForMethods(this).runOrExit(args.toIndexedSeq) 180 | } 181 | -------------------------------------------------------------------------------- /chiselv/src/RegisterBank.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.log2Ceil 5 | 6 | class RegisterBankPort(bitWidth: Int = 32) extends Bundle { 7 | val rs1 = Output(UInt(bitWidth.W)) 8 | val rs2 = Output(UInt(bitWidth.W)) 9 | val rs1_addr = Input(UInt(log2Ceil(bitWidth).W)) 10 | val rs2_addr = Input(UInt(log2Ceil(bitWidth).W)) 11 | val regwr_addr = Input(UInt(log2Ceil(bitWidth).W)) 12 | val regwr_data = Input(UInt(bitWidth.W)) 13 | val writeEnable = Input(Bool()) 14 | val stall = Input(Bool()) // >1 => Stall, 0 => Run 15 | } 16 | 17 | class RegisterBank(numRegs: Int = 32, regWidth: Int = 32) extends Module { 18 | val io = IO(new RegisterBankPort(regWidth)) 19 | 20 | val regs = RegInit(VecInit(Seq.fill(numRegs)(0.U(regWidth.W)))) 21 | regs(0) := 0.U // Register x0 is always 0 22 | 23 | io.rs1 := regs(io.rs1_addr) 24 | io.rs2 := regs(io.rs2_addr) 25 | when(io.writeEnable && io.regwr_addr =/= 0.U && !io.stall) { 26 | regs(io.regwr_addr) := io.regwr_data 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /chiselv/src/SOC.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.experimental.Analog 5 | 6 | class SOC( 7 | cpuFrequency: Int, 8 | entryPoint: Long, 9 | bitWidth: Int = 32, 10 | instructionMemorySize: Int = 1 * 1024, 11 | dataMemorySize: Int = 1 * 1024, 12 | memoryFile: String = "", 13 | ramFile: String = "", 14 | numGPIO: Int = 8, 15 | ) extends Module { 16 | val io = IO(new Bundle { 17 | val led0 = Output(Bool()) // LED 0 is the heartbeat 18 | val GPIO0External = Analog(numGPIO.W) // GPIO external port 19 | val UART0SerialPort = new UARTSerialPort // UART0 serial port 20 | }) 21 | 22 | // Heartbeat LED - Keep on if reached an error 23 | val blink = Module(new Blinky(cpuFrequency)) 24 | io.led0 := blink.io.led0 25 | 26 | // Instantiate and initialize the Instruction memory 27 | val instructionMemory = Module(new InstructionMemory(bitWidth, instructionMemorySize, memoryFile)) 28 | instructionMemory.io.readAddr := 0.U 29 | 30 | // Instantiate and initialize the Data memory 31 | val dataMemory = Module(new DualPortRAM(bitWidth, dataMemorySize, ramFile)) 32 | dataMemory.io.writeEnable := false.B 33 | dataMemory.io.writeData := 0.U 34 | dataMemory.io.readAddress := 0.U 35 | dataMemory.io.writeAddress := 0.U 36 | dataMemory.io.dataSize := 0.U 37 | dataMemory.io.writeMask := 0.U 38 | 39 | // Instantiate and connect the UART 40 | val fifoLength = 128 41 | val rxOverclock = 16 42 | val UART0 = Module(new Uart(fifoLength, rxOverclock)) 43 | UART0.io.serialPort <> io.UART0SerialPort 44 | 45 | // Instantiate the Syscon Module 46 | val syscon = Module(new Syscon(32, cpuFrequency, numGPIO, entryPoint, instructionMemorySize, dataMemorySize)) 47 | 48 | // Instantiate our core 49 | val core = Module( 50 | new CPUSingleCycle(cpuFrequency, entryPoint, bitWidth, instructionMemorySize, dataMemorySize, numGPIO) 51 | ) 52 | 53 | // Connect the core to the devices 54 | core.io.instructionMemPort <> instructionMemory.io 55 | core.io.dataMemPort <> dataMemory.io 56 | core.io.UART0Port <> UART0.io.dataPort 57 | core.io.SysconPort <> syscon.io 58 | if (numGPIO > 0) { 59 | core.io.GPIO0External <> io.GPIO0External 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /chiselv/src/Syscon.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.{is, switch} 5 | 6 | class SysconPort(val bitWidth: Int) extends Bundle { 7 | val Address = Input(UInt(12.W)) 8 | val DataOut = Output(UInt(bitWidth.W)) 9 | } 10 | 11 | class Syscon( 12 | bitWidth: Int = 32, 13 | clockFreq: Long, 14 | numGPIO0: Int, 15 | bootAddr: Long, 16 | romSize: Int, 17 | ramSize: Int, 18 | ) extends Module { 19 | val io = IO(new SysconPort(bitWidth)) 20 | 21 | val dataOut = WireDefault(0.U(bitWidth.W)) 22 | 23 | switch(io.Address) { 24 | is(0x0L.U)(dataOut := 0xbaad_cafeL.U) 25 | // Clock frequency - (0x0000_1008) 26 | is(0x8L.U)(dataOut := clockFreq.asUInt) 27 | // Has UART0 - (0x0000_1010) 28 | is(0x10L.U)(dataOut := 1.U) 29 | // Has GPIO0 - (0x0000_1018) 30 | is(0x18L.U)(dataOut := 1.U) 31 | // Has PWM0 - (0x0000_1020) 32 | is(0x20L.U)(dataOut := 0.U) 33 | // Has Timer0 - (0x0000_1024) 34 | is(0x24L.U)(dataOut := 1.U) 35 | // Num GPIOs in GPIO0 - (0x0000_1028) 36 | is(0x28L.U)(dataOut := numGPIO0.asUInt) 37 | // Boot io.address - (0x0000_102c) 38 | is(0x2cL.U)(dataOut := bootAddr.asUInt) 39 | // ROM Size - (0x0000_1030) 40 | is(0x30L.U)(dataOut := romSize.asUInt) 41 | // RAM Size - (0x0000_1034) 42 | is(0x34L.U)(dataOut := ramSize.asUInt) 43 | } 44 | 45 | io.DataOut := dataOut 46 | } 47 | -------------------------------------------------------------------------------- /chiselv/src/Timer.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util.Counter 5 | 6 | class TimerPort(bitWidth: Int = 32) extends Bundle { 7 | val dataIn = Input(UInt(bitWidth.W)) 8 | val dataOut = Output(UInt(bitWidth.W)) 9 | val writeEnable = Input(Bool()) 10 | val stall = Output(Bool()) // >1 => Stall, 0 => Run 11 | } 12 | 13 | class Timer(bitWidth: Int = 32, cpuFrequency: Int) extends Module { 14 | val io = IO(new TimerPort(bitWidth)) 15 | 16 | val counter = RegInit(0.U(bitWidth.W)) 17 | 18 | when(io.writeEnable) { 19 | counter := io.dataIn 20 | }.otherwise { 21 | // Count up in milliseconds 22 | val (_, counterWrap) = Counter(true.B, cpuFrequency / 1000) 23 | when(counterWrap) { 24 | counter := counter + 1.U 25 | } 26 | } 27 | io.dataOut := counter 28 | io.stall := false.B 29 | } 30 | -------------------------------------------------------------------------------- /chiselv/src/Toplevel.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.experimental.Analog 5 | import circt.stage.ChiselStage 6 | import mainargs.{Leftover, ParserForMethods, arg, main} 7 | 8 | // Project Top level 9 | class Toplevel( 10 | board: String, 11 | invReset: Boolean = true, 12 | cpuFrequency: Int, 13 | ) extends Module { 14 | val io = FlatIO(new Bundle { 15 | val led0 = Output(Bool()) // LED 0 is the heartbeat 16 | val UART0 = new UARTSerialPort // UART 0 17 | val GPIO0 = Analog(8.W) // GPIO 0 18 | }) 19 | 20 | // Instantiate PLL module based on board 21 | val pll = Module(new PLL0(board)) 22 | pll.io.clki := clock 23 | // Define if reset should be inverted based on board switch 24 | val customReset = if (invReset) ~reset.asBool else reset 25 | 26 | // Instantiate the Core connecting using the PLL clock 27 | withClockAndReset(pll.io.clko, customReset) { 28 | val bitWidth = 32 29 | val instructionMemorySize = 64 * 1024 30 | val dataMemorySize = 64 * 1024 31 | val numGPIO = 8 32 | 33 | val SOC = 34 | Module( 35 | new SOC( 36 | cpuFrequency = cpuFrequency, 37 | entryPoint = 0x00000000, 38 | bitWidth = bitWidth, 39 | instructionMemorySize = instructionMemorySize, 40 | dataMemorySize = dataMemorySize, 41 | memoryFile = "progload.mem", 42 | ramFile = "progload-RAM.mem", 43 | numGPIO = numGPIO, 44 | ) 45 | ) 46 | 47 | // Connect IO 48 | io.led0 <> SOC.io.led0 49 | io.GPIO0 <> SOC.io.GPIO0External 50 | io.UART0 <> SOC.io.UART0SerialPort 51 | } 52 | } 53 | 54 | // The Main object extending App to generate the Verilog code. 55 | object Toplevel { 56 | @main 57 | def run( 58 | // Parse command line arguments and extract required parameters 59 | @arg(short = 'b', doc = "FPGA Board to use") board: String = "bypass", 60 | @arg(short = 'r', doc = "FPGA Board have inverted reset") invreset: Boolean = false, 61 | @arg(short = 'f', doc = "CPU Frequency to run core") cpufreq: Int = 50000000, 62 | @arg(short = 'c', doc = "Chisel arguments") chiselArgs: Leftover[String], 63 | ) = 64 | // Generate SystemVerilog 65 | ChiselStage.emitSystemVerilogFile( 66 | new Toplevel(board, invreset, cpufreq), 67 | chiselArgs.value.toArray, 68 | Array( 69 | // Removes debug information from the generated Verilog 70 | "--strip-debug-info", 71 | // Disables reg and memory randomization on initialization 72 | "--disable-all-randomization", 73 | // Creates memories with write masks in a single reg. Ref. https://github.com/llvm/circt/pull/4275 74 | "--lower-memories", 75 | // Avoids "unexpected TOK_AUTOMATIC" errors in Yosys. Ref. https://github.com/llvm/circt/issues/4751 76 | "--lowering-options=disallowLocalVariables,disallowPackedArrays", 77 | ), 78 | ) 79 | 80 | def main(args: Array[String]): Unit = 81 | ParserForMethods(this).runOrExit(args.toIndexedSeq) 82 | } 83 | -------------------------------------------------------------------------------- /chiselv/src/Uart.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | /* 7 | * A simple TTL serial module. Idle is high. Start bits are low, stop bits 8 | * are high and we send each byte out LSB first. We only implement 8n1, 9 | * ie 1 start bit, no parity and 1 stop bit. There is no flow control, so 10 | * we might overflow the RX fifo if the rxQueue consumer can't keep up. 11 | * 12 | * We oversample RX. clockDivisor is set as follows: 13 | * 14 | * clockDivisor = (clock_freq / (baudrate * rxOverclock)) - 1 15 | * 16 | * When programming the divider, software currently assumes we overclock 16x. 17 | * 18 | * Also note that if the input clock frequency is low enough then the errors 19 | * introduced by oversampling might be significant. Eg at 10MHz, 115200 baud, 20 | * 16x oversampling we have almost 8% error and the UART fails to work. 21 | * 22 | * This file has been created by Anton Blanchard on Chiselwatt repository at: 23 | * https://github.com/antonblanchard/chiselwatt 24 | */ 25 | 26 | class UARTSerialPort extends Bundle { 27 | val rx = Input(UInt(1.W)) 28 | val tx = Output(UInt(1.W)) 29 | } 30 | 31 | class UARTPort extends Bundle { 32 | val rxQueue = Decoupled(UInt(8.W)) 33 | val txQueue = Flipped(Decoupled(UInt(8.W))) 34 | val rxEmpty = Output(Bool()) 35 | val txEmpty = Output(Bool()) 36 | val rxFull = Output(Bool()) 37 | val txFull = Output(Bool()) 38 | val clockDivisor = Flipped(Valid(UInt(8.W))) 39 | } 40 | 41 | class Uart(val fifoLength: Int, val rxOverclock: Int) extends Module { 42 | val io = IO(new Bundle { 43 | val serialPort = new UARTSerialPort 44 | val dataPort = new UARTPort 45 | }) 46 | 47 | require(isPow2(rxOverclock)) 48 | 49 | val sampleClk = RegInit(0.U(1.W)) 50 | val sampleClkCounter = RegInit(0.U(8.W)) 51 | val clockDivisor = RegInit(0.U(8.W)) 52 | 53 | when(io.dataPort.clockDivisor.valid) { 54 | clockDivisor := io.dataPort.clockDivisor.bits 55 | } 56 | 57 | val txQueue = Module(new Queue(UInt(8.W), fifoLength)) 58 | val rxQueue = Module(new Queue(UInt(8.W), fifoLength)) 59 | 60 | io.dataPort.rxEmpty := rxQueue.io.count === 0.U 61 | io.dataPort.txEmpty := txQueue.io.count === 0.U 62 | io.dataPort.rxFull := rxQueue.io.count === fifoLength.U 63 | io.dataPort.txFull := txQueue.io.count === fifoLength.U 64 | 65 | val uartEnabled = clockDivisor.orR 66 | 67 | when(uartEnabled) { 68 | when(sampleClkCounter === clockDivisor) { 69 | sampleClk := 1.U 70 | sampleClkCounter := 0.U 71 | }.otherwise { 72 | sampleClk := 0.U 73 | sampleClkCounter := sampleClkCounter + 1.U 74 | } 75 | }.otherwise { 76 | sampleClk := 0.U 77 | sampleClkCounter := 0.U 78 | } 79 | 80 | /* 81 | * Our TX clock needs to match our baud rate. This means we need to 82 | * further divide sampleClk by rxOverclock. 83 | */ 84 | val (txCounterValue, txCounterWrap) = Counter(sampleClk === 1.U, rxOverclock) 85 | val txClk = txCounterWrap 86 | 87 | /* TX */ 88 | val sTxIdle :: sTxTx :: sTxStop :: Nil = Enum(3) 89 | val txState = RegInit(sTxIdle) 90 | val txByte = Reg(UInt(8.W)) 91 | val txByteBit = Reg(UInt(3.W)) 92 | /* RS232 idle state is high */ 93 | val tx = RegInit(1.U(1.W)) 94 | 95 | txQueue.io.deq.ready := false.B 96 | 97 | /* We run the tx state machine off the txClk */ 98 | when(txClk === 1.U) { 99 | switch(txState) { 100 | is(sTxIdle) { 101 | /* Does the FIFO contain data? */ 102 | when(txQueue.io.deq.valid) { 103 | txQueue.io.deq.ready := true.B 104 | txByte := txQueue.io.deq.bits 105 | txByteBit := 0.U 106 | txState := sTxTx 107 | /* Send start bit */ 108 | tx := 0.U 109 | }.otherwise { 110 | tx := 1.U 111 | } 112 | } 113 | 114 | is(sTxTx) { 115 | when(txByteBit === 7.U) { 116 | txState := sTxStop 117 | } 118 | tx := txByte(txByteBit) 119 | txByteBit := txByteBit + 1.U 120 | } 121 | 122 | is(sTxStop) { 123 | txState := sTxIdle 124 | /* Send stop bit */ 125 | tx := 1.U 126 | } 127 | } 128 | } 129 | 130 | io.serialPort.tx := tx 131 | 132 | /* RX */ 133 | val sRxIdle :: sRxStart :: sRxRx :: sRxStop :: sRxError1 :: sRxError2 :: Nil = 134 | Enum(6) 135 | val rxState = RegInit(sRxIdle) 136 | val rxCounter = RegInit(0.U(log2Ceil(rxOverclock).W)) 137 | val rxByte = RegInit(VecInit(Seq.fill(8)(0.U(1.W)))) 138 | val rxByteBit = RegInit(0.U(3.W)) 139 | 140 | rxQueue.io.enq.bits := 0.U 141 | rxQueue.io.enq.valid := false.B 142 | 143 | /* Synchronize the input to avoid any metastability issues */ 144 | val rx = RegNext(RegNext(RegNext(io.serialPort.rx))) 145 | 146 | when(sampleClk === 1.U) { 147 | switch(rxState) { 148 | is(sRxIdle) { 149 | when(rx === 0.U) { 150 | rxState := sRxStart 151 | rxCounter := 1.U 152 | rxByte := Seq.fill(8)(0.U) 153 | rxByteBit := 0.U 154 | } 155 | } 156 | 157 | is(sRxStart) { 158 | rxCounter := rxCounter + 1.U 159 | /* We should be at the middle of the start bit */ 160 | when(rxCounter === (rxOverclock / 2).U) { 161 | rxCounter := 1.U 162 | rxState := sRxRx 163 | } 164 | } 165 | 166 | is(sRxRx) { 167 | rxCounter := rxCounter + 1.U 168 | when(rxCounter === 0.U) { 169 | when(rxByteBit === 7.U) { 170 | rxState := sRxStop 171 | } 172 | rxByte(rxByteBit) := rx 173 | rxByteBit := rxByteBit + 1.U 174 | } 175 | } 176 | 177 | is(sRxStop) { 178 | rxCounter := rxCounter + 1.U 179 | when(rxCounter === 0.U) { 180 | /* Ensure the stop bit is high */ 181 | when(rx === 1.U) { 182 | /* We might overflow the queue if we can't keep up */ 183 | rxQueue.io.enq.bits := rxByte.reverse.reduce(_ ## _) 184 | rxQueue.io.enq.valid := true.B 185 | rxState := sRxIdle 186 | }.otherwise { 187 | /* Something went wrong */ 188 | rxState := sRxError1 189 | } 190 | } 191 | } 192 | 193 | /* 194 | * We might not have synchronised on a start bit. Delay 2 bits on 195 | * each error so we eventually line up with the start bit. 196 | */ 197 | is(sRxError1) { 198 | /* Delay one bit */ 199 | rxCounter := rxCounter + 1.U 200 | when(rxCounter === 0.U) { 201 | rxState := sRxError2 202 | } 203 | } 204 | 205 | is(sRxError2) { 206 | /* Delay another bit */ 207 | rxCounter := rxCounter + 1.U 208 | when(rxCounter === 0.U) { 209 | rxState := sRxIdle 210 | } 211 | } 212 | } 213 | } 214 | 215 | rxQueue.io.deq <> io.dataPort.rxQueue 216 | txQueue.io.enq <> io.dataPort.txQueue 217 | } 218 | -------------------------------------------------------------------------------- /chiselv/test/src/ALUSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chiseltest._ 5 | import com.carlosedp.riscvassembler.ObjectUtils.NumericManipulation 6 | import org.scalatest._ 7 | 8 | import Instruction._ 9 | import flatspec._ 10 | import matchers._ 11 | 12 | class ALUSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 13 | val one = BigInt(1) 14 | val max = (one << 32) - one 15 | val min_signed = one << 32 - 1 16 | val max_signed = (one << 32 - 1) - one 17 | val cases = 18 | Array[BigInt](1, 2, 4, 123, -1, -2, -4, 0, 0x7fffffffL, 0x80000000L, max, min_signed, max_signed) ++ Seq.fill(10)( 19 | BigInt(scala.util.Random.nextInt()) 20 | ) 21 | 22 | it should "ADD" in { 23 | testCycle(ADD) 24 | } 25 | it should "ADDI" in { 26 | testCycle(ADDI) 27 | } 28 | it should "SUB" in { 29 | testCycle(SUB) 30 | } 31 | it should "AND" in { 32 | testCycle(AND) 33 | } 34 | it should "ANDI" in { 35 | testCycle(ANDI) 36 | } 37 | it should "OR" in { 38 | testCycle(OR) 39 | } 40 | it should "ORI" in { 41 | testCycle(ORI) 42 | } 43 | it should "XOR" in { 44 | testCycle(XOR) 45 | } 46 | it should "XORI" in { 47 | testCycle(XORI) 48 | } 49 | it should "SRA" in { 50 | testCycle(SRA) 51 | } 52 | it should "SRAI" in { 53 | testCycle(SRAI) 54 | } 55 | it should "SRL" in { 56 | testCycle(SRL) 57 | } 58 | it should "SRLI" in { 59 | testCycle(SRLI) 60 | } 61 | it should "SLL" in { 62 | testCycle(SLL) 63 | } 64 | it should "SLLI" in { 65 | testCycle(SLLI) 66 | } 67 | it should "SLT" in { 68 | testCycle(SLT) 69 | } 70 | it should "SLTI" in { 71 | testCycle(SLTI) 72 | } 73 | it should "SLTU" in { 74 | testCycle(SLTU) 75 | } 76 | it should "SLTIU" in { 77 | testCycle(SLTIU) 78 | } 79 | it should "EQ" in { 80 | testCycle(EQ) 81 | } 82 | it should "NEQ" in { 83 | testCycle(NEQ) 84 | } 85 | it should "GT" in { 86 | testCycle(GTE) 87 | } 88 | it should "GTU" in { 89 | testCycle(GTEU) 90 | } 91 | // --------------------- Test Helpers --------------------- 92 | def aluHelper( 93 | a: BigInt, 94 | b: BigInt, 95 | op: Type, 96 | ): BigInt = 97 | op match { 98 | case ADD | ADDI => (a + b).to32Bit 99 | case SUB => a - b 100 | case AND | ANDI => a & b 101 | case OR | ORI => a | b 102 | case XOR | XORI => a ^ b 103 | case SRA | SRAI => a.toInt >> (b.toInt & 0x1f) 104 | case SRL | SRLI => a.toInt >>> b.toInt 105 | case SLL | SLLI => a.toInt << b.toInt 106 | case SLT | SLTI => if (a.toInt < b.toInt) 1 else 0 107 | case SLTU | SLTIU => if (a.to32Bit < b.to32Bit) 1 else 0 108 | case EQ => if (a.to32Bit == b.to32Bit) 1 else 0 109 | case NEQ => if (a.to32Bit != b.to32Bit) 1 else 0 110 | case GTE => if (a.toInt >= b.toInt) 1 else 0 111 | case GTEU => if (a.to32Bit >= b.to32Bit) 1 else 0 112 | case _ => 0 // Never happens 113 | } 114 | 115 | def testDut( 116 | i: BigInt, 117 | j: BigInt, 118 | out: BigInt, 119 | op: Type, 120 | dut: ALU, 121 | ) = { 122 | // print(s"Inputs: $i $op $j | Test result should be ${aluHelper(i, j, op)} | ") 123 | dut.io.inst.poke(op) 124 | dut.io.a.poke(i.to32Bit) 125 | dut.io.b.poke(j.to32Bit) 126 | dut.clock.step() 127 | dut.io.x.peekInt() should be(out) 128 | } 129 | def testCycle( 130 | op: Type 131 | ) = 132 | test(new ALU) { c => 133 | cases.foreach { i => 134 | cases.foreach { j => 135 | testDut(i, j, aluHelper(i, j, op).to32Bit, op, c) 136 | } 137 | } 138 | } 139 | 140 | def toUInt( 141 | i: BigInt 142 | ) = i.to32Bit.asUInt(32.W) 143 | } 144 | -------------------------------------------------------------------------------- /chiselv/test/src/CPUDemoAppsSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import chiseltest.experimental._ 5 | import org.scalatest._ 6 | 7 | import flatspec._ 8 | import matchers._ 9 | 10 | // Extend the SOC module to add the observer for sub-module signals 11 | class SOCWrapperDemo( 12 | cpuFrequency: Int, 13 | bitWidth: Int, 14 | instructionMemorySize: Int, 15 | memorySize: Int, 16 | memoryFile: String, 17 | ramFile: String, 18 | numGPIO: Int, 19 | // baudRate: Int, 20 | ) extends SOC( 21 | cpuFrequency, 22 | entryPoint = 0, 23 | bitWidth, 24 | instructionMemorySize, 25 | memorySize, 26 | memoryFile, 27 | ramFile, 28 | numGPIO, 29 | ) { 30 | val registers = expose(core.registerBank.regs) 31 | val pc = expose(core.PC.pc) 32 | } 33 | 34 | class CPUDemoAppsSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 35 | val cpuFrequency = 10000 36 | val bitWidth = 32 37 | val instructionMemorySize = 64 * 1024 38 | val memorySize = 64 * 1024 39 | 40 | def defaultDut( 41 | memoryfile: String, 42 | ramFile: String = "", 43 | ) = 44 | test( 45 | new SOCWrapperDemo( 46 | cpuFrequency, 47 | bitWidth, 48 | instructionMemorySize, 49 | memorySize, 50 | memoryfile, 51 | ramFile, 52 | 8, 53 | // 1200, 54 | ) 55 | ) 56 | .withAnnotations( 57 | Seq( 58 | WriteVcdAnnotation, 59 | VerilatorBackendAnnotation, 60 | ) 61 | ) 62 | 63 | behavior of "GPIODemo" 64 | it should "lit a LED connected to GPIO from gcc program" in { 65 | val filename = "./gcc/simpleLED/main.mem" 66 | defaultDut(filename) { c => 67 | c.clock.setTimeout(10000) 68 | c.clock.step(1) // Step from initial PC 69 | while (c.pc.peekInt() != 0x0) 70 | c.clock.step(1) 71 | } 72 | } 73 | 74 | it should "blink LED connected to GPIO0 from gcc program" in { 75 | val filename = "./gcc/blinkLED/main-rom.mem" 76 | defaultDut(filename) { c => 77 | c.clock.setTimeout(3000) 78 | c.clock.step(2000) 79 | } 80 | } 81 | 82 | behavior of "UARTDemo" 83 | it should "print to UART0 from gcc program" in { 84 | val filename = "./gcc/helloUART/main-rom.mem" 85 | val filename_ram = "./gcc/helloUART/main-ram.mem" 86 | defaultDut(filename, filename_ram) { c => 87 | c.clock.setTimeout(30000) 88 | c.clock.step(25000) 89 | // while (c.pc.peekInt() != 0x90) { // 0x90 is the address of _halt 90 | // c.clock.step(1) 91 | // } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /chiselv/test/src/CPUSingleCycleAppsSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import chiseltest.experimental._ 5 | import org.scalatest._ 6 | 7 | import flatspec._ 8 | import matchers._ 9 | 10 | // Extend the Control module to add the observer for sub-module signals 11 | class CPUSingleCycleWrapperApps(memoryFile: String) extends SOC( 12 | cpuFrequency = 25000000, 13 | entryPoint = 0, 14 | bitWidth = 32, 15 | instructionMemorySize = 1 * 1024, 16 | dataMemorySize = 1 * 1024, 17 | memoryFile = memoryFile, 18 | numGPIO = 0, 19 | ) { 20 | val registers = expose(core.registerBank.regs) 21 | val pc = expose(core.PC.pc) 22 | val memWriteAddr = expose(core.memoryIOManager.io.MemoryIOPort.writeAddr) 23 | val memWriteData = expose(core.memoryIOManager.io.MemoryIOPort.writeData) 24 | val memReadAddr = expose(core.memoryIOManager.io.MemoryIOPort.readAddr) 25 | val memReadData = expose(core.memoryIOManager.io.MemoryIOPort.readData) 26 | } 27 | 28 | class CPUSingleCycleAppsSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 29 | val writeLatency = 2 30 | val readLatency = 1 31 | 32 | def defaultDut(memoryfile: String) = 33 | test(new CPUSingleCycleWrapperApps(memoryFile = memoryfile)) 34 | .withAnnotations( 35 | Seq( 36 | WriteVcdAnnotation 37 | ) 38 | ) 39 | 40 | it should "load instructions from file to write to all registers with ADDI" in { 41 | val filename = "./gcc/test/test_addi.mem" 42 | defaultDut(filename) { c => 43 | c.clock.setTimeout(0) 44 | val results = List.fill(8)(List(0, 1000, 3000, 2000)).flatten 45 | for ((i, r) <- 0 until 31 zip results) { 46 | c.registers(i).peekInt() should be(r) 47 | c.clock.step(1) 48 | } 49 | c.clock.step(20) 50 | } 51 | } 52 | 53 | it should "load program and end with 25 (0x19) in mem address 100 (0x64)" in { 54 | val filename = "./gcc/test/test_book.mem" 55 | defaultDut(filename) { c => 56 | c.clock.setTimeout(0) 57 | c.clock.step(1) // addi 58 | c.registers(2).peekInt() should be(5) 59 | c.clock.step(1) // addi 60 | c.registers(3).peekInt() should be(12) 61 | c.clock.step(1) // addi 62 | c.registers(7).peekInt() should be(3) 63 | c.clock.step(1) // lui 64 | c.registers(6).peekInt() should be(0x80000000L) 65 | c.clock.step(1) // or 66 | c.registers(4).peekInt() should be(7) 67 | c.clock.step(1) // and 68 | c.registers(5).peekInt() should be(4) 69 | c.clock.step(1) // add 70 | c.registers(5).peekInt() should be(11) 71 | c.clock.step(1) // beq (skip) 72 | c.clock.step(1) // slt 73 | c.registers(4).peekInt() should be(0) 74 | c.clock.step(1) // beq (skip next addi) 75 | c.clock.step(1) // slt 76 | c.registers(4).peekInt() should be(1) 77 | c.clock.step(1) // add 78 | c.registers(7).peekInt() should be(12) 79 | c.clock.step(1) // sub 80 | c.registers(7).peekInt() should be(7) 81 | // Check Memory write at address 0x80000000 82 | c.memWriteAddr.peekInt() should be(0x80000000L) 83 | c.memWriteData.peekInt() should be(7) 84 | c.clock.step(1 + writeLatency) // sw 85 | // Check Memory read at address 0x80000000 86 | c.memReadAddr.peekInt() should be(0x80000000L) 87 | c.memReadData.peekInt() should be(7) 88 | c.clock.step(1 + readLatency) // lw 89 | c.registers(2).peekInt() should be(7) 90 | c.clock.step(1) // add 91 | c.registers(9).peekInt() should be(18) 92 | c.clock.step(1) // jal (skip next addi) 93 | c.clock.step(1) // add 94 | c.registers(2).peekInt() should be(25) 95 | // // Check Memory address 0x80000000 + 100 (0x64) 96 | c.memWriteAddr.peekInt() should be(0x80000000L + 0x64) 97 | c.memWriteData.peekInt() should be(25) 98 | c.clock.step(1 + writeLatency) // sw 99 | 100 | // Add some padding at the end 101 | c.clock.step(10) 102 | } 103 | } 104 | 105 | it should "loop thru ascii table writing to 0x3000_0000 region" in { 106 | val filename = "./gcc/test/test_ascii.mem" 107 | defaultDut(filename) { c => 108 | c.clock.setTimeout(0) 109 | c.clock.step(1) 110 | c.registers(1).peekInt() should be(40) 111 | c.clock.step(1) 112 | c.registers(2).peekInt() should be(33) 113 | c.clock.step(1) 114 | c.registers(3).peekInt() should be(126) 115 | c.clock.step(1) 116 | c.registers(4).peekInt() should be(0x3000_0000) 117 | 118 | for (i <- 33 until 127) { 119 | // Check memory write at address 0x30000000 120 | c.memWriteAddr.peekInt() should be(0x30000000L) 121 | c.memWriteData.peekInt() should be(i) 122 | c.clock.step(1) // sb (no latency to write 0x30000000 region) 123 | c.clock.step(1) // addi 124 | c.clock.step(1) // bge 125 | } 126 | c.clock.step(10) 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /chiselv/test/src/CPUSingleCycleIOSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import chiseltest.experimental._ 5 | import com.carlosedp.riscvassembler.RISCVAssembler 6 | import org.scalatest._ 7 | 8 | import flatspec._ 9 | import matchers._ 10 | 11 | // Extend the Control module to add the observer for sub-module signals 12 | class CPUSingleCycleIOWrapper(memoryFile: String) extends SOC( 13 | cpuFrequency = 25000000, 14 | entryPoint = 0, 15 | bitWidth = 32, 16 | instructionMemorySize = 1 * 1024, 17 | dataMemorySize = 1 * 1024, 18 | memoryFile = memoryFile, 19 | numGPIO = 8, 20 | ) { 21 | val registers = expose(core.registerBank.regs) 22 | val pc = expose(core.PC.pc) 23 | val memWriteAddr = expose(core.memoryIOManager.io.MemoryIOPort.writeAddr) 24 | val memWriteData = expose(core.memoryIOManager.io.MemoryIOPort.writeData) 25 | val memReadAddr = expose(core.memoryIOManager.io.MemoryIOPort.readAddr) 26 | val memReadData = expose(core.memoryIOManager.io.MemoryIOPort.readData) 27 | 28 | val GPIO0_value = expose(core.GPIO0.GPIO) 29 | val GPIO0_direction = expose(core.GPIO0.direction) 30 | val timerCounter = expose(core.timer0.counter) 31 | } 32 | 33 | class CPUSingleCycleIOSpec 34 | extends AnyFlatSpec 35 | with ChiselScalatestTester 36 | with BeforeAndAfterEach 37 | with BeforeAndAfterAll 38 | with should.Matchers { 39 | val cpuFrequency = 25000000 40 | val ms = cpuFrequency / 1000 41 | var memoryfile: os.Path = _ 42 | val tmpdir = os.pwd / "tmphex" 43 | 44 | override def beforeAll(): Unit = 45 | os.makeDir.all(tmpdir) 46 | override def afterAll(): Unit = 47 | scala.util.Try(os.remove(tmpdir)) 48 | override def beforeEach(): Unit = 49 | memoryfile = tmpdir / (scala.util.Random.alphanumeric.filter(_.isLetter).take(15).mkString + ".hex") 50 | override def afterEach(): Unit = 51 | os.remove.all(memoryfile) 52 | 53 | def defaultDut(prog: String) = { 54 | val hex = RISCVAssembler.fromString(prog) 55 | os.write(memoryfile, hex) 56 | test(new CPUSingleCycleIOWrapper(memoryFile = memoryfile.toString)) 57 | .withAnnotations( 58 | Seq( 59 | WriteVcdAnnotation, 60 | VerilatorBackendAnnotation, // GPIO needs Verilator backend 61 | ) 62 | ) 63 | } 64 | 65 | it should "write to GPIO0" in { 66 | val prog = """ 67 | lui x1, 0x30001 68 | addi x5, x0, -1 69 | addi x3, x3, 1 70 | addi x4, x0, 7 71 | sw x5, 0(x1) 72 | add x2, x2, x3 73 | sw x2, 4(x1) 74 | jal x0, -8 75 | """ 76 | defaultDut(prog) { c => 77 | c.clock.setTimeout(0) 78 | c.registers(1).peekInt() should be(0) 79 | c.registers(2).peekInt() should be(0) 80 | c.registers(3).peekInt() should be(0) 81 | c.registers(4).peekInt() should be(0) 82 | c.clock.step(1) // lui 83 | c.registers(1).peekInt() should be(0x30001000L) 84 | c.clock.step(1) // addi 85 | c.registers(5).peekInt() should be(0xffffffffL) 86 | c.clock.step(1) // addi 87 | c.registers(3).peekInt() should be(1) 88 | c.clock.step(1) // addi 89 | c.registers(4).peekInt() should be(7) 90 | // Check memory address 0x30001000L for direction (GPIO0) 91 | c.memWriteAddr.peekInt() should be(0x30001000L) 92 | c.memWriteData.peekInt() should be(0xffffffffL) 93 | c.clock.step(1) // sw 94 | c.clock.step(1) // add 95 | c.GPIO0_direction.peekInt() should be(0xffffffffL) 96 | c.registers(2).peekInt() should be(1) 97 | c.memWriteAddr.peekInt() should be(0x30001004L) 98 | c.memWriteData.peekInt() should be(1) 99 | c.clock.step(1) // sw 100 | c.GPIO0_value.peekInt() should be(1) 101 | c.clock.step(1) // jal 102 | c.clock.step(1) // add 103 | c.registers(2).peekInt() should be(2) 104 | c.memWriteAddr.peekInt() should be(0x30001004L) 105 | c.memWriteData.peekInt() should be(2) 106 | c.clock.step(1) // sw 107 | c.GPIO0_value.peekInt() should be(2) 108 | } 109 | } 110 | 111 | behavior of "Timer" 112 | it should "read timer and wait for 2 ms" in { 113 | val prog = """ 114 | main: lui x1, 0x30003 115 | addi x2, x0, 2 116 | wait: lw x3, 0(x1) 117 | bne x2, x3, -4 118 | cont: addi x4, x0, 1 119 | """ 120 | defaultDut(prog) { c => 121 | c.clock.setTimeout(0) 122 | c.registers(1).peekInt() should be(0) 123 | c.registers(2).peekInt() should be(0) 124 | c.registers(3).peekInt() should be(0) 125 | c.timerCounter.peekInt() should be(0) 126 | c.clock.step(1) // lui 127 | c.registers(1).peekInt() should be(0x30003000L) 128 | c.clock.step(1) // addi 129 | c.registers(2).peekInt() should be(2) 130 | // Check read from memory address 0x30003000L 131 | c.memReadAddr.peekInt() should be(0x30003000L) 132 | c.memReadData.peekInt() should be(0) 133 | c.clock.step(1) // lw 134 | c.registers(3).peekInt() should be(0) 135 | c.clock.step(1) // bne 136 | c.clock.step(2 * ms) // wait 2ms 137 | c.timerCounter.peekInt() should be(2) 138 | c.registers(3).peekInt() should be(2) 139 | c.clock.step(1) // addi 140 | c.registers(4).peekInt() should be(1) 141 | } 142 | } 143 | 144 | it should "reset timer after 1ms and wait for 1 ms" in { 145 | val prog = """ 146 | main: lui x1, 0x30003 147 | addi x2, x0, 1 148 | wait: lw x3, 0(x1) 149 | bne x2, x3, -4 150 | cont: sw x0, 0(x1) 151 | wait2: lw x3, 0(x1) 152 | bne x2, x3, -4 153 | cont2: addi x3, x0, 2 154 | """ 155 | defaultDut(prog) { c => 156 | c.clock.setTimeout(0) 157 | c.registers(1).peekInt() should be(0) 158 | c.registers(2).peekInt() should be(0) 159 | c.registers(3).peekInt() should be(0) 160 | c.timerCounter.peekInt() should be(0) 161 | c.clock.step(1) // lui 162 | c.registers(1).peekInt() should be(0x30003000L) 163 | c.clock.step(1) // addi 164 | c.registers(2).peekInt() should be(1) 165 | // Check read from memory address 0x30003000L 166 | c.memReadAddr.peekInt() should be(0x30003000L) 167 | c.memReadData.peekInt() should be(0) 168 | c.registers(3).peekInt() should be(0) 169 | c.clock.step(ms) // wait 1ms 170 | c.timerCounter.peekInt() should be(1) 171 | c.registers(3).peekInt() should be(1) 172 | c.clock.step(1) 173 | c.clock.step(1) 174 | c.clock.step(1) // sw 175 | // Check write to memory address 0x30003000L (reset) 176 | c.memWriteAddr.peekInt() should be(0x30003000L) 177 | c.memWriteData.peekInt() should be(0) 178 | c.timerCounter.peekInt() should be(0) 179 | c.registers(3).peekInt() should be(0) 180 | c.clock.step(ms) // wait 1ms 181 | c.timerCounter.peekInt() should be(1) 182 | c.clock.step(1) // lw 183 | c.clock.step(1) // bne 184 | c.clock.step(1) // addi 185 | c.registers(3).peekInt() should be(2) 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /chiselv/test/src/GPIOSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import chiseltest.experimental.expose 5 | import com.carlosedp.riscvassembler.ObjectUtils._ 6 | import org.scalatest._ 7 | 8 | import flatspec._ 9 | import matchers._ 10 | 11 | class GPIOWrapper(bitWidth: Int = 32, numGPIO: Int = 8) extends GPIO(bitWidth, numGPIO) { 12 | val obs_GPIO = expose(GPIO) 13 | val obs_DIRECTION = expose(direction) 14 | } 15 | class GPIOSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 16 | def defaultDut = 17 | test(new GPIOWrapper(32, 8)).withAnnotations( 18 | Seq( 19 | WriteVcdAnnotation, 20 | VerilatorBackendAnnotation, 21 | ) 22 | ) 23 | 24 | it should "read GPIO output and direction as 0 when initialized" in { 25 | defaultDut { c => 26 | c.io.GPIOPort.valueOut.peekInt() should be(0) 27 | c.obs_GPIO.peekInt() should be(0) 28 | c.obs_DIRECTION.peekInt() should be(0) 29 | } 30 | } 31 | 32 | it should "write direction then read" in { 33 | defaultDut { c => 34 | c.io.GPIOPort.writeDirection.poke(true) 35 | c.io.GPIOPort.dataIn.poke("10101010".b) 36 | c.clock.step() 37 | c.obs_DIRECTION.peekInt() should be("10101010".b) 38 | c.io.GPIOPort.directionOut.peekInt() should be("10101010".b) 39 | } 40 | } 41 | 42 | it should "write IO data then read" in { 43 | defaultDut { c => 44 | c.io.GPIOPort.writeValue.poke(true) 45 | c.io.GPIOPort.dataIn.poke("11111111".b) 46 | c.clock.step() 47 | c.obs_GPIO.peekInt() should be("11111111".b) 48 | c.io.GPIOPort.writeDirection.poke(true) 49 | c.io.GPIOPort.dataIn.poke("01010101".b) 50 | c.clock.step() 51 | c.io.GPIOPort.valueOut.peekInt() should be("01010101".b) 52 | c.clock.step(5) 53 | } 54 | } 55 | 56 | // Doesn't work since we can't poke the analog port 57 | // 58 | // it should "read IO data from input" in { 59 | // defaultDut(){ c => 60 | // c.io.GPIOPort.dataOut.peekInt() should be(0) 61 | // c.io.GPIOPort.dir.poke(0.U) // Read input 62 | // // c.InOut.io.dataIO.poke(1.U) // Write to input pin 63 | // c.clock.step() 64 | // c.io.GPIOPort.dataOut.peekInt() should be(1) 65 | // } 66 | // } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /chiselv/test/src/MemorySpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import org.scalatest._ 5 | 6 | import flatspec._ 7 | import matchers._ 8 | 9 | class MemorySpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 10 | 11 | it should "write and read from address" in { 12 | test(new DualPortRAM(32, 1 * 1024)).withAnnotations( 13 | Seq( 14 | WriteVcdAnnotation 15 | ) 16 | ) { c => 17 | c.io.writeEnable.poke(true) 18 | c.io.writeAddress.poke(1) 19 | c.io.writeData.poke(1234) 20 | c.clock.step(1) 21 | c.io.readAddress.poke(1) 22 | c.clock.step(2) 23 | c.io.readData.peekInt() should be(1234) 24 | } 25 | } 26 | it should "not allow write to address" in { 27 | test(new DualPortRAM(32, 1 * 1024)) { c => 28 | c.io.writeAddress.poke(0x00000010) 29 | c.io.readAddress.poke(0x00000010) 30 | c.clock.step() 31 | c.io.writeData.poke(1234) 32 | c.clock.step() 33 | c.io.readData.peekInt() should be(0) 34 | } 35 | } 36 | 37 | it should "write data and follow with a read in same address" in { 38 | test(new DualPortRAM(32, 64 * 1024)) { c => 39 | val addressOffset = 0x0000100L 40 | val addresses = Seq(0x0L, 0x0010L, 0x0d00L, 0x1000L, 0x2000L, 0x8000L, 0xe000L) 41 | val values = Seq(0, 1, 0x0000_cafeL, 0xbaad_cafeL, 0xffff_ffffL) 42 | addresses.foreach { address => 43 | values.foreach { value => 44 | c.io.writeEnable.poke(true) 45 | c.io.writeAddress.poke(addressOffset + address) 46 | c.io.readAddress.poke(addressOffset + address) 47 | c.io.writeData.poke(value) 48 | c.clock.step(1) 49 | c.io.readAddress.poke(addressOffset + address) 50 | c.clock.step(1) 51 | c.io.readData.peekInt() should be(value) 52 | } 53 | } 54 | c.clock.step(10) 55 | } 56 | } 57 | 58 | behavior of "InstructionMemory" 59 | it should "load from file and read multiple instructions" in { 60 | val filename = "MemorySpecTestFile.hex" 61 | // Create memory test file with 32bit address space 62 | val file = os.pwd / "MemorySpecTestFile.hex" 63 | os.remove(file) 64 | os.write(file, "00010203\r\n08090A0B\r\nDEADBEEF\r\n07060504\r\n") 65 | test(new InstructionMemory(32, 16 * 1024, filename)).withAnnotations(Seq(WriteVcdAnnotation)) { c => 66 | c.io.readAddr.poke(0) 67 | c.clock.step() 68 | c.io.readData.peekInt() should be(0x00010203L) 69 | c.io.readAddr.poke(4) 70 | c.clock.step() 71 | c.io.readData.peekInt() should be(0x08090a0bL) 72 | c.io.readAddr.poke(8) 73 | c.clock.step() 74 | c.io.readData.peekInt() should be(0xdeadbeefL) 75 | c.io.readAddr.poke(12) 76 | c.clock.step() 77 | c.clock.step() 78 | c.io.readData.peekInt() should be(0x07060504L) 79 | c.io.readAddr.poke(1) 80 | c.clock.step() 81 | } 82 | os.remove.all(file) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /chiselv/test/src/ProgramCounterSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import org.scalatest._ 5 | 6 | import flatspec._ 7 | import matchers._ 8 | 9 | class ProgramCounterSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 10 | 11 | it should "initialize to 0" in { 12 | test(new ProgramCounter) { c => 13 | c.io.PC.peekInt() should be(0) 14 | } 15 | } 16 | it should "initialize to 0x00400000" in { 17 | test(new ProgramCounter(entryPoint = 0x00400000)) { c => 18 | c.io.PC.peekInt() should be(0x00400000L) 19 | } 20 | } 21 | it should "walk 4 bytes" in { 22 | test(new ProgramCounter) { c => 23 | c.io.PC.peekInt() should be(0) 24 | c.io.PC4.peekInt() should be(4) 25 | c.clock.step() 26 | c.io.writeEnable.poke(true) 27 | c.io.dataIn.poke(c.io.PC4.peek()) 28 | c.clock.step() 29 | c.io.PC.peekInt() should be(4) 30 | } 31 | } 32 | it should "jump to 0xbaddcafe (write)" in { 33 | test(new ProgramCounter) { c => 34 | c.io.writeEnable.poke(true) 35 | c.io.dataIn.poke(0xbaddcafeL) 36 | c.clock.step() 37 | c.io.PC.peekInt() should be(0xbaddcafeL) 38 | } 39 | } 40 | it should "add 32 to PC ending up in 40" in { 41 | test(new ProgramCounter) { c => 42 | c.io.writeEnable.poke(true) 43 | c.io.dataIn.poke(8) 44 | c.clock.step() 45 | c.io.PC.peekInt() should be(8) 46 | c.io.writeAdd.poke(true) 47 | c.io.dataIn.poke(32) 48 | c.clock.step() 49 | c.io.PC.peekInt() should be(40) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /chiselv/test/src/RegisterBankSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import scala.util.Random 4 | import chisel3._ 5 | import chiseltest._ 6 | import org.scalatest._ 7 | 8 | import flatspec._ 9 | import matchers._ 10 | 11 | class RegisterBankSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 12 | 13 | it should "have x0 equal to 0" in { 14 | test(new RegisterBank) { c => 15 | c.io.rs1_addr.poke(0.U) 16 | c.io.rs1.expect(0.U) 17 | } 18 | } 19 | it should "not write to x0" in { 20 | test(new RegisterBank) { c => 21 | c.io.writeEnable.poke(true) 22 | c.io.regwr_addr.poke(0.U) 23 | c.io.regwr_data.poke(123.U) 24 | c.clock.step() 25 | c.io.rs1_addr.peekInt() should be(0) 26 | } 27 | } 28 | it should "not write if not enabled" in { 29 | test(new RegisterBank) { c => 30 | c.io.rs1_addr.poke(1) 31 | c.io.regwr_addr.poke(1) 32 | c.io.regwr_data.poke(123.U) 33 | c.clock.step() 34 | c.io.rs1.expect(0.U) 35 | } 36 | } 37 | it should "write all other registers and read values as expected" in { 38 | test(new RegisterBank).withAnnotations(Seq(WriteVcdAnnotation)) { c => 39 | val one = BigInt(1) 40 | val max = (one << 32) - one 41 | val cases = Array[BigInt](1, 2, 4, 123, 0, 0x7fffffffL, max) ++ Seq.fill(10)( 42 | BigInt(Random.nextLong(max.toLong)) 43 | ) 44 | Random.shuffle(1 to 31).foreach { i => 45 | cases.foreach { v => 46 | c.io.writeEnable.poke(true) 47 | c.clock.step() 48 | c.io.regwr_addr.poke(i) 49 | c.io.regwr_data.poke(v.U) 50 | c.io.rs2_addr.poke(i) 51 | c.clock.step() 52 | c.io.writeEnable.poke(false) 53 | c.clock.step() 54 | c.io.rs2.expect(v) 55 | } 56 | } 57 | c.clock.step(10) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /chiselv/test/src/SysconSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import org.scalatest._ 5 | 6 | import flatspec._ 7 | import matchers._ 8 | 9 | class SysconSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 10 | 11 | def defaultDut = 12 | test(new Syscon(32, 50000000, 8, 0L, 64 * 1024, 64 * 1024)).withAnnotations( 13 | Seq( 14 | WriteVcdAnnotation 15 | ) 16 | ) 17 | 18 | it should "read dummy value from Syscon 0x0" in { 19 | defaultDut { c => 20 | c.io.Address.poke(0x00) 21 | c.clock.step() 22 | c.io.DataOut.peekInt() should be(0xbaad_cafeL) 23 | } 24 | } 25 | it should "read clock speed from Syscon" in { 26 | defaultDut { c => 27 | c.io.Address.poke(0x08) 28 | c.clock.step() 29 | c.io.DataOut.peekInt() should be(50000000) 30 | } 31 | } 32 | it should "check if UART0 is available in Syscon" in { 33 | defaultDut { c => 34 | c.io.Address.poke(0x10) 35 | c.clock.step() 36 | c.io.DataOut.peekInt() should be(1) 37 | } 38 | } 39 | it should "check if GPIO0 is available in Syscon" in { 40 | defaultDut { c => 41 | c.io.Address.poke(0x18) 42 | c.clock.step() 43 | c.io.DataOut.peekInt() should be(1) 44 | } 45 | } 46 | it should "check num of GPIO0s in Syscon" in { 47 | defaultDut { c => 48 | c.io.Address.poke(0x28) 49 | c.clock.step() 50 | c.io.DataOut.peekInt() should be(8) 51 | } 52 | } 53 | it should "check if Timer0 is available in Syscon" in { 54 | defaultDut { c => 55 | c.io.Address.poke(0x24) 56 | c.clock.step() 57 | c.io.DataOut.peekInt() should be(1) 58 | } 59 | } 60 | it should "check RAM size in Syscon" in { 61 | defaultDut { c => 62 | c.io.Address.poke(0x34) 63 | c.clock.step() 64 | c.io.DataOut.peekInt() should be(64 * 1024) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /chiselv/test/src/TimerSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chiseltest._ 4 | import chiseltest.experimental._ 5 | import org.scalatest._ 6 | import chiselv.Timer 7 | 8 | import flatspec._ 9 | import matchers._ 10 | 11 | class TimerWrapper(bitWidth: Int = 32, cpuFrequency: Int) extends Timer(bitWidth, cpuFrequency) { 12 | val obs_counter = expose(counter) 13 | } 14 | class TimerSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 15 | 16 | val cpuFrequency = 25000000 17 | def defaultDut = 18 | test(new TimerWrapper(32, cpuFrequency)).withAnnotations( 19 | Seq( 20 | // WriteVcdAnnotation 21 | ) 22 | ) 23 | 24 | val ms = cpuFrequency / 1000 25 | it should "read timer after 1ms" in { 26 | defaultDut { c => 27 | c.clock.setTimeout(0) 28 | c.io.dataOut.peekInt() should be(0) 29 | c.obs_counter.peekInt() should be(0) 30 | c.clock.step(ms) 31 | c.io.dataOut.peekInt() should be(1) 32 | c.obs_counter.peekInt() should be(1) 33 | } 34 | } 35 | it should "reset timer after 3ms and continue counting" in { 36 | defaultDut { c => 37 | c.clock.setTimeout(0) 38 | c.clock.step(3 * ms) 39 | c.obs_counter.peekInt() should be(3) 40 | c.io.dataOut.peekInt() should be(3) 41 | c.io.writeEnable.poke(true) 42 | c.io.dataIn.poke(0) 43 | c.clock.step() 44 | c.io.writeEnable.poke(false) 45 | c.obs_counter.peekInt() should be(0) 46 | c.obs_counter.peekInt() should be(0) 47 | c.clock.step(ms) 48 | c.io.dataOut.peekInt() should be(1) 49 | c.obs_counter.peekInt() should be(1) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /chiselv/test/src/UartSpec.scala: -------------------------------------------------------------------------------- 1 | package chiselv 2 | 3 | import chisel3._ 4 | import chiseltest._ 5 | import org.scalatest._ 6 | 7 | import flatspec._ 8 | import matchers._ 9 | 10 | /* 11 | * This file has been provided by Anton Blanchard's Chiselwatt repository at: 12 | * https://github.com/antonblanchard/chiselwatt 13 | */ 14 | 15 | class UartSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers { 16 | val rxOverclock = 16 17 | val fpgaClock = 15000000 18 | val baudRate = 115200 19 | val divider = Math.round(1.0f * fpgaClock / (baudRate * rxOverclock) - 1) 20 | 21 | def clockSerial(clk: Clock) = clk.step(fpgaClock / baudRate) 22 | 23 | private def rxOne(u: Uart, c: UInt) = { 24 | /* Start bit */ 25 | u.io.serialPort.rx.poke(0.U) 26 | clockSerial(u.clock) 27 | 28 | /* 29 | * This doesn't work: 30 | * c.pad(8).asBools.foreach({cc => 31 | */ 32 | c.asBools.foreach { cc => 33 | u.io.serialPort.rx.poke(cc) 34 | clockSerial(u.clock) 35 | } 36 | 37 | /* Have to do this instead: */ 38 | u.io.serialPort.rx.poke(0.U) 39 | clockSerial(u.clock) 40 | 41 | /* Stop bit */ 42 | u.io.serialPort.rx.poke(1.U) 43 | clockSerial(u.clock) 44 | } 45 | 46 | it should "pass a unit test" in { 47 | test(new Uart(64, rxOverclock)).withAnnotations(Seq(WriteVcdAnnotation)) { u => 48 | u.clock.setTimeout(10000) 49 | 50 | u.io.dataPort.clockDivisor.valid.poke(true.B) 51 | u.io.dataPort.clockDivisor.bits.poke(divider.U) 52 | 53 | u.io.dataPort.rxQueue.ready.poke(false.B) 54 | 55 | val testChars = Seq("h41".U, "h6E".U, "h74".U, "h6F".U, "h6E".U) 56 | 57 | testChars.foreach(c => rxOne(u, c)) 58 | 59 | u.io.dataPort.rxQueue.ready.poke(true.B) 60 | testChars.foreach { c => 61 | u.io.dataPort.rxQueue.valid.expect(true.B) 62 | u.io.dataPort.rxQueue.bits.expect(c) 63 | u.clock.step() 64 | } 65 | u.io.dataPort.rxQueue.ready.poke(false.B) 66 | 67 | u.io.dataPort.rxFull.expect(false.B) 68 | u.io.dataPort.txFull.expect(false.B) 69 | 70 | rxOne(u, "h5a".U) 71 | u.io.dataPort.rxFull.expect(false.B) 72 | (0 to 64).foreach(_ => rxOne(u, "h5a".U)) 73 | u.io.dataPort.rxFull.expect(true.B) 74 | 75 | u.io.dataPort.txQueue.bits.poke("h75".U) 76 | u.io.dataPort.txQueue.valid.poke(true.B) 77 | u.clock.step() 78 | u.io.dataPort.txFull.expect(false.B) 79 | (0 to 64).foreach(_ => u.clock.step()) 80 | u.io.dataPort.txFull.expect(true.B) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /constraints/arty_a7.xdc: -------------------------------------------------------------------------------- 1 | # Clock pin 2 | set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports {clock}] 3 | 4 | # Clock constraints 5 | create_clock -period 10.0 [get_ports {clock}] 6 | 7 | # Reset 8 | set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { reset }] 9 | 10 | # LEDs 11 | set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { led0} ] 12 | set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[0]} ] 13 | set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[1]} ] 14 | set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[2]} ] 15 | 16 | set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[3] }]; #IO_L24P_T3_35 Sch=led3_g 17 | set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[4] }]; #IO_L22N_T3_35 Sch=led2_g 18 | set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[5] }]; #IO_L21P_T3_DQS_35 Sch=led1_g 19 | set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[6] }]; #IO_L19N_T3_VREF_35 Sch=led0_g 20 | 21 | ##Buttons 22 | set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[7] }]; #IO_L6N_T0_VREF_16 Sch=btn[0] 23 | # set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { GPIO0[8] }]; #IO_L11P_T1_SRCC_16 Sch=btn[1] 24 | # set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2] 25 | # set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3] 26 | 27 | ##USB-UART Interface 28 | set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { UART0_tx }]; 29 | set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { UART0_rx }]; 30 | 31 | 32 | -------------------------------------------------------------------------------- /constraints/ecp5-ulx3s.lpf: -------------------------------------------------------------------------------- 1 | LOCATE COMP "clock" SITE "G2"; 2 | IOBUF PORT "clock" PULLMODE=NONE IO_TYPE=LVCMOS33; 3 | FREQUENCY PORT "clock" 15 MHZ; 4 | 5 | LOCATE COMP "reset" SITE "D6"; 6 | IOBUF PORT "reset" PULLMODE=UP IO_TYPE=LVCMOS33; 7 | 8 | LOCATE COMP "UART0_tx" SITE "L4"; 9 | IOBUF PORT "UART0_tx" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; 10 | LOCATE COMP "UART0_rx" SITE "M1"; 11 | IOBUF PORT "UART0_rx" PULLMODE=UP IO_TYPE=LVCMOS33; 12 | 13 | LOCATE COMP "led0" SITE "B2"; # LED0 (Heartbeat) 14 | IOBUF PORT "led0" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 15 | 16 | LOCATE COMP "GPIO0[0]" SITE "C2"; # LED1 17 | IOBUF PORT "GPIO0[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 18 | LOCATE COMP "GPIO0[1]" SITE "C1"; # LED2 19 | IOBUF PORT "GPIO0[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 20 | LOCATE COMP "GPIO0[2]" SITE "D2"; # LED3 21 | IOBUF PORT "GPIO0[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 22 | LOCATE COMP "GPIO0[3]" SITE "D1"; # LED4 23 | IOBUF PORT "GPIO0[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 24 | LOCATE COMP "GPIO0[4]" SITE "E2"; # LED5 25 | IOBUF PORT "GPIO0[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 26 | LOCATE COMP "GPIO0[5]" SITE "E1"; # LED6 27 | IOBUF PORT "GPIO0[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 28 | LOCATE COMP "GPIO0[6]" SITE "H3"; # LED7 29 | IOBUF PORT "GPIO0[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 30 | 31 | ## Pushbuttons 32 | LOCATE COMP "GPIO0[7]" SITE "R1"; # FIRE1 33 | IOBUF PORT "GPIO0[7]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 34 | LOCATE COMP "GPIO0[8]" SITE "T1"; # FIRE2 35 | IOBUF PORT "GPIO0[8]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 36 | 37 | LOCATE COMP "btn[3]" SITE "R18"; # UP W1->R18 38 | LOCATE COMP "btn[4]" SITE "V1"; # DOWN 39 | LOCATE COMP "btn[5]" SITE "U1"; # LEFT 40 | LOCATE COMP "btn[6]" SITE "H16"; # RIGHT Y2->H16 41 | IOBUF PORT "btn[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 42 | IOBUF PORT "btn[4]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 43 | IOBUF PORT "btn[5]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 44 | IOBUF PORT "btn[6]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 45 | 46 | # PMOD0 47 | LOCATE COMP "PMOD0_A0" SITE "L17"; #GN17 48 | LOCATE COMP "PMOD0_A1" SITE "M17"; #GN16 49 | LOCATE COMP "PMOD0_A2" SITE "P16"; #GN15 <------ NOT WORKING ON MY BOARD 50 | LOCATE COMP "PMOD0_A3" SITE "U17"; #GN14 51 | LOCATE COMP "PMOD0_B0" SITE "L16"; #GP17 52 | LOCATE COMP "PMOD0_B1" SITE "N16"; #GP16 53 | LOCATE COMP "PMOD0_B2" SITE "N17"; #GP15 54 | LOCATE COMP "PMOD0_B3" SITE "U18"; #GP14 55 | IOBUF PORT "PMOD0_A0" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 56 | IOBUF PORT "PMOD0_A1" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 57 | IOBUF PORT "PMOD0_A2" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 58 | IOBUF PORT "PMOD0_A3" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 59 | IOBUF PORT "PMOD0_B0" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 60 | IOBUF PORT "PMOD0_B1" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 61 | IOBUF PORT "PMOD0_B2" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 62 | IOBUF PORT "PMOD0_B3" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 63 | 64 | # PMOD1 65 | LOCATE COMP "PMOD1_A0" SITE "D16"; #GN24 66 | LOCATE COMP "PMOD1_A1" SITE "C17"; #GN23 67 | LOCATE COMP "PMOD1_A2" SITE "C15"; #GN22 68 | LOCATE COMP "PMOD1_A3" SITE "D17"; #GN21 69 | LOCATE COMP "PMOD1_B0" SITE "C16"; #GP24 70 | LOCATE COMP "PMOD1_B1" SITE "B17"; #GP23 71 | LOCATE COMP "PMOD1_B2" SITE "B15"; #GP22 72 | LOCATE COMP "PMOD1_B3" SITE "C18"; #GP21 73 | IOBUF PORT "PMOD1_A0" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 74 | IOBUF PORT "PMOD1_A1" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 75 | IOBUF PORT "PMOD1_A2" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 76 | IOBUF PORT "PMOD1_A3" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 77 | IOBUF PORT "PMOD1_B0" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 78 | IOBUF PORT "PMOD1_B1" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 79 | IOBUF PORT "PMOD1_B2" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 80 | IOBUF PORT "PMOD1_B3" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; 81 | -------------------------------------------------------------------------------- /constraints/qmtech-kintex7.xdc: -------------------------------------------------------------------------------- 1 | ##### Core board ##### 2 | # Clock 3 | set_property LOC F22 [get_ports clock] 4 | set_property IOSTANDARD LVCMOS33 [get_ports {clock}] 5 | create_clock -period 20.0 [get_ports {clock}] 6 | 7 | # LED2_FPGA J26 8 | set_property LOC J26 [get_ports led0] 9 | set_property IOSTANDARD LVCMOS33 [get_ports {led0}] 10 | 11 | # LED3_FPGA H26 12 | set_property LOC H26 [get_ports GPIO0[0]] 13 | set_property IOSTANDARD LVCMOS33 [get_ports {GPIO0[0]}] 14 | 15 | ##Buttons 16 | # Sw 2 - AF9 17 | # set_property LOC AF9 [get_ports reset] 18 | # set_property IOSTANDARD LVCMOS33 [get_ports {reset}] 19 | 20 | # Sw 3 - AF10 21 | # set_property LOC AF10 [get_ports sw3] 22 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw3}] 23 | 24 | ##### Daughter board ##### 25 | 26 | # LED0 27 | set_property LOC A18 [get_ports GPIO0[1]] 28 | set_property IOSTANDARD LVCMOS33 [get_ports {GPIO0[1]}] 29 | 30 | # LED1 31 | set_property LOC A19 [get_ports GPIO0[2]] 32 | set_property IOSTANDARD LVCMOS33 [get_ports {GPIO0[2]}] 33 | 34 | # LED2 35 | set_property LOC C17 [get_ports GPIO0[3]] 36 | set_property IOSTANDARD LVCMOS33 [get_ports {GPIO0[3]}] 37 | 38 | # LED3 39 | set_property LOC C18 [get_ports GPIO0[4]] 40 | set_property IOSTANDARD LVCMOS33 [get_ports {GPIO0[4]}] 41 | 42 | # LED4 43 | set_property LOC E18 [get_ports GPIO0[5]] 44 | set_property IOSTANDARD LVCMOS33 [get_ports {GPIO0[5]}] 45 | 46 | ##Buttons 47 | # SW2 48 | set_property LOC B20 [get_ports reset] 49 | set_property IOSTANDARD LVCMOS33 [get_ports {reset}] 50 | # SW3 51 | set_property LOC A20 [get_ports GPIO0[7]] 52 | set_property IOSTANDARD LVCMOS33 [get_ports {GPIO0[7]}] 53 | # SW4 54 | # set_property LOC C19 [get_ports d_sw4] 55 | # set_property IOSTANDARD LVCMOS33 [get_ports {d_sw4}] 56 | # SW5 57 | # set_property LOC B19 [get_ports d_sw5] 58 | # set_property IOSTANDARD LVCMOS33 [get_ports {d_sw5}] 59 | 60 | 61 | ##USB-UART Interface 62 | set_property LOC B12 [get_ports UART0_tx] 63 | set_property IOSTANDARD LVCMOS33 [get_ports {UART0_tx}] 64 | set_property LOC B11 [get_ports UART0_rx] 65 | set_property IOSTANDARD LVCMOS33 [get_ports {UART0_rx}] -------------------------------------------------------------------------------- /constraints/qmtech-zyjzgw.xdc: -------------------------------------------------------------------------------- 1 | ##### Core board ##### 2 | 3 | set_property LOC F22 [get_ports clock] 4 | set_property IOSTANDARD LVCMOS33 [get_ports {clock}] 5 | create_clock -period 20.0 [get_ports {clock}] 6 | 7 | # LED2_FPGA R26 8 | set_property LOC R26 [get_ports led0] 9 | set_property IOSTANDARD LVCMOS33 [get_ports {led0}] 10 | 11 | # LED3_FPGA P26 12 | set_property LOC P26 [get_ports led2] 13 | set_property IOSTANDARD LVCMOS33 [get_ports {led2}] 14 | 15 | ##Buttons 16 | # Sw 2 - AB26 17 | set_property LOC AB26 [get_ports reset] 18 | set_property IOSTANDARD LVCMOS33 [get_ports {reset}] 19 | 20 | # Sw 3 - AC26 21 | # set_property LOC AC26 [get_ports sw3] 22 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw3}] 23 | 24 | ##### Daughter board ##### 25 | 26 | # LED3_FPGA BANK14_E25 27 | # set_property LOC E25 [get_ports io_led1] 28 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_led1}] 29 | 30 | # LED4_FPGA BANK16_C14 31 | # set_property LOC C14 [get_ports io_GPIO0[2]] 32 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_GPIO0[2]}] 33 | 34 | # LED5_FPGA BANK16_B14 35 | # set_property LOC B14 [get_ports io_GPIO0[3]] 36 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_GPIO0[3]}] 37 | 38 | ##Buttons 39 | # Sw1 40 | # set_property LOC Y22 [get_ports sw1] 41 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw1}] 42 | # Sw2 43 | # set_property LOC AA22 [get_ports sw2] 44 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw2}] 45 | # Sw3 46 | # set_property LOC Y23 [get_ports sw3] 47 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw3}] 48 | # Sw4 49 | # set_property LOC AA24 [get_ports sw4] 50 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw4}] 51 | # Sw5 52 | # set_property LOC AC23 [get_ports sw5] 53 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw5}] 54 | # Sw6 55 | # set_property LOC AC24 [get_ports sw6] 56 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw6}] 57 | # Sw7 58 | # set_property LOC AA25 [get_ports sw7] 59 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw7}] 60 | # Sw8 61 | # set_property LOC AB25 [get_ports sw8] 62 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw8}] 63 | 64 | 65 | ##USB-UART Interface (On jp3 in daughter board) Pin 1 - GND, Pin 3 - TX, Pin 5 - RX 66 | # set_property LOC AE26 [get_ports io_UART0_tx] 67 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_UART0_tx}] 68 | # set_property LOC AD26 [get_ports io_UART0_rx] 69 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_UART0_rx}] -------------------------------------------------------------------------------- /download_firtool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check latest Firtool version 4 | 5 | # FIRTOOL_VERSION=$(curl -sL https://api.github.com/repos/llvm/circt/releases/latest | grep tag_name | cut -d '"' -f 4) 6 | FIRTOOL_VERSION=firtool-1.75.0 7 | 8 | OS=$(uname -s) 9 | 10 | if [ "$OS" = "Linux" ]; then 11 | FIRTOOL_URL=https://github.com/llvm/circt/releases/download/$FIRTOOL_VERSION/firrtl-bin-linux-x64.tar.gz 12 | elif [ "$OS" = "Darwin" ]; then 13 | FIRTOOL_URL=https://github.com/llvm/circt/releases/download/$FIRTOOL_VERSION/firrtl-bin-macos-x64.tar.gz 14 | fi 15 | 16 | # Download firtool and create a symbolic link to it 17 | curl -sL "$FIRTOOL_URL" | tar -xz 18 | ln -sf "$FIRTOOL_VERSION"/bin/firtool firtool 19 | 20 | echo "Firtool $FIRTOOL_VERSION has been downloaded and linked to current directory." 21 | -------------------------------------------------------------------------------- /gcc/blinkLED/Makefile: -------------------------------------------------------------------------------- 1 | SOURCES := $(shell find . ../lib -name '*.c') 2 | ASM_SOURCES := $(shell find . ../lib -name '*.s') 3 | OBJECTS := $(SOURCES:%.c=%.o) 4 | ASM_OBJECTS := $(ASM_SOURCES:%.s=%.s.o) 5 | ASM := $(SOURCES:%.c=%.s) 6 | 7 | DOCKERORPODMAN = $(shell command -v podman 2> /dev/null || echo docker) 8 | USEDOCKER = 1 9 | CURDIR = $(shell pwd) 10 | DOCKERARGS = run --rm -v $(PWD)/..:/src -w /src/$(shell basename $(CURDIR)) 11 | DOCKERIMG = $(DOCKERORPODMAN) $(DOCKERARGS) docker.io/carlosedp/crossbuild-riscv64:latest 12 | 13 | CFLAGS=-Wall -mabi=ilp32 -march=rv32i -ffreestanding -fcommon -Os -I../lib 14 | LDFLAGS=-T ../lib/riscv.ld -m elf32lriscv -O binary -Map=main.map 15 | 16 | PREFIX=riscv64-linux-gnu 17 | 18 | ifeq ($(USEDOCKER), 1) 19 | OC=$(DOCKERIMG) $(PREFIX)-objcopy 20 | OD=$(DOCKERIMG) $(PREFIX)-objdump 21 | CC=$(DOCKERIMG) $(PREFIX)-gcc 22 | LD=$(DOCKERIMG) $(PREFIX)-ld 23 | HD=$(DOCKERIMG) hexdump 24 | else 25 | OC=$(PREFIX)-objcopy 26 | OD=$(PREFIX)-objdump 27 | CC=$(PREFIX)-gcc 28 | LD=$(PREFIX)-ld 29 | HD=hexdump 30 | endif 31 | 32 | all: main.elf main-rom.mem main-ram.mem main.hex main.dump 33 | asm: $(ASM) 34 | 35 | %.o: %.c 36 | @echo "Building $< -> $@" 37 | @$(CC) -c $(CFLAGS) -o $@ $< 38 | 39 | %.s.o: %.s 40 | @echo "Building $< -> $@" 41 | @$(CC) -c $(CFLAGS) -o $@ $< 42 | 43 | main.elf: $(OBJECTS) $(ASM_OBJECTS) 44 | @echo "Linking $< $(OBJECTS) $(ASM_OBJECTS)" 45 | @$(LD) $(LDFLAGS) $(OBJECTS) $(ASM_OBJECTS) -o main.elf 46 | 47 | main.dump: main.elf 48 | @echo "Dumping to $@" 49 | @$(OD) -d -t -r $< > $@ 50 | 51 | main.hex: main.elf 52 | @echo "Building $< -> $@ for http://tice.sea.eseo.fr/riscv/" 53 | @$(OC) -O ihex $< $@ --only-section .text\* 54 | 55 | main-%.mem: main.elf ## Readmemh 32bit memory files (rom or ram) 56 | @echo "Building $< -> $@" 57 | $(OC) -O binary $< $(@:main-%.mem=main-%.bin) --only-section $(if $(filter %rom.mem,$@),.text*,.*data*) 58 | $(HD) -ve '1/4 "%08x\n"' $(@:main-%.mem=main-%.bin) > $@ 59 | 60 | %.s: %.c 61 | @echo "Building $< -> $@" 62 | @$(CC) -S $(CFLAGS) -o $@ $< 63 | 64 | clean: 65 | @echo "Cleaning build files" 66 | rm -f $(ASM) $(OBJECTS) $(ASM_OBJECTS) *.elf *.hex *.bin *.mem *.s.o *.map *.dump 67 | -------------------------------------------------------------------------------- /gcc/blinkLED/main-ram.mem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlosedp/chiselv/1bff2c6c5380ecf24b09275fe2a409c12fbec9a1/gcc/blinkLED/main-ram.mem -------------------------------------------------------------------------------- /gcc/blinkLED/main-rom.mem: -------------------------------------------------------------------------------- 1 | 00000033 2 | 000000b3 3 | 00000133 4 | 000001b3 5 | 00000233 6 | 000002b3 7 | 00000333 8 | 000003b3 9 | 00000433 10 | 000004b3 11 | 00000533 12 | 000005b3 13 | 00000633 14 | 000006b3 15 | 00000733 16 | 000007b3 17 | 00000833 18 | 000008b3 19 | 00000933 20 | 000009b3 21 | 00000a33 22 | 00000ab3 23 | 00000b33 24 | 00000bb3 25 | 00000c33 26 | 00000cb3 27 | 00000d33 28 | 00000db3 29 | 00000e33 30 | 00000eb3 31 | 00000f33 32 | 00000fb3 33 | 80010137 34 | 00010113 35 | 0fc000ef 36 | 0040006f 37 | 0000006f 38 | 300017b7 39 | 00a7a023 40 | 00008067 41 | 300017b7 42 | 0007a503 43 | 00008067 44 | 300017b7 45 | 00a7a223 46 | 00008067 47 | 300017b7 48 | 0047a503 49 | 00008067 50 | 300037b7 51 | 00a7a023 52 | 00008067 53 | 300017b7 54 | 0007a703 55 | 00100793 56 | 00a79533 57 | 00058a63 58 | 00e56533 59 | 300017b7 60 | 00a7a023 61 | 00008067 62 | fff54513 63 | 00e57533 64 | fedff06f 65 | 300017b7 66 | 0047a703 67 | 00100793 68 | 00a79533 69 | 00e57533 70 | 00a03533 71 | 00008067 72 | 300017b7 73 | 0047a703 74 | 00100793 75 | 00a79533 76 | 00058a63 77 | 00e56533 78 | 300017b7 79 | 00a7a223 80 | 00008067 81 | fff54513 82 | 00e57533 83 | fedff06f 84 | 300037b7 85 | 0007a503 86 | 00008067 87 | 300037b7 88 | 0007a023 89 | 00008067 90 | 300037b7 91 | 0007a023 92 | 0007a703 93 | 00e50533 94 | 0007a703 95 | fee57ee3 96 | 0007a023 97 | 00008067 98 | ff010113 99 | 00812423 100 | 30001437 101 | 00042783 102 | 00112623 103 | 00912223 104 | 0017e793 105 | 00f42023 106 | 00042783 107 | 1f400513 108 | 0027e793 109 | 00f42023 110 | 00042783 111 | 0047e793 112 | 00f42023 113 | 00042783 114 | 0087e793 115 | 00f42023 116 | 00042783 117 | 0107e793 118 | 00f42023 119 | 00042783 120 | 0207e793 121 | 00f42023 122 | 00042783 123 | 0407e793 124 | 00f42023 125 | 00042783 126 | f7f7f793 127 | 00f42023 128 | 00442783 129 | 0017e793 130 | 00f42223 131 | 00442783 132 | 0027e793 133 | 00f42223 134 | f51ff0ef 135 | 00442783 136 | 1f400513 137 | ffd7f793 138 | 00f42223 139 | f3dff0ef 140 | 00700513 141 | ed1ff0ef 142 | 0ff57593 143 | 00300513 144 | ee1ff0ef 145 | 00a00493 146 | 00442783 147 | 0c800513 148 | fff48493 149 | 0047e793 150 | 00f42223 151 | f0dff0ef 152 | 00442783 153 | 0c800513 154 | ffb7f793 155 | 00f42223 156 | ef9ff0ef 157 | fc049ae3 158 | 3e800513 159 | fb1ff06f 160 | -------------------------------------------------------------------------------- /gcc/blinkLED/main.c: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | 3 | int main() 4 | { 5 | // Set GPIO0 Direction [IOOOOOOO] right to left 6 | // Pin Number[76543210] 7 | pinMode(0, OUTPUT); 8 | pinMode(1, OUTPUT); 9 | pinMode(2, OUTPUT); 10 | pinMode(3, OUTPUT); 11 | pinMode(4, OUTPUT); 12 | pinMode(5, OUTPUT); 13 | pinMode(6, OUTPUT); 14 | pinMode(7, INPUT); 15 | 16 | // Turn on LEDs 0 and 1 17 | digitalWrite(0, HIGH); 18 | digitalWrite(1, HIGH); 19 | 20 | // Turn off LED 1 after 1/2 second 21 | sleep(500); 22 | digitalWrite(1, LOW); 23 | sleep(500); 24 | 25 | while (1) 26 | { 27 | // Light LED 3 if button is pressed before LED2 starts blinking 28 | digitalWrite(3, digitalRead(7)); 29 | 30 | // Loop blinking LED 2 31 | for (int i = 0; i < 10; i++) 32 | { 33 | 34 | digitalWrite(2, HIGH); 35 | sleep(200); 36 | digitalWrite(2, LOW); 37 | sleep(200); 38 | } 39 | sleep(1000); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /gcc/blinkLED/main.dump: -------------------------------------------------------------------------------- 1 | 2 | main.elf: file format elf32-littleriscv 3 | 4 | SYMBOL TABLE: 5 | 00000000 l d .text 00000000 .text 6 | 00000184 l d .text.startup 00000000 .text.startup 7 | 00000000 l d .comment 00000000 .comment 8 | 00000000 l df *ABS* 00000000 ../lib/crt.s.o 9 | 00000090 l .text 00000000 _halt 10 | 00000000 l df *ABS* 00000000 main.c 11 | 000000b8 g F .text 0000000c readGPIO 12 | 00008000 g *ABS* 00000000 __stack_size 13 | 00000100 g F .text 0000001c digitalRead 14 | 00000000 g .text 00000000 _boot 15 | 000000a0 g F .text 0000000c readDirection 16 | 00000164 g F .text 00000020 sleep 17 | 0000011c g F .text 00000030 digitalWrite 18 | 000000d0 g F .text 00000030 pinMode 19 | 0000014c g F .text 0000000c getTimer 20 | 00002000 g *ABS* 00000000 __heap_size 21 | 00000184 g F .text.startup 000000f8 main 22 | 80010000 g .text.startup 00000000 _sstack 23 | 000000ac g F .text 0000000c setGPIO 24 | 00000094 g F .text 0000000c setDirection 25 | 00000158 g F .text 0000000c resetTimer 26 | 80000000 g .text.startup 00000000 _heap 27 | 000000c4 g F .text 0000000c setTimer 28 | 29 | 30 | 31 | Disassembly of section .text: 32 | 33 | 00000000 <_boot>: 34 | 0: 00000033 add zero,zero,zero 35 | 4: 000000b3 add ra,zero,zero 36 | 8: 00000133 add sp,zero,zero 37 | c: 000001b3 add gp,zero,zero 38 | 10: 00000233 add tp,zero,zero 39 | 14: 000002b3 add t0,zero,zero 40 | 18: 00000333 add t1,zero,zero 41 | 1c: 000003b3 add t2,zero,zero 42 | 20: 00000433 add s0,zero,zero 43 | 24: 000004b3 add s1,zero,zero 44 | 28: 00000533 add a0,zero,zero 45 | 2c: 000005b3 add a1,zero,zero 46 | 30: 00000633 add a2,zero,zero 47 | 34: 000006b3 add a3,zero,zero 48 | 38: 00000733 add a4,zero,zero 49 | 3c: 000007b3 add a5,zero,zero 50 | 40: 00000833 add a6,zero,zero 51 | 44: 000008b3 add a7,zero,zero 52 | 48: 00000933 add s2,zero,zero 53 | 4c: 000009b3 add s3,zero,zero 54 | 50: 00000a33 add s4,zero,zero 55 | 54: 00000ab3 add s5,zero,zero 56 | 58: 00000b33 add s6,zero,zero 57 | 5c: 00000bb3 add s7,zero,zero 58 | 60: 00000c33 add s8,zero,zero 59 | 64: 00000cb3 add s9,zero,zero 60 | 68: 00000d33 add s10,zero,zero 61 | 6c: 00000db3 add s11,zero,zero 62 | 70: 00000e33 add t3,zero,zero 63 | 74: 00000eb3 add t4,zero,zero 64 | 78: 00000f33 add t5,zero,zero 65 | 7c: 00000fb3 add t6,zero,zero 66 | 80: 80010137 lui sp,0x80010 67 | 84: 00010113 mv sp,sp 68 | 88: 0fc000ef jal ra,184
69 | 8c: 0040006f j 90 <_halt> 70 | 71 | 00000090 <_halt>: 72 | 90: 0000006f j 90 <_halt> 73 | 74 | 00000094 : 75 | 94: 300017b7 lui a5,0x30001 76 | 98: 00a7a023 sw a0,0(a5) # 30001000 <__stack_size+0x2fff9000> 77 | 9c: 00008067 ret 78 | 79 | 000000a0 : 80 | a0: 300017b7 lui a5,0x30001 81 | a4: 0007a503 lw a0,0(a5) # 30001000 <__stack_size+0x2fff9000> 82 | a8: 00008067 ret 83 | 84 | 000000ac : 85 | ac: 300017b7 lui a5,0x30001 86 | b0: 00a7a223 sw a0,4(a5) # 30001004 <__stack_size+0x2fff9004> 87 | b4: 00008067 ret 88 | 89 | 000000b8 : 90 | b8: 300017b7 lui a5,0x30001 91 | bc: 0047a503 lw a0,4(a5) # 30001004 <__stack_size+0x2fff9004> 92 | c0: 00008067 ret 93 | 94 | 000000c4 : 95 | c4: 300037b7 lui a5,0x30003 96 | c8: 00a7a023 sw a0,0(a5) # 30003000 <__stack_size+0x2fffb000> 97 | cc: 00008067 ret 98 | 99 | 000000d0 : 100 | d0: 300017b7 lui a5,0x30001 101 | d4: 0007a703 lw a4,0(a5) # 30001000 <__stack_size+0x2fff9000> 102 | d8: 00100793 li a5,1 103 | dc: 00a79533 sll a0,a5,a0 104 | e0: 00058a63 beqz a1,f4 105 | e4: 00e56533 or a0,a0,a4 106 | e8: 300017b7 lui a5,0x30001 107 | ec: 00a7a023 sw a0,0(a5) # 30001000 <__stack_size+0x2fff9000> 108 | f0: 00008067 ret 109 | f4: fff54513 not a0,a0 110 | f8: 00e57533 and a0,a0,a4 111 | fc: fedff06f j e8 112 | 113 | 00000100 : 114 | 100: 300017b7 lui a5,0x30001 115 | 104: 0047a703 lw a4,4(a5) # 30001004 <__stack_size+0x2fff9004> 116 | 108: 00100793 li a5,1 117 | 10c: 00a79533 sll a0,a5,a0 118 | 110: 00e57533 and a0,a0,a4 119 | 114: 00a03533 snez a0,a0 120 | 118: 00008067 ret 121 | 122 | 0000011c : 123 | 11c: 300017b7 lui a5,0x30001 124 | 120: 0047a703 lw a4,4(a5) # 30001004 <__stack_size+0x2fff9004> 125 | 124: 00100793 li a5,1 126 | 128: 00a79533 sll a0,a5,a0 127 | 12c: 00058a63 beqz a1,140 128 | 130: 00e56533 or a0,a0,a4 129 | 134: 300017b7 lui a5,0x30001 130 | 138: 00a7a223 sw a0,4(a5) # 30001004 <__stack_size+0x2fff9004> 131 | 13c: 00008067 ret 132 | 140: fff54513 not a0,a0 133 | 144: 00e57533 and a0,a0,a4 134 | 148: fedff06f j 134 135 | 136 | 0000014c : 137 | 14c: 300037b7 lui a5,0x30003 138 | 150: 0007a503 lw a0,0(a5) # 30003000 <__stack_size+0x2fffb000> 139 | 154: 00008067 ret 140 | 141 | 00000158 : 142 | 158: 300037b7 lui a5,0x30003 143 | 15c: 0007a023 sw zero,0(a5) # 30003000 <__stack_size+0x2fffb000> 144 | 160: 00008067 ret 145 | 146 | 00000164 : 147 | 164: 300037b7 lui a5,0x30003 148 | 168: 0007a023 sw zero,0(a5) # 30003000 <__stack_size+0x2fffb000> 149 | 16c: 0007a703 lw a4,0(a5) 150 | 170: 00e50533 add a0,a0,a4 151 | 174: 0007a703 lw a4,0(a5) 152 | 178: fee57ee3 bgeu a0,a4,174 153 | 17c: 0007a023 sw zero,0(a5) 154 | 180: 00008067 ret 155 | 156 | Disassembly of section .text.startup: 157 | 158 | 00000184
: 159 | 184: ff010113 addi sp,sp,-16 # 8000fff0 <_sstack+0xfffffff0> 160 | 188: 00812423 sw s0,8(sp) 161 | 18c: 30001437 lui s0,0x30001 162 | 190: 00042783 lw a5,0(s0) # 30001000 <__stack_size+0x2fff9000> 163 | 194: 00112623 sw ra,12(sp) 164 | 198: 00912223 sw s1,4(sp) 165 | 19c: 0017e793 ori a5,a5,1 166 | 1a0: 00f42023 sw a5,0(s0) 167 | 1a4: 00042783 lw a5,0(s0) 168 | 1a8: 1f400513 li a0,500 169 | 1ac: 0027e793 ori a5,a5,2 170 | 1b0: 00f42023 sw a5,0(s0) 171 | 1b4: 00042783 lw a5,0(s0) 172 | 1b8: 0047e793 ori a5,a5,4 173 | 1bc: 00f42023 sw a5,0(s0) 174 | 1c0: 00042783 lw a5,0(s0) 175 | 1c4: 0087e793 ori a5,a5,8 176 | 1c8: 00f42023 sw a5,0(s0) 177 | 1cc: 00042783 lw a5,0(s0) 178 | 1d0: 0107e793 ori a5,a5,16 179 | 1d4: 00f42023 sw a5,0(s0) 180 | 1d8: 00042783 lw a5,0(s0) 181 | 1dc: 0207e793 ori a5,a5,32 182 | 1e0: 00f42023 sw a5,0(s0) 183 | 1e4: 00042783 lw a5,0(s0) 184 | 1e8: 0407e793 ori a5,a5,64 185 | 1ec: 00f42023 sw a5,0(s0) 186 | 1f0: 00042783 lw a5,0(s0) 187 | 1f4: f7f7f793 andi a5,a5,-129 188 | 1f8: 00f42023 sw a5,0(s0) 189 | 1fc: 00442783 lw a5,4(s0) 190 | 200: 0017e793 ori a5,a5,1 191 | 204: 00f42223 sw a5,4(s0) 192 | 208: 00442783 lw a5,4(s0) 193 | 20c: 0027e793 ori a5,a5,2 194 | 210: 00f42223 sw a5,4(s0) 195 | 214: f51ff0ef jal ra,164 196 | 218: 00442783 lw a5,4(s0) 197 | 21c: 1f400513 li a0,500 198 | 220: ffd7f793 andi a5,a5,-3 199 | 224: 00f42223 sw a5,4(s0) 200 | 228: f3dff0ef jal ra,164 201 | 22c: 00700513 li a0,7 202 | 230: ed1ff0ef jal ra,100 203 | 234: 0ff57593 andi a1,a0,255 204 | 238: 00300513 li a0,3 205 | 23c: ee1ff0ef jal ra,11c 206 | 240: 00a00493 li s1,10 207 | 244: 00442783 lw a5,4(s0) 208 | 248: 0c800513 li a0,200 209 | 24c: fff48493 addi s1,s1,-1 210 | 250: 0047e793 ori a5,a5,4 211 | 254: 00f42223 sw a5,4(s0) 212 | 258: f0dff0ef jal ra,164 213 | 25c: 00442783 lw a5,4(s0) 214 | 260: 0c800513 li a0,200 215 | 264: ffb7f793 andi a5,a5,-5 216 | 268: 00f42223 sw a5,4(s0) 217 | 26c: ef9ff0ef jal ra,164 218 | 270: fc049ae3 bnez s1,244 219 | 274: 3e800513 li a0,1000 220 | 278: fb1ff06f j 228 221 | -------------------------------------------------------------------------------- /gcc/blinkLED/main.hex: -------------------------------------------------------------------------------- 1 | :1000000033000000B300000033010000B301000022 2 | :1000100033020000B302000033030000B30300000A 3 | :1000200033040000B304000033050000B3050000F2 4 | :1000300033060000B306000033070000B3070000DA 5 | :1000400033080000B308000033090000B3090000C2 6 | :10005000330A0000B30A0000330B0000B30B0000AA 7 | :10006000330C0000B30C0000330D0000B30D000092 8 | :10007000330E0000B30E0000330F0000B30F00007A 9 | :100080003701018013010100EF00C00F6F00400035 10 | :100090006F000000B717003023A0A70067800000A2 11 | :1000A000B717003003A5070067800000B7170030BE 12 | :1000B00023A2A70067800000B717003003A5470000 13 | :1000C00067800000B737003023A0A70067800000DA 14 | :1000D000B717003003A70700930710003395A70058 15 | :1000E000638A05003365E500B717003023A0A70039 16 | :1000F000678000001345F5FF3375E5006FF0DFFE04 17 | :10010000B717003003A74700930710003395A700E7 18 | :100110003375E5003335A00067800000B717003065 19 | :1001200003A74700930710003395A700638A0500D3 20 | :100130003365E500B717003023A2A70067800000F1 21 | :100140001345F5FF3375E5006FF0DFFEB73700307C 22 | :1001500003A5070067800000B737003023A0070021 23 | :1001600067800000B737003023A0070003A707000F 24 | :100170003305E50003A70700E37EE5FE23A00700A3 25 | :040180006780000094 26 | :10018400130101FF23248100371400308327040066 27 | :10019400232611002322910093E717002320F40063 28 | :1001A400832704001305401F93E727002320F4004E 29 | :1001B4008327040093E747002320F40083270400E7 30 | :1001C40093E787002320F4008327040093E70701C3 31 | :1001D4002320F4008327040093E707022320F4007C 32 | :1001E4008327040093E707042320F40083270400F3 33 | :1001F40093F7F7F72320F4008327440093E71700CD 34 | :100204002322F4008327440093E727002322F400E9 35 | :10021400EFF01FF5832744001305401F93F7D7FF22 36 | :100224002322F400EFF0DFF313057000EFF01FED6D 37 | :100234009375F50F13053000EFF01FEE9304A00043 38 | :10024400832744001305800C9384F4FF93E747004D 39 | :100254002322F400EFF0DFF0832744001305800C21 40 | :1002640093F7B7FF2322F400EFF09FEFE39A04FC27 41 | :080274001305803E6FF01FFB33 42 | :00000001FF 43 | -------------------------------------------------------------------------------- /gcc/blinkLED/main.map: -------------------------------------------------------------------------------- 1 | 2 | Memory Configuration 3 | 4 | Name Origin Length Attributes 5 | ROM 0x0000000000000000 0x0000000000010000 xrw 6 | RAM 0x0000000080000000 0x0000000000010000 xrw 7 | *default* 0x0000000000000000 0xffffffffffffffff 8 | 9 | Linker script and memory map 10 | 11 | 0x0000000000002000 __heap_size = 0x2000 12 | 0x0000000000008000 __stack_size = 0x8000 13 | 14 | .text 0x0000000000000000 0x184 15 | *(.boot) 16 | .boot 0x0000000000000000 0x94 ../lib/crt.s.o 17 | 0x0000000000000000 _boot 18 | *(.text) 19 | .text 0x0000000000000094 0xf0 ./main.o 20 | 0x0000000000000094 setDirection 21 | 0x00000000000000a0 readDirection 22 | 0x00000000000000ac setGPIO 23 | 0x00000000000000b8 readGPIO 24 | 0x00000000000000c4 setTimer 25 | 0x00000000000000d0 pinMode 26 | 0x0000000000000100 digitalRead 27 | 0x000000000000011c digitalWrite 28 | 0x000000000000014c getTimer 29 | 0x0000000000000158 resetTimer 30 | 0x0000000000000164 sleep 31 | .text 0x0000000000000184 0x0 ../lib/crt.s.o 32 | 33 | .text.startup 0x0000000000000184 0xf8 34 | .text.startup 0x0000000000000184 0xf8 ./main.o 35 | 0x0000000000000184 main 36 | 37 | .data 0x0000000080000000 0x0 38 | *(.rodata*) 39 | *(.*data*) 40 | .data 0x0000000080000000 0x0 ./main.o 41 | .data 0x0000000080000000 0x0 ../lib/crt.s.o 42 | *(.sbss) 43 | *(.bss) 44 | .bss 0x0000000080000000 0x0 ./main.o 45 | .bss 0x0000000080000000 0x0 ../lib/crt.s.o 46 | *(.rela*) 47 | *(COMMON) 48 | 0x0000000080000000 _heap = . 49 | 0x0000000080010000 PROVIDE (_sstack = (ORIGIN (RAM) + LENGTH (RAM))) 50 | LOAD ./main.o 51 | LOAD ../lib/crt.s.o 52 | OUTPUT(main.elf elf32-littleriscv) 53 | 54 | .comment 0x0000000000000000 0x2c 55 | .comment 0x0000000000000000 0x2c ./main.o 56 | 0x2d (size before relaxing) 57 | 58 | .note.GNU-stack 59 | 0x0000000000000000 0x0 60 | .note.GNU-stack 61 | 0x0000000000000000 0x0 ./main.o 62 | -------------------------------------------------------------------------------- /gcc/helloUART/Makefile: -------------------------------------------------------------------------------- 1 | SOURCES := $(shell find . ../lib -name '*.c') 2 | ASM_SOURCES := $(shell find . ../lib -name '*.s') 3 | OBJECTS := $(SOURCES:%.c=%.o) 4 | ASM_OBJECTS := $(ASM_SOURCES:%.s=%.s.o) 5 | ASM := $(SOURCES:%.c=%.s) 6 | 7 | DOCKERORPODMAN = $(shell command -v podman 2> /dev/null || echo docker) 8 | USEDOCKER = 1 9 | CURDIR = $(shell pwd) 10 | DOCKERARGS = run --rm -v $(PWD)/..:/src -w /src/$(shell basename $(CURDIR)) 11 | DOCKERIMG = $(DOCKERORPODMAN) $(DOCKERARGS) docker.io/carlosedp/crossbuild-riscv64:latest 12 | 13 | CFLAGS=-Wall -mabi=ilp32 -march=rv32i -ffreestanding -fcommon -Os -I../lib 14 | LDFLAGS=-T ../lib/riscv.ld -m elf32lriscv -O binary -Map=main.map 15 | 16 | PREFIX=riscv64-linux-gnu 17 | 18 | ifeq ($(USEDOCKER), 1) 19 | OC=$(DOCKERIMG) $(PREFIX)-objcopy 20 | OD=$(DOCKERIMG) $(PREFIX)-objdump 21 | CC=$(DOCKERIMG) $(PREFIX)-gcc 22 | LD=$(DOCKERIMG) $(PREFIX)-ld 23 | HD=$(DOCKERIMG) hexdump 24 | else 25 | OC=$(PREFIX)-objcopy 26 | OD=$(PREFIX)-objdump 27 | CC=$(PREFIX)-gcc 28 | LD=$(PREFIX)-ld 29 | HD=hexdump 30 | endif 31 | 32 | all: main.elf main-rom.mem main-ram.mem main.hex main.dump 33 | asm: $(ASM) 34 | 35 | %.o: %.c 36 | @echo "Building $< -> $@" 37 | @$(CC) -c $(CFLAGS) -o $@ $< 38 | 39 | %.s.o: %.s 40 | @echo "Building $< -> $@" 41 | @$(CC) -c $(CFLAGS) -o $@ $< 42 | 43 | main.elf: $(OBJECTS) $(ASM_OBJECTS) 44 | @echo "Linking $< $(OBJECTS) $(ASM_OBJECTS)" 45 | @$(LD) $(LDFLAGS) $(OBJECTS) $(ASM_OBJECTS) -o main.elf 46 | 47 | main.dump: main.elf 48 | @echo "Dumping to $@" 49 | @$(OD) -d -t -r $< > $@ 50 | 51 | main.hex: main.elf 52 | @echo "Building $< -> $@ for http://tice.sea.eseo.fr/riscv/" 53 | @$(OC) -O ihex $< $@ --only-section .text\* 54 | 55 | main-%.mem: main.elf ## Readmemh 32bit memory files (rom or ram) 56 | @echo "Building $< -> $@" 57 | $(OC) -O binary $< $(@:main-%.mem=main-%.bin) --only-section $(if $(filter %rom.mem,$@),.text*,.*data*) 58 | $(HD) -ve '1/4 "%08x\n"' $(@:main-%.mem=main-%.bin) > $@ 59 | 60 | %.s: %.c 61 | @echo "Building $< -> $@" 62 | @$(CC) -S $(CFLAGS) -o $@ $< 63 | 64 | clean: 65 | @echo "Cleaning build files" 66 | rm -f $(ASM) $(OBJECTS) $(ASM_OBJECTS) *.elf *.hex *.bin *.mem *.s.o *.map *.dump 67 | -------------------------------------------------------------------------------- /gcc/helloUART/banner.h: -------------------------------------------------------------------------------- 1 | char *logorv = 2 | " vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" 3 | " vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" 4 | "rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv\n" 5 | "rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" 6 | "rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" 7 | "rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" 8 | "rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" 9 | "rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" 10 | "rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" 11 | "rr vvvvvvvvvvvvvvvvvvvvvv \n" 12 | "rr vvvvvvvvvvvvvvvvvvvvvvvv rr\n" 13 | "rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr\n" 14 | "rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr\n" 15 | "rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr\n" 16 | "rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr\n" 17 | "rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr\n" 18 | "rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr\n" 19 | "rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr\n" 20 | "rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr\n" 21 | "rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr\n" 22 | "rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr\n" 23 | "\n" 24 | " INSTRUCTION SETS WANT TO BE FREE\n\n" 25 | "Welcome to ChiselV! \n\n"; 26 | 27 | char *logocv = 28 | "(..,,**) \n" 29 | " ( #,,***) MM''''''YMM dP oo dP M''MMMMM''M\n" 30 | " (,,.,,***) M' .mmm. 'M 88 88 M MMMMM M\n" 31 | " (,,,,,,**.) M MMMMMooM 88d888b. dP .d8888b. .d8888b. 88 M MMMMP M\n" 32 | " (,,,,,,**,) M MMMMMMMM 88' '88 88 Y8ooooo. 88ooood8 88 M MMMM' .M\n" 33 | " ( .,,..*.,) M. 'MMM' .M 88 88 88 88 88. ... 88 M MMP' .MM\n" 34 | " ( .,,,.., ) MM. .dM dP dP dP '88888P' '88888P' dP M .dMMM\n" 35 | " (,,.,,.,..) MMMMMMMMMMM MMMMMMMMMMM\n" 36 | " (,*,. ,) \n" 37 | " (,*#/#.,) INSTRUCTION SETS WANT TO BE FREE \n" 38 | " ,###. \n" 39 | " *#*(, \n" 40 | " /((((((((##. \n" 41 | " ...*(((((/(/(/##( \n" 42 | " .... ((((((((((### \n" 43 | " *....,(((((((((((### \n" 44 | " .,....(((((((((((### \n" 45 | " *....(/((((((((####/ \n" 46 | " *.,,.,(((((((((((((( \n" 47 | " /.,,,,((#((/(/*** \n" 48 | " /...((((*** \n" 49 | " ,(*/* \n" 50 | " \n" 51 | "Welcome to ChiselV! \n"; -------------------------------------------------------------------------------- /gcc/helloUART/main.c: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | #include "uart.h" 3 | #include "stdio.h" 4 | #include "banner.h" 5 | 6 | #define CLEAR "\033[2K" 7 | 8 | volatile int heapcheck = 0xdeadbeef; 9 | 10 | void header(void) { 11 | printf("ChiselV, a RISC-V RV32I Core\n"); 12 | uint32_t proc_freq = *(volatile unsigned long *)(SYSCON_BASE + SYS_REG_CLKINFO) / 1000 / 1000; 13 | uint32_t num_gpio = *(volatile unsigned long *)(SYSCON_BASE + SYS_REG_NUMGPIO0); 14 | uint32_t bootaddr = *(volatile unsigned long *)(SYSCON_BASE + SYS_REG_BOOTADDR); 15 | uint32_t romsize = *(volatile unsigned long *)(SYSCON_BASE + SYS_REG_ROMSIZE); 16 | uint32_t ramsize = *(volatile unsigned long *)(SYSCON_BASE + SYS_REG_RAMSIZE); 17 | printf("clock: %dMHz\n", proc_freq); 18 | printf("bootaddr: %d\n", bootaddr); 19 | printf("ROM: %d bytes\n", romsize); 20 | printf("RAM: %d bytes\n", ramsize); 21 | printf("uart0: %d\n", UART0_BAUD); 22 | printf("gpio0: %d IO\n", num_gpio); 23 | printf("-----\n"); 24 | } 25 | 26 | int main(void) 27 | { 28 | uart_init(); 29 | // Turn on LED to say we're alive 30 | pinMode(0, OUTPUT); 31 | digitalWrite(0, HIGH); 32 | 33 | // Print the header with core info 34 | header(); 35 | // Print the banner 36 | printf(logocv); 37 | printf("This demo prints back to the console all typed characters when hit .\n"); 38 | printf("> "); 39 | char data[128]; 40 | while (1) 41 | { 42 | unsigned char c = getchar(); 43 | int bufLen = strlen(data); 44 | data[bufLen] = c; 45 | if (c == '\r') 46 | { 47 | printf("\r\n"); 48 | printf("You typed: %s", data); 49 | // Clear the buffer 50 | memset(data, 0, sizeof(data)); 51 | printf("\r\n> "); 52 | } 53 | else 54 | { 55 | putchar(c); 56 | } 57 | 58 | if (heapcheck != 0xdeadbeef) 59 | { 60 | printf("out of memory detected, a reboot is recommended...\n"); 61 | } 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /gcc/helloUART/main.hex: -------------------------------------------------------------------------------- 1 | :1000000033000000B300000033010000B301000022 2 | :1000100033020000B302000033030000B30300000A 3 | :1000200033040000B304000033050000B3050000F2 4 | :1000300033060000B306000033070000B3070000DA 5 | :1000400033080000B308000033090000B3090000C2 6 | :10005000330A0000B30A0000330B0000B30B0000AA 7 | :10006000330C0000B30C0000330D0000B30D000092 8 | :10007000330E0000B30E0000330F0000B30F00007A 9 | :100080003701018013010100EF0010186F004000DC 10 | :100090006F000000B717003023A0A70067800000A2 11 | :1000A000B717003003A5070067800000B7170030BE 12 | :1000B00023A2A70067800000B717003003A5470000 13 | :1000C00067800000B737003023A0A70067800000DA 14 | :1000D000B717003003A70700930710003395A70058 15 | :1000E000638A05003367E500B717003023A0E700F7 16 | :1000F000678000001345F5FF3377E5006FF0DFFE02 17 | :10010000B717003003A74700930710003395A700E7 18 | :100110003375E5003335A00067800000B716003066 19 | :1001200003A7460093071000938646003395A70067 20 | :10013000638805003367E50023A0E60067800000C0 21 | :100140001345F5FF3377E5006FF01FFFB737003039 22 | :1001500003A5070067800000B737003023A0070021 23 | :1001600067800000B737003023A0070003A707000F 24 | :100170003305E50003A70700E37EE5FE23A00700A3 25 | :1001800067800000B70700303305F5000325050040 26 | :1001900067800000B70700303305F5002320B50065 27 | :1001A00067800000B707003003A5C700137515006E 28 | :1001B00067800000B707003003A5C700135535005E 29 | :1001C0001375150067800000B707003003A54700CE 30 | :1001D0001375F50F67800000B707003023A0A70054 31 | :1001E00067800000130101FF93954500232611004D 32 | :1001F000EF0040698320C1001305F5FF13010101E1 33 | :1002000067800000B717000003A58700130101FFF6 34 | :10021000B7251C0023261100EF00C0668320C10013 35 | :100220001305F5FFB707003023A8A700130101014C 36 | :1002300067800000130101FF23261100EFF09FF6F5 37 | :10024000E31E05FEB707003003A547008320C10069 38 | :100250001375F50F1301010167800000130101FF01 39 | :1002600023248100232611009307A0001304050016 40 | :10027000631CF500EFF01FF4E31E05FEB707003026 41 | :100280001307D00023A0E700EFF0DFF2E31E05FE26 42 | :10029000B70700308320C10023A08700032481001A 43 | :1002A0001301010167800000130101FD2324810275 44 | :1002B00023229102232E310123286101232671017B 45 | :1002C000232481012326110223202103232C410111 46 | :1002D000232A5101130405009389050093040500A6 47 | :1002E000130BA000930BD000130C8000138AF9FFAE 48 | :1002F00063080A00EFF01FF4130905006316650593 49 | :100300001305A000EFF09FF52380040013050400FF 50 | :1003100063948400130500008320C102032481023A 51 | :1003200083244102032901028329C101032A810197 52 | :10033000832A4101032B0101832BC100032C81007F 53 | :100340001301010367800000E30C75FB937AF50F3E 54 | :1003500013850A00EFF09FF0631E89016388840013 55 | :10036000A38F04FE138A09009384F4FF93090A0003 56 | :100370006FF0DFF723805401938414006FF01FFFA8 57 | :10038000130101FF2324810023261100130405001B 58 | :1003900063160500170400801304C4C60345040057 59 | :1003A000631A05008320C1000324810013010101A9 60 | :1003B0006780000013041400EFF05FEA6FF01FFE87 61 | :1003C000130101FF23261100EFF09FFB8320C100E2 62 | :1003D0001305A000130101016FF05FE8130101FA9A 63 | :1003E0002328210513094101232A910423263105DD 64 | :1003F0001306C00293890500930405009715008039 65 | :100400009385059113050900232C8104232E1104E3 66 | :10041000232441052322510513040100EF00C021CC 67 | :10042000130640019715008093854591130504003C 68 | :10043000EF00802063840900130409001309800180 69 | :10044000930A1000170A0080130A4ABC832504008F 70 | :10045000639405028320C10503248105832441059B 71 | :10046000032901058329C104032A8104832A410445 72 | :1004700013010106678000006384550163E2B40242 73 | :100480006386090213850400EF00C03F9305A000B6 74 | :10049000EF00C03F3305AA0003450500EFF01FDC65 75 | :1004A000130989FF130444006FF05FFA93074900B2 76 | :1004B000B3D7F40093F7F700B307FA0003C50700BA 77 | :1004C000EFF0DFD9B3D7240193F7F700B307FA00B1 78 | :1004D00003C507006FF09FFC930500006FF01FF04D 79 | :1004E000930510006FF09FEF130101FB2322F1042D 80 | :1004F0009307410323248102232291022320210315 81 | :10050000232E3101232C410123261102130405005F 82 | :10051000232AB102232CC102232ED1022320E1047D 83 | :1005200023240105232611052326F10093045002FC 84 | :100530001309300793098007130A40060345040096 85 | :10054000631205028320C102032481028324410235 86 | :10055000032901028329C101032A81011301010535 87 | :100560006780000063169506034514006312250397 88 | :100570008327C10003A50700138747002326E10056 89 | :10058000EFF01FE013041400130414006FF01FFBBE 90 | :10059000631E35018327C10003A5070013874700A9 91 | :1005A0002326E100EFF05FF36FF0DFFD631E4501EE 92 | :1005B0008327C10003A50700138747002326E10016 93 | :1005C000EFF01FF26FF01FFCEFF05FC96FF09FFBC1 94 | :1005D000EFF0DFC86FF05FFB1306F6FF9307000034 95 | :1005E0003307F500834607003387F500034707000C 96 | :1005F000638AC700638806006306070093871700B5 97 | :10060000E380E6FE3385E640678000001306F0FFD6 98 | :100610006FF09FFC930705006388070003C707007E 99 | :1006200093861700631607003385A7406780000094 100 | :10063000938706006FF05FFE930700006394C70086 101 | :10064000678000003387F500834607003307F50015 102 | :10065000938717002300D7006FF05FFE3306C500B5 103 | :10066000930705006394C700678000009387170015 104 | :10067000A38FB7FE6FF01FFF130101FE232C810033 105 | :1006800013040500138505002328210123263101C9 106 | :10069000232E1100232A910013890500EFF09FF704 107 | :1006A0009309050063180400170400800324046BF9 108 | :1006B000630A04029304040083C7040063800702F2 109 | :1006C000138609009305090013850400EFF0DFF09D 110 | :1006D0009387140063180502238004001707008025 111 | :1006E000232EF7668320C101130504000324810132 112 | :1006F00083244101032901018329C100130101025F 113 | :1007000067800000938407006FF01FFB93060500CD 114 | :1007100013060000130500009305D002639A06003B 115 | :10072000631C060267800000130610006F00400281 116 | :1007300083C70600E38607FEE388B7FE938707FDBD 117 | :10074000131735003387E700931715003305F700BB 118 | :10075000938616006FF09FFC3305A0406780000071 119 | :10076000930605001306900313050000639E060020 120 | :100770006780000013174500636EF600938707FD3E 121 | :100780003385E7009386160083C70600E39407FECF 122 | :100790006780000093F7F705938797FC6FF05FFE83 123 | :1007A000930705006368B5001387050093070700EA 124 | :1007B000930505001305000063940700678000009F 125 | :1007C00013F71700630407003305B5009395150070 126 | :1007D00093D717006FF05FFE130101FF23229100F2 127 | :1007E0002326110023248100930400006356050092 128 | :1007F0003305A040930410001304000063D60500E5 129 | :10080000B305B04013041000EFF09FF96384840037 130 | :100810003305A0408320C1000324810083244100CC 131 | :100820001301010167800000130805009307100001 132 | :1008300013850500639A0500678000006348050082 133 | :100840009397170013151500E36A05FF930605003B 134 | :1008500013070000130508006304050063980700F0 135 | :10086000E30C06FC13050700678000006366D500F3 136 | :100870003305D5403307F70093D7170093D61600FA 137 | :100880006FF09FFD130610006FF01FFA13060000B3 138 | :100890006FF09FF9638E0506130101FF2324810089 139 | :1008A0002322910023261100232021011304060096 140 | :1008B00093040000635605003305A0409304100024 141 | :1008C0001309000063D60500B305B04013091000FA 142 | :1008D00013060400EFF05FF59305050063040402BE 143 | :1008E00063842401B305A0408320C1000324810058 144 | :1008F0008324410003290100138505001301010130 145 | :1009000067800000E38204FEB305A0406FF0DFFDC6 146 | :100910001385050067800000130610006FF09FF735 147 | :10092000130600006FF01FF7130101FE17F5FF7F9C 148 | :100930001305056F232E1100232C8100232A91001B 149 | :100940002328210123263101EFF01FBAB717000039 150 | :1009500003A58700B717000003A48702B71700009C 151 | :1009600083A9C702B7450F00B717000003A9070303 152 | :1009700093850524B717000083A44703EFF09FF089 153 | :100980009305050017F5FF7F1305856BEFF0DFB5C5 154 | :100990009385090017F5FF7F1305856BEFF0DFB432 155 | :1009A0009305090017F5FF7F1305856BEFF0DFB3A3 156 | :1009B0009385040017F5FF7F1305856BEFF0DFB219 157 | :1009C000B7C501009385052017F5FF7F1305456B1B 158 | :1009D000EFF09FB19305040017F5FF7F1305056B3A 159 | :1009E000EFF09FB0032481018320C10183244101E2 160 | :1009F000032901018329C10017F5FF7F1305056A4B 161 | :080A0000130101026FF05FAE6B 162 | :100A0800130101F52326110A2322910A2320210B21 163 | :100A1800232E3109232C4109232A5109232861094E 164 | :100A280023267109232481092324810AEFF00FFD6D 165 | :100A3800371700308327070037C9ADDE930401005C 166 | :100A480093E717002320F700B717003003A74700E4 167 | :100A5800130AD000970A0080938A0A2F1367170099 168 | :100A680023A2E700EFF0DFEB170500800325052E32 169 | :100A7800EFF01FA717F5FF7F13054562EFF05FA69C 170 | :100A880017F5FF7F13058566EFF09FA51309F9EEAB 171 | :100A980017FBFF7F130BCB6597FBFF7F938B8B6552 172 | :100AA80017FCFF7F130C0C6697F9FF7F9389096683 173 | :100AB800EFF0CFF71374F50F13850400EFF01FB5AF 174 | :100AC8009307050833852700230085F8631244053A 175 | :100AD80013050B00EFF0DFA09385040013850B00CE 176 | :100AE800EFF01FA01306000893050000138504000B 177 | :100AF800EFF05FB613050C00EFF09F9E83A70A0086 178 | :100B0800E38827FB13850900EFF09F9D6FF05FFADC 179 | :0C0B180013050400EFF00FF46FF05FFE17 180 | :00000001FF 181 | -------------------------------------------------------------------------------- /gcc/helloUART/main.map: -------------------------------------------------------------------------------- 1 | 2 | There are no discarded input sections 3 | 4 | Memory Configuration 5 | 6 | Name Origin Length Attributes 7 | ROM 0x00000000 0x00010000 xrw 8 | RAM 0x80000000 0x00010000 xrw 9 | *default* 0x00000000 0xffffffff 10 | 11 | Linker script and memory map 12 | 13 | 0x00002000 __heap_size = 0x2000 14 | 0x00008000 __stack_size = 0x8000 15 | 16 | .text 0x00000000 0xa08 17 | *(.boot) 18 | .boot 0x00000000 0x94 ../lib/crt.s.o 19 | 0x00000000 _boot 20 | *(.text) 21 | .text 0x00000094 0x974 ./main.o 22 | 0x00000094 setDirection 23 | 0x000000a0 readDirection 24 | 0x000000ac setGPIO 25 | 0x000000b8 readGPIO 26 | 0x000000c4 setTimer 27 | 0x000000d0 pinMode 28 | 0x00000100 digitalRead 29 | 0x0000011c digitalWrite 30 | 0x0000014c getTimer 31 | 0x00000158 resetTimer 32 | 0x00000164 sleep 33 | 0x00000184 uart_reg_read 34 | 0x00000194 uart_reg_write 35 | 0x000001a4 uart_rx_empty 36 | 0x000001b4 uart_tx_full 37 | 0x000001c8 uart_read 38 | 0x000001d8 uart_write 39 | 0x000001e4 uart_divisor 40 | 0x00000204 uart_init 41 | 0x00000234 getchar 42 | 0x0000025c putchar 43 | 0x000002a8 gets 44 | 0x00000380 putstr 45 | 0x000003c0 puts 46 | 0x000003dc putdx 47 | 0x000004d8 putx 48 | 0x000004e0 putd 49 | 0x000004e8 printf 50 | 0x000005d8 strncmp 51 | 0x0000060c strcmp 52 | 0x00000614 strlen 53 | 0x00000638 memcpy 54 | 0x0000065c memset 55 | 0x00000678 strtok 56 | 0x0000070c atoi 57 | 0x00000760 xtoi 58 | 0x000007a0 __umulsi3 59 | 0x000007d8 __mulsi3 60 | 0x00000828 __udiv_umod_si3 61 | 0x00000884 __udivsi3 62 | 0x0000088c __umodsi3 63 | 0x00000894 __div_mod_si3 64 | 0x00000918 __divsi3 65 | 0x00000920 __modsi3 66 | 0x00000928 header 67 | .text 0x00000a08 0x0 ../lib/crt.s.o 68 | 69 | .text.startup 0x00000a08 0x11c 70 | .text.startup 0x00000a08 0x11c ./main.o 71 | 0x00000a08 main 72 | 73 | .eh_frame 0x00000b24 0x4e4 74 | .eh_frame 0x00000b24 0x4e4 ./main.o 75 | 76 | .data 0x80000000 0xd5c 77 | *(.rodata*) 78 | .rodata.str1.4 79 | 0x80000000 0xd0b ./main.o 80 | *fill* 0x80000d0b 0x1 81 | .rodata 0x80000d0c 0x40 ./main.o 82 | *(.*data*) 83 | .data 0x80000d4c 0x4 ./main.o 84 | 0x80000d4c heapcheck 85 | .data.rel.local 86 | 0x80000d50 0x8 ./main.o 87 | 0x80000d50 logocv 88 | 0x80000d54 logorv 89 | .data 0x80000d58 0x0 ../lib/crt.s.o 90 | *(.sbss) 91 | *(.bss) 92 | .bss 0x80000d58 0x4 ./main.o 93 | .bss 0x80000d5c 0x0 ../lib/crt.s.o 94 | *(.rela*) 95 | *(COMMON) 96 | 0x80000d5c _heap = . 97 | 0x80010000 PROVIDE (_sstack = (ORIGIN (RAM) + LENGTH (RAM))) 98 | LOAD ./main.o 99 | LOAD ../lib/crt.s.o 100 | OUTPUT(main.elf elf32-littleriscv) 101 | 102 | .comment 0x00000000 0x26 103 | .comment 0x00000000 0x26 ./main.o 104 | 0x27 (size before relaxing) 105 | 106 | .note.GNU-stack 107 | 0x00000000 0x0 108 | .note.GNU-stack 109 | 0x00000000 0x0 ./main.o 110 | 111 | .riscv.attributes 112 | 0x00000000 0x1c 113 | .riscv.attributes 114 | 0x00000000 0x1c ./main.o 115 | .riscv.attributes 116 | 0x0000001c 0x1a ../lib/crt.s.o 117 | -------------------------------------------------------------------------------- /gcc/lib/crt.s: -------------------------------------------------------------------------------- 1 | .global _boot 2 | .section .boot 3 | 4 | _boot: 5 | add x0, x0, x0 6 | add x1, x0, x0 7 | add x2, x0, x0 8 | add x3, x0, x0 9 | add x4, x0, x0 10 | add x5, x0, x0 11 | add x6, x0, x0 12 | add x7, x0, x0 13 | add x8, x0, x0 14 | add x9, x0, x0 15 | add x10, x0, x0 16 | add x11, x0, x0 17 | add x12, x0, x0 18 | add x13, x0, x0 19 | add x14, x0, x0 20 | add x15, x0, x0 21 | add x16, x0, x0 22 | add x17, x0, x0 23 | add x18, x0, x0 24 | add x19, x0, x0 25 | add x20, x0, x0 26 | add x21, x0, x0 27 | add x22, x0, x0 28 | add x23, x0, x0 29 | add x24, x0, x0 30 | add x25, x0, x0 31 | add x26, x0, x0 32 | add x27, x0, x0 33 | add x28, x0, x0 34 | add x29, x0, x0 35 | add x30, x0, x0 36 | add x31, x0, x0 37 | 38 | lui x2, %hi(_sstack) 39 | addi x2, x2, %lo(_sstack) 40 | call main 41 | j _halt # halt 42 | # j _boot # restart 43 | 44 | _halt: 45 | j _halt 46 | -------------------------------------------------------------------------------- /gcc/lib/io.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef unsigned int uint32_t; 4 | typedef int int32_t; 5 | typedef unsigned char uint8_t; 6 | typedef char int8_t; 7 | 8 | #define SYSCON_BASE 0x00001000 /* System control regs */ 9 | #define SYS_REG_DUMMY 0x00 /* Dummy output */ 10 | #define SYS_REG_CLKINFO 0x08 /* Clock information */ 11 | #define SYS_REG_HASUART0 0x10 /* Has UART0 */ 12 | #define SYS_REG_HASGPIO0 0x18 /* Has GPIO0 */ 13 | #define SYS_REG_HASPWM0 0x20 /* Has PWM0 */ 14 | #define SYS_REG_HASTIMER0 0x24 /* Has TIMER0 */ 15 | #define SYS_REG_NUMGPIO0 0x28 /* Num IO GPIO0 */ 16 | #define SYS_REG_BOOTADDR 0x2C /* Boot address */ 17 | #define SYS_REG_ROMSIZE 0x30 /* ROM Size */ 18 | #define SYS_REG_RAMSIZE 0x34 /* RAM Size */ 19 | 20 | #define GPIO0_BASE 0x30001000 21 | #define GPIO0_DIR 0x00 22 | #define GPIO0_VAL 0x04 23 | #define TIMER0_BASE 0x30003000 24 | 25 | #define HIGH 1 26 | #define LOW 0 27 | 28 | #define INPUT 0 29 | #define OUTPUT 1 30 | 31 | //-- Internal functions --// 32 | 33 | // Set the GPIO direction (for all ports) 34 | void setDirection(unsigned int val) 35 | { 36 | uint32_t addr; 37 | addr = GPIO0_BASE + GPIO0_DIR; 38 | *(volatile uint32_t *)addr = val; 39 | } 40 | 41 | // Reads the GPIO direction (for all ports) 42 | uint32_t readDirection() 43 | { 44 | uint32_t addr; 45 | uint32_t val; 46 | addr = GPIO0_BASE + GPIO0_DIR; 47 | val = *(volatile uint32_t *)addr; 48 | return val; 49 | } 50 | 51 | // Set the GPIO value (for all ports) 52 | void setGPIO(uint32_t val) 53 | { 54 | uint32_t addr; 55 | addr = GPIO0_BASE + GPIO0_VAL; 56 | *(volatile uint32_t *)addr = val; 57 | } 58 | 59 | // Reads the GPIO value (for all ports) 60 | uint32_t readGPIO() 61 | { 62 | uint32_t addr; 63 | uint32_t val; 64 | addr = GPIO0_BASE + GPIO0_VAL; 65 | val = *(volatile uint32_t *)addr; 66 | return val; 67 | } 68 | 69 | // Sets the timer value 70 | void setTimer(unsigned int val) 71 | { 72 | uint32_t addr; 73 | addr = TIMER0_BASE; 74 | *(volatile uint32_t *)addr = val; 75 | } 76 | 77 | //-- User facing functions --// 78 | // Sets the pin mode (INPUT or OUTPUT) 79 | void pinMode(unsigned char port, unsigned char val) 80 | { 81 | uint32_t dir = readDirection(); 82 | uint32_t b = 1 << port; 83 | 84 | if (val) 85 | { 86 | dir |= b; 87 | } 88 | else 89 | { 90 | dir &= ~b; 91 | } 92 | 93 | setDirection(dir); 94 | } 95 | 96 | // Reads the value of a pin set as INPUT (LOW or HIGH) 97 | uint32_t digitalRead(uint32_t port) 98 | { 99 | uint32_t val; 100 | val = readGPIO(); 101 | if (val & (1 << port)) 102 | { 103 | return 1; 104 | } 105 | else 106 | { 107 | return 0; 108 | } 109 | } 110 | 111 | // Writes a HIGH or a LOW value to a pin set as OUTPUT 112 | void digitalWrite(uint8_t port, uint8_t val) 113 | { 114 | uint32_t vals = readGPIO(); 115 | uint32_t b = 1 << port; 116 | 117 | if (val) 118 | { 119 | vals |= b; 120 | } 121 | else 122 | { 123 | vals &= ~b; 124 | } 125 | 126 | setGPIO(vals); 127 | } 128 | 129 | // Reads the value of the timer (in microseconds) 130 | unsigned int getTimer() 131 | { 132 | uint32_t addr; 133 | uint32_t val; 134 | addr = TIMER0_BASE; 135 | val = *(volatile uint32_t *)addr; 136 | return val; 137 | } 138 | 139 | // Set the timer to 0 140 | void resetTimer() 141 | { 142 | setTimer(0); 143 | } 144 | 145 | // Sleeps for the specified number of milliseconds (blocking) 146 | void sleep(unsigned int ms) 147 | { 148 | resetTimer(); 149 | unsigned int startTime = getTimer(); 150 | unsigned int countedMs = 0; 151 | while (getTimer() <= startTime + ms) 152 | { 153 | countedMs++; 154 | } 155 | resetTimer(); 156 | } 157 | -------------------------------------------------------------------------------- /gcc/lib/riscv.ld: -------------------------------------------------------------------------------- 1 | /* Thanks https://github.com/darklife/darkriscv */ 2 | /* and https://github.com/racerxdl/riskow */ 3 | 4 | __heap_size = 0x2000; /* amount of heap */ 5 | __stack_size = 0x8000; /* amount of stack */ 6 | 7 | MEMORY 8 | { 9 | ROM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 10 | RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x10000 11 | } 12 | SECTIONS 13 | { 14 | .text : 15 | { 16 | *(.boot) 17 | *(.text) 18 | } > ROM 19 | .data : 20 | { 21 | *(.rodata*) 22 | *(.*data*) 23 | *(.sbss) 24 | *(.bss) 25 | *(.rela*) 26 | *(COMMON) 27 | _heap = .; 28 | } > RAM 29 | 30 | PROVIDE ( _sstack = ORIGIN(RAM) + LENGTH(RAM) ); 31 | } -------------------------------------------------------------------------------- /gcc/lib/stdio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Marcelo Samsoniuk 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * * Neither the name of the copyright holder nor the names of its 16 | * contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include "io.h" 33 | #include "uart.h" 34 | 35 | #ifndef __STDIO__ 36 | #define __STDIO__ 37 | 38 | #define EOF -1 39 | #define NUL 0 40 | #define NULL (void *)0 41 | 42 | // high-level functions use the getchar/putchar 43 | 44 | char *gets(char *p, int s) 45 | { 46 | char *ret = p; 47 | int c; 48 | 49 | while (--s) 50 | { 51 | c = getchar(); 52 | 53 | if (c == '\n' || c == '\r') 54 | break; 55 | putchar(c); 56 | if (c == '\b') // backspace! 57 | { 58 | if (p != ret) 59 | { 60 | *--p = 0; 61 | s++; 62 | } 63 | } 64 | else 65 | *p++ = c; 66 | } 67 | putchar('\n'); 68 | *p = 0; 69 | 70 | return p == ret ? NULL : ret; 71 | } 72 | 73 | void putstr(char *p) 74 | { 75 | if (p) 76 | while (*p) 77 | putchar(*p++); 78 | else 79 | putstr("(NULL)"); 80 | } 81 | 82 | int puts(char *p) 83 | { 84 | putstr(p); 85 | return putchar('\n'); 86 | } 87 | 88 | void putdx(unsigned i, int mode) // mode1 = dec, mode0 = hex 89 | { 90 | char *hex = "0123456789abcdef"; 91 | 92 | int dbd[] = {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1, 0}; 93 | int dbx[] = {16777216, 65536, 256, 1, 0}; 94 | 95 | int *db = mode ? dbd : dbx; 96 | 97 | if (mode && i < 0) 98 | { 99 | putchar('-'); 100 | i = -1; 101 | } 102 | 103 | int j, k, l; 104 | 105 | for (j = 0, k = 24; (l = db[j]); j++, k -= 8) 106 | { 107 | if (l == 1 || i >= l) 108 | { 109 | if (mode) 110 | { 111 | putchar(hex[(i / l) % 10]); 112 | } 113 | else 114 | { 115 | putchar(hex[(i >> (k + 4)) & 15]); 116 | putchar(hex[(i >> k) & 15]); 117 | } 118 | } 119 | } 120 | } 121 | 122 | void putx(unsigned i) 123 | { 124 | putdx(i, 0); 125 | } 126 | 127 | void putd(int i) 128 | { 129 | putdx(i, 1); 130 | } 131 | 132 | int printf(char *fmt, ...) 133 | { 134 | va_list ap; 135 | 136 | for (va_start(ap, fmt); *fmt; fmt++) 137 | { 138 | if (*fmt == '%') 139 | { 140 | fmt++; 141 | if (*fmt == 's') 142 | putstr(va_arg(ap, char *)); 143 | else if (*fmt == 'x') 144 | putx(va_arg(ap, int)); 145 | else if (*fmt == 'd') 146 | putd(va_arg(ap, int)); 147 | else 148 | putchar(*fmt); 149 | } 150 | else 151 | putchar(*fmt); 152 | } 153 | 154 | va_end(ap); 155 | 156 | return 0; 157 | } 158 | 159 | int strncmp(char *s1, char *s2, int len) 160 | { 161 | while (--len && *s1 && *s2 && (*s1 == *s2)) 162 | s1++, s2++; 163 | 164 | return (*s1 - *s2); 165 | } 166 | 167 | int strcmp(char *s1, char *s2) 168 | { 169 | return strncmp(s1, s2, -1); 170 | } 171 | 172 | int strlen(char *s1) 173 | { 174 | int len; 175 | 176 | for (len = 0; s1 && *s1++; len++) 177 | ; 178 | 179 | return len; 180 | } 181 | 182 | char *memcpy(char *dptr, char *sptr, int len) 183 | { 184 | char *ret = dptr; 185 | 186 | while (len--) 187 | *dptr++ = *sptr++; 188 | 189 | return ret; 190 | } 191 | 192 | char *memset(char *dptr, int c, int len) 193 | { 194 | char *ret = dptr; 195 | 196 | while (len--) 197 | *dptr++ = c; 198 | 199 | return ret; 200 | } 201 | 202 | char *strtok(char *str, char *dptr) 203 | { 204 | static char *nxt = NULL; 205 | 206 | int dlen = strlen(dptr); 207 | char *tmp; 208 | 209 | if (str) 210 | tmp = str; 211 | else if (nxt) 212 | tmp = nxt; 213 | else 214 | return NULL; 215 | 216 | char *ret = tmp; 217 | 218 | while (*tmp) 219 | { 220 | if (strncmp(tmp, dptr, dlen) == 0) 221 | { 222 | *tmp = NUL; 223 | nxt = tmp + 1; 224 | return ret; 225 | } 226 | tmp++; 227 | } 228 | nxt = NULL; 229 | return ret; 230 | } 231 | 232 | int atoi(char *s1) 233 | { 234 | int ret, sig; 235 | 236 | for (sig = ret = 0; s1 && *s1; s1++) 237 | { 238 | if (*s1 == '-') 239 | sig = 1; 240 | else 241 | ret = *s1 - '0' + (ret << 3) + (ret << 1); // val = val*10+int(*s1) 242 | } 243 | 244 | return sig ? -ret : ret; 245 | } 246 | 247 | int xtoi(char *s1) 248 | { 249 | int ret; 250 | 251 | for (ret = 0; s1 && *s1; s1++) 252 | { 253 | if (*s1 <= '9') 254 | ret = *s1 - '0' + (ret << 4); // val = val*16+int(*s1) 255 | else 256 | ret = 10 + (*s1 & 0x5f) - 'A' + (ret << 4); // val = val*16+int(toupper(*s1)) 257 | } 258 | 259 | return ret; 260 | } 261 | 262 | // int mac(int acc,short x,short y) 263 | // { 264 | // #ifdef __RISCV__ 265 | // __asm__(".word 0x00c5857F"); // mac a0,a1,a2 266 | // // "template" 267 | // //acc += (x^y); 268 | // #else 269 | // acc+=x*y; 270 | // #endif 271 | // return acc; 272 | // } 273 | 274 | unsigned __umulsi3(unsigned x, unsigned y) 275 | { 276 | unsigned acc; 277 | 278 | if (x < y) 279 | { 280 | unsigned z = x; 281 | x = y; 282 | y = z; 283 | } 284 | 285 | for (acc = 0; y; x <<= 1, y >>= 1) 286 | if (y & 1) 287 | acc += x; 288 | 289 | return acc; 290 | } 291 | 292 | int __mulsi3(int x, int y) 293 | { 294 | unsigned acc, xs, ys; 295 | 296 | if (x < 0) 297 | { 298 | xs = 1; 299 | x = -x; 300 | } 301 | else 302 | xs = 0; 303 | if (y < 0) 304 | { 305 | ys = 1; 306 | y = -y; 307 | } 308 | else 309 | ys = 0; 310 | 311 | acc = __umulsi3(x, y); 312 | 313 | return xs ^ ys ? -acc : acc; 314 | } 315 | 316 | unsigned __udiv_umod_si3(unsigned x, unsigned y, int opt) 317 | { 318 | unsigned acc, aux; 319 | 320 | if (!y) 321 | return 0; 322 | 323 | for (aux = 1; y < x && !(y & (1 << 31)); aux <<= 1, y <<= 1) 324 | ; 325 | for (acc = 0; x && aux; aux >>= 1, y >>= 1) 326 | if (y <= x) 327 | x -= y, acc += aux; 328 | 329 | return opt ? acc : x; 330 | } 331 | 332 | int __udivsi3(int x, int y) 333 | { 334 | return __udiv_umod_si3(x, y, 1); 335 | } 336 | 337 | int __umodsi3(int x, int y) 338 | { 339 | return __udiv_umod_si3(x, y, 0); 340 | } 341 | 342 | int __div_mod_si3(int x, int y, int opt) 343 | { 344 | unsigned acc, xs, ys; 345 | 346 | if (!y) 347 | return 0; 348 | 349 | if (x < 0) 350 | { 351 | xs = 1; 352 | x = -x; 353 | } 354 | else 355 | xs = 0; 356 | if (y < 0) 357 | { 358 | ys = 1; 359 | y = -y; 360 | } 361 | else 362 | ys = 0; 363 | 364 | acc = __udiv_umod_si3(x, y, opt); 365 | 366 | if (opt) 367 | return xs ^ ys ? -acc : acc; 368 | else 369 | return xs ? -acc : acc; 370 | } 371 | 372 | int __divsi3(int x, int y) 373 | { 374 | return __div_mod_si3(x, y, 1); 375 | } 376 | 377 | int __modsi3(int x, int y) 378 | { 379 | return __div_mod_si3(x, y, 0); 380 | } 381 | 382 | 383 | #endif 384 | -------------------------------------------------------------------------------- /gcc/lib/uart.h: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | 3 | #pragma once 4 | 5 | /* 6 | * Core UART header to implement for a port 7 | */ 8 | 9 | #define UART0_BASE 0x30000000 10 | #define UART0_BAUD 115200 11 | 12 | #define UART_TX 0x00 13 | #define UART_RX 0x04 14 | #define UART_STATUS 0x0C 15 | #define UART_STATUS_RX_EMPTY 0x01 16 | #define UART_STATUS_TX_EMPTY 0x02 17 | #define UART_STATUS_RX_FULL 0x04 18 | #define UART_STATUS_TX_FULL 0x08 19 | #define UART_CLOCKDIV 0x10 20 | 21 | /* 22 | * Core UART functions to implement for a port 23 | */ 24 | 25 | uint32_t uart_reg_read(int offset) 26 | { 27 | uint32_t addr; 28 | uint32_t val; 29 | addr = UART0_BASE + offset; 30 | val = *(volatile uint32_t *)addr; 31 | return val; 32 | } 33 | 34 | void uart_reg_write(int offset, uint32_t val) 35 | { 36 | uint32_t addr; 37 | addr = UART0_BASE + offset; 38 | *(volatile uint32_t *)addr = val; 39 | } 40 | 41 | int uart_rx_empty(void) 42 | { 43 | uint32_t val; 44 | val = uart_reg_read(UART_STATUS); 45 | if (val & UART_STATUS_RX_EMPTY) 46 | return 1; 47 | return 0; 48 | } 49 | 50 | int uart_tx_full(void) 51 | { 52 | uint32_t val; 53 | val = uart_reg_read(UART_STATUS); 54 | if (val & UART_STATUS_TX_FULL) 55 | return 1; 56 | return 0; 57 | } 58 | 59 | char uart_read(void) 60 | { 61 | uint32_t val; 62 | val = uart_reg_read(UART_RX); 63 | return (char)(val & 0x000000ff); 64 | } 65 | 66 | void uart_write(char c) 67 | { 68 | uint32_t val; 69 | val = c; 70 | uart_reg_write(UART_TX, val); 71 | } 72 | 73 | unsigned long uart_divisor(unsigned long proc_freq, unsigned long uart_freq) 74 | { 75 | return proc_freq / (uart_freq * 16) - 1; 76 | } 77 | 78 | void uart_init(void) 79 | { 80 | uint32_t proc_freq; 81 | proc_freq = *(volatile unsigned long *)(SYSCON_BASE + SYS_REG_CLKINFO); 82 | uart_reg_write(UART_CLOCKDIV, uart_divisor(proc_freq, UART0_BAUD)); 83 | } 84 | 85 | int getchar(void) 86 | { 87 | while (uart_rx_empty()) 88 | ; // Do nothing 89 | return uart_read(); 90 | } 91 | 92 | int putchar(unsigned char c) 93 | { 94 | if (c == '\n') 95 | { 96 | while (uart_tx_full()) 97 | ; // Do nothing 98 | uart_write('\r'); 99 | } 100 | while (uart_tx_full()) 101 | ; // Do nothing 102 | uart_write(c); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /gcc/riscv64-crossbuild.dockerfile: -------------------------------------------------------------------------------- 1 | # build with: 2 | # podman manifest create REPO/crossbuild-riscv64 3 | # podman build --platform linux/x86_64,linux/arm64 -t REPO/crossbuild-riscv64 -f riscv64-crossbuild.dockerfile . 4 | # podman push REPO/crossbuild-riscv64 5 | # or 6 | # docker buildx build --platform linux/x86_64,linux/arm64 -t REPO/crossbuild-riscv64 -f riscv64-crossbuild.dockerfile . 7 | FROM ubuntu 8 | 9 | ENV DEBIAN_FRONTEND noninteractive 10 | 11 | RUN apt-get update && \ 12 | apt-get install -y --no-install-recommends \ 13 | build-essential \ 14 | autoconf \ 15 | curl \ 16 | wget \ 17 | git \ 18 | python3 \ 19 | python3-pip \ 20 | bzip2 \ 21 | crossbuild-essential-riscv64 \ 22 | macutils \ 23 | bsdextrautils \ 24 | ca-certificates && \ 25 | rm -rf /var/lib/apt/lists/* 26 | 27 | WORKDIR /build 28 | 29 | RUN riscv64-linux-gnu-gcc --version 30 | 31 | CMD ["/bin/bash"] 32 | -------------------------------------------------------------------------------- /gcc/simpleLED/Makefile: -------------------------------------------------------------------------------- 1 | SOURCES := $(shell find . -name '*.c') 2 | ASM_SOURCES := $(shell find . -name '*.s') 3 | OBJECTS := $(SOURCES:%.c=%.o) 4 | ASM_OBJECTS := $(ASM_SOURCES:%.s=%.s.o) 5 | PROGDATA := $(SOURCES:%.c=%.elf) 6 | DUMPDATA := $(SOURCES:%.c=%.dump) 7 | HEXDATA := $(SOURCES:%.c=%.hex) 8 | MEMDATA := $(SOURCES:%.c=%.mem) 9 | ASM := $(SOURCES:%.c=%.s) 10 | 11 | DOCKERORPODMAN = $(shell command -v podman 2> /dev/null || echo docker) 12 | DOCKERARGS = run --rm -v $(PWD):/src -w /src 13 | DOCKERIMG = $(DOCKERORPODMAN) $(DOCKERARGS) carlosedp/crossbuild-riscv64 14 | 15 | CFLAGS=-mabi=ilp32 -march=rv32i -Os 16 | LDFLAGS=-T riscv.ld -m elf32lriscv -O binary -Map=main.map 17 | 18 | PREFIX=riscv64-linux 19 | OC=$(DOCKERIMG) $(PREFIX)-objcopy 20 | OD=$(DOCKERIMG) $(PREFIX)-objdump 21 | CC=$(DOCKERIMG) $(PREFIX)-gcc 22 | LD=$(DOCKERIMG) $(PREFIX)-ld 23 | HD=$(DOCKERIMG) hexdump 24 | 25 | all: $(PROGDATA) $(MEMDATA) $(HEXDATA) $(DUMPDATA) 26 | asm: $(ASM) 27 | 28 | %.o: %.c 29 | @echo "Building $< -> $@" 30 | @$(CC) -c $(CFLAGS) -o $@ $< 31 | 32 | %.s.o: %.s 33 | @echo "Building $< -> $@" 34 | @$(CC) -c $(CFLAGS) -o $@ $< 35 | 36 | %.elf: $(OBJECTS) $(ASM_OBJECTS) 37 | @echo "Linking $< $(OBJECTS) $(ASM_OBJECTS)" 38 | @$(LD) $(LDFLAGS) $(OBJECTS) $(ASM_OBJECTS) -o $@ 39 | 40 | %.dump: %.elf 41 | @echo "Dumping to $@" 42 | @$(OD) -d -t -r $< > $@ 43 | 44 | %.s: %.c 45 | @echo "Building $< -> $@" 46 | @$(CC) -S $(CFLAGS) -o $@ $< 47 | 48 | %.hex: %.elf 49 | @echo "Building $@ for http://tice.sea.eseo.fr/riscv/" 50 | @echo "Building $< -> $@" 51 | @$(OC) -O ihex $(@:%.hex=%.elf) $@ --only-section .text\* 52 | 53 | %.mem: %.elf ## Readmemh 32bit memory file 54 | @echo "Building $< -> $@" 55 | @$(OC) -O binary $(@:%.mem=%.elf) $(@:%.mem=%.bin) --only-section .text\* 56 | @$(HD) -ve '1/4 "%08x\n"' $(@:%.mem=%.bin) > $@ 57 | 58 | clean: 59 | @echo "Cleaning build files" 60 | rm -f $(ASM) $(OBJECTS) $(ASM_OBJECTS) *.elf *.hex *.bin *.mem *.s.o *.map *.dump 61 | -------------------------------------------------------------------------------- /gcc/simpleLED/crt.s: -------------------------------------------------------------------------------- 1 | .global _boot 2 | .section .boot 3 | 4 | _boot: 5 | # add x0, x0, x0 6 | # add x1, x0, x0 7 | # add x2, x0, x0 8 | # add x3, x0, x0 9 | # add x4, x0, x0 10 | # add x5, x0, x0 11 | # add x6, x0, x0 12 | # add x7, x0, x0 13 | # add x8, x0, x0 14 | # add x9, x0, x0 15 | # add x10, x0, x0 16 | # add x11, x0, x0 17 | # add x12, x0, x0 18 | # add x13, x0, x0 19 | # add x14, x0, x0 20 | # add x15, x0, x0 21 | # add x16, x0, x0 22 | # add x17, x0, x0 23 | # add x18, x0, x0 24 | # add x19, x0, x0 25 | # add x20, x0, x0 26 | # add x21, x0, x0 27 | # add x22, x0, x0 28 | # add x23, x0, x0 29 | # add x24, x0, x0 30 | # add x25, x0, x0 31 | # add x26, x0, x0 32 | # add x27, x0, x0 33 | # add x28, x0, x0 34 | # add x29, x0, x0 35 | # add x30, x0, x0 36 | # add x31, x0, x0 37 | 38 | lui x2, %hi(_sstack) 39 | addi x2, x2, %lo(_sstack) 40 | call main 41 | jal x0, 0 # halt 42 | # j _boot # restart 43 | -------------------------------------------------------------------------------- /gcc/simpleLED/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | #define GPIO0_BASE 0x30001000 4 | #define GPIO0_DIR 0x00 5 | #define GPIO0_VAL 0x04 6 | #define TIMER0_BASE 0x30003000 7 | 8 | #define HIGH 1 9 | #define LOW 0 10 | 11 | #define INPUT 1 12 | #define OUTPUT 0 13 | 14 | int main() { 15 | dir(); 16 | 17 | // Turn on LED1 (GPIO0) 18 | uint32_t addrval; 19 | addrval = GPIO0_BASE + GPIO0_VAL; 20 | *(volatile uint32_t *)addrval = 3; 21 | } 22 | 23 | void dir() { 24 | // Set GPIO0 Direction (IIOOOOOO) 25 | uint32_t addrdir; 26 | addrdir = GPIO0_BASE + GPIO0_DIR; 27 | *(volatile uint32_t *)addrdir = 0x3F; 28 | } 29 | -------------------------------------------------------------------------------- /gcc/simpleLED/main.dump: -------------------------------------------------------------------------------- 1 | 2 | main.elf: file format elf32-littleriscv 3 | 4 | SYMBOL TABLE: 5 | 00000000 l d .text 00000000 .text 6 | 00000020 l d .text.startup 00000000 .text.startup 7 | 80000000 l d .heap 00000000 .heap 8 | 80002000 l d .stack 00000000 .stack 9 | 00000000 l d .comment 00000000 .comment 10 | 00000000 l df *ABS* 00000000 main.c 11 | 80000000 g .heap 00000000 _sheap 12 | 00008000 g *ABS* 00000000 __stack_size 13 | 00000000 g .text 00000000 _boot 14 | 00002000 g *ABS* 00000000 __heap_size 15 | 00000020 g F .text.startup 0000001c main 16 | 00000010 g F .text 00000010 dir 17 | 8000a000 g .stack 00000000 _sstack 18 | 80002000 g .stack 00000000 _estack 19 | 80002000 g .heap 00000000 _eheap 20 | 21 | 22 | 23 | Disassembly of section .text: 24 | 25 | 00000000 <_boot>: 26 | 0: 8000a137 lui sp,0x8000a 27 | 4: 00010113 mv sp,sp 28 | 8: 018000ef jal ra,20
29 | c: ff5ff06f j 0 <_boot> 30 | 31 | 00000010 : 32 | 10: 300017b7 lui a5,0x30001 33 | 14: 03f00713 li a4,63 34 | 18: 00e7a023 sw a4,0(a5) # 30001000 <__stack_size+0x2fff9000> 35 | 1c: 00008067 ret 36 | 37 | Disassembly of section .text.startup: 38 | 39 | 00000020
: 40 | 20: 300017b7 lui a5,0x30001 41 | 24: 03f00713 li a4,63 42 | 28: 00e7a023 sw a4,0(a5) # 30001000 <__stack_size+0x2fff9000> 43 | 2c: 00300713 li a4,3 44 | 30: 00e7a223 sw a4,4(a5) 45 | 34: 00000513 li a0,0 46 | 38: 00008067 ret 47 | -------------------------------------------------------------------------------- /gcc/simpleLED/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef unsigned int uint32_t; 4 | typedef int int32_t; 5 | typedef unsigned char uint8_t; 6 | typedef char int8_t; 7 | 8 | int main(); 9 | void dir(); -------------------------------------------------------------------------------- /gcc/simpleLED/main.hex: -------------------------------------------------------------------------------- 1 | :1000000037A1008013010100EF0080016FF05FFF56 2 | :10001000B71700301307F00323A0E7006780000044 3 | :10002000B71700301307F00323A0E70013073000D1 4 | :0C00300023A2E700130500006780000019 5 | :00000001FF 6 | -------------------------------------------------------------------------------- /gcc/simpleLED/main.map: -------------------------------------------------------------------------------- 1 | 2 | Memory Configuration 3 | 4 | Name Origin Length Attributes 5 | ROM 0x0000000000000000 0x0000000000010000 xrw 6 | RAM 0x0000000080000000 0x0000000000010000 xrw 7 | IO 0x0000000030000000 0x0000000000000010 rw 8 | *default* 0x0000000000000000 0xffffffffffffffff 9 | 10 | Linker script and memory map 11 | 12 | 0x0000000000002000 __heap_size = 0x2000 13 | 0x0000000000008000 __stack_size = 0x8000 14 | 15 | .text 0x0000000000000000 0x20 16 | *(.boot) 17 | .boot 0x0000000000000000 0x10 ./crt.s.o 18 | 0x0000000000000000 _boot 19 | *(.text) 20 | .text 0x0000000000000010 0x10 ./main.o 21 | 0x0000000000000010 dir 22 | .text 0x0000000000000020 0x0 ./crt.s.o 23 | *(.text) 24 | 25 | .text.startup 0x0000000000000020 0x1c 26 | .text.startup 0x0000000000000020 0x1c ./main.o 27 | 0x0000000000000020 main 28 | 29 | .data 0x0000000080000000 0x0 30 | *(.rodata*) 31 | *(.sbss) 32 | *(.data) 33 | .data 0x0000000080000000 0x0 ./main.o 34 | .data 0x0000000080000000 0x0 ./crt.s.o 35 | *(.bss) 36 | .bss 0x0000000080000000 0x0 ./main.o 37 | .bss 0x0000000080000000 0x0 ./crt.s.o 38 | *(.rela*) 39 | *(COMMON) 40 | 41 | .heap 0x0000000080000000 0x2000 42 | 0x0000000080000000 . = ALIGN (0x4) 43 | [!provide] PROVIDE (end = .) 44 | 0x0000000080000000 _sheap = . 45 | 0x0000000080002000 . = (. + __heap_size) 46 | *fill* 0x0000000080000000 0x2000 47 | 0x0000000080002000 . = ALIGN (0x4) 48 | 0x0000000080002000 _eheap = . 49 | 50 | .stack 0x0000000080002000 0x8000 51 | 0x0000000080002000 . = ALIGN (0x4) 52 | 0x0000000080002000 _estack = . 53 | 0x000000008000a000 . = (. + __stack_size) 54 | *fill* 0x0000000080002000 0x8000 55 | 0x000000008000a000 . = ALIGN (0x4) 56 | 0x000000008000a000 _sstack = . 57 | LOAD ./main.o 58 | LOAD ./crt.s.o 59 | OUTPUT(main.elf elf32-littleriscv) 60 | 61 | .comment 0x0000000000000000 0x2c 62 | .comment 0x0000000000000000 0x2c ./main.o 63 | 0x2d (size before relaxing) 64 | 65 | .note.GNU-stack 66 | 0x0000000000000000 0x0 67 | .note.GNU-stack 68 | 0x0000000000000000 0x0 ./main.o 69 | -------------------------------------------------------------------------------- /gcc/simpleLED/main.mem: -------------------------------------------------------------------------------- 1 | 8000a137 2 | 00010113 3 | 018000ef 4 | ff5ff06f 5 | 300017b7 6 | 03f00713 7 | 00e7a023 8 | 00008067 9 | 300017b7 10 | 03f00713 11 | 00e7a023 12 | 00300713 13 | 00e7a223 14 | 00000513 15 | 00008067 16 | -------------------------------------------------------------------------------- /gcc/simpleLED/riscv.ld: -------------------------------------------------------------------------------- 1 | /* Thanks https://github.com/darklife/darkriscv */ 2 | /* and https://github.com/racerxdl/riskow */ 3 | 4 | __heap_size = 0x2000; /* amount of heap */ 5 | __stack_size = 0x8000; /* amount of stack */ 6 | 7 | MEMORY 8 | { 9 | ROM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 10 | RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x10000 11 | IO (rw) : ORIGIN = 0x30000000, LENGTH = 0x00010 12 | } 13 | SECTIONS 14 | { 15 | .text : 16 | { 17 | *(.boot) 18 | *(.text) 19 | *(.text) 20 | } > ROM 21 | .data : 22 | { 23 | *(.rodata*) 24 | *(.sbss) 25 | *(.data) 26 | *(.bss) 27 | *(.rela*) 28 | *(COMMON) 29 | } > RAM 30 | 31 | .heap : 32 | { 33 | . = ALIGN(4); 34 | PROVIDE ( end = . ); 35 | _sheap = .; 36 | . = . + __heap_size; 37 | . = ALIGN(4); 38 | _eheap = .; 39 | } >RAM 40 | 41 | 42 | .stack : 43 | { 44 | . = ALIGN(4); 45 | _estack = .; 46 | . = . + __stack_size; 47 | . = ALIGN(4); 48 | _sstack = .; 49 | } >RAM 50 | 51 | } -------------------------------------------------------------------------------- /gcc/test/Makefile: -------------------------------------------------------------------------------- 1 | SOURCES := $(shell find . -name '*.s') 2 | OBJECTS := $(SOURCES:%.s=%.o) 3 | TESTDATA := $(SOURCES:%.s=%.elf) 4 | HEXDATA := $(SOURCES:%.s=%.hex) 5 | MEMDATA := $(SOURCES:%.s=%.mem) 6 | 7 | DOCKERORPODMAN = $(shell command -v podman 2> /dev/null || echo docker) 8 | DOCKERARGS = run --rm -v $(PWD):/src -w /src 9 | DOCKERIMG = $(DOCKERORPODMAN) $(DOCKERARGS) carlosedp/crossbuild-riscv64 10 | 11 | CFLAGS=-mabi=ilp32 -march=rv32i -Os 12 | LDFLAGS=-T riscv.ld -m elf32lriscv -O binary 13 | 14 | PREFIX=riscv64-linux 15 | OC=$(DOCKERIMG) $(PREFIX)-objcopy 16 | OD=$(DOCKERIMG) $(PREFIX)-objdump 17 | CC=$(DOCKERIMG) $(PREFIX)-gcc 18 | LD=$(DOCKERIMG) $(PREFIX)-ld 19 | HD=$(DOCKERIMG) hexdump 20 | 21 | all: $(TESTDATA) $(MEMDATA) $(HEXDATA) 22 | 23 | %.elf: %.s 24 | @echo "Building $< -> $@" 25 | @$(CC) -c $(CFLAGS) -o $(@:%.elf=%.o) $< 26 | @$(LD) $(LDFLAGS) $(@:%.elf=%.o) -o $@ 27 | 28 | %.hex: %.elf 29 | @echo "Building $< -> $@" 30 | @$(OC) -O ihex $(@:%.hex=%.elf) $@ --only-section .text\* 31 | 32 | %.mem: %.elf ## Readmemh 32bit memory file 33 | @echo "Building $< -> $@" 34 | @$(OC) -O binary $(@:%.mem=%.elf) $(@:%.mem=%.bin) --only-section .text\* 35 | @hexdump -ve '1/4 "%08x\n"' $(@:%.mem=%.bin) > $@ 36 | 37 | simhex: $(HEXDATA) 38 | @echo "Building prog.hex for http://tice.sea.eseo.fr/riscv/" 39 | 40 | testmem: $(MEMDATA) 41 | @echo "Building memdata for unit tests" 42 | 43 | clean: 44 | @echo "Cleaning build files" 45 | @rm -f $(OBJECTS) *.elf *.hex *.mem *.bin 46 | -------------------------------------------------------------------------------- /gcc/test/riscv.ld: -------------------------------------------------------------------------------- 1 | /* Thanks https://github.com/darklife/darkriscv */ 2 | /* and https://github.com/racerxdl/riskow */ 3 | 4 | __heap_size = 0x200; /* required amount of heap */ 5 | __stack_size = 0x800; /* required amount of stack */ 6 | 7 | MEMORY 8 | { 9 | ROM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 10 | RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x10000 11 | RESERVED (rwx) : ORIGIN = 0x00018000, LENGTH = 0xF0000 12 | EXCEPTION (rwx) : ORIGIN = 0x05EF0DE0, LENGTH = 0x00400 13 | IO (rw) : ORIGIN = 0x30000000, LENGTH = 0x00010 14 | } 15 | SECTIONS 16 | { 17 | .text : 18 | { 19 | *(.boot) 20 | *(.text) 21 | *(.text) 22 | *(.rodata*) 23 | } > ROM 24 | .data : 25 | { 26 | *(.sbss) 27 | *(.data) 28 | *(.bss) 29 | *(.rela*) 30 | *(COMMON) 31 | } > RAM 32 | 33 | .heap : 34 | { 35 | . = ALIGN(4); 36 | PROVIDE ( end = . ); 37 | _sheap = .; 38 | . = . + __heap_size; 39 | . = ALIGN(4); 40 | _eheap = .; 41 | } >RAM 42 | 43 | 44 | .stack : 45 | { 46 | . = ALIGN(4); 47 | _estack = .; 48 | . = . + __stack_size; 49 | . = ALIGN(4); 50 | _sstack = .; 51 | } >RAM 52 | 53 | .exception : 54 | { 55 | *(.exception) 56 | } > EXCEPTION 57 | } -------------------------------------------------------------------------------- /gcc/test/test_addi.hex: -------------------------------------------------------------------------------- 1 | :100000009300803E1381007D930181C1138201839F 2 | :100010009302823E1383027D930383C1138403837F 3 | :100020009304843E1385047D930585C1138605835F 4 | :100030009306863E1387067D930787C1138807833F 5 | :100040009308883E1389087D930989C1138A09831F 6 | :10005000930A8A3E138B0A7D930B8BC1138C0B83FF 7 | :10006000930C8C3E138D0C7D930D8DC1138E0D83DF 8 | :0C007000930E8E3E138F0E7D930F8FC1F8 9 | :00000001FF 10 | -------------------------------------------------------------------------------- /gcc/test/test_addi.mem: -------------------------------------------------------------------------------- 1 | 3e800093 2 | 7d008113 3 | c1810193 4 | 83018213 5 | 3e820293 6 | 7d028313 7 | c1830393 8 | 83038413 9 | 3e840493 10 | 7d048513 11 | c1850593 12 | 83058613 13 | 3e860693 14 | 7d068713 15 | c1870793 16 | 83078813 17 | 3e880893 18 | 7d088913 19 | c1890993 20 | 83098a13 21 | 3e8a0a93 22 | 7d0a8b13 23 | c18b0b93 24 | 830b8c13 25 | 3e8c0c93 26 | 7d0c8d13 27 | c18d0d93 28 | 830d8e13 29 | 3e8e0e93 30 | 7d0e8f13 31 | c18f0f93 32 | -------------------------------------------------------------------------------- /gcc/test/test_addi.s: -------------------------------------------------------------------------------- 1 | .global _boot 2 | .text 3 | 4 | _boot: /* x0 = 0 0x000 */ 5 | /* Test ADDI */ 6 | addi x1 , x0, 1000 /* x1 = 1000 0x3E8 */ 7 | addi x2 , x1, 2000 /* x2 = 3000 0xBB8 */ 8 | addi x3 , x2, -1000 /* x3 = 2000 0x7D0 */ 9 | addi x4 , x3, -2000 /* x4 = 0 0x000 */ 10 | addi x5 , x4, 1000 /* x5 = 1000 0x3E8 */ 11 | addi x6 , x5, 2000 /* x6 = 3000 0xBB8 */ 12 | addi x7 , x6, -1000 /* x7 = 2000 0x7D0 */ 13 | addi x8 , x7, -2000 /* x8 = 0 0x000 */ 14 | addi x9 , x8, 1000 /* x9 = 1000 0x3E8 */ 15 | addi x10, x9, 2000 /* x10 = 3000 0xBB8 */ 16 | addi x11, x10, -1000 /* x11 = 2000 0x7D0 */ 17 | addi x12, x11, -2000 /* x12 = 0 0x000 */ 18 | addi x13, x12, 1000 /* x13 = 1000 0x3E8 */ 19 | addi x14, x13, 2000 /* x14 = 3000 0xBB8 */ 20 | addi x15, x14, -1000 /* x15 = 2000 0x7D0 */ 21 | addi x16 ,x15, -2000 /* x16 = 0 0x000 */ 22 | addi x17 ,x16, 1000 /* x17 = 1000 0x3E8 */ 23 | addi x18 ,x17, 2000 /* x18 = 3000 0xBB8 */ 24 | addi x19 ,x18, -1000 /* x19 = 2000 0x7D0 */ 25 | addi x20 ,x19, -2000 /* x20 = 0 0x000 */ 26 | addi x21 ,x20, 1000 /* x21 = 1000 0x3E8 */ 27 | addi x22, x21, 2000 /* x22 = 3000 0xBB8 */ 28 | addi x23, x22, -1000 /* x23 = 2000 0x7D0 */ 29 | addi x24, x23, -2000 /* x24 = 0 0x000 */ 30 | addi x25, x24, 1000 /* x25 = 1000 0x3E8 */ 31 | addi x26, x25, 2000 /* x26 = 3000 0xBB8 */ 32 | addi x27, x26, -1000 /* x27 = 2000 0x7D0 */ 33 | addi x28 ,x27, -2000 /* x28 = 0 0x000 */ 34 | addi x29 ,x28, 1000 /* x29 = 1000 0x3E8 */ 35 | addi x30 ,x29, 2000 /* x30 = 3000 0xBB8 */ 36 | addi x31 ,x30, -1000 /* x31 = 2000 0x7D0 */ 37 | -------------------------------------------------------------------------------- /gcc/test/test_ascii.hex: -------------------------------------------------------------------------------- 1 | :1000000093008002130110029301E00737020030D1 2 | :100010002300220013011100E3DC21FE6FF05FFEDC 3 | :00000001FF 4 | -------------------------------------------------------------------------------- /gcc/test/test_ascii.mem: -------------------------------------------------------------------------------- 1 | 02800093 2 | 02100113 3 | 07e00193 4 | 30000237 5 | 00220023 6 | 00110113 7 | fe21dce3 8 | fe5ff06f 9 | -------------------------------------------------------------------------------- /gcc/test/test_ascii.s: -------------------------------------------------------------------------------- 1 | .global _boot 2 | .text 3 | # Loop from 33 to 126 (visible chars in ascii table) outputting the value to the memory region 0x3000_0000 4 | _boot: /* x0 = 0 0x000 */ 5 | addi x1, x0, 40 /* x1 = 40 */ 6 | addi x2, x0, 33 /* x2 = 33 */ 7 | addi x3, x0, 126 /* x3 = 126 */ 8 | lui x4, %hi(0x30000000) /* x4 = 0x3000_0000 */ 9 | loop: sb x2, 0(x4) /* [0x3000_0000] = x2 = 33 */ 10 | addi x2, x2, 1 /* x2 = 1 */ 11 | bge x3, x2, loop /* if x3 > x2 -> pc = pc-8 (back 2 instructions)*/ 12 | jal x0, 0 /* loop forever */ 13 | -------------------------------------------------------------------------------- /gcc/test/test_book.hex: -------------------------------------------------------------------------------- 1 | :10000000130150009301C000938371FF37030080F8 2 | :1000100033E22300B3F24100B382420063887202EC 3 | :1000200033A24100630402009302000033A22300C4 4 | :10003000B3035200B3832340232073000321030042 5 | :10004000B3045100EF01800013011000330191004F 6 | :080050002322230663002100B6 7 | :00000001FF 8 | -------------------------------------------------------------------------------- /gcc/test/test_book.mem: -------------------------------------------------------------------------------- 1 | 00500113 2 | 00c00193 3 | ff718393 4 | 80000337 5 | 0023e233 6 | 0041f2b3 7 | 004282b3 8 | 02728863 9 | 0041a233 10 | 00020463 11 | 00000293 12 | 0023a233 13 | 005203b3 14 | 402383b3 15 | 00732023 16 | 00032103 17 | 005104b3 18 | 008001ef 19 | 00100113 20 | 00910133 21 | 06232223 22 | 00210063 23 | -------------------------------------------------------------------------------- /gcc/test/test_book.s: -------------------------------------------------------------------------------- 1 | # riscvtest.s 2 | # Sarah.Harris@unlv.edu 3 | # David_Harris@hmc.edu 4 | # 27 Oct 2020 5 | # Test the RISC-V processor: 6 | # add, sub, and, or, slt, addi, lw, sw, beq, jal 7 | # If successful, it should write the value 25 to address 100 8 | # 9 | # RISC-V Assembly Description Address Machine Code 10 | main: addi x2, x0, 5 # x2 = 5 0 00500113 11 | addi x3, x0, 12 # x3 = 12 4 00C00193 12 | addi x7, x3, -9 # x7 = (12 - 9) = 3 8 FF718393 13 | lui x6, %hi(0x80000000) # x5 = 0x80000000 C 800002b7 14 | or x4, x7, x2 # x4 = (3 OR 5) = 7 10 0023E233 15 | and x5, x3, x4 # x5 = (12 AND 7) = 4 14 0041F2B3 16 | add x5, x5, x4 # x5 = 4 + 7 = 11 18 004282B3 17 | beq x5, x7, end # shouldn't be taken 1C 02728863 18 | slt x4, x3, x4 # x4 = (12 < 7) = 0 20 0041A233 19 | beq x4, x0, around # should be taken 24 00020463 20 | addi x5, x0, 0 # shouldn't execute 28 00000293 21 | around: slt x4, x7, x2 # x4 = (3 < 5) = 1 2C 0023A233 22 | add x7, x4, x5 # x7 = (1 + 11) = 12 30 005203B3 23 | sub x7, x7, x2 # x7 = (12 - 5) = 7 34 402383B3 24 | sw x7, 0(x6) # [96] = 7 38 0471AA23 25 | lw x2, 0(x6) # x2 = [96] = 7 3C 06002103 26 | add x9, x2, x5 # x9 = (7 + 11) = 18 40 005104B3 27 | jal x3, end # jump to end, x3 = 0x44 44 008001EF 28 | addi x2, x0, 1 # shouldn't execute 48 00100113 29 | end: add x2, x2, x9 # x2 = (7 + 18) = 25 4C 00910133 30 | sw x2, 100(x6) # [100+x6] = 25 50 0221A023 31 | done: beq x2, x2, done # infinite loop 54 00210063 32 | -------------------------------------------------------------------------------- /gcc/test/test_gpio.hex: -------------------------------------------------------------------------------- 1 | :10000000B7100030373300309302F00CB707008090 2 | :1000100023A4570203A88702930100019303803EA3 3 | :100020001305000123A000011301110083A4400067 4 | :10003000B3F5A4006314B5001361010423A22000EA 5 | :10004000630A310003240300E39E83FE23200300A0 6 | :0C0050006FF09FFD130100006FF01FFD1A 7 | :00000001FF 8 | -------------------------------------------------------------------------------- /gcc/test/test_gpio.mem: -------------------------------------------------------------------------------- 1 | 300010b7 2 | 30003337 3 | 0cf00293 4 | 800007b7 5 | 0257a423 6 | 0287a803 7 | 01000193 8 | 3e800393 9 | 01000513 10 | 0100a023 11 | 00110113 12 | 0040a483 13 | 00a4f5b3 14 | 00b51463 15 | 04016113 16 | 0020a223 17 | 00310a63 18 | 00032403 19 | fe839ee3 20 | 00032023 21 | fd9ff06f 22 | 00000113 23 | fd1ff06f 24 | -------------------------------------------------------------------------------- /gcc/test/test_gpio.s: -------------------------------------------------------------------------------- 1 | # Test GPIO 2 | # This writes to GPIO 8 pins as a binary add 3 | # 4 | # Config for the http://tice.sea.eseo.fr/riscv simulator 5 | # GPIO_BASE = 0xd0000000 6 | # GPIO_VALUE_OFFSET = 0x10 7 | # GPIO_DIR_OFFSET = 0x00 8 | # ENABLE_OUTPUT = 0 9 | # 10 | # Config for ChiselV 11 | GPIO_BASE = 0x30001000 12 | GPIO_DIR_OFFSET = 0x00 13 | GPIO_VALUE_OFFSET = 0x04 14 | GPIO_DIRECTION = 0xCF # Set GPIO Inputs and Outputs (OOIIOOOO) 15 | TIMER_BASE = 0x30003000 16 | MEM_BASE = 0x80000000 17 | 18 | main: lui x1, %hi(GPIO_BASE) # Define the GPIO0 base address 19 | lui x6, %hi(TIMER_BASE) # Define the Timer0 base address 20 | addi x5, x0, GPIO_DIRECTION # Set x5 to use as GPIO direction 21 | lui x15, %hi(MEM_BASE) # Store base RAM address 22 | sw x5, 40(x15) # Store diretion to RAM (for testing) 23 | lw x16, 40(x15) # Load direction form RAM (for testing) 24 | addi x3, x0, 16 # Set x3 as the highest value (using 4 bits to match 8 used GPIO outputs) 25 | addi x7, x0, 1000 # Set wait timer for 1s (1000ms) 26 | addi x10, x0, 0x10 # Set x10 to check if button is pressed 27 | sw x16, GPIO_DIR_OFFSET(x1) # Write the GPIO direction to address 0x30001000 28 | loop: addi x2, x2, 1 # Increment x2 by 1 29 | lw x9, GPIO_VALUE_OFFSET(x1) # Read the GPIO value 0x30001004 to x9 30 | and x11, x9, x10 # Check if button is pressed 31 | bne x10, x11 ,write # If button is not pressed, do not switch LED on 32 | ori x2, x2, 0x40 # Add x9 to x2 33 | write: sw x2, GPIO_VALUE_OFFSET(x1) # Write the GPIO value to address 0x30001004 34 | beq x2, x3, reset # Loop until x2 is equal to x4 (from 1 to 255) 35 | wait: lw x8, 0(x6) # Check timer value 36 | bne x7, x8, wait # Unless timer value is equal to 1000ms, keep waiting 37 | sw x0, 0(x6) # Reset timer 38 | jal x0, loop # Go to GPIO Loop 39 | reset: addi x2, x0, 0 # Reset x2 to 0 (GPIO Count) 40 | jal x0, loop # Go to GPIO Loop 41 | -------------------------------------------------------------------------------- /mill: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This is a wrapper script, that automatically download mill from GitHub release pages 4 | # You can give the required mill version with MILL_VERSION env variable 5 | # If no version is given, it falls back to the value of DEFAULT_MILL_VERSION 6 | 7 | set -e 8 | 9 | if [ -z "${DEFAULT_MILL_VERSION}" ] ; then 10 | DEFAULT_MILL_VERSION=0.11.0 11 | fi 12 | 13 | if [ -z "$MILL_VERSION" ] ; then 14 | if [ -f ".mill-version" ] ; then 15 | MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)" 16 | elif [ -f ".config/mill-version" ] ; then 17 | MILL_VERSION="$(head -n 1 .config/mill-version 2> /dev/null)" 18 | elif [ -f "mill" ] && [ "$0" != "mill" ] ; then 19 | MILL_VERSION=$(grep -F "DEFAULT_MILL_VERSION=" "mill" | head -n 1 | cut -d= -f2) 20 | else 21 | MILL_VERSION=$DEFAULT_MILL_VERSION 22 | fi 23 | fi 24 | 25 | if [ "x${XDG_CACHE_HOME}" != "x" ] ; then 26 | MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download" 27 | else 28 | MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download" 29 | fi 30 | MILL_EXEC_PATH="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" 31 | 32 | version_remainder="$MILL_VERSION" 33 | MILL_MAJOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}" 34 | MILL_MINOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}" 35 | 36 | if [ ! -s "$MILL_EXEC_PATH" ] ; then 37 | mkdir -p "$MILL_DOWNLOAD_PATH" 38 | if [ "$MILL_MAJOR_VERSION" -gt 0 ] || [ "$MILL_MINOR_VERSION" -ge 5 ] ; then 39 | ASSEMBLY="-assembly" 40 | fi 41 | DOWNLOAD_FILE=$MILL_EXEC_PATH-tmp-download 42 | MILL_VERSION_TAG=$(echo $MILL_VERSION | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/') 43 | MILL_DOWNLOAD_URL="https://repo1.maven.org/maven2/com/lihaoyi/mill-dist/$MILL_VERSION/mill-dist-$MILL_VERSION.jar" 44 | curl --fail -L -o "$DOWNLOAD_FILE" "$MILL_DOWNLOAD_URL" 45 | chmod +x "$DOWNLOAD_FILE" 46 | mv "$DOWNLOAD_FILE" "$MILL_EXEC_PATH" 47 | unset DOWNLOAD_FILE 48 | unset MILL_DOWNLOAD_URL 49 | fi 50 | 51 | if [ -z "$MILL_MAIN_CLI" ] ; then 52 | MILL_MAIN_CLI="${0}" 53 | fi 54 | 55 | MILL_FIRST_ARG="" 56 | if [ "$1" = "--bsp" ] || [ "$1" = "-i" ] || [ "$1" = "--interactive" ] || [ "$1" = "--no-server" ] || [ "$1" = "--repl" ] || [ "$1" = "--help" ] ; then 57 | # Need to preserve the first position of those listed options 58 | MILL_FIRST_ARG=$1 59 | shift 60 | fi 61 | 62 | unset MILL_DOWNLOAD_PATH 63 | unset MILL_VERSION 64 | 65 | exec $MILL_EXEC_PATH $MILL_FIRST_ARG -D "mill.main.cli=${MILL_MAIN_CLI}" "$@" 66 | -------------------------------------------------------------------------------- /openocd/LFE5U-25F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043 2 | -------------------------------------------------------------------------------- /openocd/LFE5U-45F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x41112043 2 | -------------------------------------------------------------------------------- /openocd/LFE5U-85F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x41113043 2 | -------------------------------------------------------------------------------- /openocd/LFE5UM-25F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x01111043 2 | -------------------------------------------------------------------------------- /openocd/LFE5UM-45F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x01112043 2 | -------------------------------------------------------------------------------- /openocd/LFE5UM-85F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x01113043 2 | -------------------------------------------------------------------------------- /openocd/LFE5UM5G-25F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x81111043 2 | -------------------------------------------------------------------------------- /openocd/LFE5UM5G-45F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x81112043 2 | -------------------------------------------------------------------------------- /openocd/LFE5UM5G-85F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x81113043 2 | -------------------------------------------------------------------------------- /openocd/digilent-hs1.cfg: -------------------------------------------------------------------------------- 1 | # this supports JTAG-HS1 and JTAG-SMT1 2 | # (the later being the OEM on-board version) 3 | 4 | adapter driver ftdi 5 | ftdi_device_desc "Digilent USB Device" 6 | ftdi_vid_pid 0x0403 0x6010 7 | # channel 1 does not have any functionality 8 | ftdi_channel 0 9 | # just TCK TDI TDO TMS, no reset 10 | ftdi_layout_init 0x0088 0x008b 11 | reset_config none 12 | 13 | # default speed 14 | adapter speed 5000 15 | -------------------------------------------------------------------------------- /openocd/ecp5-evn.cfg: -------------------------------------------------------------------------------- 1 | # this supports ECP5 Evaluation Board 2 | 3 | adapter driver ftdi 4 | ftdi_device_desc "Lattice ECP5 Evaluation Board" 5 | ftdi_vid_pid 0x0403 0x6010 6 | # channel 1 does not have any functionality 7 | ftdi_channel 0 8 | # just TCK TDI TDO TMS, no reset 9 | ftdi_layout_init 0xfff8 0xfffb 10 | reset_config none 11 | 12 | # default speed 13 | adapter speed 5000 14 | -------------------------------------------------------------------------------- /openocd/ft231x.cfg: -------------------------------------------------------------------------------- 1 | adapter driver ft232r 2 | ft232r_vid_pid 0x0403 0x6015 3 | # ULX3S specific GPIO setting 4 | ft232r_tck_num DSR 5 | ft232r_tms_num DCD 6 | ft232r_tdi_num RI 7 | ft232r_tdo_num CTS 8 | # trst/srst are not used but must have different values than above 9 | ft232r_trst_num RTS 10 | ft232r_srst_num DTR 11 | adapter speed 1000 12 | -------------------------------------------------------------------------------- /openocd/xilinx-xc7.cfg: -------------------------------------------------------------------------------- 1 | # xilinx series 7 (artix, kintex, virtex) 2 | # http://www.xilinx.com/support/documentation/user_guides/ug470_7Series_Config.pdf 3 | 4 | if { [info exists CHIPNAME] } { 5 | set _CHIPNAME $CHIPNAME 6 | } else { 7 | set _CHIPNAME xc7 8 | } 9 | 10 | # the 4 top bits (28:31) are the die stepping/revisions. ignore it. 11 | jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \ 12 | -expected-id 0x03622093 \ 13 | -expected-id 0x03620093 \ 14 | -expected-id 0x037C4093 \ 15 | -expected-id 0x0362F093 \ 16 | -expected-id 0x037C8093 \ 17 | -expected-id 0x037C7093 \ 18 | -expected-id 0x037C3093 \ 19 | -expected-id 0x0362E093 \ 20 | -expected-id 0x037C2093 \ 21 | -expected-id 0x0362D093 \ 22 | -expected-id 0x0362C093 \ 23 | -expected-id 0x03632093 \ 24 | -expected-id 0x03631093 \ 25 | -expected-id 0x03636093 \ 26 | -expected-id 0x03647093 \ 27 | -expected-id 0x0364C093 \ 28 | -expected-id 0x03651093 \ 29 | -expected-id 0x03747093 \ 30 | -expected-id 0x03656093 \ 31 | -expected-id 0x03752093 \ 32 | -expected-id 0x03751093 \ 33 | -expected-id 0x03671093 \ 34 | -expected-id 0x036B3093 \ 35 | -expected-id 0x036B7093 \ 36 | -expected-id 0x036BB093 \ 37 | -expected-id 0x036BF093 \ 38 | -expected-id 0x03667093 \ 39 | -expected-id 0x03682093 \ 40 | -expected-id 0x03687093 \ 41 | -expected-id 0x03692093 \ 42 | -expected-id 0x03691093 \ 43 | -expected-id 0x03696093 \ 44 | -expected-id 0x036D5093 \ 45 | -expected-id 0x036D9093 \ 46 | -expected-id 0x036DB093 47 | 48 | pld device virtex2 $_CHIPNAME.tap 1 49 | 50 | set XC7_JSHUTDOWN 0x0d 51 | set XC7_JPROGRAM 0x0b 52 | set XC7_JSTART 0x0c 53 | set XC7_BYPASS 0x3f 54 | 55 | proc xc7_program {tap} { 56 | global XC7_JSHUTDOWN XC7_JPROGRAM XC7_JSTART XC7_BYPASS 57 | irscan $tap $XC7_JSHUTDOWN 58 | irscan $tap $XC7_JPROGRAM 59 | runtest 60000 60 | #JSTART prevents this from working... 61 | #irscan $tap $XC7_JSTART 62 | runtest 2000 63 | irscan $tap $XC7_BYPASS 64 | runtest 2000 65 | } 66 | -------------------------------------------------------------------------------- /proginfo/artix7-template.txt: -------------------------------------------------------------------------------- 1 | # Programming instructions for Digilent Arty A7 - Artix 7 2 | 3 | ## To program the board using OpenOCD, use the command: 4 | 5 | openocd -f $interfaceConfig -f $boardConfig -c "transport select jtag;init; pld load 0 $bitstream; exit" 6 | 7 | ## Or using openFPGALoader (https://trabucayre.github.io/openFPGALoader/guide/install.html): 8 | 9 | openfpgaloader -b arty $bitstream 10 | -------------------------------------------------------------------------------- /proginfo/boardconfig.yaml: -------------------------------------------------------------------------------- 1 | # This is the board programming files config 2 | # The board parameters must match the template for each board 3 | 4 | boards: 5 | ulx3s-85f: 6 | templateFile: ulx3s-template.txt 7 | interfaceConfig: ft231x.cfg 8 | boardConfig: LFE5U-85F.cfg 9 | bitstream: carlosedp_chiselv_singlecycle_0.bit 10 | bitstreamSVF: carlosedp_chiselv_singlecycle_0.svf 11 | 12 | artya7-35t: 13 | templateFile: artix7-template.txt 14 | interfaceConfig: digilent-hs1.cfg 15 | boardConfig: xilinx-xc7.cfg 16 | bitstream: Toplevel.bit 17 | 18 | qmtech_k325t: 19 | templateFile: qmtech_k325t-template.txt 20 | bitstream: carlosedp_chiselv_singlecycle_0.bit 21 | -------------------------------------------------------------------------------- /proginfo/proginfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import os 3 | import sys 4 | import glob 5 | import yaml 6 | from string import Template 7 | 8 | def main(): 9 | print("Build completed") 10 | with open(findFile('boardconfig.yaml')) as file: 11 | fullfile = yaml.full_load(file) 12 | boards = fullfile['boards'] 13 | boardFiles = {} 14 | if sys.argv[1] in boards: 15 | for param in boards[sys.argv[1]]: 16 | boardFiles[param] = findFile(boards[sys.argv[1]][param]) 17 | render(boardFiles, findFile(boards[sys.argv[1]]['templateFile'])) 18 | else: 19 | print("ERROR: Board " + sys.argv[1] + " not found in boardconfig.yaml") 20 | exit(1) 21 | print("") 22 | 23 | # Utility Functions 24 | 25 | def findFile(f, filter=""): 26 | r = glob.glob("../**/" + f, recursive=True) 27 | if filter != "": 28 | r = [s for s in r if filter in s] 29 | if not r: 30 | print("ERROR: Could not find file " + f) 31 | exit(1) 32 | return os.path.realpath(r[0]) 33 | 34 | def render(d, template): 35 | with open(os.path.join(os.getcwd(),template)) as f: 36 | src = Template(f.read()) 37 | output = src.substitute(d) 38 | print(output) 39 | 40 | if __name__ == "__main__": 41 | if len(sys.argv) <= 1: 42 | print("Board not supplied") 43 | exit(1) 44 | main() 45 | -------------------------------------------------------------------------------- /proginfo/qmtech_k325t-template.txt: -------------------------------------------------------------------------------- 1 | # Programming instructions for QMTech Kintex 7 board 2 | 3 | ## To program the board using OpenFPGAloader (https://trabucayre.github.io/openFPGALoader/guide/first-steps.html), use the command: 4 | 5 | openfpgaloader -c ft232 $bitstream 6 | -------------------------------------------------------------------------------- /proginfo/ulx3s-template.txt: -------------------------------------------------------------------------------- 1 | # Programming instructions for ULX3S based on Lattice ECP5 2 | 3 | ## To program with ujprog (https://github.com/emard/ulx3s-bin): 4 | 5 | ujprog $bitstreamSVF 6 | 7 | ## Or using openFPGALoader (https://trabucayre.github.io/openFPGALoader/guide/install.html): 8 | 9 | openfpgaloader -b ulx3s $bitstream 10 | 11 | ## To program the board using OpenOCD, use the command: 12 | 13 | openocd -f $interfaceConfig -f $boardConfig -c "transport select jtag; init; scan_chain; svf -quiet -progress $bitstreamSVF; exit" 14 | -------------------------------------------------------------------------------- /verilator/chiselv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "VToplevel.h" 3 | #include "verilated.h" 4 | #include "verilated_vcd_c.h" 5 | 6 | /* 7 | * Current simulation time 8 | * This is a 64-bit integer to reduce wrap over issues and 9 | * allow modulus. You can also use a double, if you wish. 10 | */ 11 | vluint64_t main_time = 0; 12 | 13 | /* 14 | * Called by $time in Verilog 15 | * converts to double, to match 16 | * what SystemC does 17 | */ 18 | double sc_time_stamp(void) 19 | { 20 | return main_time; 21 | } 22 | 23 | #if VM_TRACE 24 | VerilatedVcdC *tfp; 25 | #endif 26 | 27 | void tick(VToplevel *top) 28 | { 29 | top->clock = 1; 30 | top->eval(); 31 | #if VM_TRACE 32 | if (tfp) 33 | tfp->dump((double)main_time); 34 | #endif 35 | main_time++; 36 | 37 | top->clock = 0; 38 | top->eval(); 39 | #if VM_TRACE 40 | if (tfp) 41 | tfp->dump((double)main_time); 42 | #endif 43 | main_time++; 44 | } 45 | 46 | void uart_tx(unsigned char tx); 47 | unsigned char uart_rx(void); 48 | 49 | int main(int argc, char **argv) 50 | { 51 | Verilated::commandArgs(argc, argv); 52 | 53 | // init top verilog instance 54 | VToplevel *top = new VToplevel; 55 | 56 | #if VM_TRACE 57 | // init trace dump 58 | Verilated::traceEverOn(true); 59 | tfp = new VerilatedVcdC; 60 | top->trace(tfp, 99); 61 | tfp->open("ChiselV.vcd"); 62 | #endif 63 | 64 | // Reset 65 | top->reset = 1; 66 | for (unsigned long i = 0; i < 5; i++) 67 | tick(top); 68 | top->reset = 0; 69 | 70 | while (!Verilated::gotFinish()) 71 | { 72 | tick(top); 73 | // VL_PRINTF("GPIO %" VL_PRI64 "x\r\n", top->Toplevel__DOT__CPU__DOT__GPIO0__DOT__GPIO); 74 | 75 | uart_tx(top->UART0_tx); 76 | top->UART0_rx = uart_rx(); 77 | } 78 | 79 | #if VM_TRACE 80 | tfp->close(); 81 | delete tfp; 82 | #endif 83 | 84 | delete top; 85 | } 86 | -------------------------------------------------------------------------------- /verilator/uart.c: -------------------------------------------------------------------------------- 1 | // This UART driver for Verilator has been borrowed from Chiselwatt, an OpenPOWER 2 | // core created by Anton Blanchard: 3 | // https://github.com/antonblanchard/chiselwatt/blob/master/uart.c 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* Should we exit simulation on ctrl-c or pass it through? */ 14 | #define EXIT_ON_CTRL_C 15 | 16 | #define CLOCK 50000000L 17 | #define BAUD 115200 18 | /* Round to nearest */ 19 | #define BITWIDTH ((CLOCK+(BAUD/2))/BAUD) 20 | 21 | /* 22 | * Our UART uses 16x oversampling, so at 50 MHz and 115200 baud 23 | * each sample is: 50000000/(115200*16) = 27 clock cycles. This 24 | * means each bit is off by 0.47% so for 8 bits plus a start and 25 | * stop bit the errors add to be 4.7%. 26 | */ 27 | static double error = 0.05; 28 | 29 | enum state { 30 | IDLE, START_BIT, BITS, STOP_BIT, ERROR 31 | }; 32 | 33 | static enum state tx_state = IDLE; 34 | static unsigned long tx_countbits; 35 | static unsigned char tx_bits; 36 | static unsigned char tx_byte; 37 | static unsigned char tx_prev; 38 | 39 | /* 40 | * Return an error if the transition is not close enough to the start or 41 | * the end of an expected bit. 42 | */ 43 | static bool is_error(unsigned long bits) 44 | { 45 | double e = 1.0 * tx_countbits / BITWIDTH; 46 | 47 | if ((e <= (1.0-error)) && (e >= error)) 48 | return true; 49 | 50 | return false; 51 | } 52 | 53 | void uart_tx(unsigned char tx) 54 | { 55 | switch (tx_state) { 56 | case IDLE: 57 | if (tx == 0) { 58 | tx_state = START_BIT; 59 | tx_countbits = BITWIDTH; 60 | tx_bits = 0; 61 | tx_byte = 0; 62 | } 63 | break; 64 | 65 | case START_BIT: 66 | tx_countbits--; 67 | if (tx == 1) { 68 | if (is_error(tx_countbits)) { 69 | printf("START_BIT error %ld %ld\n", BITWIDTH, tx_countbits); 70 | tx_countbits = BITWIDTH*2; 71 | tx_state = ERROR; 72 | break; 73 | } 74 | } 75 | 76 | if (tx_countbits == 0) { 77 | tx_state = BITS; 78 | tx_countbits = BITWIDTH; 79 | } 80 | break; 81 | 82 | case BITS: 83 | tx_countbits--; 84 | if (tx_countbits == BITWIDTH/2) { 85 | tx_byte = tx_byte | (tx << tx_bits); 86 | tx_bits = tx_bits + 1; 87 | } 88 | 89 | if (tx != tx_prev) { 90 | if (is_error(tx_countbits)) { 91 | printf("BITS error %ld %ld\n", BITWIDTH, tx_countbits); 92 | tx_countbits = BITWIDTH*2; 93 | tx_state = ERROR; 94 | break; 95 | } 96 | } 97 | 98 | if (tx_countbits == 0) { 99 | if (tx_bits == 8) { 100 | tx_state = STOP_BIT; 101 | } 102 | tx_countbits = BITWIDTH; 103 | } 104 | break; 105 | 106 | case STOP_BIT: 107 | tx_countbits--; 108 | 109 | if (tx == 0) { 110 | if (is_error(tx_countbits)) { 111 | printf("STOP_BIT error %ld %ld\n", BITWIDTH, tx_countbits); 112 | tx_countbits = BITWIDTH*2; 113 | tx_state = ERROR; 114 | break; 115 | } 116 | /* Go straight to idle */ 117 | write(STDOUT_FILENO, &tx_byte, 1); 118 | tx_state = IDLE; 119 | } 120 | 121 | if (tx_countbits == 0) { 122 | write(STDOUT_FILENO, &tx_byte, 1); 123 | tx_state = IDLE; 124 | } 125 | break; 126 | 127 | case ERROR: 128 | tx_countbits--; 129 | if (tx_countbits == 0) { 130 | tx_state = IDLE; 131 | } 132 | 133 | break; 134 | } 135 | 136 | tx_prev = tx; 137 | } 138 | 139 | static struct termios oldt; 140 | 141 | static void disable_raw_mode(void) 142 | { 143 | tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 144 | } 145 | 146 | static void enable_raw_mode(void) 147 | { 148 | static bool initialized = false; 149 | 150 | if (!initialized) { 151 | static struct termios newt; 152 | 153 | tcgetattr(STDIN_FILENO, &oldt); 154 | newt = oldt; 155 | cfmakeraw(&newt); 156 | #ifdef EXIT_ON_CTRL_C 157 | newt.c_lflag |= ISIG; 158 | #endif 159 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); 160 | initialized = true; 161 | atexit(disable_raw_mode); 162 | } 163 | } 164 | 165 | static int nonblocking_read(unsigned char *c) 166 | { 167 | int ret; 168 | unsigned long val = 0; 169 | struct pollfd fdset[1]; 170 | 171 | enable_raw_mode(); 172 | 173 | memset(fdset, 0, sizeof(fdset)); 174 | 175 | fdset[0].fd = STDIN_FILENO; 176 | fdset[0].events = POLLIN; 177 | 178 | ret = poll(fdset, 1, 0); 179 | if (ret == 0) 180 | return false; 181 | 182 | ret = read(STDIN_FILENO, &val, 1); 183 | if (ret != 1) { 184 | fprintf(stderr, "%s: read of stdin returns %d\n", __func__, ret); 185 | exit(1); 186 | } 187 | 188 | if (ret == 1) { 189 | *c = val; 190 | return true; 191 | } else { 192 | return false; 193 | } 194 | } 195 | 196 | static enum state rx_state = IDLE; 197 | static unsigned char rx_char; 198 | static unsigned long rx_countbits; 199 | static unsigned char rx_bit; 200 | static unsigned char rx = 1; 201 | 202 | /* Avoid calling poll() too much */ 203 | #define RX_INTERVAL 10000 204 | static unsigned long rx_sometimes; 205 | 206 | unsigned char uart_rx(void) 207 | { 208 | unsigned char c; 209 | 210 | switch (rx_state) { 211 | case IDLE: 212 | if (rx_sometimes++ >= RX_INTERVAL) { 213 | rx_sometimes = 0; 214 | 215 | if (nonblocking_read(&c)) { 216 | rx_state = START_BIT; 217 | rx_char = c; 218 | rx_countbits = BITWIDTH; 219 | rx_bit = 0; 220 | rx = 0; 221 | } 222 | } 223 | 224 | break; 225 | 226 | case START_BIT: 227 | rx_countbits--; 228 | if (rx_countbits == 0) { 229 | rx_state = BITS; 230 | rx_countbits = BITWIDTH; 231 | rx = rx_char & 1; 232 | } 233 | break; 234 | 235 | case BITS: 236 | rx_countbits--; 237 | if (rx_countbits == 0) { 238 | rx_bit = rx_bit + 1; 239 | if (rx_bit == 8) { 240 | rx = 1; 241 | rx_state = STOP_BIT; 242 | } else { 243 | rx = (rx_char >> rx_bit) & 1; 244 | } 245 | rx_countbits = BITWIDTH; 246 | } 247 | break; 248 | 249 | case STOP_BIT: 250 | rx_countbits--; 251 | if (rx_countbits == 0) { 252 | rx_state = IDLE; 253 | } 254 | break; 255 | case ERROR: 256 | break; 257 | } 258 | 259 | return rx; 260 | } 261 | --------------------------------------------------------------------------------