# Analyze spu32 with Yosys open synthesis suite <!--. Explain how it works and validate it--> ###### tags: `computer architure 2021`、`final project` ###### contributed by ```劉品宏 朱俊霖 伍志忠 鄒柏宇``` ## Build environment? * Install Yosys,Verilator,riscv64 `$ sudo apt install yosys verilator` * Build risv32 toolchain `$ git clone https://github.com/riscv/riscv-gnu-toolchain` `$ sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev` ``./configure --with-multilib-generator="rv32i-ilp32--" --prefix=/opt/riscv32`` `sudo make` `export RISCV32=/opt/riscv32` `export PATH=$RISCV32/bin:$PATH` * Clone SPU32 `$ git clone https://github.com/maikmerten/spu32.git` `make` ## spu32 * spu32 ("Small Processing Unit 32"), a compact RISC-V processor implementing the RV32I instruction set. * spu32 is writting in Verilog is designed to be synthesizable using the open-source Yosys open synthesis suite. * spu32 statistics ``` 2.44. Printing statistics. === spu32_cpu === Number of wires: 1226 Number of wire bits: 3689 Number of public wires: 181 Number of public wire bits: 2334 Number of memories: 0 Number of memory bits: 0 Number of processes: 0 Number of cells: 2208 SB_CARRY 155 SB_DFF 30 SB_DFFE 245 SB_DFFESR 79 SB_DFFESS 1 SB_DFFN 2 SB_DFFNE 132 SB_DFFNESR 6 SB_DFFNSR 9 SB_DFFSR 1 SB_LUT4 1544 SB_RAM40_4K 4 ``` * Vectors of spu32 - ```VECTOR_RESET```: The memory address where the CPU will start execution after reset. By default set to ```0x00000000```. - ```VECTOR_EXCEPTION```: The memory address where the CPU will jump to to handle interrupts. By default set to ```0x00000010```. ## Yosys * A framework for RTL synthesis tools. ### Setup * clone Yosys ```shell= git clone https://github.com/YosysHQ/yosys ``` * Install the prerequisites for building yosys ```shell= sudo apt-get install build-essential clang bison flex \ libreadline-dev gawk tcl-dev libffi-dev git \ graphviz xdot pkg-config python3 libboost-system-dev \ libboost-python-dev libboost-filesystem-dev zlib1g-dev ``` * To configure the build system to use a specific compiler ```shell= make config-gcc ``` * Build Yosys and test ```shell= make sudo make install make test ``` * test result ```shell= Expected error pattern 'Local declaration in unnamed block is only supported in SystemVerilog mode!' found !!! Passed unnamed_block.ys Passed unnamed_genblk.ys Passed upto.ys Warning: wire '\wire_1' is assigned in a block at wire_and_var.sv:21.41-21.51. Warning: reg '\reg_2' is assigned in a continuous assignment at wire_and_var.sv:22.57-22.66. Warning: reg '\var_reg_2' is assigned in a continuous assignment at wire_and_var.sv:26.77-26.90. Warning: wire '\wire_logic_1' is assigned in a block at wire_and_var.sv:30.65-30.81. Warning: wire '\wire_integer_1' is assigned in a block at wire_and_var.sv:31.73-31.91. Passed wire_and_var.ys make[1]: Leaving directory '/home/rep/yosys/tests/verilog' Passed "make test". ``` ## Use Yosys open synthesis suite ### Reading and Elaborating the design using the Verilog frontend ```shell= cd spu32 //enter spu32 file yosys read -sv cpu/cpu.v ``` * Take ```cpu.v```for example, if we want to elaborate the design, we need to use the above instruction to parse to AST. * And yosys will also parse all Verilog file include from ```cpu.v``` to AST. :::spoiler Result(read -sv cpu/cpu.v) ```shell= 3. Executing Verilog-2005 frontend: cpu/cpu.v Parsing SystemVerilog input from `cpu/cpu.v' to AST representation. Storing AST representation for module `$abstract\spu32_cpu_mul'. Storing AST representation for module `$abstract\spu32_cpu_shifter'. Storing AST representation for module `$abstract\spu32_cpu_alu'. Storing AST representation for module `$abstract\spu32_cpu_branch'. Storing AST representation for module `$abstract\spu32_cpu_bus'. Storing AST representation for module `$abstract\spu32_cpu_decoder'. Storing AST representation for module `$abstract\spu32_cpu_registers'. Storing AST representation for module `$abstract\spu32_cpu'. Successfully finished Verilog frontend. ``` * Analyze design hierarchy ```shell= yosys> hierarchy -top spu32_cpu ``` :::spoiler Result(hierarchy -top spu32_cpu) ```shell= 3. Executing HIERARCHY pass (managing design hierarchy). 4. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu'. Generating RTLIL representation for module `\spu32_cpu'. 4.1. Analyzing design hierarchy.. Top module: \spu32_cpu 4.2. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu_branch'. Generating RTLIL representation for module `\spu32_cpu_branch'. 4.3. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu_registers'. Generating RTLIL representation for module `\spu32_cpu_registers'. 4.4. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu_decoder'. Generating RTLIL representation for module `\spu32_cpu_decoder'. 4.5. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu_bus'. Generating RTLIL representation for module `\spu32_cpu_bus'. 4.6. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu_alu'. Generating RTLIL representation for module `\spu32_cpu_alu'. 4.7. Analyzing design hierarchy.. Top module: \spu32_cpu Used module: \spu32_cpu_branch Used module: \spu32_cpu_registers Used module: \spu32_cpu_decoder Used module: \spu32_cpu_bus Used module: \spu32_cpu_alu 4.8. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu_shifter'. Generating RTLIL representation for module `\spu32_cpu_shifter'. 4.9. Executing AST frontend in derive mode using pre-parsed AST for module `\spu32_cpu_mul'. Generating RTLIL representation for module `\spu32_cpu_mul'. 4.10. Analyzing design hierarchy.. Top module: \spu32_cpu Used module: \spu32_cpu_branch Used module: \spu32_cpu_registers Used module: \spu32_cpu_decoder Used module: \spu32_cpu_bus Used module: \spu32_cpu_alu Used module: \spu32_cpu_shifter Used module: \spu32_cpu_mul 4.11. Analyzing design hierarchy.. Top module: \spu32_cpu Used module: \spu32_cpu_branch Used module: \spu32_cpu_registers Used module: \spu32_cpu_decoder Used module: \spu32_cpu_bus Used module: \spu32_cpu_alu Used module: \spu32_cpu_shifter Used module: \spu32_cpu_mul Removing unused module `$abstract\spu32_cpu'. Removing unused module `$abstract\spu32_cpu_registers'. Removing unused module `$abstract\spu32_cpu_decoder'. Removing unused module `$abstract\spu32_cpu_bus'. Removing unused module `$abstract\spu32_cpu_branch'. Removing unused module `$abstract\spu32_cpu_alu'. Removing unused module `$abstract\spu32_cpu_shifter'. Removing unused module `$abstract\spu32_cpu_mul'. Removed 8 unused modules. ``` ::: ```shell= yosys> write_ilang ``` :::spoiler Result(write_ilang) ```shell= 4. Executing RTLIL backend. Output filename: <stdout> . . . connect \output_reversed [18] \rshift0 [13] connect \output_reversed [19] \rshift0 [12] connect \output_reversed [20] \rshift0 [11] connect \output_reversed [21] \rshift0 [10] connect \output_reversed [22] \rshift0 [9] connect \output_reversed [23] \rshift0 [8] connect \output_reversed [24] \rshift0 [7] connect \output_reversed [25] \rshift0 [6] connect \output_reversed [26] \rshift0 [5] connect \output_reversed [27] \rshift0 [4] connect \output_reversed [28] \rshift0 [3] connect \output_reversed [29] \rshift0 [2] connect \output_reversed [30] \rshift0 [1] connect \output_reversed [31] \rshift0 [0] end ``` ::: ---- * Executing PROC pass ,convert processes to netlists and perform some simple optimizations. ```shell= yosys> proc; opt ``` :::spoiler Result(proc; opt) ```shell= 6.22. Executing OPT_EXPR pass (perform const folding). Optimizing module spu32_cpu. Optimizing module spu32_cpu_alu. Optimizing module spu32_cpu_branch. Optimizing module spu32_cpu_bus. Optimizing module spu32_cpu_decoder. Optimizing module spu32_cpu_mul. Optimizing module spu32_cpu_registers. Optimizing module spu32_cpu_shifter. 6.23. Finished OPT passes. (There is nothing left to do.) ``` ::: ---- * Show design netlist ```shell= yosys> show ``` :::spoiler Result(show) ```shell= 7. Generating Graphviz representation of design. ERROR: For formats different than 'ps' or 'dot' only one module must be selected. ``` ::: ```shell= yosys> show -format ps -viewer gv ``` :::spoiler Result(show -format ps -viewer gv) ```shell= 8. Generating Graphviz representation of design. Writing dot description to `/home/pinhong/.yosys_show.dot'. Dumping module spu32_cpu to page 1. Dumping module spu32_cpu_alu to page 2. Dumping module spu32_cpu_branch to page 3. Dumping module spu32_cpu_bus to page 4. Dumping module spu32_cpu_decoder to page 5. Dumping module spu32_cpu_mul to page 6. Dumping module spu32_cpu_registers to page 7. Dumping module spu32_cpu_shifter to page 8. Exec: dot -Tps '/home/pinhong/.yosys_show.dot' > '/home/pinhong/.yosys_show.ps.new' && mv '/home/pinhong/.yosys_show.ps.new' '/home/pinhong/.yosys_show.ps' Exec: gv '/home/pinhong/.yosys_show.ps' & sh: 1: gv: not found ``` ::: --- * Can map to internal cell library and do some simple optimizations ```shell= yosys> techmap; opt ``` :::spoiler Result (techmap; opt) ```shell= 10.22. Executing OPT_EXPR pass (perform const folding). Optimizing module spu32_cpu. Optimizing module spu32_cpu_alu. Optimizing module spu32_cpu_branch. Optimizing module spu32_cpu_bus. Optimizing module spu32_cpu_decoder. Optimizing module spu32_cpu_mul. Optimizing module spu32_cpu_registers. Optimizing module spu32_cpu_shifter. 10.23. Finished OPT passes. (There is nothing left to do.) ``` ::: ---- * Can write the synthesized design ```shell= yosys> write_verilog synth.v ``` :::spoiler Result (write_verilog synth.v) ```shell= 11. Executing Verilog backend. Dumping module `\spu32_cpu'. Dumping module `\spu32_cpu_alu'. Dumping module `\spu32_cpu_branch'. Dumping module `\spu32_cpu_bus'. Dumping module `\spu32_cpu_decoder'. Dumping module `\spu32_cpu_mul'. Dumping module `\spu32_cpu_registers'. Dumping module `\spu32_cpu_shifter'. ``` ::: ---- ### Analysis * Yosys is the RTL synthesis tool, and it has extensive verilog-2005 support . * You can write the verilog code and then synthesis your verilog code with Yosys. * Next, we will synthesis ```SPU32``` with ```Yosys```. * SPU32 is the RISC-V processor and it implements the RV32I instruction set. * An overview of the SoC of SPU32 is follows. ![](https://i.imgur.com/K8CqRUA.png) * From above diagram, you can observe some peripherals clearly. * Create SRV32's top.v circuit digram ```shell= yosys> read_verilog boards/icebreaker/top.v ``` :::spoiler Result (read_verilog boards/icebreaker/top.v) ```shell= 1. Executing Verilog-2005 frontend: boards/icebreaker/top.v Parsing Verilog input from `boards/icebreaker/top.v' to AST representation. Generating RTLIL representation for module `\spu32_cpu_mul'. Generating RTLIL representation for module `\spu32_cpu_shifter'. Generating RTLIL representation for module `\spu32_cpu_alu'. Generating RTLIL representation for module `\spu32_cpu_branch'. Generating RTLIL representation for module `\spu32_cpu_bus'. Generating RTLIL representation for module `\spu32_cpu_decoder'. Generating RTLIL representation for module `\spu32_cpu_registers'. Generating RTLIL representation for module `\spu32_cpu'. Generating RTLIL representation for module `\spu32_bus_wishbone8'. Generating RTLIL representation for module `\leds_wb8'. Generating RTLIL representation for module `\uart_wb8'. Generating RTLIL representation for module `\spicontroller'. Generating RTLIL representation for module `\spi_wb8'. Generating RTLIL representation for module `\timer_wb8'. Generating RTLIL representation for module `\dummy_wb8'. Generating RTLIL representation for module `\ice40_spram_1mbit_wb8_vga'. Generating RTLIL representation for module `\rom_wb8'. Generating RTLIL representation for module `\prng_wb8'. Generating RTLIL representation for module `\vga_mode_generator'. Generating RTLIL representation for module `\vga_sync'. Generating RTLIL representation for module `\vga_pixelpipe_test'. Generating RTLIL representation for module `\vga_pixelpipe_text'. Generating RTLIL representation for module `\vga_pixelpipe_bitmap'. Generating RTLIL representation for module `\vga_palette'. Generating RTLIL representation for module `\vga'. Generating RTLIL representation for module `\vga_wb8_extram'. Generating RTLIL representation for module `\top'. Successfully finished Verilog frontend. ``` ::: ```shell= yosys> show -format ps ``` Then, the file ".yosys_show.dot" and ".yosys_show.ps" will be generated. ![](https://i.imgur.com/NHthnVs.png) * This circuit diagram includes ```cpu```,```ram```,```rom```,```bus``` and ```some peripherals```. * If you carefully see the circuit diagram from yosys, you will understand the relation between the different modules in SPU32. The below screenshot is the part of SPU32'SoC. Besides, it also represents ```the cpu of SPU32 ```. ![](https://i.imgur.com/N5V2GHZ.png) * So, you also can know how the cpu relate to other modules in SPU32. --- * Create cpu's circuit digram ```shell= yosys> read_verilog cpu/cpu.v yosys> opt yosys> show -format ps ``` It will generate the file ".yosys_show.dot" and ".yosys_show.ps". ".yosys_show.ps" as follows ![](https://i.imgur.com/K1Khc7A.png) * When I have entered some command about simple optimization, it will generate new cpu's circuit diagram. ![](https://i.imgur.com/79Vy5mC.png) Apparently, the above two cpu's circuit diagrams is different. --- ## Verilator * Verilator officially claims it is the the fastest Verilog/SystemVerilog simulator. ### What Verilator does * Invoked with parameters similar to GCC or Synopsys's VCS. * Specify Verilog or SystemVerilog code by reading it, performing lint checks, and optionally inserting assertion checks and coverage-analysis points. * It outputs single- or multi-threaded .cpp and .h files, the "Verilated" code. ### Different from NC-verilog and VCS * We need to use C++ to write ```testbench``` in Verilator instead of Verilog/SystemVerilog in NC-verilog、VCS. * Steps of NC-verilog、VCS simulation: - write ```testbench.v``` - prepare synthesizable module```design_under_test.v``` - execute simulation ```ncverilog testbench.v design_under_test.v``` - this step will translate ```testbench.v``` ```design_under_test.v``` to C++ or directly to binary. - NC-verilog will generate a ```INCA_libs``` directory. - VCS will generate a ```vsim``` binary. * Steps of **Verilator** simulation - write ```testbench.cpp``` - prepare synthesizable module```design_under_test.v``` - translate module to C++(or system C) ```verilator design_under_test.v --exe testbench.cpp --cc``` - generate ```obj_dir``` directory - in ```obj_dir```, compile and generate binary ```make -C obj_dir -f Vdesign_under_test.mk``` - execute simulation ```./obj_dir/Vdesign_under_test``` ### Use Verilator on spu32 * If we want to generate ```obj_dir``` in spu32 and translate ```cpu.v``` to SystemC or C++, we need to use the following instruction. ```shell= cd spu32 verilator cpu/cpu.v --sc //--sc for SystemC, --cc for C++ ``` * ```obj_dir``` ![](https://i.imgur.com/SCY4PKK.png) #### Now we add testbench. * First, because the testbench of Verilator only accepts ```cpp``` format, we need to translate the original ```testbench.v``` to ```testbench.cpp``` * For example, if we want to analyze alu of spu32, we need to translate```spu32/cpu/tests/alu_tb.v``` and ```spu/tb/tbcommon.v``` :::spoiler tb_common.v `ifndef TBCOMMON `define TBCOMMON 1 parameter CLKPERIOD = 2; reg clk = 0; always # (CLKPERIOD / 2) clk = !clk; integer error = 0; always @(error) begin if(error !== 0) begin $display("!!! FINISHING WITH ERROR, TESTCASE %0d FAILED!", error); # (CLKPERIOD * 2); $finish_and_return(1); end end `endif ::: :::spoiler alu_tb.v ```shell= `include "./cpu/aludefs.vh" `include "./cpu/alu.v" module alu_tb; `include "./tb/tbcommon.v" reg en = 0; reg reset = 0; reg[31:0] dataS1, dataS2; reg[3:0] aluop; wire busy, lt, ltu, eq; wire[31:0] data; spu32_cpu_alu mut( .I_clk(clk), .I_en(en), .I_reset(reset), .I_dataS1(dataS1), .I_dataS2(dataS2), .I_aluop(aluop), .O_busy(busy), .O_data(data), .O_lt(lt), .O_ltu(ltu), .O_eq(eq) ); initial begin $dumpfile("./cpu/tests/alu_tb.lxt"); $dumpvars(0, error, clk, en, reset, dataS1, dataS2, aluop, busy, data, lt, ltu, eq); // testcase 1 @(negedge clk); en = 1; aluop = `ALUOP_ADD; dataS1 = 40; dataS2 = 2; @(negedge clk); if(data !== 42) error <= 1; // testcase 2 dataS1 = 44; dataS2 = -2; @(negedge clk); if(data !== 42) error <= 2; // testcase 3 dataS1 = 1; dataS2 = 3; aluop = `ALUOP_SLL; @(negedge busy); @(negedge clk); if(data !== 8) error <= 3; // testcase 4 dataS1 = 32'hFFFFFFFF; dataS2 = 8; aluop = `ALUOP_SRL; @(negedge busy); @(negedge clk); if(data !== 32'h00FFFFFF) error <= 4; // testcase 5 dataS1 = 32'h80000000; dataS2 = 3; aluop = `ALUOP_SRA; @(negedge busy); @(negedge clk); if(data != 32'hF0000000) error <= 5; // testcase 6, 7, 8 dataS1 = 1337; dataS2 = 1337; aluop = `ALUOP_ADD; @(negedge clk); if(eq !== 1) error <= 6; if(lt !== 0) error <= 7; if(ltu !== 0) error <= 8; // testcase 9, 10, 11 dataS1 = -5; dataS2 = 5; aluop = `ALUOP_ADD; @(negedge clk); if(eq !== 0) error <= 9; if(lt !== 1) error <= 10; if(ltu !== 0) error <= 11; // testcase 12, 13, 14 dataS1 = 5; dataS2 = -5; aluop = `ALUOP_ADD; @(negedge clk); if(eq !== 0) error <= 12; if(lt !== 0) error <= 13; if(ltu !== 1) error <= 14; // testcase 15 dataS1 = 32'h000000FF; dataS2 = 32'h00000FFF; aluop = `ALUOP_XOR; @(negedge clk); if(data !== 32'h00000F00) error <= 15; // testcase 16 dataS1 = 32'h000000FF; dataS2 = 32'h00000FFF; aluop = `ALUOP_OR; @(negedge clk); if(data !== 32'h00000FFF) error <= 16; // testcase 17 dataS1 = 32'h000000FF; dataS2 = 32'h00000FFF; aluop = `ALUOP_AND; @(negedge clk); if(data !== 32'h000000FF) error <= 17; // testcase 18 dataS1 = 8; dataS2 = -2; aluop = `ALUOP_SUB; @(negedge clk); if(data != 10) error <= 18; // testcase 19 dataS1 = -2; dataS2 = 13; aluop = `ALUOP_SUB; @(negedge clk); if(data != -15) error <= 19; // testcase 20 dataS1 = 1337; dataS2 = 337; aluop = `ALUOP_SUB; @(negedge clk); if(data != 1000) error <= 20; #(3 * CLKPERIOD); $finish; end endmodule ``` ::: * we combine the above two files and translate to SystemC. :::spoiler sc_main.cpp ```shell= #include "Valu.h" #include <memory> #include <iostream> #include <systemc> using namespace sc_core; SC_MODULE(Testbench) { sc_clock clk; sc_signal<bool> reset; sc_signal<bool> en; sc_signal<bool> valid; sc_signal<unsigned> dataS1; sc_signal<unsigned> dataS2; sc_signal<bool>busy; sc_signal<bool>lt; sc_signal<bool>ltu; sc_signal<sc_int<1>>eq; public: SC_HAS_PROCESS(Testbench); Testbench( const sc_module_name &name, Valu *dut ): sc_module(name) { dut->clk(clk); dut->reset(rst); dut->valid(valid); dut->data(data); } }; Testbench( const sc_module_name &name, Valu *dut ): sc_mudule(name), clk("clk", 1.0,SC_NS){ dut->clk(clk); dut->reset(reset); dut->valid(valid); dut->data(data); SC_THREAD(Reset); SC_THREAD(Monitor); } int sc_main(int, char**) { std::unique_ptr<Valu> dut (new Valu)); sc_start(100.0,SC_NS); sc_start(100.0, SC_NS); return 0; } void Reset() { reset.write(true); // initial begin rst = 1; wait(5.0, SC_NS); // #5 reset.write(false); // rst = 1 wait(5.0, SC_NS); // #5 reset.write(true); // rst = 0 end } void Monitor() { wait(reset.negedge_event()); // @(negedge rst) wait(reset.posedge_event()); // @(posedge rst) while (true) { // forever begin wait(clk.posedge_event()); // @(posedge clk) if (valid.read()) std::cout << char(data.read()) << std::endl; } // end } ``` * 2 SC_THREAD, one is to drive the reset signal Reset(),another is to check the output data Monitor() ``` void Monitor() { wait(reset.negedge_event()); // @(negedge rst) wait(reset.posedge_event()); // @(posedge rst) while (true) { // forever begin wait(clk.posedge_event()); // @(posedge clk) if (valid.read()) std::cout << char(data.read()) << std::endl; } // end ``` * you can think Monitor part as the part of verilog's testbench's initial block * in this Monitor code , it almost equivalant to two initial block in verilog ``` void Reset() { reset.write(true); // initial begin rst = 1; wait(5.0, SC_NS); // #5 reset.write(false); // rst = 1 wait(5.0, SC_NS); // #5 reset.write(true); // rst = 0 end } ``` * in Reset(),the code will check every cycle. * But I think in Reset() code,it may has some mistake since it still has some part that i didn't consider about according to the version of verilog testbench alu_tb.v. * Cause this is our first time to the SystemC so many thins we still cant figure it out, as the result , this testbench writed in SystemC probably cant work will. * about SC_THREAD, I'm still figure it out how to use it,now i use it to suspend simulation through wait(). ::: #### GTKwave * We try to use wave to see the dataflow in spu32. ```shell= iverilog cpu/tests/alu_tb.v ./a.out ``` ![](https://i.imgur.com/Mjcda14.png) but the terminal stacks at generating alu_tb.lxt which is the wave to debug alu module, we thought it might be because the lxt file is too large. * Therefore, we might have to contact the author of spu32 how to solve this problem. ### Building tests #### testgen `make all` will get `testsuite.dat` for test #### spu32-system tried run make , but we got ``` riscv32-unknown-elf-gcc : command not found ``` We found we need to add ` -march=rv32i -mabi=ilp32`behind riscv64-unknown-elf-gcc, so we tried edit `Makefile.vars` ``` RV_GCC=riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 RV_OBJCOPY=riscv64-unknown-elf-objcopy RV_OBJDUMP=riscv64-unknown-elf-objdump RV_AR=riscv64-unknown-elf-ar ``` but we still got error on merge files, and we could't add -march=rv32i -mabi=ilp32 on other command, so we tried rebuild riscv-gnu-toolchain. got `bootbios.img` #### serial-uploader `make` it seems it can be use to transmit data via usb port.(UART) #### filesrv `make` it seems it can be use to transmit file via usb port. #### c-firmware `make` ``` fatal error: libtinyc.h: No such file or directory ``` In make file it says ``` LDFLAGS=-L./libtinyc -ltinyc -L./libspu32 -lspu32 -Tlink.ld -Xlinker --gc-sections # useful additions for LDFLAGS if linking fails: -Xlinker --verbose ``` But the error still there after we add it. find that file in other folder, so we copy it and edit path to there. `cp ../spu32-system/{libtinyc,libspu32,bios_calls,bios} -r .` Then we got ``` riscv64-unknown-elf-gcc -I./libtinyc -I./libspu32 -march=rv32im -mno-div -mabi=ilp32 -static -nostdlib -fno-builtin-printf -Os -fPIC -fdata-sections -ffunction-sections -o example.elf crt0.s example.o -L./libtinyc -ltinyc -L./libspu32 -lspu32 -Tlink.ld -Xlinker --gc-sections /usr/local/lib/gcc/riscv64-unknown-elf/11.1.0/../../../../riscv64-unknown-elf/bin/ld: /usr/local/lib/gcc/riscv64-unknown-elf/11.1.0/libgcc.a(div.o): ABI is incompatible with that of the selected emulation: target emulation `elf64-littleriscv' does not match `elf32-littleriscv' ``` I build another riscv-gnu-toolchain to fix this. ``` ./configure --prefix=/opt/riscv --enable-multilib `sudo make` export RISCV3/opt/riscv export PATH=$RISCV/bin:$PATH ``` then I got ``` example.c:23:60: warning: implicit declaration of function 'string_length' [-Wimplicit-function-declaration] undefined reference to `string_length' ``` So I edit it into strlen then I got the last error `make: *** No rule to make target 'chainreaction.bin', needed by 'all'. Stop.` :::spoiler ``` cd libtinyc && make make[1]: Entering directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libtinyc' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libtinyc' cd libspu32 && make make[1]: Entering directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libspu32' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libspu32' riscv64-unknown-elf-gcc -I./libtinyc -I./libspu32 -march=rv32im -mno-div -mabi=ilp32 -static -nostdlib -fno-builtin-printf -Os -fPIC -fdata-sections -ffunction-sections -c example.c riscv64-unknown-elf-gcc -I./libtinyc -I./libspu32 -march=rv32im -mno-div -mabi=ilp32 -static -nostdlib -fno-builtin-printf -Os -fPIC -fdata-sections -ffunction-sections -o example.elf crt0.s example.o -L./libtinyc -ltinyc -L./libspu32 -lspu32 -Tlink.ld -Xlinker --gc-sections riscv64-unknown-elf-objdump -d example.elf example.elf: file format elf32-littleriscv Disassembly of section .text: 00000000 <_ftext>: 0: 0140006f j 14 <_init> ... 00000010 <_interrupt>: 10: 0000006f j 10 <_interrupt> 00000014 <_init>: 14: 00080137 lui sp,0x80 18: 154000ef jal ra,16c <main> 1c: fe5ff06f j 0 <_ftext> 00000020 <__divsi3>: 20: 06054063 bltz a0,80 <__umodsi3+0x10> 24: 0605c663 bltz a1,90 <__umodsi3+0x20> 00000028 <__udivsi3>: 28: 00058613 mv a2,a1 2c: 00050593 mv a1,a0 30: fff00513 li a0,-1 34: 02060c63 beqz a2,6c <__udivsi3+0x44> 38: 00100693 li a3,1 3c: 00b67a63 bgeu a2,a1,50 <__udivsi3+0x28> 40: 00c05863 blez a2,50 <__udivsi3+0x28> 44: 00161613 slli a2,a2,0x1 48: 00169693 slli a3,a3,0x1 4c: feb66ae3 bltu a2,a1,40 <__udivsi3+0x18> 50: 00000513 li a0,0 54: 00c5e663 bltu a1,a2,60 <__udivsi3+0x38> 58: 40c585b3 sub a1,a1,a2 5c: 00d56533 or a0,a0,a3 60: 0016d693 srli a3,a3,0x1 64: 00165613 srli a2,a2,0x1 68: fe0696e3 bnez a3,54 <__udivsi3+0x2c> 6c: 00008067 ret 00000070 <__umodsi3>: 70: 00008293 mv t0,ra 74: fb5ff0ef jal ra,28 <__udivsi3> 78: 00058513 mv a0,a1 7c: 00028067 jr t0 80: 40a00533 neg a0,a0 84: 00b04863 bgtz a1,94 <__umodsi3+0x24> 88: 40b005b3 neg a1,a1 8c: f9dff06f j 28 <__udivsi3> 90: 40b005b3 neg a1,a1 94: 00008293 mv t0,ra 98: f91ff0ef jal ra,28 <__udivsi3> 9c: 40a00533 neg a0,a0 a0: 00028067 jr t0 000000a4 <__modsi3>: a4: 00008293 mv t0,ra a8: 0005ca63 bltz a1,bc <__modsi3+0x18> ac: 00054c63 bltz a0,c4 <__modsi3+0x20> b0: f79ff0ef jal ra,28 <__udivsi3> b4: 00058513 mv a0,a1 b8: 00028067 jr t0 bc: 40b005b3 neg a1,a1 c0: fe0558e3 bgez a0,b0 <__modsi3+0xc> c4: 40a00533 neg a0,a0 c8: f61ff0ef jal ra,28 <__udivsi3> cc: 40b00533 neg a0,a1 d0: 00028067 jr t0 000000d4 <isr>: d4: fc010113 addi sp,sp,-64 # 7ffc0 <//.+0x6ffc0> d8: 02a12623 sw a0,44(sp) dc: 00000517 auipc a0,0x0 e0: 75c50513 addi a0,a0,1884 # 838 <disable_interrupt+0x1c> e4: 02112e23 sw ra,60(sp) e8: 02512c23 sw t0,56(sp) ec: 02612a23 sw t1,52(sp) f0: 02712823 sw t2,48(sp) f4: 02b12423 sw a1,40(sp) f8: 02c12223 sw a2,36(sp) fc: 02d12023 sw a3,32(sp) 100: 00e12e23 sw a4,28(sp) 104: 00f12c23 sw a5,24(sp) 108: 01012a23 sw a6,20(sp) 10c: 01112823 sw a7,16(sp) 110: 01c12623 sw t3,12(sp) 114: 01d12423 sw t4,8(sp) 118: 01e12223 sw t5,4(sp) 11c: 01f12023 sw t6,0(sp) 120: 3cc000ef jal ra,4ec <printf> 124: 03c12083 lw ra,60(sp) 128: 03812283 lw t0,56(sp) 12c: 03412303 lw t1,52(sp) 130: 03012383 lw t2,48(sp) 134: 02c12503 lw a0,44(sp) 138: 02812583 lw a1,40(sp) 13c: 02412603 lw a2,36(sp) 140: 02012683 lw a3,32(sp) 144: 01c12703 lw a4,28(sp) 148: 01812783 lw a5,24(sp) 14c: 01412803 lw a6,20(sp) 150: 01012883 lw a7,16(sp) 154: 00c12e03 lw t3,12(sp) 158: 00812e83 lw t4,8(sp) 15c: 00412f03 lw t5,4(sp) 160: 00012f83 lw t6,0(sp) 164: 04010113 addi sp,sp,64 168: 30200073 mret 0000016c <main>: 16c: fc010113 addi sp,sp,-64 170: 02812c23 sw s0,56(sp) 174: 03212823 sw s2,48(sp) 178: 03312623 sw s3,44(sp) 17c: 03412423 sw s4,40(sp) 180: 03512223 sw s5,36(sp) 184: 03612023 sw s6,32(sp) 188: 01712e23 sw s7,28(sp) 18c: 01812c23 sw s8,24(sp) 190: 01912a23 sw s9,20(sp) 194: 02112e23 sw ra,60(sp) 198: 02912a23 sw s1,52(sp) 19c: 00000913 li s2,0 1a0: 00000c97 auipc s9,0x0 1a4: 6a0c8c93 addi s9,s9,1696 # 840 <disable_interrupt+0x24> 1a8: 00010413 mv s0,sp 1ac: 00000c17 auipc s8,0x0 1b0: 7acc0c13 addi s8,s8,1964 # 958 <disable_interrupt+0x13c> 1b4: 00000b97 auipc s7,0x0 1b8: 698b8b93 addi s7,s7,1688 # 84c <disable_interrupt+0x30> 1bc: 00000b17 auipc s6,0x0 1c0: 69cb0b13 addi s6,s6,1692 # 858 <disable_interrupt+0x3c> 1c4: 00000a97 auipc s5,0x0 1c8: 6b4a8a93 addi s5,s5,1716 # 878 <disable_interrupt+0x5c> 1cc: 00000a17 auipc s4,0x0 1d0: 6d4a0a13 addi s4,s4,1748 # 8a0 <disable_interrupt+0x84> 1d4: 00000997 auipc s3,0x0 1d8: 71898993 addi s3,s3,1816 # 8ec <disable_interrupt+0xd0> 1dc: 000c8513 mv a0,s9 1e0: 30c000ef jal ra,4ec <printf> 1e4: 00100613 li a2,1 1e8: 01000593 li a1,16 1ec: 00040513 mv a0,s0 1f0: 3f4000ef jal ra,5e4 <read_string> 1f4: 000c0513 mv a0,s8 1f8: 2f4000ef jal ra,4ec <printf> 1fc: 00040513 mv a0,s0 200: 248000ef jal ra,448 <parse_int> 204: 00050493 mv s1,a0 208: 00040593 mv a1,s0 20c: 000b8513 mv a0,s7 210: 2dc000ef jal ra,4ec <printf> 214: 00040513 mv a0,s0 218: 4a0000ef jal ra,6b8 <strlen> 21c: 00050593 mv a1,a0 220: 000b0513 mv a0,s6 224: 2c8000ef jal ra,4ec <printf> 228: 00048593 mv a1,s1 22c: 000a8513 mv a0,s5 230: 2bc000ef jal ra,4ec <printf> 234: 5a0000ef jal ra,7d4 <read_msr_evect> 238: 00050593 mv a1,a0 23c: 000a0513 mv a0,s4 240: 2ac000ef jal ra,4ec <printf> 244: 00048513 mv a0,s1 248: 594000ef jal ra,7dc <write_msr_evect> 24c: 00050613 mv a2,a0 250: 00048593 mv a1,s1 254: 00000517 auipc a0,0x0 258: 66c50513 addi a0,a0,1644 # 8c0 <disable_interrupt+0xa4> 25c: 290000ef jal ra,4ec <printf> 260: 584000ef jal ra,7e4 <get_interrupt_enabled> 264: 00050593 mv a1,a0 268: 00098513 mv a0,s3 26c: 280000ef jal ra,4ec <printf> 270: 590000ef jal ra,800 <enable_interrupt> 274: 570000ef jal ra,7e4 <get_interrupt_enabled> 278: 00050593 mv a1,a0 27c: 00098513 mv a0,s3 280: 26c000ef jal ra,4ec <printf> 284: 598000ef jal ra,81c <disable_interrupt> 288: 55c000ef jal ra,7e4 <get_interrupt_enabled> 28c: 00050593 mv a1,a0 290: 00098513 mv a0,s3 294: 258000ef jal ra,4ec <printf> 298: 00000597 auipc a1,0x0 29c: 6cc5a583 lw a1,1740(a1) # 964 <_GLOBAL_OFFSET_TABLE_+0x4> 2a0: 00000517 auipc a0,0x0 2a4: 66450513 addi a0,a0,1636 # 904 <disable_interrupt+0xe8> 2a8: 244000ef jal ra,4ec <printf> 2ac: 00040593 mv a1,s0 2b0: 00000517 auipc a0,0x0 2b4: 66c50513 addi a0,a0,1644 # 91c <disable_interrupt+0x100> 2b8: 420000ef jal ra,6d8 <strcmp> 2bc: 00050593 mv a1,a0 2c0: 00000517 auipc a0,0x0 2c4: 66450513 addi a0,a0,1636 # 924 <disable_interrupt+0x108> 2c8: 224000ef jal ra,4ec <printf> 2cc: 00090593 mv a1,s2 2d0: 00000517 auipc a0,0x0 2d4: 67450513 addi a0,a0,1652 # 944 <disable_interrupt+0x128> 2d8: 214000ef jal ra,4ec <printf> 2dc: 00190913 addi s2,s2,1 2e0: efdff06f j 1dc <main+0x70> 000002e4 <bios_stream_read>: 2e4: fe010113 addi sp,sp,-32 2e8: 00400793 li a5,4 2ec: 00f12623 sw a5,12(sp) 2f0: 00a12823 sw a0,16(sp) 2f4: 00b12e23 sw a1,28(sp) 2f8: 00c12a23 sw a2,20(sp) 2fc: 00c10793 addi a5,sp,12 300: 00f062b3 or t0,zero,a5 304: 00000073 ecall 308: 01812503 lw a0,24(sp) 30c: 02010113 addi sp,sp,32 310: 00008067 ret 00000314 <bios_stream_write>: 314: fe010113 addi sp,sp,-32 318: 00500793 li a5,5 31c: 00f12623 sw a5,12(sp) 320: 00a12823 sw a0,16(sp) 324: 00b12e23 sw a1,28(sp) 328: 00c12a23 sw a2,20(sp) 32c: 00c10793 addi a5,sp,12 330: 00f062b3 or t0,zero,a5 334: 00000073 ecall 338: 01812503 lw a0,24(sp) 33c: 02010113 addi sp,sp,32 340: 00008067 ret 00000344 <printf_c>: 344: fe010113 addi sp,sp,-32 348: 00a107a3 sb a0,15(sp) 34c: 00f10593 addi a1,sp,15 350: 00100613 li a2,1 354: 00400513 li a0,4 358: 00112e23 sw ra,28(sp) 35c: fb9ff0ef jal ra,314 <bios_stream_write> 360: 01c12083 lw ra,28(sp) 364: 02010113 addi sp,sp,32 368: 00008067 ret 0000036c <printf_s>: 36c: ff010113 addi sp,sp,-16 370: 00812423 sw s0,8(sp) 374: 00112623 sw ra,12(sp) 378: 00050413 mv s0,a0 37c: 00044503 lbu a0,0(s0) 380: 00051a63 bnez a0,394 <printf_s+0x28> 384: 00c12083 lw ra,12(sp) 388: 00812403 lw s0,8(sp) 38c: 01010113 addi sp,sp,16 390: 00008067 ret 394: 00140413 addi s0,s0,1 398: fadff0ef jal ra,344 <printf_c> 39c: fe1ff06f j 37c <printf_s+0x10> 000003a0 <_read_character_uart>: 3a0: fe010113 addi sp,sp,-32 3a4: 00f10593 addi a1,sp,15 3a8: 00100613 li a2,1 3ac: 00000513 li a0,0 3b0: 00112e23 sw ra,28(sp) 3b4: f31ff0ef jal ra,2e4 <bios_stream_read> 3b8: 01c12083 lw ra,28(sp) 3bc: 00f14503 lbu a0,15(sp) 3c0: 02010113 addi sp,sp,32 3c4: 00008067 ret 000003c8 <parse_long>: 3c8: 00050693 mv a3,a0 3cc: 00000813 li a6,0 3d0: 00000513 li a0,0 3d4: 00000593 li a1,0 3d8: 02d00893 li a7,45 3dc: 00900313 li t1,9 3e0: 00a00613 li a2,10 3e4: 0006c703 lbu a4,0(a3) 3e8: 04070463 beqz a4,430 <parse_long+0x68> 3ec: 03170e63 beq a4,a7,428 <parse_long+0x60> 3f0: fd070713 addi a4,a4,-48 3f4: 0ff77793 zext.b a5,a4 3f8: 02f36463 bltu t1,a5,420 <parse_long+0x58> 3fc: 02a637b3 mulhu a5,a2,a0 400: 02b605b3 mul a1,a2,a1 404: 02a60e33 mul t3,a2,a0 408: 00f585b3 add a1,a1,a5 40c: 41f75793 srai a5,a4,0x1f 410: 00b787b3 add a5,a5,a1 414: 01c70533 add a0,a4,t3 418: 00e53733 sltu a4,a0,a4 41c: 00f705b3 add a1,a4,a5 420: 00168693 addi a3,a3,1 424: fc1ff06f j 3e4 <parse_long+0x1c> 428: 00100813 li a6,1 42c: ff5ff06f j 420 <parse_long+0x58> 430: 00080a63 beqz a6,444 <parse_long+0x7c> 434: 00a037b3 snez a5,a0 438: 40b005b3 neg a1,a1 43c: 40f585b3 sub a1,a1,a5 440: 40a00533 neg a0,a0 444: 00008067 ret 00000448 <parse_int>: 448: ff010113 addi sp,sp,-16 44c: 00112623 sw ra,12(sp) 450: f79ff0ef jal ra,3c8 <parse_long> 454: 00c12083 lw ra,12(sp) 458: 01010113 addi sp,sp,16 45c: 00008067 ret 00000460 <printf_d>: 460: fe010113 addi sp,sp,-32 464: 00812c23 sw s0,24(sp) 468: 00112e23 sw ra,28(sp) 46c: 00912a23 sw s1,20(sp) 470: 01212823 sw s2,16(sp) 474: 00050413 mv s0,a0 478: 00055863 bgez a0,488 <printf_d+0x28> 47c: 02d00513 li a0,45 480: ec5ff0ef jal ra,344 <printf_c> 484: 40800433 neg s0,s0 488: 00010493 mv s1,sp 48c: 00048913 mv s2,s1 490: 02041863 bnez s0,4c0 <printf_d+0x60> 494: 03248663 beq s1,s2,4c0 <printf_d+0x60> 498: fff4c503 lbu a0,-1(s1) 49c: fff48493 addi s1,s1,-1 4a0: ea5ff0ef jal ra,344 <printf_c> 4a4: ff249ae3 bne s1,s2,498 <printf_d+0x38> 4a8: 01c12083 lw ra,28(sp) 4ac: 01812403 lw s0,24(sp) 4b0: 01412483 lw s1,20(sp) 4b4: 01012903 lw s2,16(sp) 4b8: 02010113 addi sp,sp,32 4bc: 00008067 ret 4c0: 00a00593 li a1,10 4c4: 00040513 mv a0,s0 4c8: bddff0ef jal ra,a4 <__modsi3> 4cc: 03050513 addi a0,a0,48 4d0: 00a48023 sb a0,0(s1) 4d4: 00a00593 li a1,10 4d8: 00040513 mv a0,s0 4dc: b45ff0ef jal ra,20 <__divsi3> 4e0: 00148493 addi s1,s1,1 4e4: 00050413 mv s0,a0 4e8: fa9ff06f j 490 <printf_d+0x30> 000004ec <printf>: 4ec: fb010113 addi sp,sp,-80 4f0: 04f12223 sw a5,68(sp) 4f4: 03410793 addi a5,sp,52 4f8: 02812423 sw s0,40(sp) 4fc: 02912223 sw s1,36(sp) 500: 03212023 sw s2,32(sp) 504: 01312e23 sw s3,28(sp) 508: 01412c23 sw s4,24(sp) 50c: 01512a23 sw s5,20(sp) 510: 02112623 sw ra,44(sp) 514: 00050493 mv s1,a0 518: 02b12a23 sw a1,52(sp) 51c: 02c12c23 sw a2,56(sp) 520: 02d12e23 sw a3,60(sp) 524: 04e12023 sw a4,64(sp) 528: 05012423 sw a6,72(sp) 52c: 05112623 sw a7,76(sp) 530: 00f12623 sw a5,12(sp) 534: 00000413 li s0,0 538: 02500913 li s2,37 53c: 06300993 li s3,99 540: 07300a13 li s4,115 544: 06400a93 li s5,100 548: 008487b3 add a5,s1,s0 54c: 0007c503 lbu a0,0(a5) 550: 02051463 bnez a0,578 <printf+0x8c> 554: 02c12083 lw ra,44(sp) 558: 02812403 lw s0,40(sp) 55c: 02412483 lw s1,36(sp) 560: 02012903 lw s2,32(sp) 564: 01c12983 lw s3,28(sp) 568: 01812a03 lw s4,24(sp) 56c: 01412a83 lw s5,20(sp) 570: 05010113 addi sp,sp,80 574: 00008067 ret 578: 03251463 bne a0,s2,5a0 <printf+0xb4> 57c: 00140413 addi s0,s0,1 580: 008487b3 add a5,s1,s0 584: 0007c783 lbu a5,0(a5) 588: 02078c63 beqz a5,5c0 <printf+0xd4> 58c: 01379e63 bne a5,s3,5a8 <printf+0xbc> 590: 00c12783 lw a5,12(sp) 594: 0007c503 lbu a0,0(a5) 598: 00478713 addi a4,a5,4 59c: 00e12623 sw a4,12(sp) 5a0: da5ff0ef jal ra,344 <printf_c> 5a4: 01c0006f j 5c0 <printf+0xd4> 5a8: 03479063 bne a5,s4,5c8 <printf+0xdc> 5ac: 00c12783 lw a5,12(sp) 5b0: 0007a503 lw a0,0(a5) 5b4: 00478713 addi a4,a5,4 5b8: 00e12623 sw a4,12(sp) 5bc: db1ff0ef jal ra,36c <printf_s> 5c0: 00140413 addi s0,s0,1 5c4: f85ff06f j 548 <printf+0x5c> 5c8: fb579ae3 bne a5,s5,57c <printf+0x90> 5cc: 00c12783 lw a5,12(sp) 5d0: 0007a503 lw a0,0(a5) 5d4: 00478713 addi a4,a5,4 5d8: 00e12623 sw a4,12(sp) 5dc: e85ff0ef jal ra,460 <printf_d> 5e0: fe1ff06f j 5c0 <printf+0xd4> 000005e4 <read_string>: 5e4: fd010113 addi sp,sp,-48 5e8: 02812423 sw s0,40(sp) 5ec: 02912223 sw s1,36(sp) 5f0: 03212023 sw s2,32(sp) 5f4: 01312e23 sw s3,28(sp) 5f8: 01512a23 sw s5,20(sp) 5fc: 01612823 sw s6,16(sp) 600: 01712623 sw s7,12(sp) 604: 01812423 sw s8,8(sp) 608: 02112623 sw ra,44(sp) 60c: 01412c23 sw s4,24(sp) 610: 00050493 mv s1,a0 614: 00060993 mv s3,a2 618: fff58913 addi s2,a1,-1 61c: 00000413 li s0,0 620: 00d00a93 li s5,13 624: 00a00b13 li s6,10 628: 07f00b93 li s7,127 62c: 00000c17 auipc s8,0x0 630: 330c0c13 addi s8,s8,816 # 95c <disable_interrupt+0x140> 634: 05244063 blt s0,s2,674 <read_string+0x90> 638: 00848433 add s0,s1,s0 63c: 00040023 sb zero,0(s0) 640: 02c12083 lw ra,44(sp) 644: 02812403 lw s0,40(sp) 648: 02012903 lw s2,32(sp) 64c: 01c12983 lw s3,28(sp) 650: 01812a03 lw s4,24(sp) 654: 01412a83 lw s5,20(sp) 658: 01012b03 lw s6,16(sp) 65c: 00c12b83 lw s7,12(sp) 660: 00812c03 lw s8,8(sp) 664: 00048513 mv a0,s1 668: 02412483 lw s1,36(sp) 66c: 03010113 addi sp,sp,48 670: 00008067 ret 674: d2dff0ef jal ra,3a0 <_read_character_uart> 678: fd5500e3 beq a0,s5,638 <read_string+0x54> 67c: fb650ee3 beq a0,s6,638 <read_string+0x54> 680: 03750063 beq a0,s7,6a0 <read_string+0xbc> 684: 00140a13 addi s4,s0,1 688: 00848433 add s0,s1,s0 68c: 00a40023 sb a0,0(s0) 690: 00098463 beqz s3,698 <read_string+0xb4> 694: cb1ff0ef jal ra,344 <printf_c> 698: 000a0413 mv s0,s4 69c: f99ff06f j 634 <read_string+0x50> 6a0: 00000a13 li s4,0 6a4: fe040ae3 beqz s0,698 <read_string+0xb4> 6a8: 000c0513 mv a0,s8 6ac: fff40a13 addi s4,s0,-1 6b0: e3dff0ef jal ra,4ec <printf> 6b4: fe5ff06f j 698 <read_string+0xb4> 000006b8 <strlen>: 6b8: 00050793 mv a5,a0 6bc: 00000513 li a0,0 6c0: 00a78733 add a4,a5,a0 6c4: 00074703 lbu a4,0(a4) 6c8: 00071463 bnez a4,6d0 <strlen+0x18> 6cc: 00008067 ret 6d0: 00150513 addi a0,a0,1 6d4: fedff06f j 6c0 <strlen+0x8> 000006d8 <strcmp>: 6d8: 00b567b3 or a5,a0,a1 6dc: 0037f793 andi a5,a5,3 6e0: 02079e63 bnez a5,71c <strcmp+0x44> 6e4: feff06b7 lui a3,0xfeff0 6e8: 80808637 lui a2,0x80808 6ec: eff68693 addi a3,a3,-257 # fefefeff <//.+0xfefdfeff> 6f0: 08060613 addi a2,a2,128 # 80808080 <//.+0x807f8080> 6f4: 00052783 lw a5,0(a0) 6f8: 0005a703 lw a4,0(a1) 6fc: 0ae78463 beq a5,a4,7a4 <strcmp+0xcc> 700: 0ff7f693 zext.b a3,a5 704: 0ff77613 zext.b a2,a4 708: 04c68263 beq a3,a2,74c <strcmp+0x74> 70c: 00100513 li a0,1 710: 08c6f863 bgeu a3,a2,7a0 <strcmp+0xc8> 714: fff00513 li a0,-1 718: 00008067 ret 71c: 00054783 lbu a5,0(a0) 720: 0005c703 lbu a4,0(a1) 724: 00150513 addi a0,a0,1 728: 00158593 addi a1,a1,1 72c: 00e78a63 beq a5,a4,740 <strcmp+0x68> 730: fff00513 li a0,-1 734: 06e7e663 bltu a5,a4,7a0 <strcmp+0xc8> 738: 00100513 li a0,1 73c: 00008067 ret 740: f8079ce3 bnez a5,6d8 <strcmp> 744: 00000513 li a0,0 748: 0580006f j 7a0 <strcmp+0xc8> 74c: 00000513 li a0,0 750: 04068863 beqz a3,7a0 <strcmp+0xc8> 754: 0087d693 srli a3,a5,0x8 758: 00875613 srli a2,a4,0x8 75c: 0ff6f693 zext.b a3,a3 760: 0ff67613 zext.b a2,a2 764: fac694e3 bne a3,a2,70c <strcmp+0x34> 768: 00000513 li a0,0 76c: 02068a63 beqz a3,7a0 <strcmp+0xc8> 770: 0107d693 srli a3,a5,0x10 774: 01075613 srli a2,a4,0x10 778: 0ff6f693 zext.b a3,a3 77c: 0ff67613 zext.b a2,a2 780: f8c696e3 bne a3,a2,70c <strcmp+0x34> 784: 00000513 li a0,0 788: 00068c63 beqz a3,7a0 <strcmp+0xc8> 78c: 0187d793 srli a5,a5,0x18 790: 01875713 srli a4,a4,0x18 794: 00e78663 beq a5,a4,7a0 <strcmp+0xc8> 798: 00100513 li a0,1 79c: f6e7ece3 bltu a5,a4,714 <strcmp+0x3c> 7a0: 00008067 ret 7a4: 00d78733 add a4,a5,a3 7a8: fff7c793 not a5,a5 7ac: 00f777b3 and a5,a4,a5 7b0: 00c7f7b3 and a5,a5,a2 7b4: f80798e3 bnez a5,744 <strcmp+0x6c> 7b8: 00450513 addi a0,a0,4 7bc: 00458593 addi a1,a1,4 7c0: f35ff06f j 6f4 <strcmp+0x1c> 000007c4 <read_msr_status>: 7c4: fc001573 csrrw a0,0xfc0,zero 7c8: 00008067 ret 000007cc <write_msr_status>: 7cc: 7c051573 csrrw a0,0x7c0,a0 7d0: 00008067 ret 000007d4 <read_msr_evect>: 7d4: fc301573 csrrw a0,0xfc3,zero 7d8: 00008067 ret 000007dc <write_msr_evect>: 7dc: 7c351573 csrrw a0,0x7c3,a0 7e0: 00008067 ret 000007e4 <get_interrupt_enabled>: 7e4: ff010113 addi sp,sp,-16 7e8: 00112623 sw ra,12(sp) 7ec: fd9ff0ef jal ra,7c4 <read_msr_status> 7f0: 00c12083 lw ra,12(sp) 7f4: 00157513 andi a0,a0,1 7f8: 01010113 addi sp,sp,16 7fc: 00008067 ret 00000800 <enable_interrupt>: 800: ff010113 addi sp,sp,-16 804: 00112623 sw ra,12(sp) 808: fbdff0ef jal ra,7c4 <read_msr_status> 80c: 00c12083 lw ra,12(sp) 810: 00156513 ori a0,a0,1 814: 01010113 addi sp,sp,16 818: fb5ff06f j 7cc <write_msr_status> 0000081c <disable_interrupt>: 81c: ff010113 addi sp,sp,-16 820: 00112623 sw ra,12(sp) 824: fa1ff0ef jal ra,7c4 <read_msr_status> 828: 00c12083 lw ra,12(sp) 82c: ffe57513 andi a0,a0,-2 830: 01010113 addi sp,sp,16 834: f99ff06f j 7cc <write_msr_status> riscv64-unknown-elf-objcopy -O binary example.elf example.bin cd libtinyc && make make[1]: Entering directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libtinyc' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libtinyc' cd libspu32 && make make[1]: Entering directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libspu32' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/cicero/Documents/code/example_reference/spu32/software/c-firmware/libspu32' riscv64-unknown-elf-gcc -I./libtinyc -I./libspu32 -march=rv32im -mno-div -mabi=ilp32 -static -nostdlib -fno-builtin-printf -Os -fPIC -fdata-sections -ffunction-sections -c interrupts.c interrupts.c: In function 'main': interrupts.c:18:25: warning: passing argument 1 of 'write_msr_evect' makes integer from pointer without a cast [-Wint-conversion] 18 | write_msr_evect(isr); | ^~~ | | | void (*)() In file included from interrupts.c:2: ./libspu32/libspu32.h:21:29: note: expected 'int' but argument is of type 'void (*)()' 21 | int write_msr_evect(int vec); | ~~~~^~~ riscv64-unknown-elf-gcc -I./libtinyc -I./libspu32 -march=rv32im -mno-div -mabi=ilp32 -static -nostdlib -fno-builtin-printf -Os -fPIC -fdata-sections -ffunction-sections -o interrupts.elf crt0.s interrupts.o -L./libtinyc -ltinyc -L./libspu32 -lspu32 -Tlink.ld -Xlinker --gc-sections riscv64-unknown-elf-objdump -d interrupts.elf interrupts.elf: file format elf32-littleriscv Disassembly of section .text: 00000000 <_ftext>: 0: 0140006f j 14 <_init> ... 00000010 <_interrupt>: 10: 0000006f j 10 <_interrupt> 00000014 <_init>: 14: 00080137 lui sp,0x80 18: 168000ef jal ra,180 <main> 1c: fe5ff06f j 0 <_ftext> 00000020 <__divsi3>: 20: 06054063 bltz a0,80 <__umodsi3+0x10> 24: 0605c663 bltz a1,90 <__umodsi3+0x20> 00000028 <__udivsi3>: 28: 00058613 mv a2,a1 2c: 00050593 mv a1,a0 30: fff00513 li a0,-1 34: 02060c63 beqz a2,6c <__udivsi3+0x44> 38: 00100693 li a3,1 3c: 00b67a63 bgeu a2,a1,50 <__udivsi3+0x28> 40: 00c05863 blez a2,50 <__udivsi3+0x28> 44: 00161613 slli a2,a2,0x1 48: 00169693 slli a3,a3,0x1 4c: feb66ae3 bltu a2,a1,40 <__udivsi3+0x18> 50: 00000513 li a0,0 54: 00c5e663 bltu a1,a2,60 <__udivsi3+0x38> 58: 40c585b3 sub a1,a1,a2 5c: 00d56533 or a0,a0,a3 60: 0016d693 srli a3,a3,0x1 64: 00165613 srli a2,a2,0x1 68: fe0696e3 bnez a3,54 <__udivsi3+0x2c> 6c: 00008067 ret 00000070 <__umodsi3>: 70: 00008293 mv t0,ra 74: fb5ff0ef jal ra,28 <__udivsi3> 78: 00058513 mv a0,a1 7c: 00028067 jr t0 80: 40a00533 neg a0,a0 84: 00b04863 bgtz a1,94 <__umodsi3+0x24> 88: 40b005b3 neg a1,a1 8c: f9dff06f j 28 <__udivsi3> 90: 40b005b3 neg a1,a1 94: 00008293 mv t0,ra 98: f91ff0ef jal ra,28 <__udivsi3> 9c: 40a00533 neg a0,a0 a0: 00028067 jr t0 000000a4 <__modsi3>: a4: 00008293 mv t0,ra a8: 0005ca63 bltz a1,bc <__modsi3+0x18> ac: 00054c63 bltz a0,c4 <__modsi3+0x20> b0: f79ff0ef jal ra,28 <__udivsi3> b4: 00058513 mv a0,a1 b8: 00028067 jr t0 bc: 40b005b3 neg a1,a1 c0: fe0558e3 bgez a0,b0 <__modsi3+0xc> c4: 40a00533 neg a0,a0 c8: f61ff0ef jal ra,28 <__udivsi3> cc: 40b00533 neg a0,a1 d0: 00028067 jr t0 000000d4 <isr>: d4: fc010113 addi sp,sp,-64 # 7ffc0 <//.+0x6ffc0> d8: 02112e23 sw ra,60(sp) dc: 02512c23 sw t0,56(sp) e0: 02612a23 sw t1,52(sp) e4: 02712823 sw t2,48(sp) e8: 02c12223 sw a2,36(sp) ec: 02d12023 sw a3,32(sp) f0: 00e12e23 sw a4,28(sp) f4: 00f12c23 sw a5,24(sp) f8: 01012a23 sw a6,20(sp) fc: 01112823 sw a7,16(sp) 100: 01c12623 sw t3,12(sp) 104: 01d12423 sw t4,8(sp) 108: 01e12223 sw t5,4(sp) 10c: 01f12023 sw t6,0(sp) 110: 02b12423 sw a1,40(sp) 114: 02a12623 sw a0,44(sp) 118: 334000ef jal ra,44c <ack_milli_time_interrupt> 11c: 338000ef jal ra,454 <get_prng_value> 120: 00050593 mv a1,a0 124: 00000517 auipc a0,0x0 128: 34050513 addi a0,a0,832 # 464 <set_prng_seed+0x8> 12c: 1c8000ef jal ra,2f4 <printf> 130: 1f400513 li a0,500 134: 308000ef jal ra,43c <request_milli_time_interrupt> 138: 03c12083 lw ra,60(sp) 13c: 03812283 lw t0,56(sp) 140: 03412303 lw t1,52(sp) 144: 03012383 lw t2,48(sp) 148: 02c12503 lw a0,44(sp) 14c: 02812583 lw a1,40(sp) 150: 02412603 lw a2,36(sp) 154: 02012683 lw a3,32(sp) 158: 01c12703 lw a4,28(sp) 15c: 01812783 lw a5,24(sp) 160: 01412803 lw a6,20(sp) 164: 01012883 lw a7,16(sp) 168: 00c12e03 lw t3,12(sp) 16c: 00812e83 lw t4,8(sp) 170: 00412f03 lw t5,4(sp) 174: 00012f83 lw t6,0(sp) 178: 04010113 addi sp,sp,64 17c: 30200073 mret 00000180 <main>: 180: ff010113 addi sp,sp,-16 184: 53900513 li a0,1337 188: 00112623 sw ra,12(sp) 18c: 00812423 sw s0,8(sp) 190: 00912223 sw s1,4(sp) 194: 2c8000ef jal ra,45c <set_prng_seed> 198: 00000517 auipc a0,0x0 19c: 31c52503 lw a0,796(a0) # 4b4 <_GLOBAL_OFFSET_TABLE_+0x4> 1a0: 25c000ef jal ra,3fc <write_msr_evect> 1a4: 260000ef jal ra,404 <enable_interrupt> 1a8: 3e800513 li a0,1000 1ac: 290000ef jal ra,43c <request_milli_time_interrupt> 1b0: 000314b7 lui s1,0x31 1b4: 00000417 auipc s0,0x0 1b8: 2d840413 addi s0,s0,728 # 48c <set_prng_seed+0x30> 1bc: d4048793 addi a5,s1,-704 # 30d40 <//.+0x20d40> 1c0: fff78793 addi a5,a5,-1 1c4: fe079ee3 bnez a5,1c0 <main+0x40> 1c8: 258000ef jal ra,420 <disable_interrupt> 1cc: 00040513 mv a0,s0 1d0: 124000ef jal ra,2f4 <printf> 1d4: 230000ef jal ra,404 <enable_interrupt> 1d8: fe5ff06f j 1bc <main+0x3c> 000001dc <bios_stream_write>: 1dc: fe010113 addi sp,sp,-32 1e0: 00500793 li a5,5 1e4: 00f12623 sw a5,12(sp) 1e8: 00a12823 sw a0,16(sp) 1ec: 00b12e23 sw a1,28(sp) 1f0: 00c12a23 sw a2,20(sp) 1f4: 00c10793 addi a5,sp,12 1f8: 00f062b3 or t0,zero,a5 1fc: 00000073 ecall 200: 01812503 lw a0,24(sp) 204: 02010113 addi sp,sp,32 208: 00008067 ret 0000020c <printf_c>: 20c: fe010113 addi sp,sp,-32 210: 00a107a3 sb a0,15(sp) 214: 00f10593 addi a1,sp,15 218: 00100613 li a2,1 21c: 00400513 li a0,4 220: 00112e23 sw ra,28(sp) 224: fb9ff0ef jal ra,1dc <bios_stream_write> 228: 01c12083 lw ra,28(sp) 22c: 02010113 addi sp,sp,32 230: 00008067 ret 00000234 <printf_s>: 234: ff010113 addi sp,sp,-16 238: 00812423 sw s0,8(sp) 23c: 00112623 sw ra,12(sp) 240: 00050413 mv s0,a0 244: 00044503 lbu a0,0(s0) 248: 00051a63 bnez a0,25c <printf_s+0x28> 24c: 00c12083 lw ra,12(sp) 250: 00812403 lw s0,8(sp) 254: 01010113 addi sp,sp,16 258: 00008067 ret 25c: 00140413 addi s0,s0,1 260: fadff0ef jal ra,20c <printf_c> 264: fe1ff06f j 244 <printf_s+0x10> 00000268 <printf_d>: 268: fe010113 addi sp,sp,-32 26c: 00812c23 sw s0,24(sp) 270: 00112e23 sw ra,28(sp) 274: 00912a23 sw s1,20(sp) 278: 01212823 sw s2,16(sp) 27c: 00050413 mv s0,a0 280: 00055863 bgez a0,290 <printf_d+0x28> 284: 02d00513 li a0,45 288: f85ff0ef jal ra,20c <printf_c> 28c: 40800433 neg s0,s0 290: 00010493 mv s1,sp 294: 00048913 mv s2,s1 298: 02041863 bnez s0,2c8 <printf_d+0x60> 29c: 03248663 beq s1,s2,2c8 <printf_d+0x60> 2a0: fff4c503 lbu a0,-1(s1) 2a4: fff48493 addi s1,s1,-1 2a8: f65ff0ef jal ra,20c <printf_c> 2ac: ff249ae3 bne s1,s2,2a0 <printf_d+0x38> 2b0: 01c12083 lw ra,28(sp) 2b4: 01812403 lw s0,24(sp) 2b8: 01412483 lw s1,20(sp) 2bc: 01012903 lw s2,16(sp) 2c0: 02010113 addi sp,sp,32 2c4: 00008067 ret 2c8: 00a00593 li a1,10 2cc: 00040513 mv a0,s0 2d0: dd5ff0ef jal ra,a4 <__modsi3> 2d4: 03050513 addi a0,a0,48 2d8: 00a48023 sb a0,0(s1) 2dc: 00a00593 li a1,10 2e0: 00040513 mv a0,s0 2e4: d3dff0ef jal ra,20 <__divsi3> 2e8: 00148493 addi s1,s1,1 2ec: 00050413 mv s0,a0 2f0: fa9ff06f j 298 <printf_d+0x30> 000002f4 <printf>: 2f4: fb010113 addi sp,sp,-80 2f8: 04f12223 sw a5,68(sp) 2fc: 03410793 addi a5,sp,52 300: 02812423 sw s0,40(sp) 304: 02912223 sw s1,36(sp) 308: 03212023 sw s2,32(sp) 30c: 01312e23 sw s3,28(sp) 310: 01412c23 sw s4,24(sp) 314: 01512a23 sw s5,20(sp) 318: 02112623 sw ra,44(sp) 31c: 00050493 mv s1,a0 320: 02b12a23 sw a1,52(sp) 324: 02c12c23 sw a2,56(sp) 328: 02d12e23 sw a3,60(sp) 32c: 04e12023 sw a4,64(sp) 330: 05012423 sw a6,72(sp) 334: 05112623 sw a7,76(sp) 338: 00f12623 sw a5,12(sp) 33c: 00000413 li s0,0 340: 02500913 li s2,37 344: 06300993 li s3,99 348: 07300a13 li s4,115 34c: 06400a93 li s5,100 350: 008487b3 add a5,s1,s0 354: 0007c503 lbu a0,0(a5) 358: 02051463 bnez a0,380 <printf+0x8c> 35c: 02c12083 lw ra,44(sp) 360: 02812403 lw s0,40(sp) 364: 02412483 lw s1,36(sp) 368: 02012903 lw s2,32(sp) 36c: 01c12983 lw s3,28(sp) 370: 01812a03 lw s4,24(sp) 374: 01412a83 lw s5,20(sp) 378: 05010113 addi sp,sp,80 37c: 00008067 ret 380: 03251463 bne a0,s2,3a8 <printf+0xb4> 384: 00140413 addi s0,s0,1 388: 008487b3 add a5,s1,s0 38c: 0007c783 lbu a5,0(a5) 390: 02078c63 beqz a5,3c8 <printf+0xd4> 394: 01379e63 bne a5,s3,3b0 <printf+0xbc> 398: 00c12783 lw a5,12(sp) 39c: 0007c503 lbu a0,0(a5) 3a0: 00478713 addi a4,a5,4 3a4: 00e12623 sw a4,12(sp) 3a8: e65ff0ef jal ra,20c <printf_c> 3ac: 01c0006f j 3c8 <printf+0xd4> 3b0: 03479063 bne a5,s4,3d0 <printf+0xdc> 3b4: 00c12783 lw a5,12(sp) 3b8: 0007a503 lw a0,0(a5) 3bc: 00478713 addi a4,a5,4 3c0: 00e12623 sw a4,12(sp) 3c4: e71ff0ef jal ra,234 <printf_s> 3c8: 00140413 addi s0,s0,1 3cc: f85ff06f j 350 <printf+0x5c> 3d0: fb579ae3 bne a5,s5,384 <printf+0x90> 3d4: 00c12783 lw a5,12(sp) 3d8: 0007a503 lw a0,0(a5) 3dc: 00478713 addi a4,a5,4 3e0: 00e12623 sw a4,12(sp) 3e4: e85ff0ef jal ra,268 <printf_d> 3e8: fe1ff06f j 3c8 <printf+0xd4> 000003ec <read_msr_status>: 3ec: fc001573 csrrw a0,0xfc0,zero 3f0: 00008067 ret 000003f4 <write_msr_status>: 3f4: 7c051573 csrrw a0,0x7c0,a0 3f8: 00008067 ret 000003fc <write_msr_evect>: 3fc: 7c351573 csrrw a0,0x7c3,a0 400: 00008067 ret 00000404 <enable_interrupt>: 404: ff010113 addi sp,sp,-16 408: 00112623 sw ra,12(sp) 40c: fe1ff0ef jal ra,3ec <read_msr_status> 410: 00c12083 lw ra,12(sp) 414: 00156513 ori a0,a0,1 418: 01010113 addi sp,sp,16 41c: fd9ff06f j 3f4 <write_msr_status> 00000420 <disable_interrupt>: 420: ff010113 addi sp,sp,-16 424: 00112623 sw ra,12(sp) 428: fc5ff0ef jal ra,3ec <read_msr_status> 42c: 00c12083 lw ra,12(sp) 430: ffe57513 andi a0,a0,-2 434: 01010113 addi sp,sp,16 438: fbdff06f j 3f4 <write_msr_status> 0000043c <request_milli_time_interrupt>: 43c: d0002783 lw a5,-768(zero) # fffffd00 <//.+0xfffefd00> 440: 00a787b3 add a5,a5,a0 444: d0f02223 sw a5,-764(zero) # fffffd04 <//.+0xfffefd04> 448: 00008067 ret 0000044c <ack_milli_time_interrupt>: 44c: d0404783 lbu a5,-764(zero) # fffffd04 <//.+0xfffefd04> 450: 00008067 ret 00000454 <get_prng_value>: 454: e0002503 lw a0,-512(zero) # fffffe00 <//.+0xfffefe00> 458: 00008067 ret 0000045c <set_prng_seed>: 45c: e0a02023 sw a0,-512(zero) # fffffe00 <//.+0xfffefe00> 460: 00008067 ret riscv64-unknown-elf-objcopy -O binary interrupts.elf interrupts.bin make: *** No rule to make target 'chainreaction.bin', needed by 'all'. Stop. rm example.elf example.o interrupts.o interrupts.elf ``` ::: I think it's the author trying to test the [game](https://github.com/maikmerten/chainreaction) he wrote. We already build it in `software/spu32-system/apps` #### brief summary of software I think we need something like FPGA board to run the spu32, so that we can execute those software.(install system via `filesrv`,control via `serial-uploader`) ## Interrupt/Exception of spu32 * When the interrupt or exception occurs, the CPU will jump to ```VECTOR_EXCEPTION``` which sets to ```0x00000010``` by default to handle interrupts and exceptions. - interrupts : include ```software or external interrupt ``` - exceptions : illegal or unknown instructions ---- * MSR (machine-status registers) will be used to control ```interrupt and exception ```, if any of them happens. The below circuit diagram is about the ```MSR_STATUS``` and ```MSR_CAUSE``` registers. ![](https://i.imgur.com/hg9bkrK.png) * MSR_STATUS's information as follows - MSR[0] is indicated by register ```meie```,which means external interrupt flag's current state. - MSR[1] is indicated by register ```meie_prev```,which means external interrupt flag's previous state. - MSR[2] is indicated by ```I_interrupt```. ```I_interrupt``` is the one of SPU32's inputs and it means whether the external interrupt is requested. - MSR[31:3] is ```all zeros```. * MSR_CAUSE can encode the interrupt or the exception's cauae. - Next, we will explain how MSR_CAUSE works. - MSR_CAUSE[31]'s value is 1,which means the external interupt occurs. - Therefore, we can use ```MSR_CAUSE[31]``` to know external interrupt or internal interrupt. - Besides, MSR_CAUSE[31]=0 and MSR_CAUSE[3:0]=0010 represent ```invalid instruction```. - MSR_CAUSE[31:4] are ```all zero``` * MSR_EPC can store the instruction address. - Once a instruction causes the interrupt or the exception, MSR_EPC will store the instruction's address. - Then, the instruction ```mret``` will jump to the address stord in MSR_EPC. - Especially, once ```mret``` is issued directly, the instruction caused interrupt will be execute again. So, another interrupt will be raised. - If we want the original program to resume, we have to get ```mret```'s contents and increment it by four to execute the next instruction. * MSR_EVECT can store the memory address. - If the interrupt or the exception happens, the cpu will immediately jump to the memory address stored in MSR_EVECT. - Moreover, the memory address can be change with the different interrupt service routine. ---- ## reference ### tools [spu32 github](https://github.com/maikmerten/spu32) [yosys](https://github.com/YosysHQ/yosys) [verilator](https://www.veripool.org/verilator/) ### tutorial [verilator tutorial](https://ys-hayashi.me/2020/12/verilator/) [verilator testbench in troduction video](https://www.youtube.com/watch?v=vqSyj_XZlEo&t=354s) [riscv32 toolchain](https://twgreatdaily.com/CT10DHIBiuFnsJQVZ12V.html)