secs_ret time_in_secs(CORE_TICKS ticks) { /* Perform 64-bit division, then cast result to secs_ret (ee_u32). * Since seconds is a small number, 32-bit result is sufficient. */ ee_u64 secs_64 = ticks / (ee_u64)EE_TICKS_PER_SEC; secs_ret retval = (secs_ret)secs_64; return retval; }
staticinline ee_u64 read_mcycle64(void) { ee_u32 hi1, lo, hi2; /* Atomic read sequence: read high, low, high again. * If high changed, low overflowed, so retry. */ do { __asm__ volatile("csrr %0, mcycleh" : "=r"(hi1)); __asm__ volatile("csrr %0, mcycle" : "=r"(lo)); __asm__ volatile("csrr %0, mcycleh" : "=r"(hi2)); } while (hi1 != hi2); return ((ee_u64)hi1 << 32) | (ee_u64)lo; }
关键的计算校验值部分在282行开始的地方:
1 2 3 4 5 6 7
stop_time(); total_time = get_time(); /* get a function of the input to report */ seedcrc = crc16(results[0].seed1, seedcrc); seedcrc = crc16(results[0].seed2, seedcrc); seedcrc = crc16(results[0].seed3, seedcrc); seedcrc = crc16(results[0].size, seedcrc);
if (total_errors > 0) { ee_printf("Errors detected\n"); exit_sim(2); } if (total_errors < 0) { ee_printf( "Cannot validate operation for these seed values, please compare " "with results on a known platform.\n"); exit_sim(2); }
#if (MEM_METHOD == MEM_MALLOC) for (i = 0; i < MULTITHREAD; i++) portable_free(results[i].memblock[0]); #endif /* And last call any target specific code for finalizing */ portable_fini(&(results[0].port)); exit_sim(1); return MAIN_RETURN_VAL;
至此,CoreMark库修改完毕。
编译与链接相关
start.S
我们编译需要start.S作为link.ld的入口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
.section .text.init .globl _start _start: la sp, _stack_top
# 清 BSS(如果你没定义 __bss_start/__bss_end 就先不做) # la t0, __bss_start # la t1, __bss_end # ...
# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Original Author: Shay Gal-on
#File : core_portme.mak
# Flag : OUTFLAG # Use this flag to define how to to get an executable (e.g -o) OUTFLAG= -o # Flag : CC # Use this flag to define compiler to use CC = gcc # Flag : LD # Use this flag to define compiler to use LD = gld # Flag : AS # Use this flag to define compiler to use AS = gas # Flag : CFLAGS # Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags" PORT_CFLAGS = -O0 -g FLAGS_STR = "$(PORT_CFLAGS)$(XCFLAGS)$(XLFLAGS)$(LFLAGS_END)" CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\" #Flag : LFLAGS_END # Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts). # Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt. SEPARATE_COMPILE=1 # Flag : SEPARATE_COMPILE # You must also define below how to create an object file, and how to link. OBJOUT = -o LFLAGS = ASFLAGS = OFLAG = -o COUT = -c LFLAGS_END = # Flag : PORT_SRCS # Port specific source files can be added here # You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler! PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c vpath %.c $(PORT_DIR) vpath %.s $(PORT_DIR) # Flag : LOAD # For a simple port, we assume self hosted compile and run, no load needed. # Flag : RUN # For a simple port, we assume self hosted compile and run, simple invocation of the executable LOAD = echo "Please set LOAD to the process of loading the executable to the flash" RUN = echo "Please set LOAD to the process of running the executable (e.g. via jtag, or board reset)" OEXT = .o EXE = .bin $(OPATH)$(PORT_DIR)/%$(OEXT) : %.c $(CC)$(CFLAGS)$(XCFLAGS)$(COUT)$<$(OBJOUT)$@ $(OPATH)%$(OEXT) : %.c $(CC)$(CFLAGS)$(XCFLAGS)$(COUT)$<$(OBJOUT)$@ $(OPATH)$(PORT_DIR)/%$(OEXT) : %.s $(AS)$(ASFLAGS)$<$(OBJOUT)$@ # Target : port_pre% and port_post% # For the purpose of this simple port, no pre or post steps needed. .PHONY : port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload port_pre% port_post% : # FLAG : OPATH # Path to the output folder. Default - current folder. OPATH = ./ MKDIR = mkdir -p
always_ff @(posedge clk) begin if (u_CPU_TOP.dram_we_MEM && u_CPU_TOP.alu_result_MEM == TOHOST_ADDR) begin // ✅ 读取要写入 tohost 的数据 logic [31:0] tohost_data; tohost_data = u_CPU_TOP.rf_rd2_MEM;
// 退出码判断 if (tohost_data == 32'd1) begin $display("%10t| [PASS] | Finished ", $time); $finish; end else if (tohost_data == 32'd2) begin $display("%10t| [FAIL] | Finished ", $time); $finish; end else begin // 普通字符输出 $write("%c", tohost_data[7:0]); $fflush(); end end end
// 复位和测试控制 initial begin // 波形文件设置 integer dumpwave; if ($value$plusargs("DUMPWAVE=%d", dumpwave)) begin if (dumpwave == 1) begin `ifdef VCD_FILEPATH $dumpfile({"../../", `VCD_FILEPATH}); `else $dumpfile("wave.vcd"); `endif $dumpvars; end end
// 初始化信号 rst_n = 0; // 复位 CPU #5; // 保持复位 25ns rst_n = 1; end
string testcase; initial begin if ($value$plusargs("TESTCASE=%s", testcase)) begin end end
// 检测异常 always_ff @(posedge clk) begin if (u_CPU_TOP.exception_valid) begin $display("%10t| [EXCEPTION] PC=0x%08h, cause=%d, tval=0x%08h", $time, u_CPU_TOP.exception_pc, u_CPU_TOP.exception_cause, u_CPU_TOP.exception_tval); end end
// 超时保护 initial begin #100000000; // 1ms 超时 $display("%10t| [EROR] | TimeOut! ", $time); $finish; end