diff --git a/README.md b/README.md index d420045..0e9e4e7 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,9 @@ mix of instructions in the code. The CPI for the individual instructions is: | indirect jump (jalr) | 8 | | shift operations | 5+ | -Dhrystone benchmark results: 0.146 DMIPS/MHz (258 Dhrystones/Second/MHz) +Dhrystone benchmark results: 0.215 DMIPS/MHz (379 Dhrystones/Second/MHz) -For the Dryhstone benchmark the average CPI is 6.181. +For the Dryhstone benchmark the average CPI is 5.983. *This numbers apply for setups with memory that can accomodate requests within one clock cycle. Slower memory will degrade the performance of the processor.* diff --git a/dhrystone/Makefile b/dhrystone/Makefile index 81dea54..412ffda 100644 --- a/dhrystone/Makefile +++ b/dhrystone/Makefile @@ -1,6 +1,6 @@ OBJS = start.o dhry_1.o dhry_2.o stdlib.o -CFLAGS = -MD -O3 -m32 -march=RV32I -ffreestanding -nostdlib -DTIME +CFLAGS = -MD -O3 -m32 -march=RV32I -ffreestanding -nostdlib -DTIME -DRISCV test: testbench.exe dhry.hex vvp -N testbench.exe diff --git a/dhrystone/dhry_1.c b/dhrystone/dhry_1.c index f2fd95c..849cea8 100644 --- a/dhrystone/dhry_1.c +++ b/dhrystone/dhry_1.c @@ -52,7 +52,9 @@ extern int times (); #endif #ifdef TIME extern long time(); +#ifdef RISCV extern long insn(); +#endif /* see library function "time" */ #define Too_Small_Time 2 /* Measurements should last at least 2 seconds */ @@ -61,9 +63,11 @@ extern long insn(); long Begin_Time, End_Time, User_Time; +#ifdef RISCV long Begin_Insn, End_Insn, User_Insn; +#endif float Microseconds, Dhrystones_Per_Second; @@ -138,7 +142,9 @@ main () #endif #ifdef TIME Begin_Time = time ( (long *) 0); +#ifdef RISCV Begin_Insn = insn ( (long *) 0); +#endif #endif for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) @@ -197,7 +203,9 @@ main () #endif #ifdef TIME End_Time = time ( (long *) 0); +#ifdef RISCV End_Insn = insn ( (long *) 0); +#endif #endif printf ("Execution ends\n"); @@ -254,9 +262,10 @@ main () printf ("\n"); User_Time = End_Time - Begin_Time; + +#ifdef RISCV User_Insn = End_Insn - Begin_Insn; -#if 1 printf("Number_Of_Runs: %d\n", Number_Of_Runs); printf("User_Time: %d cycles, %d insn\n", User_Time, User_Insn); diff --git a/dhrystone/dhry_1_orig.c b/dhrystone/dhry_1_orig.c new file mode 100644 index 0000000..7ab02a8 --- /dev/null +++ b/dhrystone/dhry_1_orig.c @@ -0,0 +1,385 @@ +/* + **************************************************************************** + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry_1.c (part 2 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * + **************************************************************************** + */ + +#include "dhry.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]; + +extern char *malloc (); +Enumeration Func_1 (); + /* forward declaration necessary since Enumeration may not simply be int */ + +#ifndef REG + Boolean Reg = false; +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#else + Boolean Reg = true; +#endif + +/* variables for time measurement: */ + +#ifdef TIMES +struct tms time_info; +extern int times (); + /* see library function "times" */ +#define Too_Small_Time 120 + /* Measurements should last at least about 2 seconds */ +#endif +#ifdef TIME +extern long time(); + /* see library function "time" */ +#define Too_Small_Time 2 + /* Measurements should last at least 2 seconds */ +#endif + +long Begin_Time, + End_Time, + User_Time; +float Microseconds, + Dhrystones_Per_Second; + +/* end of variables for time measurement */ + + +main () +/*****/ + + /* 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; + + /* Initializations */ + + Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + Ptr_Glob = (Rec_Pointer) malloc (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. */ + + printf ("\n"); + printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); + printf ("\n"); + if (Reg) + { + printf ("Program compiled with 'register' attribute\n"); + printf ("\n"); + } + else + { + printf ("Program compiled without 'register' attribute\n"); + printf ("\n"); + } + printf ("Please give the number of runs through the benchmark: "); + { + int n; + scanf ("%d", &n); + Number_Of_Runs = n; + } + printf ("\n"); + + printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs); + + /***************/ + /* Start timer */ + /***************/ + +#ifdef TIMES + times (&time_info); + Begin_Time = (long) time_info.tms_utime; +#endif +#ifdef TIME + Begin_Time = time ( (long *) 0); +#endif + + 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 */ + /**************/ + +#ifdef TIMES + times (&time_info); + End_Time = (long) time_info.tms_utime; +#endif +#ifdef TIME + End_Time = time ( (long *) 0); +#endif + + printf ("Execution ends\n"); + printf ("\n"); + printf ("Final values of the variables used in the benchmark:\n"); + printf ("\n"); + printf ("Int_Glob: %d\n", Int_Glob); + printf (" should be: %d\n", 5); + printf ("Bool_Glob: %d\n", Bool_Glob); + printf (" should be: %d\n", 1); + printf ("Ch_1_Glob: %c\n", Ch_1_Glob); + printf (" should be: %c\n", 'A'); + printf ("Ch_2_Glob: %c\n", Ch_2_Glob); + printf (" should be: %c\n", 'B'); + printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); + printf (" should be: %d\n", 7); + printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); + printf (" should be: Number_Of_Runs + 10\n"); + printf ("Ptr_Glob->\n"); + printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); + printf (" should be: (implementation-dependent)\n"); + printf (" Discr: %d\n", Ptr_Glob->Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); + printf (" should be: %d\n", 2); + printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); + printf (" should be: %d\n", 17); + printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Next_Ptr_Glob->\n"); + printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); + printf (" should be: (implementation-dependent), same as above\n"); + printf (" Discr: %d\n", Next_Ptr_Glob->Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); + printf (" should be: %d\n", 1); + printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); + printf (" should be: %d\n", 18); + printf (" Str_Comp: %s\n", + Next_Ptr_Glob->variant.var_1.Str_Comp); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Int_1_Loc: %d\n", Int_1_Loc); + printf (" should be: %d\n", 5); + printf ("Int_2_Loc: %d\n", Int_2_Loc); + printf (" should be: %d\n", 13); + printf ("Int_3_Loc: %d\n", Int_3_Loc); + printf (" should be: %d\n", 7); + printf ("Enum_Loc: %d\n", Enum_Loc); + printf (" should be: %d\n", 1); + printf ("Str_1_Loc: %s\n", Str_1_Loc); + printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); + printf ("Str_2_Loc: %s\n", Str_2_Loc); + printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); + printf ("\n"); + + User_Time = End_Time - Begin_Time; + + if (User_Time < Too_Small_Time) + { + printf ("Measured time too small to obtain meaningful results\n"); + printf ("Please increase number of runs\n"); + printf ("\n"); + } + else + { +#ifdef TIME + Microseconds = (float) User_Time * Mic_secs_Per_Second + / (float) Number_Of_Runs; + Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; +#else + 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; +#endif + printf ("Microseconds for one run through Dhrystone: "); + printf ("%6.1f \n", Microseconds); + printf ("Dhrystones per Second: "); + printf ("%6.1f \n", Dhrystones_Per_Second); + printf ("\n"); + } + +} + + +Proc_1 (Ptr_Val_Par) +/******************/ + +REG 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 */ + + +Proc_2 (Int_Par_Ref) +/******************/ + /* executed once */ + /* *Int_Par_Ref == 1, becomes 4 */ + +One_Fifty *Int_Par_Ref; +{ + 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 */ + + +Proc_3 (Ptr_Ref_Par) +/******************/ + /* executed once */ + /* Ptr_Ref_Par becomes Ptr_Glob */ + +Rec_Pointer *Ptr_Ref_Par; + +{ + 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 */ + + +Proc_4 () /* without parameters */ +/*******/ + /* executed once */ +{ + Boolean Bool_Loc; + + Bool_Loc = Ch_1_Glob == 'A'; + Bool_Glob = Bool_Loc | Bool_Glob; + Ch_2_Glob = 'B'; +} /* Proc_4 */ + + +Proc_5 () /* without parameters */ +/*******/ + /* executed once */ +{ + Ch_1_Glob = 'A'; + Bool_Glob = false; +} /* Proc_5 */ + + + /* Procedure for the assignment of structures, */ + /* if the C compiler doesn't support this feature */ +#ifdef NOSTRUCTASSIGN +memcpy (d, s, l) +register char *d; +register char *s; +register int l; +{ + while (l--) *d++ = *s++; +} +#endif + + diff --git a/dhrystone/stdlib.c b/dhrystone/stdlib.c index 4229aa2..2ff7ba3 100644 --- a/dhrystone/stdlib.c +++ b/dhrystone/stdlib.c @@ -38,12 +38,97 @@ char *malloc(int size) return p; } +#if 0 void *memcpy(char *dest, const char *src, int n) { while (n--) *(dest++) = *(src++); } +#else +/* copy&paste from disassembled libc */ +asm ( +" .global memcpy; " +" memcpy: xor a5,a1,a0; " +" slli a4,a5,0x1e; " +" add a7,a0,a2; " +" bnez a4,.M1; " +" li a5,3; " +" bleu a2,a5,.M2; " +" slli a5,a0,0x1e; " +" bnez a5,.M3; " +" andi a6,a7,-4; " +" addi a5,a6,-32; " +" mv a4,a0; " +" bltu a0,a5,.M4; " +" .M9: mv a3,a1; " +" mv a5,a4; " +" bleu a6,a4,.M5; " +" .M6: lw a2,0(a3); " +" addi a5,a5,4; " +" addi a3,a3,4; " +" sw a2,-4(a5); " +" bltu a5,a6,.M6; " +" not a5,a4; " +" add a6,a5,a6; " +" andi a6,a6,-4; " +" addi a6,a6,4; " +" add a4,a4,a6; " +" add a1,a1,a6; " +" .M5: bltu a4,a7,.M7; " +" .M11: ret; " +" .M3: mv a4,a0; " +" .M8: lbu a5,0(a1); " +" addi a4,a4,1; " +" addi a1,a1,1; " +" sb a5,-1(a4); " +" slli a5,a4,0x1e; " +" bnez a5,.M8; " +" andi a6,a7,-4; " +" addi a5,a6,-32; " +" bleu a5,a4,.M9; " +" .M4: lw t6,0(a1); " +" lw t5,4(a1); " +" lw t4,8(a1); " +" lw t3,12(a1); " +" lw t2,16(a1); " +" lw t1,20(a1); " +" lw t0,24(a1); " +" lw a2,28(a1); " +" addi a1,a1,36; " +" addi a4,a4,36; " +" lw a3,-4(a1); " +" sw t6,-36(a4); " +" sw t5,-32(a4); " +" sw t4,-28(a4); " +" sw t3,-24(a4); " +" sw t2,-20(a4); " +" sw t1,-16(a4); " +" sw t0,-12(a4); " +" sw a2,-8(a4); " +" sw a3,-4(a4); " +" bltu a4,a5,.M4; " +" j .M9; " +" .M1: mv a4,a0; " +" bleu a7,a0,.M10; " +" .M7: lbu a5,0(a1); " +" addi a4,a4,1; " +" addi a1,a1,1; " +" sb a5,-1(a4); " +" bltu a4,a7,.M7; " +" .M12: ret; " +" .M2: mv a4,a0; " +" bleu a7,a0,.M11; " +" lbu a5,0(a1); " +" addi a4,a4,1; " +" addi a1,a1,1; " +" sb a5,-1(a4); " +" bltu a4,a7,.M7; " +" j .M12; " +" .M10: ret; " +); +#endif +#if 0 char *strcpy(char *dest, const char *src) { char *ret = dest; @@ -53,7 +138,55 @@ char *strcpy(char *dest, const char *src) while (*(src++)); return ret; } +#else +/* copy&paste from disassembled libc */ +asm ( +" .global strcpy; " +" strcpy: or a5,a0,a1; " +" slli a4,a5,0x1e; " +" bnez a4,.S1; " +" lw a4,0(a1); " +" lui a3,0x7f7f8; " +" addi a3,a3,-129; " +" and a5,a4,a3; " +" add a5,a5,a3; " +" or a7,a4,a3; " +" or a7,a7,a5; " +" li a5,-1; " +" mv a2,a0; " +" bne a7,a5,.S2; " +" .S3: addi a2,a2,4; " +" addi a1,a1,4; " +" sw a4,-4(a2); " +" lw a4,0(a1); " +" and a5,a4,a3; " +" or a6,a4,a3; " +" add a5,a5,a3; " +" or a5,a6,a5; " +" beq a5,a7,.S3; " +" .S2: lbu a5,0(a1); " +" lbu a4,1(a1); " +" lbu a3,2(a1); " +" sb a5,0(a2); " +" beqz a5,.S4; " +" sb a4,1(a2); " +" beqz a4,.S4; " +" sb a3,2(a2); " +" bnez a3,.S5; " +" .S4: ret; " +" .S5: sb zero,3(a2); " +" ret; " +" .S1: mv a5,a0; " +" .S6: lbu a4,0(a1); " +" addi a5,a5,1; " +" addi a1,a1,1; " +" sb a4,-1(a5); " +" bnez a4,.S6; " +" ret; " +); +#endif +#if 0 int strcmp(const char *s1, const char *s2) { // printf("[strcmp()]"); @@ -67,6 +200,81 @@ int strcmp(const char *s1, const char *s2) s1++, s2++; } } +#else +/* copy&paste from disassembled libc */ +asm ( +" .global strcmp; " +" strcmp: or a4,a0,a1; " +" li t2,-1; " +" andi a4,a4,3; " +" bnez a4,.K1; " +" lui t3,0x7f7f8; " +" addi t3,t3,-129; " +" .K6: lw a2,0(a0); " +" lw a3,0(a1); " +" and t0,a2,t3; " +" or t1,a2,t3; " +" add t0,t0,t3; " +" or t0,t0,t1; " +" bne t0,t2,.K2; " +" bne a2,a3,.K3; " +" lw a2,4(a0); " +" lw a3,4(a1); " +" and t0,a2,t3; " +" or t1,a2,t3; " +" add t0,t0,t3; " +" or t0,t0,t1; " +" bne t0,t2,.K4; " +" bne a2,a3,.K3; " +" lw a2,8(a0); " +" lw a3,8(a1); " +" and t0,a2,t3; " +" or t1,a2,t3; " +" add t0,t0,t3; " +" or t0,t0,t1; " +" bne t0,t2,.K5; " +" addi a0,a0,12; " +" addi a1,a1,12; " +" beq a2,a3,.K6; " +" .K3: slli a4,a2,0x10; " +" slli a5,a3,0x10; " +" bne a4,a5,.K7; " +" srli a4,a2,0x10; " +" srli a5,a3,0x10; " +" sub a0,a4,a5; " +" andi a1,a0,255; " +" bnez a1,.K8; " +" ret; " +" .K7: srli a4,a4,0x10; " +" srli a5,a5,0x10; " +" sub a0,a4,a5; " +" andi a1,a0,255; " +" bnez a1,.K8; " +" ret; " +" .K8: andi a4,a4,255; " +" andi a5,a5,255; " +" sub a0,a4,a5; " +" ret; " +" .K1: lbu a2,0(a0); " +" lbu a3,0(a1); " +" addi a0,a0,1; " +" addi a1,a1,1; " +" bne a2,a3,.K9; " +" bnez a2,.K1; " +" .K9: sub a0,a2,a3; " +" ret; " +" .K4: addi a0,a0,4; " +" addi a1,a1,4; " +" .K2: bne a2,a3,.K1; " +" li a0,0; " +" ret; " +" .K5: addi a0,a0,8; " +" addi a1,a1,8; " +" bne a2,a3,.K1; " +" li a0,0; " +" ret; " +); +#endif static void printf_c(int c) {