├── _config.yml ├── docs ├── _config.yml ├── figs │ ├── poyo-v.jpg │ └── poyo-v.png └── README.md ├── software ├── README.md ├── serial_read │ ├── serial_read.c │ └── Makefile ├── gpio │ ├── gpio.c │ └── Makefile ├── serial_write │ ├── serial_write.c │ └── Makefile ├── blink │ ├── blink.c │ └── Makefile ├── software_tools │ ├── ld.script │ ├── include │ │ ├── poyoio.h │ │ └── poyoio.c │ ├── crt0.s │ ├── Makefile.inc │ └── hex_converter.py ├── test │ ├── test.c │ └── Makefile └── coremark │ ├── Makefile │ ├── barebones │ ├── core_portme.c │ ├── core_portme.h │ └── ee_printf.c │ ├── coremark.h │ ├── core_util.c │ ├── core_state.c │ ├── core_matrix.c │ ├── core_main.c │ ├── LICENSE.md │ └── core_list_join.c ├── src └── pipeline_3stage │ ├── design │ ├── gpi.v │ ├── cpu_tb.v │ ├── gpo.v │ ├── hardware_counter.v │ ├── imem.v │ ├── regfile.v │ ├── dmem.v │ ├── uart.v │ ├── define.vh │ ├── alu.v │ ├── uart_rx.v │ ├── cpu_top.v │ └── decoder.v │ └── constraint │ └── const.xdc ├── README.md ├── LICENSE └── .gitignore /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-dinky -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-dinky -------------------------------------------------------------------------------- /docs/figs/poyo-v.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kadomoto/poyo-v/HEAD/docs/figs/poyo-v.jpg -------------------------------------------------------------------------------- /docs/figs/poyo-v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kadomoto/poyo-v/HEAD/docs/figs/poyo-v.png -------------------------------------------------------------------------------- /software/README.md: -------------------------------------------------------------------------------- 1 | This software includes the work that is distributed in the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). 2 | -------------------------------------------------------------------------------- /software/serial_read/serial_read.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char c; 4 | 5 | int main() { 6 | 7 | while(1){ 8 | 9 | c = serial_read(); 10 | delay(1000); 11 | serial_write(c); 12 | delay(1000); 13 | 14 | } 15 | 16 | return 0; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /software/gpio/gpio.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int led[4] = {1, 1, 1, 1}; 4 | 5 | int main() { 6 | 7 | while(1){ 8 | 9 | for (int i=0; i < 4; i++) { 10 | led[i] = digital_read(i); 11 | digital_write(i, led[i]); 12 | } 13 | delay(1000); 14 | 15 | } 16 | 17 | return 0; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/gpi.v: -------------------------------------------------------------------------------- 1 | // 2 | // gpi 3 | // 4 | 5 | 6 | module gpi ( 7 | input wire clk, 8 | input wire rst_n, 9 | input wire [7:0] wr_data, 10 | output reg [7:0] gpi_out 11 | ); 12 | 13 | always @(posedge clk or negedge rst_n) begin 14 | if (!rst_n) begin 15 | gpi_out <= 8'b00000000; 16 | end else begin 17 | gpi_out <= wr_data; 18 | end 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/cpu_tb.v: -------------------------------------------------------------------------------- 1 | // 2 | // cpu_tb 3 | // 4 | 5 | 6 | module cpu_tb; 7 | 8 | reg clk; 9 | reg rst; 10 | 11 | parameter CYCLE = 10; 12 | 13 | always #(CYCLE/2) clk = ~clk; 14 | 15 | cpu_top cpu_top ( 16 | .clk(clk), 17 | .rst(rst) 18 | ); 19 | 20 | initial begin 21 | #10 clk = 1'd0; 22 | rst = 1'd1; 23 | #(CYCLE) rst = 1'd0; 24 | end 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /software/serial_write/serial_write.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | while(1){ 6 | 7 | serial_write('H'); 8 | serial_write('E'); 9 | 10 | for (int i=0; i < 2; i++) { 11 | serial_write('L'); 12 | } 13 | 14 | serial_write('O'); 15 | 16 | serial_write('C'); 17 | serial_write('Q'); 18 | 19 | delay(3000); 20 | 21 | } 22 | 23 | return 0; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /software/blink/blink.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | while(1){ 6 | 7 | digital_write(0, 1); 8 | digital_write(1, 0); 9 | digital_write(2, 1); 10 | digital_write(3, 0); 11 | delay(1000); 12 | digital_write(0, 0); 13 | digital_write(1, 1); 14 | digital_write(2, 0); 15 | digital_write(3, 1); 16 | delay(1000); 17 | 18 | } 19 | 20 | return 0; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /software/software_tools/ld.script: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littleriscv"); 2 | OUTPUT_ARCH("riscv") 3 | 4 | ENTRY(_start); 5 | MEMORY { 6 | ROM(rxai) : ORIGIN = 0x8000, LENGTH = 32k 7 | RAM(wa) : ORIGIN = 0x10000, LENGTH = 32k 8 | } 9 | 10 | SECTIONS 11 | { 12 | .text : { *(.text) } > ROM 13 | .rodata : { *(.rodata) } > RAM 14 | .data : { *(.data) } > RAM 15 | . = ALIGN(4); 16 | __bss_start = .; 17 | .bss : {*(.bss)} > RAM 18 | __bss_end = .; 19 | } 20 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/gpo.v: -------------------------------------------------------------------------------- 1 | // 2 | // gpo 3 | // 4 | 5 | 6 | module gpo ( 7 | input wire clk, 8 | input wire rst_n, 9 | input wire we, 10 | input wire [7:0] wr_data, 11 | output reg [7:0] gpo_out 12 | ); 13 | 14 | always @(posedge clk or negedge rst_n) begin 15 | if (!rst_n) begin 16 | gpo_out <= 8'b00000000; 17 | end else begin 18 | if (we) begin 19 | gpo_out <= wr_data; 20 | end 21 | end 22 | end 23 | 24 | endmodule 25 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/hardware_counter.v: -------------------------------------------------------------------------------- 1 | // 2 | // hardware counter 3 | // 4 | 5 | 6 | module hardware_counter ( 7 | input wire clk, 8 | input wire rst_n, 9 | output wire [31:0] hc_out 10 | ); 11 | 12 | reg [31:0] cycles; 13 | 14 | assign hc_out = cycles; 15 | 16 | always @(posedge clk or negedge rst_n) begin 17 | if (!rst_n) begin 18 | cycles <= 32'd0; 19 | end else begin 20 | cycles <= cycles + 1; 21 | end 22 | end 23 | 24 | endmodule 25 | -------------------------------------------------------------------------------- /software/test/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | int main() { 5 | 6 | while(1){ 7 | 8 | serial_write('H'); 9 | serial_write('E'); 10 | serial_write('L'); 11 | serial_write('L'); 12 | serial_write('O'); 13 | 14 | for (int i=0; i < 2; i++) { 15 | serial_write('P'); 16 | serial_write('O'); 17 | serial_write('Y'); 18 | serial_write('O'); 19 | } 20 | 21 | delay(3000); 22 | 23 | } 24 | 25 | return 0; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/imem.v: -------------------------------------------------------------------------------- 1 | // 2 | // imem 3 | // 4 | 5 | 6 | `include "define.vh" 7 | 8 | module imem ( 9 | input wire clk, 10 | input wire [31:0] addr, 11 | output wire [31:0] rd_data 12 | ); 13 | 14 | reg [31:0] mem [0:16383]; // 64KiB(16bitアドレス空間) 15 | reg [13:0] addr_sync; // 64KiBを表現するための14bitアドレス(下位2bitはここでは考慮しない) 16 | 17 | initial $readmemh({`MEM_DATA_PATH, "code.hex"}, mem); 18 | 19 | always @(posedge clk) begin 20 | addr_sync <= addr[15:2]; // 読み出しアドレス更新をクロックと同期することでBRAM化 21 | end 22 | 23 | assign rd_data = mem[addr_sync]; 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /software/software_tools/include/poyoio.h: -------------------------------------------------------------------------------- 1 | #ifndef POYOIO_H 2 | #define POYOIO_H 3 | 4 | // ハードウェアカウンタのアドレス指定 5 | #define HARDWARE_COUNTER_ADDR (int*)0x20010 6 | 7 | // 1msあたりにかかるサイクル数(周波数[Hz]/1000)を指定 8 | #define HARDWARE_COUNT_FOR_ONE_MSEC 45000 9 | 10 | // UART関係の設定 11 | #define UART_TX_ADDR (char*)0x20020 12 | #define UART_TX_DELAY_TIME 1 13 | #define UART_RX_ADDR (int*)0x20030 14 | 15 | // GPIO関係の設定 16 | #define GPI_ADDR (int*)0x20040 17 | #define GPO_WRADDR (char*)0x20050 18 | #define GPO_RDADDR (int*)0x20050 19 | 20 | // poyo.c 21 | void digital_write(int pin, int vol); 22 | int digital_read(int pin); 23 | void serial_write(char c); 24 | char serial_read(); 25 | void delay(unsigned int time); 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/regfile.v: -------------------------------------------------------------------------------- 1 | // 2 | // regfile 3 | // 4 | 5 | 6 | module regfile ( 7 | input wire clk, 8 | input wire we, 9 | input wire [4:0] srcreg1_num, 10 | input wire [4:0] srcreg2_num, 11 | input wire [4:0] dstreg_num, 12 | input wire [31:0] dstreg_value, 13 | output wire [31:0] srcreg1_value, 14 | output wire [31:0] srcreg2_value 15 | ); 16 | 17 | reg [31:0] regfile [1:31]; // 1-31レジスタ 18 | 19 | always @(posedge clk) begin 20 | if (we) regfile[dstreg_num] <= dstreg_value; 21 | end 22 | 23 | assign srcreg1_value = (srcreg1_num == 5'd0) ? 32'd0 : regfile[srcreg1_num]; 24 | assign srcreg2_value = (srcreg2_num == 5'd0) ? 32'd0 : regfile[srcreg2_num]; 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /software/software_tools/crt0.s: -------------------------------------------------------------------------------- 1 | .text 2 | .align 2 3 | .global _start 4 | .global _end 5 | .extern main 6 | 7 | stack_top = 0x20000 8 | 9 | _start: 10 | j init_reg 11 | 12 | _end: 13 | j _end 14 | 15 | init_reg: 16 | li x1, 0 17 | li x2, 0 18 | li x3, 0 19 | li x4, 0 20 | li x5, 0 21 | li x6, 0 22 | li x7, 0 23 | li x8, 0 24 | li x9, 0 25 | li x10, 0 26 | li x11, 0 27 | li x12, 0 28 | li x13, 0 29 | li x14, 0 30 | li x15, 0 31 | li x16, 0 32 | li x17, 0 33 | li x18, 0 34 | li x19, 0 35 | li x20, 0 36 | li x21, 0 37 | li x22, 0 38 | li x23, 0 39 | li x24, 0 40 | li x25, 0 41 | li x26, 0 42 | li x27, 0 43 | li x28, 0 44 | li x29, 0 45 | li x30, 0 46 | li x31, 0 47 | li sp, 0x20000 48 | 49 | call_main: 50 | call main 51 | j _end 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # poyo-v 2 | 3 | poyo-vはFPGAやASICに使えるRISC-Vソフトプロセッサです。誰でも容易に拡張・インプリメントできるマイクロコントローラを目指してVerilog HDLで開発されています。 4 | 5 | *Poyo-v is a RISC-V ISA soft processor developed for FPGAs and ASICs. It is being developed in Verilog HDL.* 6 | 7 | なお、本リポジトリは 8 | 9 | * [CQ出版社 トランジスタ技術 2019年12月号「一緒に作ろう! RISC-Vマイコンピュータ」](https://toragi.cqpub.co.jp/tabid/887/Default.aspx) 10 | * d.lab-VDEC設計チュートリアル 11 | 12 | の参考用となっており、現在は更新を停止しています。 13 | 14 | 詳細は下記リンクから! 15 | 16 | *View documentation, FAQ, help, examples, and more at* 17 | 18 | ### [https://github.com/kadomoto/poyo-v/tree/master/docs](https://github.com/kadomoto/poyo-v/tree/master/docs) 19 | ### 20 | 21 | ## License 22 | * This project is released under the MIT License - see the [LICENSE](LICENSE) file for details. 23 | * This project includes the work that is distributed in the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). 24 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/dmem.v: -------------------------------------------------------------------------------- 1 | // 2 | // dmem 3 | // 4 | 5 | 6 | `include "define.vh" 7 | 8 | module dmem #(parameter byte_num = 2'b00) ( 9 | input wire clk, 10 | input wire we, 11 | input wire [31:0] addr, 12 | input wire [7:0] wr_data, 13 | output wire [7:0] rd_data 14 | ); 15 | 16 | reg [7:0] mem [0:16383]; // 64KiB(16bitアドレス空間) 17 | reg [13:0] addr_sync; // 64KiBを表現するための14bitアドレス(下位2bitはここでは考慮しない) 18 | 19 | initial begin 20 | case (byte_num) 21 | 2'b00: $readmemh({`MEM_DATA_PATH, "data0.hex"}, mem); 22 | 2'b01: $readmemh({`MEM_DATA_PATH, "data1.hex"}, mem); 23 | 2'b10: $readmemh({`MEM_DATA_PATH, "data2.hex"}, mem); 24 | 2'b11: $readmemh({`MEM_DATA_PATH, "data3.hex"}, mem); 25 | endcase 26 | end 27 | 28 | always @(posedge clk) begin 29 | if (we) mem[addr[15:2]] <= wr_data; // 書き込みタイミングをクロックと同期することでBRAM化 30 | addr_sync <= addr[15:2]; // 読み出しアドレス更新をクロックと同期することでBRAM化 31 | end 32 | 33 | assign rd_data = mem[addr_sync]; 34 | 35 | endmodule 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 ourfool 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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ######################################################################################################### 2 | ## This is an example .gitignore file for Vivado, please treat it as an example as 3 | ## it might not be complete. In addition, XAPP 1165 should be followed. 4 | ######################################################################################################### 5 | ######### 6 | #Exclude all 7 | ######### 8 | * 9 | !*/ 10 | !.gitignore 11 | ########################################################################### 12 | ## VIVADO 13 | ########################################################################### 14 | ######### 15 | #Source files: 16 | ######### 17 | #Do NOT ignore VHDL, Verilog, block diagrams or EDIF files. 18 | !*.vhd 19 | !*.vh 20 | !*.v 21 | !*.bd 22 | !*.edif 23 | ######### 24 | #Constraint files 25 | ######### 26 | #Do NOT ignore *.xdc files 27 | !*.xdc 28 | ######### 29 | #TCL - files 30 | ######### 31 | !*.tcl 32 | ######### 33 | #Software files 34 | ######### 35 | !*.md 36 | !*.hex 37 | !*.s 38 | !*.h 39 | !*.c 40 | !*.py 41 | !*.script 42 | !Makefile 43 | !*.inc 44 | ######### 45 | #document files 46 | ######### 47 | !*.png 48 | !*.jpg 49 | -------------------------------------------------------------------------------- /software/blink/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for c code 3 | # 4 | 5 | # 共通初期設定ファイルをインクルード 6 | include ../software_tools/Makefile.inc 7 | 8 | # C言語ソースコードファイルを指定 9 | SRC = blink.c 10 | 11 | SRCS = $(SRC) $(INCLUDE_ROOT)/poyoio.c 12 | OBJS = $(SRCS:.c=.o) 13 | 14 | 15 | all: code.hex data.hex data0.hex data1.hex data2.hex data3.hex 16 | 17 | # オブジェクトファイル生成 18 | %.o: %.c Makefile 19 | $(CC) $(CFLAGS) -o $@ -c $< 20 | 21 | # 下記はアセンブリコードを入力する場合の例 22 | #%.o: %.s Makefile 23 | # $(CC) $(CFLAGS) -o $@ -c $< 24 | 25 | # ELFファイル生成 26 | app.elf: $(OBJS) $(CRTOBJ) Makefile 27 | $(LD) $(CRTOBJ) $(OBJS) $(LIBC) $(LIBGCC) -T$(LDSCRIPT) $(LDFLAGS) -o app.elf 28 | 29 | # バイナリファイル生成 30 | app.bin: app.elf 31 | $(OBJDUMP) -D $< > app.dump 32 | $(OBJCOPY) -O binary $< $@ 33 | 34 | # バイナリファイルから.hex形式ファイルを生成 35 | app.hex: app.bin 36 | hexdump -v -e '1/4 "%08x" "\n"' $< > app_im.hex 37 | cat $(MEM_INIT) app_im.hex > $@ 38 | rm -f app_im.hex 39 | 40 | # .hex形式ファイルを命令メモリ用ファイルとデータメモリ用ファイルへと分割 41 | code.hex data.hex: app.hex 42 | $(HEX_CONVERTER) $< 43 | 44 | 45 | .PHONY: clean 46 | clean: 47 | rm $(OBJS) code.hex data.hex data0.hex data1.hex data2.hex data3.hex app.hex app.dump app.bin app.elf crt0.o -f 48 | -------------------------------------------------------------------------------- /software/gpio/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for c code 3 | # 4 | 5 | # 共通初期設定ファイルをインクルード 6 | include ../software_tools/Makefile.inc 7 | 8 | # C言語ソースコードファイルを指定 9 | SRC = gpio.c 10 | 11 | SRCS = $(SRC) $(INCLUDE_ROOT)/poyoio.c 12 | OBJS = $(SRCS:.c=.o) 13 | 14 | 15 | all: code.hex data.hex data0.hex data1.hex data2.hex data3.hex 16 | 17 | # オブジェクトファイル生成 18 | %.o: %.c Makefile 19 | $(CC) $(CFLAGS) -o $@ -c $< 20 | 21 | # 下記はアセンブリコードを入力する場合の例 22 | #%.o: %.s Makefile 23 | # $(CC) $(CFLAGS) -o $@ -c $< 24 | 25 | # ELFファイル生成 26 | app.elf: $(OBJS) $(CRTOBJ) Makefile 27 | $(LD) $(CRTOBJ) $(OBJS) $(LIBC) $(LIBGCC) -T$(LDSCRIPT) $(LDFLAGS) -o app.elf 28 | 29 | # バイナリファイル生成 30 | app.bin: app.elf 31 | $(OBJDUMP) -D $< > app.dump 32 | $(OBJCOPY) -O binary $< $@ 33 | 34 | # バイナリファイルから.hex形式ファイルを生成 35 | app.hex: app.bin 36 | hexdump -v -e '1/4 "%08x" "\n"' $< > app_im.hex 37 | cat $(MEM_INIT) app_im.hex > $@ 38 | rm -f app_im.hex 39 | 40 | # .hex形式ファイルを命令メモリ用ファイルとデータメモリ用ファイルへと分割 41 | code.hex data.hex: app.hex 42 | $(HEX_CONVERTER) $< 43 | 44 | 45 | .PHONY: clean 46 | clean: 47 | rm $(OBJS) code.hex code32k.hex data.hex data0.hex data1.hex data2.hex data3.hex app.hex app.dump app.bin app.elf crt0.o -f 48 | -------------------------------------------------------------------------------- /software/test/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for c code 3 | # 4 | 5 | # 共通初期設定ファイルをインクルード 6 | include ../software_tools/Makefile.inc 7 | 8 | # C言語ソースコードファイルを指定 9 | SRC = test.c 10 | 11 | SRCS = $(SRC) $(INCLUDE_ROOT)/poyoio.c 12 | OBJS = $(SRCS:.c=.o) 13 | 14 | 15 | all: code.hex code32k.hex data.hex data0.hex data1.hex data2.hex data3.hex 16 | 17 | # オブジェクトファイル生成 18 | %.o: %.c Makefile 19 | $(CC) $(CFLAGS) -o $@ -c $< 20 | 21 | # 下記はアセンブリコードを入力する場合の例 22 | #%.o: %.s Makefile 23 | # $(CC) $(CFLAGS) -o $@ -c $< 24 | 25 | # ELFファイル生成 26 | app.elf: $(OBJS) $(CRTOBJ) Makefile 27 | $(LD) $(CRTOBJ) $(OBJS) $(LIBC) $(LIBGCC) -T$(LDSCRIPT) $(LDFLAGS) -o app.elf 28 | 29 | # バイナリファイル生成 30 | app.bin: app.elf 31 | $(OBJDUMP) -D $< > app.dump 32 | $(OBJCOPY) -O binary $< $@ 33 | 34 | # バイナリファイルから.hex形式ファイルを生成 35 | app.hex: app.bin 36 | hexdump -v -e '1/4 "%08x" "\n"' $< > app_im.hex 37 | cat $(MEM_INIT) app_im.hex > $@ 38 | rm -f app_im.hex 39 | 40 | # .hex形式ファイルを命令メモリ用ファイルとデータメモリ用ファイルへと分割 41 | code.hex data.hex: app.hex 42 | $(HEX_CONVERTER) $< 43 | 44 | 45 | .PHONY: clean 46 | clean: 47 | rm $(OBJS) code.hex code32k.hex data.hex data0.hex data1.hex data2.hex data3.hex app.hex app.dump app.bin app.elf crt0.o -f 48 | -------------------------------------------------------------------------------- /software/serial_read/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for c code 3 | # 4 | 5 | # 共通初期設定ファイルをインクルード 6 | include ../software_tools/Makefile.inc 7 | 8 | # C言語ソースコードファイルを指定 9 | SRC = serial_read.c 10 | 11 | SRCS = $(SRC) $(INCLUDE_ROOT)/poyoio.c 12 | OBJS = $(SRCS:.c=.o) 13 | 14 | 15 | all: code.hex data.hex data0.hex data1.hex data2.hex data3.hex 16 | 17 | # オブジェクトファイル生成 18 | %.o: %.c Makefile 19 | $(CC) $(CFLAGS) -o $@ -c $< 20 | 21 | # 下記はアセンブリコードを入力する場合の例 22 | #%.o: %.s Makefile 23 | # $(CC) $(CFLAGS) -o $@ -c $< 24 | 25 | # ELFファイル生成 26 | app.elf: $(OBJS) $(CRTOBJ) Makefile 27 | $(LD) $(CRTOBJ) $(OBJS) $(LIBC) $(LIBGCC) -T$(LDSCRIPT) $(LDFLAGS) -o app.elf 28 | 29 | # バイナリファイル生成 30 | app.bin: app.elf 31 | $(OBJDUMP) -D $< > app.dump 32 | $(OBJCOPY) -O binary $< $@ 33 | 34 | # バイナリファイルから.hex形式ファイルを生成 35 | app.hex: app.bin 36 | hexdump -v -e '1/4 "%08x" "\n"' $< > app_im.hex 37 | cat $(MEM_INIT) app_im.hex > $@ 38 | rm -f app_im.hex 39 | 40 | # .hex形式ファイルを命令メモリ用ファイルとデータメモリ用ファイルへと分割 41 | code.hex data.hex: app.hex 42 | $(HEX_CONVERTER) $< 43 | 44 | 45 | .PHONY: clean 46 | clean: 47 | rm $(OBJS) code.hex code32k.hex data.hex data0.hex data1.hex data2.hex data3.hex app.hex app.dump app.bin app.elf crt0.o -f 48 | -------------------------------------------------------------------------------- /software/serial_write/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for c code 3 | # 4 | 5 | # 共通初期設定ファイルをインクルード 6 | include ../software_tools/Makefile.inc 7 | 8 | # C言語ソースコードファイルを指定 9 | SRC = serial_write.c 10 | 11 | SRCS = $(SRC) $(INCLUDE_ROOT)/poyoio.c 12 | OBJS = $(SRCS:.c=.o) 13 | 14 | 15 | all: code.hex data.hex data0.hex data1.hex data2.hex data3.hex 16 | 17 | # オブジェクトファイル生成 18 | %.o: %.c Makefile 19 | $(CC) $(CFLAGS) -o $@ -c $< 20 | 21 | # 下記はアセンブリコードを入力する場合の例 22 | #%.o: %.s Makefile 23 | # $(CC) $(CFLAGS) -o $@ -c $< 24 | 25 | # ELFファイル生成 26 | app.elf: $(OBJS) $(CRTOBJ) Makefile 27 | $(LD) $(CRTOBJ) $(OBJS) $(LIBC) $(LIBGCC) -T$(LDSCRIPT) $(LDFLAGS) -o app.elf 28 | 29 | # バイナリファイル生成 30 | app.bin: app.elf 31 | $(OBJDUMP) -D $< > app.dump 32 | $(OBJCOPY) -O binary $< $@ 33 | 34 | # バイナリファイルから.hex形式ファイルを生成 35 | app.hex: app.bin 36 | hexdump -v -e '1/4 "%08x" "\n"' $< > app_im.hex 37 | cat $(MEM_INIT) app_im.hex > $@ 38 | rm -f app_im.hex 39 | 40 | # .hex形式ファイルを命令メモリ用ファイルとデータメモリ用ファイルへと分割 41 | code.hex data.hex: app.hex 42 | $(HEX_CONVERTER) $< 43 | 44 | 45 | .PHONY: clean 46 | clean: 47 | rm $(OBJS) code.hex code32k.hex data.hex data0.hex data1.hex data2.hex data3.hex app.hex app.dump app.bin app.elf crt0.o -f 48 | -------------------------------------------------------------------------------- /software/software_tools/include/poyoio.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void digital_write(int pin, int vol) { 5 | 6 | volatile char* output_addr = GPO_WRADDR; 7 | volatile int* input_addr = GPO_RDADDR; 8 | 9 | // 0ビット目は0ピンの状態、1ビット目は1ピンの状態というように値を格納しているので、 10 | // ピンの値に応じたビットのみを変更する 11 | if (vol == 1) { 12 | *output_addr = (*input_addr | (1 << pin)); 13 | } else if (vol == 0) { 14 | *output_addr = (*input_addr & ~(1 << pin)); 15 | } 16 | } 17 | 18 | 19 | int digital_read(int pin) { 20 | 21 | volatile int* input_addr = GPI_ADDR; 22 | int vol; 23 | 24 | // 0ビット目は0ピンの状態、1ビット目は1ピンの状態というように値を格納しているので、 25 | // ピンの値に応じて特定ビットを読み出す 26 | vol = (*input_addr >> pin) & 1; 27 | 28 | return vol; 29 | } 30 | 31 | 32 | void serial_write(char c) { 33 | 34 | volatile char* output_addr = UART_TX_ADDR; 35 | 36 | delay(UART_TX_DELAY_TIME); 37 | *output_addr = c; 38 | } 39 | 40 | 41 | char serial_read() { 42 | 43 | volatile int* input_addr = UART_RX_ADDR; 44 | char c; 45 | 46 | c = *input_addr; 47 | 48 | return c; 49 | } 50 | 51 | 52 | void delay(unsigned int time) { 53 | 54 | volatile unsigned int* input_addr = HARDWARE_COUNTER_ADDR; 55 | unsigned int start_cycle = *input_addr; 56 | 57 | while (time > 0) { 58 | while ((*input_addr - start_cycle) >= HARDWARE_COUNT_FOR_ONE_MSEC) { 59 | time--; 60 | start_cycle += HARDWARE_COUNT_FOR_ONE_MSEC; 61 | } 62 | if (*input_addr < start_cycle) { 63 | start_cycle = *input_addr; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /software/software_tools/Makefile.inc: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile.inc 3 | # 4 | 5 | # リポジトリのルートディレクトリの場所を環境に合わせて指定(要変更) 6 | PROJECT_ROOT = $(HOME)/Git/poyo-v 7 | 8 | # GCCのインストールパスを環境に合わせて指定(要変更) 9 | GCC_DIR = /opt/riscv 10 | 11 | # GCCのバージョンを環境に合わせて指定(要変更) 12 | GCC_VERSION = 10.2.0 13 | 14 | # 各種ファイルの場所を指定 15 | TEST_CODE_ROOT = . 16 | TOOLS_ROOT = $(PROJECT_ROOT)/software/software_tools 17 | INCLUDE_ROOT = $(TOOLS_ROOT)/include 18 | 19 | # GCCの設定 20 | GCC_PREFIX = riscv32-unknown-elf- 21 | GCC_TOOLS = $(GCC_DIR)/bin 22 | 23 | CC = $(GCC_TOOLS)/$(GCC_PREFIX)gcc 24 | AS = $(GCC_TOOLS)/$(GCC_PREFIX)as 25 | LD = $(GCC_TOOLS)/$(GCC_PREFIX)ld 26 | OBJCOPY = $(GCC_TOOLS)/$(GCC_PREFIX)objcopy 27 | OBJDUMP = $(GCC_TOOLS)/$(GCC_PREFIX)objdump 28 | 29 | 30 | CFLAGS = \ 31 | -g \ 32 | -O3 \ 33 | -fno-zero-initialized-in-bss \ 34 | -ffreestanding \ 35 | -fno-builtin \ 36 | -nostdlib \ 37 | -nodefaultlibs \ 38 | -nostartfiles \ 39 | -mstrict-align \ 40 | -I $(INCLUDE_ROOT) \ 41 | -march=rv32i \ 42 | 43 | #-march=rv32im \ 44 | #-mno-div \ 45 | 46 | 47 | LDFLAGS= \ 48 | -static \ 49 | 50 | LIBC = 51 | LIBGCC = \ 52 | -L $(GCC_DIR)/lib/gcc/riscv32-unknown-elf/$(GCC_VERSION) \ 53 | -lgcc \ 54 | -lgcov \ 55 | -L $(GCC_DIR)/riscv32-unknown-elf/lib \ 56 | -lm \ 57 | 58 | 59 | # スタートアップルーチンとリンカスクリプトの指定 60 | CRTASM = $(TOOLS_ROOT)/crt0.s 61 | CRTOBJ = $(TEST_CODE_ROOT)/crt0.o 62 | LDSCRIPT = $(TOOLS_ROOT)/ld.script 63 | 64 | $(CRTOBJ): $(CRTASM) 65 | $(CC) $(CFLAGS) -o $@ -c $< 66 | 67 | 68 | # 下位Makefileを正常動作させるための変数定義 69 | .DEFAULT_GOAL = 70 | 71 | # メモリ初期化用ファイルの指定 72 | MEM_INIT = $(TOOLS_ROOT)/mem_init.hex 73 | 74 | # .hex形式ファイル生成ツールの指定 75 | HEX_CONVERTER = \ 76 | python3 $(TOOLS_ROOT)/hex_converter.py 77 | -------------------------------------------------------------------------------- /software/coremark/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for Coremark 3 | # 4 | 5 | # 共通初期設定ファイルをインクルード 6 | include ../software_tools/Makefile.inc 7 | 8 | # Coremark用の設定 9 | # 実行回数を指定(0の場合は自動算出) 10 | ITERATIONS = 0 11 | # 周波数[Hz]を指定 12 | CLOCKS_PER_SEC = 45000000 13 | # 最適化フラグを指定 14 | FLAGS_STR = "-O3" 15 | 16 | # C言語ソースコードファイルを指定 17 | SRC = \ 18 | core_list_join.c \ 19 | core_main.c \ 20 | core_matrix.c \ 21 | core_state.c \ 22 | core_util.c \ 23 | 24 | BAREBONES_ROOT = barebones 25 | BAREBONES_SRC = \ 26 | $(BAREBONES_ROOT)/core_portme.c \ 27 | $(BAREBONES_ROOT)/ee_printf.c \ 28 | 29 | SRCS = $(SRC) $(BAREBONES_SRC) 30 | OBJS = $(SRCS:.c=.o) 31 | 32 | XCFLAGS = \ 33 | -g \ 34 | -DITERATIONS=$(ITERATIONS) \ 35 | -DCLOCKS_PER_SEC=$(CLOCKS_PER_SEC) \ 36 | -I ./ \ 37 | -I $(BAREBONES_ROOT) \ 38 | -DFLAGS_STR=\"$(FLAGS_STR)\" \ 39 | 40 | 41 | all: code.hex data.hex data0.hex data1.hex data2.hex data3.hex 42 | 43 | # オブジェクトファイル生成 44 | %.o: %.c Makefile 45 | $(CC) $(CFLAGS) $(XCFLAGS) -o $@ -c $< 46 | 47 | # 下記はアセンブリコードを入力する場合の例 48 | #%.o: %.s Makefile 49 | # $(CC) $(CFLAGS) -o $@ -c $< 50 | 51 | # ELFファイル生成 52 | app.elf: $(OBJS) $(CRTOBJ) Makefile 53 | $(LD) $(CRTOBJ) $(OBJS) $(LIBC) $(LIBGCC) -T$(LDSCRIPT) $(LDFLAGS) -o app.elf 54 | 55 | # バイナリファイル生成 56 | app.bin: app.elf 57 | $(OBJDUMP) -D $< > app.dump 58 | $(OBJCOPY) -O binary $< $@ 59 | 60 | # バイナリファイルから.hex形式ファイルを生成 61 | app.hex: app.bin 62 | hexdump -v -e '1/4 "%08x" "\n"' $< > app_im.hex 63 | cat $(MEM_INIT) app_im.hex > $@ 64 | rm -f app_im.hex 65 | 66 | # .hex形式ファイルを命令メモリ用ファイルとデータメモリ用ファイルへと分割 67 | code.hex data.hex: app.hex 68 | $(HEX_CONVERTER) $< 69 | 70 | 71 | .PHONY: clean 72 | clean: 73 | rm $(OBJS) code.hex code32k.hex data.hex data0.hex data1.hex data2.hex data3.hex app.hex app.dump app.bin app.elf crt0.o -f 74 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/uart.v: -------------------------------------------------------------------------------- 1 | // 2 | // uart 3 | // 4 | 5 | 6 | `include "define.vh" 7 | 8 | module uart ( 9 | input wire clk, 10 | input wire rst_n, 11 | input wire [7:0] wr_data, 12 | input wire wr_en, 13 | output reg uart_tx 14 | ); 15 | 16 | // UART用クロック生成用信号 17 | wire uart_clk; 18 | reg [28:0] val; 19 | wire [28:0] next_val; 20 | wire [28:0] delta; 21 | 22 | // シフトレジスタ関係 23 | reg [3:0] bit_count; 24 | reg [8:0] shift_reg; 25 | wire en_seq; 26 | 27 | // システムクロックをUART用クロックへ変換 28 | assign delta = val[28] ? (`BAUD_RATE) : (`BAUD_RATE - `SYSCLK_FREQ); 29 | assign next_val = val + delta; 30 | 31 | assign uart_clk = ~val[28]; // 1システムクロック幅だけ立ち上がるUART用クロック 32 | 33 | always @(posedge clk or negedge rst_n) begin 34 | if (!rst_n) begin 35 | val <= 29'b0; 36 | end else begin 37 | val <= next_val; 38 | end 39 | end 40 | 41 | // ビットカウンタ 42 | always @(posedge clk or negedge rst_n) begin 43 | if (!rst_n) begin 44 | bit_count <= 4'd0; 45 | end else begin 46 | if (wr_en && (!en_seq)) begin 47 | bit_count <= 4'd11; // スタート 1bit + データ 8bit + ストップ 2bit で 合計 11bit 48 | end else if (uart_clk && en_seq) begin 49 | bit_count <= bit_count - 4'd1; 50 | end 51 | end 52 | end 53 | 54 | assign en_seq = (bit_count != 4'd0); // カウンタが0でなければ送信中 55 | 56 | // シフトレジスタ 57 | always @(posedge clk or negedge rst_n) begin 58 | if (!rst_n) begin 59 | shift_reg <= 9'd0; 60 | end else begin 61 | if (wr_en && (!en_seq)) begin 62 | shift_reg <= {wr_data[7:0], 1'd0}; // パラレルデータをシフトレジスタへ格納 63 | end else if (uart_clk && en_seq) begin 64 | shift_reg <= {1'd1, shift_reg[8:1]}; 65 | end 66 | end 67 | end 68 | 69 | // データ送信 70 | always @(posedge clk or negedge rst_n) begin 71 | if (!rst_n) begin 72 | uart_tx <= 1'b1; 73 | end else begin 74 | if (uart_clk && en_seq) begin 75 | uart_tx <= shift_reg[0]; 76 | end 77 | end 78 | end 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/define.vh: -------------------------------------------------------------------------------- 1 | // 2 | // define.vh 3 | // 4 | 5 | 6 | // プログラムが格納されたディレクトリの絶対パスを指定 7 | `define MEM_DATA_PATH "D:/Github/poyo-v/software/Coremark_RV32I_45MHz/" 8 | // `define MEM_DATA_PATH "D:/Github/poyo-v/software/coremark/" 9 | 10 | // システムクロックの周波数とその半分の値を指定 11 | `define SYSCLK_FREQ 45000000 12 | `define SYSCLK_FREQ_HALF 22500000 13 | 14 | // UARTのbaud rateを指定 15 | `define BAUD_RATE 115200 16 | 17 | // データメモリの開始アドレスと容量を指定 18 | `define DMEM_START_ADDR 32'h10000 19 | `define DMEM_SIZE 32'h10000 20 | 21 | // address for hardware counter 22 | `define HARDWARE_COUNTER_ADDR 32'h20010 23 | 24 | // address for UART 25 | `define UART_TX_ADDR 32'h20020 26 | `define UART_RX_ADDR 32'h20030 27 | 28 | // address for GPIO 29 | `define GPI_ADDR 32'h20040 30 | `define GPO_ADDR 32'h20050 31 | 32 | `define ENABLE 1'b1 33 | `define DISABLE 1'b0 34 | 35 | // 命令形式 36 | `define TYPE_NONE 3'd0 37 | `define TYPE_U 3'd1 38 | `define TYPE_J 3'd2 39 | `define TYPE_I 3'd3 40 | `define TYPE_B 3'd4 41 | `define TYPE_S 3'd5 42 | `define TYPE_R 3'd6 43 | 44 | // OPコード 45 | `define LUI 7'b0110111 46 | `define AUIPC 7'b0010111 47 | `define JAL 7'b1101111 48 | `define JALR 7'b1100111 49 | `define BRANCH 7'b1100011 50 | `define LOAD 7'b0000011 51 | `define STORE 7'b0100011 52 | `define OPIMM 7'b0010011 53 | `define OP 7'b0110011 54 | 55 | // DSTレジスタの有無 56 | `define REG_NONE 1'd0 57 | `define REG_RD 1'd1 58 | 59 | // ALUコード 60 | `define ALU_LUI 6'd0 61 | `define ALU_JAL 6'd1 62 | `define ALU_JALR 6'd2 63 | `define ALU_BEQ 6'd3 64 | `define ALU_BNE 6'd4 65 | `define ALU_BLT 6'd5 66 | `define ALU_BGE 6'd6 67 | `define ALU_BLTU 6'd7 68 | `define ALU_BGEU 6'd8 69 | `define ALU_LB 6'd9 70 | `define ALU_LH 6'd10 71 | `define ALU_LW 6'd11 72 | `define ALU_LBU 6'd12 73 | `define ALU_LHU 6'd13 74 | `define ALU_SB 6'd14 75 | `define ALU_SH 6'd15 76 | `define ALU_SW 6'd16 77 | `define ALU_ADD 6'd17 78 | `define ALU_SUB 6'd18 79 | `define ALU_SLT 6'd19 80 | `define ALU_SLTU 6'd20 81 | `define ALU_XOR 6'd21 82 | `define ALU_OR 6'd22 83 | `define ALU_AND 6'd23 84 | `define ALU_SLL 6'd24 85 | `define ALU_SRL 6'd25 86 | `define ALU_SRA 6'd26 87 | `define ALU_NOP 6'd63 88 | 89 | // ALU入力タイプ 90 | `define OP_TYPE_NONE 2'd0 91 | `define OP_TYPE_REG 2'd1 92 | `define OP_TYPE_IMM 2'd2 93 | `define OP_TYPE_PC 2'd3 94 | -------------------------------------------------------------------------------- /software/software_tools/hex_converter.py: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | 3 | import sys 4 | 5 | 6 | # code.hexとdata.hexを分離 7 | def split(file_name): 8 | f = open(file_name, 'r', encoding="UTF-8") 9 | line_list = f.readlines() 10 | 11 | line_list_0 = [] 12 | line_list_1 = [] 13 | 14 | for i, line in enumerate(line_list): 15 | byte_list = list(line) 16 | if i < 16384: 17 | line_list_0.append(''.join(byte_list)) 18 | else: 19 | line_list_1.append(''.join(byte_list)) 20 | 21 | f.close() 22 | 23 | f0 = open("code.hex", 'w', encoding="UTF-8") 24 | f0.writelines(line_list_0) 25 | f0.close() 26 | 27 | f1 = open("data.hex", 'w', encoding="UTF-8") 28 | f1.writelines(line_list_1) 29 | f1.close() 30 | 31 | 32 | # code.hexを2ファイルへと分割 33 | def code_split(file_name): 34 | f = open(file_name, 'r', encoding="UTF-8") 35 | line_list = f.readlines() 36 | 37 | line_list_0 = [] 38 | 39 | for i, line in enumerate(line_list): 40 | byte_list = list(line) 41 | if i > 8191: 42 | line_list_0.append(''.join(byte_list)) 43 | 44 | f.close() 45 | 46 | f0 = open("code32k.hex", 'w', encoding="UTF-8") 47 | f0.writelines(line_list_0) 48 | f0.close() 49 | 50 | 51 | # data.hexを4ファイルへと分割 52 | def data_split(file_name): 53 | f = open(file_name, 'r', encoding="UTF-8") 54 | line_list = f.readlines() 55 | 56 | line_list_0 = [] 57 | line_list_1 = [] 58 | line_list_2 = [] 59 | line_list_3 = [] 60 | 61 | for line in line_list: 62 | byte_list = list(line) 63 | line_list_0.append(''.join(byte_list[6:8]) + "\n") 64 | line_list_1.append(''.join(byte_list[4:6]) + "\n") 65 | line_list_2.append(''.join(byte_list[2:4]) + "\n") 66 | line_list_3.append(''.join(byte_list[0:2]) + "\n") 67 | 68 | f.close() 69 | 70 | f0 = open("data0.hex", 'w', encoding="UTF-8") 71 | f0.writelines(line_list_0) 72 | f0.close() 73 | 74 | f1 = open("data1.hex", 'w', encoding="UTF-8") 75 | f1.writelines(line_list_1) 76 | f1.close() 77 | 78 | f2 = open("data2.hex", 'w', encoding="UTF-8") 79 | f2.writelines(line_list_2) 80 | f2.close() 81 | 82 | f3 = open("data3.hex", 'w', encoding="UTF-8") 83 | f3.writelines(line_list_3) 84 | f3.close() 85 | 86 | 87 | if __name__ == "__main__": 88 | args = sys.argv 89 | if len(args) == 2: 90 | prog_file_name = args[1] 91 | code_file_name = "code.hex" 92 | data_file_name = "data.hex" 93 | split(prog_file_name) 94 | code_split(code_file_name) 95 | data_split(data_file_name) 96 | 97 | else: 98 | print("usage: python hexConverter.py ") 99 | quit() 100 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/alu.v: -------------------------------------------------------------------------------- 1 | // 2 | // alu 3 | // 4 | 5 | 6 | `include "define.vh" 7 | 8 | module alu ( 9 | input wire [5:0] alucode, 10 | input wire [31:0] op1, 11 | input wire [31:0] op2, 12 | output reg [31:0] alu_result, 13 | output reg br_taken 14 | ); 15 | 16 | wire signed [31:0] signed_op1; 17 | wire signed [31:0] signed_op2; 18 | reg signed [31:0] signed_alu_result; 19 | 20 | // 符号付き計算用 21 | assign signed_op1 = op1; 22 | assign signed_op2 = op2; 23 | 24 | always @* begin 25 | case (alucode) 26 | `ALU_LUI: begin 27 | alu_result = op2; 28 | br_taken = `DISABLE; 29 | end 30 | `ALU_JAL, `ALU_JALR: begin 31 | alu_result = op2 + 32'd4; 32 | br_taken = `ENABLE; 33 | end 34 | `ALU_BEQ: begin 35 | alu_result = 32'd0; 36 | br_taken = (op1 == op2); 37 | end 38 | `ALU_BNE: begin 39 | alu_result = 32'd0; 40 | br_taken = (op1 != op2); 41 | end 42 | `ALU_BLT: begin 43 | alu_result = 32'd0; 44 | br_taken = (signed_op1 < signed_op2); 45 | end 46 | `ALU_BGE: begin 47 | alu_result = 32'd0; 48 | br_taken = (signed_op1 >= signed_op2); 49 | end 50 | `ALU_BLTU: begin 51 | alu_result = 32'd0; 52 | br_taken = (op1 < op2); 53 | end 54 | `ALU_BGEU: begin 55 | alu_result = 32'd0; 56 | br_taken = (op1 >= op2); 57 | end 58 | `ALU_LB, `ALU_LH, `ALU_LW, `ALU_LBU, `ALU_LHU, `ALU_SB, `ALU_SH, `ALU_SW: begin 59 | alu_result = op1 + op2; 60 | br_taken = `DISABLE; 61 | end 62 | `ALU_ADD: begin 63 | alu_result = op1 + op2; 64 | br_taken = `DISABLE; 65 | end 66 | `ALU_SUB: begin 67 | alu_result = op1 - op2; 68 | br_taken = `DISABLE; 69 | end 70 | `ALU_SLT: begin 71 | alu_result = (signed_op1 < signed_op2) ? 32'd1 : 32'd0; 72 | br_taken = `DISABLE; 73 | end 74 | `ALU_SLTU: begin 75 | alu_result = (op1 < op2) ? 32'd1 : 32'd0; 76 | br_taken = `DISABLE; 77 | end 78 | `ALU_XOR: begin 79 | alu_result = op1 ^ op2; 80 | br_taken = `DISABLE; 81 | end 82 | `ALU_OR: begin 83 | alu_result = op1 | op2; 84 | br_taken = `DISABLE; 85 | end 86 | `ALU_AND: begin 87 | alu_result = op1 & op2; 88 | br_taken = `DISABLE; 89 | end 90 | `ALU_SLL: begin 91 | alu_result = op1 << op2[4:0]; 92 | br_taken = `DISABLE; 93 | end 94 | `ALU_SRL: begin 95 | alu_result = op1 >> op2[4:0]; 96 | br_taken = `DISABLE; 97 | end 98 | `ALU_SRA: begin 99 | signed_alu_result = signed_op1 >>> signed_op2[4:0]; 100 | alu_result = signed_alu_result; 101 | br_taken = `DISABLE; 102 | end 103 | default: begin 104 | alu_result = 32'd0; 105 | br_taken = `DISABLE; 106 | end 107 | endcase 108 | end 109 | 110 | endmodule 111 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/uart_rx.v: -------------------------------------------------------------------------------- 1 | // 2 | // uart_rx 3 | // 4 | 5 | 6 | `include "define.vh" 7 | 8 | module uart_rx( 9 | input wire clk, 10 | input wire rst_n, 11 | input wire uart_rx, 12 | output reg [7:0] rd_data, 13 | output reg rd_en 14 | ); 15 | 16 | // UART用クロック生成用信号 17 | wire uart_clk; 18 | reg [28:0] val; 19 | wire [28:0] next_val; 20 | wire [28:0] delta; 21 | 22 | // 受信データの立下りエッジ検出 23 | reg [2:0] edge_shift_reg; 24 | 25 | // 受信開始信号 26 | wire rd_begin; 27 | 28 | // 受信データのビットカウンタ 29 | reg [3:0] bit_count; 30 | wire en_seq; 31 | 32 | // SerDes用シフトレジスタ 33 | reg [10:0] shift_reg; 34 | 35 | // 受信データチェック用信号 36 | reg reception; 37 | wire data_valid; 38 | 39 | 40 | // システムクロックをUART用クロックへ変換 41 | assign delta = val[28] ? (`BAUD_RATE) : (`BAUD_RATE - `SYSCLK_FREQ); 42 | assign next_val = val + delta; 43 | 44 | assign uart_clk = ~val[28]; // 1システムクロック幅だけ立ち上がるUART用クロック 45 | 46 | always @(posedge clk or negedge rst_n) begin 47 | if (!rst_n) begin 48 | val <= 29'b0; 49 | end else if (rd_begin) begin 50 | val <= -`SYSCLK_FREQ_HALF; // 半クロックだけずらしてデータの中央を叩く 51 | end else if (en_seq) begin 52 | val <= next_val; 53 | end else begin 54 | val <= 29'b0; 55 | end 56 | end 57 | 58 | // データの立下り(スタートビット)検出 59 | always @(posedge clk or negedge rst_n) begin 60 | if (!rst_n) begin 61 | edge_shift_reg[2:0] <= 3'd0; 62 | end else begin 63 | edge_shift_reg[2:0] <= {edge_shift_reg[1:0], uart_rx}; 64 | end 65 | end 66 | 67 | assign rd_begin = ((edge_shift_reg[2:1] == 2'b10) && (en_seq == 1'b0)); 68 | 69 | // ビットカウンタ 70 | always @(posedge clk or negedge rst_n) begin 71 | if (!rst_n) begin 72 | bit_count <= 4'd0; 73 | end else begin 74 | if (rd_begin && (!en_seq)) begin 75 | bit_count <= 4'd11; // スタート 1bit + データ 8bit + ストップ 2bit で 合計 11bit 76 | end else if (uart_clk && en_seq) begin 77 | bit_count <= bit_count - 4'd1; 78 | end 79 | end 80 | end 81 | 82 | assign en_seq = (bit_count != 4'd0); // カウンタが0でなければ受信中 83 | 84 | // シフトレジスタ 85 | always @(posedge clk or negedge rst_n) begin 86 | if (!rst_n) begin 87 | shift_reg <= 11'd0; // 1埋め 88 | end else if (uart_clk && en_seq) begin 89 | shift_reg <= {edge_shift_reg[2], shift_reg[10:1]}; // 受信データを取り込んでシフト 90 | end 91 | end 92 | 93 | // 受信完了信号 94 | always @(posedge clk or negedge rst_n) begin 95 | if (!rst_n) begin 96 | reception <= 1'b0; 97 | end else if (uart_clk && en_seq) begin 98 | if (bit_count == 4'd1) begin 99 | reception <= 1'b1; 100 | end else begin 101 | reception <= 1'b0; 102 | end 103 | end 104 | end 105 | 106 | assign data_valid = ((shift_reg[0] == 1'b0) && (shift_reg[10:9] == 2'b11)); // スタート/エンドビットのチェック 107 | 108 | // 受信データ 109 | always @(posedge clk or negedge rst_n) begin 110 | if (!rst_n) begin 111 | rd_data <= 8'd0; 112 | end else if (reception && data_valid) begin 113 | rd_data <= shift_reg[8:1]; // スタートビットとエンドビットが合っていればデータ読み出し 114 | end else begin 115 | rd_data <= rd_data; 116 | end 117 | end 118 | 119 | // データ読出し可否 120 | always @(posedge clk or negedge rst_n) begin 121 | if (!rst_n) begin 122 | rd_en <= 1'b0; 123 | end else if (reception && data_valid) begin 124 | rd_en <= 1'b1; // スタートビットとエンドビットが合っていれば受信完了 125 | end else begin 126 | rd_en <= 1'b0; 127 | end 128 | end 129 | 130 | endmodule 131 | -------------------------------------------------------------------------------- /software/coremark/barebones/core_portme.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | #include "coremark.h" 19 | #include "core_portme.h" 20 | 21 | #if VALIDATION_RUN 22 | volatile ee_s32 seed1_volatile = 0x3415; 23 | volatile ee_s32 seed2_volatile = 0x3415; 24 | volatile ee_s32 seed3_volatile = 0x66; 25 | #endif 26 | #if PERFORMANCE_RUN 27 | volatile ee_s32 seed1_volatile = 0x0; 28 | volatile ee_s32 seed2_volatile = 0x0; 29 | volatile ee_s32 seed3_volatile = 0x66; 30 | #endif 31 | #if PROFILE_RUN 32 | volatile ee_s32 seed1_volatile = 0x8; 33 | volatile ee_s32 seed2_volatile = 0x8; 34 | volatile ee_s32 seed3_volatile = 0x8; 35 | #endif 36 | volatile ee_s32 seed4_volatile = ITERATIONS; 37 | volatile ee_s32 seed5_volatile = 0; 38 | /* Porting : Timing functions 39 | How to capture time and convert to seconds must be ported to whatever is 40 | supported by the platform. e.g. Read value from on board RTC, read value from 41 | cpu clock cycles performance counter etc. Sample implementation for standard 42 | time.h and windows.h definitions included. 43 | */ 44 | CORETIMETYPE 45 | barebones_clock() 46 | { 47 | volatile unsigned int* hardware_count = (unsigned int*)0x20010; 48 | return (CORETIMETYPE)*hardware_count; 49 | } 50 | /* Define : TIMER_RES_DIVIDER 51 | Divider to trade off timer resolution and total time that can be 52 | measured. 53 | 54 | Use lower values to increase resolution, but make sure that overflow 55 | does not occur. If there are issues with the return value overflowing, 56 | increase this value. 57 | */ 58 | #define GETMYTIME(_t) (*_t = barebones_clock()) 59 | #define MYTIMEDIFF(fin, ini) ((fin) - (ini)) 60 | #define TIMER_RES_DIVIDER 1 61 | #define SAMPLE_TIME_IMPLEMENTATION 1 62 | #define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER) 63 | 64 | /** Define Host specific (POSIX), or target specific global time variables. */ 65 | static CORETIMETYPE start_time_val, stop_time_val; 66 | 67 | /* Function : start_time 68 | This function will be called right before starting the timed portion of 69 | the benchmark. 70 | 71 | Implementation may be capturing a system timer (as implemented in the 72 | example code) or zeroing some system parameters - e.g. setting the cpu clocks 73 | cycles to 0. 74 | */ 75 | void 76 | start_time(void) 77 | { 78 | GETMYTIME(&start_time_val); 79 | } 80 | /* Function : stop_time 81 | This function will be called right after ending the timed portion of the 82 | benchmark. 83 | 84 | Implementation may be capturing a system timer (as implemented in the 85 | example code) or other system parameters - e.g. reading the current value of 86 | cpu cycles counter. 87 | */ 88 | void 89 | stop_time(void) 90 | { 91 | GETMYTIME(&stop_time_val); 92 | } 93 | /* Function : get_time 94 | Return an abstract "ticks" number that signifies time on the system. 95 | 96 | Actual value returned may be cpu cycles, milliseconds or any other 97 | value, as long as it can be converted to seconds by . This 98 | methodology is taken to accomodate any hardware or simulated platform. The 99 | sample implementation returns millisecs by default, and the resolution is 100 | controlled by 101 | */ 102 | CORE_TICKS 103 | get_time(void) 104 | { 105 | CORE_TICKS elapsed 106 | = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); 107 | return elapsed; 108 | } 109 | /* Function : time_in_secs 110 | Convert the value returned by get_time to seconds. 111 | 112 | The type is used to accomodate systems with no support for 113 | floating point. Default implementation implemented by the EE_TICKS_PER_SEC 114 | macro above. 115 | */ 116 | secs_ret 117 | time_in_secs(CORE_TICKS ticks) 118 | { 119 | secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; 120 | return retval; 121 | } 122 | 123 | ee_u32 default_num_contexts = 1; 124 | 125 | /* Function : portable_init 126 | Target specific initialization code 127 | Test for some common mistakes. 128 | */ 129 | void 130 | portable_init(core_portable *p, int *argc, char *argv[]) 131 | { 132 | //#error \ 133 | "Call board initialization routines in portable init (if needed), in particular initialize UART!\n" 134 | if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) 135 | { 136 | ee_printf( 137 | "ERROR! Please define ee_ptr_int to a type that holds a " 138 | "pointer!\n"); 139 | } 140 | if (sizeof(ee_u32) != 4) 141 | { 142 | ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); 143 | } 144 | p->portable_id = 1; 145 | } 146 | /* Function : portable_fini 147 | Target specific final code 148 | */ 149 | void 150 | portable_fini(core_portable *p) 151 | { 152 | p->portable_id = 0; 153 | } 154 | -------------------------------------------------------------------------------- /software/coremark/coremark.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | 19 | /* Topic: Description 20 | This file contains declarations of the various benchmark functions. 21 | */ 22 | 23 | /* Configuration: TOTAL_DATA_SIZE 24 | Define total size for data algorithms will operate on 25 | */ 26 | #ifndef TOTAL_DATA_SIZE 27 | #define TOTAL_DATA_SIZE 2 * 1000 28 | #endif 29 | 30 | #define SEED_ARG 0 31 | #define SEED_FUNC 1 32 | #define SEED_VOLATILE 2 33 | 34 | #define MEM_STATIC 0 35 | #define MEM_MALLOC 1 36 | #define MEM_STACK 2 37 | 38 | #include "core_portme.h" 39 | 40 | #if HAS_STDIO 41 | #include 42 | #endif 43 | #if HAS_PRINTF 44 | #define ee_printf printf 45 | #endif 46 | 47 | /* Actual benchmark execution in iterate */ 48 | void *iterate(void *pres); 49 | 50 | /* Typedef: secs_ret 51 | For machines that have floating point support, get number of seconds as 52 | a double. Otherwise an unsigned int. 53 | */ 54 | #if HAS_FLOAT 55 | typedef double secs_ret; 56 | #else 57 | typedef ee_u32 secs_ret; 58 | #endif 59 | 60 | #if MAIN_HAS_NORETURN 61 | #define MAIN_RETURN_VAL 62 | #define MAIN_RETURN_TYPE void 63 | #else 64 | #define MAIN_RETURN_VAL 0 65 | #define MAIN_RETURN_TYPE int 66 | #endif 67 | 68 | void start_time(void); 69 | void stop_time(void); 70 | CORE_TICKS get_time(void); 71 | secs_ret time_in_secs(CORE_TICKS ticks); 72 | 73 | /* Misc useful functions */ 74 | ee_u16 crcu8(ee_u8 data, ee_u16 crc); 75 | ee_u16 crc16(ee_s16 newval, ee_u16 crc); 76 | ee_u16 crcu16(ee_u16 newval, ee_u16 crc); 77 | ee_u16 crcu32(ee_u32 newval, ee_u16 crc); 78 | ee_u8 check_data_types(void); 79 | void * portable_malloc(ee_size_t size); 80 | void portable_free(void *p); 81 | ee_s32 parseval(char *valstring); 82 | 83 | /* Algorithm IDS */ 84 | #define ID_LIST (1 << 0) 85 | #define ID_MATRIX (1 << 1) 86 | #define ID_STATE (1 << 2) 87 | #define ALL_ALGORITHMS_MASK (ID_LIST | ID_MATRIX | ID_STATE) 88 | #define NUM_ALGORITHMS 3 89 | 90 | /* list data structures */ 91 | typedef struct list_data_s 92 | { 93 | ee_s16 data16; 94 | ee_s16 idx; 95 | } list_data; 96 | 97 | typedef struct list_head_s 98 | { 99 | struct list_head_s *next; 100 | struct list_data_s *info; 101 | } list_head; 102 | 103 | /*matrix benchmark related stuff */ 104 | #define MATDAT_INT 1 105 | #if MATDAT_INT 106 | typedef ee_s16 MATDAT; 107 | typedef ee_s32 MATRES; 108 | #else 109 | typedef ee_f16 MATDAT; 110 | typedef ee_f32 MATRES; 111 | #endif 112 | 113 | typedef struct MAT_PARAMS_S 114 | { 115 | int N; 116 | MATDAT *A; 117 | MATDAT *B; 118 | MATRES *C; 119 | } mat_params; 120 | 121 | /* state machine related stuff */ 122 | /* List of all the possible states for the FSM */ 123 | typedef enum CORE_STATE 124 | { 125 | CORE_START = 0, 126 | CORE_INVALID, 127 | CORE_S1, 128 | CORE_S2, 129 | CORE_INT, 130 | CORE_FLOAT, 131 | CORE_EXPONENT, 132 | CORE_SCIENTIFIC, 133 | NUM_CORE_STATES 134 | } core_state_e; 135 | 136 | /* Helper structure to hold results */ 137 | typedef struct RESULTS_S 138 | { 139 | /* inputs */ 140 | ee_s16 seed1; /* Initializing seed */ 141 | ee_s16 seed2; /* Initializing seed */ 142 | ee_s16 seed3; /* Initializing seed */ 143 | void * memblock[4]; /* Pointer to safe memory location */ 144 | ee_u32 size; /* Size of the data */ 145 | ee_u32 iterations; /* Number of iterations to execute */ 146 | ee_u32 execs; /* Bitmask of operations to execute */ 147 | struct list_head_s *list; 148 | mat_params mat; 149 | /* outputs */ 150 | ee_u16 crc; 151 | ee_u16 crclist; 152 | ee_u16 crcmatrix; 153 | ee_u16 crcstate; 154 | ee_s16 err; 155 | /* ultithread specific */ 156 | core_portable port; 157 | } core_results; 158 | 159 | /* Multicore execution handling */ 160 | #if (MULTITHREAD > 1) 161 | ee_u8 core_start_parallel(core_results *res); 162 | ee_u8 core_stop_parallel(core_results *res); 163 | #endif 164 | 165 | /* list benchmark functions */ 166 | list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed); 167 | ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx); 168 | 169 | /* state benchmark functions */ 170 | void core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p); 171 | ee_u16 core_bench_state(ee_u32 blksize, 172 | ee_u8 *memblock, 173 | ee_s16 seed1, 174 | ee_s16 seed2, 175 | ee_s16 step, 176 | ee_u16 crc); 177 | 178 | /* matrix benchmark functions */ 179 | ee_u32 core_init_matrix(ee_u32 blksize, 180 | void * memblk, 181 | ee_s32 seed, 182 | mat_params *p); 183 | ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc); 184 | -------------------------------------------------------------------------------- /software/coremark/barebones/core_portme.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | /* Topic : Description 19 | This file contains configuration constants required to execute on 20 | different platforms 21 | */ 22 | #ifndef CORE_PORTME_H 23 | #define CORE_PORTME_H 24 | /************************/ 25 | /* Data types and settings */ 26 | /************************/ 27 | /* Configuration : HAS_FLOAT 28 | Define to 1 if the platform supports floating point. 29 | */ 30 | #ifndef HAS_FLOAT 31 | #define HAS_FLOAT 0 32 | #endif 33 | /* Configuration : HAS_TIME_H 34 | Define to 1 if platform has the time.h header file, 35 | and implementation of functions thereof. 36 | */ 37 | #ifndef HAS_TIME_H 38 | #define HAS_TIME_H 0 39 | #endif 40 | /* Configuration : USE_CLOCK 41 | Define to 1 if platform has the time.h header file, 42 | and implementation of functions thereof. 43 | */ 44 | #ifndef USE_CLOCK 45 | #define USE_CLOCK 0 46 | #endif 47 | /* Configuration : HAS_STDIO 48 | Define to 1 if the platform has stdio.h. 49 | */ 50 | #ifndef HAS_STDIO 51 | #define HAS_STDIO 0 52 | #endif 53 | /* Configuration : HAS_PRINTF 54 | Define to 1 if the platform has stdio.h and implements the printf 55 | function. 56 | */ 57 | #ifndef HAS_PRINTF 58 | #define HAS_PRINTF 0 59 | #endif 60 | 61 | /* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION 62 | Initialize these strings per platform 63 | */ 64 | #ifndef COMPILER_VERSION 65 | #ifdef __GNUC__ 66 | #define COMPILER_VERSION "GCC"__VERSION__ 67 | #else 68 | #define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" 69 | #endif 70 | #endif 71 | #ifndef COMPILER_FLAGS 72 | #define COMPILER_FLAGS \ 73 | FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ 74 | #endif 75 | #ifndef MEM_LOCATION 76 | #define MEM_LOCATION "STACK" 77 | #endif 78 | 79 | /* Data Types : 80 | To avoid compiler issues, define the data types that need ot be used for 81 | 8b, 16b and 32b in . 82 | 83 | *Imprtant* : 84 | ee_ptr_int needs to be the data type used to hold pointers, otherwise 85 | coremark may fail!!! 86 | */ 87 | typedef signed short ee_s16; 88 | typedef unsigned short ee_u16; 89 | typedef signed int ee_s32; 90 | typedef double ee_f32; 91 | typedef unsigned char ee_u8; 92 | typedef unsigned int ee_u32; 93 | typedef ee_u32 ee_ptr_int; 94 | typedef unsigned int size_t; 95 | typedef size_t ee_size_t; 96 | #define NULL ((void *)0) 97 | /* align_mem : 98 | This macro is used to align an offset to point to a 32b value. It is 99 | used in the Matrix algorithm to initialize the input memory blocks. 100 | */ 101 | #define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) 102 | 103 | /* Configuration : CORE_TICKS 104 | Define type of return from the timing functions. 105 | */ 106 | #define CORETIMETYPE ee_u32 107 | typedef ee_u32 CORE_TICKS; 108 | 109 | /* Configuration : SEED_METHOD 110 | Defines method to get seed values that cannot be computed at compile 111 | time. 112 | 113 | Valid values : 114 | SEED_ARG - from command line. 115 | SEED_FUNC - from a system function. 116 | SEED_VOLATILE - from volatile variables. 117 | */ 118 | #ifndef SEED_METHOD 119 | #define SEED_METHOD SEED_VOLATILE 120 | #endif 121 | 122 | /* Configuration : MEM_METHOD 123 | Defines method to get a block of memry. 124 | 125 | Valid values : 126 | MEM_MALLOC - for platforms that implement malloc and have malloc.h. 127 | MEM_STATIC - to use a static memory array. 128 | MEM_STACK - to allocate the data block on the stack (NYI). 129 | */ 130 | #ifndef MEM_METHOD 131 | #define MEM_METHOD MEM_STACK 132 | #endif 133 | 134 | /* Configuration : MULTITHREAD 135 | Define for parallel execution 136 | 137 | Valid values : 138 | 1 - only one context (default). 139 | N>1 - will execute N copies in parallel. 140 | 141 | Note : 142 | If this flag is defined to more then 1, an implementation for launching 143 | parallel contexts must be defined. 144 | 145 | Two sample implementations are provided. Use or 146 | to enable them. 147 | 148 | It is valid to have a different implementation of 149 | and in , to fit a particular architecture. 150 | */ 151 | #ifndef MULTITHREAD 152 | #define MULTITHREAD 1 153 | #define USE_PTHREAD 0 154 | #define USE_FORK 0 155 | #define USE_SOCKET 0 156 | #endif 157 | 158 | /* Configuration : MAIN_HAS_NOARGC 159 | Needed if platform does not support getting arguments to main. 160 | 161 | Valid values : 162 | 0 - argc/argv to main is supported 163 | 1 - argc/argv to main is not supported 164 | 165 | Note : 166 | This flag only matters if MULTITHREAD has been defined to a value 167 | greater then 1. 168 | */ 169 | #ifndef MAIN_HAS_NOARGC 170 | #define MAIN_HAS_NOARGC 1 171 | #endif 172 | 173 | /* Configuration : MAIN_HAS_NORETURN 174 | Needed if platform does not support returning a value from main. 175 | 176 | Valid values : 177 | 0 - main returns an int, and return value will be 0. 178 | 1 - platform does not support returning a value from main 179 | */ 180 | #ifndef MAIN_HAS_NORETURN 181 | #define MAIN_HAS_NORETURN 0 182 | #endif 183 | 184 | /* Variable : default_num_contexts 185 | Not used for this simple port, must cintain the value 1. 186 | */ 187 | extern ee_u32 default_num_contexts; 188 | 189 | typedef struct CORE_PORTABLE_S 190 | { 191 | ee_u8 portable_id; 192 | } core_portable; 193 | 194 | /* target specific init/fini */ 195 | void portable_init(core_portable *p, int *argc, char *argv[]); 196 | void portable_fini(core_portable *p); 197 | 198 | #if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \ 199 | && !defined(VALIDATION_RUN) 200 | #if (TOTAL_DATA_SIZE == 1200) 201 | #define PROFILE_RUN 1 202 | #elif (TOTAL_DATA_SIZE == 2000) 203 | #define PERFORMANCE_RUN 1 204 | #else 205 | #define VALIDATION_RUN 1 206 | #endif 207 | #endif 208 | 209 | int ee_printf(const char *fmt, ...); 210 | 211 | #endif /* CORE_PORTME_H */ 212 | -------------------------------------------------------------------------------- /software/coremark/core_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | 19 | #include "coremark.h" 20 | /* Function: get_seed 21 | Get a values that cannot be determined at compile time. 22 | 23 | Since different embedded systems and compilers are used, 3 different 24 | methods are provided: 1 - Using a volatile variable. This method is only 25 | valid if the compiler is forced to generate code that reads the value of a 26 | volatile variable from memory at run time. Please note, if using this method, 27 | you would need to modify core_portme.c to generate training profile. 2 - 28 | Command line arguments. This is the preferred method if command line 29 | arguments are supported. 3 - System function. If none of the first 2 methods 30 | is available on the platform, a system function which is not a stub can be 31 | used. 32 | 33 | e.g. read the value on GPIO pins connected to switches, or invoke 34 | special simulator functions. 35 | */ 36 | #if (SEED_METHOD == SEED_VOLATILE) 37 | extern volatile ee_s32 seed1_volatile; 38 | extern volatile ee_s32 seed2_volatile; 39 | extern volatile ee_s32 seed3_volatile; 40 | extern volatile ee_s32 seed4_volatile; 41 | extern volatile ee_s32 seed5_volatile; 42 | ee_s32 43 | get_seed_32(int i) 44 | { 45 | ee_s32 retval; 46 | switch (i) 47 | { 48 | case 1: 49 | retval = seed1_volatile; 50 | break; 51 | case 2: 52 | retval = seed2_volatile; 53 | break; 54 | case 3: 55 | retval = seed3_volatile; 56 | break; 57 | case 4: 58 | retval = seed4_volatile; 59 | break; 60 | case 5: 61 | retval = seed5_volatile; 62 | break; 63 | default: 64 | retval = 0; 65 | break; 66 | } 67 | return retval; 68 | } 69 | #elif (SEED_METHOD == SEED_ARG) 70 | ee_s32 71 | parseval(char *valstring) 72 | { 73 | ee_s32 retval = 0; 74 | ee_s32 neg = 1; 75 | int hexmode = 0; 76 | if (*valstring == '-') 77 | { 78 | neg = -1; 79 | valstring++; 80 | } 81 | if ((valstring[0] == '0') && (valstring[1] == 'x')) 82 | { 83 | hexmode = 1; 84 | valstring += 2; 85 | } 86 | /* first look for digits */ 87 | if (hexmode) 88 | { 89 | while (((*valstring >= '0') && (*valstring <= '9')) 90 | || ((*valstring >= 'a') && (*valstring <= 'f'))) 91 | { 92 | ee_s32 digit = *valstring - '0'; 93 | if (digit > 9) 94 | digit = 10 + *valstring - 'a'; 95 | retval *= 16; 96 | retval += digit; 97 | valstring++; 98 | } 99 | } 100 | else 101 | { 102 | while ((*valstring >= '0') && (*valstring <= '9')) 103 | { 104 | ee_s32 digit = *valstring - '0'; 105 | retval *= 10; 106 | retval += digit; 107 | valstring++; 108 | } 109 | } 110 | /* now add qualifiers */ 111 | if (*valstring == 'K') 112 | retval *= 1024; 113 | if (*valstring == 'M') 114 | retval *= 1024 * 1024; 115 | 116 | retval *= neg; 117 | return retval; 118 | } 119 | 120 | ee_s32 121 | get_seed_args(int i, int argc, char *argv[]) 122 | { 123 | if (argc > i) 124 | return parseval(argv[i]); 125 | return 0; 126 | } 127 | 128 | #elif (SEED_METHOD == SEED_FUNC) 129 | /* If using OS based function, you must define and implement the functions below 130 | * in core_portme.h and core_portme.c ! */ 131 | ee_s32 132 | get_seed_32(int i) 133 | { 134 | ee_s32 retval; 135 | switch (i) 136 | { 137 | case 1: 138 | retval = portme_sys1(); 139 | break; 140 | case 2: 141 | retval = portme_sys2(); 142 | break; 143 | case 3: 144 | retval = portme_sys3(); 145 | break; 146 | case 4: 147 | retval = portme_sys4(); 148 | break; 149 | case 5: 150 | retval = portme_sys5(); 151 | break; 152 | default: 153 | retval = 0; 154 | break; 155 | } 156 | return retval; 157 | } 158 | #endif 159 | 160 | /* Function: crc* 161 | Service functions to calculate 16b CRC code. 162 | 163 | */ 164 | ee_u16 165 | crcu8(ee_u8 data, ee_u16 crc) 166 | { 167 | ee_u8 i = 0, x16 = 0, carry = 0; 168 | 169 | for (i = 0; i < 8; i++) 170 | { 171 | x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1)); 172 | data >>= 1; 173 | 174 | if (x16 == 1) 175 | { 176 | crc ^= 0x4002; 177 | carry = 1; 178 | } 179 | else 180 | carry = 0; 181 | crc >>= 1; 182 | if (carry) 183 | crc |= 0x8000; 184 | else 185 | crc &= 0x7fff; 186 | } 187 | return crc; 188 | } 189 | ee_u16 190 | crcu16(ee_u16 newval, ee_u16 crc) 191 | { 192 | crc = crcu8((ee_u8)(newval), crc); 193 | crc = crcu8((ee_u8)((newval) >> 8), crc); 194 | return crc; 195 | } 196 | ee_u16 197 | crcu32(ee_u32 newval, ee_u16 crc) 198 | { 199 | crc = crc16((ee_s16)newval, crc); 200 | crc = crc16((ee_s16)(newval >> 16), crc); 201 | return crc; 202 | } 203 | ee_u16 204 | crc16(ee_s16 newval, ee_u16 crc) 205 | { 206 | return crcu16((ee_u16)newval, crc); 207 | } 208 | 209 | ee_u8 210 | check_data_types() 211 | { 212 | ee_u8 retval = 0; 213 | if (sizeof(ee_u8) != 1) 214 | { 215 | ee_printf("ERROR: ee_u8 is not an 8b datatype!\n"); 216 | retval++; 217 | } 218 | if (sizeof(ee_u16) != 2) 219 | { 220 | ee_printf("ERROR: ee_u16 is not a 16b datatype!\n"); 221 | retval++; 222 | } 223 | if (sizeof(ee_s16) != 2) 224 | { 225 | ee_printf("ERROR: ee_s16 is not a 16b datatype!\n"); 226 | retval++; 227 | } 228 | if (sizeof(ee_s32) != 4) 229 | { 230 | ee_printf("ERROR: ee_s32 is not a 32b datatype!\n"); 231 | retval++; 232 | } 233 | if (sizeof(ee_u32) != 4) 234 | { 235 | ee_printf("ERROR: ee_u32 is not a 32b datatype!\n"); 236 | retval++; 237 | } 238 | if (sizeof(ee_ptr_int) != sizeof(int *)) 239 | { 240 | ee_printf( 241 | "ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n"); 242 | retval++; 243 | } 244 | if (retval > 0) 245 | { 246 | ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n"); 247 | } 248 | return retval; 249 | } 250 | -------------------------------------------------------------------------------- /src/pipeline_3stage/constraint/const.xdc: -------------------------------------------------------------------------------- 1 | ## This file is a general .xdc for the Cmod S7-25 Rev. B 2 | ## To use it in a project: 3 | ## - uncomment the lines corresponding to used pins 4 | ## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project 5 | 6 | ## 12 MHz System Clock 7 | set_property -dict { PACKAGE_PIN M9 IOSTANDARD LVCMOS33 } [get_ports { sys_clk }]; #IO_L13P_T2_MRCC_14 Sch=gclk 8 | create_clock -add -name sys_clk_pin -period 83.33 -waveform {0 41.66} [get_ports { sys_clk }]; 9 | 10 | ## Push Buttons 11 | set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { sys_rst }]; #IO_L6P_T0_34 Sch=btn[0] 12 | #set_property -dict { PACKAGE_PIN D1 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L6N_T0_VREF_34 Sch=btn[1] 13 | 14 | ## RGB LEDs 15 | #set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { led0_b }]; #IO_L10N_T1_34 Sch=led0_b 16 | #set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { led0_g }]; #IO_L9N_T1_DQS_34 Sch=led0_g 17 | #set_property -dict { PACKAGE_PIN F2 IOSTANDARD LVCMOS33 } [get_ports { led0_r }]; #IO_L10P_T1_34 Sch=led0_r 18 | 19 | ## 4 LEDs 20 | set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { gpo[0] }]; #IO_L8P_T1_34 Sch=led[1] 21 | set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { gpo[1] }]; #IO_L16P_T2_34 Sch=led[2] 22 | set_property -dict { PACKAGE_PIN J1 IOSTANDARD LVCMOS33 } [get_ports { gpo[2] }]; #IO_L16N_T2_34 Sch=led[3] 23 | set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { gpo[3] }]; #IO_L8N_T1_34 Sch=led[4] 24 | 25 | ## Pmod Header JA 26 | #set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L14P_T2_SRCC_34 Sch=ja[1] 27 | #set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L14N_T2_SRCC_34 Sch=ja[2] 28 | #set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L13P_T2_MRCC_34 Sch=ja[3] 29 | #set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L11N_T1_SRCC_34 Sch=ja[4] 30 | #set_property -dict { PACKAGE_PIN H3 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L13N_T2_MRCC_34 Sch=ja[7] 31 | #set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L12P_T1_MRCC_34 Sch=ja[8] 32 | #set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L12N_T1_MRCC_34 Sch=ja[9] 33 | #set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L11P_T1_SRCC_34 Sch=ja[10] 34 | 35 | ## USB UART 36 | ## Note: Port names are from the perspoctive of the FPGA. 37 | #set_property -dict { PACKAGE_PIN L12 IOSTANDARD LVCMOS33 } [get_ports { uart_tx }]; #IO_L6N_T0_D08_VREF_14 Sch=uart_rxd_out 38 | #set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { uart_rx }]; #IO_L5N_T0_D07_14 Sch=uart_txd_in 39 | 40 | ## Analog Inputs on PIO Pins 32 and 33 41 | #set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { vaux5_p }]; #IO_L12P_T1_MRCC_AD5P_15 Sch=ain_p[32] 42 | #set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { vaux5_n }]; #IO_L12N_T1_MRCC_AD5N_15 Sch=ain_n[32] 43 | #set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { vaux12_p }]; #IO_L11P_T1_SRCC_AD12P_15 Sch=ain_p[33] 44 | #set_property -dict { PACKAGE_PIN A12 IOSTANDARD LVCMOS33 } [get_ports { vaux12_n }]; #IO_L11N_T1_SRCC_AD12N_15 Sch=ain_n[33] 45 | 46 | ## Dedicated Digital I/O on the PIO Headers 47 | #set_property -dict { PACKAGE_PIN L1 IOSTANDARD LVCMOS33 } [get_ports { pio1 }]; #IO_L18N_T2_34 Sch=pio[01] 48 | #set_property -dict { PACKAGE_PIN M4 IOSTANDARD LVCMOS33 } [get_ports { pio2 }]; #IO_L19P_T3_34 Sch=pio[02] 49 | #set_property -dict { PACKAGE_PIN M3 IOSTANDARD LVCMOS33 } [get_ports { pio3 }]; #IO_L19N_T3_VREF_34 Sch=pio[03] 50 | #set_property -dict { PACKAGE_PIN N2 IOSTANDARD LVCMOS33 } [get_ports { pio4 }]; #IO_L20P_T3_34 Sch=pio[04] 51 | #set_property -dict { PACKAGE_PIN M2 IOSTANDARD LVCMOS33 } [get_ports { pio5 }]; #IO_L20N_T3_34 Sch=pio[05] 52 | #set_property -dict { PACKAGE_PIN P3 IOSTANDARD LVCMOS33 } [get_ports { pio6 }]; #IO_L21P_T3_DQS_34 Sch=pio[06] 53 | #set_property -dict { PACKAGE_PIN N3 IOSTANDARD LVCMOS33 } [get_ports { pio7 }]; #IO_L21N_T3_DQS_34 Sch=pio[07] 54 | #set_property -dict { PACKAGE_PIN P1 IOSTANDARD LVCMOS33 } [get_ports { pio8 }]; #IO_L22P_T3_34 Sch=pio[08] 55 | #set_property -dict { PACKAGE_PIN N1 IOSTANDARD LVCMOS33 } [get_ports { pio9 }]; #IO_L22N_T3_34 Sch=pio[09] 56 | #set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { pio16 }]; #IO_L11P_T1_SRCC_14 Sch=pio[16] 57 | #set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { pio17 }]; #IO_L11N_T1_SRCC_14 Sch=pio[17] 58 | #set_property -dict { PACKAGE_PIN N13 IOSTANDARD LVCMOS33 } [get_ports { pio18 }]; #IO_L8N_T1_D12_14 Sch=pio[18] 59 | #set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { pio19 }]; #IO_L10N_T1_D15_14 Sch=pio[19] 60 | #set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { pio20 }]; #IO_L10P_T1_D14_14 Sch=pio[20] 61 | #set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { pio21 }]; #IO_L9N_T1_DQS_D13_14 Sch=pio[21] 62 | #set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { pio22 }]; #IO_L9P_T1_DQS_14 Sch=pio[22] 63 | #set_property -dict { PACKAGE_PIN L15 IOSTANDARD LVCMOS33 } [get_ports { pio23 }]; #IO_L4N_T0_D05_14 Sch=pio[23] 64 | set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { uart }]; #IO_L7N_T1_D10_14 Sch=pio[26] 65 | #set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports { pio27 }]; #IO_L4P_T0_D04_14 Sch=pio[27] 66 | set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { uart_in }]; #IO_L5P_T0_D06_14 Sch=pio[28] 67 | #set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { pio29 }]; #IO_L7P_T1_D09_14 Sch=pio[29] 68 | #set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { pio30 }]; #IO_L8P_T1_D11_14 Sch=pio[30] 69 | #set_property -dict { PACKAGE_PIN J11 IOSTANDARD LVCMOS33 } [get_ports { pio31 }]; #IO_0_14 Sch=pio[31] 70 | set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { gpi[3] }]; #IO_L5P_T0_34 Sch=pio[40] 71 | set_property -dict { PACKAGE_PIN A2 IOSTANDARD LVCMOS33 } [get_ports { gpi[2] }]; #IO_L2N_T0_34 Sch=pio[41] 72 | set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { gpi[1] }]; #IO_L2P_T0_34 Sch=pio[42] 73 | set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { gpi[0] }]; #IO_L4N_T0_34 Sch=pio[43] 74 | #set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { pio44 }]; #IO_L4P_T0_34 Sch=pio[44] 75 | #set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { pio45 }]; #IO_L3N_T0_DQS_34 Sch=pio[45] 76 | #set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { pio46 }]; #IO_L3P_T0_DQS_34 Sch=pio[46] 77 | #set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { pio47 }]; #IO_L1N_T0_34 Sch=pio[47] 78 | #set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { pio48 }]; #IO_L1P_T0_34 Sch=pio[48] 79 | 80 | ## Quad SPI Flash 81 | ## Note: QSPI clock can only be accessed through the STARTUPE2 primitive 82 | #set_property -dict { PACKAGE_PIN L11 IOSTANDARD LVCMOS33 } [get_ports { qspi_cs }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_cs 83 | #set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] 84 | #set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1] 85 | #set_property -dict { PACKAGE_PIN J12 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] 86 | #set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] 87 | 88 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 89 | set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design] 90 | set_property CONFIG_MODE SPIx4 [current_design] -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # poyo-v 2 | poyo-vはFPGAやASICに使えるRISC-Vソフトプロセッサです。RV32Iの一通りの命令を実行可能な3段パイプラインインオーダプロセッサになっています。 3 | 4 | ## Running poyo-v on an FPGA 5 | ### 動作環境 6 | - OS: Windows10 or Ubuntu18.04 7 | - Vivado: 2018.3 8 | - FPGAボード: [ZYBO Z7-10](http://akizukidenshi.com/catalog/g/gM-12552/)等([ZYBO Z7-20](http://akizukidenshi.com/catalog/g/gM-12553/), [PYNQ-Z1](http://akizukidenshi.com/catalog/g/gM-13812/), [CMOD S7](http://akizukidenshi.com/catalog/g/gM-13487/)でも動作確認済。近年のXilinx社製FPGA搭載ボードであればだいたいどれでも動作可能と思われます。poyo-vは特定のIPに依存しないよう基本的に全てのモジュールがVerilog HDLのソースによって記述されています。) 9 | - USB-シリアル変換モジュール: [FT232RL](http://akizukidenshi.com/catalog/g/gK-01977/)等 10 | 11 | poyo-vをFPGA上で動かすためには、以下のような手順が必要です。 12 | 13 | ### 1. 本リポジトリをクローン 14 | このリポジトリをローカルに持ってきます。 15 | ``` 16 | $ git clone https://github.com/ourfool/poyo-v.git 17 | ``` 18 | 19 | ### 2. Vivadoへのファイル読み込み 20 | 新規プロジェクトを作成し、リポジトリ内の、`src/pipeline_3stage/design/`以下のファイルをソースとして、`poyo-v/src/pipeline_3stage/constraint/`以下を制約ファイルとして読み込みます。ここで制約ファイルは[CMOD S7](http://akizukidenshi.com/catalog/g/gM-13487/)向けのものになっているので、他のFPGAボードを利用する場合は合わせて各端子名を修正する必要があります。 21 | 22 | ### 3. ブロックデザインでのクロックモジュール生成 23 | 適切な周波数のクロックを生成するためVivadoのブロックデザインを利用してクロックモジュールを生成します。 24 | 具体的な手順としては、Vivado上の「Flow Navigator」 の 「IP INTEGRATOR」→「Create Block Design」を選択します。ウィンドウ上の+ボタンを押して、追加したいIPコアを検索すると、Clocking Wizardが見つかります。Clocking Wizardを追加したのちウィンドウに表示されたブロック図をダブルクリックすると、種々の設定をおこなうことができます。「Output Clocks」を選択し、「Output Freq」を変更すると、入力したクロック信号の周波数が所望の値に変化して出力されます。作成済みのCPUモジュールと組み合わせるには、「Sources」内に表示されたモジュールの名前を右クリックし、「Add module to Block Design」を選択します。するとBlock Designのウィンドウ上にモジュールが現れます。モジュールの各ポートをクリックすることで、モジュール同士を接続する線が引けます。また、FPGA外部に信号を入出力するためのportは、ウィンドウ上で右クリックしてCreate Portとすると生成できます。 25 | 26 | Clocking wizardとトップモジュールとを組み合わせ終わったら、Design Sources 内に表示されているBlock Design の名前を右クリックしCreate HDL Wrapperを選択します。確認のウィンドウでOKを押すと、HDLで書かれたラッパーが生成されます。最終的なFPGAへの書き込みの際には、このラッパーHDLを論理合成・配置配線していくことになります。ここで、論理合成・配置配線に用いるソースは太字で表示されています。HDLの名前を右クリックして、「Set as Top」を選択すると、名前が太字に変わり合成出来るようになります。 27 | 28 | ### 4. メモリデータパスの書き換え 29 | RISC-Vプロセッサのメモリに読み込む.hexファイルのパスを環境に合わせて修正します。修正する箇所は、`define.vh`内の`define MEM_DATA_PATH "D:/Github/poyo-v/software/Coremark_RV32I_45MHz/"`です。ローカル環境に合わせて 30 | `"D:/Github/poyo-v/software/Coremark_RV32I_45MHz/"`の場所を絶対パスで記述し直してください。 31 | 32 | ### 5. Bitstream生成・書き込み 33 | 各ファイルの修正完了後に、作成したVivadoプロジェクト上で、左端の**Flow Navigator**から**PROGRAM AND DEBUG**→**Generate Bitstream**を選択してBitstreamを生成します。完了したらPCとFPGAボードとを接続し、**Open Hardware Manager**から**Program device**を選択してFPGAボードへと書き込みます。 34 | 35 | ### 6. 動作確認 36 | サンプルプログラムは組み込み向けベンチマークの[Coremark](https://www.eembc.org/coremark/)です。`const.xdc`内で指定されたUART用端子とGND端子とをUSB-シリアル変換モジュールのRX端子とGND端子へそれぞれ接続し、PCへUSBケーブルを介してつなぐことで、UART出力をPC上のシリアルターミナルソフト(Teraterm、gtkterm、Arduino IDE付属のターミナル等)で確認することができます。シリアルターミナルソフトのbaudrateは115200に設定してください。 37 | 38 | 39 | 40 | 各接続とターミナルソフトの設定を完了したら、動作確認をおこなうことができます。`const.xdc`内で指定されたリセットボタンを押すとプログラムが開始し、10秒ほどでシリアルターミナル上に完了のメッセージが表示されます。 41 | 42 | 43 | 44 | ## Creating an executable program file 45 | poyo-v上で動作するプログラムを作るためには、以下のような手順が必要です。 46 | 47 | ### 1. コンパイラツールチェーンの用意 48 | RISC-V RV32I向けの実行ファイルを生成するソフトウェアツールチェーンを用意します。gccの場合は[公式リポジトリ](https://github.com/riscv/riscv-gnu-toolchain)から導入することができます。これを利用することで、C言語で記述したコードをコンパイルしてRISC-V向けの実行ファイルを生成することができます。以降にクロスコンパイル環境を整えるための一連の作業を書いていきます。なお、開発環境としてはWSL(Windows Subsystem for Linux)、またはその他の仮想環境上でのUbuntuの利用を想定しています。 49 | 50 | まずは、ツールチェーンをビルドするために必要な各種パッケージを入手します。下記のようなコマンドで各種パッケージをインストールします。 51 | 52 | ``` 53 | $ sudo apt update 54 | $ sudo apt install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev 55 | ``` 56 | 57 | 続いて、公式のクロスコンパイラのリポジトリをクローンします。 58 | 59 | ``` 60 | $ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain 61 | ``` 62 | 63 | クローン作業が完了したら、リポジトリ内へと移動してツールチェーンのビルド作業をおこないます。下記のようなコマンドを打つことでビルドできます。ここで、--prefix=/opt/riscvによってツールチェーンのインストール先を指定し、--with-arch=rv32gによってRV32Iを含むRV32GC向けのクロスコンパイラを作ることを命じています。--with-abi=ilp32では浮動小数点演算はハードウェア側でサポートしない前提であることを伝えています。インストール先については変更しても問題ありません。ビルド時間は実行環境のコア数に合わせてmakeコマンド時に-jオプションを指定することで短縮できるかもしれません。 64 | 65 | ``` 66 | $ cd riscv-gnu-toolchain/ 67 | $ ./configure --prefix=/opt/riscv --with-arch=rv32g --with-abi=ilp32 68 | $ sudo make 69 | ``` 70 | 71 | 問題が無ければ1時間程度で完了します。成功していれば下記のコマンドに応じて 72 | 73 | ``` 74 | $ /opt/riscv/bin/riscv32-unknown-elf-gcc --version 75 | riscv32-unknown-elf-gcc (GCC) 9.2.0 76 | Copyright (C) 2019 Free Software Foundation, Inc. 77 | This is free software; see the source for copying conditions. There is NO 78 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 79 | ``` 80 | 81 | のように表示されます。インストール先を変更した場合、/opt/riscvの部分は異なります。クロスコンパイラ自体も随時開発が進められているため、最新版に問題が生じる場合もあるかもしれません。その場合はクローン作業の代わりに、リポジトリの[リリースページ](https://github.com/riscv/riscv-gnu-toolchain/releases)から既にリリースされているバージョン(2019年8月現在では、「v20180629」が最新リリース)のソースをダウンロードして使います。 82 | 83 | ### 2. makeによるビルド 84 | クロスコンパイラによって実行ファイルを生成し、そこからobjcopy等を利用して.bin形式のファイルを生成します、続いてこれを.hex形式へ変換し、命令メモリと4つのデータメモリ向けに分割することによって最終的に読み込む.hexファイルが揃います。この作業をまとめたMakeファイルの例が`software/test/Makefile`として用意されています。おこなわれる作業の詳細については実際のMakefile`software/test/Makefile`やそのインクルードファイル`software/software_tools/Makefile.inc`、リンカスクリプト`software/software_tools/ld.script`、.hexファイルへの変換スクリプト`hex_converter.py`を参照してください。 85 | 86 | 利用に先立って、Makefile実行用のインクルード・ファイル`software/software_tools/Makefile.inc`をローカル環境に合わせて修正する必要があります。 87 | 88 | ``` 89 | $ cd software/software_tools/ 90 | $ vi Makefile.inc 91 | ``` 92 | 93 | として、リポジトリのルート・ディレクトリの場所と先ほどGCCをインストールした場所、導入したGCCのバージョンを必要に応じて変更します。 94 | 95 | ``` 96 | # リポジトリのルートディレクトリの場所を環境に合わせて指定(要変更) 97 | PROJECT_ROOT = $(HOME)/poyo-v 98 | 99 | # GCCのインストールパスを環境に合わせて指定(要変更) 100 | GCC_DIR = /opt/riscv 101 | 102 | # GCCのバージョンを環境に合わせて指定(要変更) 103 | GCC_VERSION = 9.2.0 104 | ``` 105 | 106 | 修正完了後に、Makefileと同一の階層にC言語で記述されたコード(デフォルトではtest.cという名前に設定する。変更の場合は合わせてMakefile修正が必要)を用意し、 107 | 108 | ``` 109 | $ cd software/test/ 110 | $ make 111 | ``` 112 | 113 | とすればメモリへ読み込み可能な各種.hexファイルが生成されます。 114 | 115 | 生成される.hexファイルはそれぞれ、 116 | 117 | * code.hex: 命令メモリ用ファイル(4byteのデータ×16384行(合計64KiB)、メモリマップの0x00000-0x0FFFFに対応) 118 | * code32k.hex: 命令メモリ用ファイル(4byteのデータ×8192行(合計32KiB)、メモリマップの0x08000-0x0FFFFに対応) 119 | * data.hex: データメモリ用ファイル(4byteのデータ×8192行(合計32KiB)、メモリマップの0x10000-0x17FFFに対応) 120 | * data{0, 1, 2, 3}.hex: 命令メモリ用ファイル(1byteのデータ×8192行(4ファイル合計で32KiB)、メモリマップの0x10000-0x17FFFに対応) 121 | 122 | となっており、メモリの仕様に応じて適切なものを利用します。FPGAの例では、`code.hex`と`data{0, 1, 2, 3}.hex`を利用します。 123 | 124 | ### A. メモリ周りの詳細仕様 125 | poyo-vにおいては以下のようなメモリマップを想定しています。 126 | 127 | |アドレス |容量 |内容 |対応する.hexファイル | 128 | |--- |--- |--- |--- | 129 | |0x00000-0x07FFF |32KiB |なし |software/${各プログラムのフォルダ名}/code.hex | 130 | |0x08000-0x0FFFF |32KiB |.text(ROM) |software/${各プログラムのフォルダ名}/code.hex | 131 | |0x10000-0x17FFF |32KiB |.rodata + .data + .bss + .comment(RAM) |software/${各プログラムのフォルダ名}/data{0, 1, 2, 3}.hex | 132 | |0x18000-0x1FFFF |32KiB |stack(RAM) |なし | 133 | |0x20010 |. |hardware counter用アドレス |なし | 134 | |0x20020 |. |uart送信用アドレス |なし | 135 | |0x20030 |. |uart受信用アドレス |なし | 136 | |0x20040 |. |汎用入力ピン用アドレス |なし | 137 | |0x20050 |. |汎用出力ピン用アドレス |なし | 138 | 139 | また、poyo-vの読み込めるcode.hexファイル形式は、一行あたり4byteのデータ×16384行(合計64KiB)のテキストファイルです。一行あたり16進数で8文字が書かれており、一つの命令を表しています。たとえば、`0080006f`という行の場合は 140 | 141 | |[3]番地 |[2]番地 |[1]番地 |[0]番地 | 142 | |:---: |:---: |:---: |:---: | 143 | |00 |80 |00 |6F | 144 | 145 | というバイトオーダで命令メモリへ格納されることになります。 146 | 147 | すなわち命令メモリの中身は、 148 | 149 | |番地 |格納されたデータ | 150 | |--- |--- | 151 | |0 |code.hexの1行目{7,8}番目文字 | 152 | |1 |code.hexの1行目{5,6}番目文字 | 153 | |2 |code.hexの1行目{3,4}番目文字 | 154 | |3 |code.hexの1行目{1,2}番目文字 | 155 | |4 |code.hexの2行目{7,8}番目文字 | 156 | |5 |code.hexの2行目{5,6}番目文字 | 157 | |6 |code.hexの2行目{3,4}番目文字 | 158 | |7 |code.hexの2行目{1,2}番目文字 | 159 | |. |. | 160 | |. |. | 161 | |. |. | 162 | |n |code.hexの {n/4+1} 行目 {7-2x,8-2x(x≡n(mod 4))} 番目文字 | 163 | 164 | となります。 165 | 166 | 一方、data{0, 1, 2, 3}.hexは、一行あたり1byteのデータ×8192行(4ファイル合計で32KiB)のテキストファイルです。 167 | 168 | |[3]番地 |[2]番地 |[1]番地 |[0]番地 | 169 | |:---: |:---: |:---: |:---: | 170 | |data3.hexに記述された値 |data2.hexに記述された値 |data1.hexに記述された値 |data0.hexに記述された値 | 171 | 172 | というようにデータメモリへ格納されることになります。 173 | 174 | すなわちデータメモリの中身は、 175 | 176 | |番地 |格納されたデータ | 177 | |--- |--- | 178 | |0 |data0.hexの1行目 | 179 | |1 |data1.hexの1行目 | 180 | |2 |data2.hexの1行目 | 181 | |3 |data3.hexの1行目 | 182 | |4 |data0.hexの2行目 | 183 | |5 |data1.hexの2行目 | 184 | |6 |data2.hexの2行目 | 185 | |7 |data3.hexの2行目 | 186 | |. |. | 187 | |. |. | 188 | |. |. | 189 | |n |data{x}.hex (x≡n(mod 4)) の {n/4+1} 行目 | 190 | 191 | となります。poyo-vのデータメモリ(dmem.v)は実際には4つのインスタンスへと分割されて呼び出されており、それぞれのインスタンスが対応するファイルを読み込んでいます。 192 | 193 | 194 | ## License 195 | * This project is released under the MIT License - see the [LICENSE](LICENSE) file for details. 196 | * This project includes the work that is distributed in the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). 197 | -------------------------------------------------------------------------------- /software/coremark/core_state.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | 19 | #include "coremark.h" 20 | /* local functions */ 21 | enum CORE_STATE core_state_transition(ee_u8 **instr, ee_u32 *transition_count); 22 | 23 | /* 24 | Topic: Description 25 | Simple state machines like this one are used in many embedded products. 26 | 27 | For more complex state machines, sometimes a state transition table 28 | implementation is used instead, trading speed of direct coding for ease of 29 | maintenance. 30 | 31 | Since the main goal of using a state machine in CoreMark is to excercise 32 | the switch/if behaviour, we are using a small moore machine. 33 | 34 | In particular, this machine tests type of string input, 35 | trying to determine whether the input is a number or something else. 36 | (see core_state.png). 37 | */ 38 | 39 | /* Function: core_bench_state 40 | Benchmark function 41 | 42 | Go over the input twice, once direct, and once after introducing some 43 | corruption. 44 | */ 45 | ee_u16 46 | core_bench_state(ee_u32 blksize, 47 | ee_u8 *memblock, 48 | ee_s16 seed1, 49 | ee_s16 seed2, 50 | ee_s16 step, 51 | ee_u16 crc) 52 | { 53 | ee_u32 final_counts[NUM_CORE_STATES]; 54 | ee_u32 track_counts[NUM_CORE_STATES]; 55 | ee_u8 *p = memblock; 56 | ee_u32 i; 57 | 58 | #if CORE_DEBUG 59 | ee_printf("State Bench: %d,%d,%d,%04x\n", seed1, seed2, step, crc); 60 | #endif 61 | for (i = 0; i < NUM_CORE_STATES; i++) 62 | { 63 | final_counts[i] = track_counts[i] = 0; 64 | } 65 | /* run the state machine over the input */ 66 | while (*p != 0) 67 | { 68 | enum CORE_STATE fstate = core_state_transition(&p, track_counts); 69 | final_counts[fstate]++; 70 | #if CORE_DEBUG 71 | ee_printf("%d,", fstate); 72 | } 73 | ee_printf("\n"); 74 | #else 75 | } 76 | #endif 77 | p = memblock; 78 | while (p < (memblock + blksize)) 79 | { /* insert some corruption */ 80 | if (*p != ',') 81 | *p ^= (ee_u8)seed1; 82 | p += step; 83 | } 84 | p = memblock; 85 | /* run the state machine over the input again */ 86 | while (*p != 0) 87 | { 88 | enum CORE_STATE fstate = core_state_transition(&p, track_counts); 89 | final_counts[fstate]++; 90 | #if CORE_DEBUG 91 | ee_printf("%d,", fstate); 92 | } 93 | ee_printf("\n"); 94 | #else 95 | } 96 | #endif 97 | p = memblock; 98 | while (p < (memblock + blksize)) 99 | { /* undo corruption is seed1 and seed2 are equal */ 100 | if (*p != ',') 101 | *p ^= (ee_u8)seed2; 102 | p += step; 103 | } 104 | /* end timing */ 105 | for (i = 0; i < NUM_CORE_STATES; i++) 106 | { 107 | crc = crcu32(final_counts[i], crc); 108 | crc = crcu32(track_counts[i], crc); 109 | } 110 | return crc; 111 | } 112 | 113 | /* Default initialization patterns */ 114 | static ee_u8 *intpat[4] 115 | = { (ee_u8 *)"5012", (ee_u8 *)"1234", (ee_u8 *)"-874", (ee_u8 *)"+122" }; 116 | static ee_u8 *floatpat[4] = { (ee_u8 *)"35.54400", 117 | (ee_u8 *)".1234500", 118 | (ee_u8 *)"-110.700", 119 | (ee_u8 *)"+0.64400" }; 120 | static ee_u8 *scipat[4] = { (ee_u8 *)"5.500e+3", 121 | (ee_u8 *)"-.123e-2", 122 | (ee_u8 *)"-87e+832", 123 | (ee_u8 *)"+0.6e-12" }; 124 | static ee_u8 *errpat[4] = { (ee_u8 *)"T0.3e-1F", 125 | (ee_u8 *)"-T.T++Tq", 126 | (ee_u8 *)"1T3.4e4z", 127 | (ee_u8 *)"34.0e-T^" }; 128 | 129 | /* Function: core_init_state 130 | Initialize the input data for the state machine. 131 | 132 | Populate the input with several predetermined strings, interspersed. 133 | Actual patterns chosen depend on the seed parameter. 134 | 135 | Note: 136 | The seed parameter MUST be supplied from a source that cannot be 137 | determined at compile time 138 | */ 139 | void 140 | core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p) 141 | { 142 | ee_u32 total = 0, next = 0, i; 143 | ee_u8 *buf = 0; 144 | #if CORE_DEBUG 145 | ee_u8 *start = p; 146 | ee_printf("State: %d,%d\n", size, seed); 147 | #endif 148 | size--; 149 | next = 0; 150 | while ((total + next + 1) < size) 151 | { 152 | if (next > 0) 153 | { 154 | for (i = 0; i < next; i++) 155 | *(p + total + i) = buf[i]; 156 | *(p + total + i) = ','; 157 | total += next + 1; 158 | } 159 | seed++; 160 | switch (seed & 0x7) 161 | { 162 | case 0: /* int */ 163 | case 1: /* int */ 164 | case 2: /* int */ 165 | buf = intpat[(seed >> 3) & 0x3]; 166 | next = 4; 167 | break; 168 | case 3: /* float */ 169 | case 4: /* float */ 170 | buf = floatpat[(seed >> 3) & 0x3]; 171 | next = 8; 172 | break; 173 | case 5: /* scientific */ 174 | case 6: /* scientific */ 175 | buf = scipat[(seed >> 3) & 0x3]; 176 | next = 8; 177 | break; 178 | case 7: /* invalid */ 179 | buf = errpat[(seed >> 3) & 0x3]; 180 | next = 8; 181 | break; 182 | default: /* Never happen, just to make some compilers happy */ 183 | break; 184 | } 185 | } 186 | size++; 187 | while (total < size) 188 | { /* fill the rest with 0 */ 189 | *(p + total) = 0; 190 | total++; 191 | } 192 | #if CORE_DEBUG 193 | ee_printf("State Input: %s\n", start); 194 | #endif 195 | } 196 | 197 | static ee_u8 198 | ee_isdigit(ee_u8 c) 199 | { 200 | ee_u8 retval; 201 | retval = ((c >= '0') & (c <= '9')) ? 1 : 0; 202 | return retval; 203 | } 204 | 205 | /* Function: core_state_transition 206 | Actual state machine. 207 | 208 | The state machine will continue scanning until either: 209 | 1 - an invalid input is detcted. 210 | 2 - a valid number has been detected. 211 | 212 | The input pointer is updated to point to the end of the token, and the 213 | end state is returned (either specific format determined or invalid). 214 | */ 215 | 216 | enum CORE_STATE 217 | core_state_transition(ee_u8 **instr, ee_u32 *transition_count) 218 | { 219 | ee_u8 * str = *instr; 220 | ee_u8 NEXT_SYMBOL; 221 | enum CORE_STATE state = CORE_START; 222 | for (; *str && state != CORE_INVALID; str++) 223 | { 224 | NEXT_SYMBOL = *str; 225 | if (NEXT_SYMBOL == ',') /* end of this input */ 226 | { 227 | str++; 228 | break; 229 | } 230 | switch (state) 231 | { 232 | case CORE_START: 233 | if (ee_isdigit(NEXT_SYMBOL)) 234 | { 235 | state = CORE_INT; 236 | } 237 | else if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') 238 | { 239 | state = CORE_S1; 240 | } 241 | else if (NEXT_SYMBOL == '.') 242 | { 243 | state = CORE_FLOAT; 244 | } 245 | else 246 | { 247 | state = CORE_INVALID; 248 | transition_count[CORE_INVALID]++; 249 | } 250 | transition_count[CORE_START]++; 251 | break; 252 | case CORE_S1: 253 | if (ee_isdigit(NEXT_SYMBOL)) 254 | { 255 | state = CORE_INT; 256 | transition_count[CORE_S1]++; 257 | } 258 | else if (NEXT_SYMBOL == '.') 259 | { 260 | state = CORE_FLOAT; 261 | transition_count[CORE_S1]++; 262 | } 263 | else 264 | { 265 | state = CORE_INVALID; 266 | transition_count[CORE_S1]++; 267 | } 268 | break; 269 | case CORE_INT: 270 | if (NEXT_SYMBOL == '.') 271 | { 272 | state = CORE_FLOAT; 273 | transition_count[CORE_INT]++; 274 | } 275 | else if (!ee_isdigit(NEXT_SYMBOL)) 276 | { 277 | state = CORE_INVALID; 278 | transition_count[CORE_INT]++; 279 | } 280 | break; 281 | case CORE_FLOAT: 282 | if (NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e') 283 | { 284 | state = CORE_S2; 285 | transition_count[CORE_FLOAT]++; 286 | } 287 | else if (!ee_isdigit(NEXT_SYMBOL)) 288 | { 289 | state = CORE_INVALID; 290 | transition_count[CORE_FLOAT]++; 291 | } 292 | break; 293 | case CORE_S2: 294 | if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') 295 | { 296 | state = CORE_EXPONENT; 297 | transition_count[CORE_S2]++; 298 | } 299 | else 300 | { 301 | state = CORE_INVALID; 302 | transition_count[CORE_S2]++; 303 | } 304 | break; 305 | case CORE_EXPONENT: 306 | if (ee_isdigit(NEXT_SYMBOL)) 307 | { 308 | state = CORE_SCIENTIFIC; 309 | transition_count[CORE_EXPONENT]++; 310 | } 311 | else 312 | { 313 | state = CORE_INVALID; 314 | transition_count[CORE_EXPONENT]++; 315 | } 316 | break; 317 | case CORE_SCIENTIFIC: 318 | if (!ee_isdigit(NEXT_SYMBOL)) 319 | { 320 | state = CORE_INVALID; 321 | transition_count[CORE_INVALID]++; 322 | } 323 | break; 324 | default: 325 | break; 326 | } 327 | } 328 | *instr = str; 329 | return state; 330 | } 331 | -------------------------------------------------------------------------------- /software/coremark/core_matrix.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | 19 | #include "coremark.h" 20 | /* 21 | Topic: Description 22 | Matrix manipulation benchmark 23 | 24 | This very simple algorithm forms the basis of many more complex 25 | algorithms. 26 | 27 | The tight inner loop is the focus of many optimizations (compiler as 28 | well as hardware based) and is thus relevant for embedded processing. 29 | 30 | The total available data space will be divided to 3 parts: 31 | NxN Matrix A - initialized with small values (upper 3/4 of the bits all 32 | zero). NxN Matrix B - initialized with medium values (upper half of the bits all 33 | zero). NxN Matrix C - used for the result. 34 | 35 | The actual values for A and B must be derived based on input that is not 36 | available at compile time. 37 | */ 38 | ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val); 39 | ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval); 40 | void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val); 41 | void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); 42 | void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); 43 | void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); 44 | void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val); 45 | 46 | #define matrix_test_next(x) (x + 1) 47 | #define matrix_clip(x, y) ((y) ? (x)&0x0ff : (x)&0x0ffff) 48 | #define matrix_big(x) (0xf000 | (x)) 49 | #define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to)))) 50 | 51 | #if CORE_DEBUG 52 | void 53 | printmat(MATDAT *A, ee_u32 N, char *name) 54 | { 55 | ee_u32 i, j; 56 | ee_printf("Matrix %s [%dx%d]:\n", name, N, N); 57 | for (i = 0; i < N; i++) 58 | { 59 | for (j = 0; j < N; j++) 60 | { 61 | if (j != 0) 62 | ee_printf(","); 63 | ee_printf("%d", A[i * N + j]); 64 | } 65 | ee_printf("\n"); 66 | } 67 | } 68 | void 69 | printmatC(MATRES *C, ee_u32 N, char *name) 70 | { 71 | ee_u32 i, j; 72 | ee_printf("Matrix %s [%dx%d]:\n", name, N, N); 73 | for (i = 0; i < N; i++) 74 | { 75 | for (j = 0; j < N; j++) 76 | { 77 | if (j != 0) 78 | ee_printf(","); 79 | ee_printf("%d", C[i * N + j]); 80 | } 81 | ee_printf("\n"); 82 | } 83 | } 84 | #endif 85 | /* Function: core_bench_matrix 86 | Benchmark function 87 | 88 | Iterate N times, 89 | changing the matrix values slightly by a constant amount each time. 90 | */ 91 | ee_u16 92 | core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) 93 | { 94 | ee_u32 N = p->N; 95 | MATRES *C = p->C; 96 | MATDAT *A = p->A; 97 | MATDAT *B = p->B; 98 | MATDAT val = (MATDAT)seed; 99 | 100 | crc = crc16(matrix_test(N, C, A, B, val), crc); 101 | 102 | return crc; 103 | } 104 | 105 | /* Function: matrix_test 106 | Perform matrix manipulation. 107 | 108 | Parameters: 109 | N - Dimensions of the matrix. 110 | C - memory for result matrix. 111 | A - input matrix 112 | B - operator matrix (not changed during operations) 113 | 114 | Returns: 115 | A CRC value that captures all results calculated in the function. 116 | In particular, crc of the value calculated on the result matrix 117 | after each step by . 118 | 119 | Operation: 120 | 121 | 1 - Add a constant value to all elements of a matrix. 122 | 2 - Multiply a matrix by a constant. 123 | 3 - Multiply a matrix by a vector. 124 | 4 - Multiply a matrix by a matrix. 125 | 5 - Add a constant value to all elements of a matrix. 126 | 127 | After the last step, matrix A is back to original contents. 128 | */ 129 | ee_s16 130 | matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) 131 | { 132 | ee_u16 crc = 0; 133 | MATDAT clipval = matrix_big(val); 134 | 135 | matrix_add_const(N, A, val); /* make sure data changes */ 136 | #if CORE_DEBUG 137 | printmat(A, N, "matrix_add_const"); 138 | #endif 139 | matrix_mul_const(N, C, A, val); 140 | crc = crc16(matrix_sum(N, C, clipval), crc); 141 | #if CORE_DEBUG 142 | printmatC(C, N, "matrix_mul_const"); 143 | #endif 144 | matrix_mul_vect(N, C, A, B); 145 | crc = crc16(matrix_sum(N, C, clipval), crc); 146 | #if CORE_DEBUG 147 | printmatC(C, N, "matrix_mul_vect"); 148 | #endif 149 | matrix_mul_matrix(N, C, A, B); 150 | crc = crc16(matrix_sum(N, C, clipval), crc); 151 | #if CORE_DEBUG 152 | printmatC(C, N, "matrix_mul_matrix"); 153 | #endif 154 | matrix_mul_matrix_bitextract(N, C, A, B); 155 | crc = crc16(matrix_sum(N, C, clipval), crc); 156 | #if CORE_DEBUG 157 | printmatC(C, N, "matrix_mul_matrix_bitextract"); 158 | #endif 159 | 160 | matrix_add_const(N, A, -val); /* return matrix to initial value */ 161 | return crc; 162 | } 163 | 164 | /* Function : matrix_init 165 | Initialize the memory block for matrix benchmarking. 166 | 167 | Parameters: 168 | blksize - Size of memory to be initialized. 169 | memblk - Pointer to memory block. 170 | seed - Actual values chosen depend on the seed parameter. 171 | p - pointers to containing initialized matrixes. 172 | 173 | Returns: 174 | Matrix dimensions. 175 | 176 | Note: 177 | The seed parameter MUST be supplied from a source that cannot be 178 | determined at compile time 179 | */ 180 | ee_u32 181 | core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p) 182 | { 183 | ee_u32 N = 0; 184 | MATDAT *A; 185 | MATDAT *B; 186 | ee_s32 order = 1; 187 | MATDAT val; 188 | ee_u32 i = 0, j = 0; 189 | if (seed == 0) 190 | seed = 1; 191 | while (j < blksize) 192 | { 193 | i++; 194 | j = i * i * 2 * 4; 195 | } 196 | N = i - 1; 197 | A = (MATDAT *)align_mem(memblk); 198 | B = A + N * N; 199 | 200 | for (i = 0; i < N; i++) 201 | { 202 | for (j = 0; j < N; j++) 203 | { 204 | seed = ((order * seed) % 65536); 205 | val = (seed + order); 206 | val = matrix_clip(val, 0); 207 | B[i * N + j] = val; 208 | val = (val + order); 209 | val = matrix_clip(val, 1); 210 | A[i * N + j] = val; 211 | order++; 212 | } 213 | } 214 | 215 | p->A = A; 216 | p->B = B; 217 | p->C = (MATRES *)align_mem(B + N * N); 218 | p->N = N; 219 | #if CORE_DEBUG 220 | printmat(A, N, "A"); 221 | printmat(B, N, "B"); 222 | #endif 223 | return N; 224 | } 225 | 226 | /* Function: matrix_sum 227 | Calculate a function that depends on the values of elements in the 228 | matrix. 229 | 230 | For each element, accumulate into a temporary variable. 231 | 232 | As long as this value is under the parameter clipval, 233 | add 1 to the result if the element is bigger then the previous. 234 | 235 | Otherwise, reset the accumulator and add 10 to the result. 236 | */ 237 | ee_s16 238 | matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) 239 | { 240 | MATRES tmp = 0, prev = 0, cur = 0; 241 | ee_s16 ret = 0; 242 | ee_u32 i, j; 243 | for (i = 0; i < N; i++) 244 | { 245 | for (j = 0; j < N; j++) 246 | { 247 | cur = C[i * N + j]; 248 | tmp += cur; 249 | if (tmp > clipval) 250 | { 251 | ret += 10; 252 | tmp = 0; 253 | } 254 | else 255 | { 256 | ret += (cur > prev) ? 1 : 0; 257 | } 258 | prev = cur; 259 | } 260 | } 261 | return ret; 262 | } 263 | 264 | /* Function: matrix_mul_const 265 | Multiply a matrix by a constant. 266 | This could be used as a scaler for instance. 267 | */ 268 | void 269 | matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) 270 | { 271 | ee_u32 i, j; 272 | for (i = 0; i < N; i++) 273 | { 274 | for (j = 0; j < N; j++) 275 | { 276 | C[i * N + j] = (MATRES)A[i * N + j] * (MATRES)val; 277 | } 278 | } 279 | } 280 | 281 | /* Function: matrix_add_const 282 | Add a constant value to all elements of a matrix. 283 | */ 284 | void 285 | matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val) 286 | { 287 | ee_u32 i, j; 288 | for (i = 0; i < N; i++) 289 | { 290 | for (j = 0; j < N; j++) 291 | { 292 | A[i * N + j] += val; 293 | } 294 | } 295 | } 296 | 297 | /* Function: matrix_mul_vect 298 | Multiply a matrix by a vector. 299 | This is common in many simple filters (e.g. fir where a vector of 300 | coefficients is applied to the matrix.) 301 | */ 302 | void 303 | matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) 304 | { 305 | ee_u32 i, j; 306 | for (i = 0; i < N; i++) 307 | { 308 | C[i] = 0; 309 | for (j = 0; j < N; j++) 310 | { 311 | C[i] += (MATRES)A[i * N + j] * (MATRES)B[j]; 312 | } 313 | } 314 | } 315 | 316 | /* Function: matrix_mul_matrix 317 | Multiply a matrix by a matrix. 318 | Basic code is used in many algorithms, mostly with minor changes such as 319 | scaling. 320 | */ 321 | void 322 | matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) 323 | { 324 | ee_u32 i, j, k; 325 | for (i = 0; i < N; i++) 326 | { 327 | for (j = 0; j < N; j++) 328 | { 329 | C[i * N + j] = 0; 330 | for (k = 0; k < N; k++) 331 | { 332 | C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j]; 333 | } 334 | } 335 | } 336 | } 337 | 338 | /* Function: matrix_mul_matrix_bitextract 339 | Multiply a matrix by a matrix, and extract some bits from the result. 340 | Basic code is used in many algorithms, mostly with minor changes such as 341 | scaling. 342 | */ 343 | void 344 | matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) 345 | { 346 | ee_u32 i, j, k; 347 | for (i = 0; i < N; i++) 348 | { 349 | for (j = 0; j < N; j++) 350 | { 351 | C[i * N + j] = 0; 352 | for (k = 0; k < N; k++) 353 | { 354 | MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j]; 355 | C[i * N + j] += bit_extract(tmp, 2, 4) * bit_extract(tmp, 5, 7); 356 | } 357 | } 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/cpu_top.v: -------------------------------------------------------------------------------- 1 | // 2 | // cpu_top 3 | // 4 | 5 | 6 | `include "define.vh" 7 | 8 | module cpu_top ( 9 | input wire clk, 10 | input wire rst, 11 | input wire uart_rx, 12 | input wire [3:0] gpi_in, 13 | output wire [3:0] gpo_out, 14 | output wire uart_tx 15 | ); 16 | 17 | // reset 18 | wire rst_n; 19 | assign rst_n = ~rst; 20 | 21 | // PC 22 | wire [31:0] next_PC; 23 | wire [31:0] ex_br_addr; 24 | wire ex_br_taken; 25 | reg [31:0] PC; 26 | 27 | // fetch stage関連の定義 28 | wire [31:0] imem_addr, imem_rd_data; 29 | 30 | // execution stage関連の定義 31 | reg [31:0] ex_PC; 32 | 33 | // decoder 34 | wire [31:0] decoder_insn; 35 | wire [4:0] decoder_srcreg1_num, decoder_srcreg2_num, ex_dstreg_num; 36 | wire [31:0] decoder_imm; 37 | wire [5:0] ex_alucode; 38 | wire [1:0] ex_aluop1_type, ex_aluop2_type; 39 | wire ex_reg_we, ex_is_load, ex_is_store; 40 | 41 | // register file 42 | wire regfile_we; 43 | wire [4:0] regfile_srcreg1_num, regfile_srcreg2_num, regfile_dstreg_num; 44 | wire [31:0] regfile_srcreg1_value, regfile_srcreg2_value, regfile_dstreg_value; 45 | 46 | // ALU 47 | wire [5:0] alu_alucode; 48 | wire [31:0] alu_op1, alu_op2, ex_alu_result; 49 | 50 | wire [31:0] ex_srcreg1_value, ex_srcreg2_value, ex_store_value; 51 | 52 | // dmem 53 | wire [3:0] dmem_we; 54 | wire [31:0] dmem_addr; 55 | wire [7:0] dmem_wr_data [3:0]; 56 | wire [7:0] dmem_rd_data [3:0]; 57 | 58 | // UART TX 59 | wire uart_we; 60 | wire [7:0] uart_data_in; 61 | wire uart_data_out; 62 | 63 | // UART RX 64 | wire uart_rd_en; 65 | wire [7:0] uart_rd_data; 66 | wire [31:0] uart_value; 67 | 68 | // GPIO 69 | wire [7:0] gpi_data_in; 70 | wire [7:0] gpi_data_out; 71 | wire [31:0] gpi_value; 72 | wire gpo_we; 73 | wire [7:0] gpo_data_in; 74 | wire [7:0] gpo_data_out; 75 | wire [31:0] gpo_value; 76 | 77 | // ハードウェアカウンタ 78 | wire [31:0] hc_value; 79 | 80 | // write-back stage関連の定義 81 | reg wb_reg_we; 82 | reg [4:0] wb_dstreg_num; 83 | reg wb_is_load; 84 | reg [5:0] wb_alucode; 85 | reg [31:0] wb_alu_result; 86 | wire [31:0] wb_load_value, wb_dstreg_value; 87 | 88 | 89 | //==================================================================== 90 | // program counter 91 | //==================================================================== 92 | 93 | // ex stageの結果をフォワーディング 94 | assign next_PC = (rst_n == 1'b0) ? PC + 32'd4 : ex_br_taken ? ex_br_addr + 32'd4 : PC + 32'd4; 95 | 96 | always @(posedge clk or negedge rst_n) begin 97 | if (!rst_n) begin 98 | PC <= 32'd0; 99 | end else begin 100 | PC <= next_PC; 101 | end 102 | end 103 | 104 | //==================================================================== 105 | // fetch stage 106 | //==================================================================== 107 | 108 | // ex stageの結果をフォワーディング 109 | assign imem_addr = (rst_n == 1'b0) ? 32'd0 : ex_br_taken ? ex_br_addr : PC; 110 | 111 | imem imem ( 112 | .clk(clk), 113 | .addr(imem_addr), 114 | .rd_data(imem_rd_data) 115 | ); 116 | 117 | always @(posedge clk or negedge rst_n) begin 118 | if(!rst_n) begin 119 | ex_PC <= 32'd0; 120 | end else begin 121 | ex_PC <= imem_addr; 122 | end 123 | end 124 | 125 | //==================================================================== 126 | // execution stage 127 | //==================================================================== 128 | 129 | assign decoder_insn = imem_rd_data; 130 | 131 | decoder decoder_0 ( 132 | .insn(decoder_insn), 133 | .srcreg1_num(decoder_srcreg1_num), 134 | .srcreg2_num(decoder_srcreg2_num), 135 | .dstreg_num(ex_dstreg_num), 136 | .imm(decoder_imm), 137 | .alucode(ex_alucode), 138 | .aluop1_type(ex_aluop1_type), 139 | .aluop2_type(ex_aluop2_type), 140 | .reg_we(ex_reg_we), 141 | .is_load(ex_is_load), 142 | .is_store(ex_is_store) 143 | ); 144 | 145 | 146 | assign regfile_srcreg1_num = decoder_srcreg1_num; 147 | assign regfile_srcreg2_num = decoder_srcreg2_num; 148 | 149 | regfile regfile_0 ( 150 | .clk(clk), 151 | .we(regfile_we), 152 | .srcreg1_num(regfile_srcreg1_num), 153 | .srcreg2_num(regfile_srcreg2_num), 154 | .dstreg_num(regfile_dstreg_num), 155 | .dstreg_value(regfile_dstreg_value), 156 | .srcreg1_value(regfile_srcreg1_value), 157 | .srcreg2_value(regfile_srcreg2_value) 158 | ); 159 | 160 | 161 | // alu 162 | assign alu_alucode = ex_alucode; 163 | 164 | // wb stageの結果をフォワーディング 165 | assign ex_srcreg1_value = (regfile_srcreg1_num==5'd0) ? 32'd0 : 166 | (wb_reg_we && (decoder_srcreg1_num == wb_dstreg_num)) ? wb_dstreg_value : regfile_srcreg1_value; 167 | assign ex_srcreg2_value = (regfile_srcreg2_num==5'd0) ? 32'd0 : 168 | (wb_reg_we && (decoder_srcreg2_num == wb_dstreg_num)) ? wb_dstreg_value : regfile_srcreg2_value; 169 | 170 | assign alu_op1 = (ex_aluop1_type == `OP_TYPE_REG) ? ex_srcreg1_value : 171 | (ex_aluop1_type == `OP_TYPE_IMM) ? decoder_imm : 172 | (ex_aluop1_type == `OP_TYPE_PC) ? ex_PC: 32'd0; 173 | assign alu_op2 = (ex_aluop2_type == `OP_TYPE_REG) ? ex_srcreg2_value : 174 | (ex_aluop2_type == `OP_TYPE_IMM) ? decoder_imm : 175 | (ex_aluop2_type == `OP_TYPE_PC) ? ex_PC : 32'd0; 176 | 177 | alu alu_0 ( 178 | .alucode(alu_alucode), 179 | .op1(alu_op1), 180 | .op2(alu_op2), 181 | .alu_result(ex_alu_result), 182 | .br_taken(ex_br_taken) 183 | ); 184 | 185 | assign ex_store_value = ((ex_alucode == `ALU_SW) || (ex_alucode == `ALU_SH) || (ex_alucode == `ALU_SB)) ? ex_srcreg2_value : 32'd0; 186 | 187 | assign ex_br_addr = (ex_alucode==`ALU_JAL) ? ex_PC + decoder_imm : 188 | (ex_alucode==`ALU_JALR) ? alu_op1 + decoder_imm : 189 | ((ex_alucode==`ALU_BEQ) || (ex_alucode==`ALU_BNE) || (ex_alucode==`ALU_BLT) || 190 | (ex_alucode==`ALU_BGE) || (ex_alucode==`ALU_BLTU) || (ex_alucode==`ALU_BGEU)) ? ex_PC + decoder_imm : 32'd0; 191 | 192 | 193 | // store 194 | assign dmem_addr = ex_alu_result - `DMEM_START_ADDR; // データメモリの読出しアドレスを変換 195 | 196 | function [31:0] dmem_wr_data_sel( 197 | input is_store, 198 | input [5:0] alucode, 199 | input [1:0] alu_result, 200 | input [31:0] store_value 201 | ); 202 | 203 | begin 204 | if (is_store) begin 205 | case (alucode) 206 | `ALU_SW: dmem_wr_data_sel = store_value; 207 | `ALU_SH: begin 208 | case (alu_result) 209 | 2'b00: dmem_wr_data_sel = {16'd0, store_value[15:0]}; 210 | 2'b01: dmem_wr_data_sel = {8'd0, store_value[15:0], 8'd0}; 211 | 2'b10: dmem_wr_data_sel = {store_value[15:0], 16'd0}; 212 | default: dmem_wr_data_sel = {16'd0, store_value[15:0]}; 213 | endcase 214 | end 215 | `ALU_SB: begin 216 | case (alu_result) 217 | 2'b00: dmem_wr_data_sel = {24'd0, store_value[7:0]}; 218 | 2'b01: dmem_wr_data_sel = {16'd0, store_value[7:0], 8'd0}; 219 | 2'b10: dmem_wr_data_sel = {8'd0, store_value[7:0], 16'd0}; 220 | 2'b11: dmem_wr_data_sel = {store_value[7:0], 24'd0}; 221 | endcase 222 | end 223 | default: dmem_wr_data_sel = store_value; 224 | endcase 225 | end else begin 226 | dmem_wr_data_sel = 32'd0; 227 | end 228 | end 229 | 230 | endfunction 231 | 232 | assign {dmem_wr_data[3], dmem_wr_data[2], dmem_wr_data[1], dmem_wr_data[0]} = dmem_wr_data_sel(ex_is_store, ex_alucode, ex_alu_result[1:0], ex_store_value); 233 | 234 | 235 | function [3:0] dmem_we_sel( 236 | input is_store, 237 | input [5:0] alucode, 238 | input [1:0] alu_result 239 | ); 240 | 241 | begin 242 | if (is_store) begin 243 | case (alucode) 244 | `ALU_SW: dmem_we_sel = 4'b1111; 245 | `ALU_SH: begin 246 | case (alu_result) 247 | 2'b00: dmem_we_sel = 4'b0011; 248 | 2'b01: dmem_we_sel = 4'b0110; 249 | 2'b10: dmem_we_sel = 4'b1100; 250 | default: dmem_we_sel = 4'b0000; 251 | endcase 252 | end 253 | `ALU_SB: begin 254 | case (alu_result) 255 | 2'b00: dmem_we_sel = 4'b0001; 256 | 2'b01: dmem_we_sel = 4'b0010; 257 | 2'b10: dmem_we_sel = 4'b0100; 258 | 2'b11: dmem_we_sel = 4'b1000; 259 | endcase 260 | end 261 | default: dmem_we_sel = 4'b0000; 262 | endcase 263 | end else begin 264 | dmem_we_sel = 4'b0000; 265 | end 266 | end 267 | 268 | endfunction 269 | 270 | // メモリマップのデータメモリにあたるアドレスが指定されていれば書き込み有効化 271 | assign dmem_we = (dmem_addr <= `DMEM_SIZE) ? dmem_we_sel(ex_is_store, ex_alucode, ex_alu_result[1:0]) : 4'd0; 272 | 273 | 274 | dmem #(.byte_num(2'b00)) dmem_0 ( 275 | .clk(clk), 276 | .we(dmem_we[0]), 277 | .addr(dmem_addr), 278 | .wr_data(dmem_wr_data[0]), 279 | .rd_data(dmem_rd_data[0]) 280 | ); 281 | 282 | dmem #(.byte_num(2'b01)) dmem_1 ( 283 | .clk(clk), 284 | .we(dmem_we[1]), 285 | .addr(dmem_addr), 286 | .wr_data(dmem_wr_data[1]), 287 | .rd_data(dmem_rd_data[1]) 288 | ); 289 | 290 | dmem #(.byte_num(2'b10)) dmem_2 ( 291 | .clk(clk), 292 | .we(dmem_we[2]), 293 | .addr(dmem_addr), 294 | .wr_data(dmem_wr_data[2]), 295 | .rd_data(dmem_rd_data[2]) 296 | ); 297 | 298 | dmem #(.byte_num(2'b11)) dmem_3 ( 299 | .clk(clk), 300 | .we(dmem_we[3]), 301 | .addr(dmem_addr), 302 | .wr_data(dmem_wr_data[3]), 303 | .rd_data(dmem_rd_data[3]) 304 | ); 305 | 306 | 307 | // UART 308 | assign uart_data_in = ex_store_value[7:0]; 309 | assign uart_we = ((ex_alu_result == `UART_TX_ADDR) && ex_is_store) ? `ENABLE : `DISABLE; 310 | assign uart_tx = uart_data_out; 311 | 312 | uart uart_0 ( 313 | .clk(clk), 314 | .rst_n(rst_n), 315 | .wr_data(uart_data_in), 316 | .wr_en(uart_we), 317 | .uart_tx(uart_data_out) 318 | ); 319 | 320 | uart_rx uart_rx_0 ( 321 | .clk(clk), 322 | .rst_n(rst_n), 323 | .uart_rx(uart_rx), 324 | .rd_data(uart_rd_data), 325 | .rd_en(uart_rd_en) 326 | ); 327 | 328 | 329 | // GPIO 330 | assign gpi_data_in = {4'd0, gpi_in}; // デフォルトでは汎用入力は4bit 331 | assign gpo_data_in = ex_store_value[7:0]; 332 | assign gpo_we = ((ex_alu_result == `GPO_ADDR) && ex_is_store) ? `ENABLE : `DISABLE; 333 | assign gpo_out = gpo_data_out[3:0]; // デフォルトでは汎用出力は4bit 334 | 335 | gpi gpi_0 ( 336 | .clk(clk), 337 | .rst_n(rst_n), 338 | .wr_data(gpi_data_in), 339 | .gpi_out(gpi_data_out) 340 | ); 341 | 342 | gpo gpo_0 ( 343 | .clk(clk), 344 | .rst_n(rst_n), 345 | .we(gpo_we), 346 | .wr_data(gpo_data_in), 347 | .gpo_out(gpo_data_out) 348 | ); 349 | 350 | 351 | // hardware counter 352 | hardware_counter hardware_counter_0 ( 353 | .clk(clk), 354 | .rst_n(rst_n), 355 | .hc_out(hc_value) 356 | ); 357 | 358 | 359 | // パイプラインレジスタ 360 | always @(posedge clk or negedge rst_n) begin 361 | if (!rst_n) begin 362 | wb_reg_we <= `DISABLE; 363 | wb_dstreg_num <= 5'd0; 364 | wb_is_load <= `DISABLE; 365 | wb_alucode <= 6'd0; 366 | wb_alu_result <= 32'd0; 367 | end else begin 368 | wb_reg_we <= ex_reg_we; 369 | wb_dstreg_num <= ex_dstreg_num; 370 | wb_is_load <= ex_is_load; 371 | wb_alucode <= ex_alucode; 372 | wb_alu_result <= ex_alu_result; 373 | end 374 | end 375 | 376 | //==================================================================== 377 | // write-back stage 378 | //==================================================================== 379 | 380 | // 各種I/Oからのロード値 381 | assign gpi_value = {28'd0, gpi_data_out[3:0]}; 382 | assign gpo_value = {28'd0, gpo_data_out[3:0]}; 383 | assign uart_value = {24'd0, uart_rd_data}; 384 | 385 | function [31:0] load_value_sel( 386 | input is_load, 387 | input [5:0] alucode, 388 | input [31:0] alu_result, 389 | input [7:0] dmem_rd_data_0, dmem_rd_data_1, dmem_rd_data_2, dmem_rd_data_3, 390 | input [31:0] uart_value, 391 | input [31:0] hc_value, 392 | input [31:0] gpi_value, 393 | input [31:0] gpo_value 394 | ); 395 | 396 | begin 397 | if (is_load) begin 398 | case (alucode) 399 | `ALU_LW: begin 400 | if (alu_result == `HARDWARE_COUNTER_ADDR) begin 401 | load_value_sel = hc_value; 402 | end else if (alu_result == `UART_RX_ADDR) begin 403 | load_value_sel = uart_value; 404 | end else if (alu_result == `GPI_ADDR) begin 405 | load_value_sel = gpi_value; 406 | end else if (alu_result == `GPO_ADDR) begin 407 | load_value_sel = gpo_value; 408 | end else begin 409 | load_value_sel = {dmem_rd_data_3, dmem_rd_data_2, dmem_rd_data_1, dmem_rd_data_0}; 410 | end 411 | end 412 | `ALU_LH: begin 413 | case (alu_result[1:0]) 414 | 2'b00: load_value_sel = {{16{dmem_rd_data_1[7]}}, dmem_rd_data_1, dmem_rd_data_0}; 415 | 2'b01: load_value_sel = {{16{dmem_rd_data_2[7]}}, dmem_rd_data_2, dmem_rd_data_1}; 416 | 2'b10: load_value_sel = {{16{dmem_rd_data_3[7]}}, dmem_rd_data_3, dmem_rd_data_2}; 417 | default: load_value_sel = {{16{dmem_rd_data_1[7]}}, dmem_rd_data_1, dmem_rd_data_0}; 418 | endcase 419 | end 420 | `ALU_LB: begin 421 | case (alu_result[1:0]) 422 | 2'b00: load_value_sel = {{24{dmem_rd_data_0[7]}}, dmem_rd_data_0}; 423 | 2'b01: load_value_sel = {{24{dmem_rd_data_1[7]}}, dmem_rd_data_1}; 424 | 2'b10: load_value_sel = {{24{dmem_rd_data_2[7]}}, dmem_rd_data_2}; 425 | 2'b11: load_value_sel = {{24{dmem_rd_data_3[7]}}, dmem_rd_data_3}; 426 | endcase 427 | end 428 | `ALU_LHU: begin 429 | case (alu_result[1:0]) 430 | 2'b00: load_value_sel = {16'd0, dmem_rd_data_1, dmem_rd_data_0}; 431 | 2'b01: load_value_sel = {16'd0, dmem_rd_data_2, dmem_rd_data_1}; 432 | 2'b10: load_value_sel = {16'd0, dmem_rd_data_3, dmem_rd_data_2}; 433 | default: load_value_sel = {16'd0, dmem_rd_data_1, dmem_rd_data_0}; 434 | endcase 435 | end 436 | `ALU_LBU: begin 437 | case (alu_result[1:0]) 438 | 2'b00: load_value_sel = {24'd0, dmem_rd_data_0}; 439 | 2'b01: load_value_sel = {24'd0, dmem_rd_data_1}; 440 | 2'b10: load_value_sel = {24'd0, dmem_rd_data_2}; 441 | 2'b11: load_value_sel = {24'd0, dmem_rd_data_3}; 442 | endcase 443 | end 444 | default: load_value_sel = {dmem_rd_data_3, dmem_rd_data_2, dmem_rd_data_1, dmem_rd_data_0}; 445 | endcase 446 | end else begin 447 | load_value_sel = 32'd0; 448 | end 449 | end 450 | 451 | endfunction 452 | 453 | assign wb_load_value = load_value_sel(wb_is_load, wb_alucode, wb_alu_result, dmem_rd_data[0], 454 | dmem_rd_data[1], dmem_rd_data[2], dmem_rd_data[3], uart_value, hc_value, gpi_value, gpo_value); 455 | 456 | assign wb_dstreg_value = wb_is_load ? wb_load_value : wb_alu_result; 457 | 458 | // wb stageの結果に応じてレジスタへ書き込み 459 | assign regfile_we = wb_reg_we; 460 | assign regfile_dstreg_num = wb_dstreg_num; 461 | assign regfile_dstreg_value = wb_dstreg_value; 462 | 463 | 464 | endmodule 465 | -------------------------------------------------------------------------------- /software/coremark/core_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | 19 | /* File: core_main.c 20 | This file contains the framework to acquire a block of memory, seed 21 | initial parameters, tun t he benchmark and report the results. 22 | */ 23 | #include "coremark.h" 24 | 25 | /* Function: iterate 26 | Run the benchmark for a specified number of iterations. 27 | 28 | Operation: 29 | For each type of benchmarked algorithm: 30 | a - Initialize the data block for the algorithm. 31 | b - Execute the algorithm N times. 32 | 33 | Returns: 34 | NULL. 35 | */ 36 | static ee_u16 list_known_crc[] = { (ee_u16)0xd4b0, 37 | (ee_u16)0x3340, 38 | (ee_u16)0x6a79, 39 | (ee_u16)0xe714, 40 | (ee_u16)0xe3c1 }; 41 | static ee_u16 matrix_known_crc[] = { (ee_u16)0xbe52, 42 | (ee_u16)0x1199, 43 | (ee_u16)0x5608, 44 | (ee_u16)0x1fd7, 45 | (ee_u16)0x0747 }; 46 | static ee_u16 state_known_crc[] = { (ee_u16)0x5e47, 47 | (ee_u16)0x39bf, 48 | (ee_u16)0xe5a4, 49 | (ee_u16)0x8e3a, 50 | (ee_u16)0x8d84 }; 51 | void * 52 | iterate(void *pres) 53 | { 54 | ee_u32 i; 55 | ee_u16 crc; 56 | core_results *res = (core_results *)pres; 57 | ee_u32 iterations = res->iterations; 58 | res->crc = 0; 59 | res->crclist = 0; 60 | res->crcmatrix = 0; 61 | res->crcstate = 0; 62 | 63 | for (i = 0; i < iterations; i++) 64 | { 65 | crc = core_bench_list(res, 1); 66 | res->crc = crcu16(crc, res->crc); 67 | crc = core_bench_list(res, -1); 68 | res->crc = crcu16(crc, res->crc); 69 | if (i == 0) 70 | res->crclist = res->crc; 71 | } 72 | return NULL; 73 | } 74 | 75 | #if (SEED_METHOD == SEED_ARG) 76 | ee_s32 get_seed_args(int i, int argc, char *argv[]); 77 | #define get_seed(x) (ee_s16) get_seed_args(x, argc, argv) 78 | #define get_seed_32(x) get_seed_args(x, argc, argv) 79 | #else /* via function or volatile */ 80 | ee_s32 get_seed_32(int i); 81 | #define get_seed(x) (ee_s16) get_seed_32(x) 82 | #endif 83 | 84 | #if (MEM_METHOD == MEM_STATIC) 85 | ee_u8 static_memblk[TOTAL_DATA_SIZE]; 86 | #endif 87 | char *mem_name[3] = { "Static", "Heap", "Stack" }; 88 | /* Function: main 89 | Main entry routine for the benchmark. 90 | This function is responsible for the following steps: 91 | 92 | 1 - Initialize input seeds from a source that cannot be determined at 93 | compile time. 2 - Initialize memory block for use. 3 - Run and time the 94 | benchmark. 4 - Report results, testing the validity of the output if the 95 | seeds are known. 96 | 97 | Arguments: 98 | 1 - first seed : Any value 99 | 2 - second seed : Must be identical to first for iterations to be 100 | identical 3 - third seed : Any value, should be at least an order of 101 | magnitude less then the input size, but bigger then 32. 4 - Iterations : 102 | Special, if set to 0, iterations will be automatically determined such that 103 | the benchmark will run between 10 to 100 secs 104 | 105 | */ 106 | 107 | #if MAIN_HAS_NOARGC 108 | MAIN_RETURN_TYPE 109 | main(void) 110 | { 111 | int argc = 0; 112 | char *argv[1]; 113 | #else 114 | MAIN_RETURN_TYPE 115 | main(int argc, char *argv[]) 116 | { 117 | #endif 118 | ee_u16 i, j = 0, num_algorithms = 0; 119 | ee_s16 known_id = -1, total_errors = 0; 120 | ee_u16 seedcrc = 0; 121 | CORE_TICKS total_time; 122 | core_results results[MULTITHREAD]; 123 | #if (MEM_METHOD == MEM_STACK) 124 | ee_u8 stack_memblock[TOTAL_DATA_SIZE * MULTITHREAD]; 125 | #endif 126 | /* first call any initializations needed */ 127 | portable_init(&(results[0].port), &argc, argv); 128 | /* First some checks to make sure benchmark will run ok */ 129 | if (sizeof(struct list_head_s) > 128) 130 | { 131 | ee_printf("list_head structure too big for comparable data!\n"); 132 | return MAIN_RETURN_VAL; 133 | } 134 | results[0].seed1 = get_seed(1); 135 | results[0].seed2 = get_seed(2); 136 | results[0].seed3 = get_seed(3); 137 | results[0].iterations = get_seed_32(4); 138 | #if CORE_DEBUG 139 | results[0].iterations = 1; 140 | #endif 141 | results[0].execs = get_seed_32(5); 142 | if (results[0].execs == 0) 143 | { /* if not supplied, execute all algorithms */ 144 | results[0].execs = ALL_ALGORITHMS_MASK; 145 | } 146 | /* put in some default values based on one seed only for easy testing */ 147 | if ((results[0].seed1 == 0) && (results[0].seed2 == 0) 148 | && (results[0].seed3 == 0)) 149 | { /* perfromance run */ 150 | results[0].seed1 = 0; 151 | results[0].seed2 = 0; 152 | results[0].seed3 = 0x66; 153 | } 154 | if ((results[0].seed1 == 1) && (results[0].seed2 == 0) 155 | && (results[0].seed3 == 0)) 156 | { /* validation run */ 157 | results[0].seed1 = 0x3415; 158 | results[0].seed2 = 0x3415; 159 | results[0].seed3 = 0x66; 160 | } 161 | #if (MEM_METHOD == MEM_STATIC) 162 | results[0].memblock[0] = (void *)static_memblk; 163 | results[0].size = TOTAL_DATA_SIZE; 164 | results[0].err = 0; 165 | #if (MULTITHREAD > 1) 166 | #error "Cannot use a static data area with multiple contexts!" 167 | #endif 168 | #elif (MEM_METHOD == MEM_MALLOC) 169 | for (i = 0; i < MULTITHREAD; i++) 170 | { 171 | ee_s32 malloc_override = get_seed(7); 172 | if (malloc_override != 0) 173 | results[i].size = malloc_override; 174 | else 175 | results[i].size = TOTAL_DATA_SIZE; 176 | results[i].memblock[0] = portable_malloc(results[i].size); 177 | results[i].seed1 = results[0].seed1; 178 | results[i].seed2 = results[0].seed2; 179 | results[i].seed3 = results[0].seed3; 180 | results[i].err = 0; 181 | results[i].execs = results[0].execs; 182 | } 183 | #elif (MEM_METHOD == MEM_STACK) 184 | for (i = 0; i < MULTITHREAD; i++) 185 | { 186 | results[i].memblock[0] = stack_memblock + i * TOTAL_DATA_SIZE; 187 | results[i].size = TOTAL_DATA_SIZE; 188 | results[i].seed1 = results[0].seed1; 189 | results[i].seed2 = results[0].seed2; 190 | results[i].seed3 = results[0].seed3; 191 | results[i].err = 0; 192 | results[i].execs = results[0].execs; 193 | } 194 | #else 195 | #error "Please define a way to initialize a memory block." 196 | #endif 197 | /* Data init */ 198 | /* Find out how space much we have based on number of algorithms */ 199 | for (i = 0; i < NUM_ALGORITHMS; i++) 200 | { 201 | if ((1 << (ee_u32)i) & results[0].execs) 202 | num_algorithms++; 203 | } 204 | for (i = 0; i < MULTITHREAD; i++) 205 | results[i].size = results[i].size / num_algorithms; 206 | /* Assign pointers */ 207 | for (i = 0; i < NUM_ALGORITHMS; i++) 208 | { 209 | ee_u32 ctx; 210 | if ((1 << (ee_u32)i) & results[0].execs) 211 | { 212 | for (ctx = 0; ctx < MULTITHREAD; ctx++) 213 | results[ctx].memblock[i + 1] 214 | = (char *)(results[ctx].memblock[0]) + results[0].size * j; 215 | j++; 216 | } 217 | } 218 | /* call inits */ 219 | for (i = 0; i < MULTITHREAD; i++) 220 | { 221 | if (results[i].execs & ID_LIST) 222 | { 223 | results[i].list = core_list_init( 224 | results[0].size, results[i].memblock[1], results[i].seed1); 225 | } 226 | if (results[i].execs & ID_MATRIX) 227 | { 228 | core_init_matrix(results[0].size, 229 | results[i].memblock[2], 230 | (ee_s32)results[i].seed1 231 | | (((ee_s32)results[i].seed2) << 16), 232 | &(results[i].mat)); 233 | } 234 | if (results[i].execs & ID_STATE) 235 | { 236 | core_init_state( 237 | results[0].size, results[i].seed1, results[i].memblock[3]); 238 | } 239 | } 240 | 241 | /* automatically determine number of iterations if not set */ 242 | if (results[0].iterations == 0) 243 | { 244 | secs_ret secs_passed = 0; 245 | ee_u32 divisor; 246 | results[0].iterations = 1; 247 | while (secs_passed < (secs_ret)1) 248 | { 249 | results[0].iterations *= 10; 250 | start_time(); 251 | iterate(&results[0]); 252 | stop_time(); 253 | secs_passed = time_in_secs(get_time()); 254 | } 255 | /* now we know it executes for at least 1 sec, set actual run time at 256 | * about 10 secs */ 257 | divisor = (ee_u32)secs_passed; 258 | if (divisor == 0) /* some machines cast float to int as 0 since this 259 | conversion is not defined by ANSI, but we know at 260 | least one second passed */ 261 | divisor = 1; 262 | results[0].iterations *= 1 + 10 / divisor; 263 | } 264 | /* perform actual benchmark */ 265 | start_time(); 266 | #if (MULTITHREAD > 1) 267 | if (default_num_contexts > MULTITHREAD) 268 | { 269 | default_num_contexts = MULTITHREAD; 270 | } 271 | for (i = 0; i < default_num_contexts; i++) 272 | { 273 | results[i].iterations = results[0].iterations; 274 | results[i].execs = results[0].execs; 275 | core_start_parallel(&results[i]); 276 | } 277 | for (i = 0; i < default_num_contexts; i++) 278 | { 279 | core_stop_parallel(&results[i]); 280 | } 281 | #else 282 | iterate(&results[0]); 283 | #endif 284 | stop_time(); 285 | total_time = get_time(); 286 | /* get a function of the input to report */ 287 | seedcrc = crc16(results[0].seed1, seedcrc); 288 | seedcrc = crc16(results[0].seed2, seedcrc); 289 | seedcrc = crc16(results[0].seed3, seedcrc); 290 | seedcrc = crc16(results[0].size, seedcrc); 291 | 292 | switch (seedcrc) 293 | { /* test known output for common seeds */ 294 | case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */ 295 | known_id = 0; 296 | ee_printf("6k performance run parameters for coremark.\n"); 297 | break; 298 | case 0x7b05: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per 299 | algorithm */ 300 | known_id = 1; 301 | ee_printf("6k validation run parameters for coremark.\n"); 302 | break; 303 | case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm 304 | */ 305 | known_id = 2; 306 | ee_printf("Profile generation run parameters for coremark.\n"); 307 | break; 308 | case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */ 309 | known_id = 3; 310 | ee_printf("2K performance run parameters for coremark.\n"); 311 | break; 312 | case 0x18f2: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per 313 | algorithm */ 314 | known_id = 4; 315 | ee_printf("2K validation run parameters for coremark.\n"); 316 | break; 317 | default: 318 | total_errors = -1; 319 | break; 320 | } 321 | if (known_id >= 0) 322 | { 323 | for (i = 0; i < default_num_contexts; i++) 324 | { 325 | results[i].err = 0; 326 | if ((results[i].execs & ID_LIST) 327 | && (results[i].crclist != list_known_crc[known_id])) 328 | { 329 | ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n", 330 | i, 331 | results[i].crclist, 332 | list_known_crc[known_id]); 333 | results[i].err++; 334 | } 335 | if ((results[i].execs & ID_MATRIX) 336 | && (results[i].crcmatrix != matrix_known_crc[known_id])) 337 | { 338 | ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n", 339 | i, 340 | results[i].crcmatrix, 341 | matrix_known_crc[known_id]); 342 | results[i].err++; 343 | } 344 | if ((results[i].execs & ID_STATE) 345 | && (results[i].crcstate != state_known_crc[known_id])) 346 | { 347 | ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n", 348 | i, 349 | results[i].crcstate, 350 | state_known_crc[known_id]); 351 | results[i].err++; 352 | } 353 | total_errors += results[i].err; 354 | } 355 | } 356 | total_errors += check_data_types(); 357 | /* and report results */ 358 | ee_printf("CoreMark Size : %lu\n", (long unsigned)results[0].size); 359 | ee_printf("Total ticks : %lu\n", (long unsigned)total_time); 360 | #if HAS_FLOAT 361 | ee_printf("Total time (secs): %f\n", time_in_secs(total_time)); 362 | if (time_in_secs(total_time) > 0) 363 | ee_printf("Iterations/Sec : %f\n", 364 | default_num_contexts * results[0].iterations 365 | / time_in_secs(total_time)); 366 | #else 367 | ee_printf("Total time (secs): %d\n", time_in_secs(total_time)); 368 | if (time_in_secs(total_time) > 0) 369 | ee_printf("Iterations/Sec : %d\n", 370 | default_num_contexts * results[0].iterations 371 | / time_in_secs(total_time)); 372 | #endif 373 | if (time_in_secs(total_time) < 10) 374 | { 375 | ee_printf( 376 | "ERROR! Must execute for at least 10 secs for a valid result!\n"); 377 | total_errors++; 378 | } 379 | 380 | ee_printf("Iterations : %lu\n", 381 | (long unsigned)default_num_contexts * results[0].iterations); 382 | ee_printf("Compiler version : %s\n", COMPILER_VERSION); 383 | ee_printf("Compiler flags : %s\n", COMPILER_FLAGS); 384 | #if (MULTITHREAD > 1) 385 | ee_printf("Parallel %s : %d\n", PARALLEL_METHOD, default_num_contexts); 386 | #endif 387 | ee_printf("Memory location : %s\n", MEM_LOCATION); 388 | /* output for verification */ 389 | ee_printf("seedcrc : 0x%04x\n", seedcrc); 390 | if (results[0].execs & ID_LIST) 391 | for (i = 0; i < default_num_contexts; i++) 392 | ee_printf("[%d]crclist : 0x%04x\n", i, results[i].crclist); 393 | if (results[0].execs & ID_MATRIX) 394 | for (i = 0; i < default_num_contexts; i++) 395 | ee_printf("[%d]crcmatrix : 0x%04x\n", i, results[i].crcmatrix); 396 | if (results[0].execs & ID_STATE) 397 | for (i = 0; i < default_num_contexts; i++) 398 | ee_printf("[%d]crcstate : 0x%04x\n", i, results[i].crcstate); 399 | for (i = 0; i < default_num_contexts; i++) 400 | ee_printf("[%d]crcfinal : 0x%04x\n", i, results[i].crc); 401 | if (total_errors == 0) 402 | { 403 | ee_printf( 404 | "Correct operation validated. See README.md for run and reporting " 405 | "rules.\n"); 406 | #if HAS_FLOAT 407 | if (known_id == 3) 408 | { 409 | ee_printf("CoreMark 1.0 : %f / %s %s", 410 | default_num_contexts * results[0].iterations 411 | / time_in_secs(total_time), 412 | COMPILER_VERSION, 413 | COMPILER_FLAGS); 414 | #if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC) 415 | ee_printf(" / %s", MEM_LOCATION); 416 | #else 417 | ee_printf(" / %s", mem_name[MEM_METHOD]); 418 | #endif 419 | 420 | #if (MULTITHREAD > 1) 421 | ee_printf(" / %d:%s", default_num_contexts, PARALLEL_METHOD); 422 | #endif 423 | ee_printf("\n"); 424 | } 425 | #endif 426 | } 427 | if (total_errors > 0) 428 | ee_printf("Errors detected\n"); 429 | if (total_errors < 0) 430 | ee_printf( 431 | "Cannot validate operation for these seed values, please compare " 432 | "with results on a known platform.\n"); 433 | 434 | #if (MEM_METHOD == MEM_MALLOC) 435 | for (i = 0; i < MULTITHREAD; i++) 436 | portable_free(results[i].memblock[0]); 437 | #endif 438 | /* And last call any target specific code for finalizing */ 439 | portable_fini(&(results[0].port)); 440 | 441 | return MAIN_RETURN_VAL; 442 | } 443 | -------------------------------------------------------------------------------- /software/coremark/LICENSE.md: -------------------------------------------------------------------------------- 1 | # COREMARK® ACCEPTABLE USE AGREEMENT 2 | 3 | This ACCEPTABLE USE AGREEMENT (this “Agreement”) is offered by Embedded Microprocessor Benchmark Consortium, a California nonprofit corporation (“Licensor”), to users of its CoreMark® software (“Licensee”) exclusively on the following terms. 4 | 5 | Licensor offers benchmarking software (“Software”) pursuant to an open source license, but carefully controls use of its benchmarks and their associated goodwill. Licensor has registered its trademark in one of the benchmarks available through the Software, COREMARK, Ser. No. 85/487,290; Reg. No. 4,179,307 (the “Trademark”), and promotes the use of a standard metric as a benchmark for assessing the performance of embedded systems. Solely on the terms described herein, Licensee may use and display the Trademark in connection with the generation of data regarding measurement and analysis of computer and embedded system benchmarking via the Software (the “Licensed Use”). 6 | 7 | ## Article 1 – License Grant. 8 | 1.1. License. Subject to the terms and conditions of this Agreement, Licensor hereby grants to Licensee, and Licensee hereby accepts from Licensor, a personal, non-exclusive, royalty-free, revocable right and license to use and display the Trademark during the term of this Agreement (the “Term”), solely and exclusively in connection with the Licensed Use. During the Term, Licensee (i) shall not modify or otherwise create derivative works of the Trademark, and (ii) may use the Trademark only to the extent permitted under this License. Neither Licensee nor any affiliate or agent thereof shall otherwise use the Trademark without the prior express written consent of Licensor, which may be withheld in its sole and absolute discretion. All rights not expressly granted to Licensee hereunder shall remain the exclusive property of Licensor. 9 | 10 | 1.2. Modifications to the Software. Licensee shall not use the Trademark in connection with any use of a modified, derivative, or otherwise altered copy of the Software. 11 | 12 | 1.3. Licensor’s Use. Nothing in this Agreement shall preclude Licensor or any of its successors or assigns from using or permitting other entities to use the Trademark, whether or not such entity directly or indirectly competes or conflicts with Licensee’s Licensed Use in any manner. 13 | 14 | 1.4. Term and Termination. This Agreement is perpetual unless terminated by either of the parties. Licensee may terminate this Agreement for convenience, without cause or liability, for any reason or for no reason whatsoever, upon ten (10) business days written notice. Licensor may terminate this Agreement effective immediately upon notice of breach. Upon termination, Licensee shall immediately remove all implementations of the Trademark from the Licensed Use, and delete all digitals files and records of all materials related to the Trademark. 15 | 16 | ## Article 2 – Ownership. 17 | 2.1. Ownership. Licensee acknowledges and agrees that Licensor is the owner of all right, title, and interest in and to the Trademark, and all such right, title, and interest shall remain with Licensor. Licensee shall not contest, dispute, challenge, oppose, or seek to cancel Licensor’s right, title, and interest in and to the Trademark. Licensee shall not prosecute any application for registration of the Trademark. Licensee shall display appropriate notices regarding ownership of the Trademark in connection with the Licensed Use. 18 | 19 | 2.2. Goodwill. Licensee acknowledges that Licensee shall not acquire any right, title, or interest in the Trademark by virtue of this Agreement other than the license granted hereunder, and disclaims any such right, title, interest, or ownership. All goodwill and reputation generated by Licensee’s use of the Trademark shall inure to the exclusive benefit of Licensor. Licensee shall not by any act or omission use the Trademark in any manner that disparages or reflects adversely on Licensor or its Licensed Use or reputation. Licensee shall not take any action that would interfere with or prejudice Licensor’s ownership or registration of the Trademark, the validity of the Trademark or the validity of the license granted by this Agreement. If Licensor determines and notifies Licensee that any act taken in connection with the Licensed Use (i) is inaccurate, unlawful or offensive to good taste; (ii) fails to provide for proper trademark notices, or (iii) otherwise violates Licensee’s obligations under this Agreement, the license granted under this Agreement shall terminate. 20 | 21 | ## Article 3 – Indemnification. 22 | 3.1. Indemnification Generally. Licensee agrees to indemnify, defend, and hold harmless (collectively “indemnify” or “indemnification”) Licensor, including Licensor’s members, managers, officers, and employees (collectively “Related Persons”), from and against, and pay or reimburse Licensor and such Related Persons for, any and all third-party actions, claims, demands, proceedings, investigations, inquiries (collectively, “Claims”), and any and all liabilities, obligations, fines, deficiencies, costs, expenses, royalties, losses, and damages (including reasonable outside counsel fees and expenses) associated with such Claims, to the extent that such Claim arises out of (i) Licensee’s material breach of this Agreement, or (ii) any allegation(s) that Licensee’s actions infringe or violate any third-party intellectual property right, including without limitation, any U.S. copyright, patent, or trademark, or are otherwise found to be tortious or criminal (whether or not such indemnified person is a named party in a legal proceeding). 23 | 24 | 3.2. Notice and Defense of Claims. Licensor shall promptly notify Licensee of any Claim for which indemnification is sought, following actual knowledge of such Claim, provided however that the failure to give such notice shall not relieve Licensee of its obligations hereunder except to the extent that Licensee is materially prejudiced by such failure. In the event that any third-party Claim is brought, Licensee shall have the right and option to undertake and control the defense of such action with counsel of its choice, provided however that (i) Licensor at its own expense may participate and appear on an equal footing with Licensee in the defense of any such Claim, (ii) Licensor may undertake and control such defense in the event of the material failure of Licensee to undertake and control the same; and (iii) the defense of any Claim relating to the intellectual property rights of Licensor or its licensors and any related counterclaims shall be solely controlled by Licensor with counsel of its choice. Licensee shall not consent to judgment or concede or settle or compromise any Claim without the prior written approval of Licensor (whose approval shall not be unreasonably withheld), unless such concession or settlement or compromise includes a full and unconditional release of Licensor and any applicable Related Persons from all liabilities in respect of such Claim. 25 | 26 | ## Article 4 – Miscellaneous. 27 | 4.1. Relationship of the Parties. This Agreement does not create a partnership, franchise, joint venture, agency, fiduciary, or employment relationship between the parties. 28 | 29 | 4.2. No Third-Party Beneficiaries. Except for the rights of Related Persons under Article 3 (Indemnification), there are no third-party beneficiaries to this Agreement. 30 | 31 | 4.3. Assignment. Licensee’s rights hereunder are non-assignable, and may not be sublicensed. 32 | 33 | 4.4. Equitable Relief. Licensee acknowledges that the remedies available at law for any breach of this Agreement will, by their nature, be inadequate. Accordingly, Licensor may obtain injunctive relief or other equitable relief to restrain a breach or threatened breach of this Agreement or to specifically enforce this Agreement, without proving that any monetary damages have been sustained, and without the requirement of posting of a bond prior to obtaining such equitable relief. 34 | 35 | 4.5. Governing Law. This Agreement will be interpreted, construed, and enforced in all respects in accordance with the laws of the State of California, without reference to its conflict of law principles. 36 | 37 | 4.6. Attorneys’ Fees. If any legal action, arbitration or other proceeding is brought for the enforcement of this Agreement, or because of an alleged dispute, breach, default, or misrepresentation in connection with any of the provisions of this Agreement, the successful or prevailing party shall be entitled to recover its reasonable attorneys’ fees and other reasonable costs incurred in that action or proceeding, in addition to any other relief to which it may be entitled. 38 | 39 | 4.7. Amendment; Waiver. This Agreement may not be amended, nor may any rights under it be waived, except in writing by Licensor. 40 | 41 | 4.8. Severability. If any provision of this Agreement is held by a court of competent jurisdiction to be contrary to law, the provision shall be modified by the court and interpreted so as best to accomplish the objectives of the original provision to the fullest extent 42 | permitted by law, and the remaining provisions of this Agreement shall remain in effect. 43 | 44 | 4.9. Entire Agreement. This Agreement constitutes the entire agreement between the parties and supersedes all prior and contemporaneous agreements, proposals or representations, written or oral, concerning its subject matter. 45 | 46 | 47 | # Apache License 48 | 49 | Version 2.0, January 2004 50 | 51 | http://www.apache.org/licenses/ 52 | 53 | ## TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 54 | 55 | 1. Definitions. 56 | 57 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 58 | 59 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 60 | 61 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 62 | 63 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 64 | 65 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 66 | 67 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 68 | 69 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 70 | 71 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 72 | 73 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 74 | 75 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 76 | 77 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 78 | 79 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 80 | 81 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 82 | 83 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 84 | You must cause any modified files to carry prominent notices stating that You changed the files; and 85 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 86 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 87 | 88 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 89 | 90 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 91 | 92 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 93 | 94 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 95 | 96 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 97 | 98 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 99 | 100 | END OF TERMS AND CONDITIONS 101 | -------------------------------------------------------------------------------- /software/coremark/barebones/ee_printf.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define ZEROPAD (1 << 0) /* Pad with zero */ 21 | #define SIGN (1 << 1) /* Unsigned/signed long */ 22 | #define PLUS (1 << 2) /* Show plus */ 23 | #define SPACE (1 << 3) /* Spacer */ 24 | #define LEFT (1 << 4) /* Left justified */ 25 | #define HEX_PREP (1 << 5) /* 0x */ 26 | #define UPPERCASE (1 << 6) /* 'ABCDEF' */ 27 | 28 | #define is_digit(c) ((c) >= '0' && (c) <= '9') 29 | 30 | static char * digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 31 | static char * upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 32 | static ee_size_t strnlen(const char *s, ee_size_t count); 33 | 34 | static ee_size_t 35 | strnlen(const char *s, ee_size_t count) 36 | { 37 | const char *sc; 38 | for (sc = s; *sc != '\0' && count--; ++sc) 39 | ; 40 | return sc - s; 41 | } 42 | 43 | static int 44 | skip_atoi(const char **s) 45 | { 46 | int i = 0; 47 | while (is_digit(**s)) 48 | i = i * 10 + *((*s)++) - '0'; 49 | return i; 50 | } 51 | 52 | static char * 53 | number(char *str, long num, int base, int size, int precision, int type) 54 | { 55 | char c, sign, tmp[66]; 56 | char *dig = digits; 57 | int i; 58 | 59 | if (type & UPPERCASE) 60 | dig = upper_digits; 61 | if (type & LEFT) 62 | type &= ~ZEROPAD; 63 | if (base < 2 || base > 36) 64 | return 0; 65 | 66 | c = (type & ZEROPAD) ? '0' : ' '; 67 | sign = 0; 68 | if (type & SIGN) 69 | { 70 | if (num < 0) 71 | { 72 | sign = '-'; 73 | num = -num; 74 | size--; 75 | } 76 | else if (type & PLUS) 77 | { 78 | sign = '+'; 79 | size--; 80 | } 81 | else if (type & SPACE) 82 | { 83 | sign = ' '; 84 | size--; 85 | } 86 | } 87 | 88 | if (type & HEX_PREP) 89 | { 90 | if (base == 16) 91 | size -= 2; 92 | else if (base == 8) 93 | size--; 94 | } 95 | 96 | i = 0; 97 | 98 | if (num == 0) 99 | tmp[i++] = '0'; 100 | else 101 | { 102 | while (num != 0) 103 | { 104 | tmp[i++] = dig[((unsigned long)num) % (unsigned)base]; 105 | num = ((unsigned long)num) / (unsigned)base; 106 | } 107 | } 108 | 109 | if (i > precision) 110 | precision = i; 111 | size -= precision; 112 | if (!(type & (ZEROPAD | LEFT))) 113 | while (size-- > 0) 114 | *str++ = ' '; 115 | if (sign) 116 | *str++ = sign; 117 | 118 | if (type & HEX_PREP) 119 | { 120 | if (base == 8) 121 | *str++ = '0'; 122 | else if (base == 16) 123 | { 124 | *str++ = '0'; 125 | *str++ = digits[33]; 126 | } 127 | } 128 | 129 | if (!(type & LEFT)) 130 | while (size-- > 0) 131 | *str++ = c; 132 | while (i < precision--) 133 | *str++ = '0'; 134 | while (i-- > 0) 135 | *str++ = tmp[i]; 136 | while (size-- > 0) 137 | *str++ = ' '; 138 | 139 | return str; 140 | } 141 | 142 | static char * 143 | eaddr(char *str, unsigned char *addr, int size, int precision, int type) 144 | { 145 | char tmp[24]; 146 | char *dig = digits; 147 | int i, len; 148 | 149 | if (type & UPPERCASE) 150 | dig = upper_digits; 151 | len = 0; 152 | for (i = 0; i < 6; i++) 153 | { 154 | if (i != 0) 155 | tmp[len++] = ':'; 156 | tmp[len++] = dig[addr[i] >> 4]; 157 | tmp[len++] = dig[addr[i] & 0x0F]; 158 | } 159 | 160 | if (!(type & LEFT)) 161 | while (len < size--) 162 | *str++ = ' '; 163 | for (i = 0; i < len; ++i) 164 | *str++ = tmp[i]; 165 | while (len < size--) 166 | *str++ = ' '; 167 | 168 | return str; 169 | } 170 | 171 | static char * 172 | iaddr(char *str, unsigned char *addr, int size, int precision, int type) 173 | { 174 | char tmp[24]; 175 | int i, n, len; 176 | 177 | len = 0; 178 | for (i = 0; i < 4; i++) 179 | { 180 | if (i != 0) 181 | tmp[len++] = '.'; 182 | n = addr[i]; 183 | 184 | if (n == 0) 185 | tmp[len++] = digits[0]; 186 | else 187 | { 188 | if (n >= 100) 189 | { 190 | tmp[len++] = digits[n / 100]; 191 | n = n % 100; 192 | tmp[len++] = digits[n / 10]; 193 | n = n % 10; 194 | } 195 | else if (n >= 10) 196 | { 197 | tmp[len++] = digits[n / 10]; 198 | n = n % 10; 199 | } 200 | 201 | tmp[len++] = digits[n]; 202 | } 203 | } 204 | 205 | if (!(type & LEFT)) 206 | while (len < size--) 207 | *str++ = ' '; 208 | for (i = 0; i < len; ++i) 209 | *str++ = tmp[i]; 210 | while (len < size--) 211 | *str++ = ' '; 212 | 213 | return str; 214 | } 215 | 216 | #if HAS_FLOAT 217 | 218 | char * ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); 219 | char * fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); 220 | static void ee_bufcpy(char *d, char *s, int count); 221 | 222 | void 223 | ee_bufcpy(char *pd, char *ps, int count) 224 | { 225 | char *pe = ps + count; 226 | while (ps != pe) 227 | *pd++ = *ps++; 228 | } 229 | 230 | static void 231 | parse_float(double value, char *buffer, char fmt, int precision) 232 | { 233 | int decpt, sign, exp, pos; 234 | char *digits = NULL; 235 | char cvtbuf[80]; 236 | int capexp = 0; 237 | int magnitude; 238 | 239 | if (fmt == 'G' || fmt == 'E') 240 | { 241 | capexp = 1; 242 | fmt += 'a' - 'A'; 243 | } 244 | 245 | if (fmt == 'g') 246 | { 247 | digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf); 248 | magnitude = decpt - 1; 249 | if (magnitude < -4 || magnitude > precision - 1) 250 | { 251 | fmt = 'e'; 252 | precision -= 1; 253 | } 254 | else 255 | { 256 | fmt = 'f'; 257 | precision -= decpt; 258 | } 259 | } 260 | 261 | if (fmt == 'e') 262 | { 263 | digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf); 264 | 265 | if (sign) 266 | *buffer++ = '-'; 267 | *buffer++ = *digits; 268 | if (precision > 0) 269 | *buffer++ = '.'; 270 | ee_bufcpy(buffer, digits + 1, precision); 271 | buffer += precision; 272 | *buffer++ = capexp ? 'E' : 'e'; 273 | 274 | if (decpt == 0) 275 | { 276 | if (value == 0.0) 277 | exp = 0; 278 | else 279 | exp = -1; 280 | } 281 | else 282 | exp = decpt - 1; 283 | 284 | if (exp < 0) 285 | { 286 | *buffer++ = '-'; 287 | exp = -exp; 288 | } 289 | else 290 | *buffer++ = '+'; 291 | 292 | buffer[2] = (exp % 10) + '0'; 293 | exp = exp / 10; 294 | buffer[1] = (exp % 10) + '0'; 295 | exp = exp / 10; 296 | buffer[0] = (exp % 10) + '0'; 297 | buffer += 3; 298 | } 299 | else if (fmt == 'f') 300 | { 301 | digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf); 302 | if (sign) 303 | *buffer++ = '-'; 304 | if (*digits) 305 | { 306 | if (decpt <= 0) 307 | { 308 | *buffer++ = '0'; 309 | *buffer++ = '.'; 310 | for (pos = 0; pos < -decpt; pos++) 311 | *buffer++ = '0'; 312 | while (*digits) 313 | *buffer++ = *digits++; 314 | } 315 | else 316 | { 317 | pos = 0; 318 | while (*digits) 319 | { 320 | if (pos++ == decpt) 321 | *buffer++ = '.'; 322 | *buffer++ = *digits++; 323 | } 324 | } 325 | } 326 | else 327 | { 328 | *buffer++ = '0'; 329 | if (precision > 0) 330 | { 331 | *buffer++ = '.'; 332 | for (pos = 0; pos < precision; pos++) 333 | *buffer++ = '0'; 334 | } 335 | } 336 | } 337 | 338 | *buffer = '\0'; 339 | } 340 | 341 | static void 342 | decimal_point(char *buffer) 343 | { 344 | while (*buffer) 345 | { 346 | if (*buffer == '.') 347 | return; 348 | if (*buffer == 'e' || *buffer == 'E') 349 | break; 350 | buffer++; 351 | } 352 | 353 | if (*buffer) 354 | { 355 | int n = strnlen(buffer, 256); 356 | while (n > 0) 357 | { 358 | buffer[n + 1] = buffer[n]; 359 | n--; 360 | } 361 | 362 | *buffer = '.'; 363 | } 364 | else 365 | { 366 | *buffer++ = '.'; 367 | *buffer = '\0'; 368 | } 369 | } 370 | 371 | static void 372 | cropzeros(char *buffer) 373 | { 374 | char *stop; 375 | 376 | while (*buffer && *buffer != '.') 377 | buffer++; 378 | if (*buffer++) 379 | { 380 | while (*buffer && *buffer != 'e' && *buffer != 'E') 381 | buffer++; 382 | stop = buffer--; 383 | while (*buffer == '0') 384 | buffer--; 385 | if (*buffer == '.') 386 | buffer--; 387 | while (buffer != stop) 388 | *++buffer = 0; 389 | } 390 | } 391 | 392 | static char * 393 | flt(char *str, double num, int size, int precision, char fmt, int flags) 394 | { 395 | char tmp[80]; 396 | char c, sign; 397 | int n, i; 398 | 399 | // Left align means no zero padding 400 | if (flags & LEFT) 401 | flags &= ~ZEROPAD; 402 | 403 | // Determine padding and sign char 404 | c = (flags & ZEROPAD) ? '0' : ' '; 405 | sign = 0; 406 | if (flags & SIGN) 407 | { 408 | if (num < 0.0) 409 | { 410 | sign = '-'; 411 | num = -num; 412 | size--; 413 | } 414 | else if (flags & PLUS) 415 | { 416 | sign = '+'; 417 | size--; 418 | } 419 | else if (flags & SPACE) 420 | { 421 | sign = ' '; 422 | size--; 423 | } 424 | } 425 | 426 | // Compute the precision value 427 | if (precision < 0) 428 | precision = 6; // Default precision: 6 429 | 430 | // Convert floating point number to text 431 | parse_float(num, tmp, fmt, precision); 432 | 433 | if ((flags & HEX_PREP) && precision == 0) 434 | decimal_point(tmp); 435 | if (fmt == 'g' && !(flags & HEX_PREP)) 436 | cropzeros(tmp); 437 | 438 | n = strnlen(tmp, 256); 439 | 440 | // Output number with alignment and padding 441 | size -= n; 442 | if (!(flags & (ZEROPAD | LEFT))) 443 | while (size-- > 0) 444 | *str++ = ' '; 445 | if (sign) 446 | *str++ = sign; 447 | if (!(flags & LEFT)) 448 | while (size-- > 0) 449 | *str++ = c; 450 | for (i = 0; i < n; i++) 451 | *str++ = tmp[i]; 452 | while (size-- > 0) 453 | *str++ = ' '; 454 | 455 | return str; 456 | } 457 | 458 | #endif 459 | 460 | static int 461 | ee_vsprintf(char *buf, const char *fmt, va_list args) 462 | { 463 | int len; 464 | unsigned long num; 465 | int i, base; 466 | char * str; 467 | char * s; 468 | 469 | int flags; // Flags to number() 470 | 471 | int field_width; // Width of output field 472 | int precision; // Min. # of digits for integers; max number of chars for 473 | // from string 474 | int qualifier; // 'h', 'l', or 'L' for integer fields 475 | 476 | for (str = buf; *fmt; fmt++) 477 | { 478 | if (*fmt != '%') 479 | { 480 | *str++ = *fmt; 481 | continue; 482 | } 483 | 484 | // Process flags 485 | flags = 0; 486 | repeat: 487 | fmt++; // This also skips first '%' 488 | switch (*fmt) 489 | { 490 | case '-': 491 | flags |= LEFT; 492 | goto repeat; 493 | case '+': 494 | flags |= PLUS; 495 | goto repeat; 496 | case ' ': 497 | flags |= SPACE; 498 | goto repeat; 499 | case '#': 500 | flags |= HEX_PREP; 501 | goto repeat; 502 | case '0': 503 | flags |= ZEROPAD; 504 | goto repeat; 505 | } 506 | 507 | // Get field width 508 | field_width = -1; 509 | if (is_digit(*fmt)) 510 | field_width = skip_atoi(&fmt); 511 | else if (*fmt == '*') 512 | { 513 | fmt++; 514 | field_width = va_arg(args, int); 515 | if (field_width < 0) 516 | { 517 | field_width = -field_width; 518 | flags |= LEFT; 519 | } 520 | } 521 | 522 | // Get the precision 523 | precision = -1; 524 | if (*fmt == '.') 525 | { 526 | ++fmt; 527 | if (is_digit(*fmt)) 528 | precision = skip_atoi(&fmt); 529 | else if (*fmt == '*') 530 | { 531 | ++fmt; 532 | precision = va_arg(args, int); 533 | } 534 | if (precision < 0) 535 | precision = 0; 536 | } 537 | 538 | // Get the conversion qualifier 539 | qualifier = -1; 540 | if (*fmt == 'l' || *fmt == 'L') 541 | { 542 | qualifier = *fmt; 543 | fmt++; 544 | } 545 | 546 | // Default base 547 | base = 10; 548 | 549 | switch (*fmt) 550 | { 551 | case 'c': 552 | if (!(flags & LEFT)) 553 | while (--field_width > 0) 554 | *str++ = ' '; 555 | *str++ = (unsigned char)va_arg(args, int); 556 | while (--field_width > 0) 557 | *str++ = ' '; 558 | continue; 559 | 560 | case 's': 561 | s = va_arg(args, char *); 562 | if (!s) 563 | s = ""; 564 | len = strnlen(s, precision); 565 | if (!(flags & LEFT)) 566 | while (len < field_width--) 567 | *str++ = ' '; 568 | for (i = 0; i < len; ++i) 569 | *str++ = *s++; 570 | while (len < field_width--) 571 | *str++ = ' '; 572 | continue; 573 | 574 | case 'p': 575 | if (field_width == -1) 576 | { 577 | field_width = 2 * sizeof(void *); 578 | flags |= ZEROPAD; 579 | } 580 | str = number(str, 581 | (unsigned long)va_arg(args, void *), 582 | 16, 583 | field_width, 584 | precision, 585 | flags); 586 | continue; 587 | 588 | case 'A': 589 | flags |= UPPERCASE; 590 | 591 | case 'a': 592 | if (qualifier == 'l') 593 | str = eaddr(str, 594 | va_arg(args, unsigned char *), 595 | field_width, 596 | precision, 597 | flags); 598 | else 599 | str = iaddr(str, 600 | va_arg(args, unsigned char *), 601 | field_width, 602 | precision, 603 | flags); 604 | continue; 605 | 606 | // Integer number formats - set up the flags and "break" 607 | case 'o': 608 | base = 8; 609 | break; 610 | 611 | case 'X': 612 | flags |= UPPERCASE; 613 | 614 | case 'x': 615 | base = 16; 616 | break; 617 | 618 | case 'd': 619 | case 'i': 620 | flags |= SIGN; 621 | 622 | case 'u': 623 | break; 624 | 625 | #if HAS_FLOAT 626 | 627 | case 'f': 628 | str = flt(str, 629 | va_arg(args, double), 630 | field_width, 631 | precision, 632 | *fmt, 633 | flags | SIGN); 634 | continue; 635 | 636 | #endif 637 | 638 | default: 639 | if (*fmt != '%') 640 | *str++ = '%'; 641 | if (*fmt) 642 | *str++ = *fmt; 643 | else 644 | --fmt; 645 | continue; 646 | } 647 | 648 | if (qualifier == 'l') 649 | num = va_arg(args, unsigned long); 650 | else if (flags & SIGN) 651 | num = va_arg(args, int); 652 | else 653 | num = va_arg(args, unsigned int); 654 | 655 | str = number(str, num, base, field_width, precision, flags); 656 | } 657 | 658 | *str = '\0'; 659 | return str - buf; 660 | } 661 | 662 | void 663 | uart_send_char(char c) 664 | { 665 | //#error "You must implement the method uart_send_char to use this file!\n"; 666 | /* Output of a char to a UART usually follows the following model: 667 | Wait until UART is ready 668 | Write char to UART 669 | Wait until UART is done 670 | 671 | Or in code: 672 | while (*UART_CONTROL_ADDRESS != UART_READY); 673 | *UART_DATA_ADDRESS = c; 674 | while (*UART_CONTROL_ADDRESS != UART_READY); 675 | 676 | Check the UART sample code on your platform or the board 677 | documentation. 678 | */ 679 | volatile int sum = 0; 680 | int uart_wait = 10000; 681 | int i; 682 | 683 | for(i = 0; i < uart_wait; i++) sum += i; 684 | 685 | volatile unsigned int* output_addr = (unsigned int*)0x20020; 686 | *output_addr = c; 687 | } 688 | 689 | int 690 | ee_printf(const char *fmt, ...) 691 | { 692 | char buf[1024], *p; 693 | va_list args; 694 | int n = 0; 695 | 696 | va_start(args, fmt); 697 | ee_vsprintf(buf, fmt, args); 698 | va_end(args); 699 | p = buf; 700 | while (*p) 701 | { 702 | uart_send_char(*p); 703 | n++; 704 | p++; 705 | } 706 | 707 | return n; 708 | } 709 | -------------------------------------------------------------------------------- /software/coremark/core_list_join.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Original Author: Shay Gal-on 17 | */ 18 | 19 | #include "coremark.h" 20 | /* 21 | Topic: Description 22 | Benchmark using a linked list. 23 | 24 | Linked list is a common data structure used in many applications. 25 | 26 | For our purposes, this will excercise the memory units of the processor. 27 | In particular, usage of the list pointers to find and alter data. 28 | 29 | We are not using Malloc since some platforms do not support this 30 | library. 31 | 32 | Instead, the memory block being passed in is used to create a list, 33 | and the benchmark takes care not to add more items then can be 34 | accomodated by the memory block. The porting layer will make sure 35 | that we have a valid memory block. 36 | 37 | All operations are done in place, without using any extra memory. 38 | 39 | The list itself contains list pointers and pointers to data items. 40 | Data items contain the following: 41 | 42 | idx - An index that captures the initial order of the list. 43 | data - Variable data initialized based on the input parameters. The 16b 44 | are divided as follows: o Upper 8b are backup of original data. o Bit 7 45 | indicates if the lower 7 bits are to be used as is or calculated. o Bits 0-2 46 | indicate type of operation to perform to get a 7b value. o Bits 3-6 provide 47 | input for the operation. 48 | 49 | */ 50 | 51 | /* local functions */ 52 | 53 | list_head *core_list_find(list_head *list, list_data *info); 54 | list_head *core_list_reverse(list_head *list); 55 | list_head *core_list_remove(list_head *item); 56 | list_head *core_list_undo_remove(list_head *item_removed, 57 | list_head *item_modified); 58 | list_head *core_list_insert_new(list_head * insert_point, 59 | list_data * info, 60 | list_head **memblock, 61 | list_data **datablock, 62 | list_head * memblock_end, 63 | list_data * datablock_end); 64 | typedef ee_s32 (*list_cmp)(list_data *a, list_data *b, core_results *res); 65 | list_head *core_list_mergesort(list_head * list, 66 | list_cmp cmp, 67 | core_results *res); 68 | 69 | ee_s16 70 | calc_func(ee_s16 *pdata, core_results *res) 71 | { 72 | ee_s16 data = *pdata; 73 | ee_s16 retval; 74 | ee_u8 optype 75 | = (data >> 7) 76 | & 1; /* bit 7 indicates if the function result has been cached */ 77 | if (optype) /* if cached, use cache */ 78 | return (data & 0x007f); 79 | else 80 | { /* otherwise calculate and cache the result */ 81 | ee_s16 flag = data & 0x7; /* bits 0-2 is type of function to perform */ 82 | ee_s16 dtype 83 | = ((data >> 3) 84 | & 0xf); /* bits 3-6 is specific data for the operation */ 85 | dtype |= dtype << 4; /* replicate the lower 4 bits to get an 8b value */ 86 | switch (flag) 87 | { 88 | case 0: 89 | if (dtype < 0x22) /* set min period for bit corruption */ 90 | dtype = 0x22; 91 | retval = core_bench_state(res->size, 92 | res->memblock[3], 93 | res->seed1, 94 | res->seed2, 95 | dtype, 96 | res->crc); 97 | if (res->crcstate == 0) 98 | res->crcstate = retval; 99 | break; 100 | case 1: 101 | retval = core_bench_matrix(&(res->mat), dtype, res->crc); 102 | if (res->crcmatrix == 0) 103 | res->crcmatrix = retval; 104 | break; 105 | default: 106 | retval = data; 107 | break; 108 | } 109 | res->crc = crcu16(retval, res->crc); 110 | retval &= 0x007f; 111 | *pdata = (data & 0xff00) | 0x0080 | retval; /* cache the result */ 112 | return retval; 113 | } 114 | } 115 | /* Function: cmp_complex 116 | Compare the data item in a list cell. 117 | 118 | Can be used by mergesort. 119 | */ 120 | ee_s32 121 | cmp_complex(list_data *a, list_data *b, core_results *res) 122 | { 123 | ee_s16 val1 = calc_func(&(a->data16), res); 124 | ee_s16 val2 = calc_func(&(b->data16), res); 125 | return val1 - val2; 126 | } 127 | 128 | /* Function: cmp_idx 129 | Compare the idx item in a list cell, and regen the data. 130 | 131 | Can be used by mergesort. 132 | */ 133 | ee_s32 134 | cmp_idx(list_data *a, list_data *b, core_results *res) 135 | { 136 | if (res == NULL) 137 | { 138 | a->data16 = (a->data16 & 0xff00) | (0x00ff & (a->data16 >> 8)); 139 | b->data16 = (b->data16 & 0xff00) | (0x00ff & (b->data16 >> 8)); 140 | } 141 | return a->idx - b->idx; 142 | } 143 | 144 | void 145 | copy_info(list_data *to, list_data *from) 146 | { 147 | to->data16 = from->data16; 148 | to->idx = from->idx; 149 | } 150 | 151 | /* Benchmark for linked list: 152 | - Try to find multiple data items. 153 | - List sort 154 | - Operate on data from list (crc) 155 | - Single remove/reinsert 156 | * At the end of this function, the list is back to original state 157 | */ 158 | ee_u16 159 | core_bench_list(core_results *res, ee_s16 finder_idx) 160 | { 161 | ee_u16 retval = 0; 162 | ee_u16 found = 0, missed = 0; 163 | list_head *list = res->list; 164 | ee_s16 find_num = res->seed3; 165 | list_head *this_find; 166 | list_head *finder, *remover; 167 | list_data info; 168 | ee_s16 i; 169 | 170 | info.idx = finder_idx; 171 | /* find values in the list, and change the list each time 172 | * (reverse and cache if value found) */ 173 | for (i = 0; i < find_num; i++) 174 | { 175 | info.data16 = (i & 0xff); 176 | this_find = core_list_find(list, &info); 177 | list = core_list_reverse(list); 178 | if (this_find == NULL) 179 | { 180 | missed++; 181 | retval += (list->next->info->data16 >> 8) & 1; 182 | } 183 | else 184 | { 185 | found++; 186 | if (this_find->info->data16 & 0x1) /* use found value */ 187 | retval += (this_find->info->data16 >> 9) & 1; 188 | /* and cache next item at the head of the list (if any) */ 189 | if (this_find->next != NULL) 190 | { 191 | finder = this_find->next; 192 | this_find->next = finder->next; 193 | finder->next = list->next; 194 | list->next = finder; 195 | } 196 | } 197 | if (info.idx >= 0) 198 | info.idx++; 199 | #if CORE_DEBUG 200 | ee_printf("List find %d: [%d,%d,%d]\n", i, retval, missed, found); 201 | #endif 202 | } 203 | retval += found * 4 - missed; 204 | /* sort the list by data content and remove one item*/ 205 | if (finder_idx > 0) 206 | list = core_list_mergesort(list, cmp_complex, res); 207 | remover = core_list_remove(list->next); 208 | /* CRC data content of list from location of index N forward, and then undo 209 | * remove */ 210 | finder = core_list_find(list, &info); 211 | if (!finder) 212 | finder = list->next; 213 | while (finder) 214 | { 215 | retval = crc16(list->info->data16, retval); 216 | finder = finder->next; 217 | } 218 | #if CORE_DEBUG 219 | ee_printf("List sort 1: %04x\n", retval); 220 | #endif 221 | remover = core_list_undo_remove(remover, list->next); 222 | /* sort the list by index, in effect returning the list to original state */ 223 | list = core_list_mergesort(list, cmp_idx, NULL); 224 | /* CRC data content of list */ 225 | finder = list->next; 226 | while (finder) 227 | { 228 | retval = crc16(list->info->data16, retval); 229 | finder = finder->next; 230 | } 231 | #if CORE_DEBUG 232 | ee_printf("List sort 2: %04x\n", retval); 233 | #endif 234 | return retval; 235 | } 236 | /* Function: core_list_init 237 | Initialize list with data. 238 | 239 | Parameters: 240 | blksize - Size of memory to be initialized. 241 | memblock - Pointer to memory block. 242 | seed - Actual values chosen depend on the seed parameter. 243 | The seed parameter MUST be supplied from a source that cannot be 244 | determined at compile time 245 | 246 | Returns: 247 | Pointer to the head of the list. 248 | 249 | */ 250 | list_head * 251 | core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed) 252 | { 253 | /* calculated pointers for the list */ 254 | ee_u32 per_item = 16 + sizeof(struct list_data_s); 255 | ee_u32 size = (blksize / per_item) 256 | - 2; /* to accomodate systems with 64b pointers, and make sure 257 | same code is executed, set max list elements */ 258 | list_head *memblock_end = memblock + size; 259 | list_data *datablock = (list_data *)(memblock_end); 260 | list_data *datablock_end = datablock + size; 261 | /* some useful variables */ 262 | ee_u32 i; 263 | list_head *finder, *list = memblock; 264 | list_data info; 265 | 266 | /* create a fake items for the list head and tail */ 267 | list->next = NULL; 268 | list->info = datablock; 269 | list->info->idx = 0x0000; 270 | list->info->data16 = (ee_s16)0x8080; 271 | memblock++; 272 | datablock++; 273 | info.idx = 0x7fff; 274 | info.data16 = (ee_s16)0xffff; 275 | core_list_insert_new( 276 | list, &info, &memblock, &datablock, memblock_end, datablock_end); 277 | 278 | /* then insert size items */ 279 | for (i = 0; i < size; i++) 280 | { 281 | ee_u16 datpat = ((ee_u16)(seed ^ i) & 0xf); 282 | ee_u16 dat 283 | = (datpat << 3) | (i & 0x7); /* alternate between algorithms */ 284 | info.data16 = (dat << 8) | dat; /* fill the data with actual data and 285 | upper bits with rebuild value */ 286 | core_list_insert_new( 287 | list, &info, &memblock, &datablock, memblock_end, datablock_end); 288 | } 289 | /* and now index the list so we know initial seed order of the list */ 290 | finder = list->next; 291 | i = 1; 292 | while (finder->next != NULL) 293 | { 294 | if (i < size / 5) /* first 20% of the list in order */ 295 | finder->info->idx = i++; 296 | else 297 | { 298 | ee_u16 pat = (ee_u16)(i++ ^ seed); /* get a pseudo random number */ 299 | finder->info->idx = 0x3fff 300 | & (((i & 0x07) << 8) 301 | | pat); /* make sure the mixed items end up 302 | after the ones in sequence */ 303 | } 304 | finder = finder->next; 305 | } 306 | list = core_list_mergesort(list, cmp_idx, NULL); 307 | #if CORE_DEBUG 308 | ee_printf("Initialized list:\n"); 309 | finder = list; 310 | while (finder) 311 | { 312 | ee_printf( 313 | "[%04x,%04x]", finder->info->idx, (ee_u16)finder->info->data16); 314 | finder = finder->next; 315 | } 316 | ee_printf("\n"); 317 | #endif 318 | return list; 319 | } 320 | 321 | /* Function: core_list_insert 322 | Insert an item to the list 323 | 324 | Parameters: 325 | insert_point - where to insert the item. 326 | info - data for the cell. 327 | memblock - pointer for the list header 328 | datablock - pointer for the list data 329 | memblock_end - end of region for list headers 330 | datablock_end - end of region for list data 331 | 332 | Returns: 333 | Pointer to new item. 334 | */ 335 | list_head * 336 | core_list_insert_new(list_head * insert_point, 337 | list_data * info, 338 | list_head **memblock, 339 | list_data **datablock, 340 | list_head * memblock_end, 341 | list_data * datablock_end) 342 | { 343 | list_head *newitem; 344 | 345 | if ((*memblock + 1) >= memblock_end) 346 | return NULL; 347 | if ((*datablock + 1) >= datablock_end) 348 | return NULL; 349 | 350 | newitem = *memblock; 351 | (*memblock)++; 352 | newitem->next = insert_point->next; 353 | insert_point->next = newitem; 354 | 355 | newitem->info = *datablock; 356 | (*datablock)++; 357 | copy_info(newitem->info, info); 358 | 359 | return newitem; 360 | } 361 | 362 | /* Function: core_list_remove 363 | Remove an item from the list. 364 | 365 | Operation: 366 | For a singly linked list, remove by copying the data from the next item 367 | over to the current cell, and unlinking the next item. 368 | 369 | Note: 370 | since there is always a fake item at the end of the list, no need to 371 | check for NULL. 372 | 373 | Returns: 374 | Removed item. 375 | */ 376 | list_head * 377 | core_list_remove(list_head *item) 378 | { 379 | list_data *tmp; 380 | list_head *ret = item->next; 381 | /* swap data pointers */ 382 | tmp = item->info; 383 | item->info = ret->info; 384 | ret->info = tmp; 385 | /* and eliminate item */ 386 | item->next = item->next->next; 387 | ret->next = NULL; 388 | return ret; 389 | } 390 | 391 | /* Function: core_list_undo_remove 392 | Undo a remove operation. 393 | 394 | Operation: 395 | Since we want each iteration of the benchmark to be exactly the same, 396 | we need to be able to undo a remove. 397 | Link the removed item back into the list, and switch the info items. 398 | 399 | Parameters: 400 | item_removed - Return value from the 401 | item_modified - List item that was modified during 402 | 403 | Returns: 404 | The item that was linked back to the list. 405 | 406 | */ 407 | list_head * 408 | core_list_undo_remove(list_head *item_removed, list_head *item_modified) 409 | { 410 | list_data *tmp; 411 | /* swap data pointers */ 412 | tmp = item_removed->info; 413 | item_removed->info = item_modified->info; 414 | item_modified->info = tmp; 415 | /* and insert item */ 416 | item_removed->next = item_modified->next; 417 | item_modified->next = item_removed; 418 | return item_removed; 419 | } 420 | 421 | /* Function: core_list_find 422 | Find an item in the list 423 | 424 | Operation: 425 | Find an item by idx (if not 0) or specific data value 426 | 427 | Parameters: 428 | list - list head 429 | info - idx or data to find 430 | 431 | Returns: 432 | Found item, or NULL if not found. 433 | */ 434 | list_head * 435 | core_list_find(list_head *list, list_data *info) 436 | { 437 | if (info->idx >= 0) 438 | { 439 | while (list && (list->info->idx != info->idx)) 440 | list = list->next; 441 | return list; 442 | } 443 | else 444 | { 445 | while (list && ((list->info->data16 & 0xff) != info->data16)) 446 | list = list->next; 447 | return list; 448 | } 449 | } 450 | /* Function: core_list_reverse 451 | Reverse a list 452 | 453 | Operation: 454 | Rearrange the pointers so the list is reversed. 455 | 456 | Parameters: 457 | list - list head 458 | info - idx or data to find 459 | 460 | Returns: 461 | Found item, or NULL if not found. 462 | */ 463 | 464 | list_head * 465 | core_list_reverse(list_head *list) 466 | { 467 | list_head *next = NULL, *tmp; 468 | while (list) 469 | { 470 | tmp = list->next; 471 | list->next = next; 472 | next = list; 473 | list = tmp; 474 | } 475 | return next; 476 | } 477 | /* Function: core_list_mergesort 478 | Sort the list in place without recursion. 479 | 480 | Description: 481 | Use mergesort, as for linked list this is a realistic solution. 482 | Also, since this is aimed at embedded, care was taken to use iterative 483 | rather then recursive algorithm. The sort can either return the list to 484 | original order (by idx) , or use the data item to invoke other other 485 | algorithms and change the order of the list. 486 | 487 | Parameters: 488 | list - list to be sorted. 489 | cmp - cmp function to use 490 | 491 | Returns: 492 | New head of the list. 493 | 494 | Note: 495 | We have a special header for the list that will always be first, 496 | but the algorithm could theoretically modify where the list starts. 497 | 498 | */ 499 | list_head * 500 | core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) 501 | { 502 | list_head *p, *q, *e, *tail; 503 | ee_s32 insize, nmerges, psize, qsize, i; 504 | 505 | insize = 1; 506 | 507 | while (1) 508 | { 509 | p = list; 510 | list = NULL; 511 | tail = NULL; 512 | 513 | nmerges = 0; /* count number of merges we do in this pass */ 514 | 515 | while (p) 516 | { 517 | nmerges++; /* there exists a merge to be done */ 518 | /* step `insize' places along from p */ 519 | q = p; 520 | psize = 0; 521 | for (i = 0; i < insize; i++) 522 | { 523 | psize++; 524 | q = q->next; 525 | if (!q) 526 | break; 527 | } 528 | 529 | /* if q hasn't fallen off end, we have two lists to merge */ 530 | qsize = insize; 531 | 532 | /* now we have two lists; merge them */ 533 | while (psize > 0 || (qsize > 0 && q)) 534 | { 535 | 536 | /* decide whether next element of merge comes from p or q */ 537 | if (psize == 0) 538 | { 539 | /* p is empty; e must come from q. */ 540 | e = q; 541 | q = q->next; 542 | qsize--; 543 | } 544 | else if (qsize == 0 || !q) 545 | { 546 | /* q is empty; e must come from p. */ 547 | e = p; 548 | p = p->next; 549 | psize--; 550 | } 551 | else if (cmp(p->info, q->info, res) <= 0) 552 | { 553 | /* First element of p is lower (or same); e must come from 554 | * p. */ 555 | e = p; 556 | p = p->next; 557 | psize--; 558 | } 559 | else 560 | { 561 | /* First element of q is lower; e must come from q. */ 562 | e = q; 563 | q = q->next; 564 | qsize--; 565 | } 566 | 567 | /* add the next element to the merged list */ 568 | if (tail) 569 | { 570 | tail->next = e; 571 | } 572 | else 573 | { 574 | list = e; 575 | } 576 | tail = e; 577 | } 578 | 579 | /* now p has stepped `insize' places along, and q has too */ 580 | p = q; 581 | } 582 | 583 | tail->next = NULL; 584 | 585 | /* If we have done only one merge, we're finished. */ 586 | if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ 587 | return list; 588 | 589 | /* Otherwise repeat, merging lists twice the size */ 590 | insize *= 2; 591 | } 592 | #if COMPILER_REQUIRES_SORT_RETURN 593 | return list; 594 | #endif 595 | } 596 | -------------------------------------------------------------------------------- /src/pipeline_3stage/design/decoder.v: -------------------------------------------------------------------------------- 1 | // 2 | // decoder 3 | // 4 | 5 | 6 | `include "define.vh" 7 | 8 | module decoder ( 9 | input wire [31:0] insn, 10 | output wire [4:0] srcreg1_num, 11 | output wire [4:0] srcreg2_num, 12 | output wire [4:0] dstreg_num, 13 | output wire [31:0] imm, 14 | output reg [5:0] alucode, 15 | output reg [1:0] aluop1_type, 16 | output reg [1:0] aluop2_type, 17 | output reg reg_we, 18 | output reg is_load, 19 | output reg is_store 20 | ); 21 | 22 | // internal signal 23 | wire [6:0] opcode; 24 | wire [2:0] funct3; 25 | wire [4:0] funct5; 26 | wire [4:0] rd; 27 | 28 | // op_type 29 | reg [2:0] op_type; 30 | reg dst_type; 31 | 32 | // opcode 33 | assign opcode = insn[6:0]; 34 | 35 | // funct 36 | assign funct3 = insn[14:12]; 37 | assign funct5 = insn[31:27]; 38 | 39 | // destination 40 | assign rd = insn[11:7]; 41 | 42 | // multiplexer 43 | assign srcreg1_num = (op_type == `TYPE_U || op_type == `TYPE_J) ? 5'd0 : insn[19:15]; 44 | assign srcreg2_num = (op_type == `TYPE_U || op_type == `TYPE_J || op_type == `TYPE_I) ? 5'd0 : insn[24:20]; 45 | assign dstreg_num = (dst_type == `REG_RD) ? rd : 5'd0; 46 | assign imm = (op_type == `TYPE_U) ? {insn[31:12], 12'd0} : 47 | (op_type == `TYPE_J) ? {{11{insn[31]}}, insn[31], insn[19:12], insn[20], insn[30:21], 1'd0} : 48 | (op_type == `TYPE_I) ? {{20{insn[31]}}, insn[31:20]} : 49 | (op_type == `TYPE_B) ? {{19{insn[31]}}, insn[31], insn[7], insn[30:25], insn[11:8], 1'd0} : 50 | (op_type == `TYPE_S) ? {{20{insn[31]}}, insn[31:25], insn[11:7]} : 32'd0; 51 | 52 | always @(*) begin 53 | case (opcode) 54 | `LUI: begin 55 | alucode = `ALU_LUI; 56 | reg_we = `ENABLE; 57 | is_load = `DISABLE; 58 | is_store = `DISABLE; 59 | aluop1_type = `OP_TYPE_NONE; 60 | aluop2_type = `OP_TYPE_IMM; 61 | op_type = `TYPE_U; 62 | dst_type = `REG_RD; 63 | end 64 | `AUIPC: begin 65 | alucode = `ALU_ADD; 66 | reg_we = `ENABLE; 67 | is_load = `DISABLE; 68 | is_store = `DISABLE; 69 | aluop1_type = `OP_TYPE_IMM; 70 | aluop2_type = `OP_TYPE_PC; 71 | op_type = `TYPE_U; 72 | dst_type = `REG_RD; 73 | end 74 | `JAL: begin 75 | alucode = `ALU_JAL; 76 | is_load = `DISABLE; 77 | is_store = `DISABLE; 78 | aluop1_type = `OP_TYPE_NONE; 79 | aluop2_type = `OP_TYPE_PC; 80 | op_type = `TYPE_J; 81 | dst_type = `REG_RD; 82 | case (dstreg_num) 83 | 5'b00000: begin 84 | reg_we = `DISABLE; 85 | end 86 | default: begin 87 | reg_we = `ENABLE; 88 | end 89 | endcase 90 | end 91 | `JALR: begin 92 | alucode = `ALU_JALR; 93 | reg_we = `ENABLE; 94 | is_load = `DISABLE; 95 | is_store = `DISABLE; 96 | aluop1_type = `OP_TYPE_REG; 97 | aluop2_type = `OP_TYPE_PC; 98 | op_type = `TYPE_I; 99 | dst_type = `REG_RD; 100 | case (dstreg_num) 101 | 5'b00000: begin 102 | reg_we = `DISABLE; 103 | end 104 | default: begin 105 | reg_we = `ENABLE; 106 | end 107 | endcase 108 | end 109 | `BRANCH: begin 110 | case (funct3) 111 | 3'b000: begin // BEQ 112 | alucode = `ALU_BEQ; 113 | reg_we = `DISABLE; 114 | is_load = `DISABLE; 115 | is_store = `DISABLE; 116 | aluop1_type = `OP_TYPE_REG; 117 | aluop2_type = `OP_TYPE_REG; 118 | op_type = `TYPE_B; 119 | dst_type = `REG_NONE; 120 | end 121 | 3'b001: begin // BNE 122 | alucode = `ALU_BNE; 123 | reg_we = `DISABLE; 124 | is_load = `DISABLE; 125 | is_store = `DISABLE; 126 | aluop1_type = `OP_TYPE_REG; 127 | aluop2_type = `OP_TYPE_REG; 128 | op_type = `TYPE_B; 129 | dst_type = `REG_NONE; 130 | end 131 | 3'b100: begin // BLT 132 | alucode = `ALU_BLT; 133 | reg_we = `DISABLE; 134 | is_load = `DISABLE; 135 | is_store = `DISABLE; 136 | aluop1_type = `OP_TYPE_REG; 137 | aluop2_type = `OP_TYPE_REG; 138 | op_type = `TYPE_B; 139 | dst_type = `REG_NONE; 140 | end 141 | 3'b101: begin // BGE 142 | alucode = `ALU_BGE; 143 | reg_we = `DISABLE; 144 | is_load = `DISABLE; 145 | is_store = `DISABLE; 146 | aluop1_type = `OP_TYPE_REG; 147 | aluop2_type = `OP_TYPE_REG; 148 | op_type = `TYPE_B; 149 | dst_type = `REG_NONE; 150 | end 151 | 3'b110: begin // BLTU 152 | alucode = `ALU_BLTU; 153 | reg_we = `DISABLE; 154 | is_load = `DISABLE; 155 | is_store = `DISABLE; 156 | aluop1_type = `OP_TYPE_REG; 157 | aluop2_type = `OP_TYPE_REG; 158 | op_type = `TYPE_B; 159 | dst_type = `REG_NONE; 160 | end 161 | 3'b111: begin // BGEU 162 | alucode = `ALU_BGEU; 163 | reg_we = `DISABLE; 164 | is_load = `DISABLE; 165 | is_store = `DISABLE; 166 | aluop1_type = `OP_TYPE_REG; 167 | aluop2_type = `OP_TYPE_REG; 168 | op_type = `TYPE_B; 169 | dst_type = `REG_NONE; 170 | end 171 | default: begin 172 | alucode = `ALU_NOP; 173 | reg_we = `DISABLE; 174 | is_load = `DISABLE; 175 | is_store = `DISABLE; 176 | aluop1_type = `OP_TYPE_NONE; 177 | aluop2_type = `OP_TYPE_NONE; 178 | op_type = `TYPE_NONE; 179 | dst_type = `REG_NONE; 180 | end 181 | endcase 182 | end 183 | `LOAD: begin 184 | case (funct3) 185 | 3'b000: begin // LB 186 | alucode = `ALU_LB; 187 | reg_we = `ENABLE; 188 | is_load = `ENABLE; 189 | is_store = `DISABLE; 190 | aluop1_type = `OP_TYPE_REG; 191 | aluop2_type = `OP_TYPE_IMM; 192 | op_type = `TYPE_I; 193 | dst_type = `REG_RD; 194 | end 195 | 3'b001: begin // LH 196 | alucode = `ALU_LH; 197 | reg_we = `ENABLE; 198 | is_load = `ENABLE; 199 | is_store = `DISABLE; 200 | aluop1_type = `OP_TYPE_REG; 201 | aluop2_type = `OP_TYPE_IMM; 202 | op_type = `TYPE_I; 203 | dst_type = `REG_RD; 204 | end 205 | 3'b010: begin // LW 206 | alucode = `ALU_LW; 207 | reg_we = `ENABLE; 208 | is_load = `ENABLE; 209 | is_store = `DISABLE; 210 | aluop1_type = `OP_TYPE_REG; 211 | aluop2_type = `OP_TYPE_IMM; 212 | op_type = `TYPE_I; 213 | dst_type = `REG_RD; 214 | end 215 | 3'b100: begin // LBU 216 | alucode = `ALU_LBU; 217 | reg_we = `ENABLE; 218 | is_load = `ENABLE; 219 | is_store = `DISABLE; 220 | aluop1_type = `OP_TYPE_REG; 221 | aluop2_type = `OP_TYPE_IMM; 222 | op_type = `TYPE_I; 223 | dst_type = `REG_RD; 224 | end 225 | 3'b101: begin // LHU 226 | alucode = `ALU_LHU; 227 | reg_we = `ENABLE; 228 | is_load = `ENABLE; 229 | is_store = `DISABLE; 230 | aluop1_type = `OP_TYPE_REG; 231 | aluop2_type = `OP_TYPE_IMM; 232 | op_type = `TYPE_I; 233 | dst_type = `REG_RD; 234 | end 235 | default: begin 236 | alucode = `ALU_NOP; 237 | reg_we = `DISABLE; 238 | is_load = `DISABLE; 239 | is_store = `DISABLE; 240 | aluop1_type = `OP_TYPE_NONE; 241 | aluop2_type = `OP_TYPE_NONE; 242 | op_type = `TYPE_NONE; 243 | dst_type = `REG_NONE; 244 | end 245 | endcase 246 | end 247 | `STORE: begin 248 | case (funct3) 249 | 3'b000: begin // SB 250 | alucode = `ALU_SB; 251 | reg_we = `DISABLE; 252 | is_load = `DISABLE; 253 | is_store = `ENABLE; 254 | aluop1_type = `OP_TYPE_REG; 255 | aluop2_type = `OP_TYPE_IMM; 256 | op_type = `TYPE_S; 257 | dst_type = `REG_NONE; 258 | end 259 | 3'b001: begin // SH 260 | alucode = `ALU_SH; 261 | reg_we = `DISABLE; 262 | is_load = `DISABLE; 263 | is_store = `ENABLE; 264 | aluop1_type = `OP_TYPE_REG; 265 | aluop2_type = `OP_TYPE_IMM; 266 | op_type = `TYPE_S; 267 | dst_type = `REG_NONE; 268 | end 269 | 3'b010: begin // SW 270 | alucode = `ALU_SW; 271 | reg_we = `DISABLE; 272 | is_load = `DISABLE; 273 | is_store = `ENABLE; 274 | aluop1_type = `OP_TYPE_REG; 275 | aluop2_type = `OP_TYPE_IMM; 276 | op_type = `TYPE_S; 277 | dst_type = `REG_NONE; 278 | end 279 | default: begin 280 | alucode = `ALU_NOP; 281 | reg_we = `DISABLE; 282 | is_load = `DISABLE; 283 | is_store = `DISABLE; 284 | aluop1_type = `OP_TYPE_NONE; 285 | aluop2_type = `OP_TYPE_NONE; 286 | op_type = `TYPE_NONE; 287 | dst_type = `REG_NONE; 288 | end 289 | endcase 290 | end 291 | `OPIMM: begin 292 | case (funct3) 293 | 3'b000: begin // ADDI 294 | alucode = `ALU_ADD; 295 | reg_we = `ENABLE; 296 | is_load = `DISABLE; 297 | is_store = `DISABLE; 298 | aluop1_type = `OP_TYPE_REG; 299 | aluop2_type = `OP_TYPE_IMM; 300 | op_type = `TYPE_I; 301 | dst_type = `REG_RD; 302 | end 303 | 3'b010: begin // SLTI 304 | alucode = `ALU_SLT; 305 | reg_we = `ENABLE; 306 | is_load = `DISABLE; 307 | is_store = `DISABLE; 308 | aluop1_type = `OP_TYPE_REG; 309 | aluop2_type = `OP_TYPE_IMM; 310 | op_type = `TYPE_I; 311 | dst_type = `REG_RD; 312 | end 313 | 3'b011: begin // SLTIU 314 | alucode = `ALU_SLTU; 315 | reg_we = `ENABLE; 316 | is_load = `DISABLE; 317 | is_store = `DISABLE; 318 | aluop1_type = `OP_TYPE_REG; 319 | aluop2_type = `OP_TYPE_IMM; 320 | op_type = `TYPE_I; 321 | dst_type = `REG_RD; 322 | end 323 | 3'b100: begin // XORI 324 | alucode = `ALU_XOR; 325 | reg_we = `ENABLE; 326 | is_load = `DISABLE; 327 | is_store = `DISABLE; 328 | aluop1_type = `OP_TYPE_REG; 329 | aluop2_type = `OP_TYPE_IMM; 330 | op_type = `TYPE_I; 331 | dst_type = `REG_RD; 332 | end 333 | 3'b110: begin // ORI 334 | alucode = `ALU_OR; 335 | reg_we = `ENABLE; 336 | is_load = `DISABLE; 337 | is_store = `DISABLE; 338 | aluop1_type = `OP_TYPE_REG; 339 | aluop2_type = `OP_TYPE_IMM; 340 | op_type = `TYPE_I; 341 | dst_type = `REG_RD; 342 | end 343 | 3'b111: begin // ANDI 344 | alucode = `ALU_AND; 345 | reg_we = `ENABLE; 346 | is_load = `DISABLE; 347 | is_store = `DISABLE; 348 | aluop1_type = `OP_TYPE_REG; 349 | aluop2_type = `OP_TYPE_IMM; 350 | op_type = `TYPE_I; 351 | dst_type = `REG_RD; 352 | end 353 | 3'b001: begin // SLLI 354 | alucode = `ALU_SLL; 355 | reg_we = `ENABLE; 356 | is_load = `DISABLE; 357 | is_store = `DISABLE; 358 | aluop1_type = `OP_TYPE_REG; 359 | aluop2_type = `OP_TYPE_IMM; 360 | op_type = `TYPE_I; 361 | dst_type = `REG_RD; 362 | end 363 | 3'b101: begin 364 | case (funct5[3]) 365 | 1'b0: begin // SRLI 366 | alucode = `ALU_SRL; 367 | reg_we = `ENABLE; 368 | is_load = `DISABLE; 369 | is_store = `DISABLE; 370 | aluop1_type = `OP_TYPE_REG; 371 | aluop2_type = `OP_TYPE_IMM; 372 | op_type = `TYPE_I; 373 | dst_type = `REG_RD; 374 | end 375 | 1'b1: begin // SRAI 376 | alucode = `ALU_SRA; 377 | reg_we = `ENABLE; 378 | is_load = `DISABLE; 379 | is_store = `DISABLE; 380 | aluop1_type = `OP_TYPE_REG; 381 | aluop2_type = `OP_TYPE_IMM; 382 | op_type = `TYPE_I; 383 | dst_type = `REG_RD; 384 | end 385 | endcase 386 | end 387 | endcase 388 | end 389 | `OP: begin 390 | case (funct3) 391 | 3'b000: begin 392 | case (funct5[3]) 393 | 1'b0: begin // ADD 394 | alucode = `ALU_ADD; 395 | reg_we = `ENABLE; 396 | is_load = `DISABLE; 397 | is_store = `DISABLE; 398 | aluop1_type = `OP_TYPE_REG; 399 | aluop2_type = `OP_TYPE_REG; 400 | op_type = `TYPE_R; 401 | dst_type = `REG_RD; 402 | end 403 | 1'b1: begin // SUB 404 | alucode = `ALU_SUB; 405 | reg_we = `ENABLE; 406 | is_load = `DISABLE; 407 | is_store = `DISABLE; 408 | aluop1_type = `OP_TYPE_REG; 409 | aluop2_type = `OP_TYPE_REG; 410 | op_type = `TYPE_R; 411 | dst_type = `REG_RD; 412 | end 413 | endcase 414 | end 415 | 3'b001: begin // SLL 416 | alucode = `ALU_SLL; 417 | reg_we = `ENABLE; 418 | is_load = `DISABLE; 419 | is_store = `DISABLE; 420 | aluop1_type = `OP_TYPE_REG; 421 | aluop2_type = `OP_TYPE_REG; 422 | op_type = `TYPE_R; 423 | dst_type = `REG_RD; 424 | end 425 | 3'b010: begin // SLT 426 | alucode = `ALU_SLT; 427 | reg_we = `ENABLE; 428 | is_load = `DISABLE; 429 | is_store = `DISABLE; 430 | aluop1_type = `OP_TYPE_REG; 431 | aluop2_type = `OP_TYPE_REG; 432 | op_type = `TYPE_R; 433 | dst_type = `REG_RD; 434 | end 435 | 3'b011: begin // SLTU 436 | alucode = `ALU_SLTU; 437 | reg_we = `ENABLE; 438 | is_load = `DISABLE; 439 | is_store = `DISABLE; 440 | aluop1_type = `OP_TYPE_REG; 441 | aluop2_type = `OP_TYPE_REG; 442 | op_type = `TYPE_R; 443 | dst_type = `REG_RD; 444 | end 445 | 3'b100: begin // XOR 446 | alucode = `ALU_XOR; 447 | reg_we = `ENABLE; 448 | is_load = `DISABLE; 449 | is_store = `DISABLE; 450 | aluop1_type = `OP_TYPE_REG; 451 | aluop2_type = `OP_TYPE_REG; 452 | op_type = `TYPE_R; 453 | dst_type = `REG_RD; 454 | end 455 | 3'b101: begin 456 | case (funct5[3]) 457 | 1'b0: begin // SRL 458 | alucode = `ALU_SRL; 459 | reg_we = `ENABLE; 460 | is_load = `DISABLE; 461 | is_store = `DISABLE; 462 | aluop1_type = `OP_TYPE_REG; 463 | aluop2_type = `OP_TYPE_REG; 464 | op_type = `TYPE_R; 465 | dst_type = `REG_RD; 466 | end 467 | 1'b1: begin // SRA 468 | alucode = `ALU_SRA; 469 | reg_we = `ENABLE; 470 | is_load = `DISABLE; 471 | is_store = `DISABLE; 472 | aluop1_type = `OP_TYPE_REG; 473 | aluop2_type = `OP_TYPE_REG; 474 | op_type = `TYPE_R; 475 | dst_type = `REG_RD; 476 | end 477 | endcase 478 | end 479 | 3'b110: begin // OR 480 | alucode = `ALU_OR; 481 | reg_we = `ENABLE; 482 | is_load = `DISABLE; 483 | is_store = `DISABLE; 484 | aluop1_type = `OP_TYPE_REG; 485 | aluop2_type = `OP_TYPE_REG; 486 | op_type = `TYPE_R; 487 | dst_type = `REG_RD; 488 | end 489 | 3'b111: begin // AND 490 | alucode = `ALU_AND; 491 | reg_we = `ENABLE; 492 | is_load = `DISABLE; 493 | is_store = `DISABLE; 494 | aluop1_type = `OP_TYPE_REG; 495 | aluop2_type = `OP_TYPE_REG; 496 | op_type = `TYPE_R; 497 | dst_type = `REG_RD; 498 | end 499 | endcase 500 | end 501 | default: begin 502 | alucode = `ALU_NOP; 503 | reg_we = `DISABLE; 504 | is_load = `DISABLE; 505 | is_store = `DISABLE; 506 | aluop1_type = `OP_TYPE_NONE; 507 | aluop2_type = `OP_TYPE_NONE; 508 | op_type = `TYPE_NONE; 509 | dst_type = `REG_NONE; 510 | end 511 | endcase 512 | end 513 | 514 | endmodule 515 | --------------------------------------------------------------------------------