benchmarks initial commit
authorYunsup Lee <yunsup@cs.berkeley.edu>
Tue, 30 Apr 2013 01:44:21 +0000 (18:44 -0700)
committerYunsup Lee <yunsup@cs.berkeley.edu>
Tue, 30 Apr 2013 01:44:21 +0000 (18:44 -0700)
71 files changed:
benchmarks/Makefile [new file with mode: 0644]
benchmarks/common/crt-mt.S [new file with mode: 0644]
benchmarks/common/crt.S [new file with mode: 0644]
benchmarks/common/pcr.h [new file with mode: 0644]
benchmarks/common/syscalls.S [new file with mode: 0644]
benchmarks/common/syscalls.c [new file with mode: 0644]
benchmarks/common/test-mt.ld [new file with mode: 0644]
benchmarks/common/test.ld [new file with mode: 0644]
benchmarks/common/util.h [new file with mode: 0644]
benchmarks/dgemm/bmark.mk [new file with mode: 0644]
benchmarks/dgemm/dataset1.h [new file with mode: 0644]
benchmarks/dgemm/dgemm_gendata.scala [new file with mode: 0644]
benchmarks/dgemm/dgemm_main.c [new file with mode: 0644]
benchmarks/dhrystone/bmark.mk [new file with mode: 0644]
benchmarks/dhrystone/dhrystone.c [new file with mode: 0644]
benchmarks/dhrystone/dhrystone.h [new file with mode: 0644]
benchmarks/dhrystone/dhrystone_main.c [new file with mode: 0644]
benchmarks/median/bmark.mk [new file with mode: 0644]
benchmarks/median/dataset1.h [new file with mode: 0644]
benchmarks/median/median.c [new file with mode: 0644]
benchmarks/median/median.h [new file with mode: 0644]
benchmarks/median/median_gendata.pl [new file with mode: 0755]
benchmarks/median/median_main.c [new file with mode: 0644]
benchmarks/mt-matmul/bmark.mk [new file with mode: 0644]
benchmarks/mt-matmul/dataset.h [new file with mode: 0644]
benchmarks/mt-matmul/matmul_gendata.pl [new file with mode: 0755]
benchmarks/mt-matmul/mt-matmul.c [new file with mode: 0644]
benchmarks/mt-vvadd/bmark.mk [new file with mode: 0644]
benchmarks/mt-vvadd/dataset.h [new file with mode: 0644]
benchmarks/mt-vvadd/mt-vvadd.c [new file with mode: 0644]
benchmarks/mt-vvadd/vvadd_gendata.pl [new file with mode: 0755]
benchmarks/multiply/bmark.mk [new file with mode: 0644]
benchmarks/multiply/dataset1.h [new file with mode: 0644]
benchmarks/multiply/multiply.c [new file with mode: 0644]
benchmarks/multiply/multiply.h [new file with mode: 0644]
benchmarks/multiply/multiply_gendata.pl [new file with mode: 0755]
benchmarks/multiply/multiply_main.c [new file with mode: 0644]
benchmarks/qsort/bmark.mk [new file with mode: 0644]
benchmarks/qsort/dataset1.h [new file with mode: 0644]
benchmarks/qsort/qsort_gendata.pl [new file with mode: 0755]
benchmarks/qsort/qsort_main.c [new file with mode: 0644]
benchmarks/readme.txt [new file with mode: 0644]
benchmarks/spmv/bmark.mk [new file with mode: 0644]
benchmarks/spmv/dataset1.h [new file with mode: 0644]
benchmarks/spmv/spmv_gendata.scala [new file with mode: 0644]
benchmarks/spmv/spmv_main.c [new file with mode: 0644]
benchmarks/towers/bmark.mk [new file with mode: 0644]
benchmarks/towers/towers_main.c [new file with mode: 0644]
benchmarks/vec-cmplxmult/bmark.mk [new file with mode: 0644]
benchmarks/vec-cmplxmult/cmplxmult_gendata.pl [new file with mode: 0755]
benchmarks/vec-cmplxmult/dataset.h [new file with mode: 0644]
benchmarks/vec-cmplxmult/dataset_test.h [new file with mode: 0644]
benchmarks/vec-cmplxmult/vec_cmplxmult_asm.S [new file with mode: 0644]
benchmarks/vec-cmplxmult/vec_cmplxmult_main.c [new file with mode: 0644]
benchmarks/vec-matmul/bmark.mk [new file with mode: 0644]
benchmarks/vec-matmul/dataset.h [new file with mode: 0644]
benchmarks/vec-matmul/dataset_test.h [new file with mode: 0644]
benchmarks/vec-matmul/matmul_gendata.pl [new file with mode: 0755]
benchmarks/vec-matmul/vec_matmul_asm.S [new file with mode: 0644]
benchmarks/vec-matmul/vec_matmul_main.c [new file with mode: 0644]
benchmarks/vec-vvadd/bmark.mk [new file with mode: 0644]
benchmarks/vec-vvadd/dataset.h [new file with mode: 0644]
benchmarks/vec-vvadd/dataset_test.h [new file with mode: 0644]
benchmarks/vec-vvadd/vec_vvadd_asm.S [new file with mode: 0644]
benchmarks/vec-vvadd/vec_vvadd_main.c [new file with mode: 0644]
benchmarks/vec-vvadd/vvadd_gendata.pl [new file with mode: 0755]
benchmarks/vvadd/bmark.mk [new file with mode: 0644]
benchmarks/vvadd/dataset1-large.h [new file with mode: 0644]
benchmarks/vvadd/dataset1.h [new file with mode: 0644]
benchmarks/vvadd/vvadd_gendata.pl [new file with mode: 0755]
benchmarks/vvadd/vvadd_main.c [new file with mode: 0644]

diff --git a/benchmarks/Makefile b/benchmarks/Makefile
new file mode 100644 (file)
index 0000000..a0ce377
--- /dev/null
@@ -0,0 +1,144 @@
+#=======================================================================
+# UCB VLSI FLOW: Makefile for riscv-bmarks
+#-----------------------------------------------------------------------
+# Yunsup Lee (yunsup@cs.berkeley.edu)
+#
+
+default: all
+
+bmarkdir = .
+
+instname = riscv-bmarks
+instbasedir = $(UCB_VLSI_HOME)/install
+
+#--------------------------------------------------------------------
+# Sources
+#--------------------------------------------------------------------
+
+bmarks = \
+       median \
+       qsort \
+       towers \
+       vvadd \
+       multiply \
+       dgemm \
+       dhrystone \
+       spmv \
+       vec-vvadd \
+       vec-cmplxmult \
+       vec-matmul \
+       mt-vvadd \
+       mt-matmul \
+
+bmarks_host = \
+       median \
+       qsort \
+       towers \
+       vvadd \
+       multiply \
+       dgemm \
+       spmv \
+       vec-vvadd \
+       vec-cmplxmult \
+       vec-matmul \
+
+#--------------------------------------------------------------------
+# Build rules
+#--------------------------------------------------------------------
+
+HOST_OPTS = -std=gnu99 -DPREALLOCATE=0 -DHOST_DEBUG=1
+HOST_COMP = gcc $(HOST_OPTS)
+
+RISCV_GCC = riscv-gcc
+RISCV_GCC_OPTS = -std=gnu99 -DSET_STATS -O2 -nostdlib -nostartfiles -ffast-math
+RISCV_LINK = riscv-gcc -T $(bmarkdir)/common/test.ld
+RISCV_LINK_MT = riscv-gcc -T $(bmarkdir)/common/test-mt.ld
+RISCV_LINK_OPTS = -lc
+RISCV_LINK_SYSCALL = $(bmarkdir)/common/syscalls.c -lc
+RISCV_OBJDUMP = riscv-objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.data
+RISCV_SIM = riscv-isa-run
+
+VPATH += $(addprefix $(bmarkdir)/, $(bmarks))
+VPATH += $(bmarkdir)/common
+
+incs  += -I. -I./common $(addprefix -I$(bmarkdir)/, $(bmarks))
+objs  :=
+
+include $(patsubst %, $(bmarkdir)/%/bmark.mk, $(bmarks))
+
+#------------------------------------------------------------
+# Build and run benchmarks on riscv simulator
+
+bmarks_riscv_bin  = $(addsuffix .riscv,  $(bmarks))
+bmarks_riscv_dump = $(addsuffix .riscv.dump, $(bmarks))
+bmarks_riscv_hex = $(addsuffix .riscv.hex, $(bmarks))
+bmarks_riscv_out  = $(addsuffix .riscv.out,  $(bmarks))
+
+bmarks_defs   = -DPREALLOCATE=1 -DHOST_DEBUG=0
+bmarks_cycles = 80000
+
+%.hex: %
+       elf2hex 16 32768 $< > $@
+
+$(bmarks_riscv_dump): %.riscv.dump: %.riscv
+       $(RISCV_OBJDUMP) $< > $@
+
+$(bmarks_riscv_out): %.riscv.out: %.riscv
+       $(RISCV_SIM) $< > $@
+
+%.o: %.c
+       $(RISCV_GCC) $(RISCV_GCC_OPTS) $(bmarks_defs) \
+                    -c $(incs) $< -o $@
+
+%.o: %.S
+       $(RISCV_GCC) $(RISCV_GCC_OPTS) $(bmarks_defs) \
+                    -c $(incs) $< -o $@
+
+riscv: $(bmarks_riscv_dump) $(bmarks_riscv_hex)
+run-riscv: $(bmarks_riscv_out)
+       echo; perl -ne 'print "  [$$1] $$ARGV \t$$2\n" if /\*{3}(.{8})\*{3}(.*)/' \
+              $(bmarks_riscv_out); echo;
+
+junk += $(bmarks_riscv_bin) $(bmarks_riscv_dump) $(bmarks_riscv_hex) $(bmarks_riscv_out)
+
+#------------------------------------------------------------
+# Build and run benchmarks on host machine
+
+bmarks_host_bin = $(addsuffix .host, $(bmarks_host))
+bmarks_host_out = $(addsuffix .host.out, $(bmarks_host))
+
+$(bmarks_host_out): %.host.out: %.host
+       ./$< > $@
+
+host: $(bmarks_host_bin)
+run-host: $(bmarks_host_out)
+       echo; perl -ne 'print "  [$$1] $$ARGV \t$$2\n" if /\*{3}(.{8})\*{3}(.*)/' \
+              $(bmarks_host_out); echo;
+
+junk += $(bmarks_host_bin) $(bmarks_host_out)
+
+#------------------------------------------------------------
+# Default
+
+all: riscv
+
+#------------------------------------------------------------
+# Install
+
+date_suffix = $(shell date +%Y-%m-%d_%H-%M)
+install_dir = $(instbasedir)/$(instname)-$(date_suffix)
+latest_install = $(shell ls -1 -d $(instbasedir)/$(instname)* | tail -n 1)
+
+install:
+       mkdir $(install_dir)
+       cp -r $(bmarks_riscv_bin) $(bmarks_riscv_dump) $(install_dir)
+
+install-link:
+       rm -rf $(instbasedir)/$(instname)
+       ln -s $(latest_install) $(instbasedir)/$(instname)
+
+#------------------------------------------------------------
+# Clean up
+
+clean:
+       rm -rf $(objs) $(junk)
diff --git a/benchmarks/common/crt-mt.S b/benchmarks/common/crt-mt.S
new file mode 100644 (file)
index 0000000..283b3bf
--- /dev/null
@@ -0,0 +1,116 @@
+  .data
+  .globl _heapend
+  .globl environ
+_heapend:
+  .word 0
+environ:
+  .word 0
+
+  .text
+  .globl _start
+
+_start:
+  li  x1, 0
+  li  x2, 0
+  li  x3, 0
+  li  x4, 0
+  li  x5, 0
+  li  x6, 0
+  li  x7, 0
+  li  x8, 0
+  li  x9, 0
+  li  x10,0
+  li  x11,0
+  li  x12,0
+  li  x13,0
+  li  x14,0
+  li  x15,0
+  li  x16,0
+  li  x17,0
+  li  x18,0
+  li  x19,0
+  li  x20,0
+  li  x21,0
+  li  x22,0
+  li  x23,0
+  li  x24,0
+  li  x25,0
+  li  x26,0
+  li  x27,0
+  li  x28,0
+  li  x29,0
+  li  x30,0
+  li  x31,0
+
+  # enable fp
+  mfpcr  x1,cr0
+  ori  x1,x1,0x2
+  mtpcr  x1,cr0
+
+  # enable vec
+  mfpcr  x1,cr0
+  ori  x1,x1,0x4
+  mtpcr  x1,cr0
+
+  ## if that didn't stick, we don't have an FPU, so don't initialize it
+  mfpcr x1,cr0
+  andi x1,x1,0x2
+  beqz x1,1f
+
+  mtfsr   x0
+  mxtf.s  f0, x0
+  mxtf.s  f1, x0
+  mxtf.s  f2, x0
+  mxtf.s  f3, x0
+  mxtf.s  f4, x0
+  mxtf.s  f5, x0
+  mxtf.s  f6, x0
+  mxtf.s  f7, x0
+  mxtf.s  f8, x0
+  mxtf.s  f9, x0
+  mxtf.s  f10,x0
+  mxtf.s  f11,x0
+  mxtf.s  f12,x0
+  mxtf.s  f13,x0
+  mxtf.s  f14,x0
+  mxtf.s  f15,x0
+  mxtf.s  f16,x0
+  mxtf.s  f17,x0
+  mxtf.s  f18,x0
+  mxtf.s  f19,x0
+  mxtf.s  f20,x0
+  mxtf.s  f21,x0
+  mxtf.s  f22,x0
+  mxtf.s  f23,x0
+  mxtf.s  f24,x0
+  mxtf.s  f25,x0
+  mxtf.s  f26,x0
+  mxtf.s  f27,x0
+  mxtf.s  f28,x0
+  mxtf.s  f29,x0
+  mxtf.s  f30,x0
+  mxtf.s  f31,x0
+1:
+
+  # get core id and number of cores
+  mfpcr a0,cr10
+  lw a1, 4(zero)
+
+  slli a2, a0, 13
+  la sp, stacktop
+  sub sp, sp, a2
+
+  la tp, tlstop
+  sub tp, tp, a2
+
+  jal thread_entry
+
+  .bss
+  .globl stacktop
+  .globl tlstop
+
+  .align 4
+  .skip 32768
+stacktop:
+  .skip 65536
+tlstop:
diff --git a/benchmarks/common/crt.S b/benchmarks/common/crt.S
new file mode 100644 (file)
index 0000000..d153210
--- /dev/null
@@ -0,0 +1,108 @@
+  .data
+  .globl _heapend
+  .globl environ
+_heapend:
+  .word 0
+environ:
+  .word 0
+
+  .text
+  .globl _start
+
+_start:
+  li  x1, 0
+  li  x2, 0
+  li  x3, 0
+  li  x4, 0
+  li  x5, 0
+  li  x6, 0
+  li  x7, 0
+  li  x8, 0
+  li  x9, 0
+  li  x10,0
+  li  x11,0
+  li  x12,0
+  li  x13,0
+  li  x14,0
+  li  x15,0
+  li  x16,0
+  li  x17,0
+  li  x18,0
+  li  x19,0
+  li  x20,0
+  li  x21,0
+  li  x22,0
+  li  x23,0
+  li  x24,0
+  li  x25,0
+  li  x26,0
+  li  x27,0
+  li  x28,0
+  li  x29,0
+  li  x30,0
+  li  x31,0
+
+  # enable fp
+  mfpcr  x1,cr0
+  ori  x1,x1,0x2
+  mtpcr  x1,cr0
+
+  # enable vec
+  mfpcr  x1,cr0
+  ori  x1,x1,0x4
+  mtpcr  x1,cr0
+
+  ## if that didn't stick, we don't have an FPU, so don't initialize it
+  mfpcr x1,cr0
+  andi x1,x1,0x2
+  beqz x1,1f
+
+  mtfsr   x0
+  mxtf.s  f0, x0
+  mxtf.s  f1, x0
+  mxtf.s  f2, x0
+  mxtf.s  f3, x0
+  mxtf.s  f4, x0
+  mxtf.s  f5, x0
+  mxtf.s  f6, x0
+  mxtf.s  f7, x0
+  mxtf.s  f8, x0
+  mxtf.s  f9, x0
+  mxtf.s  f10,x0
+  mxtf.s  f11,x0
+  mxtf.s  f12,x0
+  mxtf.s  f13,x0
+  mxtf.s  f14,x0
+  mxtf.s  f15,x0
+  mxtf.s  f16,x0
+  mxtf.s  f17,x0
+  mxtf.s  f18,x0
+  mxtf.s  f19,x0
+  mxtf.s  f20,x0
+  mxtf.s  f21,x0
+  mxtf.s  f22,x0
+  mxtf.s  f23,x0
+  mxtf.s  f24,x0
+  mxtf.s  f25,x0
+  mxtf.s  f26,x0
+  mxtf.s  f27,x0
+  mxtf.s  f28,x0
+  mxtf.s  f29,x0
+  mxtf.s  f30,x0
+  mxtf.s  f31,x0
+1:
+
+  # only allow core 0 to proceed
+1:mfpcr a0, cr10
+  bnez a0, 1b
+
+  la  sp,stacktop
+  jal main
+1:b 1b
+
+  .bss
+  .globl stacktop
+
+  .align 4
+  .skip 131072
+stacktop:
diff --git a/benchmarks/common/pcr.h b/benchmarks/common/pcr.h
new file mode 100644 (file)
index 0000000..7659a97
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef _RISCV_PCR_H
+#define _RISCV_PCR_H
+
+#define SR_ET    0x00000001
+#define SR_EF    0x00000002
+#define SR_EV    0x00000004
+#define SR_EC    0x00000008
+#define SR_PS    0x00000010
+#define SR_S     0x00000020
+#define SR_U64   0x00000040
+#define SR_S64   0x00000080
+#define SR_VM    0x00000100
+#define SR_IM    0x00FF0000
+#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM)
+#define SR_IM_SHIFT 16
+
+#define PCR_SR       0
+#define PCR_EPC      1
+#define PCR_BADVADDR 2
+#define PCR_EVEC     3
+#define PCR_COUNT    4
+#define PCR_COMPARE  5
+#define PCR_CAUSE    6
+#define PCR_PTBR     7
+#define PCR_SEND_IPI 8
+#define PCR_CLR_IPI  9
+#define PCR_COREID   10
+#define PCR_IMPL     11
+#define PCR_K0       12
+#define PCR_K1       13
+#define PCR_VECBANK  18
+#define PCR_VECCFG   19
+#define PCR_RESET    29
+#define PCR_TOHOST   30
+#define PCR_FROMHOST 31
+
+#define IRQ_IPI   5
+#define IRQ_TIMER 7
+
+#define CAUSE_MISALIGNED_FETCH 0
+#define CAUSE_FAULT_FETCH 1
+#define CAUSE_ILLEGAL_INSTRUCTION 2
+#define CAUSE_PRIVILEGED_INSTRUCTION 3
+#define CAUSE_FP_DISABLED 4
+#define CAUSE_SYSCALL 6
+#define CAUSE_BREAKPOINT 7
+#define CAUSE_MISALIGNED_LOAD 8
+#define CAUSE_MISALIGNED_STORE 9
+#define CAUSE_FAULT_LOAD 10
+#define CAUSE_FAULT_STORE 11
+#define CAUSE_VECTOR_DISABLED 12
+#define CAUSE_VECTOR_BANK 13
+
+#define CAUSE_VECTOR_MISALIGNED_FETCH 24
+#define CAUSE_VECTOR_FAULT_FETCH 25
+#define CAUSE_VECTOR_ILLEGAL_INSTRUCTION 26
+#define CAUSE_VECTOR_ILLEGAL_COMMAND 27
+#define CAUSE_VECTOR_MISALIGNED_LOAD 28
+#define CAUSE_VECTOR_MISALIGNED_STORE 29
+#define CAUSE_VECTOR_FAULT_LOAD 30
+#define CAUSE_VECTOR_FAULT_STORE 31
+
+#ifdef __riscv
+
+#define ASM_CR(r)   _ASM_CR(r)
+#define _ASM_CR(r)  cr##r
+
+#ifndef __ASSEMBLER__
+
+#define mtpcr(reg,val) ({ long __tmp = (long)(val), __tmp2; \
+          asm volatile ("mtpcr %0,%1,cr%2" : "=r"(__tmp2) : "r"(__tmp),"i"(reg)); \
+          __tmp2; })
+
+#define mfpcr(reg) ({ long __tmp; \
+          asm volatile ("mfpcr %0,cr%1" : "=r"(__tmp) : "i"(reg)); \
+          __tmp; })
+
+#define setpcr(reg,val) ({ long __tmp; \
+          asm volatile ("setpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \
+          __tmp; })
+
+#define clearpcr(reg,val) ({ long __tmp; \
+          asm volatile ("clearpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \
+          __tmp; })
+
+#endif
+
+#endif
+
+#endif
diff --git a/benchmarks/common/syscalls.S b/benchmarks/common/syscalls.S
new file mode 100644 (file)
index 0000000..a0cdf6e
--- /dev/null
@@ -0,0 +1,678 @@
+       .file   1 "syscalls.c"
+       .section .mdebug.abi64
+       .previous
+       .section        .rodata.str1.8,"aMS",@progbits,1
+       .align  3
+$LC0:
+       .ascii  "0123456789abcdef\000"
+       .text
+       .align  2
+       .ent    printnum
+       .type   printnum, @function
+printnum:
+       .frame  x30,64,x1               # vars= 0, regs= 7/0, args= 0
+       .mask   0x03f00002,-8
+       .fmask  0x00000000,0
+       add     x30,x30,-64
+       sd      x22,32(x30)
+       sll     x22,x7,32
+       srl     x22,x22,32
+       sd      x24,48(x30)
+       sd      x23,40(x30)
+       sd      x21,24(x30)
+       sd      x20,16(x30)
+       sd      x25,56(x30)
+       sd      x1,8(x30)
+       move    x23,x6
+       move    x20,x4
+       move    x21,x5
+       move    x24,x9
+       bleu    x22,x6,$L2
+       addw    x8,x8,-1
+       move    x25,x8
+       ble     x8,x0,$L4
+$L6:
+       addw    x25,x25,-1
+       move    x4,x24
+       move    x5,x21
+       jalr    x20
+       bne     x25,x0,$L6
+$L4:
+       lui     x2,%hi($LC0)
+       add     x2,x2,%lo($LC0)
+       remu    x22,x23,x22
+       add     x22,x22,x2
+       lb      x4,0(x22)
+       move    x5,x21
+       move    x19,x20
+       ld      x25,56(x30)
+       ld      x24,48(x30)
+       ld      x23,40(x30)
+       ld      x22,32(x30)
+       ld      x21,24(x30)
+       ld      x20,16(x30)
+       ld      x1,8(x30)
+       add     x30,x30,64
+       jr      x19
+$L2:
+       addw    x8,x8,-1
+       divu    x6,x6,x22
+       jal     printnum
+       j       $L4
+       .end    printnum
+       .size   printnum, .-printnum
+       .align  2
+       .ent    getuint
+       .type   getuint, @function
+getuint:
+       .frame  x30,0,x1                # vars= 0, regs= 0/0, args= 0
+       .mask   0x00000000,0
+       .fmask  0x00000000,0
+       slt     x2,x5,2
+       bne     x2,x0,$L10
+$L13:
+       ld      x2,0(x4)
+       add     x3,x2,8
+       sd      x3,0(x4)
+       ld      x2,0(x2)
+       ret
+$L10:
+       bne     x5,x0,$L13
+       ld      x3,0(x4)
+       lwu     x2,0(x3)
+       add     x3,x3,8
+       sd      x3,0(x4)
+       ret
+       .end    getuint
+       .size   getuint, .-getuint
+       .align  2
+       .globl  putchar
+       .ent    putchar
+       .type   putchar, @function
+putchar:
+       .frame  x30,64,x1               # vars= 64, regs= 0/0, args= 0
+       .mask   0x00000000,0
+       .fmask  0x00000000,0
+       li      x2,-1                   # 0xffffffffffffffff
+       add     x30,x30,-64
+       lui     x3,%hi(buflen.1596)
+       beq     x4,x2,$L21
+       lw      x5,%lo(buflen.1596)(x3)
+       lui     x2,%hi(buf.1595)
+       add     x2,x2,%lo(buf.1595)
+       add     x6,x2,x5
+       sb      x4,0(x6)
+       addw    x5,x5,1
+       li      x4,64                   # 0x40
+       sw      x5,%lo(buflen.1596)(x3)
+       beq     x5,x4,$L15
+       move    x2,x0
+       add     x30,x30,64
+       j       x1
+$L21:
+       lui     x2,%hi(buf.1595)
+       add     x2,x2,%lo(buf.1595)
+$L15:
+       lw      x4,%lo(buflen.1596)(x3)
+       li      x5,4                    # 0x4
+       sd      x0,0(x30)
+       sd      x0,8(x30)
+       sd      x0,16(x30)
+       sd      x0,24(x30)
+       sd      x0,32(x30)
+       sd      x0,40(x30)
+       sd      x0,48(x30)
+       sd      x0,56(x30)
+       sd      x5,0(x30)
+       li      x5,1                    # 0x1
+       sd      x5,8(x30)
+       sd      x2,16(x30)
+       sd      x4,24(x30)
+       fence
+ #APP
+ # 45 "syscalls.c" 1
+       mtpcr x2,x30,cr30
+ # 0 "" 2
+ #NO_APP
+$L17:
+ #APP
+ # 46 "syscalls.c" 1
+       mfpcr x2,cr31
+ # 0 "" 2
+ #NO_APP
+       beq     x2,x0,$L17
+       move    x2,x0
+       sw      x0,%lo(buflen.1596)(x3)
+       add     x30,x30,64
+       j       x1
+       .end    putchar
+       .size   putchar, .-putchar
+       .align  2
+       .globl  exit
+       .ent    exit
+       .type   exit, @function
+exit:
+       .frame  x30,64,x1               # vars= 64, regs= 0/0, args= 0
+       .mask   0x00000000,0
+       .fmask  0x00000000,0
+       add     x30,x30,-64
+       li      x2,1                    # 0x1
+       sd      x0,0(x30)
+       sd      x0,8(x30)
+       sd      x0,16(x30)
+       sd      x0,24(x30)
+       sd      x0,32(x30)
+       sd      x0,40(x30)
+       sd      x0,48(x30)
+       sd      x0,56(x30)
+       sd      x2,0(x30)
+       sd      x4,8(x30)
+       fence
+ #APP
+ # 12 "syscalls.c" 1
+       mtpcr x2,x30,cr30
+ # 0 "" 2
+ #NO_APP
+$L23:
+       j       $L23
+       .end    exit
+       .size   exit, .-exit
+       .align  2
+       .globl  printstr
+       .ent    printstr
+       .type   printstr, @function
+printstr:
+       .frame  x30,80,x1               # vars= 64, regs= 1/0, args= 0
+       .mask   0x00000002,-8
+       .fmask  0x00000000,0
+       add     x30,x30,-80
+       li      x3,4                    # 0x4
+       sd      x0,0(x30)
+       sd      x0,8(x30)
+       sd      x0,16(x30)
+       sd      x0,24(x30)
+       sd      x0,32(x30)
+       sd      x0,40(x30)
+       sd      x0,48(x30)
+       sd      x0,56(x30)
+       sd      x3,0(x30)
+       li      x3,1                    # 0x1
+       sd      x3,8(x30)
+       sd      x1,72(x30)
+       sd      x4,16(x30)
+       jal     strlen
+       sd      x2,24(x30)
+       fence
+ #APP
+ # 24 "syscalls.c" 1
+       mtpcr x2,x30,cr30
+ # 0 "" 2
+ #NO_APP
+$L25:
+ #APP
+ # 25 "syscalls.c" 1
+       mfpcr x2,cr31
+ # 0 "" 2
+ #NO_APP
+       beq     x2,x0,$L25
+       ld      x1,72(x30)
+       add     x30,x30,80
+       j       x1
+       .end    printstr
+       .size   printstr, .-printstr
+       .align  2
+       .globl  printhex
+       .ent    printhex
+       .type   printhex, @function
+printhex:
+       .frame  x30,48,x1               # vars= 32, regs= 1/0, args= 0
+       .mask   0x00000002,-8
+       .fmask  0x00000000,0
+       add     x30,x30,-48
+       sd      x1,40(x30)
+       add     x2,x30,15
+       add     x7,x30,-1
+$L29:
+       and     x3,x4,15
+       sltu    x6,x3,10
+       li      x5,87                   # 0x57
+       beq     x6,x0,$L28
+       li      x5,48                   # 0x30
+$L28:
+       add     x3,x5,x3
+       sb      x3,0(x2)
+       add     x2,x2,-1
+       srl     x4,x4,4
+       bne     x2,x7,$L29
+       move    x4,x30
+       sb      x0,16(x30)
+       jal     printstr
+       ld      x1,40(x30)
+       add     x30,x30,48
+       j       x1
+       .end    printhex
+       .size   printhex, .-printhex
+       .section        .rodata.str1.8
+       .align  3
+$LC1:
+       .ascii  "(null)\000"
+       .text
+       .align  2
+       .globl  vprintfmt
+       .ent    vprintfmt
+       .type   vprintfmt, @function
+vprintfmt:
+       .frame  x30,112,x1              # vars= 32, regs= 10/0, args= 0
+       .mask   0x2ff00002,-8
+       .fmask  0x00000000,0
+       add     x30,x30,-112
+       sd      x25,80(x30)
+       lui     x25,%hi($L53)
+       sd      x26,88(x30)
+       sd      x24,72(x30)
+       sd      x23,64(x30)
+       sd      x22,56(x30)
+       sd      x21,48(x30)
+       sd      x20,40(x30)
+       sd      x29,104(x30)
+       sd      x27,96(x30)
+       sd      x1,32(x30)
+       move    x21,x4
+       move    x20,x5
+       move    x23,x6
+       sd      x7,0(x30)
+       li      x22,37                  # 0x25
+       add     x25,x25,%lo($L53)
+       li      x24,-1                  # 0xffffffffffffffff
+       lui     x26,%hi($LC1)
+       j       $L84
+$L35:
+       beq     x2,x0,$L32
+       move    x5,x20
+       add     x23,x23,1
+       jalr    x21
+$L84:
+       lbu     x4,0(x23)
+       move    x2,x4
+       bne     x4,x22,$L35
+       ld      x2,0(x30)
+       add     x6,x23,1
+       move    x7,x6
+       li      x27,32                  # 0x20
+       sd      x0,8(x30)
+       li      x3,-1                   # 0xffffffffffffffff
+       li      x29,-1                  # 0xffffffffffffffff
+       move    x5,x0
+$L85:
+       lbu     x4,0(x7)
+       add     x23,x7,1
+       addw    x8,x4,-35
+       and     x9,x8,0xff
+       sltu    x9,x9,86
+       bne     x9,x0,$L90
+$L38:
+       li      x4,37                   # 0x25
+       move    x5,x20
+       sd      x2,0(x30)
+       move    x23,x6
+       jalr    x21
+       j       $L84
+$L32:
+       ld      x1,32(x30)
+       ld      x29,104(x30)
+       ld      x27,96(x30)
+       ld      x26,88(x30)
+       ld      x25,80(x30)
+       ld      x24,72(x30)
+       ld      x23,64(x30)
+       ld      x22,56(x30)
+       ld      x21,48(x30)
+       ld      x20,40(x30)
+       add     x30,x30,112
+       j       x1
+$L90:
+       and     x8,x8,0xff
+       sll     x8,x8,3
+       add     x8,x25,x8
+       ld      x8,0(x8)
+       j       x8
+       .section        .rodata
+       .align  3
+       .align  2
+$L53:
+       .dword  $L39
+       .dword  $L38
+       .dword  $L40
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L41
+       .dword  $L38
+       .dword  $L38
+       .dword  $L42
+       .dword  $L43
+       .dword  $L38
+       .dword  $L74
+       .dword  $L44
+       .dword  $L44
+       .dword  $L44
+       .dword  $L44
+       .dword  $L44
+       .dword  $L44
+       .dword  $L44
+       .dword  $L44
+       .dword  $L44
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L45
+       .dword  $L46
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L38
+       .dword  $L47
+       .dword  $L38
+       .dword  $L38
+       .dword  $L48
+       .dword  $L49
+       .dword  $L38
+       .dword  $L38
+       .dword  $L50
+       .dword  $L38
+       .dword  $L51
+       .dword  $L38
+       .dword  $L38
+       .dword  $L52
+       .text
+$L52:
+       move    x4,x30
+       sd      x2,0(x30)
+       jal     getuint
+       move    x6,x2
+       li      x7,16                   # 0x10
+$L73:
+       move    x4,x21
+       move    x5,x20
+       move    x8,x29
+       move    x9,x27
+       jal     printnum
+       j       $L84
+$L39:
+       li      x4,1                    # 0x1
+       move    x7,x23
+       sd      x4,8(x30)
+       j       $L85
+$L40:
+       move    x5,x20
+       sd      x2,0(x30)
+       jalr    x21
+       j       $L84
+$L41:
+       lw      x3,0(x2)
+       move    x7,x23
+       add     x2,x2,8
+$L54:
+       bge     x29,x0,$L85
+       move    x29,x3
+       li      x3,-1                   # 0xffffffffffffffff
+       j       $L85
+$L42:
+       move    x7,x23
+       li      x27,45                  # 0x2d
+       j       $L85
+$L43:
+       blt     x29,x0,$L91
+       move    x7,x23
+       j       $L85
+$L74:
+       move    x7,x23
+       li      x27,48                  # 0x30
+       j       $L85
+$L44:
+       lb      x8,1(x7)
+       addw    x3,x4,-48
+       move    x7,x23
+       addw    x4,x8,-48
+       sltu    x4,x4,10
+       beq     x4,x0,$L54
+$L55:
+       add     x7,x7,1
+       lb      x4,0(x7)
+       sllw    x9,x3,1
+       sllw    x3,x3,3
+       addw    x3,x9,x3
+       addw    x9,x4,-48
+       addw    x3,x3,x8
+       sltu    x9,x9,10
+       addw    x3,x3,-48
+       move    x8,x4
+       bne     x9,x0,$L55
+       j       $L54
+$L45:
+       lw      x4,0(x2)
+       add     x2,x2,8
+       move    x5,x20
+       sd      x2,0(x30)
+       jalr    x21
+       j       $L84
+$L46:
+       slt     x3,x5,2
+       bne     x3,x0,$L69
+$L88:
+       add     x3,x2,8
+       sd      x3,0(x30)
+       ld      x6,0(x2)
+       blt     x6,x0,$L72
+$L89:
+       li      x7,10                   # 0xa
+       j       $L73
+$L47:
+       addw    x5,x5,1
+       move    x7,x23
+       j       $L85
+$L48:
+       move    x4,x30
+       sd      x2,0(x30)
+       jal     getuint
+       move    x6,x2
+       li      x7,8                    # 0x8
+       j       $L73
+$L49:
+       sd      x2,0(x30)
+       li      x4,48                   # 0x30
+       move    x5,x20
+       jalr    x21
+       li      x4,120                  # 0x78
+       move    x5,x20
+       jalr    x21
+       ld      x2,0(x30)
+       li      x7,16                   # 0x10
+       add     x3,x2,8
+       sd      x3,0(x30)
+       ld      x6,0(x2)
+       j       $L73
+$L50:
+       add     x4,x2,8
+       sd      x4,0(x30)
+       ld      x2,0(x2)
+       sd      x2,16(x30)
+       beq     x2,x0,$L92
+$L58:
+       ble     x29,x0,$L59
+       li      x2,45                   # 0x2d
+       beq     x27,x2,$L59
+       ld      x4,16(x30)
+       move    x5,x3
+       sd      x3,24(x30)
+       jal     strnlen
+       sllw    x2,x2,0
+       subw    x2,x29,x2
+       move    x29,x2
+       ld      x3,24(x30)
+       ble     x2,x0,$L59
+       move    x29,x2
+$L60:
+       sd      x3,24(x30)
+       move    x4,x27
+       move    x5,x20
+       addw    x29,x29,-1
+       jalr    x21
+       ld      x3,24(x30)
+       bne     x29,x0,$L60
+$L59:
+       ld      x2,16(x30)
+       lb      x4,0(x2)
+       add     x27,x2,1
+       beq     x4,x0,$L62
+$L80:
+       blt     x3,x0,$L67
+       addw    x2,x3,-1
+       move    x3,x2
+       beq     x2,x24,$L62
+$L67:
+       ld      x2,8(x30)
+       beq     x2,x0,$L63
+       addw    x2,x4,-32
+       sltu    x2,x2,95
+       beq     x2,x0,$L93
+$L63:
+       sd      x3,24(x30)
+       move    x5,x20
+       jalr    x21
+       ld      x3,24(x30)
+$L64:
+       lb      x4,0(x27)
+       addw    x29,x29,-1
+       add     x27,x27,1
+       bne     x4,x0,$L80
+$L62:
+       ble     x29,x0,$L84
+$L79:
+       addw    x29,x29,-1
+       li      x4,32                   # 0x20
+       move    x5,x20
+       jalr    x21
+       bne     x29,x0,$L79
+       j       $L84
+$L51:
+       move    x4,x30
+       sd      x2,0(x30)
+       jal     getuint
+       move    x6,x2
+       li      x7,10                   # 0xa
+       j       $L73
+$L93:
+       sd      x3,24(x30)
+       li      x4,63                   # 0x3f
+       move    x5,x20
+       jalr    x21
+       ld      x3,24(x30)
+       j       $L64
+$L91:
+       move    x7,x23
+       move    x29,x0
+       j       $L85
+$L92:
+       add     x2,x26,%lo($LC1)
+       sd      x2,16(x30)
+       j       $L58
+$L72:
+       sd      x6,24(x30)
+       li      x4,45                   # 0x2d
+       move    x5,x20
+       jalr    x21
+       ld      x6,24(x30)
+       li      x7,10                   # 0xa
+       sub     x6,zero,x6
+       j       $L73
+$L69:
+       bne     x5,x0,$L88
+       lw      x6,0(x2)
+       add     x2,x2,8
+       sd      x2,0(x30)
+       bge     x6,x0,$L89
+       j       $L72
+       .end    vprintfmt
+       .size   vprintfmt, .-vprintfmt
+       .align  2
+       .globl  printf
+       .ent    printf
+       .type   printf, @function
+printf:
+       .frame  x30,96,x1               # vars= 16, regs= 1/0, args= 0
+       .mask   0x00000002,-72
+       .fmask  0x00000000,0
+       add     x30,x30,-96
+       add     x2,x30,40
+       move    x3,x4
+       lui     x4,%hi(putchar)
+       sd      x5,40(x30)
+       sd      x6,48(x30)
+       sd      x7,56(x30)
+       add     x4,x4,%lo(putchar)
+       move    x5,x0
+       move    x6,x3
+       move    x7,x2
+       sd      x1,24(x30)
+       sd      x8,64(x30)
+       sd      x9,72(x30)
+       sd      x10,80(x30)
+       sd      x11,88(x30)
+       sd      x2,0(x30)
+       jal     vprintfmt
+       li      x4,-1                   # 0xffffffffffffffff
+       jal     putchar
+       ld      x1,24(x30)
+       move    x2,x0
+       add     x30,x30,96
+       j       x1
+       .end    printf
+       .size   printf, .-printf
+       .local  buflen.1596
+       .comm   buflen.1596,4,4
+       .local  buf.1595
+       .comm   buf.1595,64,8
+       .ident  "GCC: (GNU) 4.6.1"
diff --git a/benchmarks/common/syscalls.c b/benchmarks/common/syscalls.c
new file mode 100644 (file)
index 0000000..f95dde4
--- /dev/null
@@ -0,0 +1,265 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+#include "pcr.h"
+
+void exit(int code)
+{
+  volatile uint64_t magic_mem[8] = {0};
+  magic_mem[0] = 1;
+  magic_mem[1] = code;
+  __sync_synchronize();
+  mtpcr(PCR_TOHOST, (long)magic_mem);
+  while(1);
+}
+
+void printstr(const char* s)
+{
+  volatile uint64_t magic_mem[8] = {0};
+  magic_mem[0] = 4;
+  magic_mem[1] = 1;
+  magic_mem[2] = (unsigned long)s;
+  magic_mem[3] = strlen(s);
+  __sync_synchronize();
+  mtpcr(PCR_TOHOST, (long)magic_mem);
+  while(mtpcr(PCR_FROMHOST, 0) == 0);
+}
+
+int putchar(int ch)
+{
+  #define buffered_putch_bufsize 64
+  static char buf[buffered_putch_bufsize];
+  static int buflen = 0;
+
+  if(ch != -1)
+    buf[buflen++] = ch;
+
+  if(ch == -1 || buflen == buffered_putch_bufsize)
+  {
+    volatile uint64_t magic_mem[8] = {0};
+    magic_mem[0] = 4;
+    magic_mem[1] = 1;
+    magic_mem[2] = (long)buf;
+    magic_mem[3] = buflen;
+    __sync_synchronize();
+    mtpcr(PCR_TOHOST, (long)magic_mem);
+    while(mtpcr(PCR_FROMHOST, 0) == 0);
+
+    buflen = 0;
+  }
+
+  return 0;
+}
+
+void printhex(uint64_t x)
+{
+  char str[17];
+  int i;
+  for (i = 0; i < 16; i++)
+  {
+    str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10);
+    x >>= 4;
+  }
+  str[16] = 0;
+
+  printstr(str);
+}
+
+static void printnum(void (*putch)(int, void**), void **putdat,
+                   unsigned long long num, unsigned base, int width, int padc)
+{
+  if (num >= base)
+    printnum(putch, putdat, num / base, base, width - 1, padc);
+  else while (--width > 0)
+    putch(padc, putdat);
+
+  putch("0123456789abcdef"[num % base], putdat);
+}
+
+static unsigned long long getuint(va_list *ap, int lflag)
+{
+  if (lflag >= 2)
+    return va_arg(*ap, unsigned long long);
+  else if (lflag)
+    return va_arg(*ap, unsigned long);
+  else
+    return va_arg(*ap, unsigned int);
+}
+
+static long long getint(va_list *ap, int lflag)
+{
+  if (lflag >= 2)
+    return va_arg(*ap, long long);
+  else if (lflag)
+    return va_arg(*ap, long);
+  else
+    return va_arg(*ap, int);
+}
+
+void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
+{
+  register const char* p;
+  const char* last_fmt;
+  register int ch, err;
+  unsigned long long num;
+  int base, lflag, width, precision, altflag;
+  char padc;
+
+  while (1) {
+    while ((ch = *(unsigned char *) fmt) != '%') {
+      if (ch == '\0')
+        return;
+      fmt++;
+      putch(ch, putdat);
+    }
+    fmt++;
+
+    // Process a %-escape sequence
+    last_fmt = fmt;
+    padc = ' ';
+    width = -1;
+    precision = -1;
+    lflag = 0;
+    altflag = 0;
+  reswitch:
+    switch (ch = *(unsigned char *) fmt++) {
+
+    // flag to pad on the right
+    case '-':
+      padc = '-';
+      goto reswitch;
+      
+    // flag to pad with 0's instead of spaces
+    case '0':
+      padc = '0';
+      goto reswitch;
+
+    // width field
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      for (precision = 0; ; ++fmt) {
+        precision = precision * 10 + ch - '0';
+        ch = *fmt;
+        if (ch < '0' || ch > '9')
+          break;
+      }
+      goto process_precision;
+
+    case '*':
+      precision = va_arg(ap, int);
+      goto process_precision;
+
+    case '.':
+      if (width < 0)
+        width = 0;
+      goto reswitch;
+
+    case '#':
+      altflag = 1;
+      goto reswitch;
+
+    process_precision:
+      if (width < 0)
+        width = precision, precision = -1;
+      goto reswitch;
+
+    // long flag (doubled for long long)
+    case 'l':
+      lflag++;
+      goto reswitch;
+
+    // character
+    case 'c':
+      putch(va_arg(ap, int), putdat);
+      break;
+
+    // string
+    case 's':
+      if ((p = va_arg(ap, char *)) == NULL)
+        p = "(null)";
+      if (width > 0 && padc != '-')
+        for (width -= strnlen(p, precision); width > 0; width--)
+          putch(padc, putdat);
+      for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) {
+        if (altflag && (ch < ' ' || ch > '~'))
+          putch('?', putdat);
+        else
+          putch(ch, putdat);
+        p++;
+      }
+      for (; width > 0; width--)
+        putch(' ', putdat);
+      break;
+
+    // (signed) decimal
+    case 'd':
+      num = getint(&ap, lflag);
+      if ((long long) num < 0) {
+        putch('-', putdat);
+        num = -(long long) num;
+      }
+      base = 10;
+      goto number;
+
+    // unsigned decimal
+    case 'u':
+      num = getuint(&ap, lflag);
+      base = 10;
+      goto number;
+
+    // (unsigned) octal
+    case 'o':
+      // should do something with padding so it's always 3 octits
+      num = getuint(&ap, lflag);
+      base = 8;
+      goto number;
+
+    // pointer
+    case 'p':
+      putch('0', putdat);
+      putch('x', putdat);
+      num = (unsigned long long)
+        (uintptr_t) va_arg(ap, void *);
+      base = 16;
+      goto number;
+
+    // (unsigned) hexadecimal
+    case 'x':
+      num = getuint(&ap, lflag);
+      base = 16;
+    number:
+      printnum(putch, putdat, num, base, width, padc);
+      break;
+
+    // escaped '%' character
+    case '%':
+      putch(ch, putdat);
+      break;
+      
+    // unrecognized escape sequence - just print it literally
+    default:
+      putch('%', putdat);
+      fmt = last_fmt;
+      break;
+    }
+  }
+}
+
+int printf(const char* fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+
+  vprintfmt((void*)putchar, 0, fmt, ap);
+  putchar(-1);
+
+  va_end(ap);
+  return 0; // incorrect return value, but who cares, anyway?
+}
diff --git a/benchmarks/common/test-mt.ld b/benchmarks/common/test-mt.ld
new file mode 100644 (file)
index 0000000..5523032
--- /dev/null
@@ -0,0 +1,45 @@
+/*======================================================================*/
+/* Proxy kernel linker script                                           */
+/*======================================================================*/
+/* This is the linker script used when building the proxy kernel. */
+
+/*----------------------------------------------------------------------*/
+/* Setup                                                                */
+/*----------------------------------------------------------------------*/
+
+/* The OUTPUT_ARCH command specifies the machine architecture where the
+   argument is one of the names used in the BFD library. More
+   specifically one of the entires in bfd/cpu-mips.c */
+
+OUTPUT_ARCH( "riscv" )
+
+/* The ENTRY command specifies the entry point (ie. first instruction
+   to execute). The symbol _start should be defined in each test. */
+
+ENTRY( _start )
+
+/*----------------------------------------------------------------------*/
+/* Sections                                                             */
+/*----------------------------------------------------------------------*/
+
+SECTIONS
+{
+
+  /* text: test code section */
+  . = 0x00002000;
+  .text : 
+  {
+    crt-mt.o(.text)
+    *(.text)
+  }
+
+  /* data: Initialized data segment */
+  .data : 
+  {
+    *(.data)
+  }
+
+  /* End of uninitalized data segement */
+  _end = .;
+}
+
diff --git a/benchmarks/common/test.ld b/benchmarks/common/test.ld
new file mode 100644 (file)
index 0000000..952bf53
--- /dev/null
@@ -0,0 +1,45 @@
+/*======================================================================*/
+/* Proxy kernel linker script                                           */
+/*======================================================================*/
+/* This is the linker script used when building the proxy kernel. */
+
+/*----------------------------------------------------------------------*/
+/* Setup                                                                */
+/*----------------------------------------------------------------------*/
+
+/* The OUTPUT_ARCH command specifies the machine architecture where the
+   argument is one of the names used in the BFD library. More
+   specifically one of the entires in bfd/cpu-mips.c */
+
+OUTPUT_ARCH( "riscv" )
+
+/* The ENTRY command specifies the entry point (ie. first instruction
+   to execute). The symbol _start should be defined in each test. */
+
+ENTRY( _start )
+
+/*----------------------------------------------------------------------*/
+/* Sections                                                             */
+/*----------------------------------------------------------------------*/
+
+SECTIONS
+{
+
+  /* text: test code section */
+  . = 0x00002000;
+  .text : 
+  {
+    crt.o(.text)
+    *(.text)
+  }
+
+  /* data: Initialized data segment */
+  .data : 
+  {
+    *(.data)
+  }
+
+  /* End of uninitalized data segement */
+  _end = .;
+}
+
diff --git a/benchmarks/common/util.h b/benchmarks/common/util.h
new file mode 100644 (file)
index 0000000..83b2b6c
--- /dev/null
@@ -0,0 +1,32 @@
+// helpful utility and synch functions 
+
+// relies on defining "ncores" before including this file...
+
+#ifndef __UTIL_H
+#define __UTIL_H
+
+#define rdcycle() ({ unsigned long _c; asm volatile ("rdcycle %0" : "=r"(_c) :: "memory"); _c; })
+#define rdinstret() ({ unsigned long _c; asm volatile ("rdinstret %0" : "=r"(_c) :: "memory"); _c; })
+                            
+void __attribute__((noinline)) barrier()
+{
+  static volatile int sense;
+  static volatile int count;
+  static __thread int threadsense;
+
+  __sync_synchronize();
+
+  threadsense = !threadsense;
+  if (__sync_fetch_and_add(&count, 1) == ncores-1)
+  {
+    count = 0;
+    sense = threadsense;
+  }
+  else while(sense != threadsense)
+    ;
+
+  __sync_synchronize();
+}
+   
+#endif //__UTIL_H
+
diff --git a/benchmarks/dgemm/bmark.mk b/benchmarks/dgemm/bmark.mk
new file mode 100644 (file)
index 0000000..5a26242
--- /dev/null
@@ -0,0 +1,29 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include
+# the benchmark name as a prefix so that they are unique.
+#
+
+dgemm_c_src = \
+       dgemm_main.c \
+
+dgemm_riscv_src = \
+       crt.S \
+
+dgemm_c_objs     = $(patsubst %.c, %.o, $(dgemm_c_src))
+dgemm_riscv_objs = $(patsubst %.S, %.o, $(dgemm_riscv_src))
+
+dgemm_host_bin = dgemm.host
+$(dgemm_host_bin) : $(dgemm_c_src)
+       $(HOST_COMP) $^ -o $(dgemm_host_bin)
+
+dgemm_riscv_bin = dgemm.riscv
+$(dgemm_riscv_bin) : $(dgemm_c_objs) $(dgemm_riscv_objs)
+       $(RISCV_LINK) $(dgemm_c_objs) $(dgemm_riscv_objs) -o $(dgemm_riscv_bin)
+
+junk += $(dgemm_c_objs) $(dgemm_riscv_objs) \
+        $(dgemm_host_bin) $(dgemm_riscv_bin)
diff --git a/benchmarks/dgemm/dataset1.h b/benchmarks/dgemm/dataset1.h
new file mode 100644 (file)
index 0000000..9db066e
--- /dev/null
@@ -0,0 +1,97 @@
+#define DATA_SIZE 30
+const double input1_data[DATA_SIZE*DATA_SIZE] = {
+745.0, 504.0, 772.0, 818.0, 443.0, 308.0, 823.0, 523.0, 93.0, 379.0, 728.0, 543.0, 40.0, 482.0, 728.0, 487.0, 144.0, 486.0, 109.0, 994.0, 373.0, 257.0, 196.0, 145.0, 234.0, 301.0, 639.0, 379.0, 913.0, 420.0, 
+264.0, 636.0, 873.0, 677.0, 330.0, 928.0, 30.0, 603.0, 96.0, 510.0, 196.0, 55.0, 702.0, 663.0, 151.0, 526.0, 624.0, 598.0, 529.0, 926.0, 914.0, 641.0, 401.0, 146.0, 756.0, 550.0, 92.0, 452.0, 786.0, 417.0, 
+115.0, 202.0, 806.0, 841.0, 657.0, 33.0, 66.0, 595.0, 751.0, 302.0, 70.0, 453.0, 318.0, 580.0, 114.0, 85.0, 585.0, 959.0, 393.0, 810.0, 276.0, 839.0, 58.0, 632.0, 940.0, 568.0, 676.0, 625.0, 861.0, 702.0, 
+413.0, 79.0, 762.0, 494.0, 695.0, 774.0, 877.0, 968.0, 327.0, 742.0, 163.0, 353.0, 692.0, 870.0, 634.0, 60.0, 545.0, 300.0, 625.0, 48.0, 390.0, 713.0, 661.0, 613.0, 673.0, 89.0, 116.0, 472.0, 837.0, 864.0, 
+256.0, 542.0, 660.0, 768.0, 474.0, 229.0, 783.0, 583.0, 975.0, 278.0, 838.0, 557.0, 372.0, 815.0, 94.0, 820.0, 713.0, 685.0, 606.0, 304.0, 549.0, 150.0, 237.0, 981.0, 111.0, 85.0, 741.0, 960.0, 499.0, 110.0, 
+540.0, 414.0, 153.0, 809.0, 477.0, 176.0, 46.0, 27.0, 106.0, 704.0, 709.0, 728.0, 355.0, 934.0, 38.0, 974.0, 744.0, 651.0, 169.0, 514.0, 550.0, 742.0, 456.0, 453.0, 106.0, 956.0, 374.0, 945.0, 688.0, 594.0, 
+983.0, 686.0, 86.0, 247.0, 389.0, 914.0, 378.0, 837.0, 556.0, 332.0, 884.0, 102.0, 651.0, 329.0, 305.0, 874.0, 863.0, 752.0, 94.0, 102.0, 878.0, 200.0, 645.0, 601.0, 573.0, 369.0, 247.0, 241.0, 158.0, 647.0, 
+166.0, 139.0, 810.0, 531.0, 118.0, 750.0, 759.0, 621.0, 87.0, 472.0, 846.0, 644.0, 209.0, 515.0, 172.0, 565.0, 685.0, 344.0, 850.0, 218.0, 788.0, 323.0, 867.0, 809.0, 991.0, 806.0, 617.0, 878.0, 937.0, 816.0, 
+517.0, 811.0, 181.0, 590.0, 705.0, 691.0, 847.0, 233.0, 652.0, 374.0, 570.0, 160.0, 873.0, 78.0, 246.0, 652.0, 876.0, 145.0, 587.0, 729.0, 467.0, 111.0, 590.0, 653.0, 972.0, 987.0, 231.0, 809.0, 456.0, 887.0, 
+861.0, 60.0, 588.0, 71.0, 519.0, 479.0, 640.0, 608.0, 336.0, 259.0, 7.0, 578.0, 53.0, 823.0, 305.0, 911.0, 230.0, 445.0, 216.0, 696.0, 278.0, 804.0, 413.0, 333.0, 409.0, 632.0, 86.0, 401.0, 226.0, 93.0, 
+815.0, 177.0, 894.0, 51.0, 441.0, 785.0, 888.0, 915.0, 347.0, 55.0, 762.0, 896.0, 964.0, 539.0, 572.0, 889.0, 275.0, 43.0, 220.0, 195.0, 963.0, 342.0, 915.0, 651.0, 750.0, 286.0, 632.0, 168.0, 652.0, 880.0, 
+803.0, 439.0, 112.0, 544.0, 624.0, 656.0, 679.0, 117.0, 413.0, 798.0, 230.0, 571.0, 106.0, 36.0, 656.0, 848.0, 733.0, 931.0, 513.0, 614.0, 302.0, 776.0, 401.0, 703.0, 510.0, 682.0, 280.0, 351.0, 79.0, 353.0, 
+106.0, 355.0, 343.0, 802.0, 232.0, 583.0, 103.0, 663.0, 683.0, 37.0, 130.0, 795.0, 261.0, 202.0, 949.0, 739.0, 926.0, 930.0, 522.0, 872.0, 567.0, 724.0, 0.0, 385.0, 191.0, 704.0, 586.0, 974.0, 944.0, 100.0, 
+506.0, 903.0, 325.0, 622.0, 218.0, 842.0, 298.0, 676.0, 503.0, 4.0, 784.0, 63.0, 195.0, 495.0, 740.0, 518.0, 845.0, 649.0, 730.0, 287.0, 231.0, 477.0, 939.0, 472.0, 324.0, 459.0, 784.0, 988.0, 572.0, 338.0, 
+114.0, 993.0, 965.0, 134.0, 608.0, 613.0, 527.0, 645.0, 324.0, 497.0, 949.0, 659.0, 555.0, 494.0, 91.0, 317.0, 222.0, 276.0, 232.0, 266.0, 985.0, 146.0, 713.0, 54.0, 592.0, 879.0, 799.0, 16.0, 273.0, 791.0, 
+47.0, 235.0, 306.0, 873.0, 829.0, 266.0, 672.0, 893.0, 396.0, 396.0, 809.0, 603.0, 307.0, 712.0, 551.0, 390.0, 551.0, 898.0, 777.0, 672.0, 385.0, 810.0, 39.0, 311.0, 868.0, 734.0, 554.0, 941.0, 414.0, 182.0, 
+549.0, 589.0, 24.0, 141.0, 332.0, 833.0, 76.0, 431.0, 528.0, 313.0, 690.0, 190.0, 860.0, 670.0, 991.0, 679.0, 0.0, 460.0, 122.0, 585.0, 647.0, 157.0, 260.0, 941.0, 943.0, 27.0, 820.0, 81.0, 612.0, 622.0, 
+252.0, 183.0, 673.0, 275.0, 27.0, 867.0, 36.0, 45.0, 80.0, 321.0, 373.0, 485.0, 232.0, 428.0, 379.0, 973.0, 532.0, 804.0, 763.0, 91.0, 802.0, 463.0, 190.0, 153.0, 910.0, 552.0, 885.0, 976.0, 84.0, 572.0, 
+83.0, 109.0, 349.0, 881.0, 368.0, 980.0, 316.0, 97.0, 654.0, 737.0, 652.0, 525.0, 714.0, 526.0, 608.0, 245.0, 296.0, 765.0, 222.0, 403.0, 419.0, 663.0, 256.0, 23.0, 144.0, 446.0, 905.0, 933.0, 238.0, 709.0, 
+17.0, 587.0, 508.0, 879.0, 525.0, 310.0, 486.0, 372.0, 742.0, 764.0, 462.0, 8.0, 108.0, 741.0, 803.0, 502.0, 422.0, 579.0, 993.0, 835.0, 953.0, 584.0, 92.0, 932.0, 579.0, 534.0, 602.0, 473.0, 99.0, 961.0, 
+413.0, 83.0, 255.0, 849.0, 953.0, 912.0, 552.0, 220.0, 968.0, 600.0, 918.0, 48.0, 863.0, 88.0, 132.0, 278.0, 957.0, 507.0, 320.0, 618.0, 768.0, 776.0, 401.0, 943.0, 995.0, 695.0, 869.0, 295.0, 960.0, 357.0, 
+446.0, 304.0, 926.0, 664.0, 785.0, 211.0, 287.0, 420.0, 187.0, 325.0, 49.0, 355.0, 607.0, 752.0, 783.0, 963.0, 952.0, 188.0, 939.0, 953.0, 384.0, 255.0, 674.0, 747.0, 243.0, 892.0, 60.0, 3.0, 643.0, 831.0, 
+734.0, 240.0, 944.0, 943.0, 382.0, 671.0, 12.0, 292.0, 18.0, 966.0, 296.0, 335.0, 206.0, 881.0, 22.0, 473.0, 888.0, 510.0, 725.0, 276.0, 769.0, 506.0, 202.0, 789.0, 515.0, 110.0, 658.0, 835.0, 345.0, 885.0, 
+776.0, 194.0, 8.0, 124.0, 908.0, 176.0, 144.0, 820.0, 803.0, 56.0, 270.0, 676.0, 741.0, 621.0, 290.0, 214.0, 511.0, 382.0, 431.0, 164.0, 173.0, 504.0, 116.0, 828.0, 68.0, 465.0, 263.0, 383.0, 793.0, 32.0, 
+313.0, 39.0, 34.0, 331.0, 874.0, 310.0, 607.0, 128.0, 505.0, 948.0, 827.0, 357.0, 31.0, 904.0, 165.0, 491.0, 809.0, 607.0, 390.0, 156.0, 441.0, 219.0, 198.0, 165.0, 592.0, 890.0, 192.0, 791.0, 234.0, 424.0, 
+886.0, 552.0, 965.0, 615.0, 370.0, 30.0, 79.0, 178.0, 67.0, 148.0, 20.0, 241.0, 928.0, 301.0, 73.0, 55.0, 428.0, 812.0, 752.0, 535.0, 110.0, 518.0, 584.0, 661.0, 35.0, 856.0, 279.0, 633.0, 354.0, 450.0, 
+327.0, 165.0, 508.0, 261.0, 763.0, 496.0, 415.0, 872.0, 557.0, 428.0, 110.0, 406.0, 341.0, 425.0, 326.0, 644.0, 904.0, 676.0, 542.0, 590.0, 738.0, 651.0, 980.0, 521.0, 865.0, 511.0, 920.0, 563.0, 448.0, 780.0, 
+920.0, 999.0, 28.0, 940.0, 120.0, 908.0, 167.0, 319.0, 891.0, 53.0, 158.0, 319.0, 202.0, 283.0, 793.0, 608.0, 320.0, 711.0, 447.0, 533.0, 528.0, 300.0, 532.0, 797.0, 571.0, 960.0, 104.0, 773.0, 122.0, 99.0, 
+156.0, 119.0, 932.0, 689.0, 227.0, 991.0, 396.0, 890.0, 579.0, 54.0, 459.0, 624.0, 976.0, 904.0, 781.0, 712.0, 403.0, 560.0, 226.0, 225.0, 940.0, 68.0, 140.0, 714.0, 937.0, 731.0, 624.0, 416.0, 601.0, 50.0, 
+883.0, 869.0, 921.0, 350.0, 226.0, 596.0, 698.0, 51.0, 510.0, 865.0, 942.0, 971.0, 794.0, 254.0, 757.0, 19.0, 690.0, 303.0, 664.0, 127.0, 538.0, 487.0, 609.0, 86.0, 688.0, 76.0, 477.0, 664.0, 343.0, 613.0
+};
+const double input2_data[DATA_SIZE*DATA_SIZE] = {
+494.0, 929.0, 783.0, 86.0, 317.0, 957.0, 289.0, 481.0, 222.0, 945.0, 97.0, 952.0, 1.0, 834.0, 795.0, 59.0, 127.0, 10.0, 399.0, 904.0, 907.0, 665.0, 623.0, 841.0, 190.0, 903.0, 698.0, 132.0, 775.0, 911.0, 
+346.0, 417.0, 995.0, 439.0, 159.0, 390.0, 902.0, 917.0, 174.0, 462.0, 638.0, 484.0, 505.0, 353.0, 943.0, 724.0, 684.0, 845.0, 753.0, 983.0, 353.0, 730.0, 883.0, 679.0, 449.0, 442.0, 242.0, 117.0, 64.0, 143.0, 
+42.0, 476.0, 395.0, 343.0, 983.0, 724.0, 153.0, 3.0, 88.0, 131.0, 475.0, 517.0, 297.0, 917.0, 522.0, 776.0, 796.0, 468.0, 11.0, 9.0, 788.0, 908.0, 161.0, 554.0, 429.0, 381.0, 495.0, 720.0, 795.0, 563.0, 
+976.0, 786.0, 349.0, 930.0, 421.0, 218.0, 589.0, 210.0, 18.0, 536.0, 888.0, 18.0, 142.0, 674.0, 684.0, 297.0, 190.0, 160.0, 195.0, 232.0, 917.0, 451.0, 955.0, 340.0, 553.0, 470.0, 287.0, 263.0, 164.0, 28.0, 
+133.0, 206.0, 141.0, 697.0, 860.0, 45.0, 508.0, 61.0, 442.0, 142.0, 991.0, 523.0, 720.0, 544.0, 787.0, 231.0, 635.0, 828.0, 162.0, 150.0, 656.0, 915.0, 557.0, 56.0, 539.0, 108.0, 862.0, 160.0, 739.0, 561.0, 
+525.0, 564.0, 334.0, 977.0, 789.0, 287.0, 316.0, 169.0, 18.0, 140.0, 322.0, 707.0, 458.0, 646.0, 902.0, 728.0, 877.0, 386.0, 922.0, 657.0, 490.0, 942.0, 127.0, 617.0, 143.0, 979.0, 911.0, 71.0, 348.0, 989.0, 
+55.0, 968.0, 173.0, 987.0, 959.0, 865.0, 850.0, 194.0, 776.0, 681.0, 893.0, 564.0, 305.0, 645.0, 600.0, 214.0, 613.0, 790.0, 496.0, 127.0, 564.0, 197.0, 818.0, 419.0, 597.0, 414.0, 552.0, 240.0, 517.0, 34.0, 
+487.0, 497.0, 614.0, 182.0, 761.0, 45.0, 959.0, 441.0, 90.0, 500.0, 76.0, 435.0, 905.0, 920.0, 402.0, 641.0, 621.0, 526.0, 521.0, 438.0, 457.0, 224.0, 718.0, 611.0, 909.0, 347.0, 524.0, 158.0, 491.0, 331.0, 
+727.0, 536.0, 243.0, 503.0, 252.0, 633.0, 675.0, 671.0, 600.0, 598.0, 479.0, 522.0, 92.0, 778.0, 793.0, 956.0, 562.0, 659.0, 29.0, 132.0, 182.0, 491.0, 107.0, 891.0, 108.0, 664.0, 985.0, 608.0, 610.0, 589.0, 
+364.0, 665.0, 689.0, 262.0, 356.0, 324.0, 646.0, 275.0, 906.0, 316.0, 551.0, 836.0, 14.0, 495.0, 900.0, 859.0, 529.0, 900.0, 516.0, 654.0, 635.0, 90.0, 337.0, 59.0, 954.0, 419.0, 921.0, 903.0, 393.0, 503.0, 
+458.0, 879.0, 568.0, 925.0, 809.0, 496.0, 22.0, 780.0, 966.0, 265.0, 759.0, 872.0, 352.0, 110.0, 467.0, 641.0, 321.0, 272.0, 646.0, 765.0, 413.0, 935.0, 309.0, 661.0, 796.0, 881.0, 283.0, 612.0, 602.0, 684.0, 
+680.0, 332.0, 688.0, 896.0, 483.0, 131.0, 680.0, 265.0, 828.0, 779.0, 410.0, 176.0, 657.0, 776.0, 678.0, 232.0, 522.0, 722.0, 485.0, 878.0, 987.0, 754.0, 225.0, 897.0, 374.0, 704.0, 117.0, 929.0, 586.0, 891.0, 
+162.0, 237.0, 300.0, 147.0, 648.0, 324.0, 376.0, 552.0, 381.0, 589.0, 788.0, 637.0, 461.0, 802.0, 481.0, 694.0, 406.0, 127.0, 623.0, 743.0, 662.0, 257.0, 636.0, 655.0, 827.0, 649.0, 961.0, 561.0, 511.0, 991.0, 
+633.0, 907.0, 279.0, 732.0, 527.0, 31.0, 54.0, 320.0, 875.0, 863.0, 82.0, 881.0, 272.0, 677.0, 787.0, 149.0, 709.0, 457.0, 411.0, 287.0, 598.0, 27.0, 231.0, 853.0, 270.0, 520.0, 96.0, 178.0, 51.0, 938.0, 
+414.0, 639.0, 127.0, 888.0, 18.0, 821.0, 606.0, 253.0, 566.0, 134.0, 833.0, 324.0, 316.0, 393.0, 157.0, 753.0, 888.0, 131.0, 40.0, 450.0, 762.0, 139.0, 603.0, 196.0, 324.0, 590.0, 573.0, 738.0, 252.0, 297.0, 
+353.0, 280.0, 718.0, 350.0, 813.0, 663.0, 2.0, 405.0, 405.0, 353.0, 957.0, 699.0, 981.0, 499.0, 807.0, 648.0, 0.0, 675.0, 8.0, 514.0, 215.0, 22.0, 463.0, 671.0, 65.0, 764.0, 25.0, 232.0, 891.0, 152.0, 
+698.0, 426.0, 813.0, 87.0, 12.0, 246.0, 1.0, 834.0, 81.0, 695.0, 296.0, 935.0, 30.0, 699.0, 811.0, 881.0, 822.0, 259.0, 883.0, 935.0, 447.0, 973.0, 629.0, 58.0, 534.0, 745.0, 654.0, 344.0, 826.0, 568.0, 
+198.0, 814.0, 111.0, 912.0, 84.0, 179.0, 706.0, 700.0, 838.0, 455.0, 972.0, 216.0, 659.0, 210.0, 781.0, 842.0, 248.0, 465.0, 518.0, 37.0, 3.0, 803.0, 562.0, 983.0, 375.0, 34.0, 882.0, 586.0, 668.0, 228.0, 
+644.0, 632.0, 530.0, 729.0, 783.0, 543.0, 450.0, 151.0, 302.0, 148.0, 225.0, 794.0, 590.0, 212.0, 146.0, 191.0, 718.0, 621.0, 303.0, 343.0, 562.0, 715.0, 516.0, 409.0, 36.0, 486.0, 248.0, 416.0, 624.0, 865.0, 
+680.0, 460.0, 737.0, 813.0, 658.0, 396.0, 749.0, 132.0, 875.0, 73.0, 243.0, 874.0, 309.0, 5.0, 748.0, 526.0, 273.0, 634.0, 661.0, 382.0, 61.0, 728.0, 511.0, 960.0, 418.0, 454.0, 249.0, 725.0, 68.0, 306.0, 
+899.0, 127.0, 599.0, 587.0, 7.0, 236.0, 722.0, 531.0, 694.0, 403.0, 163.0, 483.0, 557.0, 10.0, 855.0, 494.0, 90.0, 186.0, 180.0, 335.0, 646.0, 74.0, 869.0, 751.0, 409.0, 777.0, 449.0, 310.0, 989.0, 624.0, 
+672.0, 27.0, 968.0, 211.0, 459.0, 70.0, 617.0, 431.0, 983.0, 291.0, 878.0, 599.0, 69.0, 873.0, 904.0, 337.0, 250.0, 120.0, 20.0, 389.0, 254.0, 714.0, 478.0, 62.0, 931.0, 992.0, 324.0, 537.0, 84.0, 333.0, 
+724.0, 874.0, 511.0, 407.0, 915.0, 566.0, 809.0, 905.0, 811.0, 291.0, 572.0, 374.0, 376.0, 988.0, 751.0, 881.0, 888.0, 169.0, 922.0, 616.0, 181.0, 203.0, 389.0, 622.0, 568.0, 204.0, 924.0, 543.0, 331.0, 765.0, 
+273.0, 742.0, 682.0, 913.0, 38.0, 787.0, 983.0, 783.0, 821.0, 848.0, 114.0, 661.0, 678.0, 634.0, 865.0, 551.0, 700.0, 253.0, 481.0, 231.0, 860.0, 680.0, 801.0, 783.0, 987.0, 624.0, 888.0, 770.0, 11.0, 689.0, 
+731.0, 72.0, 538.0, 78.0, 324.0, 368.0, 176.0, 305.0, 817.0, 136.0, 122.0, 783.0, 608.0, 391.0, 136.0, 859.0, 13.0, 452.0, 663.0, 826.0, 880.0, 728.0, 947.0, 342.0, 646.0, 182.0, 13.0, 148.0, 450.0, 610.0, 
+477.0, 121.0, 487.0, 143.0, 125.0, 153.0, 268.0, 635.0, 745.0, 792.0, 981.0, 109.0, 694.0, 353.0, 547.0, 559.0, 974.0, 59.0, 655.0, 694.0, 165.0, 628.0, 544.0, 694.0, 476.0, 702.0, 494.0, 627.0, 88.0, 630.0, 
+194.0, 650.0, 165.0, 587.0, 884.0, 53.0, 44.0, 931.0, 432.0, 630.0, 214.0, 817.0, 383.0, 3.0, 908.0, 667.0, 205.0, 791.0, 845.0, 584.0, 396.0, 26.0, 547.0, 399.0, 189.0, 438.0, 698.0, 826.0, 734.0, 322.0, 
+678.0, 305.0, 868.0, 564.0, 480.0, 499.0, 182.0, 215.0, 276.0, 272.0, 803.0, 21.0, 458.0, 2.0, 90.0, 213.0, 223.0, 97.0, 68.0, 589.0, 408.0, 197.0, 472.0, 915.0, 771.0, 830.0, 907.0, 133.0, 146.0, 848.0, 
+89.0, 17.0, 580.0, 755.0, 909.0, 310.0, 249.0, 606.0, 544.0, 193.0, 409.0, 235.0, 537.0, 580.0, 850.0, 838.0, 882.0, 416.0, 365.0, 263.0, 331.0, 868.0, 68.0, 519.0, 206.0, 70.0, 530.0, 927.0, 590.0, 29.0, 
+990.0, 507.0, 164.0, 89.0, 550.0, 150.0, 959.0, 787.0, 444.0, 695.0, 79.0, 86.0, 359.0, 841.0, 991.0, 71.0, 537.0, 521.0, 253.0, 88.0, 872.0, 760.0, 71.0, 959.0, 844.0, 24.0, 323.0, 86.0, 284.0, 324.0
+};
+const double verify_data[DATA_SIZE*DATA_SIZE] = {
+6411903.0, 7533490.0, 6901412.0, 8515176.0, 7937886.0, 5660376.0, 6684238.0, 5930516.0, 7411434.0, 5963715.0, 7339541.0, 7325224.0, 5773363.0, 6987016.0, 9472107.0, 7333522.0, 6868741.0, 6373927.0, 5818371.0, 6232365.0, 7410967.0, 7456844.0, 7008217.0, 8317827.0, 6560681.0, 6993670.0, 6792972.0, 6664526.0, 6449148.0, 6153016.0, 
+7767492.0, 6619373.0, 8084203.0, 7609675.0, 7767288.0, 5081659.0, 6915392.0, 6473820.0, 7434817.0, 5832034.0, 7317348.0, 8206514.0, 6552649.0, 7813213.0, 1.0197744E7, 8753506.0, 7589899.0, 6153453.0, 6716065.0, 7097060.0, 7488858.0, 8435675.0, 7671781.0, 8759777.0, 7413370.0, 7802106.0, 7613653.0, 6343832.0, 6741596.0, 7885307.0, 
+7584476.0, 6627809.0, 7334380.0, 7777143.0, 7311439.0, 4673418.0, 7231791.0, 6792764.0, 8133419.0, 6543855.0, 7278453.0, 7372708.0, 6345899.0, 7821711.0, 1.0014052E7, 8297702.0, 7222827.0, 6550430.0, 5927298.0, 5988751.0, 7626028.0, 8765186.0, 7449916.0, 8719206.0, 7751464.0, 6820384.0, 7786274.0, 7199576.0, 6446456.0, 7164579.0, 
+7690319.0, 8107202.0, 7462090.0, 8353962.0, 8807718.0, 5963658.0, 8163425.0, 6652851.0, 8169066.0, 6906018.0, 7448498.0, 8403353.0, 6499220.0, 9827668.0, 1.0370807E7, 8413234.0, 8979741.0, 6743719.0, 6583108.0, 6733404.0, 9203350.0, 8305284.0, 7661872.0, 8475391.0, 8638725.0, 7679995.0, 8961802.0, 6750314.0, 7049775.0, 8577580.0, 
+7412324.0, 8652125.0, 7961811.0, 9598288.0, 8296849.0, 6391772.0, 7240482.0, 7531594.0, 8110724.0, 7533868.0, 8155571.0, 8596878.0, 6925515.0, 7915918.0, 1.0572044E7, 8603488.0, 7693006.0, 7286678.0, 6399408.0, 6860014.0, 8027549.0, 7922416.0, 8053228.0, 9735395.0, 7584369.0, 8588126.0, 8653757.0, 7169521.0, 7682896.0, 8137235.0, 
+7988409.0, 7238778.0, 8449952.0, 7992084.0, 7262269.0, 5011760.0, 6432958.0, 7422948.0, 8648278.0, 7337408.0, 8462957.0, 7677222.0, 6397788.0, 7568297.0, 1.0797395E7, 7705063.0, 7146568.0, 6022723.0, 6370298.0, 7586299.0, 7452484.0, 7887693.0, 7307727.0, 9197385.0, 7726968.0, 8478492.0, 7601569.0, 6960883.0, 6522251.0, 7976344.0, 
+7572166.0, 7897218.0, 7706123.0, 7359858.0, 6988842.0, 5975477.0, 7234281.0, 8027665.0, 7471601.0, 7160694.0, 7249166.0, 8618544.0, 6644699.0, 8171915.0, 1.0497206E7, 8729802.0, 7174778.0, 5972218.0, 7216469.0, 7843533.0, 7628960.0, 7931021.0, 7962767.0, 9166492.0, 7547189.0, 8369468.0, 8488684.0, 5609773.0, 7562941.0, 8204473.0, 
+8857954.0, 8551958.0, 8909718.0, 9431684.0, 9556061.0, 6617423.0, 7827032.0, 8179745.0, 9353072.0, 7550842.0, 8121182.0, 8962388.0, 7937096.0, 8954704.0, 1.1085794E7, 9549551.0, 9145331.0, 7163225.0, 7988163.0, 8211966.0, 9352371.0, 9330003.0, 8532410.0, 1.0197366E7, 8931427.0, 8915845.0, 8823015.0, 7853048.0, 8044845.0, 9386048.0, 
+8545963.0, 7912549.0, 8606518.0, 8379764.0, 8351466.0, 6814749.0, 8057369.0, 8048780.0, 8451865.0, 7466527.0, 8749940.0, 8919463.0, 7276916.0, 8536482.0, 1.0911699E7, 9197448.0, 8560655.0, 7064115.0, 7860209.0, 8511883.0, 8654584.0, 9323289.0, 8981720.0, 9803015.0, 8598113.0, 8780796.0, 9135261.0, 6665333.0, 7324434.0, 8872122.0, 
+5946430.0, 6135788.0, 6591364.0, 6433251.0, 6632373.0, 4985963.0, 5769881.0, 4843727.0, 7021916.0, 5697194.0, 6385378.0, 6994046.0, 5502157.0, 7123974.0, 8365161.0, 6212258.0, 6104723.0, 5313031.0, 4845223.0, 5646055.0, 6129753.0, 6289476.0, 6051385.0, 7494259.0, 5723628.0, 6965055.0, 6172636.0, 5253106.0, 5610430.0, 6685980.0, 
+8055844.0, 8469174.0, 8170470.0, 8793113.0, 9859241.0, 7007325.0, 8137618.0, 8029717.0, 8997562.0, 7852580.0, 7740885.0, 9375326.0, 7883965.0, 1.0029182E7, 1.1346371E7, 9215599.0, 8636081.0, 7104102.0, 7496227.0, 8176023.0, 9732692.0, 8508678.0, 8257884.0, 1.0379885E7, 8448925.0, 9060668.0, 8836821.0, 7441640.0, 8726147.0, 9513821.0, 
+7367171.0, 7678838.0, 7804927.0, 8158615.0, 6673882.0, 6127379.0, 7575878.0, 6722516.0, 8300529.0, 6711008.0, 8389597.0, 8171405.0, 6196454.0, 7704372.0, 1.029698E7, 8112392.0, 7236981.0, 6508313.0, 6457042.0, 7280014.0, 7526900.0, 8231928.0, 7990796.0, 8184970.0, 7283106.0, 8214745.0, 8201658.0, 6708897.0, 6728783.0, 7449993.0, 
+7865362.0, 6776674.0, 8132061.0, 9041300.0, 7066772.0, 5445850.0, 7151522.0, 6942482.0, 7679044.0, 6487802.0, 8458847.0, 7314760.0, 6955102.0, 7314651.0, 9998347.0, 8897441.0, 7785211.0, 6248190.0, 6094040.0, 7118063.0, 7145775.0, 8373612.0, 7778499.0, 9104195.0, 6890059.0, 8603542.0, 8143136.0, 7583203.0, 6981314.0, 7304046.0, 
+7986730.0, 8495508.0, 8226132.0, 8837284.0, 8110164.0, 6270243.0, 7155084.0, 8144444.0, 7505249.0, 6776566.0, 8180893.0, 8341901.0, 6720764.0, 7941827.0, 1.0232075E7, 9099507.0, 8475362.0, 6245408.0, 7407245.0, 7953062.0, 7429359.0, 8415664.0, 8058703.0, 9250511.0, 7408836.0, 8633240.0, 8794298.0, 6612461.0, 6871055.0, 8223063.0, 
+7048151.0, 7129340.0, 7082981.0, 7489318.0, 8235538.0, 4945598.0, 7158417.0, 7404589.0, 7952446.0, 6524416.0, 7264108.0, 7881673.0, 6788833.0, 7675645.0, 1.0238341E7, 8484876.0, 7867557.0, 7037936.0, 7237519.0, 7346638.0, 7710289.0, 7883823.0, 7209172.0, 8844511.0, 7452039.0, 7340367.0, 7433870.0, 6571140.0, 7229344.0, 7904304.0, 
+8240448.0, 7954564.0, 8154706.0, 9504953.0, 8400499.0, 5460298.0, 7584126.0, 6871697.0, 9185194.0, 6905207.0, 9141475.0, 8494493.0, 7418418.0, 7753101.0, 1.0000234E7, 8633021.0, 7846515.0, 7199308.0, 6775263.0, 7435406.0, 8253684.0, 8758868.0, 8831361.0, 9095568.0, 8526076.0, 8528570.0, 8182811.0, 7299290.0, 7191919.0, 8226562.0, 
+6751777.0, 7186625.0, 6646412.0, 8018233.0, 6909389.0, 5658036.0, 6840978.0, 7190409.0, 7959774.0, 6192193.0, 6295944.0, 8365353.0, 6495593.0, 6989066.0, 9678769.0, 8422620.0, 6708233.0, 6122942.0, 6541236.0, 6976638.0, 7715128.0, 7027844.0, 7287427.0, 8765201.0, 6824683.0, 7411205.0, 7587931.0, 6447872.0, 6342510.0, 7582018.0, 
+7082585.0, 6197492.0, 6807726.0, 6956058.0, 6641216.0, 4830697.0, 5048238.0, 6053977.0, 6808066.0, 5552500.0, 6709804.0, 7175350.0, 6209976.0, 5950372.0, 8477306.0, 7412364.0, 5897445.0, 5540244.0, 5666371.0, 6696737.0, 6961106.0, 6862383.0, 6637593.0, 8019798.0, 5997948.0, 7597047.0, 6638311.0, 5646733.0, 6753680.0, 7600719.0, 
+7405626.0, 7342316.0, 6412193.0, 8347922.0, 7388131.0, 4709450.0, 6484686.0, 6422277.0, 7614878.0, 6155351.0, 8101524.0, 7056940.0, 5444306.0, 7010298.0, 9663947.0, 7786125.0, 6890705.0, 6006121.0, 6032720.0, 6508389.0, 7243995.0, 7137452.0, 6513236.0, 8338516.0, 7172679.0, 7934665.0, 8344129.0, 6707389.0, 6191989.0, 7659162.0, 
+8824351.0, 8499764.0, 7935349.0, 9362467.0, 7540129.0, 6218015.0, 8666871.0, 7431305.0, 9119473.0, 7093927.0, 8066413.0, 8889088.0, 6865107.0, 7703744.0, 1.1009442E7, 8749305.0, 8122317.0, 7493355.0, 6353037.0, 6661887.0, 8703986.0, 8305822.0, 8770358.0, 9415405.0, 8359360.0, 8392544.0, 8323587.0, 7316703.0, 6900664.0, 7998790.0, 
+8559320.0, 8232032.0, 8582628.0, 9561300.0, 8909146.0, 6399353.0, 7974575.0, 8670453.0, 9676934.0, 7602031.0, 9078286.0, 1.0045779E7, 7111219.0, 8996593.0, 1.226795E7, 1.0495147E7, 8627020.0, 7247946.0, 8214785.0, 8248879.0, 8942703.0, 1.0207892E7, 9159335.0, 9386478.0, 9122587.0, 9412550.0, 1.0407378E7, 8320858.0, 8412198.0, 9183005.0, 
+7864178.0, 7731246.0, 7874580.0, 8126602.0, 8217140.0, 6306880.0, 7598202.0, 6913447.0, 7964758.0, 7035041.0, 7879116.0, 8569671.0, 7028566.0, 9038832.0, 1.0641974E7, 8450936.0, 9082649.0, 6675630.0, 6481241.0, 6939335.0, 8501496.0, 8693928.0, 7876616.0, 8953343.0, 7470078.0, 7817750.0, 7845736.0, 7283306.0, 7144396.0, 8159051.0, 
+8244761.0, 8043437.0, 8160617.0, 7960796.0, 7638538.0, 5521627.0, 6770600.0, 6827077.0, 7424432.0, 7085102.0, 6703036.0, 8663556.0, 6008305.0, 8127122.0, 1.0757715E7, 7838981.0, 7320679.0, 6470974.0, 6395050.0, 7078761.0, 9051568.0, 8296696.0, 7669203.0, 8793438.0, 7935840.0, 8242858.0, 8167852.0, 6513437.0, 7222152.0, 8621155.0, 
+5398601.0, 5656258.0, 6127160.0, 6431306.0, 5861315.0, 4330490.0, 5807953.0, 5755300.0, 6320034.0, 6114599.0, 5885148.0, 6497254.0, 5450734.0, 6993714.0, 8061082.0, 6229394.0, 6511621.0, 4914814.0, 4902640.0, 5650877.0, 6261491.0, 6670406.0, 5878213.0, 7134964.0, 5872648.0, 6551681.0, 7116052.0, 5637658.0, 5610163.0, 6938664.0, 
+6665479.0, 6655902.0, 6361533.0, 6987969.0, 6216951.0, 4491075.0, 5339732.0, 5808102.0, 7720459.0, 6041092.0, 7229382.0, 7153949.0, 5369655.0, 6203304.0, 8545499.0, 6785740.0, 6520276.0, 5817279.0, 5606822.0, 6256946.0, 6558416.0, 6783016.0, 6327605.0, 7218378.0, 6631328.0, 6923787.0, 7005653.0, 5461050.0, 6094680.0, 7234228.0, 
+5843630.0, 6349173.0, 6588290.0, 6096008.0, 6187686.0, 4971317.0, 6130619.0, 5956329.0, 6069945.0, 6017854.0, 6689679.0, 6237127.0, 5164682.0, 6970236.0, 8278739.0, 6412665.0, 6644780.0, 4531485.0, 5404887.0, 5762443.0, 6496410.0, 7358530.0, 6524107.0, 7809916.0, 6432073.0, 6378435.0, 7274185.0, 5883336.0, 5290775.0, 7048857.0, 
+8593925.0, 7961767.0, 8292016.0, 8257014.0, 8765041.0, 5832016.0, 8184239.0, 8118105.0, 8933460.0, 7297129.0, 7909218.0, 9048344.0, 7497893.0, 8965430.0, 1.135426E7, 9530131.0, 8401874.0, 7390341.0, 7549933.0, 7675511.0, 8338916.0, 8618154.0, 8505674.0, 9483324.0, 8414926.0, 8193850.0, 9268065.0, 7355728.0, 8122626.0, 8739657.0, 
+7908996.0, 7506755.0, 7778220.0, 8175639.0, 5766252.0, 6284412.0, 7460913.0, 6975311.0, 7164714.0, 6767688.0, 7763452.0, 7215835.0, 6324251.0, 7271730.0, 9511219.0, 8140001.0, 7262476.0, 5372931.0, 6328202.0, 7443961.0, 7220668.0, 7721429.0, 8144112.0, 9294316.0, 6481768.0, 8506164.0, 8022424.0, 5875671.0, 5724007.0, 7793814.0, 
+7633150.0, 7688795.0, 7394176.0, 9147539.0, 8138372.0, 6018889.0, 6933383.0, 7053057.0, 8134616.0, 7254464.0, 7889703.0, 8526882.0, 7741309.0, 8523760.0, 1.0130337E7, 9570375.0, 8261785.0, 6437251.0, 6961202.0, 7470969.0, 8885321.0, 7952766.0, 8360734.0, 9775719.0, 7554078.0, 8847637.0, 8491061.0, 7347352.0, 7755601.0, 8960722.0, 
+7960421.0, 8470588.0, 8332189.0, 8444058.0, 8235295.0, 6839043.0, 7517756.0, 7415098.0, 8360872.0, 7000654.0, 8095598.0, 8937832.0, 5813282.0, 8713683.0, 1.0340755E7, 8893432.0, 8245456.0, 6941267.0, 7209275.0, 8630017.0, 9331110.0, 8897494.0, 7845643.0, 9026386.0, 8115773.0, 8895582.0, 8748333.0, 7461803.0, 7814024.0, 9201676.0
+};
diff --git a/benchmarks/dgemm/dgemm_gendata.scala b/benchmarks/dgemm/dgemm_gendata.scala
new file mode 100644 (file)
index 0000000..de2740b
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/env scala
+!#
+
+val size = args(0).toInt
+
+def print_matrix(name: String, rows: Int, cols: Int, data: Array[Double]) = {
+  println("const double " + name + "[DATA_SIZE*DATA_SIZE] = {")
+  for (i <- 0 until rows) {
+    println(data.slice(cols*i, cols*(i+1)).mkString(", ") + (if (i < rows-1) ", " else ""))
+  }
+  println("};")
+}
+def rand_matrix(rows: Int, cols: Int) = {
+  var r = new scala.util.Random
+  var m = new Array[Double](rows*cols)
+  for (i <- 0 until rows*cols)
+    m(i) = r.nextInt(1000)
+  m
+}
+def matmul(a: Array[Double], b: Array[Double], m: Int, n: Int, k: Int) = {
+  var c = new Array[Double](m*n)
+  for (i <- 0 until m)
+    for (j <- 0 until n)
+      for (l <- 0 until k)
+        c(i*n+j) += a(i*n+l)*b(l*k+j)
+  c
+}
+
+println("#define DATA_SIZE " + size)
+
+val a = rand_matrix(size, size)
+val b = rand_matrix(size, size)
+val c = matmul(a, b, size, size, size)
+
+print_matrix("input1_data", size, size, a)
+print_matrix("input2_data", size, size, b)
+print_matrix("verify_data", size, size, c)
diff --git a/benchmarks/dgemm/dgemm_main.c b/benchmarks/dgemm/dgemm_main.c
new file mode 100644 (file)
index 0000000..7c8ce7c
--- /dev/null
@@ -0,0 +1,205 @@
+//**************************************************************************
+// Double-precision general matrix multiplication benchmark
+//--------------------------------------------------------------------------
+
+//--------------------------------------------------------------------------
+// Macros
+
+// Set HOST_DEBUG to 1 if you are going to compile this for a host
+// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
+// to 0 if you are compiling with the smips-gcc toolchain.
+
+#ifndef HOST_DEBUG
+#define HOST_DEBUG 0
+#endif
+
+// Set PREALLOCATE to 1 if you want to preallocate the benchmark
+// function before starting stats. If you have instruction/data
+// caches and you don't want to count the overhead of misses, then
+// you will need to use preallocation.
+
+#ifndef PREALLOCATE
+#define PREALLOCATE 0
+#endif
+
+// Set SET_STATS to 1 if you want to carve out the piece that actually
+// does the computation.
+
+#ifndef SET_STATS
+#define SET_STATS 0
+#endif
+
+//--------------------------------------------------------------------------
+// Input/Reference Data
+
+#include "dataset1.h"
+
+//--------------------------------------------------------------------------
+// Helper functions
+
+int verify( long n, const double test[], const double correct[] )
+{
+  int i;
+  for ( i = 0; i < n; i++ ) {
+    if ( test[i] != correct[i] ) {
+      return 2;
+    }
+  }
+  return 1;
+}
+
+#if HOST_DEBUG
+#include <stdio.h>
+#include <stdlib.h>
+void printArray( char name[], long n, const double arr[] )
+{
+  int i;
+  printf( " %10s :", name );
+  for ( i = 0; i < n; i++ )
+    printf( " %8.1f ", arr[i] );
+  printf( "\n" );
+}
+#endif
+
+void finishTest( int toHostValue )
+{
+#if HOST_DEBUG
+  if ( toHostValue == 1 )
+    printf( "*** PASSED ***\n" );
+  else
+    printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
+  exit(0);
+#else
+  asm( "mtpcr %0, cr30" : : "r" (toHostValue) );
+  while ( 1 ) { }
+#endif
+}
+
+void setStats( int enable )
+{
+#if ( !HOST_DEBUG && SET_STATS )
+  asm( "mtpcr %0, cr10" : : "r" (enable) );
+#endif
+}
+
+//--------------------------------------------------------------------------
+// square_dgemm function
+
+void square_dgemm( long n0, const double a0[], const double b0[], double c0[] )
+{
+  long n = (n0+2)/3*3;
+  double a[n*n], b[n*n], c[n*n];
+
+  for (long i = 0; i < n0; i++)
+  {
+    long j;
+    for (j = 0; j < n0; j++)
+    {
+      a[i*n+j] = a0[i*n0+j];
+      b[i*n+j] = b0[j*n0+i];
+    }
+    for ( ; j < n; j++)
+    {
+      a[i*n+j] = b[i*n+j] = 0;
+    }
+  }
+  for (long i = n0; i < n; i++)
+    for (long j = 0; j < n; j++)
+      a[i*n+j] = b[i*n+j] = 0;
+
+  long i, j, k;
+  for (i = 0; i < n; i+=3)
+  {
+    for (j = 0; j < n; j+=3)
+    {
+      double *a0 = a + (i+0)*n, *b0 = b + (j+0)*n;
+      double *a1 = a + (i+1)*n, *b1 = b + (j+1)*n;
+      double *a2 = a + (i+2)*n, *b2 = b + (j+2)*n;
+
+      double s00 = 0, s01 = 0, s02 = 0;
+      double s10 = 0, s11 = 0, s12 = 0;
+      double s20 = 0, s21 = 0, s22 = 0;
+
+      while (a0 < a + (i+1)*n)
+      {
+        double a00 = a0[0], a01 = a0[1], a02 = a0[2];
+        double b00 = b0[0], b01 = b0[1], b02 = b0[2];
+        double a10 = a1[0], a11 = a1[1], a12 = a1[2];
+        double b10 = b1[0], b11 = b1[1], b12 = b1[2];
+        asm ("" ::: "memory");
+        double a20 = a2[0], a21 = a2[1], a22 = a2[2];
+        double b20 = b2[0], b21 = b2[1], b22 = b2[2];
+
+        s00 = a00*b00 + (a01*b01 + (a02*b02 + s00));
+        s01 = a00*b10 + (a01*b11 + (a02*b12 + s01));
+        s02 = a00*b20 + (a01*b21 + (a02*b22 + s02));
+        s10 = a10*b00 + (a11*b01 + (a12*b02 + s10));
+        s11 = a10*b10 + (a11*b11 + (a12*b12 + s11));
+        s12 = a10*b20 + (a11*b21 + (a12*b22 + s12));
+        s20 = a20*b00 + (a21*b01 + (a22*b02 + s20));
+        s21 = a20*b10 + (a21*b11 + (a22*b12 + s21));
+        s22 = a20*b20 + (a21*b21 + (a22*b22 + s22));
+
+        a0 += 3; b0 += 3;
+        a1 += 3; b1 += 3;
+        a2 += 3; b2 += 3;
+      }
+
+      c[(i+0)*n+j+0] = s00; c[(i+0)*n+j+1] = s01; c[(i+0)*n+j+2] = s02;
+      c[(i+1)*n+j+0] = s10; c[(i+1)*n+j+1] = s11; c[(i+1)*n+j+2] = s12;
+      c[(i+2)*n+j+0] = s20; c[(i+2)*n+j+1] = s21; c[(i+2)*n+j+2] = s22;
+    }
+  }
+
+  for (long i = 0; i < n0; i++)
+  {
+    long j;
+    for (j = 0; j < n0 - 2; j+=3)
+    {
+      c0[i*n0+j+0] = c[i*n+j+0];
+      c0[i*n0+j+1] = c[i*n+j+1];
+      c0[i*n0+j+2] = c[i*n+j+2];
+    }
+    for ( ; j < n0; j++)
+      c0[i*n0+j] = c[i*n+j];
+  }
+}
+
+//--------------------------------------------------------------------------
+// Main
+
+int main( int argc, char* argv[] )
+{
+  double results_data[DATA_SIZE*DATA_SIZE];
+
+  // Output the input array
+
+#if HOST_DEBUG
+  printArray( "input1", DATA_SIZE*DATA_SIZE, input1_data );
+  printArray( "input2", DATA_SIZE*DATA_SIZE, input2_data );
+  printArray( "verify", DATA_SIZE*DATA_SIZE, verify_data );
+#endif
+
+  // If needed we preallocate everything in the caches
+
+#if PREALLOCATE
+  square_dgemm( DATA_SIZE, input1_data, input2_data, results_data );
+#endif
+
+  // Do the dgemm
+
+  setStats(1);
+  square_dgemm( DATA_SIZE, input1_data, input2_data, results_data );
+  setStats(0);
+
+  // Print out the results
+
+#if HOST_DEBUG
+  printArray( "results", DATA_SIZE*DATA_SIZE, results_data );
+#endif
+
+  // Check the results
+
+  finishTest(verify( DATA_SIZE*DATA_SIZE, results_data, verify_data ));
+
+}
diff --git a/benchmarks/dhrystone/bmark.mk b/benchmarks/dhrystone/bmark.mk
new file mode 100644 (file)
index 0000000..6e45706
--- /dev/null
@@ -0,0 +1,31 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include
+# the benchmark name as a prefix so that they are unique.
+#
+
+dhrystone_c_src = \
+       dhrystone_main.c \
+       dhrystone.c \
+
+dhrystone_riscv_src = \
+       crt.S \
+
+dhrystone_c_objs     = $(patsubst %.c, %.o, $(dhrystone_c_src))
+dhrystone_riscv_objs = $(patsubst %.S, %.o, $(dhrystone_riscv_src))
+
+dhrystone_host_bin = dhrystone.host
+$(dhrystone_host_bin): $(dhrystone_c_src)
+       $(HOST_COMP) $^ -o $(dhrystone_host_bin)
+
+dhrystone_riscv_bin = dhrystone.riscv
+$(dhrystone_riscv_bin): $(dhrystone_c_objs) $(dhrystone_riscv_objs)
+       $(RISCV_LINK) $(dhrystone_c_objs) $(dhrystone_riscv_objs) \
+    -o $(dhrystone_riscv_bin) $(RISCV_LINK_OPTS)
+
+junk += $(dhrystone_c_objs) $(dhrystone_riscv_objs) \
+        $(dhrystone_host_bin) $(dhrystone_riscv_bin)
diff --git a/benchmarks/dhrystone/dhrystone.c b/benchmarks/dhrystone/dhrystone.c
new file mode 100644 (file)
index 0000000..abc45d4
--- /dev/null
@@ -0,0 +1,160 @@
+#include "dhrystone.h"
+
+#ifndef REG
+#define REG
+        /* REG becomes defined as empty */
+        /* i.e. no register variables   */
+#else
+#undef REG
+#define REG register
+#endif
+
+extern  int     Int_Glob;
+extern  char    Ch_1_Glob;
+
+
+void Proc_6(Enumeration Enum_Val_Par, Enumeration* Enum_Ref_Par)
+/*********************************/
+    /* executed once */
+    /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
+{
+  *Enum_Ref_Par = Enum_Val_Par;
+  if (! Func_3 (Enum_Val_Par))
+    /* then, not executed */
+    *Enum_Ref_Par = Ident_4;
+  switch (Enum_Val_Par)
+  {
+    case Ident_1: 
+      *Enum_Ref_Par = Ident_1;
+      break;
+    case Ident_2: 
+      if (Int_Glob > 100)
+        /* then */
+      *Enum_Ref_Par = Ident_1;
+      else *Enum_Ref_Par = Ident_4;
+      break;
+    case Ident_3: /* executed */
+      *Enum_Ref_Par = Ident_2;
+      break;
+    case Ident_4: break;
+    case Ident_5: 
+      *Enum_Ref_Par = Ident_3;
+      break;
+  } /* switch */
+} /* Proc_6 */
+
+
+void Proc_7(int Int_1_Par_Val, int Int_2_Par_Val, int* Int_Par_Ref)
+/**********************************************/
+    /* executed three times                                      */ 
+    /* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */
+    /*                  Int_Par_Ref becomes 7                    */
+    /* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
+    /*                  Int_Par_Ref becomes 17                   */
+    /* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
+    /*                  Int_Par_Ref becomes 18                   */
+{
+  One_Fifty Int_Loc;
+
+  Int_Loc = Int_1_Par_Val + 2;
+  *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
+} /* Proc_7 */
+
+
+void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val)
+/*********************************************************************/
+    /* executed once      */
+    /* Int_Par_Val_1 == 3 */
+    /* Int_Par_Val_2 == 7 */
+{
+  REG One_Fifty Int_Index;
+  REG One_Fifty Int_Loc;
+
+  Int_Loc = Int_1_Par_Val + 5;
+  Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
+  Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
+  Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
+  for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
+    Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
+  Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
+  Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
+  Int_Glob = 5;
+} /* Proc_8 */
+
+
+Enumeration Func_1 (char Ch_1_Par_Val, char Ch_2_Par_Val)
+/*************************************************/
+    /* executed three times                                         */
+    /* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */
+    /* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */
+    /* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */
+{
+  Capital_Letter        Ch_1_Loc;
+  Capital_Letter        Ch_2_Loc;
+
+  Ch_1_Loc = Ch_1_Par_Val;
+  Ch_2_Loc = Ch_1_Loc;
+  if (Ch_2_Loc != Ch_2_Par_Val)
+    /* then, executed */
+    return (Ident_1);
+  else  /* not executed */
+  {
+    Ch_1_Glob = Ch_1_Loc;
+    return (Ident_2);
+   }
+} /* Func_1 */
+
+
+Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
+/*************************************************/
+    /* executed once */
+    /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
+    /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
+{
+  REG One_Thirty        Int_Loc;
+      Capital_Letter    Ch_Loc;
+
+  Int_Loc = 2;
+  while (Int_Loc <= 2) /* loop body executed once */
+    if (Func_1 (Str_1_Par_Ref[Int_Loc],
+                Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
+      /* then, executed */
+    {
+      Ch_Loc = 'A';
+      Int_Loc += 1;
+    } /* if, while */
+  if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
+    /* then, not executed */
+    Int_Loc = 7;
+  if (Ch_Loc == 'R')
+    /* then, not executed */
+    return (true);
+  else /* executed */
+  {
+    if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
+      /* then, not executed */
+    {
+      Int_Loc += 7;
+      Int_Glob = Int_Loc;
+      return (true);
+    }
+    else /* executed */
+      return (false);
+  } /* if Ch_Loc */
+} /* Func_2 */
+
+
+Boolean Func_3(Enumeration Enum_Par_Val)
+/***************************/
+    /* executed once        */
+    /* Enum_Par_Val == Ident_3 */
+{
+  Enumeration Enum_Loc;
+
+  Enum_Loc = Enum_Par_Val;
+  if (Enum_Loc == Ident_3)
+    /* then, executed */
+    return (true);
+  else /* not executed */
+    return (false);
+} /* Func_3 */
diff --git a/benchmarks/dhrystone/dhrystone.h b/benchmarks/dhrystone/dhrystone.h
new file mode 100644 (file)
index 0000000..8abb874
--- /dev/null
@@ -0,0 +1,491 @@
+#ifndef _DHRYSTONE_H
+#define _DHRYSTONE_H
+
+/****************** "DHRYSTONE" Benchmark Program ***************************/
+#define Version "C, Version 2.2"
+/*  File:       dhry_1.c (part 2 of 3)
+ *  Author:     Reinhold P. Weicker
+ *              Siemens Nixdorf, Paderborn/Germany
+ *              weicker@specbench.org
+ *  Date:       May 25, 1988
+ *  Modified:  Steven Pemberton, CWI, Amsterdam; Steven.Pemberton@cwi.nl
+ *  Date:       October, 1993; March 1995
+ *              Included both files into one source, that gets compiled
+ *              in two passes. Made program auto-compiling, and auto-running,
+ *              and generally made it much easier to use.
+ *
+ *              Original Version (in Ada) published in
+ *              "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
+ *              pp. 1013 - 1030, together with the statistics
+ *              on which the distribution of statements etc. is based.
+ *
+ *              In this C version, the following C library functions are used:
+ *              - strcpy, strcmp (inside the measurement loop)
+ *              - printf, scanf (outside the measurement loop)
+ *              In addition, Berkeley UNIX system calls "times ()" or "time ()"
+ *              are used for execution time measurement. For measurements
+ *              on other systems, these calls have to be changed.
+ *
+ *  Collection of Results:
+ *              Reinhold Weicker (address see above) and
+ *              
+ *              Rick Richardson
+ *              PC Research. Inc.
+ *              94 Apple Orchard Drive
+ *              Tinton Falls, NJ 07724
+ *                      Phone:  (201) 389-8963 (9-17 EST)               
+ *                      Usenet: ...!uunet!pcrat!rick
+ *
+ *      Please send results to Rick Richardson and/or Reinhold Weicker.
+ *      Complete information should be given on hardware and software used.
+ *      Hardware information includes: Machine type, CPU, type and size
+ *      of caches; for microprocessors: clock frequency, memory speed
+ *      (number of wait states).
+ *      Software information includes: Compiler (and runtime library)
+ *      manufacturer and version, compilation switches, OS version.
+ *      The Operating System version may give an indication about the compiler;
+ *      Dhrystone itself performs no OS calls in the measurement loop.
+ *
+ *      The complete output generated by the program should be mailed
+ *      such that at least some checks for correctness can be made.
+ *
+ ***************************************************************************
+ *
+ * Defines:     The following "Defines" are possible:
+ *      -DREG          (default: Not defined)
+ *              As an approximation to what an average C programmer
+ *              might do, causes the "register" storage class to be applied
+ *              - for local variables, if they are used (dynamically)
+ *                five or more times
+ *              - for parameters if they are used (dynamically)
+ *                six or more times
+ *              Note that an optimal "register" strategy is
+ *              compiler-dependent, and that "register" declarations
+ *              do not necessarily lead to faster execution.
+ *      -DNOSTRUCTASSIGN        (default: Not defined)
+ *              Define if the C compiler does not support
+ *              assignment of structures.
+ *      -DNOENUMS               (default: Not defined)
+ *              Define if the C compiler does not support
+ *              enumeration types.
+ *      -DTIMES                 (default)
+ *      -DTIME
+ *              The "times" function of UNIX (returning process times)
+ *              or the "time" function (returning wallclock time)
+ *              is used for measurement. 
+ *              For single user machines, "time ()" is adequate. For
+ *              multi-user machines where you cannot get single-user
+ *              access, use the "times ()" function. If you have
+ *              neither, use a stopwatch in the dead of night.
+ *              "printf"s are provided marking the points "Start Timer"
+ *              and "Stop Timer". DO NOT use the UNIX "time(1)"
+ *              command, as this will measure the total time to
+ *              run this program, which will (erroneously) include
+ *              the time to allocate storage (malloc) and to perform
+ *              the initialization.
+ *      -DHZ=nnn
+ *              In Berkeley UNIX, the function "times" returns process
+ *              time in 1/HZ seconds, with HZ = 60 for most systems.
+ *              CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY
+ *              A VALUE.
+ *
+ ***************************************************************************
+ *
+ *  History:   Version C/2.1 was made for two reasons:
+ *
+ *     1) There was an obvious need for a common C version of
+ *      Dhrystone, since C is at present the most popular system
+ *      programming language for the class of processors
+ *      (microcomputers, minicomputers) where Dhrystone is used most.
+ *      There should be, as far as possible, only one C version of
+ *      Dhrystone such that results can be compared without
+ *      restrictions. In the past, the C versions distributed
+ *      by Rick Richardson (Version 1.1) and by Reinhold Weicker
+ *      had small (though not significant) differences.
+ *
+ *      2) As far as it is possible without changes to the Dhrystone
+ *      statistics, optimizing compilers should be prevented from
+ *      removing significant statements.
+ *
+ *      This C version has been developed in cooperation with
+ *      Rick Richardson (Tinton Falls, NJ), it incorporates many
+ *      ideas from the "Version 1.1" distributed previously by
+ *      him over the UNIX network Usenet.
+ *      I also thank Chaim Benedelac (National Semiconductor),
+ *      David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
+ *      Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
+ *      for their help with comments on earlier versions of the
+ *      benchmark.
+ *
+ *  Changes:    In the initialization part, this version follows mostly
+ *      Rick Richardson's version distributed via Usenet, not the
+ *      version distributed earlier via floppy disk by Reinhold Weicker.
+ *      As a concession to older compilers, names have been made
+ *      unique within the first 8 characters.
+ *      Inside the measurement loop, this version follows the
+ *      version previously distributed by Reinhold Weicker.
+ *
+ *      At several places in the benchmark, code has been added,
+ *      but within the measurement loop only in branches that 
+ *      are not executed. The intention is that optimizing compilers
+ *      should be prevented from moving code out of the measurement
+ *      loop, or from removing code altogether. Since the statements
+ *      that are executed within the measurement loop have NOT been
+ *      changed, the numbers defining the "Dhrystone distribution"
+ *      (distribution of statements, operand types and locality)
+ *      still hold. Except for sophisticated optimizing compilers,
+ *      execution times for this version should be the same as
+ *      for previous versions.
+ *
+ *      Since it has proven difficult to subtract the time for the
+ *      measurement loop overhead in a correct way, the loop check
+ *      has been made a part of the benchmark. This does have
+ *      an impact - though a very minor one - on the distribution
+ *      statistics which have been updated for this version.
+ *
+ *      All changes within the measurement loop are described
+ *      and discussed in the companion paper "Rationale for
+ *      Dhrystone version 2".
+ *
+ *      Because of the self-imposed limitation that the order and
+ *      distribution of the executed statements should not be
+ *      changed, there are still cases where optimizing compilers
+ *      may not generate code for some statements. To a certain
+ *      degree, this is unavoidable for small synthetic benchmarks.
+ *      Users of the benchmark are advised to check code listings
+ *      whether code is generated for all statements of Dhrystone.
+ *
+ *      Version 2.1 is identical to version 2.0 distributed via
+ *      the UNIX network Usenet in March 1988 except that it corrects
+ *      some minor deficiencies that were found by users of version 2.0.
+ *      The only change within the measurement loop is that a
+ *      non-executed "else" part was added to the "if" statement in
+ *      Func_3, and a non-executed "else" part removed from Proc_3.
+ *
+ * Version C/2.2, Steven Pemberton, October 1993
+ *     Functionally, identical to version 2.2; the changes are in
+ *     how you compile and use it:
+ *     - Everything is in one file now, but compiled in 2 passes
+ *     - Compile (and run) by running the file through the shell: 'sh dhry.c"
+ *     - Uses the system definition of HZ if one can be found
+ *     - HZ must be defined, otherwise it won't compile (no defaults here)
+ *     - The (uninteresting) output is printed to stderr (dhry2 > /dev/null)
+ *     - The number of loops is passed as a parameter, rather than read
+ *       (dhry2 500000)
+ *     - If the number of loops is insufficient to get a good result,
+ *       it repeats it with loops*10 until it is enough (rather than just
+ *       stopping)
+ *     - Output says which sort of clock it is using, and the HZ value
+ *     - You can use -DREG instead of the -DREG=register of previous versions
+ *     - Some stylistic cleanups.
+ *             
+ ***************************************************************************
+ *
+ *  Compilation model and measurement (IMPORTANT):
+ *
+ *  The following "ground rules" apply for measurements:
+ *  - Separate compilation
+ *  - No procedure merging
+ *  - Otherwise, compiler optimizations are allowed but should be indicated
+ *  - Default results are those without register declarations
+ *  See the companion paper "Rationale for Dhrystone Version 2" for a more
+ *  detailed discussion of these ground rules.
+ *
+ *  For 16-Bit processors (e.g. 80186, 80286), times for all compilation
+ *  models ("small", "medium", "large" etc.) should be given if possible,
+ *  together with a definition of these models for the compiler system used.
+ *
+ **************************************************************************
+ *
+ *  Dhrystone (C version) statistics:
+ *
+ *  [Comment from the first distribution, updated for version 2.
+ *   Note that because of language differences, the numbers are slightly
+ *   different from the Ada version.]
+ *
+ *  The following program contains statements of a high level programming
+ *  language (here: C) in a distribution considered representative:           
+ *
+ *    assignments                  52 (51.0 %)
+ *    control statements           33 (32.4 %)
+ *    procedure, function calls    17 (16.7 %)
+ *
+ *  103 statements are dynamically executed. The program is balanced with
+ *  respect to the three aspects:                                             
+ *
+ *    - statement type
+ *    - operand type
+ *    - operand locality
+ *         operand global, local, parameter, or constant.                     
+ *
+ *  The combination of these three aspects is balanced only approximately.    
+ *
+ *  1. Statement Type:                                                        
+ *  -----------------             number
+ *
+ *     V1 = V2                     9
+ *       (incl. V1 = F(..)
+ *     V = Constant               12
+ *     Assignment,                 7
+ *       with array element
+ *     Assignment,                 6
+ *       with record component
+ *                                --
+ *                                34       34
+ *
+ *     X = Y +|-|"&&"|"|" Z        5
+ *     X = Y +|-|"==" Constant     6
+ *     X = X +|- 1                 3
+ *     X = Y *|/ Z                 2
+ *     X = Expression,             1
+ *           two operators
+ *     X = Expression,             1
+ *           three operators
+ *                                --
+ *                                18       18
+ *
+ *     if ....                    14
+ *       with "else"      7
+ *       without "else"   7
+ *           executed        3
+ *           not executed    4
+ *     for ...                     7  |  counted every time
+ *     while ...                   4  |  the loop condition
+ *     do ... while                1  |  is evaluated
+ *     switch ...                  1
+ *     break                       1
+ *     declaration with            1
+ *       initialization
+ *                                --
+ *                                34       34
+ *
+ *     P (...)  procedure call    11
+ *       user procedure      10
+ *       library procedure    1
+ *     X = F (...)
+ *             function  call      6
+ *       user function        5                                         
+ *       library function     1                                               
+ *                                --                                          
+ *                                17       17
+ *                                        ---
+ *                                        103
+ *
+ *    The average number of parameters in procedure or function calls
+ *    is 1.82 (not counting the function values aX *
+ *
+ *  2. Operators
+ *  ------------
+ *                          number    approximate
+ *                                    percentage
+ *
+ *    Arithmetic             32          50.8                                 
+ *
+ *       +                     21          33.3                              
+ *       -                      7          11.1                              
+ *       *                      3           4.8
+ *       / (int div)            1           1.6
+ *
+ *    Comparison             27           42.8
+ *
+ *       ==                     9           14.3
+ *       /=                     4            6.3
+ *       >                      1            1.6
+ *       <                      3            4.8
+ *       >=                     1            1.6
+ *       <=                     9           14.3
+ *
+ *    Logic                   4            6.3
+ *
+ *       && (AND-THEN)          1            1.6
+ *       |  (OR)                1            1.6
+ *       !  (NOT)               2            3.2
+ * 
+ *                           --          -----
+ *                           63          100.1
+ *
+ *
+ *  3. Operand Type (counted once per operand reference):
+ *  ---------------
+ *                          number    approximate
+ *                                    percentage
+ *
+ *     Integer               175        72.3 %
+ *     Character              45        18.6 %
+ *     Pointer                12         5.0 %
+ *     String30                6         2.5 %
+ *     Array                   2         0.8 %
+ *     Record                  2         0.8 %
+ *                           ---       -------
+ *                           242       100.0 %
+ *
+ *  When there is an access path leading to the final operand (e.g. a record
+ *  component), only the final data type on the access path is counted.       
+ *
+ *
+ *  4. Operand Locality:                                                      
+ *  -------------------
+ *                                number    approximate
+ *                                          percentage
+ *
+ *     local variable              114        47.1 %
+ *     global variable              22         9.1 %
+ *     parameter                    45        18.6 %
+ *        value                        23         9.5 %
+ *        reference                    22         9.1 %
+ *     function result               6         2.5 %
+ *     constant                     55        22.7 %
+ *                                 ---       -------
+ *                                 242       100.0 %
+ *
+ *  The program does not compute anything meaningful, but it is syntactically
+ *  and semantically correct. All variables have a value assigned to them
+ *  before they are used as a source operand.
+ *
+ *  There has been no explicit effort to account for the effects of a
+ *  cache, or to balance the use of long or short displacements for code or
+ *  data.
+ *
+ ***************************************************************************
+ */
+
+/* Compiler and system dependent definitions: */
+
+/* variables for time measurement: */
+
+#ifdef TIME
+
+#define CLOCK_TYPE "time()"
+#undef HZ
+#define HZ     (1) /* time() returns time in seconds */
+extern long     time(); /* see library function "time"  */
+#define Too_Small_Time 2 /* Measurements should last at least 2 seconds */
+#define Start_Timer() Begin_Time = time ( (long *) 0)
+#define Stop_Timer()  End_Time   = time ( (long *) 0)
+
+#else
+
+#ifdef MSC_CLOCK /* Use Microsoft C hi-res clock */
+
+#undef HZ
+#undef TIMES
+#include <time.h>
+#define HZ     CLK_TCK
+#define CLOCK_TYPE "MSC clock()"
+extern clock_t clock();
+#define Too_Small_Time (2*HZ)
+#define Start_Timer() Begin_Time = clock()
+#define Stop_Timer()  End_Time   = clock()
+
+#elif defined(__riscv)
+
+#define HZ 976563
+#define Too_Small_Time 50
+#define rdcycle() ({ \
+  long __x; \
+  asm volatile("rdcycle %0; srl %0, %0, 10" : "=r"(__x)); \
+  __x; })
+#define CLOCK_TYPE "rdcycle()"
+#define Start_Timer() Begin_Time = rdcycle()
+#define Stop_Timer() End_Time = rdcycle()
+
+#else
+                /* Use times(2) time function unless    */
+                /* explicitly defined otherwise         */
+#define CLOCK_TYPE "times()"
+#include <sys/types.h>
+#include <sys/times.h>
+#ifndef HZ     /* Added by SP 900619 */
+#include <sys/param.h> /* If your system doesn't have this, use -DHZ=xxx */
+#else
+       *** You must define HZ!!! ***
+#endif /* HZ */
+#ifndef PASS2
+struct tms      time_info;
+#endif
+/*extern  int     times ();*/
+                /* see library function "times" */
+#define Too_Small_Time (2*HZ)
+                /* Measurements should last at least about 2 seconds */
+#define Start_Timer() times(&time_info); Begin_Time=(long)time_info.tms_utime
+#define Stop_Timer()  times(&time_info); End_Time = (long)time_info.tms_utime
+
+#endif /* MSC_CLOCK */
+#endif /* TIME */
+
+
+#define Mic_secs_Per_Second     1000000.0
+#define NUMBER_OF_RUNS         500 /* Default number of runs */
+
+#ifdef  NOSTRUCTASSIGN
+#define structassign(d, s)      memcpy(&(d), &(s), sizeof(d))
+#else
+#define structassign(d, s)      d = s
+#endif
+
+#ifdef  NOENUM
+#define Ident_1 0
+#define Ident_2 1
+#define Ident_3 2
+#define Ident_4 3
+#define Ident_5 4
+  typedef int   Enumeration;
+#else
+  typedef       enum    {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
+                Enumeration;
+#endif
+        /* for boolean and enumeration types in Ada, Pascal */
+
+/* General definitions: */
+
+#include <stdio.h>
+#include <string.h>
+                /* for strcpy, strcmp */
+
+#define Null 0 
+                /* Value of a Null pointer */
+#define true  1
+#define false 0
+
+typedef int     One_Thirty;
+typedef int     One_Fifty;
+typedef char    Capital_Letter;
+typedef int     Boolean;
+typedef char    Str_30 [31];
+typedef int     Arr_1_Dim [50];
+typedef int     Arr_2_Dim [50] [50];
+
+typedef struct record 
+    {
+    struct record *Ptr_Comp;
+    Enumeration    Discr;
+    union {
+          struct {
+                  Enumeration Enum_Comp;
+                  int         Int_Comp;
+                  char        Str_Comp [31];
+                  } var_1;
+          struct {
+                  Enumeration E_Comp_2;
+                  char        Str_2_Comp [31];
+                  } var_2;
+          struct {
+                  char        Ch_1_Comp;
+                  char        Ch_2_Comp;
+                  } var_3;
+          } variant;
+      } Rec_Type, *Rec_Pointer;
+
+void Proc_1(Rec_Pointer Ptr_Val_Par);
+void Proc_2(int* Int_Par_Ref);
+void Proc_3(Rec_Pointer* Ptr_Ref_Par);
+void Proc_4();
+void Proc_5();
+void Proc_6(Enumeration Enum_Val_Par, Enumeration* Enum_Ref_Par);
+void Proc_7(int Int_1_Par_Val, int Int_2_Par_Val, int* Int_Par_Ref);
+void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val);
+Enumeration Func_1 (char Ch_1_Par_Val, char Ch_2_Par_Val);
+Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
+Boolean Func_3(Enumeration Enum_Par_Val);
+
+#endif
diff --git a/benchmarks/dhrystone/dhrystone_main.c b/benchmarks/dhrystone/dhrystone_main.c
new file mode 100644 (file)
index 0000000..7e8c6af
--- /dev/null
@@ -0,0 +1,400 @@
+//**************************************************************************
+// Dhrystone bencmark
+//--------------------------------------------------------------------------
+//
+// This is the classic Dhrystone synthetic integer benchmark.
+// You should not change anything except the HOST_DEBUG and
+// PREALLOCATE macros for your timing run.
+
+#include "dhrystone.h"
+
+//--------------------------------------------------------------------------
+// Macros
+
+// Set HOST_DEBUG to 1 if you are going to compile this for a host
+// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
+// to 0 if you are compiling with the smips-gcc toolchain.
+
+#ifndef HOST_DEBUG
+#define HOST_DEBUG 0
+#endif
+
+// Set PREALLOCATE to 1 if you want to preallocate the benchmark
+// function before starting stats. If you have instruction/data
+// caches and you don't want to count the overhead of misses, then
+// you will need to use preallocation.
+
+#ifndef PREALLOCATE
+#define PREALLOCATE 0
+#endif
+
+// Set SET_STATS to 1 if you want to carve out the piece that actually
+// does the computation.
+
+#ifndef SET_STATS
+#define SET_STATS 0
+#endif
+
+#if HOST_DEBUG
+# define do_fprintf fprintf
+#else
+int __attribute__((noinline)) do_fprintf(FILE* f, const char* str, ...)
+{
+  return 0;
+}
+#endif
+
+void finishTest( int toHostValue )
+{
+#if HOST_DEBUG
+  if ( toHostValue == 1 )
+    printf( "*** PASSED ***\n" );
+  else
+    printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
+  exit(0);
+#else
+  asm( "mtpcr %0, cr30" : : "r" (toHostValue) );
+  while ( 1 ) { }
+#endif
+}
+
+void setStats( int enable )
+{
+#if ( !HOST_DEBUG && SET_STATS )
+  asm( "mtpcr %0, cr10" : : "r" (enable) );
+#endif
+}
+
+#include <alloca.h>
+
+/* Global Variables: */
+
+Rec_Pointer     Ptr_Glob,
+                Next_Ptr_Glob;
+int             Int_Glob;
+Boolean         Bool_Glob;
+char            Ch_1_Glob,
+                Ch_2_Glob;
+int             Arr_1_Glob [50];
+int             Arr_2_Glob [50] [50];
+
+#ifndef REG
+        Boolean Reg = false;
+#define REG
+        /* REG becomes defined as empty */
+        /* i.e. no register variables   */
+#else
+        Boolean Reg = true;
+#undef REG
+#define REG register
+#endif
+
+Boolean                Done;
+
+long            Begin_Time,
+                End_Time,
+                User_Time;
+float           Microseconds,
+                Dhrystones_Per_Second;
+
+/* end of variables for time measurement */
+
+
+int main (int argc, char** argv)
+/*****/
+  /* main program, corresponds to procedures        */
+  /* Main and Proc_0 in the Ada version             */
+{
+        One_Fifty       Int_1_Loc;
+  REG   One_Fifty       Int_2_Loc;
+        One_Fifty       Int_3_Loc;
+  REG   char            Ch_Index;
+        Enumeration     Enum_Loc;
+        Str_30          Str_1_Loc;
+        Str_30          Str_2_Loc;
+  REG   int             Run_Index;
+  REG   int             Number_Of_Runs;
+
+  /* Arguments */
+#if HOST_DEBUG
+  if (argc > 2)
+  {
+     do_fprintf (stdout, "Usage: %s [number of loops]\n", argv[0]);
+     exit (1);
+  }
+  if (argc == 2)
+  {
+     Number_Of_Runs = atoi (argv[1]);
+  } else
+#endif
+  {
+     Number_Of_Runs = NUMBER_OF_RUNS;
+  }
+  if (Number_Of_Runs <= 0)
+  {
+     Number_Of_Runs = NUMBER_OF_RUNS;
+  }
+
+  /* Initializations */
+
+  Next_Ptr_Glob = (Rec_Pointer) alloca (sizeof (Rec_Type));
+  Ptr_Glob = (Rec_Pointer) alloca (sizeof (Rec_Type));
+
+  Ptr_Glob->Ptr_Comp                    = Next_Ptr_Glob;
+  Ptr_Glob->Discr                       = Ident_1;
+  Ptr_Glob->variant.var_1.Enum_Comp     = Ident_3;
+  Ptr_Glob->variant.var_1.Int_Comp      = 40;
+  strcpy (Ptr_Glob->variant.var_1.Str_Comp, 
+          "DHRYSTONE PROGRAM, SOME STRING");
+  strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
+
+  Arr_2_Glob [8][7] = 10;
+        /* Was missing in published program. Without this statement,    */
+        /* Arr_2_Glob [8][7] would have an undefined value.             */
+        /* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */
+        /* overflow may occur for this array element.                   */
+
+#if HOST_DEBUG
+  do_fprintf (stdout, "\n");
+  do_fprintf (stdout, "Dhrystone Benchmark, Version %s\n", Version);
+  if (Reg)
+  {
+    do_fprintf (stdout, "Program compiled with 'register' attribute\n");
+  }
+  else
+  {
+    do_fprintf (stdout, "Program compiled without 'register' attribute\n");
+  }
+  do_fprintf (stdout, "Using %s, HZ=%d\n", CLOCK_TYPE, HZ);
+  do_fprintf (stdout, "\n");
+#endif
+
+  Done = false;
+  while (!Done) {
+#if HOST_DEBUG
+    do_fprintf (stdout, "Trying %d runs through Dhrystone:\n", Number_Of_Runs);
+#endif
+
+    /***************/
+    /* Start timer */
+    /***************/
+
+    Start_Timer();
+    setStats(1);
+
+    for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
+    {
+
+      Proc_5();
+      Proc_4();
+       /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
+      Int_1_Loc = 2;
+      Int_2_Loc = 3;
+      strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
+      Enum_Loc = Ident_2;
+      Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
+       /* Bool_Glob == 1 */
+      while (Int_1_Loc < Int_2_Loc)  /* loop body executed once */
+      {
+       Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
+         /* Int_3_Loc == 7 */
+       Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
+         /* Int_3_Loc == 7 */
+       Int_1_Loc += 1;
+      } /* while */
+       /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+      Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
+       /* Int_Glob == 5 */
+      Proc_1 (Ptr_Glob);
+      for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
+                              /* loop body executed twice */
+      {
+       if (Enum_Loc == Func_1 (Ch_Index, 'C'))
+           /* then, not executed */
+         {
+         Proc_6 (Ident_1, &Enum_Loc);
+         strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
+         Int_2_Loc = Run_Index;
+         Int_Glob = Run_Index;
+         }
+      }
+       /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+      Int_2_Loc = Int_2_Loc * Int_1_Loc;
+      Int_1_Loc = Int_2_Loc / Int_3_Loc;
+      Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
+       /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
+      Proc_2 (&Int_1_Loc);
+       /* Int_1_Loc == 5 */
+
+    } /* loop "for Run_Index" */
+
+    /**************/
+    /* Stop timer */
+    /**************/
+
+    setStats(0);
+    Stop_Timer();
+
+    User_Time = End_Time - Begin_Time;
+
+    if (User_Time < Too_Small_Time)
+    {
+      do_fprintf (stdout, "Measured time too small to obtain meaningful results\n");
+      Number_Of_Runs = Number_Of_Runs * 10;
+      do_fprintf (stdout, "\n");
+    } else Done = true;
+  }
+
+  do_fprintf (stderr, "Final values of the variables used in the benchmark:\n");
+  do_fprintf (stderr, "\n");
+  do_fprintf (stderr, "Int_Glob:            %d\n", Int_Glob);
+  do_fprintf (stderr, "        should be:   %d\n", 5);
+  do_fprintf (stderr, "Bool_Glob:           %d\n", Bool_Glob);
+  do_fprintf (stderr, "        should be:   %d\n", 1);
+  do_fprintf (stderr, "Ch_1_Glob:           %c\n", Ch_1_Glob);
+  do_fprintf (stderr, "        should be:   %c\n", 'A');
+  do_fprintf (stderr, "Ch_2_Glob:           %c\n", Ch_2_Glob);
+  do_fprintf (stderr, "        should be:   %c\n", 'B');
+  do_fprintf (stderr, "Arr_1_Glob[8]:       %d\n", Arr_1_Glob[8]);
+  do_fprintf (stderr, "        should be:   %d\n", 7);
+  do_fprintf (stderr, "Arr_2_Glob[8][7]:    %d\n", Arr_2_Glob[8][7]);
+  do_fprintf (stderr, "        should be:   Number_Of_Runs + 10\n");
+  do_fprintf (stderr, "Ptr_Glob->\n");
+  do_fprintf (stderr, "  Ptr_Comp:          %d\n", (int) Ptr_Glob->Ptr_Comp);
+  do_fprintf (stderr, "        should be:   (implementation-dependent)\n");
+  do_fprintf (stderr, "  Discr:             %d\n", Ptr_Glob->Discr);
+  do_fprintf (stderr, "        should be:   %d\n", 0);
+  do_fprintf (stderr, "  Enum_Comp:         %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
+  do_fprintf (stderr, "        should be:   %d\n", 2);
+  do_fprintf (stderr, "  Int_Comp:          %d\n", Ptr_Glob->variant.var_1.Int_Comp);
+  do_fprintf (stderr, "        should be:   %d\n", 17);
+  do_fprintf (stderr, "  Str_Comp:          %s\n", Ptr_Glob->variant.var_1.Str_Comp);
+  do_fprintf (stderr, "        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
+  do_fprintf (stderr, "Next_Ptr_Glob->\n");
+  do_fprintf (stderr, "  Ptr_Comp:          %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
+  do_fprintf (stderr, "        should be:   (implementation-dependent), same as above\n");
+  do_fprintf (stderr, "  Discr:             %d\n", Next_Ptr_Glob->Discr);
+  do_fprintf (stderr, "        should be:   %d\n", 0);
+  do_fprintf (stderr, "  Enum_Comp:         %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
+  do_fprintf (stderr, "        should be:   %d\n", 1);
+  do_fprintf (stderr, "  Int_Comp:          %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
+  do_fprintf (stderr, "        should be:   %d\n", 18);
+  do_fprintf (stderr, "  Str_Comp:          %s\n",
+                                Next_Ptr_Glob->variant.var_1.Str_Comp);
+  do_fprintf (stderr, "        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
+  do_fprintf (stderr, "Int_1_Loc:           %d\n", Int_1_Loc);
+  do_fprintf (stderr, "        should be:   %d\n", 5);
+  do_fprintf (stderr, "Int_2_Loc:           %d\n", Int_2_Loc);
+  do_fprintf (stderr, "        should be:   %d\n", 13);
+  do_fprintf (stderr, "Int_3_Loc:           %d\n", Int_3_Loc);
+  do_fprintf (stderr, "        should be:   %d\n", 7);
+  do_fprintf (stderr, "Enum_Loc:            %d\n", Enum_Loc);
+  do_fprintf (stderr, "        should be:   %d\n", 1);
+  do_fprintf (stderr, "Str_1_Loc:           %s\n", Str_1_Loc);
+  do_fprintf (stderr, "        should be:   DHRYSTONE PROGRAM, 1'ST STRING\n");
+  do_fprintf (stderr, "Str_2_Loc:           %s\n", Str_2_Loc);
+  do_fprintf (stderr, "        should be:   DHRYSTONE PROGRAM, 2'ND STRING\n");
+  do_fprintf (stderr, "\n");
+
+
+#if HOST_DEBUG
+    Microseconds = (float) User_Time * Mic_secs_Per_Second 
+                        / ((float) HZ * ((float) Number_Of_Runs));
+    Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
+                        / (float) User_Time;
+
+    do_fprintf (stdout, "Microseconds for one run through Dhrystone: ");
+    do_fprintf (stdout, "%10.1f \n", Microseconds);
+    do_fprintf (stdout, "Dhrystones per Second:                      ");
+    do_fprintf (stdout, "%10.0f \n", Dhrystones_Per_Second);
+    do_fprintf (stdout, "\n");
+#endif
+
+  finishTest(1);
+}
+
+
+void Proc_1(Rec_Pointer Ptr_Val_Par)
+/******************/
+    /* executed once */
+{
+  REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;  
+                                        /* == Ptr_Glob_Next */
+  /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
+  /* corresponds to "rename" in Ada, "with" in Pascal           */
+  
+  structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); 
+  Ptr_Val_Par->variant.var_1.Int_Comp = 5;
+  Next_Record->variant.var_1.Int_Comp 
+        = Ptr_Val_Par->variant.var_1.Int_Comp;
+  Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
+  Proc_3 (&Next_Record->Ptr_Comp);
+    /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp 
+                        == Ptr_Glob->Ptr_Comp */
+  if (Next_Record->Discr == Ident_1)
+    /* then, executed */
+  {
+    Next_Record->variant.var_1.Int_Comp = 6;
+    Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, 
+           &Next_Record->variant.var_1.Enum_Comp);
+    Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
+    Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, 
+           &Next_Record->variant.var_1.Int_Comp);
+  }
+  else /* not executed */
+    structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
+} /* Proc_1 */
+
+
+void Proc_2(int* Int_Par_Ref)
+/******************/
+    /* executed once */
+    /* *Int_Par_Ref == 1, becomes 4 */
+{
+  One_Fifty  Int_Loc;  
+  Enumeration   Enum_Loc;
+
+  Int_Loc = *Int_Par_Ref + 10;
+  do /* executed once */
+    if (Ch_1_Glob == 'A')
+      /* then, executed */
+    {
+      Int_Loc -= 1;
+      *Int_Par_Ref = Int_Loc - Int_Glob;
+      Enum_Loc = Ident_1;
+    } /* if */
+  while (Enum_Loc != Ident_1); /* true */
+} /* Proc_2 */
+
+
+void Proc_3(Rec_Pointer* Ptr_Ref_Par)
+/******************/
+    /* executed once */
+    /* Ptr_Ref_Par becomes Ptr_Glob */
+{
+  if (Ptr_Glob != Null)
+    /* then, executed */
+    *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
+  Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
+} /* Proc_3 */
+
+
+void Proc_4()
+/*******/
+    /* executed once */
+{
+  Boolean Bool_Loc;
+
+  Bool_Loc = Ch_1_Glob == 'A';
+  Bool_Glob = Bool_Loc | Bool_Glob;
+  Ch_2_Glob = 'B';
+} /* Proc_4 */
+
+
+void Proc_5()
+/*******/
+    /* executed once */
+{
+  Ch_1_Glob = 'A';
+  Bool_Glob = false;
+} /* Proc_5 */
diff --git a/benchmarks/median/bmark.mk b/benchmarks/median/bmark.mk
new file mode 100644 (file)
index 0000000..31c853a
--- /dev/null
@@ -0,0 +1,30 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include
+# the benchmark name as a prefix so that they are unique.
+#
+
+median_c_src = \
+       median_main.c \
+       median.c \
+
+median_riscv_src = \
+       crt.S \
+
+median_c_objs     = $(patsubst %.c, %.o, $(median_c_src))
+median_riscv_objs = $(patsubst %.S, %.o, $(median_riscv_src))
+
+median_host_bin = median.host
+$(median_host_bin): $(median_c_src)
+       $(HOST_COMP) $^ -o $(median_host_bin)
+
+median_riscv_bin = median.riscv
+$(median_riscv_bin): $(median_c_objs) $(median_riscv_objs)
+       $(RISCV_LINK) $(median_c_objs) $(median_riscv_objs) -o $(median_riscv_bin)
+
+junk += $(median_c_objs) $(median_riscv_objs) \
+        $(median_host_bin) $(median_riscv_bin)
diff --git a/benchmarks/median/dataset1.h b/benchmarks/median/dataset1.h
new file mode 100644 (file)
index 0000000..a7bc568
--- /dev/null
@@ -0,0 +1,51 @@
+
+#define DATA_SIZE 400
+
+int input_data[DATA_SIZE] =
+{
+   41, 454, 833, 335, 564,   1, 187, 989, 749, 365, 350, 572, 132,  64, 949, 153, 584, 216, 805, 140,
+  621, 210,   6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961,  12, 110, 883, 116, 750, 296, 646,
+  426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258,
+  539, 647, 569, 509, 203,  88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592,  81, 569,
+  267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388,
+  195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657,  79, 181, 208, 111, 998, 859, 629,  65, 847,
+  288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761,   4, 241, 494,
+  478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317,  78, 224, 351, 937, 540,
+  288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358,  92,
+  584, 989,  62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332,
+  778, 684, 598, 740, 143, 446,  33, 311, 125, 743, 941, 557, 933, 479, 799, 557, 553, 925, 431, 796,
+  648, 357, 952, 891, 287, 666,  19, 514,  49, 557,  86, 870,  95, 853, 441, 440, 587,  61, 614, 678,
+  382, 396, 280,   9, 808,  17, 971, 170, 819, 291, 344, 380, 450, 536, 512, 185, 965, 917, 347, 539,
+  808, 983, 882, 887, 537,  54, 946, 612, 701, 951, 356, 479, 567, 151, 891,   7,  22, 641, 568, 335,
+  665, 730, 423,  95, 434, 728, 158, 280,   2, 395,  84, 688, 247, 911,  49, 476, 435, 815, 792, 729,
+  869, 265, 486, 127, 414, 236, 369, 214, 548, 180, 518,   6, 888, 503, 682, 596, 284, 173, 264, 643,
+  499, 346, 290, 599, 897,  68, 215, 849, 731, 658, 688, 619, 251, 121, 786, 131, 555, 828, 302, 667,
+  528, 433, 544, 487, 322, 753, 947, 125, 287, 626, 824,  14, 304,  10, 788, 403, 733, 106, 959, 703,
+  366, 818, 722, 964, 294, 406, 975, 874, 653, 856, 748,  86,  91,  60, 378, 660, 105, 667, 102, 153,
+  381, 121, 651,  98, 825, 412, 840, 236, 356,  12, 148, 423,  54, 965, 140, 216, 955, 621, 343, 361
+};
+
+int verify_data[DATA_SIZE] =
+{
+    0, 454, 454, 564, 335, 187, 187, 749, 749, 365, 365, 350, 132, 132, 153, 584, 216, 584, 216, 621,
+  210, 210, 210, 572, 572, 890, 593, 593, 593, 694, 694, 694, 228, 110, 110, 116, 750, 296, 646, 426,
+  500, 426, 436, 436, 659, 701, 774, 774, 812, 678, 678, 678, 696, 696, 564, 474, 474, 474, 272, 539,
+  539, 569, 569, 509, 203, 203, 280, 703, 703, 669, 606, 511, 511, 551, 657, 657, 592, 195, 569, 267,
+  569, 267, 800, 337, 584, 584, 643, 902, 643, 368, 368, 489, 489, 826, 328, 826, 592, 933, 592, 388,
+  388, 543, 649, 649, 649, 566, 979, 649, 814, 657, 657, 181, 181, 181, 208, 859, 859, 629, 629, 288,
+  704, 349, 704, 349, 253, 253, 715, 886, 715, 430, 415, 415, 538, 576, 700, 761, 700, 241, 241, 478,
+  478, 478, 499, 499, 693, 403, 416, 416, 416, 444, 296, 676, 620, 620, 317, 224, 224, 351, 540, 540,
+  540, 288, 169, 169, 527, 606, 527, 389, 389, 389, 796, 455, 720, 455, 720, 367, 745, 367, 358, 358,
+  584, 584, 271, 271, 853, 853, 788, 403, 531, 517, 517, 517, 461, 559, 461, 775, 358, 358, 332, 332,
+  684, 684, 684, 598, 446, 143, 311, 125, 311, 743, 743, 933, 557, 799, 557, 557, 557, 553, 796, 648,
+  648, 648, 891, 891, 666, 287, 514,  49, 514,  86, 557,  95, 853, 441, 441, 441, 440, 587, 614, 614,
+  396, 382, 280, 280,  17, 808, 170, 819, 291, 344, 344, 380, 450, 512, 512, 512, 917, 917, 539, 539,
+  808, 882, 887, 882, 537, 537, 612, 701, 701, 701, 479, 479, 479, 567, 151,  22,  22, 568, 568, 568,
+  665, 665, 423, 423, 434, 434, 280, 158, 280,  84, 395, 247, 688, 247, 476, 435, 476, 792, 792, 792,
+  729, 486, 265, 414, 236, 369, 236, 369, 214, 518, 180, 518, 503, 682, 596, 596, 284, 264, 264, 499,
+  499, 346, 346, 599, 599, 215, 215, 731, 731, 688, 658, 619, 251, 251, 131, 555, 555, 555, 667, 528,
+  528, 528, 487, 487, 487, 753, 753, 287, 287, 626, 626, 304,  14, 304, 403, 733, 403, 733, 703, 703,
+  703, 722, 818, 722, 406, 406, 874, 874, 856, 748, 748,  91,  86,  91, 378, 378, 660, 105, 153, 153,
+  153, 381, 121, 651, 412, 825, 412, 356, 236, 148, 148, 148, 423, 140, 216, 216, 621, 621, 361,   0
+};
+
diff --git a/benchmarks/median/median.c b/benchmarks/median/median.c
new file mode 100644 (file)
index 0000000..3c509cc
--- /dev/null
@@ -0,0 +1,40 @@
+//**************************************************************************
+// Median filter (c version)
+//--------------------------------------------------------------------------
+
+void median( int n, int input[], int results[] )
+{
+  int A, B, C, i;
+
+  // Zero the ends
+  results[0]   = 0;
+  results[n-1] = 0;
+
+  // Do the filter
+  for ( i = 1; i < (n-1); i++ ) {
+
+    A = input[i-1];
+    B = input[i];
+    C = input[i+1];
+
+    if ( A < B ) {
+      if ( B < C )
+        results[i] = B;
+      else if ( C < A )
+        results[i] = A;
+      else
+        results[i] = C;
+    }
+
+    else {
+      if ( A < C )
+        results[i] = A;
+      else if ( C < B )
+        results[i] = B;
+      else
+        results[i] = C;
+    }
+
+  }
+
+}
diff --git a/benchmarks/median/median.h b/benchmarks/median/median.h
new file mode 100644 (file)
index 0000000..b8b9a94
--- /dev/null
@@ -0,0 +1,9 @@
+//**************************************************************************
+// Median filters
+//--------------------------------------------------------------------------
+
+// Simple C version
+void median( int n, int input[], int results[] );
+
+// Simple assembly version
+void median_asm( int n, int input[], int results[] );
diff --git a/benchmarks/median/median_gendata.pl b/benchmarks/median/median_gendata.pl
new file mode 100755 (executable)
index 0000000..373904e
--- /dev/null
@@ -0,0 +1,140 @@
+#!/usr/bin/perl -w
+#==========================================================================
+# median_gendata.pl
+#
+# Author : Christopher Batten (cbatten@mit.edu)
+# Date   : May 9, 2005
+#
+(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm;
+#
+# Simple script which creates an input data set and the reference data
+# for the median benchmark.
+#
+ENDMSG
+
+use strict "vars";
+use warnings;
+no  warnings("once");
+use Getopt::Long;
+
+#--------------------------------------------------------------------------
+# Command line processing
+#--------------------------------------------------------------------------
+
+our %opts;
+
+sub usage()
+{
+
+  print "\n";
+  print " Usage: median_gendata.pl [options] \n";
+  print "\n";
+  print " Options:\n";
+  print "  --help  print this message\n";
+  print "  --size  size of input data [750]\n";
+  print "  --seed  random seed [1]\n";
+  print "$usageMsg";
+
+  exit();
+}
+
+sub processCommandLine()
+{
+
+  $opts{"help"} = 0;
+  $opts{"size"} = 750;
+  $opts{"seed"} = 1;
+  Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage();
+  $opts{"help"} and usage();
+
+}
+
+#--------------------------------------------------------------------------
+# Helper Functions
+#--------------------------------------------------------------------------
+
+sub printArray
+{
+  my $arrayName = $_[0];
+  my $arrayRef  = $_[1];
+
+  my $numCols = 20;
+  my $arrayLen = scalar(@{$arrayRef});
+
+  print "int ".$arrayName."[DATA_SIZE] = \n";
+  print "{\n";
+
+  if ( $arrayLen <= $numCols ) {
+    print "  ";
+    for ( my $i = 0; $i < $arrayLen; $i++ ) {
+      print sprintf("%3d",$arrayRef->[$i]);
+      if ( $i != $arrayLen-1 ) {
+        print ", ";
+      }
+    }
+    print "\n";
+  }
+
+  else {
+    my $numRows = int($arrayLen/$numCols);
+    for ( my $j = 0; $j < $numRows; $j++ ) {
+      print "  ";
+      for ( my $i = 0; $i < $numCols; $i++ ) {
+        my $index = $j*$numCols + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+    if ( $arrayLen > ($numRows*$numCols) ) {
+      print "  ";
+      for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) {
+        my $index = $numCols*$numRows + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+  }
+
+  print  "};\n\n";
+}
+
+#--------------------------------------------------------------------------
+# Main
+#--------------------------------------------------------------------------
+
+sub main()
+{
+
+  processCommandLine();
+  srand($opts{"seed"});
+
+  my @values;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    push( @values, int(rand(999)) );
+  }
+
+  my @median;
+  $median[0] = 0;
+  $median[$opts{"size"}-1] = 0;
+  for ( my $i = 1; $i < $opts{"size"}-1; $i++ ) {
+    my @tempList = ( $values[$i-1], $values[$i], $values[$i+1] );
+    my @sorted = sort { $a <=> $b } @tempList;
+    $median[$i] = $sorted[1];
+  }
+
+  print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n";
+  printArray( "input_data", \@values );
+  printArray( "verify_data", \@median );
+
+}
+
+main();
+
diff --git a/benchmarks/median/median_main.c b/benchmarks/median/median_main.c
new file mode 100644 (file)
index 0000000..6decd3d
--- /dev/null
@@ -0,0 +1,131 @@
+//**************************************************************************
+// Median filter bencmark
+//--------------------------------------------------------------------------
+//
+// This benchmark performs a 1D three element median filter. The
+// input data (and reference data) should be generated using the
+// median_gendata.pl perl script and dumped to a file named
+// dataset1.h You should not change anything except the
+// HOST_DEBUG and PREALLOCATE macros for your timing run.
+
+#include "median.h"
+
+//--------------------------------------------------------------------------
+// Macros
+
+// Set HOST_DEBUG to 1 if you are going to compile this for a host
+// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
+// to 0 if you are compiling with the smips-gcc toolchain.
+
+#ifndef HOST_DEBUG
+#define HOST_DEBUG 0
+#endif
+
+// Set PREALLOCATE to 1 if you want to preallocate the benchmark
+// function before starting stats. If you have instruction/data
+// caches and you don't want to count the overhead of misses, then
+// you will need to use preallocation.
+
+#ifndef PREALLOCATE
+#define PREALLOCATE 0
+#endif
+
+// Set SET_STATS to 1 if you want to carve out the piece that actually
+// does the computation.
+
+#ifndef SET_STATS
+#define SET_STATS 0
+#endif
+
+//--------------------------------------------------------------------------
+// Input/Reference Data
+
+#include "dataset1.h"
+
+//--------------------------------------------------------------------------
+// Helper functions
+
+int verify( int n, int test[], int correct[] )
+{
+  int i;
+  for ( i = 0; i < n; i++ ) {
+    if ( test[i] != correct[i] ) {
+      return 2;
+    }
+  }
+  return 1;
+}
+
+#if HOST_DEBUG
+void printArray( char name[], int n, int arr[] )
+{
+  int i;
+  printf( " %10s :", name );
+  for ( i = 0; i < n; i++ )
+    printf( " %3d ", arr[i] );
+  printf( "\n" );
+}
+#endif
+
+void finishTest( int toHostValue )
+{
+#if HOST_DEBUG
+  if ( toHostValue == 1 )
+    printf( "*** PASSED ***\n" );
+  else
+    printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
+  exit(0);
+#else
+  asm( "mtpcr %0, cr30" : : "r" (toHostValue) );
+  while ( 1 ) { }
+#endif
+}
+
+void setStats( int enable )
+{
+#if ( !HOST_DEBUG && SET_STATS )
+  asm( "mtpcr %0, cr10" : : "r" (enable) );
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Main
+
+int main( int argc, char* argv[] )
+{
+  int results_data[DATA_SIZE];
+
+  // Output the input array
+
+#if HOST_DEBUG
+  printArray( "input",  DATA_SIZE, input_data  );
+  printArray( "verify", DATA_SIZE, verify_data );
+#endif
+
+  // If needed we preallocate everything in the caches
+
+#if ( !HOST_DEBUG && PREALLOCATE )
+  median( DATA_SIZE, input_data, results_data );
+#endif
+
+  // Do the filter
+
+#if HOST_DEBUG
+  median( DATA_SIZE, input_data, results_data );
+#else
+  setStats(1);
+  median( DATA_SIZE, input_data, results_data );
+  setStats(0);
+#endif
+
+  // Print out the results
+
+#if HOST_DEBUG
+  printArray( "results", DATA_SIZE, results_data );
+#endif
+
+  // Check the results
+
+  finishTest(verify( DATA_SIZE, results_data, verify_data ));
+
+}
diff --git a/benchmarks/mt-matmul/bmark.mk b/benchmarks/mt-matmul/bmark.mk
new file mode 100644 (file)
index 0000000..67d6af3
--- /dev/null
@@ -0,0 +1,29 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include
+# the benchmark name as a prefix so that they are unique.
+#
+
+mt_matmul_c_src = \
+       mt-matmul.c \
+
+mt_matmul_riscv_src = \
+       crt-mt.S \
+
+mt_matmul_c_objs     = $(patsubst %.c, %.o, $(mt_matmul_c_src))
+mt_matmul_riscv_objs = $(patsubst %.S, %.o, $(mt_matmul_riscv_src))
+
+mt_matmul_host_bin = mt-matmul.host
+$(mt_matmul_host_bin) : $(mt_matmul_c_src)
+       $(HOST_COMP) $^ -o $(mt_matmul_host_bin)
+
+mt_matmul_riscv_bin = mt-matmul.riscv
+$(mt_matmul_riscv_bin) : $(mt_matmul_c_objs) $(mt_matmul_riscv_objs)
+       $(RISCV_LINK_MT) $(RISCV_LINK_SYSCALL) $(mt_matmul_c_objs) $(mt_matmul_riscv_objs) -o $(mt_matmul_riscv_bin)
+
+junk += $(mt_matmul_c_objs) $(mt_matmul_riscv_objs) \
+        $(mt_matmul_host_bin) $(mt_matmul_riscv_bin)
diff --git a/benchmarks/mt-matmul/dataset.h b/benchmarks/mt-matmul/dataset.h
new file mode 100644 (file)
index 0000000..dde3ee4
--- /dev/null
@@ -0,0 +1,174 @@
+
+#define ARRAY_SIZE 1024 
+
+
+#define DIM_SIZE 32 
+
+static data_t input1_data[ARRAY_SIZE] = 
+{
+    0,   3,   2,   0,   3,   1,   0,   3,   2,   3,   2,   0,   3,   3,   1,   2,   3,   0,   0,   1, 
+    1,   1,   2,   3,   1,   2,   3,   1,   1,   3,   2,   2,   0,   1,   3,   2,   2,   2,   0,   0, 
+    1,   0,   1,   3,   3,   0,   3,   3,   3,   3,   0,   3,   2,   1,   2,   2,   0,   0,   3,   0, 
+    1,   1,   0,   3,   3,   1,   2,   3,   3,   0,   1,   2,   1,   0,   1,   2,   2,   1,   0,   3, 
+    1,   0,   2,   2,   1,   1,   1,   1,   1,   1,   2,   0,   3,   1,   1,   2,   2,   3,   3,   1, 
+    3,   2,   0,   0,   0,   3,   3,   3,   2,   1,   2,   3,   1,   0,   0,   0,   0,   1,   2,   2, 
+    1,   1,   3,   3,   3,   1,   1,   2,   3,   1,   3,   3,   2,   3,   2,   1,   2,   3,   0,   2, 
+    2,   1,   1,   0,   0,   0,   0,   0,   1,   3,   3,   1,   1,   1,   2,   2,   3,   2,   1,   1, 
+    1,   1,   3,   0,   2,   2,   1,   3,   2,   1,   2,   2,   1,   3,   1,   3,   1,   3,   2,   3, 
+    1,   2,   1,   3,   2,   2,   0,   1,   0,   0,   1,   2,   3,   3,   1,   0,   0,   0,   3,   1, 
+    2,   3,   2,   3,   2,   0,   0,   0,   0,   0,   3,   1,   3,   0,   0,   0,   3,   1,   1,   1, 
+    1,   2,   1,   2,   3,   2,   0,   0,   2,   2,   3,   0,   3,   0,   0,   3,   0,   3,   1,   3, 
+    3,   1,   1,   1,   2,   2,   1,   3,   0,   3,   3,   1,   0,   0,   3,   2,   1,   3,   3,   3, 
+    1,   0,   1,   1,   2,   1,   0,   1,   1,   2,   2,   3,   1,   2,   2,   2,   0,   1,   3,   3, 
+    3,   2,   2,   1,   0,   1,   2,   0,   1,   1,   1,   1,   2,   3,   2,   2,   3,   3,   0,   0, 
+    2,   0,   0,   0,   3,   0,   1,   0,   3,   0,   0,   0,   3,   0,   0,   2,   0,   2,   0,   0, 
+    2,   3,   2,   0,   0,   3,   3,   2,   1,   1,   0,   2,   0,   0,   3,   3,   2,   3,   3,   0, 
+    1,   0,   2,   2,   0,   3,   3,   1,   1,   0,   2,   3,   2,   1,   1,   0,   1,   2,   1,   2, 
+    2,   0,   0,   1,   0,   1,   1,   0,   1,   0,   2,   3,   3,   2,   0,   0,   1,   3,   0,   3, 
+    3,   0,   0,   0,   0,   3,   3,   1,   0,   0,   3,   3,   2,   1,   2,   1,   3,   3,   0,   1, 
+    3,   0,   2,   3,   1,   3,   3,   3,   3,   3,   0,   1,   1,   3,   0,   2,   2,   3,   1,   2, 
+    2,   2,   1,   3,   3,   0,   3,   0,   0,   2,   0,   2,   3,   0,   1,   3,   2,   2,   0,   0, 
+    2,   3,   0,   2,   2,   2,   3,   1,   0,   3,   3,   3,   3,   1,   0,   3,   3,   2,   0,   3, 
+    2,   0,   3,   0,   2,   0,   0,   2,   2,   1,   0,   2,   3,   1,   1,   1,   1,   2,   3,   3, 
+    3,   0,   0,   3,   3,   3,   2,   3,   3,   1,   2,   2,   3,   1,   2,   1,   1,   3,   0,   1, 
+    2,   0,   2,   0,   0,   1,   3,   2,   0,   1,   3,   2,   3,   3,   0,   0,   0,   1,   0,   3, 
+    3,   2,   2,   2,   1,   1,   2,   2,   1,   3,   2,   0,   1,   3,   2,   0,   2,   1,   3,   0, 
+    0,   0,   1,   3,   3,   2,   2,   2,   3,   1,   0,   0,   1,   1,   2,   1,   3,   1,   1,   2, 
+    2,   3,   2,   3,   0,   2,   3,   3,   0,   3,   0,   0,   1,   0,   0,   0,   1,   3,   1,   1, 
+    2,   3,   2,   1,   1,   2,   2,   2,   3,   0,   1,   1,   2,   1,   2,   0,   2,   3,   1,   3, 
+    0,   1,   1,   3,   0,   2,   3,   0,   1,   2,   3,   2,   0,   0,   3,   3,   2,   1,   1,   2, 
+    3,   0,   1,   1,   1,   1,   2,   0,   1,   2,   0,   1,   1,   1,   0,   1,   3,   2,   3,   1, 
+    0,   2,   1,   2,   1,   3,   3,   1,   0,   2,   2,   3,   1,   3,   1,   3,   0,   1,   0,   3, 
+    0,   3,   2,   0,   3,   3,   3,   0,   3,   2,   2,   2,   1,   3,   0,   0,   1,   1,   3,   0, 
+    1,   2,   1,   0,   0,   0,   3,   2,   2,   0,   0,   2,   1,   3,   0,   0,   3,   0,   0,   2, 
+    1,   1,   2,   2,   1,   3,   2,   2,   1,   1,   2,   1,   3,   2,   1,   1,   3,   0,   1,   3, 
+    3,   2,   2,   1,   0,   3,   2,   2,   2,   3,   0,   1,   3,   3,   2,   3,   0,   3,   2,   3, 
+    1,   1,   0,   0,   0,   2,   3,   0,   3,   0,   1,   1,   3,   1,   3,   2,   1,   1,   2,   1, 
+    3,   2,   0,   2,   1,   0,   2,   3,   2,   3,   2,   1,   2,   3,   0,   0,   1,   1,   0,   0, 
+    2,   1,   0,   1,   2,   2,   2,   2,   0,   3,   3,   1,   0,   0,   0,   0,   3,   1,   1,   0, 
+    0,   0,   0,   1,   2,   2,   1,   3,   0,   2,   3,   2,   3,   2,   2,   1,   2,   2,   3,   3, 
+    1,   3,   0,   2,   2,   3,   3,   1,   2,   2,   2,   3,   1,   1,   1,   0,   0,   0,   3,   0, 
+    1,   0,   3,   1,   1,   3,   0,   1,   2,   2,   0,   0,   3,   3,   3,   3,   2,   1,   0,   0, 
+    1,   0,   2,   0,   1,   1,   0,   0,   3,   3,   2,   1,   1,   1,   0,   1,   1,   2,   2,   1, 
+    1,   2,   0,   3,   1,   3,   1,   0,   3,   0,   3,   1,   1,   1,   0,   2,   0,   3,   1,   0, 
+    1,   0,   2,   0,   2,   3,   3,   3,   1,   2,   3,   2,   2,   0,   1,   1,   0,   3,   3,   1, 
+    3,   3,   2,   0,   2,   0,   2,   2,   3,   3,   3,   0,   2,   3,   3,   1,   3,   2,   2,   2, 
+    0,   2,   3,   0,   2,   0,   3,   2,   2,   1,   1,   0,   2,   2,   2,   0,   2,   2,   0,   1, 
+    3,   2,   1,   3,   2,   2,   0,   3,   3,   1,   2,   2,   0,   0,   3,   2,   1,   2,   2,   1, 
+    3,   1,   2,   0,   0,   1,   1,   2,   1,   3,   2,   2,   3,   0,   2,   1,   3,   2,   1,   3, 
+    2,   3,   3,   1,   2,   1,   2,   2,   0,   0,   0,   3,   0,   2,   3,   1,   0,   0,   2,   3, 
+    3,   2,   2,   1
+};
+
+static data_t input2_data[ARRAY_SIZE] = 
+{
+    1,   1,   0,   3,   1,   2,   0,   0,   0,   0,   0,   2,   1,   2,   3,   0,   0,   3,   3,   2, 
+    2,   1,   2,   3,   3,   0,   2,   2,   1,   1,   2,   2,   0,   2,   2,   1,   2,   3,   2,   2, 
+    3,   3,   2,   2,   1,   1,   1,   1,   2,   1,   2,   2,   3,   3,   3,   0,   0,   3,   2,   3, 
+    2,   3,   1,   2,   1,   1,   2,   2,   0,   1,   0,   3,   2,   1,   1,   1,   2,   0,   1,   2, 
+    2,   0,   2,   1,   3,   3,   2,   3,   2,   0,   3,   1,   3,   3,   2,   0,   1,   0,   1,   1, 
+    2,   2,   1,   1,   2,   2,   1,   2,   3,   3,   1,   3,   2,   2,   2,   3,   3,   1,   0,   2, 
+    1,   0,   0,   0,   1,   1,   2,   0,   3,   2,   3,   3,   0,   2,   3,   1,   0,   0,   2,   1, 
+    2,   0,   2,   1,   1,   2,   3,   1,   3,   2,   1,   0,   0,   0,   0,   0,   2,   2,   0,   2, 
+    1,   2,   0,   3,   2,   2,   0,   0,   3,   2,   1,   1,   3,   0,   2,   0,   0,   1,   0,   2, 
+    3,   3,   1,   3,   3,   0,   0,   2,   2,   0,   0,   0,   1,   0,   0,   1,   3,   0,   2,   1, 
+    3,   2,   2,   1,   3,   2,   0,   1,   2,   2,   3,   2,   1,   1,   1,   1,   3,   0,   1,   3, 
+    2,   2,   3,   1,   1,   2,   0,   2,   1,   1,   2,   3,   1,   0,   1,   0,   1,   1,   0,   0, 
+    2,   0,   3,   0,   3,   0,   3,   2,   2,   3,   3,   2,   1,   0,   2,   2,   1,   1,   0,   3, 
+    3,   2,   2,   0,   0,   3,   0,   1,   0,   0,   1,   2,   0,   1,   3,   0,   1,   2,   2,   0, 
+    0,   3,   0,   3,   0,   1,   1,   2,   0,   0,   0,   3,   0,   0,   2,   1,   1,   1,   0,   2, 
+    1,   3,   1,   2,   0,   3,   0,   3,   1,   3,   0,   0,   2,   2,   2,   2,   3,   3,   2,   1, 
+    2,   2,   1,   1,   2,   2,   2,   2,   0,   3,   0,   0,   2,   0,   1,   2,   0,   3,   2,   3, 
+    2,   0,   2,   1,   2,   1,   0,   2,   1,   1,   3,   2,   2,   3,   1,   0,   3,   3,   1,   0, 
+    3,   2,   2,   0,   0,   3,   0,   0,   2,   0,   3,   2,   3,   1,   1,   0,   0,   2,   3,   0, 
+    0,   1,   1,   1,   2,   1,   3,   2,   1,   3,   0,   1,   3,   3,   1,   1,   1,   1,   1,   1, 
+    0,   0,   2,   3,   2,   2,   2,   3,   2,   3,   1,   2,   3,   2,   2,   2,   0,   1,   3,   0, 
+    1,   1,   0,   1,   0,   1,   1,   3,   3,   1,   2,   2,   3,   2,   0,   2,   2,   0,   1,   3, 
+    0,   1,   3,   2,   1,   3,   3,   2,   0,   1,   3,   2,   0,   2,   1,   1,   0,   3,   0,   1, 
+    1,   1,   1,   1,   3,   0,   0,   1,   0,   2,   3,   1,   3,   0,   2,   1,   3,   0,   3,   0, 
+    3,   2,   2,   0,   0,   2,   1,   3,   3,   2,   3,   2,   2,   1,   2,   2,   3,   0,   3,   2, 
+    2,   0,   3,   2,   3,   2,   0,   0,   1,   2,   0,   0,   2,   0,   0,   3,   3,   2,   0,   0, 
+    3,   3,   0,   2,   3,   1,   0,   1,   0,   2,   1,   0,   2,   1,   0,   1,   0,   3,   0,   2, 
+    2,   3,   0,   0,   2,   1,   0,   1,   0,   0,   0,   2,   2,   3,   2,   0,   3,   3,   2,   1, 
+    0,   0,   3,   1,   2,   3,   3,   1,   0,   3,   1,   1,   0,   3,   3,   3,   2,   2,   2,   0, 
+    1,   2,   0,   3,   0,   1,   0,   1,   1,   0,   1,   2,   0,   3,   2,   0,   1,   2,   2,   0, 
+    2,   0,   0,   1,   0,   3,   0,   3,   2,   1,   1,   1,   1,   3,   2,   1,   1,   1,   1,   0, 
+    2,   1,   1,   3,   2,   0,   2,   1,   1,   0,   2,   2,   1,   3,   0,   2,   1,   0,   1,   2, 
+    0,   1,   3,   2,   3,   2,   1,   0,   2,   0,   2,   2,   3,   1,   1,   3,   2,   3,   2,   2, 
+    0,   2,   0,   0,   0,   3,   2,   0,   2,   2,   3,   3,   3,   2,   1,   2,   0,   0,   3,   0, 
+    2,   0,   3,   2,   2,   3,   0,   3,   2,   1,   2,   2,   1,   2,   0,   0,   3,   1,   2,   0, 
+    2,   3,   2,   2,   1,   1,   1,   3,   3,   3,   3,   3,   1,   3,   0,   1,   3,   2,   2,   1, 
+    0,   1,   1,   2,   1,   2,   3,   1,   2,   2,   1,   2,   1,   1,   0,   3,   3,   1,   1,   3, 
+    2,   0,   0,   1,   2,   0,   1,   3,   1,   0,   0,   2,   2,   3,   3,   0,   2,   3,   2,   1, 
+    1,   3,   0,   2,   2,   3,   3,   1,   2,   3,   3,   3,   1,   3,   0,   3,   1,   1,   2,   2, 
+    2,   1,   0,   3,   2,   3,   0,   2,   3,   2,   3,   1,   2,   3,   3,   1,   2,   1,   0,   0, 
+    0,   3,   3,   3,   3,   0,   3,   3,   3,   3,   2,   1,   0,   3,   0,   3,   2,   3,   1,   0, 
+    0,   1,   3,   1,   0,   2,   2,   3,   1,   0,   2,   1,   1,   3,   1,   1,   3,   1,   2,   1, 
+    0,   0,   3,   2,   1,   1,   1,   1,   3,   2,   1,   3,   3,   1,   0,   3,   1,   1,   2,   0, 
+    0,   0,   2,   3,   3,   2,   2,   3,   0,   2,   3,   1,   3,   3,   0,   2,   1,   2,   2,   2, 
+    1,   0,   1,   3,   2,   3,   1,   1,   2,   1,   1,   0,   0,   2,   3,   2,   1,   0,   3,   1, 
+    3,   0,   1,   1,   2,   2,   1,   3,   3,   1,   1,   0,   0,   3,   3,   0,   0,   0,   0,   0, 
+    3,   1,   3,   0,   0,   0,   3,   3,   2,   1,   3,   0,   1,   3,   1,   1,   1,   0,   1,   0, 
+    1,   2,   2,   2,   3,   3,   0,   2,   3,   2,   1,   3,   3,   1,   1,   3,   0,   3,   3,   2, 
+    1,   1,   2,   0,   3,   0,   1,   2,   1,   1,   0,   0,   1,   2,   2,   0,   3,   1,   1,   1, 
+    3,   3,   3,   1,   0,   3,   3,   2,   2,   2,   1,   2,   0,   1,   1,   3,   0,   3,   1,   0, 
+    2,   2,   0,   1,   2,   3,   2,   1,   2,   0,   3,   2,   1,   3,   0,   1,   2,   0,   3,   0, 
+    1,   1,   2,   1
+};
+
+static data_t verify_data[ARRAY_SIZE] = 
+{
+   72,  75,  88, 101,  80,  88,  73,  75,  80,  81,  58,  75,  86,  65,  60,  80,  84,  83,  87,  83, 
+  108,  93,  85,  76,  72,  98,  79,  86,  80,  96,  91,  85,  72,  64,  70,  83,  68,  92,  51,  54, 
+   85,  85,  60,  58,  90,  64,  55,  69,  72,  48,  94,  77,  91,  83,  70,  69,  67,  77,  59,  50, 
+   67,  74,  77,  67,  67,  62,  72,  71,  68,  79,  54,  61,  67,  61,  55,  62,  78,  60,  53,  64, 
+   67,  69,  99,  68,  88,  60,  66,  63,  70,  62,  65,  50,  53,  66,  70,  72,  75,  78,  85,  95, 
+   71,  89,  70,  68,  86,  88,  58,  77,  84,  70,  65,  68,  73,  75,  91,  96, 105,  92,  76,  68, 
+   86,  69,  80,  59,  73,  83,  88,  75,  64,  63,  71,  99,  77,  77,  69,  55,  80,  73,  54,  73, 
+   87,  78,  60,  69,  65,  78,  86,  89,  95,  92,  63,  69,  89,  61,  80,  65,  70,  77,  89,  77, 
+   79,  79,  73,  92,  64,  81,  60,  78,  81,  80,  61,  63,  89,  65,  56,  83,  77,  65, 102,  70, 
+   98,  86,  96,  68,  72,  89,  73,  73,  70,  89,  84,  76,  48,  61,  63,  70,  70,  79,  50,  53, 
+   64,  63,  43,  51,  59,  62,  43,  63,  55,  77,  79,  74,  75,  74,  64,  44,  65,  69,  72,  66, 
+   54,  71,  74,  72,  69,  76,  68,  89,  94,  75,  65,  53,  85,  79,  65,  74,  82,  73,  58,  70, 
+   84,  77,  99,  72,  92,  84,  78,  62,  59,  83,  71,  74,  63,  85,  80,  78,  71,  72,  79,  83, 
+   73,  82,  60,  85,  76,  82,  60,  70,  82,  68,  54,  85,  84,  70,  86,  74, 100,  88,  98,  68, 
+   67,  87,  69,  73,  68,  88,  76,  71,  47,  43,  47,  80,  54,  65,  40,  37,  59,  53,  33,  48, 
+   62,  40,  36,  55,  36,  62,  53,  57,  70,  69,  45,  43,  53,  61,  42,  57,  56,  63,  51,  47, 
+   59,  75,  64,  89,  83,  75,  59,  75,  91,  92,  58,  64,  83,  74,  58,  60,  76,  66,  97,  69, 
+   90,  95,  92,  64,  78,  75,  77,  73,  65,  78,  82,  75,  47,  54,  59,  71,  59,  56,  53,  42, 
+   60,  55,  40,  51,  60,  46,  36,  59,  46,  57,  67,  43,  51,  53,  53,  38,  54,  56,  55,  48, 
+   41,  46,  63,  63,  80,  77,  89, 102,  89,  98,  74,  86,  98,  93,  63,  76,  98,  77,  48, 101, 
+   86,  88, 100,  82, 102,  90,  95,  75,  86, 103,  83,  98,  80, 104,  98,  86,  71,  74,  80,  90, 
+   86,  87,  73,  70,  81,  83,  55,  66,  90,  66,  58,  84,  77,  84,  93,  72,  99,  75,  85,  65, 
+   70,  89,  71,  82,  64,  79,  82,  80,  67,  73,  86, 101,  78,  97,  66,  64,  84,  80,  55,  64, 
+   79,  73,  51,  79,  89,  68,  94,  77, 109, 102,  82,  61,  66,  93,  88,  70,  82,  82,  85,  69, 
+   69,  72,  66,  97,  85,  90,  70,  59,  76,  89,  53,  56,  90,  79,  71,  64,  70,  67, 100,  92, 
+  106,  89,  83,  78,  73,  80,  70,  72,  65,  70,  92,  88,  57,  76,  55,  85,  66,  80,  61,  63, 
+   63,  78,  54,  58,  71,  73,  54,  63,  63,  62,  89,  76,  86,  81,  83,  54,  70,  81,  78,  64, 
+   56,  72,  74,  81,  75,  63,  68,  89,  65,  77,  58,  68,  75,  83,  52,  62,  82,  63,  55,  75, 
+   51,  70,  95,  66,  83,  77,  86,  61,  64,  77,  48,  70,  66,  82,  72,  75,  79,  71,  72,  89, 
+   78,  78,  66,  59,  91,  80,  55,  64,  79,  68,  54,  71,  67,  75,  87,  84, 100, 101,  76,  58, 
+   74,  82,  61,  74,  75,  97,  85,  79,  61,  55,  69,  68,  72,  65,  52,  64,  80,  73,  48,  54, 
+   71,  66,  42,  61,  66,  63,  92,  64,  85,  77,  73,  54,  74,  73,  76,  66,  62,  79,  85,  70, 
+   71,  84,  87,  81,  88,  86,  77,  77,  93,  88,  78,  71, 101,  89,  58,  84,  95,  81,  89,  97, 
+  104,  79,  83,  76,  90,  81,  91,  74,  70,  76,  91,  80,  51,  48,  56,  69,  47,  63,  54,  42, 
+   63,  63,  42,  52,  66,  56,  39,  59,  61,  52,  59,  63,  62,  68,  57,  35,  67,  58,  56,  52, 
+   61,  63,  60,  47,  85,  75,  89, 106,  88,  95,  74,  82, 107, 107,  64,  78,  98,  90,  62,  91, 
+   79,  87, 111,  84, 104, 106,  96,  68,  94,  99,  81,  89,  79, 105,  95,  86,  65,  63,  77,  89, 
+   66,  88,  56,  73,  82,  92,  41,  62,  85,  66,  50,  81,  57,  71,  77,  78,  86,  89,  77,  53, 
+   67,  78,  61,  63,  72,  82,  69,  66,  59,  46,  55,  70,  56,  64,  45,  50,  65,  64,  42,  56, 
+   78,  49,  51,  52,  38,  56,  72,  55,  73,  72,  61,  50,  63,  60,  47,  57,  55,  73,  53,  68, 
+   85,  88,  91,  96,  82,  89,  73,  76,  87,  86,  67,  69,  96,  84,  57,  89,  87,  89,  99,  88, 
+  104,  90,  85,  75,  88,  92,  85,  75,  74,  87, 103,  94,  55,  48,  56,  65,  72,  50,  45,  51, 
+   63,  62,  47,  57,  79,  53,  36,  63,  54,  68,  71,  59,  63,  61,  63,  41,  50,  73,  57,  59, 
+   56,  76,  73,  65,  61,  64,  61,  79,  53,  73,  57,  44,  61,  59,  59,  56,  81,  59,  49,  62, 
+   65,  55,  69,  72,  79,  70,  58,  57,  68,  61,  62,  50,  57,  60,  66,  66,  63,  77,  81,  89, 
+   85,  81,  76,  73,  78,  95,  59,  70,  81,  77,  46,  79,  78,  79,  83,  81,  84,  82,  85,  48, 
+   74,  85,  85,  74,  74,  80,  80,  74,  60,  76,  80,  97,  88,  93,  66,  66,  73,  84,  56,  70, 
+   90,  63,  58,  78,  73,  93,  90,  78,  94,  88,  82,  67,  85,  70,  81,  86,  74,  82,  88,  82, 
+   68,  73,  75,  91,  78,  97,  71,  66,  74,  85,  50,  59,  86,  77,  70,  74,  75,  74,  99,  82, 
+   99,  91,  86,  65,  80,  77,  72,  69,  60,  78,  90,  87,  79,  69,  74,  98,  70,  86,  81,  67, 
+   69,  78,  48,  65,  88,  70,  70,  70,  69,  72,  96,  90,  99,  82,  81,  76,  98,  73,  74,  71, 
+   69,  73,  94,  89
+};
+
diff --git a/benchmarks/mt-matmul/matmul_gendata.pl b/benchmarks/mt-matmul/matmul_gendata.pl
new file mode 100755 (executable)
index 0000000..f21bb46
--- /dev/null
@@ -0,0 +1,200 @@
+#!/usr/bin/perl -w
+#==========================================================================
+# matmul_gendata.pl
+#
+# Author : Christopher Batten (cbatten@mit.edu)
+# Date   : April 29, 2005
+#
+(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm;
+#
+# Simple script which creates an input data set and the reference data
+# for the matmul benchmark.
+#
+ENDMSG
+
+use strict "vars";
+use warnings;
+no  warnings("once");
+use Getopt::Long;
+
+#--------------------------------------------------------------------------
+# Command line processing
+#--------------------------------------------------------------------------
+
+our %opts;
+
+sub usage()
+{
+
+  print "\n";
+  print " Usage: matmul_gendata.pl [options] \n";
+  print "\n";
+  print " Options:\n";
+  print "  --help  print this message\n";
+  print "  --size  size of input data [1000]\n";
+  print "  --seed  random seed [1]\n";
+  print "$usageMsg";
+
+  exit();
+}
+
+sub processCommandLine()
+{
+
+  $opts{"help"} = 0;
+  $opts{"size"} = 1000;
+  $opts{"seed"} = 1;
+  Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage();
+  $opts{"help"} and usage();
+
+}
+
+#--------------------------------------------------------------------------
+# Helper Functions
+#--------------------------------------------------------------------------
+
+sub printArray
+{
+  my $arrayName = $_[0];
+  my $arrayRef  = $_[1];
+
+  my $numCols = 20;
+  my $arrayLen = scalar(@{$arrayRef});
+
+  print "static data_t ".$arrayName."[ARRAY_SIZE] = \n";
+  print "{\n";
+
+  if ( $arrayLen <= $numCols ) {
+    print "  ";
+    for ( my $i = 0; $i < $arrayLen; $i++ ) {
+      print sprintf("%3d",$arrayRef->[$i]);
+      if ( $i != $arrayLen-1 ) {
+        print ", ";
+      }
+    }
+    print "\n";
+  }
+
+  else {
+    my $numRows = int($arrayLen/$numCols);
+    for ( my $j = 0; $j < $numRows; $j++ ) {
+      print "  ";
+      for ( my $i = 0; $i < $numCols; $i++ ) {
+        my $index = $j*$numCols + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+    if ( $arrayLen > ($numRows*$numCols) ) {
+      print "  ";
+      for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) {
+        my $index = $numCols*$numRows + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+  }
+
+  print  "};\n\n";
+}
+
+
+
+#--------------------------------------------------------------------------
+# Matmul
+#--------------------------------------------------------------------------
+
+# http://answers.oreilly.com/topic/418-how-to-multiply-matrices-in-perl/
+
+sub mmult {
+    my ($m1,$m2) = @_;
+    my ($m1rows,$m1cols) = matdim($m1);
+    my ($m2rows,$m2cols) = matdim($m2);
+
+    my $result = [  ];
+    my ($i, $j, $k);
+
+    for $i (range($m1rows)) {
+        for $j (range($m2cols)) {
+            for $k (range($m1cols)) {
+                $result->[$i][$j] += $m1->[$i][$k] * $m2->[$k][$j];
+            }
+        }
+    }
+    return $result;
+}
+
+sub range { 0 .. ($_[0] - 1) }
+
+
+sub veclen {
+    my $ary_ref = $_[0];
+    my $type = ref $ary_ref;
+    if ($type ne "ARRAY") { die "$type is bad array ref for $ary_ref" }
+    return scalar(@$ary_ref);
+}
+
+sub matdim {
+    my $matrix = $_[0];
+    my $rows = veclen($matrix);
+    my $cols = veclen($matrix->[0]);
+    return ($rows, $cols);
+}
+
+#--------------------------------------------------------------------------
+# Main
+#--------------------------------------------------------------------------
+
+sub main()
+{
+
+  processCommandLine();
+  srand($opts{"seed"});
+
+  # create random input arrays
+  my $mat_values1;
+  my $mat_values2;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    for ( my $j = 0; $j < $opts{"size"}; $j++ ) {
+      $mat_values1->[$i][$j] = int(rand(4));
+      $mat_values2->[$i][$j] = int(rand(4));
+    }
+  }
+
+  # perform matmul
+  my $mat_results = mmult( $mat_values1, $mat_values2 );
+  
+  # translate 2d arrays to 1d-somethings (I don't know how to code in perl - Chris)
+  my @values1;
+  my @values2;
+  my @results;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    for ( my $j = 0; $j < $opts{"size"}; $j++ ) {
+    my $value1 = $mat_values1->[$i][$j];
+    my $value2 = $mat_values2->[$i][$j];
+    my $result = $mat_results->[$i][$j];
+    push( @values1, $value1 );
+    push( @values2, $value2 );
+    push( @results, $result );
+    }
+  }
+
+  print "\n\#define ARRAY_SIZE ".($opts{"size"}*$opts{"size"})." \n\n";
+  print "\n\#define DIM_SIZE ".$opts{"size"}." \n\n";
+   
+  printArray( "input1_data", \@values1 );
+  printArray( "input2_data", \@values2 );
+  printArray( "verify_data", \@results);
+}
+
+main();
+
diff --git a/benchmarks/mt-matmul/mt-matmul.c b/benchmarks/mt-matmul/mt-matmul.c
new file mode 100644 (file)
index 0000000..93f8ea9
--- /dev/null
@@ -0,0 +1,167 @@
+//**************************************************************************
+// Multi-threaded Matrix Multiply benchmark
+//--------------------------------------------------------------------------
+// TA     : Christopher Celio
+// Student: 
+//
+//
+// This benchmark multiplies two 2-D arrays together and writes the results to
+// a third vector. The input data (and reference data) should be generated
+// using the matmul_gendata.pl perl script and dumped to a file named
+// dataset.h. 
+
+
+// print out arrays, etc.
+//#define DEBUG
+
+//--------------------------------------------------------------------------
+// Includes 
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+//--------------------------------------------------------------------------
+// Input/Reference Data
+
+typedef float data_t;
+#include "dataset.h"
+  
+//--------------------------------------------------------------------------
+// Basic Utilities and Multi-thread Support
+
+__thread unsigned long coreid;
+unsigned long ncores;
+
+#include "util.h"
+   
+#define stringify_1(s) #s
+#define stringify(s) stringify_1(s)
+#define stats(code) do { \
+    unsigned long _c = -rdcycle(), _i = -rdinstret(); \
+    code; \
+    _c += rdcycle(), _i += rdinstret(); \
+    if (coreid == 0) \
+      printf("%s: %ld cycles, %ld.%ld cycles/iter, %ld.%ld CPI\n", \
+             stringify(code), _c, _c/DIM_SIZE/DIM_SIZE/DIM_SIZE, 10*_c/DIM_SIZE/DIM_SIZE/DIM_SIZE%10, _c/_i, 10*_c/_i%10); \
+  } while(0)
+
+//--------------------------------------------------------------------------
+// Helper functions
+    
+void printArray( char name[], int n, data_t arr[] )
+{
+   int i;
+   if (coreid != 0)
+      return;
+  
+   printf( " %10s :", name );
+   for ( i = 0; i < n; i++ )
+      printf( " %3ld ", (long) arr[i] );
+   printf( "\n" );
+}
+      
+void __attribute__((noinline)) verify(size_t n, const data_t* test, const data_t* correct)
+{
+   if (coreid != 0)
+      return;
+
+   size_t i;
+   for (i = 0; i < n; i++)
+   {
+      if (test[i] != correct[i])
+      {
+         printf("FAILED test[%d]= %3ld, correct[%d]= %3ld\n", 
+            i, (long)test[i], i, (long)correct[i]);
+         exit(-1);
+      }
+   }
+   
+   return;
+}
+//--------------------------------------------------------------------------
+// matmul function
+// single-thread, naive version
+void __attribute__((noinline)) matmul_naive(const int lda,  const data_t A[], const data_t B[], data_t C[] )
+{
+   int i, j, k;
+
+   if (coreid > 0)
+      return;
+  
+   for ( i = 0; i < lda; i++ )
+      for ( j = 0; j < lda; j++ )  
+      {
+         for ( k = 0; k < lda; k++ ) 
+         {
+            C[i + j*lda] += A[j*lda + k] * B[k*lda + i];
+         }
+      }
+
+}
+
+
+void __attribute__((noinline)) matmul(const int lda,  const data_t A[], const data_t B[], data_t C[] )
+{
+   
+   // ***************************** //
+   // **** ADD YOUR CODE HERE ***** //
+   // ***************************** //
+   //
+   // feel free to make a separate function for MI and MSI versions.
+}
+
+//--------------------------------------------------------------------------
+// Main
+//
+// all threads start executing thread_entry(). Use their "coreid" to
+// differentiate between threads (each thread is running on a separate core).
+  
+void thread_entry(int cid, int nc)
+{
+   coreid = cid;
+   ncores = nc;
+
+   // static allocates data in the binary, which is visible to both threads
+   static data_t results_data[ARRAY_SIZE];
+
+
+   // Execute the provided, naive matmul
+   barrier();
+   stats(matmul_naive(DIM_SIZE, input1_data, input2_data, results_data); barrier());
+   
+   // verify
+   verify(ARRAY_SIZE, results_data, verify_data);
+   
+   // clear results from the first trial
+   size_t i;
+   if (coreid == 0) 
+      for (i=0; i < ARRAY_SIZE; i++)
+         results_data[i] = 0;
+   barrier();
+
+   
+   // Execute your faster matmul
+   barrier();
+   stats(matmul(DIM_SIZE, input1_data, input2_data, results_data); barrier());
+#ifdef DEBUG
+   printArray("results:", ARRAY_SIZE, results_data);
+   printArray("verify :", ARRAY_SIZE, verify_data);
+#endif
+   
+   // verify
+   verify(ARRAY_SIZE, results_data, verify_data);
+   barrier();
+
+   exit(0);
+}
+
diff --git a/benchmarks/mt-vvadd/bmark.mk b/benchmarks/mt-vvadd/bmark.mk
new file mode 100644 (file)
index 0000000..0ab2504
--- /dev/null
@@ -0,0 +1,29 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include
+# the benchmark name as a prefix so that they are unique.
+#
+
+mt_vvadd_c_src = \
+       mt-vvadd.c \
+
+mt_vvadd_riscv_src = \
+       crt-mt.S \
+
+mt_vvadd_c_objs     = $(patsubst %.c, %.o, $(mt_vvadd_c_src))
+mt_vvadd_riscv_objs = $(patsubst %.S, %.o, $(mt_vvadd_riscv_src))
+
+mt_vvadd_host_bin = mt-vvadd.host
+$(mt_vvadd_host_bin) : $(mt_vvadd_c_src)
+       $(HOST_COMP) $^ -o $(mt_vvadd_host_bin)
+
+mt_vvadd_riscv_bin = mt-vvadd.riscv
+$(mt_vvadd_riscv_bin) : $(mt_vvadd_c_objs) $(mt_vvadd_riscv_objs)
+       $(RISCV_LINK_MT) $(RISCV_LINK_SYSCALL) $(mt_vvadd_c_objs) $(mt_vvadd_riscv_objs) -o $(mt_vvadd_riscv_bin)
+
+junk += $(mt_vvadd_c_objs) $(mt_vvadd_riscv_objs) \
+        $(mt_vvadd_host_bin) $(mt_vvadd_riscv_bin)
diff --git a/benchmarks/mt-vvadd/dataset.h b/benchmarks/mt-vvadd/dataset.h
new file mode 100644 (file)
index 0000000..ce9f936
--- /dev/null
@@ -0,0 +1,165 @@
+
+#define DATA_SIZE 1000 
+
+static data_t input1_data[DATA_SIZE] = 
+{
+  0.00, 15.00, 10.00, 3.00, 14.00, 6.00, 2.00, 18.00, 11.00, 15.00, 11.00, 0.00, 17.00, 16.00, 7.00, 13.00, 18.00, 2.00, 2.00, 5.00, 
+  8.00, 5.00, 12.00, 14.00, 6.00, 12.00, 16.00, 7.00, 9.00, 17.00, 10.00, 10.00, 3.00, 5.00, 14.00, 11.00, 9.00, 12.00, 3.00, 1.00, 
+  5.00, 4.00, 6.00, 17.00, 17.00, 4.00, 17.00, 15.00, 17.00, 18.00, 3.00, 18.00, 10.00, 6.00, 12.00, 12.00, 3.00, 2.00, 16.00, 1.00, 
+  5.00, 6.00, 2.00, 17.00, 16.00, 5.00, 10.00, 18.00, 14.00, 4.00, 9.00, 9.00, 7.00, 4.00, 8.00, 13.00, 12.00, 6.00, 4.00, 17.00, 
+  5.00, 2.00, 11.00, 11.00, 7.00, 6.00, 8.00, 5.00, 6.00, 6.00, 11.00, 1.00, 18.00, 7.00, 6.00, 9.00, 10.00, 17.00, 14.00, 4.00, 
+  14.00, 11.00, 2.00, 0.00, 2.00, 17.00, 17.00, 15.00, 10.00, 8.00, 12.00, 18.00, 5.00, 0.00, 0.00, 1.00, 1.00, 8.00, 11.00, 11.00, 
+  7.00, 5.00, 15.00, 18.00, 15.00, 6.00, 8.00, 9.00, 18.00, 6.00, 15.00, 16.00, 10.00, 18.00, 13.00, 6.00, 10.00, 16.00, 0.00, 10.00, 
+  12.00, 8.00, 8.00, 3.00, 0.00, 1.00, 4.00, 0.00, 8.00, 15.00, 16.00, 9.00, 7.00, 7.00, 10.00, 9.00, 16.00, 12.00, 5.00, 5.00, 
+  9.00, 5.00, 17.00, 4.00, 13.00, 13.00, 4.00, 14.00, 10.00, 5.00, 10.00, 10.00, 6.00, 18.00, 5.00, 15.00, 5.00, 15.00, 13.00, 18.00, 
+  6.00, 13.00, 5.00, 18.00, 12.00, 14.00, 1.00, 7.00, 2.00, 1.00, 7.00, 12.00, 15.00, 15.00, 6.00, 2.00, 1.00, 2.00, 18.00, 6.00, 
+  10.00, 14.00, 9.00, 15.00, 11.00, 0.00, 3.00, 1.00, 2.00, 2.00, 14.00, 7.00, 18.00, 0.00, 2.00, 2.00, 16.00, 8.00, 4.00, 5.00, 
+  7.00, 11.00, 7.00, 10.00, 14.00, 10.00, 3.00, 0.00, 13.00, 9.00, 14.00, 0.00, 14.00, 1.00, 3.00, 16.00, 2.00, 14.00, 6.00, 17.00, 
+  17.00, 6.00, 9.00, 8.00, 9.00, 12.00, 5.00, 14.00, 2.00, 16.00, 17.00, 5.00, 4.00, 0.00, 14.00, 10.00, 6.00, 15.00, 15.00, 14.00, 
+  5.00, 1.00, 8.00, 8.00, 13.00, 8.00, 0.00, 4.00, 7.00, 9.00, 13.00, 16.00, 9.00, 14.00, 9.00, 13.00, 0.00, 7.00, 16.00, 17.00, 
+  18.00, 10.00, 13.00, 8.00, 4.00, 9.00, 13.00, 0.00, 6.00, 4.00, 6.00, 4.00, 10.00, 14.00, 14.00, 9.00, 15.00, 15.00, 3.00, 3.00, 
+  12.00, 0.00, 3.00, 2.00, 16.00, 1.00, 7.00, 2.00, 16.00, 2.00, 2.00, 0.00, 14.00, 3.00, 3.00, 10.00, 4.00, 10.00, 3.00, 4.00, 
+  13.00, 14.00, 13.00, 0.00, 1.00, 15.00, 16.00, 9.00, 7.00, 9.00, 0.00, 11.00, 1.00, 1.00, 15.00, 17.00, 12.00, 16.00, 15.00, 4.00, 
+  8.00, 2.00, 10.00, 10.00, 0.00, 18.00, 17.00, 7.00, 7.00, 2.00, 10.00, 17.00, 9.00, 7.00, 5.00, 3.00, 8.00, 11.00, 6.00, 9.00, 
+  13.00, 0.00, 3.00, 5.00, 2.00, 5.00, 7.00, 4.00, 9.00, 2.00, 13.00, 17.00, 14.00, 12.00, 1.00, 3.00, 7.00, 17.00, 0.00, 14.00, 
+  16.00, 2.00, 2.00, 1.00, 2.00, 15.00, 16.00, 8.00, 2.00, 4.00, 15.00, 15.00, 10.00, 6.00, 11.00, 9.00, 15.00, 17.00, 3.00, 8.00, 
+  15.00, 3.00, 10.00, 15.00, 8.00, 14.00, 16.00, 15.00, 15.00, 14.00, 1.00, 7.00, 4.00, 18.00, 2.00, 13.00, 11.00, 15.00, 7.00, 10.00, 
+  13.00, 10.00, 7.00, 14.00, 18.00, 4.00, 18.00, 4.00, 3.00, 9.00, 1.00, 13.00, 15.00, 2.00, 5.00, 15.00, 12.00, 10.00, 2.00, 0.00, 
+  10.00, 15.00, 0.00, 11.00, 14.00, 11.00, 14.00, 9.00, 1.00, 18.00, 14.00, 18.00, 15.00, 5.00, 1.00, 15.00, 18.00, 14.00, 3.00, 15.00, 
+  11.00, 2.00, 15.00, 0.00, 13.00, 1.00, 4.00, 14.00, 14.00, 5.00, 2.00, 13.00, 17.00, 8.00, 7.00, 6.00, 5.00, 10.00, 14.00, 14.00, 
+  17.00, 0.00, 0.00, 17.00, 18.00, 15.00, 10.00, 16.00, 18.00, 5.00, 9.00, 10.00, 18.00, 7.00, 11.00, 5.00, 4.00, 16.00, 2.00, 8.00, 
+  13.00, 1.00, 12.00, 3.00, 4.00, 6.00, 15.00, 12.00, 0.00, 6.00, 18.00, 12.00, 14.00, 18.00, 3.00, 2.00, 3.00, 5.00, 3.00, 14.00, 
+  18.00, 12.00, 10.00, 11.00, 8.00, 4.00, 10.00, 10.00, 9.00, 18.00, 14.00, 3.00, 7.00, 17.00, 12.00, 0.00, 10.00, 9.00, 17.00, 3.00, 
+  0.00, 4.00, 6.00, 16.00, 14.00, 12.00, 13.00, 13.00, 18.00, 7.00, 0.00, 1.00, 9.00, 7.00, 12.00, 6.00, 18.00, 8.00, 9.00, 13.00, 
+  13.00, 17.00, 10.00, 16.00, 1.00, 10.00, 17.00, 16.00, 2.00, 18.00, 4.00, 2.00, 6.00, 1.00, 1.00, 1.00, 8.00, 14.00, 6.00, 6.00, 
+  13.00, 14.00, 13.00, 6.00, 5.00, 10.00, 11.00, 11.00, 16.00, 1.00, 5.00, 9.00, 13.00, 8.00, 10.00, 2.00, 12.00, 15.00, 5.00, 14.00, 
+  3.00, 7.00, 9.00, 18.00, 2.00, 11.00, 16.00, 4.00, 5.00, 10.00, 17.00, 10.00, 3.00, 4.00, 14.00, 18.00, 13.00, 6.00, 8.00, 11.00, 
+  14.00, 3.00, 5.00, 6.00, 6.00, 5.00, 13.00, 0.00, 9.00, 9.00, 1.00, 7.00, 5.00, 5.00, 1.00, 6.00, 18.00, 11.00, 17.00, 7.00, 
+  1.00, 10.00, 5.00, 12.00, 6.00, 16.00, 16.00, 5.00, 1.00, 10.00, 10.00, 15.00, 7.00, 18.00, 8.00, 17.00, 3.00, 5.00, 3.00, 14.00, 
+  0.00, 16.00, 12.00, 0.00, 14.00, 17.00, 16.00, 2.00, 18.00, 13.00, 10.00, 13.00, 4.00, 14.00, 2.00, 3.00, 4.00, 8.00, 17.00, 0.00, 
+  6.00, 11.00, 5.00, 3.00, 3.00, 2.00, 15.00, 13.00, 10.00, 4.00, 1.00, 11.00, 6.00, 17.00, 1.00, 0.00, 18.00, 3.00, 3.00, 11.00, 
+  7.00, 7.00, 11.00, 14.00, 7.00, 16.00, 11.00, 10.00, 8.00, 6.00, 11.00, 5.00, 17.00, 10.00, 7.00, 8.00, 14.00, 2.00, 9.00, 17.00, 
+  15.00, 13.00, 10.00, 6.00, 0.00, 15.00, 11.00, 10.00, 11.00, 18.00, 2.00, 5.00, 17.00, 18.00, 11.00, 15.00, 3.00, 17.00, 9.00, 17.00, 
+  8.00, 6.00, 2.00, 4.00, 2.00, 11.00, 15.00, 2.00, 18.00, 3.00, 9.00, 7.00, 15.00, 9.00, 14.00, 10.00, 9.00, 6.00, 13.00, 8.00, 
+  15.00, 14.00, 0.00, 11.00, 5.00, 2.00, 12.00, 14.00, 10.00, 16.00, 9.00, 7.00, 9.00, 17.00, 4.00, 4.00, 7.00, 8.00, 4.00, 4.00, 
+  9.00, 7.00, 3.00, 5.00, 11.00, 11.00, 10.00, 13.00, 3.00, 14.00, 15.00, 8.00, 1.00, 1.00, 3.00, 0.00, 16.00, 9.00, 6.00, 1.00, 
+  0.00, 2.00, 0.00, 6.00, 13.00, 12.00, 5.00, 18.00, 1.00, 11.00, 17.00, 11.00, 16.00, 14.00, 14.00, 9.00, 11.00, 9.00, 17.00, 15.00, 
+  5.00, 18.00, 2.00, 11.00, 10.00, 16.00, 18.00, 5.00, 11.00, 12.00, 11.00, 18.00, 7.00, 6.00, 8.00, 3.00, 4.00, 3.00, 16.00, 4.00, 
+  6.00, 2.00, 15.00, 6.00, 7.00, 16.00, 0.00, 7.00, 11.00, 10.00, 3.00, 0.00, 14.00, 16.00, 15.00, 15.00, 12.00, 7.00, 1.00, 4.00, 
+  8.00, 4.00, 12.00, 0.00, 7.00, 8.00, 1.00, 1.00, 14.00, 15.00, 9.00, 8.00, 6.00, 6.00, 4.00, 7.00, 8.00, 13.00, 10.00, 5.00, 
+  8.00, 11.00, 2.00, 16.00, 7.00, 17.00, 5.00, 2.00, 17.00, 0.00, 18.00, 6.00, 7.00, 4.00, 4.00, 12.00, 0.00, 18.00, 8.00, 4.00, 
+  7.00, 0.00, 11.00, 1.00, 11.00, 17.00, 18.00, 15.00, 8.00, 11.00, 15.00, 9.00, 12.00, 1.00, 5.00, 6.00, 1.00, 18.00, 14.00, 7.00, 
+  16.00, 16.00, 10.00, 3.00, 13.00, 0.00, 12.00, 9.00, 18.00, 14.00, 15.00, 4.00, 11.00, 15.00, 15.00, 8.00, 16.00, 11.00, 13.00, 12.00, 
+  1.00, 13.00, 14.00, 2.00, 11.00, 0.00, 17.00, 11.00, 12.00, 6.00, 4.00, 4.00, 11.00, 13.00, 10.00, 2.00, 10.00, 14.00, 0.00, 6.00, 
+  18.00, 10.00, 7.00, 14.00, 12.00, 9.00, 4.00, 16.00, 17.00, 8.00, 14.00, 9.00, 0.00, 4.00, 15.00, 13.00, 8.00, 13.00, 13.00, 8.00, 
+  15.00, 6.00, 11.00, 4.00, 2.00, 6.00, 5.00, 14.00, 5.00, 17.00, 12.00, 11.00, 17.00, 4.00, 13.00, 7.00, 16.00, 12.00, 7.00, 18.00
+};
+
+static data_t input2_data[DATA_SIZE] = 
+{
+  8.00, 6.00, 0.00, 18.00, 6.00, 10.00, 1.00, 2.00, 4.00, 2.00, 4.00, 10.00, 6.00, 11.00, 17.00, 4.00, 0.00, 16.00, 14.00, 12.00, 
+  9.00, 8.00, 13.00, 15.00, 18.00, 2.00, 13.00, 10.00, 5.00, 4.00, 12.00, 9.00, 1.00, 13.00, 12.00, 7.00, 10.00, 17.00, 11.00, 10.00, 
+  18.00, 15.00, 11.00, 12.00, 7.00, 9.00, 6.00, 5.00, 11.00, 7.00, 10.00, 12.00, 18.00, 18.00, 15.00, 1.00, 3.00, 18.00, 11.00, 16.00, 
+  13.00, 18.00, 4.00, 13.00, 8.00, 7.00, 10.00, 13.00, 0.00, 9.00, 1.00, 16.00, 13.00, 7.00, 5.00, 5.00, 11.00, 1.00, 6.00, 10.00, 
+  12.00, 3.00, 10.00, 5.00, 15.00, 15.00, 13.00, 14.00, 14.00, 1.00, 18.00, 5.00, 16.00, 14.00, 10.00, 4.00, 8.00, 4.00, 6.00, 6.00, 
+  13.00, 14.00, 8.00, 5.00, 14.00, 10.00, 9.00, 10.00, 17.00, 15.00, 6.00, 16.00, 12.00, 9.00, 10.00, 16.00, 16.00, 8.00, 1.00, 12.00, 
+  7.00, 0.00, 0.00, 3.00, 5.00, 7.00, 10.00, 3.00, 17.00, 10.00, 18.00, 16.00, 1.00, 11.00, 18.00, 9.00, 2.00, 0.00, 12.00, 6.00, 
+  13.00, 1.00, 13.00, 5.00, 7.00, 13.00, 17.00, 9.00, 15.00, 13.00, 5.00, 2.00, 4.00, 4.00, 3.00, 0.00, 9.00, 11.00, 3.00, 12.00, 
+  6.00, 11.00, 1.00, 16.00, 12.00, 11.00, 2.00, 2.00, 15.00, 12.00, 8.00, 9.00, 14.00, 2.00, 11.00, 0.00, 0.00, 7.00, 2.00, 13.00, 
+  15.00, 18.00, 7.00, 16.00, 16.00, 1.00, 1.00, 12.00, 12.00, 2.00, 2.00, 1.00, 7.00, 4.00, 0.00, 8.00, 18.00, 4.00, 11.00, 6.00, 
+  17.00, 13.00, 12.00, 5.00, 16.00, 12.00, 0.00, 9.00, 10.00, 10.00, 18.00, 12.00, 8.00, 7.00, 5.00, 8.00, 16.00, 3.00, 9.00, 18.00, 
+  12.00, 13.00, 18.00, 6.00, 8.00, 12.00, 2.00, 12.00, 8.00, 8.00, 9.00, 18.00, 8.00, 0.00, 9.00, 2.00, 6.00, 7.00, 0.00, 3.00, 
+  11.00, 2.00, 18.00, 2.00, 16.00, 1.00, 16.00, 11.00, 11.00, 16.00, 16.00, 11.00, 7.00, 4.00, 14.00, 10.00, 5.00, 8.00, 4.00, 14.00, 
+  17.00, 13.00, 13.00, 3.00, 1.00, 14.00, 1.00, 7.00, 0.00, 2.00, 7.00, 14.00, 4.00, 9.00, 14.00, 3.00, 9.00, 13.00, 13.00, 3.00, 
+  3.00, 17.00, 0.00, 18.00, 4.00, 8.00, 6.00, 9.00, 4.00, 2.00, 0.00, 14.00, 3.00, 3.00, 14.00, 8.00, 6.00, 7.00, 2.00, 12.00, 
+  5.00, 14.00, 6.00, 12.00, 2.00, 16.00, 1.00, 15.00, 7.00, 18.00, 0.00, 0.00, 13.00, 13.00, 12.00, 11.00, 16.00, 15.00, 14.00, 8.00, 
+  9.00, 10.00, 8.00, 8.00, 13.00, 13.00, 13.00, 10.00, 1.00, 15.00, 4.00, 0.00, 12.00, 1.00, 8.00, 12.00, 1.00, 18.00, 12.00, 18.00, 
+  9.00, 1.00, 11.00, 5.00, 13.00, 7.00, 1.00, 13.00, 5.00, 8.00, 17.00, 11.00, 13.00, 15.00, 9.00, 3.00, 17.00, 18.00, 9.00, 3.00, 
+  15.00, 11.00, 12.00, 0.00, 2.00, 15.00, 3.00, 0.00, 13.00, 1.00, 14.00, 14.00, 15.00, 8.00, 6.00, 0.00, 0.00, 11.00, 17.00, 0.00, 
+  1.00, 8.00, 6.00, 6.00, 10.00, 6.00, 18.00, 12.00, 7.00, 18.00, 4.00, 6.00, 15.00, 18.00, 7.00, 5.00, 8.00, 6.00, 6.00, 7.00, 
+  4.00, 4.00, 10.00, 17.00, 12.00, 13.00, 11.00, 15.00, 12.00, 18.00, 7.00, 12.00, 17.00, 10.00, 14.00, 12.00, 2.00, 7.00, 17.00, 3.00, 
+  8.00, 6.00, 3.00, 9.00, 3.00, 7.00, 7.00, 15.00, 18.00, 5.00, 13.00, 13.00, 15.00, 10.00, 0.00, 11.00, 10.00, 1.00, 5.00, 16.00, 
+  2.00, 7.00, 14.00, 12.00, 7.00, 17.00, 17.00, 11.00, 0.00, 5.00, 16.00, 14.00, 1.00, 9.00, 8.00, 8.00, 3.00, 17.00, 0.00, 8.00, 
+  6.00, 5.00, 7.00, 6.00, 17.00, 3.00, 3.00, 8.00, 3.00, 12.00, 17.00, 5.00, 14.00, 3.00, 11.00, 5.00, 17.00, 2.00, 15.00, 1.00, 
+  18.00, 11.00, 12.00, 0.00, 0.00, 14.00, 7.00, 17.00, 15.00, 10.00, 18.00, 10.00, 11.00, 7.00, 12.00, 10.00, 17.00, 2.00, 18.00, 9.00, 
+  11.00, 4.00, 17.00, 10.00, 15.00, 12.00, 4.00, 1.00, 5.00, 10.00, 4.00, 2.00, 11.00, 3.00, 4.00, 15.00, 16.00, 10.00, 2.00, 2.00, 
+  15.00, 16.00, 0.00, 13.00, 16.00, 9.00, 1.00, 7.00, 3.00, 10.00, 7.00, 2.00, 12.00, 8.00, 1.00, 5.00, 0.00, 16.00, 4.00, 14.00, 
+  13.00, 16.00, 3.00, 0.00, 10.00, 6.00, 3.00, 9.00, 1.00, 3.00, 0.00, 13.00, 12.00, 17.00, 11.00, 4.00, 15.00, 15.00, 12.00, 4.00, 
+  4.00, 2.00, 16.00, 6.00, 11.00, 17.00, 14.00, 7.00, 4.00, 14.00, 8.00, 8.00, 3.00, 18.00, 17.00, 17.00, 12.00, 10.00, 11.00, 1.00, 
+  8.00, 13.00, 1.00, 14.00, 0.00, 9.00, 0.00, 7.00, 9.00, 0.00, 7.00, 12.00, 0.00, 18.00, 10.00, 1.00, 5.00, 13.00, 13.00, 2.00, 
+  10.00, 4.00, 2.00, 6.00, 0.00, 16.00, 2.00, 15.00, 13.00, 6.00, 8.00, 5.00, 6.00, 15.00, 12.00, 6.00, 6.00, 7.00, 8.00, 1.00, 
+  11.00, 9.00, 7.00, 18.00, 14.00, 4.00, 9.00, 6.00, 4.00, 2.00, 10.00, 13.00, 6.00, 17.00, 2.00, 11.00, 7.00, 3.00, 8.00, 9.00, 
+  2.00, 6.00, 18.00, 12.00, 18.00, 13.00, 8.00, 1.00, 11.00, 4.00, 13.00, 14.00, 16.00, 8.00, 6.00, 18.00, 14.00, 15.00, 9.00, 11.00, 
+  2.00, 13.00, 4.00, 3.00, 3.00, 15.00, 14.00, 3.00, 13.00, 12.00, 14.00, 16.00, 18.00, 12.00, 5.00, 11.00, 2.00, 3.00, 15.00, 1.00, 
+  12.00, 1.00, 15.00, 13.00, 12.00, 18.00, 4.00, 17.00, 13.00, 7.00, 11.00, 13.00, 7.00, 10.00, 1.00, 3.00, 18.00, 6.00, 10.00, 3.00, 
+  9.00, 16.00, 12.00, 10.00, 6.00, 6.00, 7.00, 16.00, 16.00, 16.00, 17.00, 18.00, 8.00, 18.00, 0.00, 6.00, 17.00, 13.00, 14.00, 8.00, 
+  0.00, 7.00, 5.00, 13.00, 8.00, 12.00, 14.00, 9.00, 10.00, 10.00, 9.00, 9.00, 8.00, 6.00, 0.00, 14.00, 16.00, 8.00, 7.00, 16.00, 
+  10.00, 3.00, 1.00, 9.00, 11.00, 2.00, 6.00, 18.00, 5.00, 4.00, 2.00, 11.00, 10.00, 17.00, 16.00, 2.00, 12.00, 15.00, 14.00, 6.00, 
+  6.00, 17.00, 3.00, 10.00, 9.00, 18.00, 18.00, 6.00, 11.00, 16.00, 18.00, 17.00, 7.00, 14.00, 1.00, 16.00, 7.00, 9.00, 11.00, 12.00, 
+  10.00, 6.00, 1.00, 16.00, 9.00, 18.00, 0.00, 9.00, 16.00, 10.00, 14.00, 6.00, 9.00, 14.00, 15.00, 7.00, 12.00, 8.00, 1.00, 1.00, 
+  1.00, 17.00, 17.00, 17.00, 18.00, 1.00, 15.00, 18.00, 16.00, 16.00, 11.00, 7.00, 4.00, 15.00, 3.00, 14.00, 13.00, 14.00, 9.00, 2.00, 
+  4.00, 8.00, 14.00, 7.00, 0.00, 12.00, 14.00, 15.00, 8.00, 2.00, 11.00, 5.00, 6.00, 16.00, 6.00, 4.00, 16.00, 7.00, 9.00, 5.00, 
+  1.00, 0.00, 16.00, 10.00, 9.00, 6.00, 5.00, 8.00, 15.00, 13.00, 7.00, 18.00, 18.00, 8.00, 0.00, 15.00, 4.00, 6.00, 14.00, 3.00, 
+  3.00, 2.00, 9.00, 14.00, 18.00, 13.00, 10.00, 15.00, 0.00, 11.00, 16.00, 7.00, 16.00, 18.00, 0.00, 12.00, 6.00, 13.00, 12.00, 12.00, 
+  5.00, 3.00, 5.00, 16.00, 13.00, 16.00, 8.00, 5.00, 12.00, 8.00, 8.00, 0.00, 2.00, 9.00, 18.00, 11.00, 8.00, 4.00, 14.00, 6.00, 
+  17.00, 2.00, 6.00, 8.00, 11.00, 13.00, 6.00, 18.00, 17.00, 6.00, 8.00, 0.00, 1.00, 14.00, 18.00, 4.00, 0.00, 4.00, 3.00, 3.00, 
+  16.00, 8.00, 16.00, 1.00, 2.00, 0.00, 15.00, 14.00, 10.00, 9.00, 15.00, 3.00, 5.00, 18.00, 5.00, 6.00, 7.00, 3.00, 7.00, 2.00, 
+  6.00, 12.00, 10.00, 10.00, 18.00, 16.00, 0.00, 9.00, 17.00, 10.00, 9.00, 14.00, 15.00, 5.00, 8.00, 15.00, 3.00, 15.00, 14.00, 11.00, 
+  6.00, 6.00, 14.00, 0.00, 14.00, 0.00, 7.00, 12.00, 8.00, 7.00, 1.00, 3.00, 6.00, 10.00, 12.00, 1.00, 16.00, 5.00, 5.00, 6.00, 
+  17.00, 15.00, 15.00, 9.00, 4.00, 18.00, 17.00, 13.00, 12.00, 9.00, 7.00, 10.00, 2.00, 5.00, 8.00, 18.00, 1.00, 15.00, 8.00, 0.00
+};
+
+static data_t verify_data[DATA_SIZE] = 
+{
+  8.00, 21.00, 10.00, 21.00, 20.00, 16.00, 3.00, 20.00, 15.00, 17.00, 15.00, 10.00, 23.00, 27.00, 24.00, 17.00, 18.00, 18.00, 16.00, 17.00, 
+  17.00, 13.00, 25.00, 29.00, 24.00, 14.00, 29.00, 17.00, 14.00, 21.00, 22.00, 19.00, 4.00, 18.00, 26.00, 18.00, 19.00, 29.00, 14.00, 11.00, 
+  23.00, 19.00, 17.00, 29.00, 24.00, 13.00, 23.00, 20.00, 28.00, 25.00, 13.00, 30.00, 28.00, 24.00, 27.00, 13.00, 6.00, 20.00, 27.00, 17.00, 
+  18.00, 24.00, 6.00, 30.00, 24.00, 12.00, 20.00, 31.00, 14.00, 13.00, 10.00, 25.00, 20.00, 11.00, 13.00, 18.00, 23.00, 7.00, 10.00, 27.00, 
+  17.00, 5.00, 21.00, 16.00, 22.00, 21.00, 21.00, 19.00, 20.00, 7.00, 29.00, 6.00, 34.00, 21.00, 16.00, 13.00, 18.00, 21.00, 20.00, 10.00, 
+  27.00, 25.00, 10.00, 5.00, 16.00, 27.00, 26.00, 25.00, 27.00, 23.00, 18.00, 34.00, 17.00, 9.00, 10.00, 17.00, 17.00, 16.00, 12.00, 23.00, 
+  14.00, 5.00, 15.00, 21.00, 20.00, 13.00, 18.00, 12.00, 35.00, 16.00, 33.00, 32.00, 11.00, 29.00, 31.00, 15.00, 12.00, 16.00, 12.00, 16.00, 
+  25.00, 9.00, 21.00, 8.00, 7.00, 14.00, 21.00, 9.00, 23.00, 28.00, 21.00, 11.00, 11.00, 11.00, 13.00, 9.00, 25.00, 23.00, 8.00, 17.00, 
+  15.00, 16.00, 18.00, 20.00, 25.00, 24.00, 6.00, 16.00, 25.00, 17.00, 18.00, 19.00, 20.00, 20.00, 16.00, 15.00, 5.00, 22.00, 15.00, 31.00, 
+  21.00, 31.00, 12.00, 34.00, 28.00, 15.00, 2.00, 19.00, 14.00, 3.00, 9.00, 13.00, 22.00, 19.00, 6.00, 10.00, 19.00, 6.00, 29.00, 12.00, 
+  27.00, 27.00, 21.00, 20.00, 27.00, 12.00, 3.00, 10.00, 12.00, 12.00, 32.00, 19.00, 26.00, 7.00, 7.00, 10.00, 32.00, 11.00, 13.00, 23.00, 
+  19.00, 24.00, 25.00, 16.00, 22.00, 22.00, 5.00, 12.00, 21.00, 17.00, 23.00, 18.00, 22.00, 1.00, 12.00, 18.00, 8.00, 21.00, 6.00, 20.00, 
+  28.00, 8.00, 27.00, 10.00, 25.00, 13.00, 21.00, 25.00, 13.00, 32.00, 33.00, 16.00, 11.00, 4.00, 28.00, 20.00, 11.00, 23.00, 19.00, 28.00, 
+  22.00, 14.00, 21.00, 11.00, 14.00, 22.00, 1.00, 11.00, 7.00, 11.00, 20.00, 30.00, 13.00, 23.00, 23.00, 16.00, 9.00, 20.00, 29.00, 20.00, 
+  21.00, 27.00, 13.00, 26.00, 8.00, 17.00, 19.00, 9.00, 10.00, 6.00, 6.00, 18.00, 13.00, 17.00, 28.00, 17.00, 21.00, 22.00, 5.00, 15.00, 
+  17.00, 14.00, 9.00, 14.00, 18.00, 17.00, 8.00, 17.00, 23.00, 20.00, 2.00, 0.00, 27.00, 16.00, 15.00, 21.00, 20.00, 25.00, 17.00, 12.00, 
+  22.00, 24.00, 21.00, 8.00, 14.00, 28.00, 29.00, 19.00, 8.00, 24.00, 4.00, 11.00, 13.00, 2.00, 23.00, 29.00, 13.00, 34.00, 27.00, 22.00, 
+  17.00, 3.00, 21.00, 15.00, 13.00, 25.00, 18.00, 20.00, 12.00, 10.00, 27.00, 28.00, 22.00, 22.00, 14.00, 6.00, 25.00, 29.00, 15.00, 12.00, 
+  28.00, 11.00, 15.00, 5.00, 4.00, 20.00, 10.00, 4.00, 22.00, 3.00, 27.00, 31.00, 29.00, 20.00, 7.00, 3.00, 7.00, 28.00, 17.00, 14.00, 
+  17.00, 10.00, 8.00, 7.00, 12.00, 21.00, 34.00, 20.00, 9.00, 22.00, 19.00, 21.00, 25.00, 24.00, 18.00, 14.00, 23.00, 23.00, 9.00, 15.00, 
+  19.00, 7.00, 20.00, 32.00, 20.00, 27.00, 27.00, 30.00, 27.00, 32.00, 8.00, 19.00, 21.00, 28.00, 16.00, 25.00, 13.00, 22.00, 24.00, 13.00, 
+  21.00, 16.00, 10.00, 23.00, 21.00, 11.00, 25.00, 19.00, 21.00, 14.00, 14.00, 26.00, 30.00, 12.00, 5.00, 26.00, 22.00, 11.00, 7.00, 16.00, 
+  12.00, 22.00, 14.00, 23.00, 21.00, 28.00, 31.00, 20.00, 1.00, 23.00, 30.00, 32.00, 16.00, 14.00, 9.00, 23.00, 21.00, 31.00, 3.00, 23.00, 
+  17.00, 7.00, 22.00, 6.00, 30.00, 4.00, 7.00, 22.00, 17.00, 17.00, 19.00, 18.00, 31.00, 11.00, 18.00, 11.00, 22.00, 12.00, 29.00, 15.00, 
+  35.00, 11.00, 12.00, 17.00, 18.00, 29.00, 17.00, 33.00, 33.00, 15.00, 27.00, 20.00, 29.00, 14.00, 23.00, 15.00, 21.00, 18.00, 20.00, 17.00, 
+  24.00, 5.00, 29.00, 13.00, 19.00, 18.00, 19.00, 13.00, 5.00, 16.00, 22.00, 14.00, 25.00, 21.00, 7.00, 17.00, 19.00, 15.00, 5.00, 16.00, 
+  33.00, 28.00, 10.00, 24.00, 24.00, 13.00, 11.00, 17.00, 12.00, 28.00, 21.00, 5.00, 19.00, 25.00, 13.00, 5.00, 10.00, 25.00, 21.00, 17.00, 
+  13.00, 20.00, 9.00, 16.00, 24.00, 18.00, 16.00, 22.00, 19.00, 10.00, 0.00, 14.00, 21.00, 24.00, 23.00, 10.00, 33.00, 23.00, 21.00, 17.00, 
+  17.00, 19.00, 26.00, 22.00, 12.00, 27.00, 31.00, 23.00, 6.00, 32.00, 12.00, 10.00, 9.00, 19.00, 18.00, 18.00, 20.00, 24.00, 17.00, 7.00, 
+  21.00, 27.00, 14.00, 20.00, 5.00, 19.00, 11.00, 18.00, 25.00, 1.00, 12.00, 21.00, 13.00, 26.00, 20.00, 3.00, 17.00, 28.00, 18.00, 16.00, 
+  13.00, 11.00, 11.00, 24.00, 2.00, 27.00, 18.00, 19.00, 18.00, 16.00, 25.00, 15.00, 9.00, 19.00, 26.00, 24.00, 19.00, 13.00, 16.00, 12.00, 
+  25.00, 12.00, 12.00, 24.00, 20.00, 9.00, 22.00, 6.00, 13.00, 11.00, 11.00, 20.00, 11.00, 22.00, 3.00, 17.00, 25.00, 14.00, 25.00, 16.00, 
+  3.00, 16.00, 23.00, 24.00, 24.00, 29.00, 24.00, 6.00, 12.00, 14.00, 23.00, 29.00, 23.00, 26.00, 14.00, 35.00, 17.00, 20.00, 12.00, 25.00, 
+  2.00, 29.00, 16.00, 3.00, 17.00, 32.00, 30.00, 5.00, 31.00, 25.00, 24.00, 29.00, 22.00, 26.00, 7.00, 14.00, 6.00, 11.00, 32.00, 1.00, 
+  18.00, 12.00, 20.00, 16.00, 15.00, 20.00, 19.00, 30.00, 23.00, 11.00, 12.00, 24.00, 13.00, 27.00, 2.00, 3.00, 36.00, 9.00, 13.00, 14.00, 
+  16.00, 23.00, 23.00, 24.00, 13.00, 22.00, 18.00, 26.00, 24.00, 22.00, 28.00, 23.00, 25.00, 28.00, 7.00, 14.00, 31.00, 15.00, 23.00, 25.00, 
+  15.00, 20.00, 15.00, 19.00, 8.00, 27.00, 25.00, 19.00, 21.00, 28.00, 11.00, 14.00, 25.00, 24.00, 11.00, 29.00, 19.00, 25.00, 16.00, 33.00, 
+  18.00, 9.00, 3.00, 13.00, 13.00, 13.00, 21.00, 20.00, 23.00, 7.00, 11.00, 18.00, 25.00, 26.00, 30.00, 12.00, 21.00, 21.00, 27.00, 14.00, 
+  21.00, 31.00, 3.00, 21.00, 14.00, 20.00, 30.00, 20.00, 21.00, 32.00, 27.00, 24.00, 16.00, 31.00, 5.00, 20.00, 14.00, 17.00, 15.00, 16.00, 
+  19.00, 13.00, 4.00, 21.00, 20.00, 29.00, 10.00, 22.00, 19.00, 24.00, 29.00, 14.00, 10.00, 15.00, 18.00, 7.00, 28.00, 17.00, 7.00, 2.00, 
+  1.00, 19.00, 17.00, 23.00, 31.00, 13.00, 20.00, 36.00, 17.00, 27.00, 28.00, 18.00, 20.00, 29.00, 17.00, 23.00, 24.00, 23.00, 26.00, 17.00, 
+  9.00, 26.00, 16.00, 18.00, 10.00, 28.00, 32.00, 20.00, 19.00, 14.00, 22.00, 23.00, 13.00, 22.00, 14.00, 7.00, 20.00, 10.00, 25.00, 9.00, 
+  7.00, 2.00, 31.00, 16.00, 16.00, 22.00, 5.00, 15.00, 26.00, 23.00, 10.00, 18.00, 32.00, 24.00, 15.00, 30.00, 16.00, 13.00, 15.00, 7.00, 
+  11.00, 6.00, 21.00, 14.00, 25.00, 21.00, 11.00, 16.00, 14.00, 26.00, 25.00, 15.00, 22.00, 24.00, 4.00, 19.00, 14.00, 26.00, 22.00, 17.00, 
+  13.00, 14.00, 7.00, 32.00, 20.00, 33.00, 13.00, 7.00, 29.00, 8.00, 26.00, 6.00, 9.00, 13.00, 22.00, 23.00, 8.00, 22.00, 22.00, 10.00, 
+  24.00, 2.00, 17.00, 9.00, 22.00, 30.00, 24.00, 33.00, 25.00, 17.00, 23.00, 9.00, 13.00, 15.00, 23.00, 10.00, 1.00, 22.00, 17.00, 10.00, 
+  32.00, 24.00, 26.00, 4.00, 15.00, 0.00, 27.00, 23.00, 28.00, 23.00, 30.00, 7.00, 16.00, 33.00, 20.00, 14.00, 23.00, 14.00, 20.00, 14.00, 
+  7.00, 25.00, 24.00, 12.00, 29.00, 16.00, 17.00, 20.00, 29.00, 16.00, 13.00, 18.00, 26.00, 18.00, 18.00, 17.00, 13.00, 29.00, 14.00, 17.00, 
+  24.00, 16.00, 21.00, 14.00, 26.00, 9.00, 11.00, 28.00, 25.00, 15.00, 15.00, 12.00, 6.00, 14.00, 27.00, 14.00, 24.00, 18.00, 18.00, 14.00, 
+  32.00, 21.00, 26.00, 13.00, 6.00, 24.00, 22.00, 27.00, 17.00, 26.00, 19.00, 21.00, 19.00, 9.00, 21.00, 25.00, 17.00, 27.00, 15.00, 18.00
+};
+
diff --git a/benchmarks/mt-vvadd/mt-vvadd.c b/benchmarks/mt-vvadd/mt-vvadd.c
new file mode 100644 (file)
index 0000000..497b9bb
--- /dev/null
@@ -0,0 +1,165 @@
+//**************************************************************************
+// Vector-vector add benchmark
+//--------------------------------------------------------------------------
+// Author  : Andrew Waterman
+// TA      : Christopher Celio
+// Student : 
+//
+// This benchmark adds two vectors and writes the results to a
+// third vector. The input data (and reference data) should be
+// generated using the vvadd_gendata.pl perl script and dumped
+// to a file named dataset.h 
+
+// to print out arrays, etc.
+//#define DEBUG
+
+//--------------------------------------------------------------------------
+// Includes 
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+//--------------------------------------------------------------------------
+// Input/Reference Data
+
+typedef float data_t;
+#include "dataset.h"
+  
+//--------------------------------------------------------------------------
+// Basic Utilities and Multi-thread Support
+
+__thread unsigned long coreid;
+unsigned long ncores;
+
+#include "util.h"
+   
+#define stringify_1(s) #s
+#define stringify(s) stringify_1(s)
+#define stats(code) do { \
+    unsigned long _c = -rdcycle(), _i = -rdinstret(); \
+    code; \
+    _c += rdcycle(), _i += rdinstret(); \
+    if (coreid == 0) \
+      printf("%s: %ld cycles, %ld.%ld cycles/iter, %ld.%ld CPI\n", \
+             stringify(code), _c, _c/DATA_SIZE, 10*_c/DATA_SIZE%10, _c/_i, 10*_c/_i%10); \
+  } while(0)
+
+//--------------------------------------------------------------------------
+// Helper functions
+void printArray( char name[], int n, data_t arr[] )
+{
+  int i;
+  if (coreid != 0)
+     return;
+
+  printf( " %10s :", name );
+  for ( i = 0; i < n; i++ )
+    printf( " %4ld ", (long) arr[i] );
+  printf( "\n" );
+}
+      
+void __attribute__((noinline)) verify(size_t n, const data_t* test, const data_t* correct)
+{
+   if (coreid != 0)
+      return;
+
+   size_t i;
+   for (i = 0; i < n; i++)
+   {
+      if (test[i] != correct[i])
+      {
+         printf("FAILED test[%d]= %4ld, correct[%d]= %4ld\n", 
+            i, (long) test[i], i, (long)correct[i]);
+         exit(-1);
+      }
+   }
+   
+   return;
+}
+//--------------------------------------------------------------------------
+// vvadd function
+
+//perform in-place vvadd
+void __attribute__((noinline)) vvadd(size_t n, data_t* __restrict__ x, const data_t* __restrict__ y)
+{
+   size_t i;
+
+   // interleave accesses
+   for (i = coreid; i < n; i+=ncores)
+   {
+      x[i] = x[i] + y[i];
+   }
+}
+
+void __attribute__((noinline)) vvadd_opt(size_t n, data_t* __restrict__ x, const data_t* __restrict__ y)
+{
+   // ***************************** //
+   // **** ADD YOUR CODE HERE ***** //
+   // ***************************** //
+}
+
+//--------------------------------------------------------------------------
+// Main
+//
+// all threads start executing thread_entry(). Use their "coreid" to
+// differentiate between threads (each thread is running on a separate core).
+  
+void thread_entry(int cid, int nc)
+{
+   coreid = cid;
+   ncores = nc;
+
+   // static allocates data in the binary, which is visible to both threads
+   static data_t results_data[DATA_SIZE];
+   
+   // because we're going to perform an in-place vvadd (and we're going to run
+   // it a couple of times) let's copy the input data to a temporary results
+   // array
+   
+   size_t i;
+   if (coreid == 0)
+   {
+      for (i = 0; i < DATA_SIZE; i++)
+         results_data[i] = input1_data[i];
+   }
+
+
+   // Execute the provided, terrible vvadd
+   barrier();
+   stats(vvadd(DATA_SIZE, results_data, input2_data); barrier());
+   
+   // verify
+   verify(DATA_SIZE, results_data, verify_data);
+   
+   // reset results from the first trial
+   if (coreid == 0) 
+   {
+      for (i=0; i < DATA_SIZE; i++)
+         results_data[i] = input1_data[i];
+   }
+   barrier();
+                                            
+   
+   // Execute your faster vvadd
+   barrier();
+   stats(vvadd_opt(DATA_SIZE, results_data, input2_data); barrier());
+
+#ifdef DEBUG
+   printArray("results: ", DATA_SIZE, results_data);
+   printArray("verify : ", DATA_SIZE, verify_data);
+#endif
+   
+   // verify
+   verify(DATA_SIZE, results_data, verify_data);
+   barrier();
+
+   exit(0);
+}
+
diff --git a/benchmarks/mt-vvadd/vvadd_gendata.pl b/benchmarks/mt-vvadd/vvadd_gendata.pl
new file mode 100755 (executable)
index 0000000..a9fceac
--- /dev/null
@@ -0,0 +1,139 @@
+#!/usr/bin/perl -w
+#==========================================================================
+# vvadd_gendata.pl
+#
+# Author : Christopher Batten (cbatten@mit.edu)
+# Date   : April 29, 2005
+#
+(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm;
+#
+# Simple script which creates an input data set and the reference data
+# for the vvadd benchmark.
+#
+ENDMSG
+
+use strict "vars";
+use warnings;
+no  warnings("once");
+use Getopt::Long;
+
+#--------------------------------------------------------------------------
+# Command line processing
+#--------------------------------------------------------------------------
+
+our %opts;
+
+sub usage()
+{
+
+  print "\n";
+  print " Usage: vvadd_gendata.pl [options] \n";
+  print "\n";
+  print " Options:\n";
+  print "  --help  print this message\n";
+  print "  --size  size of input data [1000]\n";
+  print "  --seed  random seed [1]\n";
+  print "$usageMsg";
+
+  exit();
+}
+
+sub processCommandLine()
+{
+
+  $opts{"help"} = 0;
+  $opts{"size"} = 1000;
+  $opts{"seed"} = 1;
+  Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage();
+  $opts{"help"} and usage();
+
+}
+
+#--------------------------------------------------------------------------
+# Helper Functions
+#--------------------------------------------------------------------------
+
+sub printArray
+{
+  my $arrayName = $_[0];
+  my $arrayRef  = $_[1];
+
+  my $numCols = 20;
+  my $arrayLen = scalar(@{$arrayRef});
+
+  print "static data_t ".$arrayName."[DATA_SIZE] = \n";
+  print "{\n";
+
+  if ( $arrayLen <= $numCols ) {
+    print "  ";
+    for ( my $i = 0; $i < $arrayLen; $i++ ) {
+      print sprintf("%3.2f",$arrayRef->[$i]);
+      if ( $i != $arrayLen-1 ) {
+        print ", ";
+      }
+    }
+    print "\n";
+  }
+
+  else {
+    my $numRows = int($arrayLen/$numCols);
+    for ( my $j = 0; $j < $numRows; $j++ ) {
+      print "  ";
+      for ( my $i = 0; $i < $numCols; $i++ ) {
+        my $index = $j*$numCols + $i;
+        print sprintf("%3.2f",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+    if ( $arrayLen > ($numRows*$numCols) ) {
+      print "  ";
+      for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) {
+        my $index = $numCols*$numRows + $i;
+        print sprintf("%3.2f",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+  }
+
+  print  "};\n\n";
+}
+
+#--------------------------------------------------------------------------
+# Main
+#--------------------------------------------------------------------------
+
+sub main()
+{
+
+  processCommandLine();
+  srand($opts{"seed"});
+
+  my @values1;
+  my @values2;
+  my @sum;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    my $value1 = int(rand(19));
+    my $value2 = int(rand(19));
+    push( @values1, $value1 );
+    push( @values2, $value2 );
+    push( @sum, $value1 + $value2 );
+  }
+
+
+  print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n";
+  printArray( "input1_data", \@values1 );
+  printArray( "input2_data", \@values2 );
+  printArray( "verify_data", \@sum );
+
+}
+
+main();
+
diff --git a/benchmarks/multiply/bmark.mk b/benchmarks/multiply/bmark.mk
new file mode 100644 (file)
index 0000000..d6114a1
--- /dev/null
@@ -0,0 +1,30 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which 
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include 
+# the benchmark name as a prefix so that they are unique.
+#
+
+multiply_c_src = \
+       multiply_main.c \
+       multiply.c \
+
+multiply_riscv_src = \
+       crt.S \
+
+multiply_c_objs     = $(patsubst %.c, %.o, $(multiply_c_src))
+multiply_riscv_objs = $(patsubst %.S, %.o, $(multiply_riscv_src))
+
+multiply_host_bin = multiply.host
+$(multiply_host_bin): $(multiply_c_src)
+       $(HOST_COMP) $^ -o $(multiply_host_bin)
+
+multiply_riscv_bin = multiply.riscv
+$(multiply_riscv_bin): $(multiply_c_objs) $(multiply_riscv_objs)
+       $(RISCV_LINK) $(multiply_c_objs) $(multiply_riscv_objs) -o $(multiply_riscv_bin)
+
+junk += $(multiply_c_objs) $(multiply_riscv_objs) \
+        $(multiply_host_bin) $(multiply_riscv_bin)
diff --git a/benchmarks/multiply/dataset1.h b/benchmarks/multiply/dataset1.h
new file mode 100644 (file)
index 0000000..292ad7f
--- /dev/null
@@ -0,0 +1,30 @@
+
+#define DATA_SIZE 100 
+
+int input_data1[DATA_SIZE] = 
+{
+   41, 454, 833, 335, 564,   1, 187, 989, 749, 365, 350, 572, 132,  64, 949, 153, 584, 216, 805, 140, 
+  621, 210,   6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961,  12, 110, 883, 116, 750, 296, 646, 
+  426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258, 
+  539, 647, 569, 509, 203,  88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592,  81, 569, 
+  267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388
+};
+
+int input_data2[DATA_SIZE] = 
+{
+  195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657,  79, 181, 208, 111, 998, 859, 629,  65, 847, 
+  288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761,   4, 241, 494, 
+  478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317,  78, 224, 351, 937, 540, 
+  288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358,  92, 
+  584, 989,  62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332
+};
+
+int verify_data[DATA_SIZE] = 
+{
+  7995, 246522, 799680, 217415, 319224, 979, 65450, 986033, 486101, 297110, 229950, 45188, 23892, 13312, 105339, 152694, 501656, 135864, 52325, 118580, 
+  178848, 147840, 2094, 570284, 131271, 85767, 805450, 423995, 347312, 386140, 183216, 94620, 553536, 6456, 107690, 618100, 88276, 3000, 71336, 319124, 
+  203628, 50000, 156686, 376704, 265577, 485793, 171828, 337792, 141636, 290376, 488838, 42750, 591500, 431520, 119192, 43992, 106176, 95472, 878906, 139320, 
+  155232, 417962, 67711, 86021, 124845, 46376, 169680, 203167, 295251, 532524, 212706, 300375, 232505, 396720, 182646, 709488, 71565, 441040, 28998, 52348, 
+  155928, 941528, 14198, 216800, 331945, 498152, 380432, 506684, 312092, 195408, 124597, 108558, 510367, 151208, 750008, 75433, 723075, 211936, 251175, 128816
+};
+
diff --git a/benchmarks/multiply/multiply.c b/benchmarks/multiply/multiply.c
new file mode 100644 (file)
index 0000000..98b279b
--- /dev/null
@@ -0,0 +1,22 @@
+// *************************************************************************
+// multiply function (c version)
+// -------------------------------------------------------------------------
+
+int multiply( int x, int y )
+{
+
+ int i;
+ int result = 0;
+
+ for (i = 0; i < 32; i++) {
+   if ((x & 0x1) == 1)
+     result = result + y;
+       
+   x = x >> 1;
+   y = y << 1;
+ } 
+ return result;
+
+}
+
diff --git a/benchmarks/multiply/multiply.h b/benchmarks/multiply/multiply.h
new file mode 100644 (file)
index 0000000..6d27795
--- /dev/null
@@ -0,0 +1,9 @@
+//**************************************************************************
+// Software multiply function
+//--------------------------------------------------------------------------
+
+// Simple C version
+int multiply(int x, int y);
+
+// Simple assembly version
+int multiply_asm(int x, int y);
diff --git a/benchmarks/multiply/multiply_gendata.pl b/benchmarks/multiply/multiply_gendata.pl
new file mode 100755 (executable)
index 0000000..b8d8ed5
--- /dev/null
@@ -0,0 +1,142 @@
+#!/usr/bin/perl -w
+#==========================================================================
+# multiply_gendata.pl
+#
+# Author : Christopher Batten (cbatten@mit.edu)
+# Date   : May 9, 2005
+#
+(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm;
+#
+# Simple script which creates an input data set and the reference data 
+# for the multiply benchmark.
+#
+ENDMSG
+
+use strict "vars";
+use warnings;
+no  warnings("once");
+use Getopt::Long;
+
+#--------------------------------------------------------------------------
+# Command line processing
+#--------------------------------------------------------------------------
+
+our %opts;
+
+sub usage()
+{
+
+  print "\n";
+  print " Usage: multiply_gendata.pl [options] \n";
+  print "\n";
+  print " Options:\n";
+  print "  --help  print this message\n";
+  print "  --size  size of input data [750]\n";
+  print "  --seed  random seed [1]\n";
+  print "$usageMsg";
+
+  exit();
+}
+
+sub processCommandLine()
+{
+
+  $opts{"help"} = 0;
+  $opts{"size"} = 750;
+  $opts{"seed"} = 1;
+  Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage();
+  $opts{"help"} and usage();
+
+}
+
+#--------------------------------------------------------------------------
+# Helper Functions
+#--------------------------------------------------------------------------
+
+sub printArray
+{
+  my $arrayName = $_[0];
+  my $arrayRef  = $_[1];
+
+  my $numCols = 20;
+  my $arrayLen = scalar(@{$arrayRef});
+
+  print "int ".$arrayName."[DATA_SIZE] = \n";
+  print "{\n";
+
+  if ( $arrayLen <= $numCols ) {
+    print "  ";
+    for ( my $i = 0; $i < $arrayLen; $i++ ) {
+      print sprintf("%3d",$arrayRef->[$i]);
+      if ( $i != $arrayLen-1 ) {
+        print ", ";
+      }
+    }
+    print "\n";
+  }
+  
+  else {
+    my $numRows = int($arrayLen/$numCols);
+    for ( my $j = 0; $j < $numRows; $j++ ) {
+      print "  ";
+      for ( my $i = 0; $i < $numCols; $i++ ) {
+        my $index = $j*$numCols + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+    if ( $arrayLen > ($numRows*$numCols) ) {
+      print "  ";
+      for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) {
+        my $index = $numCols*$numRows + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+  }
+
+  print  "};\n\n";
+}
+
+#--------------------------------------------------------------------------
+# Main
+#--------------------------------------------------------------------------
+
+sub main()
+{
+
+  processCommandLine();
+  srand($opts{"seed"});
+  
+  my @values1;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    push( @values1, int(rand(999)) );
+  }
+  
+  my @values2;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    push( @values2, int(rand(999)) );
+  }
+
+  my @multiply;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    $multiply[$i] = $values1[$i] * $values2[$i];
+  }
+
+  print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n";
+  printArray( "input_data1", \@values1 );
+  printArray( "input_data2", \@values2 );
+  printArray( "verify_data", \@multiply );
+
+}
+
+main();
+
diff --git a/benchmarks/multiply/multiply_main.c b/benchmarks/multiply/multiply_main.c
new file mode 100644 (file)
index 0000000..fcb6b27
--- /dev/null
@@ -0,0 +1,147 @@
+// *************************************************************************
+// multiply filter bencmark
+// -------------------------------------------------------------------------
+//
+// This benchmark tests the software multiply implemenation. The
+// input data (and reference data) should be generated using the
+// multiply_gendata.pl perl script and dumped to a file named
+// dataset1.h You should not change anything except the
+// HOST_DEBUG and VERIFY macros for your timing run.
+
+#include "multiply.h"
+
+//--------------------------------------------------------------------------
+// Macros
+
+// Set HOST_DEBUG to 1 if you are going to compile this for a host 
+// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG 
+// to 0 if you are compiling with the smips-gcc toolchain.
+
+#ifndef HOST_DEBUG
+#define HOST_DEBUG 0
+#endif
+
+// Set PREALLOCATE to 1 if you want to preallocate the benchmark
+// function before starting stats. If you have instruction/data
+// caches and you don't want to count the overhead of misses, then
+// you will need to use preallocation.
+
+#ifndef PREALLOCATE
+#define PREALLOCATE 0
+#endif
+
+// Set VERIFY to 1 if you want the program to check that the sort
+// function returns the right answer. When you are doing your 
+// benchmarking you should set this to 0 so that the verification
+// is not included in your timing.
+
+#ifndef VERIFY
+#define VERIFY     1
+#endif
+
+// Set SET_STATS to 1 if you want to carve out the piece that actually
+// does the computation.
+
+#ifndef SET_STATS
+#define SET_STATS 0
+#endif
+
+//--------------------------------------------------------------------------
+// Input/Reference Data
+
+#include "dataset1.h"
+
+//--------------------------------------------------------------------------
+// Helper functions
+
+int verify( int n, int test[], int correct[] )
+{
+  int i;
+  for ( i = 0; i < n; i++ ) {
+    if ( test[i] != correct[i] ) {
+      return 2;
+    }
+  }
+  return 1;
+}
+
+#if HOST_DEBUG
+void printArray( char name[], int n, int arr[] )
+{
+  int i;
+  printf( " %10s :", name );
+  for ( i = 0; i < n; i++ )
+    printf( " %3d ", arr[i] );
+  printf( "\n" );
+}
+#endif
+
+void finishTest( int toHostValue )
+{
+#if HOST_DEBUG
+  if ( toHostValue == 1 )
+    printf( "*** PASSED ***\n" );
+  else
+    printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
+  exit(0);
+#else
+  asm( "mtpcr %0, cr30" : : "r" (toHostValue) );
+  while ( 1 ) { }
+#endif
+}
+
+void setStats( int enable )
+{
+#if ( !HOST_DEBUG && SET_STATS )
+  asm( "mtpcr %0, cr10" : : "r" (enable) );
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Main
+
+int main( int argc, char* argv[] )
+{
+  int i;
+  int results_data[DATA_SIZE];
+
+  // Output the input arrays
+
+#if HOST_DEBUG
+  printArray( "input1",  DATA_SIZE, input_data1  );
+  printArray( "input2",  DATA_SIZE, input_data2  );
+  printArray( "verify", DATA_SIZE, verify_data );
+#endif
+
+#if ( !HOST_DEBUG && PREALLOCATE )
+  for (i = 0; i < DATA_SIZE; i++)
+  {
+    results_data[i] = multiply( input_data1[i], input_data2[i] );
+  }
+#endif
+
+#if HOST_DEBUG
+  for (i = 0; i < DATA_SIZE; i++)
+  {
+    results_data[i] = multiply( input_data1[i], input_data2[i] );
+  }
+#else
+  setStats(1);
+  for (i = 0; i < DATA_SIZE; i++)
+  {
+    results_data[i] = multiply( input_data1[i], input_data2[i] );
+  }
+  setStats(0);
+#endif
+  
+  // Print out the results
+
+#if HOST_DEBUG
+  printArray( "results", DATA_SIZE, results_data );
+#endif
+
+  // Check the results
+
+  finishTest(verify( DATA_SIZE, results_data, verify_data ));
+
+}
diff --git a/benchmarks/qsort/bmark.mk b/benchmarks/qsort/bmark.mk
new file mode 100644 (file)
index 0000000..cdc0545
--- /dev/null
@@ -0,0 +1,29 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include
+# the benchmark name as a prefix so that they are unique.
+#
+
+qsort_c_src = \
+       qsort_main.c \
+
+qsort_riscv_src = \
+       crt.S \
+
+qsort_c_objs     = $(patsubst %.c, %.o, $(qsort_c_src))
+qsort_riscv_objs = $(patsubst %.S, %.o, $(qsort_riscv_src))
+
+qsort_host_bin = qsort.host
+$(qsort_host_bin) : $(qsort_c_src)
+       $(HOST_COMP) $^ -o $(qsort_host_bin)
+
+qsort_riscv_bin = qsort.riscv
+$(qsort_riscv_bin) : $(qsort_c_objs) $(qsort_riscv_objs)
+       $(RISCV_LINK) $(qsort_c_objs) $(qsort_riscv_objs) -o $(qsort_riscv_bin)
+
+junk += $(qsort_c_objs) $(qsort_riscv_objs) \
+        $(qsort_host_bin) $(qsort_riscv_bin)
diff --git a/benchmarks/qsort/dataset1.h b/benchmarks/qsort/dataset1.h
new file mode 100644 (file)
index 0000000..c4d99e2
--- /dev/null
@@ -0,0 +1,37 @@
+
+#define DATA_SIZE 250
+
+int input_data[DATA_SIZE] =
+{
+   41, 454, 833, 335, 564,   1, 187, 989, 749, 365, 350, 572, 132,  64, 949, 153, 584, 216, 805, 140,
+  621, 210,   6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961,  12, 110, 883, 116, 750, 296, 646,
+  426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258,
+  539, 647, 569, 509, 203,  88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592,  81, 569,
+  267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388,
+  195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657,  79, 181, 208, 111, 998, 859, 629,  65, 847,
+  288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761,   4, 241, 494,
+  478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317,  78, 224, 351, 937, 540,
+  288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358,  92,
+  584, 989,  62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332,
+  778, 684, 598, 740, 143, 446,  33, 311, 125, 743, 941, 557, 933, 479, 799, 557, 553, 925, 431, 796,
+  648, 357, 952, 891, 287, 666,  19, 514,  49, 557,  86, 870,  95, 853, 441, 440, 587,  61, 614, 678,
+  382, 396, 280,   9, 808,  17, 971, 170, 819, 291
+};
+
+int verify_data[DATA_SIZE] =
+{
+    1,   4,   6,   9,  12,  17,  19,  33,  41,  49,  61,  62,  64,  65,  78,  79,  81,  86,  88,  92,
+   95, 100, 110, 111, 116, 119, 125, 132, 140, 141, 143, 150, 153, 169, 170, 181, 187, 195, 195, 203,
+  208, 210, 216, 222, 222, 224, 228, 229, 241, 241, 241, 253, 255, 258, 264, 267, 271, 272, 278, 280,
+  280, 285, 287, 288, 288, 289, 291, 296, 296, 311, 313, 314, 317, 319, 328, 332, 335, 337, 339, 346,
+  349, 350, 350, 351, 351, 357, 358, 358, 365, 367, 368, 375, 376, 382, 388, 389, 392, 396, 403, 403,
+  415, 416, 426, 430, 431, 436, 440, 441, 444, 446, 454, 455, 461, 474, 478, 479, 489, 494, 499, 500,
+  509, 511, 514, 517, 527, 531, 538, 539, 540, 543, 551, 553, 557, 557, 557, 559, 564, 564, 566, 569,
+  569, 572, 572, 576, 584, 584, 584, 587, 592, 592, 593, 598, 606, 606, 614, 615, 620, 621, 629, 643,
+  646, 646, 647, 648, 649, 649, 657, 657, 659, 666, 669, 676, 678, 678, 684, 693, 694, 696, 700, 701,
+  703, 704, 715, 720, 721, 740, 743, 745, 749, 750, 758, 759, 761, 774, 775, 778, 788, 796, 796, 799,
+  800, 801, 805, 808, 812, 814, 819, 826, 833, 847, 853, 853, 859, 864, 870, 875, 883, 886, 890, 891,
+  898, 902, 905, 908, 913, 925, 931, 933, 933, 936, 937, 938, 941, 944, 949, 952, 952, 960, 961, 971,
+  979, 979, 981, 985, 985, 989, 989, 997, 997, 998
+};
+
diff --git a/benchmarks/qsort/qsort_gendata.pl b/benchmarks/qsort/qsort_gendata.pl
new file mode 100755 (executable)
index 0000000..0a1af61
--- /dev/null
@@ -0,0 +1,132 @@
+#!/usr/bin/perl -w
+#==========================================================================
+# qsort_gendata.pl
+#
+# Author : Christopher Batten (cbatten@mit.edu)
+# Date   : April 29, 2005
+#
+(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm;
+#
+# Simple script which creates an input data set and the reference data
+# for the qsort benchmark.
+#
+ENDMSG
+
+use strict "vars";
+use warnings;
+no  warnings("once");
+use Getopt::Long;
+
+#--------------------------------------------------------------------------
+# Command line processing
+#--------------------------------------------------------------------------
+
+our %opts;
+
+sub usage()
+{
+
+  print "\n";
+  print " Usage: qsort_gendata.pl [options] \n";
+  print "\n";
+  print " Options:\n";
+  print "  --help  print this message\n";
+  print "  --size  size of input data [250]\n";
+  print "  --seed  random seed [1]\n";
+  print "$usageMsg";
+
+  exit();
+}
+
+sub processCommandLine()
+{
+
+  $opts{"help"} = 0;
+  $opts{"size"} = 250;
+  $opts{"seed"} = 1;
+  Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage();
+  $opts{"help"} and usage();
+
+}
+
+#--------------------------------------------------------------------------
+# Helper Functions
+#--------------------------------------------------------------------------
+
+sub printArray
+{
+  my $arrayName = $_[0];
+  my $arrayRef  = $_[1];
+
+  my $numCols = 20;
+  my $arrayLen = scalar(@{$arrayRef});
+
+  print "int ".$arrayName."[DATA_SIZE] = \n";
+  print "{\n";
+
+  if ( $arrayLen <= $numCols ) {
+    print "  ";
+    for ( my $i = 0; $i < $arrayLen; $i++ ) {
+      print sprintf("%3d",$arrayRef->[$i]);
+      if ( $i != $arrayLen-1 ) {
+        print ", ";
+      }
+    }
+    print "\n";
+  }
+
+  else {
+    my $numRows = int($arrayLen/$numCols);
+    for ( my $j = 0; $j < $numRows; $j++ ) {
+      print "  ";
+      for ( my $i = 0; $i < $numCols; $i++ ) {
+        my $index = $j*$numCols + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+    if ( $arrayLen > ($numRows*$numCols) ) {
+      print "  ";
+      for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) {
+        my $index = $numCols*$numRows + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+  }
+
+  print  "};\n\n";
+}
+
+#--------------------------------------------------------------------------
+# Main
+#--------------------------------------------------------------------------
+
+sub main()
+{
+
+  processCommandLine();
+  srand($opts{"seed"});
+
+  my @values;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    push( @values, int(rand(999)) );
+  }
+  my @sorted = sort { $a <=> $b } @values;
+
+  print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n";
+  printArray( "input_data", \@values );
+  printArray( "verify_data", \@sorted );
+
+}
+
+main();
+
diff --git a/benchmarks/qsort/qsort_main.c b/benchmarks/qsort/qsort_main.c
new file mode 100644 (file)
index 0000000..6de1613
--- /dev/null
@@ -0,0 +1,239 @@
+//**************************************************************************
+// Quicksort benchmark
+//--------------------------------------------------------------------------
+//
+// This benchmark uses quicksort to sort an array of integers. The
+// implementation is largely adapted from Numerical Recipes for C. The
+// input data (and reference data) should be generated using the
+// qsort_gendata.pl perl script and dumped to a file named
+// dataset1.h The smips-gcc toolchain does not support system calls
+// so printf's can only be used on a host system, not on the smips
+// processor simulator itself. You should not change anything except
+// the HOST_DEBUG and PREALLOCATE macros for your timing run.
+
+//--------------------------------------------------------------------------
+// Macros
+
+// Set HOST_DEBUG to 1 if you are going to compile this for a host
+// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
+// to 0 if you are compiling with the smips-gcc toolchain.
+
+#ifndef HOST_DEBUG
+#define HOST_DEBUG 0
+#endif
+
+// Set PREALLOCATE to 1 if you want to preallocate the benchmark
+// function before starting stats. If you have instruction/data
+// caches and you don't want to count the overhead of misses, then
+// you will need to use preallocation.
+
+#ifndef PREALLOCATE
+#define PREALLOCATE 0
+#endif
+
+// Set SET_STATS to 1 if you want to carve out the piece that actually
+// does the computation.
+
+#ifndef SET_STATS
+#define SET_STATS 0
+#endif
+
+// The INSERTION_THRESHOLD is the size of the subarray when the
+// algorithm switches to using an insertion sort instead of
+// quick sort.
+
+#define INSERTION_THRESHOLD 7
+
+// NSTACK is the required auxiliary storage.
+// It must be at least 2*lg(DATA_SIZE)
+
+#define NSTACK 50
+
+// Swap macro for swapping two values.
+
+#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp;
+
+//--------------------------------------------------------------------------
+// Input/Reference Data
+
+#include "dataset1.h"
+
+//--------------------------------------------------------------------------
+// Helper functions
+
+int verify( int n, int test[], int correct[] )
+{
+  int i;
+  for ( i = 0; i < n; i++ ) {
+    if ( test[i] != correct[i] ) {
+      return 2;
+    }
+  }
+  return 1;
+}
+
+#if HOST_DEBUG
+void printArray( char name[], int n, int arr[] )
+{
+  int i;
+  printf( " %10s :", name );
+  for ( i = 0; i < n; i++ )
+    printf( " %3d ", arr[i] );
+  printf( "\n" );
+}
+#endif
+
+void finishTest( int toHostValue )
+{
+#if HOST_DEBUG
+  if ( toHostValue == 1 )
+    printf( "*** PASSED ***\n" );
+  else
+    printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
+  exit(0);
+#else
+  asm( "mtpcr %0, cr30" : : "r" (toHostValue) );
+  while ( 1 ) { }
+#endif
+}
+
+void setStats( int enable )
+{
+#if ( !HOST_DEBUG && SET_STATS )
+  asm( "mtpcr %0, cr10" : : "r" (enable) );
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Quicksort function
+
+void sort( int n, int arr[] )
+{
+  int i,j,k;
+  int ir = n;
+  int l = 1;
+  int jstack = 0;
+  int a, temp;
+
+  int istack[NSTACK];
+
+  for (;;) {
+
+#if HOST_DEBUG
+    printArray( "", n, arr );
+#endif
+
+    // Insertion sort when subarray small enough.
+    if ( ir-l < INSERTION_THRESHOLD ) {
+
+      for ( j = l+1; j <= ir; j++ ) {
+        a = arr[j-1];
+        for ( i = j-1; i >= l; i-- ) {
+          if ( arr[i-1] <= a ) break;
+          arr[i] = arr[i-1];
+        }
+        arr[i] = a;
+      }
+
+      if ( jstack == 0 ) break;
+
+      // Pop stack and begin a new round of partitioning.
+      ir = istack[jstack--];
+      l = istack[jstack--];
+
+    }
+    else {
+
+      // Choose median of left, center, and right elements as
+      // partitioning element a. Also rearrange so that a[l-1] <= a[l] <= a[ir-].
+
+      k = (l+ir) >> 1;
+      SWAP(arr[k-1],arr[l])
+      if ( arr[l-1] > arr[ir-1] ) {
+        SWAP(arr[l-1],arr[ir-1])
+      }
+      if ( arr[l] > arr[ir-1] ) {
+        SWAP(arr[l],arr[ir-1])
+      }
+      if ( arr[l-1] > arr[l] ) {
+        SWAP(arr[l-1],arr[l])
+      }
+
+      // Initialize pointers for partitioning.
+      i = l+1;
+      j = ir;
+
+      // Partitioning element.
+      a = arr[l];
+
+      for (;;) {                       // Beginning of innermost loop.
+        do i++; while (arr[i-1] < a);  // Scan up to find element > a.
+        do j--; while (arr[j-1] > a);  // Scan down to find element < a.
+        if (j < i) break;              // Pointers crossed. Partitioning complete.
+        SWAP(arr[i-1],arr[j-1]);       // Exchange elements.
+      }                                // End of innermost loop.
+
+      // Insert partitioning element.
+      arr[l] = arr[j-1];
+      arr[j-1] = a;
+      jstack += 2;
+
+      // Push pointers to larger subarray on stack,
+      // process smaller subarray immediately.
+
+#if HOST_DEBUG
+      if ( jstack > NSTACK ) { printf("NSTACK too small in sort.\n"); exit(1); }
+#endif
+
+      if ( ir-i+1 >= j-l ) {
+        istack[jstack]   = ir;
+        istack[jstack-1] = i;
+        ir = j-1;
+      }
+      else {
+        istack[jstack]   = j-1;
+        istack[jstack-1] = l;
+        l = i;
+      }
+    }
+
+  }
+
+}
+
+//--------------------------------------------------------------------------
+// Main
+
+int main( int argc, char* argv[] )
+{
+
+  // Output the input array
+
+#if HOST_DEBUG
+  printArray( "input", DATA_SIZE, input_data );
+  printArray( "verify", DATA_SIZE, verify_data );
+#endif
+
+  // If needed we preallocate everything in the caches
+
+#if PREALLOCATE
+  sort( DATA_SIZE, input_data );
+#endif
+
+  // Do the sort
+
+  setStats(1);
+  sort( DATA_SIZE, input_data );
+  setStats(0);
+
+  // Print out the results
+
+#if HOST_DEBUG
+  printArray( "test", DATA_SIZE, input_data );
+#endif
+
+  // Check the results
+
+  finishTest(verify( DATA_SIZE, input_data, verify_data ));
+
+}
diff --git a/benchmarks/readme.txt b/benchmarks/readme.txt
new file mode 100644 (file)
index 0000000..a14780f
--- /dev/null
@@ -0,0 +1,55 @@
+*************************************************************************
+Benchmarks for RISCV Processor
+-------------------------------------------------------------------------
+
+The benchmarks make use of the RISCV C compiler toolchain. You will need
+to include a bmark.mk makefile fragment in each benchmark directory. The
+fragment should include the object files and a rule to actually link
+these object files into an executable. There are a couple important
+points to make about the toolchain.
+
+ + The toolchain sets the stack pointer to memory address 0x20000 so your
+   main memory _must_ be larger than 0x20000 bytes or else the stack will
+   get wrapped around and overwrite program data.
+
+ + The stack grows down from 0x20000 and your program is loaded at 0x1000.
+   If you have a very large program and have lots of very big arrays
+   declared on the stack your stack could overwrite your program. Be aware.
+
+ + You cannot use standard clib functions (like memcopy or strcat). You
+   cannot use system calls and thus cannot use printf.
+
+ + You cannot access the simulated command line - ie you cannot use argc
+   and argv within main.
+
+ + You may have to increase the timeout check in your test harness to
+   allow longer programs to run (you can do this from the command line
+   option +max-cycles with the standard test harness)
+
+ + The compiler loads the program at 0x1000. It does not insert exception
+   setup code. So if you are careful with what C you use it will only
+   generate code in the riscv lab1 subset. If you use multiplies, shorts,
+   and chars it could generate mul, lh, and lb instructions. Be aware.
+
+ + You can write assembly in C - you need to do this to write tohost to 1
+   to indicate when the benchmark is done. Look at the example
+   benchmarks to see how this is done. You can find more information
+   about how to write assembly in C here:
+   http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
+
+ + If you look at the example benchmarks you will see that I have two
+   important macros HOST_DEBUG and VERIFY. Use HOST_DEBUG to compile the
+   benchmark on your host workstation (ie use standard gcc on Athena/Linux
+   box) and then debug the benchmark. Since you are using standard gcc you
+   can use printf's to make sure that your benchmark actually works before
+   trying it out on your RISCV processor.
+
+ + Debugging C compiled code on the RISCV processor is a real pain. It is
+   hard to associate the assembly with the C code and there is no
+   debugger. So if you encounter a bug in your processor when running a C
+   benchmark you can try to debug it, but you might have better luck
+   adding more assembly tests to your test suite.
+
+ + To avoid having the compiler try and use a global pointer (ie using
+   register 28 to point to a space where small global variables are
+   stored) you need to use the -G 0 command line option.
diff --git a/benchmarks/spmv/bmark.mk b/benchmarks/spmv/bmark.mk
new file mode 100644 (file)
index 0000000..5ab9cc0
--- /dev/null
@@ -0,0 +1,29 @@
+#=======================================================================
+# UCB CS250 Makefile fragment for benchmarks
+#-----------------------------------------------------------------------
+#
+# Each benchmark directory should have its own fragment which
+# essentially lists what the source files are and how to link them
+# into an riscv and/or host executable. All variables should include
+# the benchmark name as a prefix so that they are unique.
+#
+
+spmv_c_src = \
+       spmv_main.c \
+
+spmv_riscv_src = \
+       crt.S \
+
+spmv_c_objs     = $(patsubst %.c, %.o, $(spmv_c_src))
+spmv_riscv_objs = $(patsubst %.S, %.o, $(spmv_riscv_src))
+
+spmv_host_bin = spmv.host
+$(spmv_host_bin) : $(spmv_c_src)
+       $(HOST_COMP) $^ -o $(spmv_host_bin)
+
+spmv_riscv_bin = spmv.riscv
+$(spmv_riscv_bin) : $(spmv_c_objs) $(spmv_riscv_objs)
+       $(RISCV_LINK) $(spmv_c_objs) $(spmv_riscv_objs) -o $(spmv_riscv_bin)
+
+junk += $(spmv_c_objs) $(spmv_riscv_objs) \
+        $(spmv_host_bin) $(spmv_riscv_bin)
diff --git a/benchmarks/spmv/dataset1.h b/benchmarks/spmv/dataset1.h
new file mode 100644 (file)
index 0000000..ebdf7ff
--- /dev/null
@@ -0,0 +1,23022 @@
+#define R 1000
+#define C 1000
+#define NNZ 10004
+const double val[10004] = {
+  658,
+  279,
+  587,
+  255,
+  359,
+  844,
+  905,
+  456,
+  897,
+  837,
+  652,
+  398,
+  885,
+  21,
+  669,
+  738,
+  365,
+  928,
+  713,
+  771,
+  536,
+  987,
+  917,
+  823,
+  544,
+  40,
+  80,
+  636,
+  263,
+  929,
+  757,
+  677,
+  151,
+  500,
+  875,
+  720,
+  205,
+  292,
+  859,
+  980,
+  97,
+  608,
+  813,
+  840,
+  397,
+  765,
+  294,
+  718,
+  751,
+  7,
+  482,
+  166,
+  653,
+  172,
+  187,
+  79,
+  228,
+  857,
+  540,
+  760,
+  509,
+  190,
+  396,
+  765,
+  37,
+  85,
+  866,
+  981,
+  999,
+  793,
+  921,
+  664,
+  208,
+  856,
+  528,
+  782,
+  318,
+  170,
+  521,
+  691,
+  726,
+  996,
+  947,
+  326,
+  825,
+  77,
+  823,
+  752,
+  266,
+  834,
+  196,
+  58,
+  430,
+  764,
+  807,
+  568,
+  665,
+  583,
+  178,
+  250,
+  273,
+  654,
+  487,
+  504,
+  729,
+  338,
+  866,
+  981,
+  852,
+  842,
+  785,
+  13,
+  588,
+  44,
+  432,
+  408,
+  374,
+  761,
+  653,
+  752,
+  684,
+  6,
+  357,
+  703,
+  447,
+  966,
+  457,
+  738,
+  646,
+  646,
+  217,
+  522,
+  839,
+  417,
+  506,
+  801,
+  233,
+  929,
+  487,
+  353,
+  660,
+  751,
+  738,
+  512,
+  566,
+  130,
+  61,
+  128,
+  698,
+  467,
+  362,
+  867,
+  639,
+  289,
+  371,
+  427,
+  650,
+  16,
+  878,
+  967,
+  369,
+  517,
+  161,
+  330,
+  294,
+  396,
+  606,
+  638,
+  171,
+  602,
+  531,
+  14,
+  968,
+  15,
+  193,
+  225,
+  863,
+  171,
+  254,
+  714,
+  256,
+  873,
+  353,
+  35,
+  910,
+  849,
+  658,
+  546,
+  389,
+  239,
+  355,
+  540,
+  494,
+  968,
+  319,
+  590,
+  608,
+  445,
+  806,
+  51,
+  117,
+  401,
+  314,
+  280,
+  334,
+  44,
+  17,
+  107,
+  108,
+  650,
+  807,
+  385,
+  748,
+  942,
+  719,
+  110,
+  630,
+  559,
+  717,
+  375,
+  963,
+  45,
+  403,
+  476,
+  408,
+  732,
+  87,
+  874,
+  635,
+  119,
+  190,
+  949,
+  777,
+  201,
+  503,
+  658,
+  777,
+  564,
+  830,
+  122,
+  929,
+  68,
+  11,
+  354,
+  395,
+  213,
+  766,
+  40,
+  995,
+  577,
+  514,
+  568,
+  56,
+  439,
+  91,
+  148,
+  612,
+  717,
+  157,
+  538,
+  682,
+  190,
+  571,
+  847,
+  275,
+  190,
+  824,
+  985,
+  29,
+  426,
+  173,
+  898,
+  297,
+  156,
+  936,
+  1,
+  455,
+  812,
+  173,
+  131,
+  376,
+  947,
+  596,
+  783,
+  800,
+  361,
+  798,
+  598,
+  710,
+  86,
+  149,
+  457,
+  129,
+  437,
+  352,
+  933,
+  320,
+  709,
+  167,
+  793,
+  46,
+  49,
+  305,
+  704,
+  577,
+  855,
+  336,
+  978,
+  206,
+  662,
+  230,
+  93,
+  898,
+  368,
+  422,
+  689,
+  351,
+  87,
+  465,
+  576,
+  33,
+  884,
+  675,
+  548,
+  116,
+  730,
+  385,
+  483,
+  340,
+  809,
+  938,
+  342,
+  576,
+  887,
+  479,
+  455,
+  820,
+  521,
+  320,
+  488,
+  506,
+  591,
+  901,
+  505,
+  525,
+  5,
+  133,
+  705,
+  561,
+  285,
+  95,
+  918,
+  410,
+  578,
+  347,
+  375,
+  735,
+  624,
+  491,
+  494,
+  931,
+  655,
+  819,
+  883,
+  328,
+  527,
+  194,
+  580,
+  584,
+  837,
+  700,
+  681,
+  249,
+  643,
+  958,
+  363,
+  316,
+  397,
+  638,
+  261,
+  459,
+  960,
+  636,
+  458,
+  84,
+  797,
+  696,
+  782,
+  831,
+  419,
+  393,
+  649,
+  312,
+  811,
+  703,
+  70,
+  688,
+  285,
+  39,
+  617,
+  935,
+  495,
+  392,
+  143,
+  734,
+  166,
+  406,
+  464,
+  732,
+  709,
+  379,
+  143,
+  527,
+  514,
+  709,
+  130,
+  965,
+  632,
+  448,
+  836,
+  62,
+  567,
+  600,
+  520,
+  519,
+  16,
+  394,
+  705,
+  438,
+  548,
+  696,
+  140,
+  573,
+  509,
+  968,
+  935,
+  165,
+  868,
+  577,
+  451,
+  865,
+  304,
+  777,
+  828,
+  147,
+  704,
+  821,
+  641,
+  783,
+  376,
+  757,
+  391,
+  170,
+  592,
+  235,
+  920,
+  846,
+  683,
+  249,
+  697,
+  253,
+  386,
+  244,
+  889,
+  607,
+  768,
+  88,
+  836,
+  259,
+  945,
+  33,
+  352,
+  70,
+  83,
+  996,
+  791,
+  18,
+  599,
+  488,
+  43,
+  582,
+  993,
+  692,
+  841,
+  558,
+  530,
+  350,
+  187,
+  295,
+  215,
+  869,
+  593,
+  385,
+  722,
+  724,
+  282,
+  681,
+  534,
+  788,
+  836,
+  378,
+  825,
+  93,
+  539,
+  120,
+  794,
+  384,
+  798,
+  505,
+  833,
+  27,
+  181,
+  951,
+  966,
+  498,
+  375,
+  22,
+  545,
+  62,
+  816,
+  119,
+  712,
+  813,
+  783,
+  655,
+  832,
+  143,
+  501,
+  519,
+  43,
+  760,
+  17,
+  896,
+  96,
+  390,
+  121,
+  458,
+  736,
+  649,
+  227,
+  778,
+  283,
+  657,
+  434,
+  214,
+  123,
+  929,
+  548,
+  206,
+  993,
+  463,
+  824,
+  369,
+  260,
+  868,
+  645,
+  857,
+  184,
+  198,
+  349,
+  652,
+  522,
+  23,
+  208,
+  968,
+  290,
+  770,
+  109,
+  978,
+  513,
+  298,
+  675,
+  306,
+  866,
+  927,
+  822,
+  495,
+  653,
+  134,
+  702,
+  147,
+  366,
+  947,
+  65,
+  586,
+  412,
+  638,
+  760,
+  541,
+  118,
+  551,
+  574,
+  85,
+  736,
+  999,
+  917,
+  478,
+  35,
+  629,
+  963,
+  898,
+  826,
+  113,
+  298,
+  606,
+  568,
+  152,
+  926,
+  277,
+  984,
+  549,
+  279,
+  839,
+  348,
+  672,
+  278,
+  94,
+  455,
+  590,
+  843,
+  85,
+  222,
+  901,
+  621,
+  30,
+  880,
+  914,
+  27,
+  974,
+  399,
+  873,
+  968,
+  870,
+  479,
+  696,
+  964,
+  929,
+  499,
+  121,
+  812,
+  933,
+  799,
+  506,
+  412,
+  712,
+  791,
+  426,
+  835,
+  488,
+  910,
+  522,
+  332,
+  967,
+  380,
+  61,
+  5,
+  282,
+  119,
+  22,
+  136,
+  436,
+  730,
+  341,
+  687,
+  371,
+  19,
+  893,
+  20,
+  327,
+  221,
+  221,
+  966,
+  354,
+  198,
+  985,
+  56,
+  305,
+  691,
+  980,
+  12,
+  790,
+  64,
+  484,
+  621,
+  214,
+  332,
+  898,
+  898,
+  318,
+  416,
+  445,
+  350,
+  317,
+  336,
+  714,
+  788,
+  541,
+  890,
+  42,
+  111,
+  596,
+  164,
+  424,
+  448,
+  666,
+  362,
+  429,
+  617,
+  910,
+  917,
+  970,
+  526,
+  321,
+  551,
+  481,
+  83,
+  46,
+  146,
+  569,
+  856,
+  85,
+  192,
+  724,
+  378,
+  299,
+  13,
+  422,
+  411,
+  552,
+  569,
+  100,
+  849,
+  484,
+  906,
+  47,
+  532,
+  742,
+  415,
+  228,
+  897,
+  715,
+  807,
+  329,
+  244,
+  312,
+  903,
+  758,
+  34,
+  172,
+  18,
+  917,
+  700,
+  108,
+  611,
+  567,
+  616,
+  572,
+  174,
+  925,
+  553,
+  903,
+  268,
+  544,
+  998,
+  708,
+  133,
+  717,
+  584,
+  517,
+  608,
+  680,
+  597,
+  316,
+  470,
+  764,
+  530,
+  221,
+  405,
+  133,
+  406,
+  506,
+  56,
+  458,
+  721,
+  935,
+  356,
+  130,
+  99,
+  395,
+  117,
+  34,
+  881,
+  231,
+  214,
+  248,
+  458,
+  246,
+  632,
+  471,
+  279,
+  385,
+  594,
+  855,
+  305,
+  30,
+  542,
+  144,
+  509,
+  548,
+  364,
+  171,
+  386,
+  382,
+  616,
+  997,
+  28,
+  361,
+  855,
+  449,
+  992,
+  956,
+  439,
+  569,
+  383,
+  523,
+  852,
+  337,
+  112,
+  24,
+  902,
+  352,
+  542,
+  231,
+  664,
+  411,
+  457,
+  572,
+  52,
+  760,
+  88,
+  907,
+  345,
+  284,
+  636,
+  219,
+  975,
+  713,
+  231,
+  888,
+  49,
+  624,
+  179,
+  579,
+  401,
+  694,
+  984,
+  905,
+  673,
+  414,
+  773,
+  165,
+  349,
+  436,
+  128,
+  186,
+  487,
+  17,
+  552,
+  833,
+  98,
+  424,
+  791,
+  220,
+  352,
+  75,
+  470,
+  405,
+  679,
+  939,
+  792,
+  653,
+  142,
+  226,
+  208,
+  629,
+  429,
+  55,
+  455,
+  362,
+  210,
+  765,
+  693,
+  113,
+  656,
+  824,
+  441,
+  191,
+  50,
+  957,
+  99,
+  27,
+  582,
+  461,
+  279,
+  299,
+  492,
+  678,
+  452,
+  640,
+  349,
+  758,
+  298,
+  903,
+  361,
+  333,
+  339,
+  60,
+  824,
+  773,
+  184,
+  621,
+  66,
+  49,
+  228,
+  608,
+  523,
+  591,
+  533,
+  234,
+  566,
+  291,
+  646,
+  93,
+  42,
+  810,
+  154,
+  846,
+  426,
+  32,
+  828,
+  360,
+  917,
+  182,
+  50,
+  40,
+  182,
+  19,
+  127,
+  614,
+  951,
+  662,
+  591,
+  140,
+  110,
+  685,
+  549,
+  6,
+  346,
+  766,
+  689,
+  743,
+  414,
+  135,
+  61,
+  548,
+  363,
+  915,
+  462,
+  526,
+  405,
+  524,
+  192,
+  754,
+  796,
+  616,
+  98,
+  341,
+  786,
+  778,
+  929,
+  6,
+  388,
+  293,
+  513,
+  148,
+  298,
+  311,
+  29,
+  456,
+  960,
+  560,
+  895,
+  121,
+  511,
+  141,
+  732,
+  762,
+  774,
+  261,
+  287,
+  314,
+  801,
+  320,
+  173,
+  616,
+  356,
+  783,
+  256,
+  129,
+  513,
+  212,
+  293,
+  168,
+  813,
+  279,
+  65,
+  784,
+  360,
+  921,
+  320,
+  177,
+  923,
+  385,
+  142,
+  380,
+  772,
+  929,
+  718,
+  277,
+  61,
+  620,
+  575,
+  772,
+  356,
+  414,
+  775,
+  392,
+  523,
+  760,
+  192,
+  905,
+  606,
+  134,
+  695,
+  784,
+  540,
+  63,
+  939,
+  941,
+  887,
+  217,
+  290,
+  893,
+  206,
+  662,
+  63,
+  102,
+  74,
+  943,
+  288,
+  8,
+  254,
+  131,
+  420,
+  841,
+  79,
+  139,
+  362,
+  221,
+  915,
+  6,
+  28,
+  417,
+  846,
+  996,
+  794,
+  522,
+  391,
+  513,
+  715,
+  87,
+  449,
+  801,
+  823,
+  16,
+  485,
+  874,
+  8,
+  601,
+  885,
+  146,
+  886,
+  318,
+  235,
+  390,
+  561,
+  869,
+  640,
+  860,
+  433,
+  651,
+  145,
+  149,
+  682,
+  612,
+  580,
+  946,
+  572,
+  155,
+  736,
+  898,
+  774,
+  81,
+  882,
+  286,
+  362,
+  982,
+  788,
+  658,
+  452,
+  889,
+  688,
+  384,
+  948,
+  342,
+  402,
+  777,
+  403,
+  547,
+  123,
+  187,
+  394,
+  470,
+  978,
+  234,
+  461,
+  127,
+  349,
+  476,
+  927,
+  837,
+  997,
+  494,
+  167,
+  920,
+  911,
+  84,
+  432,
+  339,
+  87,
+  841,
+  535,
+  972,
+  671,
+  395,
+  445,
+  681,
+  494,
+  737,
+  492,
+  96,
+  84,
+  261,
+  871,
+  91,
+  696,
+  960,
+  346,
+  430,
+  796,
+  326,
+  272,
+  982,
+  25,
+  927,
+  923,
+  528,
+  924,
+  215,
+  789,
+  691,
+  898,
+  811,
+  189,
+  284,
+  856,
+  200,
+  278,
+  436,
+  354,
+  114,
+  978,
+  648,
+  797,
+  437,
+  916,
+  220,
+  449,
+  740,
+  179,
+  484,
+  470,
+  332,
+  178,
+  65,
+  807,
+  860,
+  180,
+  421,
+  148,
+  563,
+  253,
+  691,
+  121,
+  837,
+  851,
+  341,
+  948,
+  563,
+  635,
+  780,
+  148,
+  567,
+  713,
+  118,
+  877,
+  505,
+  519,
+  975,
+  504,
+  745,
+  190,
+  958,
+  134,
+  898,
+  723,
+  546,
+  781,
+  46,
+  760,
+  530,
+  572,
+  163,
+  227,
+  886,
+  408,
+  586,
+  4,
+  901,
+  233,
+  753,
+  720,
+  203,
+  575,
+  748,
+  443,
+  207,
+  838,
+  492,
+  290,
+  223,
+  256,
+  715,
+  830,
+  432,
+  97,
+  99,
+  477,
+  725,
+  574,
+  91,
+  746,
+  731,
+  615,
+  629,
+  437,
+  320,
+  843,
+  559,
+  13,
+  902,
+  779,
+  564,
+  689,
+  207,
+  599,
+  726,
+  598,
+  606,
+  148,
+  58,
+  115,
+  536,
+  319,
+  279,
+  944,
+  485,
+  699,
+  948,
+  13,
+  895,
+  766,
+  582,
+  559,
+  998,
+  250,
+  788,
+  869,
+  877,
+  23,
+  647,
+  488,
+  164,
+  845,
+  344,
+  545,
+  307,
+  991,
+  0,
+  805,
+  152,
+  412,
+  534,
+  323,
+  614,
+  415,
+  865,
+  847,
+  210,
+  743,
+  122,
+  943,
+  594,
+  320,
+  268,
+  154,
+  253,
+  816,
+  347,
+  768,
+  953,
+  982,
+  606,
+  131,
+  813,
+  92,
+  339,
+  5,
+  707,
+  517,
+  526,
+  469,
+  537,
+  89,
+  141,
+  537,
+  557,
+  190,
+  659,
+  87,
+  659,
+  401,
+  367,
+  414,
+  460,
+  34,
+  96,
+  895,
+  740,
+  694,
+  352,
+  537,
+  592,
+  877,
+  137,
+  922,
+  915,
+  99,
+  216,
+  969,
+  716,
+  44,
+  869,
+  856,
+  853,
+  352,
+  556,
+  216,
+  426,
+  231,
+  259,
+  172,
+  67,
+  694,
+  488,
+  311,
+  712,
+  767,
+  279,
+  962,
+  265,
+  615,
+  141,
+  454,
+  711,
+  384,
+  452,
+  135,
+  90,
+  391,
+  787,
+  665,
+  528,
+  296,
+  824,
+  820,
+  455,
+  885,
+  301,
+  155,
+  647,
+  6,
+  973,
+  627,
+  663,
+  922,
+  969,
+  799,
+  698,
+  523,
+  404,
+  784,
+  422,
+  128,
+  103,
+  233,
+  601,
+  812,
+  281,
+  600,
+  336,
+  11,
+  743,
+  288,
+  925,
+  181,
+  228,
+  508,
+  308,
+  3,
+  141,
+  711,
+  602,
+  71,
+  868,
+  255,
+  307,
+  24,
+  862,
+  567,
+  134,
+  74,
+  755,
+  947,
+  111,
+  812,
+  42,
+  295,
+  650,
+  859,
+  78,
+  128,
+  462,
+  308,
+  290,
+  372,
+  166,
+  111,
+  364,
+  469,
+  591,
+  127,
+  56,
+  840,
+  758,
+  781,
+  756,
+  548,
+  658,
+  412,
+  851,
+  134,
+  233,
+  432,
+  257,
+  138,
+  210,
+  184,
+  986,
+  51,
+  806,
+  442,
+  711,
+  243,
+  571,
+  861,
+  550,
+  111,
+  798,
+  138,
+  316,
+  746,
+  549,
+  276,
+  458,
+  866,
+  335,
+  334,
+  178,
+  191,
+  473,
+  452,
+  764,
+  487,
+  525,
+  273,
+  457,
+  902,
+  888,
+  519,
+  203,
+  891,
+  497,
+  998,
+  535,
+  382,
+  673,
+  787,
+  112,
+  846,
+  836,
+  898,
+  681,
+  607,
+  546,
+  863,
+  639,
+  896,
+  281,
+  845,
+  305,
+  410,
+  835,
+  985,
+  245,
+  781,
+  208,
+  337,
+  248,
+  205,
+  264,
+  198,
+  305,
+  665,
+  351,
+  609,
+  186,
+  444,
+  589,
+  130,
+  292,
+  668,
+  617,
+  611,
+  111,
+  80,
+  9,
+  267,
+  275,
+  135,
+  201,
+  926,
+  789,
+  835,
+  221,
+  290,
+  297,
+  93,
+  437,
+  892,
+  921,
+  994,
+  748,
+  321,
+  23,
+  394,
+  725,
+  377,
+  581,
+  57,
+  219,
+  461,
+  54,
+  183,
+  506,
+  889,
+  920,
+  714,
+  639,
+  836,
+  585,
+  787,
+  929,
+  597,
+  307,
+  678,
+  35,
+  296,
+  46,
+  459,
+  368,
+  342,
+  200,
+  609,
+  265,
+  11,
+  315,
+  10,
+  29,
+  32,
+  339,
+  250,
+  974,
+  736,
+  834,
+  281,
+  332,
+  656,
+  530,
+  384,
+  96,
+  544,
+  775,
+  208,
+  375,
+  230,
+  31,
+  589,
+  385,
+  130,
+  718,
+  82,
+  909,
+  267,
+  482,
+  503,
+  875,
+  824,
+  488,
+  837,
+  757,
+  19,
+  121,
+  129,
+  531,
+  712,
+  76,
+  183,
+  137,
+  764,
+  617,
+  846,
+  64,
+  65,
+  775,
+  593,
+  526,
+  53,
+  923,
+  142,
+  330,
+  153,
+  199,
+  71,
+  584,
+  423,
+  770,
+  318,
+  965,
+  493,
+  953,
+  238,
+  416,
+  471,
+  978,
+  436,
+  501,
+  505,
+  264,
+  789,
+  199,
+  241,
+  800,
+  168,
+  34,
+  291,
+  399,
+  972,
+  890,
+  462,
+  670,
+  628,
+  19,
+  204,
+  99,
+  751,
+  742,
+  231,
+  397,
+  5,
+  204,
+  886,
+  763,
+  706,
+  218,
+  775,
+  730,
+  231,
+  425,
+  118,
+  778,
+  886,
+  537,
+  364,
+  691,
+  19,
+  114,
+  195,
+  665,
+  675,
+  359,
+  653,
+  185,
+  76,
+  351,
+  221,
+  695,
+  147,
+  1,
+  109,
+  790,
+  749,
+  299,
+  358,
+  11,
+  581,
+  511,
+  614,
+  950,
+  916,
+  923,
+  764,
+  245,
+  487,
+  508,
+  471,
+  71,
+  482,
+  614,
+  660,
+  834,
+  875,
+  433,
+  470,
+  650,
+  753,
+  828,
+  360,
+  551,
+  946,
+  215,
+  358,
+  689,
+  468,
+  280,
+  98,
+  363,
+  451,
+  20,
+  842,
+  913,
+  105,
+  575,
+  798,
+  199,
+  612,
+  778,
+  959,
+  295,
+  322,
+  760,
+  963,
+  854,
+  191,
+  629,
+  165,
+  420,
+  127,
+  515,
+  858,
+  783,
+  487,
+  499,
+  534,
+  451,
+  373,
+  116,
+  973,
+  576,
+  184,
+  587,
+  765,
+  975,
+  945,
+  960,
+  801,
+  802,
+  793,
+  32,
+  608,
+  312,
+  533,
+  916,
+  92,
+  625,
+  661,
+  374,
+  967,
+  332,
+  554,
+  259,
+  838,
+  475,
+  765,
+  833,
+  74,
+  39,
+  780,
+  446,
+  132,
+  270,
+  583,
+  378,
+  677,
+  805,
+  921,
+  723,
+  624,
+  67,
+  434,
+  875,
+  847,
+  149,
+  881,
+  104,
+  729,
+  327,
+  239,
+  791,
+  22,
+  717,
+  647,
+  118,
+  353,
+  791,
+  129,
+  253,
+  60,
+  938,
+  533,
+  408,
+  994,
+  849,
+  789,
+  764,
+  797,
+  687,
+  892,
+  203,
+  880,
+  903,
+  946,
+  294,
+  830,
+  698,
+  297,
+  478,
+  305,
+  452,
+  258,
+  30,
+  799,
+  756,
+  793,
+  937,
+  775,
+  14,
+  383,
+  276,
+  481,
+  215,
+  317,
+  879,
+  52,
+  628,
+  654,
+  429,
+  753,
+  848,
+  606,
+  629,
+  748,
+  832,
+  335,
+  733,
+  90,
+  396,
+  690,
+  482,
+  54,
+  12,
+  306,
+  535,
+  750,
+  116,
+  524,
+  383,
+  475,
+  214,
+  178,
+  784,
+  798,
+  563,
+  935,
+  806,
+  949,
+  53,
+  694,
+  273,
+  124,
+  284,
+  619,
+  45,
+  521,
+  715,
+  851,
+  132,
+  424,
+  438,
+  319,
+  538,
+  981,
+  802,
+  986,
+  340,
+  600,
+  353,
+  980,
+  637,
+  505,
+  17,
+  280,
+  855,
+  237,
+  432,
+  184,
+  955,
+  538,
+  935,
+  480,
+  421,
+  580,
+  423,
+  928,
+  926,
+  930,
+  732,
+  210,
+  351,
+  346,
+  469,
+  100,
+  288,
+  353,
+  788,
+  232,
+  130,
+  79,
+  360,
+  870,
+  439,
+  47,
+  661,
+  595,
+  636,
+  52,
+  389,
+  986,
+  159,
+  454,
+  317,
+  961,
+  915,
+  76,
+  342,
+  895,
+  53,
+  396,
+  15,
+  66,
+  139,
+  310,
+  636,
+  549,
+  440,
+  926,
+  132,
+  734,
+  726,
+  696,
+  332,
+  229,
+  896,
+  486,
+  316,
+  840,
+  403,
+  557,
+  963,
+  67,
+  401,
+  318,
+  13,
+  109,
+  745,
+  296,
+  653,
+  711,
+  718,
+  2,
+  951,
+  853,
+  130,
+  22,
+  879,
+  878,
+  759,
+  466,
+  520,
+  25,
+  403,
+  952,
+  914,
+  29,
+  133,
+  156,
+  467,
+  435,
+  896,
+  78,
+  488,
+  55,
+  739,
+  861,
+  521,
+  904,
+  498,
+  748,
+  703,
+  489,
+  21,
+  377,
+  322,
+  248,
+  818,
+  176,
+  531,
+  564,
+  1,
+  694,
+  362,
+  876,
+  165,
+  881,
+  325,
+  475,
+  810,
+  181,
+  30,
+  455,
+  255,
+  673,
+  320,
+  600,
+  602,
+  568,
+  974,
+  350,
+  826,
+  212,
+  504,
+  91,
+  21,
+  317,
+  275,
+  775,
+  422,
+  278,
+  795,
+  826,
+  818,
+  377,
+  295,
+  165,
+  496,
+  753,
+  425,
+  554,
+  243,
+  964,
+  169,
+  281,
+  109,
+  884,
+  334,
+  692,
+  641,
+  411,
+  352,
+  66,
+  765,
+  196,
+  508,
+  696,
+  866,
+  369,
+  725,
+  838,
+  82,
+  62,
+  300,
+  637,
+  29,
+  108,
+  859,
+  222,
+  768,
+  442,
+  891,
+  38,
+  523,
+  158,
+  856,
+  949,
+  852,
+  145,
+  630,
+  686,
+  109,
+  577,
+  371,
+  673,
+  807,
+  224,
+  169,
+  148,
+  890,
+  329,
+  653,
+  720,
+  898,
+  771,
+  65,
+  712,
+  735,
+  606,
+  578,
+  836,
+  17,
+  498,
+  31,
+  275,
+  54,
+  494,
+  831,
+  255,
+  266,
+  574,
+  693,
+  418,
+  226,
+  351,
+  867,
+  287,
+  717,
+  708,
+  104,
+  131,
+  863,
+  474,
+  600,
+  323,
+  235,
+  80,
+  710,
+  719,
+  924,
+  168,
+  168,
+  979,
+  24,
+  755,
+  935,
+  78,
+  386,
+  41,
+  546,
+  155,
+  306,
+  366,
+  814,
+  445,
+  883,
+  504,
+  332,
+  920,
+  265,
+  484,
+  591,
+  98,
+  981,
+  576,
+  392,
+  905,
+  927,
+  715,
+  264,
+  598,
+  847,
+  753,
+  329,
+  350,
+  983,
+  179,
+  993,
+  810,
+  809,
+  155,
+  508,
+  564,
+  896,
+  733,
+  734,
+  714,
+  637,
+  560,
+  186,
+  751,
+  601,
+  636,
+  361,
+  916,
+  10,
+  542,
+  258,
+  286,
+  756,
+  471,
+  858,
+  97,
+  373,
+  699,
+  1,
+  707,
+  260,
+  900,
+  145,
+  979,
+  143,
+  487,
+  427,
+  863,
+  472,
+  638,
+  672,
+  309,
+  980,
+  332,
+  480,
+  26,
+  184,
+  40,
+  723,
+  102,
+  856,
+  785,
+  298,
+  816,
+  525,
+  160,
+  897,
+  421,
+  697,
+  122,
+  571,
+  372,
+  138,
+  892,
+  370,
+  805,
+  754,
+  113,
+  993,
+  448,
+  471,
+  423,
+  96,
+  331,
+  419,
+  144,
+  172,
+  987,
+  170,
+  788,
+  400,
+  346,
+  139,
+  676,
+  380,
+  257,
+  350,
+  89,
+  592,
+  501,
+  664,
+  19,
+  957,
+  462,
+  302,
+  430,
+  880,
+  869,
+  99,
+  70,
+  356,
+  931,
+  751,
+  43,
+  531,
+  790,
+  559,
+  455,
+  64,
+  846,
+  139,
+  685,
+  876,
+  166,
+  361,
+  28,
+  876,
+  223,
+  147,
+  928,
+  619,
+  734,
+  870,
+  738,
+  393,
+  293,
+  722,
+  301,
+  936,
+  566,
+  57,
+  881,
+  398,
+  796,
+  134,
+  566,
+  932,
+  756,
+  860,
+  638,
+  546,
+  33,
+  144,
+  29,
+  628,
+  254,
+  764,
+  604,
+  357,
+  987,
+  552,
+  400,
+  663,
+  874,
+  727,
+  586,
+  988,
+  684,
+  867,
+  343,
+  733,
+  349,
+  534,
+  976,
+  708,
+  998,
+  871,
+  564,
+  271,
+  105,
+  397,
+  40,
+  884,
+  62,
+  43,
+  361,
+  451,
+  188,
+  520,
+  953,
+  709,
+  796,
+  522,
+  365,
+  263,
+  807,
+  14,
+  439,
+  395,
+  800,
+  614,
+  831,
+  675,
+  532,
+  95,
+  332,
+  538,
+  318,
+  526,
+  1,
+  689,
+  111,
+  487,
+  370,
+  203,
+  211,
+  642,
+  549,
+  158,
+  206,
+  298,
+  846,
+  87,
+  717,
+  363,
+  83,
+  200,
+  769,
+  504,
+  670,
+  536,
+  349,
+  294,
+  441,
+  239,
+  721,
+  400,
+  355,
+  212,
+  120,
+  623,
+  664,
+  94,
+  116,
+  126,
+  904,
+  947,
+  938,
+  152,
+  542,
+  464,
+  735,
+  926,
+  112,
+  590,
+  1,
+  209,
+  102,
+  237,
+  258,
+  552,
+  427,
+  808,
+  319,
+  631,
+  769,
+  884,
+  24,
+  132,
+  697,
+  878,
+  344,
+  335,
+  391,
+  384,
+  27,
+  533,
+  900,
+  96,
+  279,
+  121,
+  998,
+  558,
+  987,
+  848,
+  426,
+  191,
+  925,
+  623,
+  850,
+  163,
+  184,
+  819,
+  881,
+  279,
+  850,
+  517,
+  178,
+  727,
+  603,
+  152,
+  657,
+  412,
+  17,
+  120,
+  241,
+  718,
+  785,
+  921,
+  237,
+  982,
+  936,
+  745,
+  810,
+  507,
+  207,
+  267,
+  17,
+  967,
+  133,
+  73,
+  627,
+  20,
+  158,
+  69,
+  829,
+  769,
+  457,
+  436,
+  986,
+  723,
+  248,
+  784,
+  704,
+  146,
+  408,
+  0,
+  170,
+  209,
+  720,
+  958,
+  149,
+  321,
+  919,
+  924,
+  223,
+  35,
+  326,
+  196,
+  513,
+  992,
+  884,
+  467,
+  877,
+  695,
+  432,
+  281,
+  722,
+  633,
+  209,
+  616,
+  140,
+  93,
+  274,
+  31,
+  401,
+  971,
+  177,
+  946,
+  782,
+  271,
+  934,
+  159,
+  416,
+  861,
+  9,
+  607,
+  415,
+  747,
+  444,
+  487,
+  701,
+  191,
+  88,
+  850,
+  580,
+  93,
+  59,
+  309,
+  477,
+  613,
+  974,
+  126,
+  348,
+  256,
+  573,
+  578,
+  865,
+  805,
+  280,
+  90,
+  858,
+  924,
+  455,
+  681,
+  307,
+  581,
+  714,
+  156,
+  224,
+  534,
+  198,
+  63,
+  489,
+  144,
+  123,
+  288,
+  500,
+  221,
+  618,
+  674,
+  233,
+  440,
+  788,
+  569,
+  70,
+  472,
+  166,
+  12,
+  979,
+  722,
+  929,
+  108,
+  736,
+  666,
+  525,
+  631,
+  554,
+  287,
+  742,
+  65,
+  324,
+  248,
+  710,
+  489,
+  834,
+  199,
+  338,
+  851,
+  793,
+  960,
+  761,
+  383,
+  891,
+  973,
+  943,
+  853,
+  422,
+  178,
+  600,
+  890,
+  732,
+  384,
+  431,
+  476,
+  237,
+  104,
+  622,
+  839,
+  904,
+  805,
+  512,
+  57,
+  17,
+  630,
+  378,
+  32,
+  996,
+  247,
+  209,
+  254,
+  119,
+  396,
+  565,
+  630,
+  782,
+  633,
+  138,
+  318,
+  112,
+  545,
+  743,
+  616,
+  663,
+  89,
+  367,
+  495,
+  845,
+  127,
+  597,
+  434,
+  129,
+  692,
+  109,
+  168,
+  953,
+  668,
+  590,
+  177,
+  578,
+  46,
+  707,
+  413,
+  115,
+  788,
+  513,
+  243,
+  935,
+  953,
+  58,
+  584,
+  64,
+  569,
+  367,
+  978,
+  249,
+  290,
+  125,
+  183,
+  852,
+  485,
+  847,
+  895,
+  835,
+  25,
+  289,
+  995,
+  226,
+  156,
+  980,
+  520,
+  656,
+  255,
+  37,
+  852,
+  719,
+  493,
+  473,
+  900,
+  417,
+  647,
+  363,
+  759,
+  778,
+  735,
+  349,
+  627,
+  525,
+  255,
+  13,
+  58,
+  399,
+  222,
+  70,
+  304,
+  663,
+  158,
+  152,
+  788,
+  103,
+  693,
+  274,
+  873,
+  116,
+  837,
+  876,
+  367,
+  272,
+  778,
+  65,
+  363,
+  625,
+  696,
+  809,
+  16,
+  491,
+  615,
+  196,
+  88,
+  0,
+  204,
+  418,
+  203,
+  952,
+  205,
+  240,
+  962,
+  899,
+  872,
+  222,
+  961,
+  363,
+  920,
+  659,
+  935,
+  943,
+  198,
+  385,
+  475,
+  298,
+  936,
+  22,
+  204,
+  947,
+  776,
+  911,
+  581,
+  661,
+  340,
+  433,
+  188,
+  622,
+  117,
+  154,
+  150,
+  388,
+  214,
+  513,
+  625,
+  875,
+  779,
+  262,
+  972,
+  396,
+  803,
+  396,
+  991,
+  976,
+  900,
+  387,
+  371,
+  522,
+  162,
+  234,
+  733,
+  314,
+  331,
+  666,
+  44,
+  205,
+  66,
+  422,
+  780,
+  978,
+  661,
+  775,
+  647,
+  511,
+  670,
+  515,
+  88,
+  714,
+  579,
+  133,
+  499,
+  837,
+  506,
+  904,
+  172,
+  248,
+  476,
+  836,
+  898,
+  514,
+  396,
+  852,
+  568,
+  706,
+  533,
+  54,
+  72,
+  167,
+  493,
+  809,
+  588,
+  792,
+  34,
+  325,
+  827,
+  878,
+  440,
+  708,
+  348,
+  589,
+  708,
+  271,
+  577,
+  857,
+  999,
+  547,
+  579,
+  502,
+  298,
+  330,
+  790,
+  687,
+  99,
+  245,
+  721,
+  264,
+  826,
+  487,
+  501,
+  783,
+  194,
+  469,
+  991,
+  653,
+  87,
+  946,
+  556,
+  707,
+  104,
+  879,
+  160,
+  15,
+  1,
+  95,
+  323,
+  870,
+  521,
+  897,
+  840,
+  699,
+  410,
+  751,
+  42,
+  342,
+  802,
+  547,
+  862,
+  168,
+  5,
+  561,
+  488,
+  170,
+  237,
+  655,
+  179,
+  909,
+  847,
+  536,
+  360,
+  44,
+  371,
+  9,
+  473,
+  253,
+  400,
+  563,
+  683,
+  471,
+  625,
+  823,
+  414,
+  590,
+  312,
+  407,
+  971,
+  929,
+  614,
+  705,
+  249,
+  69,
+  348,
+  527,
+  915,
+  978,
+  728,
+  593,
+  641,
+  627,
+  144,
+  653,
+  818,
+  763,
+  116,
+  676,
+  611,
+  451,
+  203,
+  589,
+  62,
+  984,
+  165,
+  631,
+  42,
+  873,
+  56,
+  256,
+  459,
+  134,
+  722,
+  235,
+  798,
+  291,
+  977,
+  646,
+  36,
+  156,
+  546,
+  113,
+  96,
+  964,
+  156,
+  570,
+  366,
+  718,
+  816,
+  726,
+  385,
+  188,
+  184,
+  154,
+  921,
+  821,
+  329,
+  928,
+  176,
+  688,
+  942,
+  204,
+  240,
+  423,
+  498,
+  422,
+  115,
+  696,
+  1,
+  850,
+  309,
+  733,
+  628,
+  595,
+  930,
+  467,
+  888,
+  638,
+  448,
+  895,
+  10,
+  938,
+  848,
+  116,
+  193,
+  390,
+  415,
+  330,
+  359,
+  115,
+  371,
+  432,
+  229,
+  264,
+  141,
+  162,
+  491,
+  397,
+  2,
+  141,
+  761,
+  471,
+  68,
+  55,
+  628,
+  593,
+  891,
+  84,
+  808,
+  740,
+  196,
+  196,
+  511,
+  901,
+  324,
+  464,
+  627,
+  461,
+  900,
+  995,
+  118,
+  486,
+  960,
+  709,
+  451,
+  432,
+  997,
+  785,
+  480,
+  20,
+  351,
+  25,
+  955,
+  40,
+  788,
+  56,
+  254,
+  329,
+  601,
+  293,
+  704,
+  639,
+  743,
+  983,
+  177,
+  722,
+  193,
+  708,
+  34,
+  202,
+  364,
+  404,
+  487,
+  436,
+  867,
+  906,
+  442,
+  472,
+  718,
+  610,
+  366,
+  991,
+  639,
+  821,
+  604,
+  618,
+  538,
+  266,
+  781,
+  958,
+  542,
+  744,
+  116,
+  604,
+  835,
+  310,
+  847,
+  277,
+  138,
+  979,
+  930,
+  962,
+  3,
+  641,
+  976,
+  673,
+  928,
+  851,
+  456,
+  963,
+  604,
+  336,
+  360,
+  467,
+  374,
+  536,
+  56,
+  729,
+  272,
+  563,
+  205,
+  301,
+  583,
+  329,
+  632,
+  151,
+  678,
+  100,
+  234,
+  74,
+  315,
+  289,
+  759,
+  313,
+  854,
+  558,
+  997,
+  905,
+  186,
+  261,
+  863,
+  607,
+  41,
+  70,
+  234,
+  147,
+  448,
+  619,
+  179,
+  65,
+  716,
+  309,
+  858,
+  408,
+  143,
+  61,
+  760,
+  308,
+  115,
+  116,
+  233,
+  598,
+  170,
+  675,
+  117,
+  147,
+  511,
+  935,
+  857,
+  761,
+  397,
+  692,
+  940,
+  606,
+  235,
+  50,
+  297,
+  219,
+  216,
+  501,
+  489,
+  22,
+  792,
+  878,
+  722,
+  293,
+  667,
+  71,
+  663,
+  870,
+  294,
+  596,
+  885,
+  140,
+  169,
+  325,
+  8,
+  107,
+  780,
+  536,
+  320,
+  652,
+  975,
+  155,
+  371,
+  901,
+  716,
+  175,
+  240,
+  296,
+  355,
+  416,
+  277,
+  187,
+  178,
+  977,
+  254,
+  679,
+  799,
+  428,
+  123,
+  66,
+  195,
+  143,
+  700,
+  648,
+  653,
+  570,
+  363,
+  942,
+  352,
+  981,
+  175,
+  815,
+  618,
+  479,
+  760,
+  663,
+  298,
+  944,
+  716,
+  925,
+  796,
+  312,
+  509,
+  365,
+  165,
+  945,
+  52,
+  787,
+  270,
+  663,
+  358,
+  452,
+  103,
+  809,
+  345,
+  62,
+  545,
+  863,
+  116,
+  952,
+  951,
+  810,
+  297,
+  884,
+  386,
+  683,
+  991,
+  161,
+  48,
+  267,
+  672,
+  558,
+  977,
+  2,
+  827,
+  848,
+  293,
+  860,
+  247,
+  564,
+  141,
+  285,
+  134,
+  736,
+  604,
+  789,
+  441,
+  723,
+  714,
+  911,
+  957,
+  597,
+  510,
+  547,
+  274,
+  761,
+  684,
+  747,
+  652,
+  536,
+  114,
+  555,
+  176,
+  743,
+  923,
+  442,
+  629,
+  984,
+  703,
+  957,
+  620,
+  822,
+  47,
+  186,
+  669,
+  17,
+  168,
+  377,
+  271,
+  562,
+  420,
+  799,
+  820,
+  73,
+  439,
+  884,
+  919,
+  306,
+  164,
+  749,
+  123,
+  830,
+  461,
+  452,
+  353,
+  589,
+  305,
+  907,
+  949,
+  288,
+  733,
+  975,
+  454,
+  821,
+  394,
+  329,
+  776,
+  69,
+  134,
+  808,
+  888,
+  663,
+  594,
+  378,
+  691,
+  175,
+  951,
+  234,
+  635,
+  969,
+  838,
+  443,
+  447,
+  399,
+  563,
+  442,
+  750,
+  523,
+  909,
+  889,
+  768,
+  390,
+  61,
+  896,
+  865,
+  534,
+  72,
+  558,
+  267,
+  678,
+  930,
+  662,
+  655,
+  15,
+  153,
+  885,
+  631,
+  724,
+  475,
+  919,
+  691,
+  260,
+  925,
+  49,
+  798,
+  761,
+  314,
+  497,
+  116,
+  789,
+  548,
+  1,
+  258,
+  388,
+  137,
+  467,
+  706,
+  580,
+  717,
+  110,
+  290,
+  513,
+  408,
+  639,
+  72,
+  629,
+  772,
+  67,
+  460,
+  612,
+  46,
+  88,
+  330,
+  790,
+  854,
+  708,
+  610,
+  334,
+  180,
+  901,
+  718,
+  647,
+  281,
+  135,
+  80,
+  583,
+  591,
+  828,
+  405,
+  843,
+  30,
+  709,
+  657,
+  329,
+  53,
+  351,
+  336,
+  445,
+  249,
+  761,
+  14,
+  187,
+  628,
+  154,
+  381,
+  915,
+  589,
+  911,
+  849,
+  515,
+  39,
+  58,
+  17,
+  790,
+  825,
+  446,
+  99,
+  674,
+  155,
+  407,
+  324,
+  888,
+  447,
+  662,
+  324,
+  588,
+  659,
+  898,
+  234,
+  12,
+  418,
+  514,
+  833,
+  149,
+  241,
+  655,
+  350,
+  256,
+  869,
+  127,
+  629,
+  236,
+  334,
+  940,
+  175,
+  685,
+  224,
+  243,
+  866,
+  979,
+  495,
+  375,
+  525,
+  869,
+  524,
+  894,
+  919,
+  4,
+  184,
+  348,
+  75,
+  892,
+  379,
+  899,
+  177,
+  709,
+  762,
+  356,
+  612,
+  992,
+  723,
+  47,
+  227,
+  317,
+  542,
+  703,
+  279,
+  969,
+  946,
+  473,
+  208,
+  60,
+  872,
+  674,
+  116,
+  360,
+  616,
+  976,
+  253,
+  862,
+  119,
+  649,
+  710,
+  851,
+  690,
+  448,
+  714,
+  152,
+  489,
+  62,
+  833,
+  207,
+  594,
+  100,
+  375,
+  9,
+  497,
+  111,
+  442,
+  116,
+  818,
+  749,
+  177,
+  898,
+  403,
+  243,
+  228,
+  741,
+  680,
+  393,
+  292,
+  726,
+  628,
+  149,
+  127,
+  525,
+  320,
+  404,
+  831,
+  842,
+  852,
+  367,
+  849,
+  66,
+  448,
+  978,
+  941,
+  165,
+  565,
+  960,
+  631,
+  220,
+  220,
+  154,
+  584,
+  841,
+  386,
+  582,
+  233,
+  22,
+  608,
+  508,
+  454,
+  503,
+  267,
+  660,
+  899,
+  404,
+  660,
+  451,
+  86,
+  966,
+  694,
+  133,
+  320,
+  811,
+  966,
+  556,
+  377,
+  653,
+  244,
+  718,
+  255,
+  748,
+  6,
+  237,
+  11,
+  668,
+  411,
+  351,
+  360,
+  833,
+  91,
+  414,
+  264,
+  447,
+  816,
+  962,
+  197,
+  774,
+  504,
+  426,
+  161,
+  42,
+  714,
+  130,
+  699,
+  64,
+  307,
+  15,
+  719,
+  917,
+  452,
+  573,
+  184,
+  297,
+  10,
+  249,
+  628,
+  440,
+  761,
+  170,
+  588,
+  537,
+  318,
+  130,
+  207,
+  376,
+  696,
+  203,
+  202,
+  790,
+  737,
+  133,
+  966,
+  24,
+  127,
+  820,
+  109,
+  53,
+  185,
+  38,
+  946,
+  96,
+  352,
+  529,
+  349,
+  678,
+  309,
+  51,
+  680,
+  881,
+  489,
+  940,
+  962,
+  163,
+  900,
+  797,
+  461,
+  431,
+  973,
+  204,
+  597,
+  681,
+  483,
+  903,
+  351,
+  885,
+  646,
+  358,
+  891,
+  564,
+  405,
+  989,
+  656,
+  628,
+  749,
+  23,
+  243,
+  407,
+  178,
+  22,
+  132,
+  883,
+  365,
+  471,
+  941,
+  762,
+  226,
+  403,
+  87,
+  231,
+  589,
+  543,
+  346,
+  737,
+  817,
+  261,
+  857,
+  869,
+  996,
+  27,
+  280,
+  595,
+  538,
+  113,
+  628,
+  587,
+  677,
+  641,
+  421,
+  176,
+  262,
+  399,
+  786,
+  970,
+  330,
+  936,
+  633,
+  690,
+  156,
+  855,
+  313,
+  550,
+  707,
+  201,
+  910,
+  556,
+  248,
+  34,
+  432,
+  547,
+  622,
+  737,
+  233,
+  941,
+  694,
+  526,
+  409,
+  458,
+  133,
+  900,
+  248,
+  670,
+  109,
+  802,
+  295,
+  233,
+  117,
+  923,
+  139,
+  855,
+  382,
+  757,
+  399,
+  462,
+  115,
+  447,
+  444,
+  53,
+  235,
+  163,
+  232,
+  333,
+  335,
+  219,
+  625,
+  95,
+  674,
+  879,
+  204,
+  460,
+  370,
+  829,
+  943,
+  420,
+  10,
+  538,
+  863,
+  694,
+  537,
+  124,
+  406,
+  294,
+  131,
+  306,
+  420,
+  12,
+  385,
+  107,
+  33,
+  153,
+  815,
+  899,
+  989,
+  845,
+  875,
+  772,
+  172,
+  308,
+  285,
+  1,
+  721,
+  487,
+  495,
+  310,
+  222,
+  950,
+  874,
+  211,
+  837,
+  723,
+  834,
+  407,
+  327,
+  658,
+  647,
+  1,
+  278,
+  524,
+  266,
+  906,
+  312,
+  955,
+  632,
+  631,
+  515,
+  440,
+  334,
+  122,
+  559,
+  72,
+  785,
+  431,
+  621,
+  61,
+  584,
+  588,
+  594,
+  16,
+  217,
+  50,
+  831,
+  188,
+  52,
+  393,
+  993,
+  495,
+  848,
+  480,
+  456,
+  370,
+  424,
+  777,
+  718,
+  39,
+  186,
+  466,
+  773,
+  185,
+  508,
+  464,
+  989,
+  135,
+  971,
+  470,
+  682,
+  443,
+  97,
+  124,
+  838,
+  135,
+  186,
+  427,
+  544,
+  719,
+  411,
+  244,
+  64,
+  273,
+  568,
+  160,
+  173,
+  273,
+  185,
+  826,
+  238,
+  841,
+  840,
+  553,
+  33,
+  758,
+  873,
+  162,
+  707,
+  158,
+  166,
+  714,
+  461,
+  573,
+  566,
+  256,
+  903,
+  798,
+  242,
+  561,
+  763,
+  334,
+  164,
+  781,
+  73,
+  309,
+  228,
+  71,
+  643,
+  774,
+  672,
+  507,
+  676,
+  406,
+  695,
+  623,
+  993,
+  729,
+  898,
+  324,
+  420,
+  903,
+  599,
+  622,
+  129,
+  694,
+  716,
+  742,
+  632,
+  89,
+  740,
+  417,
+  606,
+  494,
+  697,
+  697,
+  655,
+  30,
+  87,
+  617,
+  604,
+  101,
+  537,
+  566,
+  828,
+  969,
+  570,
+  993,
+  883,
+  127,
+  625,
+  985,
+  804,
+  553,
+  874,
+  758,
+  396,
+  875,
+  133,
+  224,
+  853,
+  877,
+  710,
+  782,
+  155,
+  923,
+  416,
+  794,
+  663,
+  200,
+  30,
+  689,
+  77,
+  218,
+  632,
+  849,
+  60,
+  270,
+  446,
+  419,
+  697,
+  980,
+  892,
+  935,
+  24,
+  717,
+  178,
+  471,
+  497,
+  209,
+  743,
+  284,
+  3,
+  813,
+  234,
+  76,
+  527,
+  145,
+  684,
+  742,
+  500,
+  832,
+  533,
+  780,
+  226,
+  800,
+  897,
+  102,
+  309,
+  994,
+  775,
+  888,
+  944,
+  243,
+  54,
+  17,
+  107,
+  929,
+  52,
+  244,
+  843,
+  553,
+  701,
+  236,
+  53,
+  909,
+  972,
+  753,
+  927,
+  796,
+  81,
+  679,
+  394,
+  649,
+  991,
+  973,
+  903,
+  797,
+  321,
+  763,
+  37,
+  991,
+  544,
+  268,
+  236,
+  10,
+  923,
+  443,
+  394,
+  720,
+  76,
+  434,
+  280,
+  314,
+  91,
+  934,
+  848,
+  217,
+  697,
+  646,
+  53,
+  647,
+  723,
+  154,
+  894,
+  943,
+  217,
+  641,
+  64,
+  987,
+  58,
+  98,
+  191,
+  819,
+  510,
+  708,
+  33,
+  747,
+  400,
+  513,
+  360,
+  526,
+  173,
+  733,
+  234,
+  759,
+  525,
+  485,
+  463,
+  382,
+  261,
+  826,
+  870,
+  999,
+  655,
+  564,
+  947,
+  334,
+  479,
+  963,
+  641,
+  647,
+  554,
+  497,
+  688,
+  818,
+  941,
+  20,
+  235,
+  523,
+  847,
+  527,
+  290,
+  535,
+  244,
+  312,
+  703,
+  779,
+  768,
+  732,
+  734,
+  759,
+  228,
+  671,
+  245,
+  304,
+  191,
+  808,
+  502,
+  219,
+  948,
+  24,
+  398,
+  268,
+  540,
+  243,
+  691,
+  966,
+  768,
+  631,
+  38,
+  446,
+  446,
+  697,
+  82,
+  824,
+  893,
+  696,
+  553,
+  563,
+  502,
+  25,
+  34,
+  648,
+  753,
+  857,
+  8,
+  341,
+  801,
+  913,
+  802,
+  177,
+  805,
+  155,
+  242,
+  920,
+  148,
+  139,
+  517,
+  413,
+  252,
+  225,
+  766,
+  663,
+  767,
+  179,
+  615,
+  212,
+  299,
+  424,
+  125,
+  155,
+  717,
+  263,
+  174,
+  390,
+  849,
+  645,
+  242,
+  572,
+  768,
+  821,
+  739,
+  12,
+  398,
+  617,
+  875,
+  957,
+  14,
+  791,
+  633,
+  539,
+  221,
+  80,
+  487,
+  467,
+  88,
+  234,
+  770,
+  816,
+  947,
+  220,
+  967,
+  942,
+  344,
+  993,
+  79,
+  388,
+  415,
+  886,
+  335,
+  967,
+  560,
+  486,
+  606,
+  49,
+  114,
+  582,
+  891,
+  544,
+  623,
+  858,
+  875,
+  986,
+  486,
+  549,
+  196,
+  198,
+  108,
+  152,
+  545,
+  430,
+  569,
+  122,
+  123,
+  386,
+  163,
+  269,
+  400,
+  774,
+  65,
+  689,
+  802,
+  35,
+  629,
+  738,
+  662,
+  930,
+  494,
+  45,
+  816,
+  412,
+  401,
+  728,
+  336,
+  584,
+  876,
+  14,
+  27,
+  12,
+  224,
+  482,
+  304,
+  852,
+  352,
+  163,
+  300,
+  545,
+  554,
+  958,
+  621,
+  872,
+  192,
+  450,
+  400,
+  195,
+  339,
+  916,
+  344,
+  341,
+  814,
+  450,
+  292,
+  783,
+  818,
+  573,
+  187,
+  992,
+  219,
+  103,
+  894,
+  857,
+  262,
+  204,
+  570,
+  30,
+  293,
+  454,
+  72,
+  568,
+  273,
+  112,
+  923,
+  247,
+  251,
+  780,
+  590,
+  349,
+  311,
+  856,
+  583,
+  566,
+  965,
+  74,
+  260,
+  523,
+  413,
+  892,
+  640,
+  718,
+  646,
+  244,
+  2,
+  440,
+  492,
+  906,
+  619,
+  94,
+  124,
+  732,
+  250,
+  906,
+  669,
+  903,
+  885,
+  494,
+  972,
+  619,
+  414,
+  627,
+  131,
+  249,
+  528,
+  447,
+  992,
+  345,
+  940,
+  765,
+  238,
+  131,
+  900,
+  327,
+  554,
+  975,
+  547,
+  630,
+  428,
+  673,
+  144,
+  690,
+  200,
+  148,
+  405,
+  29,
+  680,
+  559,
+  896,
+  321,
+  736,
+  540,
+  197,
+  154,
+  373,
+  221,
+  78,
+  134,
+  443,
+  514,
+  40,
+  577,
+  529,
+  205,
+  83,
+  366,
+  475,
+  703,
+  166,
+  31,
+  340,
+  803,
+  940,
+  181,
+  134,
+  520,
+  159,
+  99,
+  168,
+  404,
+  343,
+  317,
+  298,
+  715,
+  303,
+  990,
+  32,
+  999,
+  653,
+  151,
+  913,
+  449,
+  884,
+  571,
+  139,
+  806,
+  296,
+  375,
+  476,
+  206,
+  45,
+  991,
+  607,
+  5,
+  851,
+  283,
+  642,
+  396,
+  370,
+  25,
+  24,
+  418,
+  679,
+  469,
+  607,
+  355,
+  600,
+  83,
+  32,
+  787,
+  834,
+  972,
+  351,
+  948,
+  356,
+  270,
+  606,
+  322,
+  279,
+  966,
+  138,
+  832,
+  428,
+  306,
+  889,
+  828,
+  34,
+  449,
+  879,
+  205,
+  227,
+  67,
+  132,
+  845,
+  506,
+  317,
+  867,
+  353,
+  804,
+  532,
+  41,
+  157,
+  400,
+  691,
+  424,
+  812,
+  523,
+  232,
+  584,
+  885,
+  556,
+  504,
+  985,
+  322,
+  969,
+  371,
+  391,
+  98,
+  941,
+  26,
+  178,
+  774,
+  463,
+  997,
+  240,
+  265,
+  783,
+  393,
+  970,
+  984,
+  767,
+  198,
+  352,
+  641,
+  75,
+  295,
+  130,
+  103,
+  967,
+  755,
+  140,
+  35,
+  36,
+  632,
+  140,
+  31,
+  343,
+  311,
+  875,
+  957,
+  214,
+  594,
+  102,
+  708,
+  704,
+  42,
+  385,
+  66,
+  207,
+  462,
+  7,
+  629,
+  996,
+  45,
+  239,
+  67,
+  320,
+  572,
+  870,
+  745,
+  491,
+  347,
+  526,
+  400,
+  699,
+  754,
+  976,
+  956,
+  954,
+  794,
+  539,
+  303,
+  659,
+  358,
+  240,
+  499,
+  659,
+  623,
+  633,
+  84,
+  969,
+  47,
+  38,
+  147,
+  473,
+  237,
+  108,
+  223,
+  587,
+  983,
+  835,
+  709,
+  650,
+  654,
+  290,
+  457,
+  508,
+  179,
+  41,
+  861,
+  141,
+  415,
+  338,
+  134,
+  768,
+  896,
+  332,
+  774,
+  619,
+  168,
+  326,
+  995,
+  974,
+  888,
+  405,
+  863,
+  48,
+  321,
+  634,
+  321,
+  270,
+  859,
+  323,
+  320,
+  737,
+  558,
+  628,
+  600,
+  523,
+  806,
+  90,
+  149,
+  997,
+  588,
+  708,
+  940,
+  616,
+  975,
+  302,
+  113,
+  670,
+  369,
+  987,
+  171,
+  900,
+  669,
+  758,
+  668,
+  439,
+  111,
+  749,
+  85,
+  423,
+  868,
+  299,
+  854,
+  861,
+  512,
+  673,
+  594,
+  180,
+  719,
+  880,
+  377,
+  927,
+  123,
+  93,
+  351,
+  135,
+  116,
+  681,
+  353,
+  159,
+  981,
+  788,
+  232,
+  670,
+  43,
+  414,
+  383,
+  448,
+  113,
+  401,
+  103,
+  514,
+  158,
+  22,
+  537,
+  72,
+  392,
+  763,
+  35,
+  420,
+  434,
+  526,
+  732,
+  53,
+  193,
+  681,
+  185,
+  586,
+  476,
+  362,
+  274,
+  409,
+  658,
+  165,
+  767,
+  233,
+  389,
+  776,
+  179,
+  432,
+  84,
+  27,
+  691,
+  946,
+  470,
+  906,
+  144,
+  423,
+  226,
+  616,
+  247,
+  503,
+  52,
+  921,
+  450,
+  596,
+  634,
+  189,
+  640,
+  812,
+  892,
+  964,
+  903,
+  866,
+  914,
+  506,
+  858,
+  104,
+  335,
+  545,
+  557,
+  515,
+  707,
+  797,
+  965,
+  331,
+  927,
+  376,
+  757,
+  886,
+  154,
+  827,
+  675,
+  744,
+  712,
+  717,
+  977,
+  168,
+  49,
+  739,
+  407,
+  50,
+  224,
+  180,
+  317,
+  364,
+  594,
+  696,
+  318,
+  336,
+  734,
+  293,
+  497,
+  469,
+  988,
+  653,
+  241,
+  114,
+  982,
+  927,
+  708,
+  609,
+  851,
+  256,
+  225,
+  51,
+  194,
+  14,
+  282,
+  557,
+  892,
+  905,
+  457,
+  759,
+  466,
+  622,
+  351,
+  245,
+  5,
+  449,
+  80,
+  548,
+  213,
+  711,
+  458,
+  106,
+  713,
+  94,
+  587,
+  650,
+  853,
+  41,
+  578,
+  515,
+  946,
+  3,
+  758,
+  437,
+  935,
+  967,
+  284,
+  783,
+  525,
+  306,
+  820,
+  175,
+  216,
+  350,
+  866,
+  535,
+  369,
+  843,
+  642,
+  848,
+  648,
+  44,
+  796,
+  390,
+  983,
+  292,
+  352,
+  992,
+  122,
+  715,
+  123,
+  2,
+  83,
+  193,
+  711,
+  329,
+  242,
+  453,
+  600,
+  770,
+  969,
+  90,
+  259,
+  71,
+  253,
+  311,
+  865,
+  679,
+  120,
+  409,
+  329,
+  113,
+  636,
+  784,
+  548,
+  5,
+  162,
+  555,
+  82,
+  479,
+  168,
+  984,
+  802,
+  681,
+  497,
+  996,
+  382,
+  339,
+  55,
+  947,
+  117,
+  162,
+  275,
+  493,
+  410,
+  234,
+  69,
+  54,
+  817,
+  985,
+  639,
+  479,
+  362,
+  394,
+  939,
+  494,
+  462,
+  642,
+  301,
+  983,
+  350,
+  923,
+  244,
+  565,
+  587,
+  811,
+  130,
+  2,
+  249,
+  56,
+  722,
+  814,
+  940,
+  346,
+  233,
+  575,
+  764,
+  917,
+  981,
+  350,
+  589,
+  969,
+  834,
+  506,
+  623,
+  448,
+  515,
+  715,
+  397,
+  395,
+  174,
+  196,
+  337,
+  713,
+  560,
+  686,
+  836,
+  837,
+  544,
+  582,
+  586,
+  883,
+  968,
+  810,
+  164,
+  568,
+  109,
+  333,
+  703,
+  3,
+  719,
+  500,
+  530,
+  11,
+  628,
+  164,
+  246,
+  446,
+  472,
+  883,
+  142,
+  978,
+  127,
+  127,
+  837,
+  156,
+  66,
+  142,
+  382,
+  852,
+  608,
+  956,
+  287,
+  553,
+  284,
+  347,
+  23,
+  358,
+  964,
+  746,
+  894,
+  32,
+  258,
+  788,
+  404,
+  75,
+  587,
+  955,
+  593,
+  640,
+  828,
+  977,
+  428,
+  189,
+  421,
+  587,
+  31,
+  41,
+  718,
+  490,
+  535,
+  330,
+  589,
+  256,
+  762,
+  629,
+  586,
+  916,
+  745,
+  353,
+  114,
+  385,
+  517,
+  1,
+  279,
+  673,
+  638,
+  516,
+  273,
+  953,
+  822,
+  323,
+  973,
+  946,
+  715,
+  414,
+  811,
+  28,
+  804,
+  139,
+  254,
+  110,
+  811,
+  684,
+  405,
+  174,
+  97,
+  444,
+  222,
+  329,
+  911,
+  670,
+  642,
+  424,
+  24,
+  129,
+  772,
+  432,
+  372,
+  124,
+  43,
+  396,
+  319,
+  386,
+  934,
+  153,
+  697,
+  562,
+  375,
+  838,
+  510,
+  574,
+  8,
+  870,
+  677,
+  326,
+  410,
+  19,
+  510,
+  433,
+  893,
+  768,
+  853,
+  775,
+  994,
+  851,
+  611,
+  885,
+  212,
+  885,
+  411,
+  597,
+  36,
+  951,
+  482,
+  530,
+  572,
+  492,
+  583,
+  749,
+  579,
+  293,
+  315,
+  783,
+  31,
+  789,
+  298,
+  772,
+  697,
+  113,
+  87,
+  624,
+  402,
+  939,
+  214,
+  569,
+  92,
+  324,
+  338,
+  680,
+  627,
+  979,
+  679,
+  685,
+  954,
+  247,
+  130,
+  718,
+  993,
+  444,
+  692,
+  459,
+  652,
+  877,
+  733,
+  689,
+  848,
+  63,
+  325,
+  90,
+  638,
+  494,
+  278,
+  454,
+  490,
+  807,
+  30,
+  904,
+  133,
+  648,
+  201,
+  990,
+  662,
+  647,
+  987,
+  94,
+  103,
+  886,
+  386,
+  578,
+  667,
+  536,
+  754,
+  56,
+  382,
+  963,
+  506,
+  825,
+  173,
+  850,
+  635,
+  796,
+  229,
+  893,
+  785,
+  30,
+  143,
+  375,
+  306,
+  367,
+  888,
+  996,
+  908,
+  332,
+  239,
+  925,
+  603,
+  189,
+  160,
+  738,
+  16,
+  403,
+  222,
+  546,
+  469,
+  416,
+  29,
+  914,
+  212,
+  666,
+  260,
+  352,
+  592,
+  389,
+  793,
+  834,
+  43,
+  260,
+  583,
+  984,
+  590,
+  508,
+  347,
+  115,
+  199,
+  309,
+  508,
+  400,
+  669,
+  110,
+  201,
+  5,
+  575,
+  500,
+  292,
+  759,
+  898,
+  671,
+  612,
+  438,
+  33,
+  561,
+  560,
+  205,
+  719,
+  987,
+  263,
+  313,
+  144,
+  189,
+  429,
+  366,
+  229,
+  618,
+  384,
+  865,
+  278,
+  926,
+  329,
+  869,
+  930,
+  789,
+  925,
+  797,
+  554,
+  442,
+  595,
+  979,
+  276,
+  72,
+  960,
+  883,
+  436,
+  816,
+  70,
+  631,
+  956,
+  704,
+  691,
+  775,
+  67,
+  196,
+  246,
+  324,
+  260,
+  252,
+  68,
+  442,
+  493,
+  266,
+  873,
+  264,
+  920,
+  686,
+  970,
+  661,
+  807,
+  496,
+  214,
+  225,
+  80,
+  505,
+  837,
+  965,
+  360,
+  494,
+  233,
+  584,
+  268,
+  618,
+  633,
+  894,
+  994,
+  110,
+  917,
+  711,
+  214,
+  832,
+  291,
+  354,
+  961,
+  142,
+  343,
+  548,
+  803,
+  661,
+  706,
+  969,
+  201,
+  938,
+  706,
+  438,
+  922,
+  228,
+  775,
+  736,
+  91,
+  948,
+  581,
+  564,
+  370,
+  995,
+  653,
+  252,
+  872,
+  70,
+  990,
+  323,
+  392,
+  48,
+  737,
+  957,
+  660,
+  405,
+  290,
+  886,
+  550,
+  86,
+  426,
+  678,
+  908,
+  325,
+  65,
+  845,
+  933,
+  918,
+  393,
+  504,
+  272,
+  785,
+  526,
+  480,
+  331,
+  400,
+  514,
+  940,
+  121,
+  9,
+  965,
+  907,
+  165,
+  521,
+  825,
+  40,
+  251,
+  227,
+  739,
+  370,
+  606,
+  572,
+  70,
+  118,
+  684,
+  236,
+  809,
+  947,
+  221,
+  588,
+  369,
+  826,
+  554,
+  206,
+  353,
+  168,
+  995,
+  549,
+  733,
+  42,
+  297,
+  346,
+  495,
+  684,
+  266,
+  672,
+  400,
+  150,
+  178,
+  45,
+  40,
+  723,
+  527,
+  349,
+  985,
+  279,
+  965,
+  668,
+  29,
+  684,
+  447,
+  152,
+  241,
+  801,
+  335,
+  777,
+  601,
+  968,
+  997,
+  614,
+  762,
+  586,
+  540,
+  429,
+  174,
+  626,
+  770,
+  855,
+  522,
+  250,
+  846,
+  878,
+  412,
+  566,
+  995,
+  715,
+  880,
+  819,
+  67,
+  152,
+  154,
+  331,
+  191,
+  879,
+  869,
+  201,
+  642,
+  229,
+  298,
+  251,
+  182,
+  871,
+  757,
+  905,
+  462,
+  7,
+  9,
+  896,
+  234,
+  51,
+  579,
+  603,
+  265,
+  850,
+  203,
+  62,
+  577,
+  812,
+  511,
+  816,
+  498,
+  805,
+  35,
+  358,
+  144,
+  77,
+  731,
+  198,
+  647,
+  679,
+  697,
+  766,
+  553,
+  980,
+  49,
+  337,
+  803,
+  387,
+  593,
+  459,
+  286,
+  352,
+  798,
+  154,
+  888,
+  494,
+  914,
+  961,
+  547,
+  154,
+  802,
+  889,
+  726,
+  638,
+  740,
+  710,
+  263,
+  126,
+  509,
+  220,
+  626,
+  650,
+  40,
+  821,
+  979,
+  240,
+  371,
+  936,
+  7,
+  926,
+  252,
+  142,
+  200,
+  1,
+  801,
+  252,
+  208,
+  605,
+  516,
+  777,
+  997,
+  370,
+  869,
+  523,
+  651,
+  799,
+  321,
+  938,
+  575,
+  397,
+  289,
+  704,
+  359,
+  99,
+  245,
+  635,
+  79,
+  849,
+  375,
+  753,
+  806,
+  315,
+  21,
+  871,
+  991,
+  828,
+  942,
+  478,
+  651,
+  532,
+  357,
+  482,
+  76,
+  536,
+  603,
+  8,
+  941,
+  541,
+  639,
+  924,
+  709,
+  648,
+  169,
+  84,
+  810,
+  836,
+  724,
+  997,
+  346,
+  945,
+  961,
+  296,
+  708,
+  790,
+  640,
+  0,
+  829,
+  692,
+  178,
+  258,
+  727,
+  958,
+  490,
+  169,
+  612,
+  232,
+  33,
+  526,
+  776,
+  947,
+  161,
+  697,
+  20,
+  930,
+  57,
+  630,
+  359,
+  716,
+  247,
+  214,
+  839,
+  662,
+  141,
+  401,
+  157,
+  436,
+  98,
+  173,
+  390,
+  620,
+  608,
+  14,
+  518,
+  880,
+  749,
+  218,
+  704,
+  902,
+  131,
+  663,
+  288,
+  797,
+  171,
+  316,
+  89,
+  806,
+  367,
+  513,
+  666,
+  917,
+  660,
+  891,
+  835,
+  610,
+  822,
+  88,
+  765,
+  760,
+  69,
+  579,
+  16,
+  202,
+  470,
+  973,
+  542,
+  21,
+  853,
+  905,
+  108,
+  62,
+  285,
+  313,
+  337,
+  488,
+  546,
+  482,
+  575,
+  385,
+  997,
+  73,
+  919,
+  939,
+  503,
+  888,
+  345,
+  666,
+  425,
+  722,
+  864,
+  831,
+  432,
+  542,
+  196,
+  536,
+  582,
+  275,
+  489,
+  793,
+  835,
+  457,
+  645,
+  275,
+  499,
+  7,
+  759,
+  959,
+  400,
+  983,
+  387,
+  768,
+  928,
+  858,
+  938,
+  938,
+  258,
+  457,
+  166,
+  547,
+  954,
+  505,
+  483,
+  868,
+  556,
+  994,
+  752,
+  163,
+  301,
+  340,
+  445,
+  641,
+  436,
+  439,
+  935,
+  91,
+  736,
+  277,
+  895,
+  935,
+  139,
+  582,
+  208,
+  309,
+  468,
+  784,
+  847,
+  991,
+  571,
+  561,
+  573,
+  143,
+  181,
+  99,
+  232,
+  691,
+  567,
+  634,
+  352,
+  775,
+  39,
+  173,
+  877,
+  688,
+  845,
+  102,
+  565,
+  760,
+  585,
+  920,
+  979,
+  563,
+  839,
+  324,
+  987,
+  541,
+  557,
+  904,
+  658,
+  830,
+  141,
+  77,
+  955,
+  19,
+  357,
+  939,
+  324,
+  793,
+  604,
+  731,
+  535,
+  848,
+  527,
+  392,
+  804,
+  771,
+  202,
+  955,
+  996,
+  904,
+  290,
+  762,
+  368,
+  552,
+  30,
+  277,
+  784,
+  204,
+  446,
+  829,
+  367,
+  857,
+  180,
+  880,
+  148,
+  946,
+  447,
+  309,
+  315,
+  858,
+  231,
+  664,
+  490,
+  946,
+  242,
+  443,
+  448,
+  309,
+  869,
+  650,
+  431,
+  141,
+  990,
+  745,
+  850,
+  593,
+  62,
+  580,
+  690,
+  158,
+  28,
+  98,
+  371,
+  567,
+  309,
+  647,
+  651,
+  602,
+  647,
+  949,
+  938,
+  848,
+  612,
+  239,
+  812,
+  521,
+  37,
+  121,
+  756,
+  674,
+  948,
+  735,
+  779,
+  668,
+  515,
+  320,
+  142,
+  154,
+  266,
+  582,
+  941,
+  887,
+  171,
+  277,
+  392,
+  489,
+  603,
+  654,
+  492,
+  670,
+  313,
+  768,
+  51,
+  545,
+  424,
+  497,
+  834,
+  457,
+  577,
+  798,
+  243,
+  695,
+  722,
+  429,
+  691,
+  209,
+  363,
+  179,
+  302,
+  152,
+  647,
+  743,
+  158,
+  234,
+  127,
+  993,
+  971,
+  477,
+  26,
+  345,
+  84,
+  737,
+  585,
+  496,
+  220,
+  465,
+  126,
+  125,
+  991,
+  870,
+  645,
+  502,
+  531,
+  63,
+  347,
+  616,
+  580,
+  96,
+  315,
+  286,
+  264,
+  230,
+  432,
+  274,
+  537,
+  733,
+  708,
+  931,
+  224,
+  871,
+  886,
+  843,
+  727,
+  249,
+  306,
+  691,
+  887,
+  763,
+  899,
+  717,
+  480,
+  411,
+  124,
+  990,
+  895,
+  767,
+  252,
+  398,
+  713,
+  893,
+  935,
+  773,
+  998,
+  625,
+  849,
+  380,
+  761,
+  627,
+  125,
+  541,
+  108,
+  177,
+  508,
+  824,
+  640,
+  320,
+  809,
+  788,
+  513,
+  115,
+  65,
+  270,
+  584,
+  422,
+  17,
+  840,
+  587,
+  778,
+  703,
+  433,
+  399,
+  92,
+  570,
+  325,
+  22,
+  452,
+  950,
+  105,
+  459,
+  671,
+  7,
+  357,
+  713,
+  106,
+  871,
+  94,
+  404,
+  948,
+  530,
+  631,
+  679,
+  806,
+  774,
+  371,
+  124,
+  529,
+  513,
+  26,
+  859,
+  172,
+  331,
+  566,
+  434,
+  1,
+  970,
+  56,
+  18,
+  411,
+  123,
+  316,
+  194,
+  574,
+  190,
+  302,
+  548,
+  643,
+  635,
+  871,
+  630,
+  207,
+  193,
+  984,
+  963,
+  623,
+  742,
+  257,
+  336,
+  153,
+  792,
+  967,
+  235,
+  506,
+  401,
+  408,
+  45,
+  648,
+  153,
+  364,
+  320,
+  619,
+  949,
+  354,
+  243,
+  437,
+  646,
+  675,
+  74,
+  658,
+  781,
+  24,
+  282,
+  902,
+  530,
+  403,
+  499,
+  962,
+  787,
+  980,
+  815,
+  163,
+  921,
+  355,
+  375,
+  103,
+  223,
+  556,
+  860,
+  636,
+  420,
+  212,
+  690,
+  559,
+  39,
+  222,
+  201,
+  70,
+  282,
+  83,
+  53,
+  83,
+  520,
+  716,
+  286,
+  149,
+  456,
+  277,
+  130,
+  500,
+  379,
+  495,
+  485,
+  729,
+  922,
+  762,
+  59,
+  880,
+  432,
+  6,
+  500,
+  19,
+  982,
+  612,
+  22,
+  812,
+  278,
+  222,
+  897,
+  854,
+  360,
+  719,
+  923,
+  264,
+  120,
+  760,
+  427,
+  520,
+  304,
+  800,
+  411,
+  720,
+  729,
+  399,
+  207,
+  336,
+  917,
+  368,
+  763,
+  560,
+  568,
+  609,
+  361,
+  359,
+  253,
+  672,
+  742,
+  141,
+  397,
+  292,
+  262,
+  881,
+  258,
+  564,
+  566,
+  72,
+  633,
+  920,
+  904,
+  419,
+  990,
+  10,
+  812,
+  547,
+  545,
+  232,
+  129,
+  284,
+  975,
+  178,
+  483,
+  75,
+  780,
+  562,
+  910,
+  277,
+  107,
+  836,
+  912,
+  638,
+  896,
+  204,
+  861,
+  507,
+  604,
+  103,
+  868,
+  644,
+  496,
+  215,
+  215,
+  553,
+  645,
+  398,
+  752,
+  352,
+  984,
+  6,
+  846,
+  49,
+  811,
+  354,
+  263,
+  286,
+  518,
+  269,
+  639,
+  74,
+  637,
+  917,
+  15,
+  244,
+  539,
+  595,
+  545,
+  856,
+  68,
+  354,
+  968,
+  10,
+  256,
+  106,
+  124,
+  864,
+  595,
+  936,
+  194,
+  956,
+  201,
+  612,
+  603,
+  546,
+  703,
+  582,
+  139,
+  436,
+  716,
+  605,
+  65,
+  832,
+  103,
+  742,
+  511,
+  26,
+  122,
+  309,
+  599,
+  251,
+  324,
+  507,
+  125,
+  294,
+  877,
+  45,
+  956,
+  27,
+  330,
+  36,
+  80,
+  298,
+  272,
+  438,
+  243,
+  437,
+  741,
+  121,
+  507,
+  674,
+  194,
+  263,
+  440,
+  772,
+  93,
+  3,
+  139,
+  173,
+  594,
+  174,
+  770,
+  954,
+  393,
+  549,
+  33,
+  435,
+  836,
+  75,
+  842,
+  469,
+  887,
+  919,
+  901,
+  326,
+  898,
+  346,
+  314,
+  389,
+  818,
+  663,
+  371,
+  843,
+  363,
+  959,
+  215,
+  802,
+  218,
+  776,
+  153,
+  648,
+  150,
+  257,
+  31,
+  711,
+  335,
+  516,
+  582,
+  317,
+  999,
+  393,
+  435,
+  371,
+  926,
+  507,
+  933,
+  925,
+  825,
+  554,
+  870,
+  845,
+  194,
+  588,
+  423,
+  819,
+  698,
+  312,
+  107,
+  541,
+  443,
+  833,
+  20,
+  79,
+  147,
+  331,
+  986,
+  784,
+  130,
+  261,
+  714,
+  537,
+  500,
+  363,
+  259,
+  122,
+  506,
+  550,
+  204,
+  466,
+  763,
+  650,
+  360,
+  826,
+  385,
+  189,
+  836,
+  807,
+  862,
+  943,
+  431,
+  547,
+  300,
+  682,
+  336,
+  71,
+  467,
+  871,
+  6,
+  207,
+  214,
+  482,
+  128,
+  42,
+  151,
+  788,
+  597,
+  644,
+  217,
+  507,
+  653,
+  330,
+  660,
+  696,
+  287,
+  513,
+  506,
+  124,
+  348,
+  195,
+  344,
+  480,
+  112,
+  839,
+  497,
+  751,
+  689,
+  579,
+  820,
+  490,
+  903,
+  809,
+  790,
+  409,
+  684,
+  708,
+  538,
+  177,
+  77,
+  702,
+  997,
+  846,
+  958,
+  767,
+  174,
+  206,
+  236,
+  340,
+  66,
+  495,
+  364,
+  833,
+  710,
+  598,
+  889,
+  36,
+  413,
+  485,
+  27,
+  824,
+  138,
+  864,
+  146,
+  890,
+  855,
+  133,
+  57,
+  788,
+  755,
+  597,
+  256,
+  76,
+  75,
+  795,
+  970,
+  384,
+  463,
+  528,
+  142,
+  232,
+  973,
+  961,
+  696,
+  231,
+  251,
+  918,
+  383,
+  264,
+  229,
+  103,
+  610,
+  505,
+  311,
+  725,
+  203,
+  414,
+  53,
+  258,
+  973,
+  293,
+  254,
+  782,
+  26,
+  490,
+  190,
+  927,
+  341,
+  479,
+  858,
+  804,
+  463,
+  457,
+  47,
+  718,
+  205,
+  521,
+  107,
+  171,
+  414,
+  845,
+  941,
+  865,
+  778,
+  315,
+  513,
+  236,
+  669,
+  681,
+  187,
+  964,
+  875,
+  548,
+  869,
+  157,
+  782,
+  876,
+  820,
+  436,
+  595,
+  304,
+  452,
+  667,
+  827,
+  803,
+  227,
+  466,
+  253,
+  874,
+  43,
+  987,
+  416,
+  64,
+  529,
+  943,
+  471,
+  753,
+  259,
+  81,
+  693,
+  231,
+  159,
+  143,
+  399,
+  492,
+  510,
+  257,
+  825,
+  557,
+  263,
+  536,
+  200,
+  71,
+  744,
+  132,
+  231,
+  842,
+  159,
+  49,
+  302,
+  806,
+  870,
+  999,
+  580,
+  941,
+  437,
+  261,
+  861,
+  423,
+  929,
+  994,
+  534,
+  396,
+  315,
+  783,
+  765,
+  930,
+  644,
+  756,
+  462,
+  195,
+  564,
+  22,
+  384,
+  521,
+  730,
+  505,
+  63,
+  457,
+  709,
+  976,
+  314,
+  282,
+  864,
+  118,
+  724,
+  440,
+  316,
+  776,
+  848,
+  506,
+  48,
+  233,
+  789,
+  380,
+  580,
+  889,
+  81,
+  697,
+  763,
+  59,
+  234,
+  408,
+  647,
+  306,
+  431,
+  170,
+  942,
+  7,
+  854,
+  406,
+  217,
+  257,
+  654,
+  945,
+  846,
+  874,
+  436,
+  621,
+  787,
+  538,
+  556,
+  245,
+  891,
+  675,
+  141,
+  746,
+  646,
+  56,
+  919,
+  717,
+  816,
+  234,
+  712,
+  458,
+  339,
+  680,
+  705,
+  485,
+  616,
+  610,
+  208,
+  251,
+  273,
+  242,
+  151,
+  560,
+  362,
+  520,
+  417,
+  760,
+  758,
+  89,
+  229,
+  964,
+  150,
+  683,
+  851,
+  620,
+  180,
+  304,
+  339,
+  923,
+  78,
+  12,
+  253,
+  307,
+  854,
+  692,
+  339,
+  854,
+  773,
+  925,
+  938,
+  926,
+  680,
+  358,
+  592,
+  522,
+  3,
+  916,
+  431,
+  61,
+  649,
+  448,
+  463,
+  508,
+  758,
+  646,
+  122,
+  644,
+  508,
+  85,
+  945,
+  934,
+  473,
+  86,
+  380,
+  856,
+  26,
+  642,
+  831,
+  889,
+  592,
+  669,
+  896,
+  665,
+  897,
+  497,
+  740,
+  987,
+  530,
+  217,
+  945,
+  800,
+  104,
+  267,
+  558,
+  688,
+  806,
+  944,
+  79,
+  119,
+  416,
+  715,
+  389,
+  267,
+  333,
+  579,
+  882,
+  278,
+  972,
+  767,
+  890,
+  412,
+  110,
+  525,
+  605,
+  273,
+  857,
+  312,
+  841,
+  312,
+  76,
+  596,
+  956,
+  484,
+  30,
+  230,
+  319,
+  789,
+  586,
+  44,
+  341,
+  434,
+  565,
+  238,
+  907,
+  581,
+  719,
+  944,
+  19,
+  447,
+  599,
+  966,
+  776,
+  472,
+  393,
+  179,
+  350,
+  59,
+  291,
+  317,
+  585,
+  868,
+  750,
+  464,
+  35,
+  79,
+  888,
+  245,
+  972,
+  150,
+  190,
+  511,
+  785,
+  79,
+  726,
+  51,
+  655,
+  456,
+  474,
+  441,
+  257,
+  664,
+  257,
+  683,
+  70,
+  763,
+  743,
+  208,
+  190,
+  857,
+  693,
+  574,
+  626,
+  411,
+  484,
+  434,
+  507,
+  779,
+  306,
+  549,
+  778,
+  512,
+  343,
+  549,
+  679,
+  259,
+  793,
+  492,
+  966,
+  281,
+  787,
+  858,
+  419,
+  580,
+  588,
+  626,
+  166,
+  360,
+  780,
+  747,
+  249,
+  856,
+  305,
+  861,
+  383,
+  938,
+  520,
+  78,
+  311,
+  334,
+  592,
+  8,
+  629,
+  606,
+  623,
+  217,
+  466,
+  378,
+  856,
+  551,
+  458,
+  243,
+  484,
+  294,
+  587,
+  953,
+  749,
+  287,
+  733,
+  796,
+  498,
+  534,
+  989,
+  379,
+  804,
+  560,
+  971,
+  333,
+  384,
+  367,
+  292,
+  898,
+  277,
+  508,
+  58,
+  636,
+  37,
+  312,
+  742,
+  879,
+  536,
+  239,
+  240,
+  730,
+  3,
+  593,
+  301,
+  66,
+  144,
+  62,
+  248,
+  634,
+  863,
+  14,
+  579,
+  120,
+  250,
+  322,
+  964,
+  447,
+  727,
+  322,
+  765,
+  268,
+  206,
+  364,
+  515,
+  471,
+  858,
+  438,
+  840,
+  968,
+  13,
+  264,
+  388,
+  75,
+  163,
+  137,
+  999,
+  866,
+  153,
+  356,
+  193,
+  854,
+  718,
+  606,
+  730,
+  162,
+  431,
+  375,
+  917,
+  548,
+  825,
+  99,
+  271,
+  0,
+  303,
+  228,
+  894,
+  370,
+  644,
+  38,
+  532,
+  512,
+  546,
+  303,
+  923,
+  170,
+  489,
+  40,
+  82,
+  479,
+  971,
+  452,
+  637,
+  557,
+  940,
+  132,
+  908,
+  268,
+  774,
+  932,
+  786,
+  976,
+  491,
+  710,
+  197,
+  554,
+  532,
+  265,
+  909,
+  18,
+  758,
+  213,
+  45,
+  698,
+  180,
+  990,
+  471,
+  610,
+  575,
+  659,
+  412,
+  595,
+  275,
+  498,
+  713,
+  306,
+  259,
+  1,
+  253,
+  316,
+  357,
+  155,
+  55,
+  520,
+  687,
+  350,
+  644,
+  974,
+  945,
+  277,
+  654,
+  850,
+  412,
+  847,
+  384,
+  820,
+  512,
+  979,
+  21,
+  823,
+  299,
+  93,
+  793,
+  204,
+  925,
+  130,
+  103,
+  314,
+  105,
+  564,
+  762,
+  524,
+  478,
+  178,
+  807,
+  56,
+  916,
+  711,
+  511,
+  111,
+  865,
+  110,
+  195,
+  982,
+  171,
+  631,
+  960,
+  640,
+  584,
+  600,
+  770,
+  669,
+  649,
+  51,
+  212,
+  828,
+  973,
+  448,
+  101,
+  856,
+  801,
+  679,
+  694,
+  242,
+  334,
+  620,
+  160,
+  667,
+  891,
+  791,
+  659,
+  107,
+  865,
+  126,
+  882,
+  675,
+  726,
+  234,
+  346,
+  875,
+  88,
+  115,
+  592,
+  729,
+  299,
+  177,
+  210,
+  456,
+  766,
+  928,
+  837,
+  417,
+  856,
+  631,
+  142,
+  640,
+  848,
+  805,
+  989,
+  509,
+  106,
+  440,
+  276,
+  581,
+  117,
+  187,
+  565,
+  620,
+  433,
+  475,
+  873,
+  626,
+  342,
+  455,
+  373,
+  767,
+  855,
+  866,
+  942,
+  108,
+  117,
+  799,
+  85,
+  936,
+  665,
+  975,
+  750,
+  35,
+  769,
+  889,
+  610,
+  210,
+  220,
+  359,
+  981,
+  728,
+  649,
+  0,
+  826,
+  950,
+  120,
+  648,
+  58,
+  383,
+  436,
+  737,
+  11,
+  714,
+  424,
+  251,
+  301,
+  204,
+  287,
+  183,
+  472,
+  265,
+  120,
+  780,
+  369,
+  695,
+  758,
+  740,
+  107,
+  831,
+  93,
+  535,
+  306,
+  777,
+  976,
+  562,
+  59,
+  956,
+  304,
+  83,
+  576,
+  399,
+  999,
+  899,
+  824,
+  350,
+  635,
+  896,
+  802,
+  332,
+  421,
+  878,
+  433,
+  193,
+  353,
+  802,
+  683,
+  456,
+  88,
+  211,
+  132,
+  432,
+  354,
+  421,
+  616,
+  53,
+  231,
+  915,
+  510,
+  106,
+  28,
+  32,
+  600,
+  461,
+  131,
+  594,
+  678,
+  744,
+  674,
+  620,
+  290,
+  535,
+  534,
+  543,
+  62,
+  971,
+  905,
+  180,
+  10,
+  234,
+  166,
+  272,
+  73,
+  128,
+  437,
+  613,
+  291,
+  638,
+  610,
+  225,
+  630,
+  309,
+  112,
+  868,
+  557,
+  439,
+  355,
+  555,
+  579,
+  443,
+  843,
+  20,
+  464,
+  987,
+  284,
+  302,
+  450,
+  355,
+  83,
+  407,
+  711,
+  752,
+  187,
+  249,
+  807,
+  883,
+  924,
+  858,
+  110,
+  409,
+  189,
+  998,
+  439,
+  120,
+  321,
+  875,
+  140,
+  640,
+  285,
+  561,
+  873,
+  371,
+  73,
+  4,
+  169,
+  771,
+  413,
+  447,
+  985,
+  206,
+  635,
+  943,
+  960,
+  240,
+  554,
+  209,
+  576,
+  254,
+  163,
+  977,
+  846,
+  610,
+  596,
+  920,
+  524,
+  608,
+  402,
+  249,
+  624,
+  180,
+  875,
+  240,
+  670,
+  421,
+  1,
+  911,
+  505,
+  474,
+  979,
+  623,
+  678,
+  952,
+  909,
+  751,
+  241,
+  269,
+  968,
+  396,
+  641,
+  516,
+  965,
+  406,
+  54,
+  853,
+  346,
+  650,
+  787,
+  400,
+  175,
+  929,
+  662,
+  870,
+  170,
+  468,
+  173,
+  620,
+  318,
+  170,
+  995,
+  525,
+  138,
+  520,
+  151,
+  851,
+  30,
+  596,
+  605,
+  802,
+  449,
+  174,
+  518,
+  633,
+  293,
+  652,
+  779,
+  606,
+  444,
+  472,
+  359,
+  204,
+  308,
+  104,
+  274,
+  707,
+  638,
+  193,
+  577,
+  125,
+  28,
+  537,
+  987,
+  521,
+  80,
+  56,
+  111,
+  589,
+  81,
+  794,
+  377,
+  36,
+  680,
+  476,
+  227,
+  778,
+  138,
+  24,
+  752,
+  160,
+  590,
+  855,
+  396,
+  289,
+  142,
+  785,
+  551,
+  696,
+  514,
+  268,
+  536,
+  547,
+  207,
+  943,
+  166,
+  0,
+  959,
+  114,
+  322,
+  906,
+  322,
+  892,
+  960,
+  152,