Compare commits
9 Commits
encode-to-
...
performanc
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f4e3f7c72 | |||
| 0a76c24490 | |||
| e493518509 | |||
| c692932124 | |||
| dc9c8578b6 | |||
| 913d17224b | |||
| 2d212949d9 | |||
| 26b025b556 | |||
| 056d4e0821 |
16
Tests/isa/CPrograms/Benchmarks/Matrixmul/build.sh
Normal file
16
Tests/isa/CPrograms/Benchmarks/Matrixmul/build.sh
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc_test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../link.ld home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
scp matrixmul.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c memaccess.c'
|
||||||
|
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -DDEFINE_MALLOC -DDEFINE_FREE -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -T link.ld -o testC start.S matrixmul.c malloc.c malloc_test.c'
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
||||||
|
|
||||||
|
scp home-1:/home/akilan/cheri/output/sdk/bin/testC ../../../
|
||||||
|
|
||||||
|
|
||||||
217
Tests/isa/CPrograms/Benchmarks/Matrixmul/matrixmul.c
Normal file
217
Tests/isa/CPrograms/Benchmarks/Matrixmul/matrixmul.c
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
// Source: https://github.com/ivanbgd/Matrix-Multiplication-MatMul-C/blob/master/matmul_1d_seq.c
|
||||||
|
#define MATMUL_1D
|
||||||
|
#ifdef MATMUL_1D
|
||||||
|
|
||||||
|
/* Matrices are represented as 1-D arrays in memory.
|
||||||
|
* That means they are contiguous in memory.
|
||||||
|
* Minimum dimension is 1, not 0, and internal dimensions must match. */
|
||||||
|
|
||||||
|
// #include <math.h>
|
||||||
|
// #include <omp.h>
|
||||||
|
// #include <stdio.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include <string.h>
|
||||||
|
// #include <time.h>
|
||||||
|
#include <cheriintrin.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void free(void * __capability ptr);
|
||||||
|
void * __capability malloc(size_t size);
|
||||||
|
|
||||||
|
/* Initializes vector or matrix, sequentially, with indices. */
|
||||||
|
void init_seq(int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a) {
|
||||||
|
for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
|
for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
|
a[i*n_cols_a + j] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static unsigned int seed = 123456789; // must be initialized somehow
|
||||||
|
|
||||||
|
// unsigned int rand_test(void)
|
||||||
|
// {
|
||||||
|
// seed = (1103515245 * seed + 12345);
|
||||||
|
// return (seed >> 16) & 0x7FFF; // 15-bit result
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /* Initializes vector or matrix, randomly. */
|
||||||
|
// void init_rand(double *a, const unsigned n_rows_a, const unsigned n_cols_a) {
|
||||||
|
// for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
|
// for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
|
// a[i*n_cols_a + j] = rand_test() / 32767.0;
|
||||||
|
// // rand_test() / (double)RAND_MAX;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* Takes and returns a new matrix, t, which is a transpose of the original one, m.
|
||||||
|
It's also flat in memory, i.e., 1-D, but it should be looked at as a transpose
|
||||||
|
of m, meaning, n_rows_t == n_cols_m, and n_cols_t == n_rows_m.
|
||||||
|
The original matrix m stays intact. */
|
||||||
|
int __capability * transpose(const int __capability *m, const unsigned n_rows_m, const unsigned n_cols_m, int __capability *t) {
|
||||||
|
for (size_t i = 0; i < n_rows_m; i++) {
|
||||||
|
for (size_t j = 0; j < n_cols_m; j++) {
|
||||||
|
t[j*n_rows_m + i] = m[i*n_cols_m + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dot product of two arrays, or matrix product
|
||||||
|
* Allocates and returns an array.
|
||||||
|
* This variant doesn't transpose matrix b, and it's a lot slower. */
|
||||||
|
int * __capability dot_simple(const int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a,\
|
||||||
|
const int * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
||||||
|
|
||||||
|
if (n_cols_a != n_rows_b) {
|
||||||
|
// printf("#columns A must be equal to #rows B!\n");
|
||||||
|
// system("pause");
|
||||||
|
// exit(-2);
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int * __capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
||||||
|
if (c == NULL) {
|
||||||
|
// printf("Couldn't allocate memory!\n");
|
||||||
|
// system("pause");
|
||||||
|
// exit(-1);
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
|
for (size_t k = 0; k < n_cols_b; k++) {
|
||||||
|
int sum = 0;
|
||||||
|
for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
|
sum += a[i*n_cols_a + j] * b[j*n_cols_b + k];
|
||||||
|
}
|
||||||
|
c[i*n_cols_b + k] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dot product of two arrays, or matrix product
|
||||||
|
* Allocates and returns an array.
|
||||||
|
* This variant transposes matrix b, and it's a lot faster. */
|
||||||
|
int * __capability dot(const int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a, \
|
||||||
|
const int * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
||||||
|
|
||||||
|
if (n_cols_a != n_rows_b) {
|
||||||
|
// printf("#columns A must be equal to #rows B!\n");
|
||||||
|
// system("pause");
|
||||||
|
// exit(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int * __capability bt = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
||||||
|
|
||||||
|
int * __capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
||||||
|
|
||||||
|
if ((c == NULL) || (bt == NULL)) {
|
||||||
|
// printf("Couldn't allocate memory!\n");
|
||||||
|
// system("pause");
|
||||||
|
// exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt = transpose(b, n_rows_b, n_cols_b, bt);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
|
for (size_t k = 0; k < n_cols_b; k++) {
|
||||||
|
int sum = 0;
|
||||||
|
for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
|
sum += a[i*n_cols_a + j] * bt[k*n_rows_b + j];
|
||||||
|
}
|
||||||
|
c[i*n_cols_b + k] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(bt);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prints vector, or matrix. */
|
||||||
|
// void print(const double *a, const unsigned n_rows_a, const unsigned n_cols_a) {
|
||||||
|
// for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
|
// for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
|
// printf("%8.3f ", a[i*n_cols_a + j]);
|
||||||
|
// }
|
||||||
|
// printf("\n");
|
||||||
|
// }
|
||||||
|
// printf("\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
/* Intializes random number generator */
|
||||||
|
// time_t t;
|
||||||
|
// srand((unsigned)time(&t));
|
||||||
|
// srand(0);
|
||||||
|
|
||||||
|
/* For measuring time */
|
||||||
|
int t0, t1;
|
||||||
|
|
||||||
|
const unsigned scale = 20;
|
||||||
|
const unsigned n_rows_a = 4 * scale;
|
||||||
|
const unsigned n_cols_a = 3 * scale;
|
||||||
|
const unsigned n_rows_b = 3 * scale;
|
||||||
|
const unsigned n_cols_b = 2 * scale;
|
||||||
|
|
||||||
|
int __capability *a = malloc(n_rows_a * n_cols_a * sizeof(*a));
|
||||||
|
int __capability *b = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
||||||
|
int __capability *c = NULL;
|
||||||
|
int __capability *d = NULL;
|
||||||
|
|
||||||
|
if (!a || !b) {
|
||||||
|
// printf("Couldn't allocate memory!\n");
|
||||||
|
while(1);
|
||||||
|
// system("pause");
|
||||||
|
// exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init_rand(a, n_rows_a, n_cols_a);
|
||||||
|
// init_rand(b, n_rows_b, n_cols_b);
|
||||||
|
|
||||||
|
init_seq(a, n_rows_a, n_cols_a);
|
||||||
|
init_seq(b, n_rows_b, n_cols_b);
|
||||||
|
|
||||||
|
// for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
|
// for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
|
// a[i*n_cols_a + j] = i*n_cols_a + j;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// t0 = omp_get_wtime();
|
||||||
|
c = dot_simple(a, n_rows_a, n_cols_a, b, n_rows_b, n_cols_b);
|
||||||
|
// t1 = omp_get_wtime();
|
||||||
|
// printf("Dot Simple: Elapsed time %.3f s\n", t1 - t0);
|
||||||
|
|
||||||
|
// // t0 = omp_get_wtime();
|
||||||
|
d = dot(a, n_rows_a, n_cols_a, b, n_rows_b, n_cols_b);
|
||||||
|
// t1 = omp_get_wtime();
|
||||||
|
// printf("Dot: Elapsed time %.3f s\n", t1 - t0);
|
||||||
|
|
||||||
|
// if (scale == 1) {
|
||||||
|
// // printf("Matrix A:\n");
|
||||||
|
// // print(a, n_rows_a, n_cols_a);
|
||||||
|
// // // printf("Matrix B:\n");
|
||||||
|
// // print(b, n_rows_b, n_cols_b);
|
||||||
|
// // // printf("Matrix C:\n");
|
||||||
|
// // print(c, n_rows_a, n_cols_b);
|
||||||
|
// // // printf("Matrix D:\n");
|
||||||
|
// // print(d, n_rows_a, n_cols_b);
|
||||||
|
// }
|
||||||
|
|
||||||
|
free(a);
|
||||||
|
free(b);
|
||||||
|
free(c);
|
||||||
|
free(d);
|
||||||
|
|
||||||
|
// system("pause");
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MATMUL_1D
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
# scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
# scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc_test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../link.ld home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
scp memaccess.c home-1:/home/akilan/cheri/output/sdk/bin/
|
scp memaccess.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c memaccess.c'
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c memaccess.c'
|
||||||
|
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -DDEFINE_MALLOC -DDEFINE_FREE -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -T link.ld -o testC start.S memaccess.c malloc.c malloc_test.c'
|
||||||
|
|
||||||
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,10 @@ All rights reserved.
|
|||||||
|
|
||||||
#define NPAD 7
|
#define NPAD 7
|
||||||
#define MIN_WSS sizeof(struct l)
|
#define MIN_WSS sizeof(struct l)
|
||||||
#define MAX_WSS 70
|
#define MAX_WSS 64 //2^32
|
||||||
|
|
||||||
void free(void * __capability ptr);
|
|
||||||
void * __capability malloc(size_t size);
|
|
||||||
|
|
||||||
|
void free_test(void * __capability ptr);
|
||||||
|
void * __capability malloc_test(size_t size);
|
||||||
|
|
||||||
|
|
||||||
// struct l{
|
// struct l{
|
||||||
@@ -262,6 +261,8 @@ void * walk(void * __capability param)
|
|||||||
// #ifdef INCTEST
|
// #ifdef INCTEST
|
||||||
// current->pad[0]++;
|
// current->pad[0]++;
|
||||||
// #endif
|
// #endif
|
||||||
|
current->pad[0]+=current->n->pad[0];
|
||||||
|
current->pad[0]++;
|
||||||
current=current->n;
|
current=current->n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +278,7 @@ void * walk(void * __capability param)
|
|||||||
|
|
||||||
// printf("%d,%ld,%ld,%ld\n",data->thread_index,data->working_set_size, end-start, data->working_set_size/sizeof(struct l));
|
// printf("%d,%ld,%ld,%ld\n",data->thread_index,data->working_set_size, end-start, data->working_set_size/sizeof(struct l));
|
||||||
|
|
||||||
// free(data);
|
free_test(data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +298,7 @@ int main(void)
|
|||||||
|
|
||||||
// pthread_t threads[NTHREADS];
|
// pthread_t threads[NTHREADS];
|
||||||
|
|
||||||
root=malloc(MAX_WSS/sizeof(struct l) * sizeof(struct l));
|
root=malloc_test(MAX_WSS/sizeof(struct l) * sizeof(struct l));
|
||||||
|
|
||||||
for(working_set_size=MIN_WSS;working_set_size<MAX_WSS;working_set_size=working_set_size<<1)
|
for(working_set_size=MIN_WSS;working_set_size<MAX_WSS;working_set_size=working_set_size<<1)
|
||||||
{
|
{
|
||||||
@@ -330,24 +331,15 @@ int main(void)
|
|||||||
// for(i=0;i<NTHREADS;i++)
|
// for(i=0;i<NTHREADS;i++)
|
||||||
// pthread_join(threads[i],NULL);
|
// pthread_join(threads[i],NULL);
|
||||||
// #else
|
// #else
|
||||||
tdata = malloc(sizeof(struct thread_start_data));
|
tdata = malloc_test(sizeof(struct thread_start_data));
|
||||||
tdata->thread_index=0;
|
tdata->thread_index=0;
|
||||||
tdata->root=root;
|
tdata->root=root;
|
||||||
tdata->working_set_size=working_set_size;
|
tdata->working_set_size=working_set_size;
|
||||||
// clock_t tic2 = clock();
|
// clock_t tic2 = clock();
|
||||||
for (int i = 0; i < 64000; i++) {
|
for (int i = 0; i < 640000; i++) {
|
||||||
walk(tdata);
|
walk(tdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
tdata = malloc(sizeof(struct thread_start_data));
|
|
||||||
tdata->thread_index=0;
|
|
||||||
tdata->root=root;
|
|
||||||
tdata->working_set_size=working_set_size;
|
|
||||||
// clock_t tic2 = clock();
|
|
||||||
for (int i = 0; i < 64000; i++) {
|
|
||||||
walk(tdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clock_t toc2 = clock();
|
// clock_t toc2 = clock();
|
||||||
// printf("Elapsed build walk: %f seconds\n", (double)(toc2 - tic2) / CLOCKS_PER_SEC);
|
// printf("Elapsed build walk: %f seconds\n", (double)(toc2 - tic2) / CLOCKS_PER_SEC);
|
||||||
// #endif
|
// #endif
|
||||||
@@ -356,8 +348,10 @@ int main(void)
|
|||||||
// printf("-----------------------------------------------");
|
// printf("-----------------------------------------------");
|
||||||
|
|
||||||
|
|
||||||
free(root);
|
free_test(root);
|
||||||
root = NULL;
|
// root = NULL;
|
||||||
|
|
||||||
|
// while(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
16
Tests/isa/CPrograms/Benchmarks/Richards/build.sh
Normal file
16
Tests/isa/CPrograms/Benchmarks/Richards/build.sh
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc_test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../link.ld home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
scp richards.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c memaccess.c'
|
||||||
|
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -nostartfiles -fno-builtin-malloc -mcmodel=medany -T link.ld -o testC start.S richards.c malloc.c malloc_test.c'
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
||||||
|
|
||||||
|
scp home-1:/home/akilan/cheri/output/sdk/bin/testC ../../../
|
||||||
|
|
||||||
|
|
||||||
452
Tests/isa/CPrograms/Benchmarks/Richards/richards.c
Normal file
452
Tests/isa/CPrograms/Benchmarks/Richards/richards.c
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
// clang-format off
|
||||||
|
|
||||||
|
/* C version of the systems programming language benchmark
|
||||||
|
** Author: M. J. Jordan Cambridge Computer Laboratory.
|
||||||
|
**
|
||||||
|
** Modified by: M. Richards, Nov 1996
|
||||||
|
** to be ANSI C and runnable on 64 bit machines + other minor changes
|
||||||
|
** Modified by: M. Richards, 20 Oct 1998
|
||||||
|
** made minor corrections to improve ANSI compliance (suggested
|
||||||
|
** by David Levine)
|
||||||
|
** Modified by: Jeremy Singer, 25 May 2022
|
||||||
|
** adapted to use uintptr_t for compatibility with architectures
|
||||||
|
** that do not have word-sized pointers (e.g. CHERI)
|
||||||
|
** also adapted to use Boehm-Demers-Weiser GC instead of system
|
||||||
|
** malloc, when compiled with -DGC
|
||||||
|
**
|
||||||
|
** Compile with, say
|
||||||
|
**
|
||||||
|
** gcc -o bench bench.c
|
||||||
|
**
|
||||||
|
** or
|
||||||
|
**
|
||||||
|
** gcc -o bench100 -Dbench100 bench.c (for a version that obeys
|
||||||
|
** the main loop 100x more often)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
|
||||||
|
// #include "harness.h"
|
||||||
|
// #include "stddefines.h"
|
||||||
|
|
||||||
|
// #ifdef GC
|
||||||
|
// #include "gc.h"
|
||||||
|
// #define MALLOC GC_MALLOC
|
||||||
|
// #else
|
||||||
|
// #define MALLOC malloc
|
||||||
|
// #endif // GC
|
||||||
|
|
||||||
|
// #define malloc tiny_malloc
|
||||||
|
// #define free tiny_free
|
||||||
|
|
||||||
|
void* tiny_malloc(size_t);
|
||||||
|
void tiny_free(void*);
|
||||||
|
|
||||||
|
#ifdef bench100
|
||||||
|
#define Count 10000*100
|
||||||
|
#define Qpktcountval 2326410
|
||||||
|
#define Holdcountval 930563
|
||||||
|
#else
|
||||||
|
#define Count 10000
|
||||||
|
#define Qpktcountval 23246
|
||||||
|
#define Holdcountval 9297
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#define MAXINT 32767
|
||||||
|
|
||||||
|
#define BUFSIZE 3
|
||||||
|
#define I_IDLE 1
|
||||||
|
#define I_WORK 2
|
||||||
|
#define I_HANDLERA 3
|
||||||
|
#define I_HANDLERB 4
|
||||||
|
#define I_DEVA 5
|
||||||
|
#define I_DEVB 6
|
||||||
|
#define PKTBIT 1
|
||||||
|
#define WAITBIT 2
|
||||||
|
#define HOLDBIT 4
|
||||||
|
#define NOTPKTBIT !1
|
||||||
|
#define NOTWAITBIT !2
|
||||||
|
#define NOTHOLDBIT 0XFFFB
|
||||||
|
|
||||||
|
#define S_RUN 0
|
||||||
|
#define S_RUNPKT 1
|
||||||
|
#define S_WAIT 2
|
||||||
|
#define S_WAITPKT 3
|
||||||
|
#define S_HOLD 4
|
||||||
|
#define S_HOLDPKT 5
|
||||||
|
#define S_HOLDWAIT 6
|
||||||
|
#define S_HOLDWAITPKT 7
|
||||||
|
|
||||||
|
#define K_DEV 1000
|
||||||
|
#define K_WORK 1001
|
||||||
|
|
||||||
|
struct packet
|
||||||
|
{
|
||||||
|
struct packet *p_link;
|
||||||
|
int p_id;
|
||||||
|
int p_kind;
|
||||||
|
int p_a1;
|
||||||
|
char p_a2[BUFSIZE+1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct task
|
||||||
|
{
|
||||||
|
struct task *t_link;
|
||||||
|
int t_id;
|
||||||
|
int t_pri;
|
||||||
|
struct packet *t_wkq;
|
||||||
|
int t_state;
|
||||||
|
struct task *(*t_fn)(struct packet *);
|
||||||
|
uintptr_t t_v1;
|
||||||
|
uintptr_t t_v2;
|
||||||
|
};
|
||||||
|
|
||||||
|
char alphabet[28] = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
struct task *tasktab[11] = {(struct task *)10,0,0,0,0,0,0,0,0,0,0};
|
||||||
|
struct task *tasklist = 0;
|
||||||
|
struct task *tcb;
|
||||||
|
long taskid;
|
||||||
|
uintptr_t v1;
|
||||||
|
uintptr_t v2;
|
||||||
|
int qpktcount = 0;
|
||||||
|
int holdcount = 0;
|
||||||
|
int tracing = 0;
|
||||||
|
int layout = 0;
|
||||||
|
|
||||||
|
void append(struct packet *pkt, struct packet *ptr);
|
||||||
|
|
||||||
|
void createtask(int id,
|
||||||
|
int pri,
|
||||||
|
struct packet *wkq,
|
||||||
|
int state,
|
||||||
|
struct task *(*fn)(struct packet *),
|
||||||
|
uintptr_t v1,
|
||||||
|
uintptr_t v2)
|
||||||
|
{
|
||||||
|
struct task *t = (struct task *)tiny_malloc(sizeof(struct task));
|
||||||
|
|
||||||
|
tasktab[id] = t;
|
||||||
|
t->t_link = tasklist;
|
||||||
|
t->t_id = id;
|
||||||
|
t->t_pri = pri;
|
||||||
|
t->t_wkq = wkq;
|
||||||
|
t->t_state = state;
|
||||||
|
t->t_fn = fn;
|
||||||
|
t->t_v1 = v1;
|
||||||
|
t->t_v2 = v2;
|
||||||
|
tasklist = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct packet *pkt(struct packet *link, int id, int kind)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct packet *p = (struct packet *)tiny_malloc(sizeof(struct packet));
|
||||||
|
|
||||||
|
for (i=0; i<=BUFSIZE; i++)
|
||||||
|
p->p_a2[i] = 0;
|
||||||
|
|
||||||
|
p->p_link = link;
|
||||||
|
p->p_id = id;
|
||||||
|
p->p_kind = kind;
|
||||||
|
p->p_a1 = 0;
|
||||||
|
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void trace(char a)
|
||||||
|
{
|
||||||
|
if ( --layout <= 0 )
|
||||||
|
{
|
||||||
|
// printf("\n");
|
||||||
|
layout = 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("%c", a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void schedule()
|
||||||
|
{
|
||||||
|
while ( tcb != 0 )
|
||||||
|
{
|
||||||
|
struct packet *pkt;
|
||||||
|
struct task *newtcb;
|
||||||
|
|
||||||
|
pkt=0;
|
||||||
|
|
||||||
|
switch ( tcb->t_state )
|
||||||
|
{
|
||||||
|
case S_WAITPKT:
|
||||||
|
pkt = tcb->t_wkq;
|
||||||
|
tcb->t_wkq = pkt->p_link;
|
||||||
|
tcb->t_state = tcb->t_wkq == 0 ? S_RUN : S_RUNPKT;
|
||||||
|
|
||||||
|
case S_RUN:
|
||||||
|
case S_RUNPKT:
|
||||||
|
taskid = tcb->t_id;
|
||||||
|
v1 = tcb->t_v1;
|
||||||
|
v2 = tcb->t_v2;
|
||||||
|
if (tracing) {
|
||||||
|
trace(taskid+'0');
|
||||||
|
}
|
||||||
|
newtcb = (*(tcb->t_fn))(pkt);
|
||||||
|
tcb->t_v1 = v1;
|
||||||
|
tcb->t_v2 = v2;
|
||||||
|
tcb = newtcb;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_WAIT:
|
||||||
|
case S_HOLD:
|
||||||
|
case S_HOLDPKT:
|
||||||
|
case S_HOLDWAIT:
|
||||||
|
case S_HOLDWAITPKT:
|
||||||
|
tcb = tcb->t_link;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *wait_task(void)
|
||||||
|
{
|
||||||
|
tcb->t_state |= WAITBIT;
|
||||||
|
return (tcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *holdself(void)
|
||||||
|
{
|
||||||
|
++holdcount;
|
||||||
|
tcb->t_state |= HOLDBIT;
|
||||||
|
return (tcb->t_link) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *findtcb(int id)
|
||||||
|
{
|
||||||
|
struct task *t = 0;
|
||||||
|
|
||||||
|
if (1<=id && id<=(long)tasktab[0])
|
||||||
|
t = tasktab[id];
|
||||||
|
// if (t==0) printf("\nBad task id %d\n", id);
|
||||||
|
return(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *release(int id)
|
||||||
|
{
|
||||||
|
struct task *t;
|
||||||
|
|
||||||
|
t = findtcb(id);
|
||||||
|
if ( t==0 ) return (0);
|
||||||
|
|
||||||
|
t->t_state &= NOTHOLDBIT;
|
||||||
|
if ( t->t_pri > tcb->t_pri ) return (t);
|
||||||
|
|
||||||
|
return (tcb) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct task *qpkt(struct packet *pkt)
|
||||||
|
{
|
||||||
|
struct task *t;
|
||||||
|
|
||||||
|
t = findtcb(pkt->p_id);
|
||||||
|
if (t==0) return (t);
|
||||||
|
|
||||||
|
qpktcount++;
|
||||||
|
|
||||||
|
pkt->p_link = 0;
|
||||||
|
pkt->p_id = taskid;
|
||||||
|
|
||||||
|
if (t->t_wkq==0)
|
||||||
|
{
|
||||||
|
t->t_wkq = pkt;
|
||||||
|
t->t_state |= PKTBIT;
|
||||||
|
if (t->t_pri > tcb->t_pri) return (t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
append(pkt, (struct packet *)&(t->t_wkq));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *idlefn(struct packet *pkt)
|
||||||
|
{
|
||||||
|
if ( --v2==0 ) return ( holdself() );
|
||||||
|
|
||||||
|
if ( (v1&1) == 0 )
|
||||||
|
{
|
||||||
|
v1 = ( v1>>1) & MAXINT;
|
||||||
|
return ( release(I_DEVA) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v1 = ( (v1>>1) & MAXINT) ^ 0XD008;
|
||||||
|
return ( release(I_DEVB) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *workfn(struct packet *pkt)
|
||||||
|
{
|
||||||
|
if ( pkt==0 ) return ( wait_task() );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
v1 = I_HANDLERA + I_HANDLERB - v1;
|
||||||
|
pkt->p_id = v1;
|
||||||
|
|
||||||
|
pkt->p_a1 = 0;
|
||||||
|
for (i=0; i<=BUFSIZE; i++)
|
||||||
|
{
|
||||||
|
v2++;
|
||||||
|
if ( v2 > 26 ) v2 = 1;
|
||||||
|
(pkt->p_a2)[i] = alphabet[v2];
|
||||||
|
}
|
||||||
|
return ( qpkt(pkt) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *handlerfn(struct packet *pkt)
|
||||||
|
{
|
||||||
|
if ( pkt!=0) {
|
||||||
|
append(pkt, (struct packet *)(pkt->p_kind==K_WORK ? &v1 : &v2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( v1!=0 ) {
|
||||||
|
int count;
|
||||||
|
struct packet *workpkt = (struct packet *)v1;
|
||||||
|
count = workpkt->p_a1;
|
||||||
|
|
||||||
|
if ( count > BUFSIZE ) {
|
||||||
|
v1 = (uintptr_t)(((struct packet *)v1)->p_link);
|
||||||
|
return ( qpkt(workpkt) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( v2!=0 ) {
|
||||||
|
struct packet *devpkt;
|
||||||
|
|
||||||
|
devpkt = (struct packet *)v2;
|
||||||
|
v2 = (uintptr_t)(((struct packet *)v2)->p_link);
|
||||||
|
devpkt->p_a1 = workpkt->p_a2[count];
|
||||||
|
workpkt->p_a1 = count+1;
|
||||||
|
return( qpkt(devpkt) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wait_task();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task *devfn(struct packet *pkt)
|
||||||
|
{
|
||||||
|
if ( pkt==0 )
|
||||||
|
{
|
||||||
|
if ( v1==0 ) return ( wait_task() );
|
||||||
|
pkt = (struct packet *)v1;
|
||||||
|
v1 = 0;
|
||||||
|
return ( qpkt(pkt) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v1 = (uintptr_t)pkt;
|
||||||
|
if (tracing) trace(pkt->p_a1);
|
||||||
|
return ( holdself() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(struct packet *pkt, struct packet *ptr)
|
||||||
|
{
|
||||||
|
pkt->p_link = 0;
|
||||||
|
|
||||||
|
while ( ptr->p_link ) ptr = ptr->p_link;
|
||||||
|
|
||||||
|
ptr->p_link = pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bench() {
|
||||||
|
struct packet *wkq = 0;
|
||||||
|
|
||||||
|
// printf("Bench mark starting\n");
|
||||||
|
|
||||||
|
createtask(I_IDLE, 0, wkq, S_RUN, idlefn, 1, Count);
|
||||||
|
|
||||||
|
wkq = pkt(0, 0, K_WORK);
|
||||||
|
wkq = pkt(wkq, 0, K_WORK);
|
||||||
|
|
||||||
|
createtask(I_WORK, 1000, wkq, S_WAITPKT, workfn, I_HANDLERA, 0);
|
||||||
|
|
||||||
|
wkq = pkt(0, I_DEVA, K_DEV);
|
||||||
|
wkq = pkt(wkq, I_DEVA, K_DEV);
|
||||||
|
wkq = pkt(wkq, I_DEVA, K_DEV);
|
||||||
|
|
||||||
|
// createtask(I_HANDLERA, 2000, wkq, S_WAITPKT, handlerfn, 0, 0);
|
||||||
|
|
||||||
|
// wkq = pkt(0, I_DEVB, K_DEV);
|
||||||
|
// wkq = pkt(wkq, I_DEVB, K_DEV);
|
||||||
|
// wkq = pkt(wkq, I_DEVB, K_DEV);
|
||||||
|
|
||||||
|
// createtask(I_HANDLERB, 3000, wkq, S_WAITPKT, handlerfn, 0, 0);
|
||||||
|
|
||||||
|
// wkq = 0;
|
||||||
|
// createtask(I_DEVA, 4000, wkq, S_WAIT, devfn, 0, 0);
|
||||||
|
// createtask(I_DEVB, 5000, wkq, S_WAIT, devfn, 0, 0);
|
||||||
|
|
||||||
|
// tcb = tasklist;
|
||||||
|
|
||||||
|
// qpktcount = holdcount = 0;
|
||||||
|
|
||||||
|
// // printf("Starting\n");
|
||||||
|
|
||||||
|
// tracing = FALSE;
|
||||||
|
// layout = 0;
|
||||||
|
|
||||||
|
schedule();
|
||||||
|
|
||||||
|
// printf("\nfinished\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (!(qpktcount == Qpktcountval && holdcount == Holdcountval)) {
|
||||||
|
// printf("qpkt count = %d holdcount = %d\n", qpktcount, holdcount);
|
||||||
|
// printf("These results are incorrect");
|
||||||
|
// exit(1);
|
||||||
|
// }
|
||||||
|
// printf("\nend of run\n");
|
||||||
|
return qpktcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int inner_loop(int inner) {
|
||||||
|
int r = 0;
|
||||||
|
while (inner > 0) {
|
||||||
|
r += bench();
|
||||||
|
inner--;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
//INITREGULARALLOC();
|
||||||
|
int iterations = 1;
|
||||||
|
int warmup = 0;
|
||||||
|
int inner_iterations = 1;
|
||||||
|
|
||||||
|
// parse_argv(argc, argv, &iterations, &warmup, &inner_iterations);
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
while (iterations > 0) {
|
||||||
|
// unsigned long start = microseconds();
|
||||||
|
result += inner_loop(inner_iterations);
|
||||||
|
// unsigned long elapsed = microseconds() - start;
|
||||||
|
// printf("Richards: iterations=1 runtime: %lu%s\n", elapsed, "us");
|
||||||
|
// print(elapsed);
|
||||||
|
iterations--;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
Tests/isa/CPrograms/Benchmarks/barnes/barnes.c
Normal file
77
Tests/isa/CPrograms/Benchmarks/barnes/barnes.c
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/* The Computer Language Benchmarks Game
|
||||||
|
* https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
|
||||||
|
*
|
||||||
|
* Contributed by Mr Ledrug
|
||||||
|
* https://github.com/dstogov/c-benchmarks
|
||||||
|
* spectral-norm
|
||||||
|
* Algorithm lifted from Intel Fortran #2 code by Steve Decker et al.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #include <stdio.h>
|
||||||
|
// #include <math.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void* tiny_malloc(size_t);
|
||||||
|
void tiny_free(void*);
|
||||||
|
|
||||||
|
static inline int A(int i, int j) {
|
||||||
|
return ((i+j) * (i+j+1) / 2 + i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double dot(double * v, double * u, int n) {
|
||||||
|
int i;
|
||||||
|
double sum = 0;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
sum += v[i] * u[i];
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mult_Av(double * v, double * out, int n) {
|
||||||
|
int i, j;
|
||||||
|
double sum;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
for (sum = j = 0; j < n; j++)
|
||||||
|
sum += v[j] / A(i,j);
|
||||||
|
out[i] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mult_Atv(double * v, double * out,int n) {
|
||||||
|
int i, j;
|
||||||
|
double sum;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
for (sum = j = 0; j < n; j++)
|
||||||
|
sum += v[j] / A(j,i);
|
||||||
|
out[i] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double *tmp;
|
||||||
|
void mult_AtAv(double *v, double *out,int n) {
|
||||||
|
//mult_Av(v, tmp, n);
|
||||||
|
mult_Atv(tmp, out, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
int n = 1;
|
||||||
|
// if (n <= 0) n = 2000;
|
||||||
|
|
||||||
|
double *u, *v;
|
||||||
|
u = tiny_malloc(n * sizeof(double));
|
||||||
|
v = tiny_malloc(n * sizeof(double));
|
||||||
|
tmp = tiny_malloc(n * sizeof(double));
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n; i++) u[i] = 1;
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
mult_AtAv(u, v, n);
|
||||||
|
mult_AtAv(v, u, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("%.9f\n", sqrt(dot(u,v, n) / dot(v,v,n)));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
19
Tests/isa/CPrograms/Benchmarks/barnes/build.sh
Normal file
19
Tests/isa/CPrograms/Benchmarks/barnes/build.sh
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# # scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# scp ../../malloc_test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# scp ../../link.ld home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
scp barnes.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# scp barnes_hut.h home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
scp test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c memaccess.c'
|
||||||
|
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -DDEFINE_MALLOC -DDEFINE_FREE -nostdlib -nostartfiles -fno-builtin-malloc --gcc-toolchain=/opt/riscv -mcmodel=medany -T link.ld -o testC start.S barnes.c malloc.c malloc_test.c'
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
||||||
|
|
||||||
|
scp home-1:/home/akilan/cheri/output/sdk/bin/testC ../../../
|
||||||
|
|
||||||
|
|
||||||
BIN
Tests/isa/CPrograms/Benchmarks/barnes/test
Executable file
BIN
Tests/isa/CPrograms/Benchmarks/barnes/test
Executable file
Binary file not shown.
38
Tests/isa/CPrograms/Benchmarks/barnes/test.c
Normal file
38
Tests/isa/CPrograms/Benchmarks/barnes/test.c
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// double PI = 3.141592653589793;
|
||||||
|
|
||||||
|
// double wrap_angle(double x) {
|
||||||
|
// while (x > PI) x -= 2*PI;
|
||||||
|
// while (x < -PI) x += 2*PI;
|
||||||
|
// return x;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double my_sin(double x) {
|
||||||
|
// x = wrap_angle(x);
|
||||||
|
|
||||||
|
// double x2 = x * x;
|
||||||
|
// return x
|
||||||
|
// - (x * x2) / 6
|
||||||
|
// + (x * x2 * x2) / 120
|
||||||
|
// - (x * x2 * x2 * x2) / 5040;
|
||||||
|
// }
|
||||||
|
|
||||||
|
int my_cos(int x) {
|
||||||
|
x *= x;
|
||||||
|
return 1 - x/2 * (1 - x/12 * (1 - x/30 * (1 - x/56 * (1 - x/90))));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
// const double PI = 3.141592653589793;
|
||||||
|
|
||||||
|
int x = my_cos(3);
|
||||||
|
|
||||||
|
// printf("%f\n", cos(3));
|
||||||
|
// printf("%f\n", cos(-3));
|
||||||
|
// printf("%f\n", cos(0));
|
||||||
|
// printf("%f\n", cos(PI));
|
||||||
|
// printf("%f\n", cos(PI / 2.0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
# scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
# scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc_test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../link.ld home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
scp glibc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
scp glibc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c glibc.c'
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c memaccess.c'
|
||||||
|
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -DDEFINE_MALLOC -DDEFINE_FREE -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -T link.ld -o testC start.S glibc.c malloc.c malloc_test.c'
|
||||||
|
|
||||||
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
||||||
|
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ int main (void)
|
|||||||
// if (argc > 2 || size <= 0)
|
// if (argc > 2 || size <= 0)
|
||||||
// usage (argv[0]);
|
// usage (argv[0]);
|
||||||
|
|
||||||
// bench (size);
|
bench (size);
|
||||||
// bench (2*size);
|
// bench (2*size);
|
||||||
// bench (4*size);
|
// bench (4*size);
|
||||||
// bench (8*size);
|
// bench (8*size);
|
||||||
|
|||||||
16
Tests/isa/CPrograms/Benchmarks/kmeans/build.sh
Normal file
16
Tests/isa/CPrograms/Benchmarks/kmeans/build.sh
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
scp ../../start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
# scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../malloc_test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp ../../link.ld home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
scp kmeans.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S malloc.c memaccess.c'
|
||||||
|
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -DDEFINE_MALLOC -DDEFINE_FREE -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -T link.ld -o testC start.S kmeans.c malloc.c malloc_test.c'
|
||||||
|
|
||||||
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
||||||
|
|
||||||
|
scp home-1:/home/akilan/cheri/output/sdk/bin/testC ../../../
|
||||||
|
|
||||||
|
|
||||||
123
Tests/isa/CPrograms/Benchmarks/kmeans/kmeans.c
Normal file
123
Tests/isa/CPrograms/Benchmarks/kmeans/kmeans.c
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
// #include <cheri_init_globals.h>
|
||||||
|
// #include <cheritypes.h>
|
||||||
|
#include <cheriintrin.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <float.h>
|
||||||
|
// #include <math.h>
|
||||||
|
|
||||||
|
/* --- Simple Bare-Metal CHERI Malloc --- */
|
||||||
|
|
||||||
|
// #define HEAP_SIZE 0x10000
|
||||||
|
// static uint8_t raw_heap[HEAP_SIZE] __attribute__((aligned(16)));
|
||||||
|
// static size_t heap_ptr = 0;
|
||||||
|
|
||||||
|
// void* cheri_malloc(size_t size) {
|
||||||
|
// // Ensure 16-byte alignment for CHERI capability representability
|
||||||
|
// size = (size + 15) & ~15;
|
||||||
|
|
||||||
|
// if (heap_ptr + size > HEAP_SIZE) return NULL;
|
||||||
|
|
||||||
|
// // Get a capability to the heap slice
|
||||||
|
// void *ptr = cheri_get_base(&raw_heap[heap_ptr]);
|
||||||
|
|
||||||
|
// // Set strict bounds on the returned capability
|
||||||
|
// ptr = cheri_set_bounds(ptr, size);
|
||||||
|
|
||||||
|
// heap_ptr += size;
|
||||||
|
// return ptr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void free(void * __capability ptr);
|
||||||
|
void * __capability malloc(size_t size);
|
||||||
|
|
||||||
|
/* --- K-Means Hybrid Structures --- */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x, y;
|
||||||
|
} Point;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x, y;
|
||||||
|
int count;
|
||||||
|
} Centroid;
|
||||||
|
|
||||||
|
float get_distance(Point p, Centroid c) {
|
||||||
|
float dx = p.x - c.x;
|
||||||
|
float dy = p.y - c.y;
|
||||||
|
return (dx * dx) + (dy * dy); // Squared Euclidean
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Main Logic --- */
|
||||||
|
|
||||||
|
void run_kmeans(Point * __capability points, int num_points, int k, int iterations) {
|
||||||
|
// Allocate centroids using our CHERI-bounded malloc
|
||||||
|
Centroid * __capability centroids = (Centroid * __capability)malloc(sizeof(Centroid) * k);
|
||||||
|
int * __capability assignments = (int * __capability)malloc(sizeof(int) * num_points);
|
||||||
|
|
||||||
|
if (!centroids || !assignments) return;
|
||||||
|
|
||||||
|
// Initialize Centroids (Simple sequential pick)
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
centroids[i].x = points[i].x;
|
||||||
|
centroids[i].y = points[i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int iter = 0; iter < iterations; iter++) {
|
||||||
|
// 1. Assignment Step
|
||||||
|
for (int i = 0; i < num_points; i++) {
|
||||||
|
float min_dist = FLT_MAX;
|
||||||
|
int best_cluster = 0;
|
||||||
|
for (int j = 0; j < k; j++) {
|
||||||
|
float d = get_distance(points[i], centroids[j]);
|
||||||
|
if (d < min_dist) {
|
||||||
|
min_dist = d;
|
||||||
|
best_cluster = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assignments[i] = best_cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Update Step
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
centroids[i].x = 0;
|
||||||
|
centroids[i].y = 0;
|
||||||
|
centroids[i].count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_points; i++) {
|
||||||
|
int cluster = assignments[i];
|
||||||
|
centroids[cluster].x += points[i].x;
|
||||||
|
centroids[cluster].y += points[i].y;
|
||||||
|
centroids[cluster].count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
if (centroids[i].count > 0) {
|
||||||
|
centroids[i].x /= centroids[i].count;
|
||||||
|
centroids[i].y /= centroids[i].count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int n = 10;
|
||||||
|
int k = 3;
|
||||||
|
|
||||||
|
// Allocate point data on our CHERI heap
|
||||||
|
Point * __capability data = (Point * __capability)malloc(sizeof(Point) * n);
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
// Mock data initialization
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
data[i].x = (float)(i % 10);
|
||||||
|
data[i].y = (float)(i / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
run_kmeans(data, n, k, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
# Send assembler file to remote machine to run
|
# Send assembler file to remote machine to run
|
||||||
scp start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
scp start.S home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
scp main.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp malloc_test.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
scp malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
scp malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
scp link.ld home-1:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
# scp cheri.S home:/home/akilan/cheri/output/sdk/bin/
|
# scp cheri.S home:/home/akilan/cheri/output/sdk/bin/
|
||||||
|
|
||||||
@@ -13,10 +15,10 @@ scp malloc.c home-1:/home/akilan/cheri/output/sdk/bin/
|
|||||||
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -Wl,-Ttext=0x80000000 -o testC start.S main.c'
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -Wl,-Ttext=0x80000000 -o testC start.S main.c'
|
||||||
|
|
||||||
# Malloc test implementation
|
# Malloc test implementation
|
||||||
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -Wl,-Ttext=0x80000000 -o testC start.S main.c malloc.c'
|
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-elf -march=rv64gcxcheri -mabi=lp64d -DDEFINE_MALLOC -DDEFINE_FREE -nostdlib -nostartfiles -fno-builtin-malloc -mcmodel=medany -T link.ld -o testC start.S main.c malloc.c malloc_test.c'
|
||||||
|
|
||||||
# Disassembly ouput
|
# Disassembly ouput
|
||||||
ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
# ssh home-1 'cd /home/akilan/cheri/output/sdk/bin/ && ./llvm-objdump -d testC'
|
||||||
|
|
||||||
# Copy file back for testing
|
# Copy file back for testing
|
||||||
scp home-1:/home/akilan/cheri/output/sdk/bin/testC ../
|
scp home-1:/home/akilan/cheri/output/sdk/bin/testC ../
|
||||||
|
|||||||
19
Tests/isa/CPrograms/link.ld
Normal file
19
Tests/isa/CPrograms/link.ld
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x80000000;
|
||||||
|
.text.init : { *(.text.init) }
|
||||||
|
. = ALIGN(0x1000);
|
||||||
|
.tohost : { *(.tohost) }
|
||||||
|
. = ALIGN(0x1000);
|
||||||
|
.text : { *(.text) }
|
||||||
|
. = ALIGN(0x1000);
|
||||||
|
.data : { *(.data) }
|
||||||
|
.bss : { *(.bss) }
|
||||||
|
_end = .;
|
||||||
|
|
||||||
|
__malloc_start = .;
|
||||||
|
. = . + 0x10000;
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "riscv_test.h"
|
#include "riscv_test.h"
|
||||||
|
|
||||||
|
// void free(void *ptr);
|
||||||
|
// void *malloc(size_t size);
|
||||||
void free(void * __capability ptr);
|
void free(void * __capability ptr);
|
||||||
void * __capability malloc(size_t size);
|
void * __capability malloc(size_t size);
|
||||||
|
|
||||||
@@ -61,35 +63,37 @@ void test() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
char * __capability a = malloc(30);
|
int * __capability a = malloc(30);
|
||||||
char * __capability b = malloc(16);
|
char * __capability b = malloc(16);
|
||||||
|
|
||||||
|
|
||||||
// if (!a || !b) return -1;
|
// if (!a || !b) return -1;
|
||||||
|
|
||||||
a[0] = 'A';
|
a[0] = 1;
|
||||||
a[1] = 'C';
|
a[1] = 'C';
|
||||||
b[0] = 'B';
|
b[0] = 'B';
|
||||||
|
b[10] = 'D';
|
||||||
|
|
||||||
|
|
||||||
// This will fault (out-of-bounds)
|
// This will fault (out-of-bounds)
|
||||||
// a[20] = 'X';
|
// a[20] = 'X';
|
||||||
|
|
||||||
if (a[1] != 'C') {
|
if (a[0] != 1) {
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b[0] != 'B') {
|
if (b[10] != 'D') {
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(&b);
|
free(a);
|
||||||
b = NULL;
|
// b = NULL;
|
||||||
|
|
||||||
if (b[0] == 'B') {
|
// if (b[0] == 'B') {
|
||||||
while (1);
|
// while (1);
|
||||||
}
|
// }
|
||||||
|
|
||||||
char * __capability c = malloc(16);
|
// char * __capability c = malloc(16);
|
||||||
|
|
||||||
// if (c[0] != 'B') {
|
// if (c[0] != 'B') {
|
||||||
// while (1);
|
// while (1);
|
||||||
|
|||||||
@@ -13,20 +13,42 @@
|
|||||||
// | | (Distance 1 between address)
|
// | | (Distance 1 between address)
|
||||||
// [1, 2, 3. ....... n] -> virtual
|
// [1, 2, 3. ....... n] -> virtual
|
||||||
|
|
||||||
#define HEAP_SIZE 65536 // 64 KB heap
|
void* tiny_malloc(size_t);
|
||||||
|
void tiny_free(void*);
|
||||||
|
|
||||||
#define PHYS_BASE 0x80000000
|
#define ALIGN 16
|
||||||
#define VIRT_BASE 0xFFFFFFFF80000000
|
|
||||||
|
|
||||||
static char heap[HEAP_SIZE];
|
// #define HEAP_SIZE 65536 // 64 KB heap
|
||||||
static size_t bump = 0;
|
|
||||||
|
|
||||||
static void * __capability free_list = NULL;
|
// #define PHYS_BASE 0x80000000
|
||||||
|
// #define VIRT_BASE 0xFFFFFFFF80000000
|
||||||
|
|
||||||
typedef struct free_node {
|
// static char heap[HEAP_SIZE];
|
||||||
void * __capability next;
|
// static size_t bump = 0;
|
||||||
} free_node_t;
|
|
||||||
|
|
||||||
|
// static void * __capability free_list = NULL;
|
||||||
|
|
||||||
|
// typedef struct free_node {
|
||||||
|
// void * __capability next;
|
||||||
|
// } free_node_t;
|
||||||
|
|
||||||
|
static uintptr_t next_virtual = 0x10000000;
|
||||||
|
|
||||||
|
uintptr_t compute_physical_base(size_t size) {
|
||||||
|
// 1. Determine the required alignment for this size in CHERI
|
||||||
|
size_t mask = cheri_representable_alignment_mask(size);
|
||||||
|
|
||||||
|
// 2. Round up the current next_virtual to the required alignment
|
||||||
|
uintptr_t base = (next_virtual + ~mask) & mask;
|
||||||
|
|
||||||
|
// 3. Ensure the length itself is representable
|
||||||
|
size_t representable_len = cheri_representable_length(size);
|
||||||
|
|
||||||
|
// 4. Update the global pointer for the next call
|
||||||
|
next_virtual = base + representable_len;
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add delta value for TLB translation
|
// Add delta value for TLB translation
|
||||||
@@ -45,53 +67,91 @@ static inline void * __capability add_delta(void * __capability cap, int offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Malloc wrapper
|
||||||
|
// Malloc wrapper
|
||||||
|
// void * __capability malloc(size_t size) {
|
||||||
|
|
||||||
|
// uintptr_t raw = (uintptr_t)tiny_malloc(size);
|
||||||
|
|
||||||
|
// // void *__capability cap = (void *__capability)raw;
|
||||||
|
// void *__capability cap = cheri_ddc_get();
|
||||||
|
|
||||||
|
// // // Set address from raw pointer
|
||||||
|
// cap = cheri_address_set(cap, raw);
|
||||||
|
|
||||||
|
// int delta = 12;
|
||||||
|
|
||||||
|
// delta = (delta + ALIGN - 1) & ~(ALIGN - 1);
|
||||||
|
|
||||||
|
// cap = add_delta(cap, delta);
|
||||||
|
|
||||||
|
// size_t aligned = cheri_representable_length(size);
|
||||||
|
|
||||||
|
// cap = cheri_bounds_set(cap, aligned);
|
||||||
|
|
||||||
|
// // // Align to 8 bytes (important for capability safety)
|
||||||
|
// // size = (size + 7) & ~7;
|
||||||
|
|
||||||
|
// // if (bump + size > HEAP_SIZE)
|
||||||
|
// // return NULL;
|
||||||
|
|
||||||
|
// // void * __capability base = cheri_ddc_get();
|
||||||
|
|
||||||
|
// // uintptr_t addr = (uintptr_t)(heap + bump);
|
||||||
|
|
||||||
|
// // // Create capability to this region
|
||||||
|
// // void * __capability cap = cheri_address_set(base, addr);
|
||||||
|
|
||||||
|
// // // Enforce bounds (this is the key CHERI feature)
|
||||||
|
// // cap = cheri_bounds_set(cap, size);
|
||||||
|
|
||||||
|
// // // Hard-coded delta value
|
||||||
|
// // cap = add_delta(cap, 10);
|
||||||
|
|
||||||
|
// // bump += size;
|
||||||
|
|
||||||
|
// return cap;
|
||||||
|
// }
|
||||||
|
|
||||||
void * __capability malloc(size_t size) {
|
void * __capability malloc(size_t size) {
|
||||||
|
void * phys_ptr = tiny_malloc(size);
|
||||||
|
if (!phys_ptr) return NULL;
|
||||||
|
|
||||||
// Align to 8 bytes (important for capability safety)
|
uintptr_t raw_phys = (uintptr_t)phys_ptr;
|
||||||
size = (size + 7) & ~7;
|
intptr_t p_base = compute_physical_base(size);
|
||||||
|
intptr_t delta = p_base - (intptr_t)raw_phys;
|
||||||
|
|
||||||
if (bump + size > HEAP_SIZE)
|
void * __capability cap = cheri_ddc_get();
|
||||||
return NULL;
|
cap = cheri_address_set(cap, raw_phys);
|
||||||
|
|
||||||
void * __capability base = cheri_ddc_get();
|
cap = add_delta(cap, (int)delta);
|
||||||
|
|
||||||
uintptr_t addr = (uintptr_t)(heap + bump);
|
size_t aligned_size = cheri_representable_length(size);
|
||||||
|
cap = cheri_bounds_set(cap, aligned_size);
|
||||||
// Create capability to this region
|
|
||||||
void * __capability cap = cheri_address_set(base, addr);
|
|
||||||
|
|
||||||
// Enforce bounds (this is the key CHERI feature)
|
|
||||||
cap = cheri_bounds_set(cap, size);
|
|
||||||
|
|
||||||
// Hard-coded delta value
|
|
||||||
cap = add_delta(cap, 10);
|
|
||||||
|
|
||||||
bump += size;
|
|
||||||
|
|
||||||
return cap;
|
return cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bump_reset(void) {
|
// void bump_reset(void) {
|
||||||
bump = 0;
|
// bump = 0;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Can only free if it's in a stack
|
// Free wrapper
|
||||||
// Need to write a free †hat can work
|
|
||||||
// in any sequence
|
|
||||||
// In regular malloc the freelist
|
|
||||||
// is maintained from mmap.
|
|
||||||
void free(void * __capability ptr) {
|
void free(void * __capability ptr) {
|
||||||
if (!ptr) return;
|
// if (!ptr) return;
|
||||||
|
|
||||||
uintptr_t addr = cheri_address_get(ptr);
|
// uintptr_t addr = cheri_address_get(ptr);
|
||||||
size_t size = cheri_length_get(ptr);
|
// size_t size = cheri_length_get(ptr);
|
||||||
|
|
||||||
// Check if this is the most recent allocation
|
// // Check if this is the most recent allocation
|
||||||
if ((char *)addr + size == heap + bump) {
|
// if ((char *)addr + size == heap + bump) {
|
||||||
bump -= size;
|
// bump -= size;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// *ptr = NULL;
|
// Extract raw address from capability
|
||||||
|
void *raw = (void *)cheri_address_get(ptr);
|
||||||
|
|
||||||
|
tiny_free(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick tests
|
// Quick tests
|
||||||
|
|||||||
97
Tests/isa/CPrograms/malloc_simulation.c
Normal file
97
Tests/isa/CPrograms/malloc_simulation.c
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define HEAP_SIZE 0x10000
|
||||||
|
|
||||||
|
extern uint8_t __malloc_start;
|
||||||
|
|
||||||
|
static uint8_t* heap = &__malloc_start;
|
||||||
|
|
||||||
|
typedef struct block {
|
||||||
|
size_t size;
|
||||||
|
int free;
|
||||||
|
struct block* next;
|
||||||
|
} block;
|
||||||
|
|
||||||
|
static block* free_list;
|
||||||
|
|
||||||
|
static intptr_t next_virtual = 0x10000000;
|
||||||
|
|
||||||
|
intptr_t compute_virtual_base() {
|
||||||
|
intptr_t v = next_virtual;
|
||||||
|
next_virtual += 0x1000; // or size
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_init() {
|
||||||
|
free_list = (block*)heap;
|
||||||
|
|
||||||
|
free_list->size = HEAP_SIZE - sizeof(block);
|
||||||
|
free_list->free = 1;
|
||||||
|
free_list->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* my_malloc(size_t size) {
|
||||||
|
block* curr = free_list;
|
||||||
|
|
||||||
|
while (curr) {
|
||||||
|
if (curr->free && curr->size >= size) {
|
||||||
|
|
||||||
|
if (curr->size > size + sizeof(block)) {
|
||||||
|
block* newb =
|
||||||
|
(block*)((uint8_t*)curr + sizeof(block) + size);
|
||||||
|
|
||||||
|
newb->size = curr->size - size - sizeof(block);
|
||||||
|
newb->free = 1;
|
||||||
|
newb->next = curr->next;
|
||||||
|
|
||||||
|
curr->next = newb;
|
||||||
|
curr->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr->free = 0;
|
||||||
|
|
||||||
|
// TODO: lift off delta to a earlier stage
|
||||||
|
|
||||||
|
void* phys = (uint8_t*)curr + sizeof(block);
|
||||||
|
|
||||||
|
// compute delta for this allocation
|
||||||
|
intptr_t delta = compute_virtual_base() - (intptr_t)phys;
|
||||||
|
|
||||||
|
// apply hardware instruction assumption:
|
||||||
|
asm volatile("add_delta %0, %0, %1"
|
||||||
|
: "+r"(phys)
|
||||||
|
: "r"(delta));
|
||||||
|
|
||||||
|
return phys;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void my_free(void* ptr) {
|
||||||
|
if (!ptr) return;
|
||||||
|
|
||||||
|
// delta is guaranteed 0 → treat pointer as physical
|
||||||
|
block* b = (block*)((uint8_t*)ptr - sizeof(block));
|
||||||
|
|
||||||
|
b->free = 1;
|
||||||
|
|
||||||
|
// coalesce adjacent free blocks (pure physical heap logic)
|
||||||
|
block* curr = free_list;
|
||||||
|
|
||||||
|
while (curr && curr->next) {
|
||||||
|
if (curr->free && curr->next->free) {
|
||||||
|
curr->size += sizeof(block) + curr->next->size;
|
||||||
|
curr->next = curr->next->next;
|
||||||
|
} else {
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
601
Tests/isa/CPrograms/malloc_test.c
Normal file
601
Tests/isa/CPrograms/malloc_test.c
Normal file
@@ -0,0 +1,601 @@
|
|||||||
|
// https://github.com/32bitmicro/newlib-nano-1.0/blob/master/newlib/libc/machine/xstormy16/tiny-malloc.c
|
||||||
|
|
||||||
|
/* A replacement malloc with:
|
||||||
|
- Much reduced code size;
|
||||||
|
- Smaller RAM footprint;
|
||||||
|
- The ability to handle downward-growing heaps;
|
||||||
|
but
|
||||||
|
- Slower;
|
||||||
|
- Probably higher memory fragmentation;
|
||||||
|
- Doesn't support threads (but, if it did support threads,
|
||||||
|
it wouldn't need a global lock, only a compare-and-swap instruction);
|
||||||
|
- Assumes the maximum alignment required is the alignment of a pointer;
|
||||||
|
- Assumes that memory is already there and doesn't need to be allocated.
|
||||||
|
|
||||||
|
* Synopsis of public routines
|
||||||
|
|
||||||
|
malloc(size_t n);
|
||||||
|
Return a pointer to a newly allocated chunk of at least n bytes, or null
|
||||||
|
if no space is available.
|
||||||
|
free(void* p);
|
||||||
|
Release the chunk of memory pointed to by p, or no effect if p is null.
|
||||||
|
realloc(void* p, size_t n);
|
||||||
|
Return a pointer to a chunk of size n that contains the same data
|
||||||
|
as does chunk p up to the minimum of (n, p's size) bytes, or null
|
||||||
|
if no space is available. The returned pointer may or may not be
|
||||||
|
the same as p. If p is null, equivalent to malloc. Unless the
|
||||||
|
#define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
|
||||||
|
size argument of zero (re)allocates a minimum-sized chunk.
|
||||||
|
memalign(size_t alignment, size_t n);
|
||||||
|
Return a pointer to a newly allocated chunk of n bytes, aligned
|
||||||
|
in accord with the alignment argument, which must be a power of
|
||||||
|
two. Will fail if 'alignment' is too large.
|
||||||
|
calloc(size_t unit, size_t quantity);
|
||||||
|
Returns a pointer to quantity * unit bytes, with all locations
|
||||||
|
set to zero.
|
||||||
|
cfree(void* p);
|
||||||
|
Equivalent to free(p).
|
||||||
|
malloc_trim(size_t pad);
|
||||||
|
Release all but pad bytes of freed top-most memory back
|
||||||
|
to the system. Return 1 if successful, else 0.
|
||||||
|
malloc_usable_size(void* p);
|
||||||
|
Report the number usable allocated bytes associated with allocated
|
||||||
|
chunk p. This may or may not report more bytes than were requested,
|
||||||
|
due to alignment and minimum size constraints.
|
||||||
|
malloc_stats();
|
||||||
|
Prints brief summary statistics on stderr.
|
||||||
|
mallinfo()
|
||||||
|
Returns (by copy) a struct containing various summary statistics.
|
||||||
|
mallopt(int parameter_number, int parameter_value)
|
||||||
|
Changes one of the tunable parameters described below. Returns
|
||||||
|
1 if successful in changing the parameter, else 0. Actually, returns 0
|
||||||
|
always, as no parameter can be changed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __xstormy16__
|
||||||
|
#define MALLOC_DIRECTION -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MALLOC_DIRECTION
|
||||||
|
#define MALLOC_DIRECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void* tiny_malloc(size_t);
|
||||||
|
void tiny_free(void*);
|
||||||
|
void* realloc(void*, size_t);
|
||||||
|
void* memalign(size_t, size_t);
|
||||||
|
void* valloc(size_t);
|
||||||
|
void* pvalloc(size_t);
|
||||||
|
void* calloc(size_t, size_t);
|
||||||
|
void cfree(void*);
|
||||||
|
int malloc_trim(size_t);
|
||||||
|
size_t malloc_usable_size(void*);
|
||||||
|
void malloc_stats(void);
|
||||||
|
int mallopt(int, int);
|
||||||
|
struct mallinfo mallinfo(void);
|
||||||
|
|
||||||
|
typedef struct freelist_entry {
|
||||||
|
size_t size;
|
||||||
|
struct freelist_entry *next;
|
||||||
|
} *fle;
|
||||||
|
|
||||||
|
extern void * __malloc_end;
|
||||||
|
extern fle __malloc_freelist;
|
||||||
|
|
||||||
|
/* Return the number of bytes that need to be added to X to make it
|
||||||
|
aligned to an ALIGN boundary. ALIGN must be a power of 2. */
|
||||||
|
#define M_ALIGN(x, align) (-(size_t)(x) & ((align) - 1))
|
||||||
|
|
||||||
|
/* Return the number of bytes that need to be subtracted from X to make it
|
||||||
|
aligned to an ALIGN boundary. ALIGN must be a power of 2. */
|
||||||
|
#define M_ALIGN_SUB(x, align) ((size_t)(x) & ((align) - 1))
|
||||||
|
|
||||||
|
extern char *__malloc_start;
|
||||||
|
|
||||||
|
/* This is the minimum gap allowed between __malloc_end and the top of
|
||||||
|
the stack. This is only checked for when __malloc_end is
|
||||||
|
decreased; if instead the stack grows into the heap, silent data
|
||||||
|
corruption will result. */
|
||||||
|
#define MALLOC_MINIMUM_GAP 32
|
||||||
|
|
||||||
|
#ifdef __xstormy16__
|
||||||
|
register void * stack_pointer asm ("r15");
|
||||||
|
#define MALLOC_LIMIT stack_pointer
|
||||||
|
#else
|
||||||
|
#define MALLOC_LIMIT __builtin_frame_address (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MALLOC_DIRECTION < 0
|
||||||
|
#define CAN_ALLOC_P(required) \
|
||||||
|
(((size_t) __malloc_end - (size_t)MALLOC_LIMIT \
|
||||||
|
- MALLOC_MINIMUM_GAP) >= (required))
|
||||||
|
#else
|
||||||
|
#define CAN_ALLOC_P(required) \
|
||||||
|
(((size_t)MALLOC_LIMIT - (size_t) __malloc_end \
|
||||||
|
- MALLOC_MINIMUM_GAP) >= (required))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* real_size is the size we actually have to allocate, allowing for
|
||||||
|
overhead and alignment. */
|
||||||
|
#define REAL_SIZE(sz) \
|
||||||
|
((sz) < sizeof (struct freelist_entry) - sizeof (size_t) \
|
||||||
|
? sizeof (struct freelist_entry) \
|
||||||
|
: sz + sizeof (size_t) + M_ALIGN(sz, sizeof (size_t)))
|
||||||
|
|
||||||
|
#ifdef DEFINE_MALLOC
|
||||||
|
|
||||||
|
void * __malloc_end = &__malloc_start;
|
||||||
|
fle __malloc_freelist;
|
||||||
|
|
||||||
|
void *
|
||||||
|
tiny_malloc (size_t sz)
|
||||||
|
{
|
||||||
|
fle *nextfree;
|
||||||
|
fle block;
|
||||||
|
|
||||||
|
/* real_size is the size we actually have to allocate, allowing for
|
||||||
|
overhead and alignment. */
|
||||||
|
size_t real_size = REAL_SIZE (sz);
|
||||||
|
|
||||||
|
/* Look for the first block on the freelist that is large enough. */
|
||||||
|
for (nextfree = &__malloc_freelist;
|
||||||
|
*nextfree;
|
||||||
|
nextfree = &(*nextfree)->next)
|
||||||
|
{
|
||||||
|
block = *nextfree;
|
||||||
|
|
||||||
|
if (block->size >= real_size)
|
||||||
|
{
|
||||||
|
/* If the block found is just the right size, remove it from
|
||||||
|
the free list. Otherwise, split it. */
|
||||||
|
if (block->size < real_size + sizeof (struct freelist_entry))
|
||||||
|
{
|
||||||
|
*nextfree = block->next;
|
||||||
|
return (void *)&block->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t newsize = block->size - real_size;
|
||||||
|
fle newnext = block->next;
|
||||||
|
*nextfree = (fle)((size_t)block + real_size);
|
||||||
|
(*nextfree)->size = newsize;
|
||||||
|
(*nextfree)->next = newnext;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is the last block on the freelist, and it was too small,
|
||||||
|
enlarge it. */
|
||||||
|
if (! block->next
|
||||||
|
&& __malloc_end == (void *)((size_t)block + block->size))
|
||||||
|
{
|
||||||
|
size_t moresize = real_size - block->size;
|
||||||
|
if (! CAN_ALLOC_P (moresize))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*nextfree = NULL;
|
||||||
|
if (MALLOC_DIRECTION < 0)
|
||||||
|
{
|
||||||
|
block = __malloc_end = (void *)((size_t)block - moresize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__malloc_end = (void *)((size_t)block + real_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No free space at the end of the free list. Allocate new space
|
||||||
|
and use that. */
|
||||||
|
|
||||||
|
if (! CAN_ALLOC_P (real_size))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (MALLOC_DIRECTION > 0)
|
||||||
|
{
|
||||||
|
block = __malloc_end;
|
||||||
|
__malloc_end = (void *)((size_t)__malloc_end + real_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block = __malloc_end = (void *)((size_t)__malloc_end - real_size);
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
block->size = real_size;
|
||||||
|
// TODO: return as bounds
|
||||||
|
return (void *)&block->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_FREE
|
||||||
|
|
||||||
|
void
|
||||||
|
tiny_free (void *block_p)
|
||||||
|
{
|
||||||
|
fle *nextfree;
|
||||||
|
fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next));
|
||||||
|
|
||||||
|
if (block_p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Look on the freelist to see if there's a free block just before
|
||||||
|
or just after this block. */
|
||||||
|
for (nextfree = &__malloc_freelist;
|
||||||
|
*nextfree;
|
||||||
|
nextfree = &(*nextfree)->next)
|
||||||
|
{
|
||||||
|
fle thisblock = *nextfree;
|
||||||
|
if ((size_t)thisblock + thisblock->size == (size_t) block)
|
||||||
|
{
|
||||||
|
thisblock->size += block->size;
|
||||||
|
if (MALLOC_DIRECTION > 0
|
||||||
|
&& thisblock->next
|
||||||
|
&& (size_t) block + block->size == (size_t) thisblock->next)
|
||||||
|
{
|
||||||
|
thisblock->size += thisblock->next->size;
|
||||||
|
thisblock->next = thisblock->next->next;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ((size_t) thisblock == (size_t) block + block->size)
|
||||||
|
{
|
||||||
|
if (MALLOC_DIRECTION < 0
|
||||||
|
&& thisblock->next
|
||||||
|
&& (size_t) block == ((size_t) thisblock->next
|
||||||
|
+ thisblock->next->size))
|
||||||
|
{
|
||||||
|
*nextfree = thisblock->next;
|
||||||
|
thisblock->next->size += block->size + thisblock->size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block->size += thisblock->size;
|
||||||
|
block->next = thisblock->next;
|
||||||
|
*nextfree = block;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ((MALLOC_DIRECTION > 0
|
||||||
|
&& (size_t) thisblock > (size_t) block)
|
||||||
|
|| (MALLOC_DIRECTION < 0
|
||||||
|
&& (size_t) thisblock < (size_t) block))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
block->next = *nextfree;
|
||||||
|
*nextfree = block;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_REALLOC
|
||||||
|
void *
|
||||||
|
realloc (void *block_p, size_t sz)
|
||||||
|
{
|
||||||
|
fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next));
|
||||||
|
size_t real_size = REAL_SIZE (sz);
|
||||||
|
size_t old_real_size;
|
||||||
|
|
||||||
|
if (block_p == NULL)
|
||||||
|
return malloc (sz);
|
||||||
|
|
||||||
|
old_real_size = block->size;
|
||||||
|
|
||||||
|
/* Perhaps we need to allocate more space. */
|
||||||
|
if (old_real_size < real_size)
|
||||||
|
{
|
||||||
|
void *result;
|
||||||
|
size_t old_size = old_real_size - sizeof (size_t);
|
||||||
|
|
||||||
|
/* Need to allocate, copy, and free. */
|
||||||
|
result = malloc (sz);
|
||||||
|
if (result == NULL)
|
||||||
|
return NULL;
|
||||||
|
memcpy (result, block_p, old_size < sz ? old_size : sz);
|
||||||
|
free (block_p);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/* Perhaps we can free some space. */
|
||||||
|
if (old_real_size - real_size >= sizeof (struct freelist_entry))
|
||||||
|
{
|
||||||
|
fle newblock = (fle)((size_t)block + real_size);
|
||||||
|
block->size = real_size;
|
||||||
|
newblock->size = old_real_size - real_size;
|
||||||
|
free (&newblock->next);
|
||||||
|
}
|
||||||
|
return block_p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_CALLOC
|
||||||
|
void *
|
||||||
|
calloc (size_t n, size_t elem_size)
|
||||||
|
{
|
||||||
|
void *result;
|
||||||
|
size_t sz = n * elem_size;
|
||||||
|
result = malloc (sz);
|
||||||
|
if (result != NULL)
|
||||||
|
memset (result, 0, sz);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_CFREE
|
||||||
|
void
|
||||||
|
cfree (void *p)
|
||||||
|
{
|
||||||
|
free (p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_MEMALIGN
|
||||||
|
void *
|
||||||
|
memalign (size_t align, size_t sz)
|
||||||
|
{
|
||||||
|
fle *nextfree;
|
||||||
|
fle block;
|
||||||
|
|
||||||
|
/* real_size is the size we actually have to allocate, allowing for
|
||||||
|
overhead and alignment. */
|
||||||
|
size_t real_size = REAL_SIZE (sz);
|
||||||
|
|
||||||
|
/* Some sanity checking on 'align'. */
|
||||||
|
if ((align & (align - 1)) != 0
|
||||||
|
|| align <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Look for the first block on the freelist that is large enough. */
|
||||||
|
/* One tricky part is this: We want the result to be a valid pointer
|
||||||
|
to free. That means that there has to be room for a size_t
|
||||||
|
before the block. If there's additional space before the block,
|
||||||
|
it should go on the freelist, or it'll be lost---we could add it
|
||||||
|
to the size of the block before it in memory, but finding the
|
||||||
|
previous block is expensive. */
|
||||||
|
for (nextfree = &__malloc_freelist;
|
||||||
|
;
|
||||||
|
nextfree = &(*nextfree)->next)
|
||||||
|
{
|
||||||
|
size_t before_size;
|
||||||
|
size_t old_size;
|
||||||
|
|
||||||
|
/* If we've run out of free blocks, allocate more space. */
|
||||||
|
if (! *nextfree)
|
||||||
|
{
|
||||||
|
old_size = real_size;
|
||||||
|
if (MALLOC_DIRECTION < 0)
|
||||||
|
{
|
||||||
|
old_size += M_ALIGN_SUB (((size_t)__malloc_end
|
||||||
|
- old_size + sizeof (size_t)),
|
||||||
|
align);
|
||||||
|
if (! CAN_ALLOC_P (old_size))
|
||||||
|
return NULL;
|
||||||
|
block = __malloc_end = (void *)((size_t)__malloc_end - old_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block = __malloc_end;
|
||||||
|
old_size += M_ALIGN ((size_t)__malloc_end + sizeof (size_t),
|
||||||
|
align);
|
||||||
|
if (! CAN_ALLOC_P (old_size))
|
||||||
|
return NULL;
|
||||||
|
__malloc_end = (void *)((size_t)__malloc_end + old_size);
|
||||||
|
}
|
||||||
|
*nextfree = block;
|
||||||
|
block->size = old_size;
|
||||||
|
block->next = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block = *nextfree;
|
||||||
|
old_size = block->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
before_size = M_ALIGN (&block->next, align);
|
||||||
|
if (before_size != 0)
|
||||||
|
before_size = sizeof (*block) + M_ALIGN (&(block+1)->next, align);
|
||||||
|
|
||||||
|
/* If this is the last block on the freelist, and it is too small,
|
||||||
|
enlarge it. */
|
||||||
|
if (! block->next
|
||||||
|
&& old_size < real_size + before_size
|
||||||
|
&& __malloc_end == (void *)((size_t)block + block->size))
|
||||||
|
{
|
||||||
|
if (MALLOC_DIRECTION < 0)
|
||||||
|
{
|
||||||
|
size_t moresize = real_size - block->size;
|
||||||
|
moresize += M_ALIGN_SUB ((size_t)&block->next - moresize, align);
|
||||||
|
if (! CAN_ALLOC_P (moresize))
|
||||||
|
return NULL;
|
||||||
|
block = __malloc_end = (void *)((size_t)block - moresize);
|
||||||
|
block->next = NULL;
|
||||||
|
block->size = old_size = old_size + moresize;
|
||||||
|
before_size = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (! CAN_ALLOC_P (before_size + real_size - block->size))
|
||||||
|
return NULL;
|
||||||
|
__malloc_end = (void *)((size_t)block + before_size + real_size);
|
||||||
|
block->size = old_size = before_size + real_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Two out of the four cases below will now be possible; which
|
||||||
|
two depends on MALLOC_DIRECTION. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_size >= real_size + before_size)
|
||||||
|
{
|
||||||
|
/* This block will do. If there needs to be space before it,
|
||||||
|
split the block. */
|
||||||
|
if (before_size != 0)
|
||||||
|
{
|
||||||
|
fle old_block = block;
|
||||||
|
|
||||||
|
old_block->size = before_size;
|
||||||
|
block = (fle)((size_t)block + before_size);
|
||||||
|
|
||||||
|
/* If there's no space after the block, we're now nearly
|
||||||
|
done; just make a note of the size required.
|
||||||
|
Otherwise, we need to create a new free space block. */
|
||||||
|
if (old_size - before_size
|
||||||
|
<= real_size + sizeof (struct freelist_entry))
|
||||||
|
{
|
||||||
|
block->size = old_size - before_size;
|
||||||
|
return (void *)&block->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fle new_block;
|
||||||
|
new_block = (fle)((size_t)block + real_size);
|
||||||
|
new_block->size = old_size - before_size - real_size;
|
||||||
|
if (MALLOC_DIRECTION > 0)
|
||||||
|
{
|
||||||
|
new_block->next = old_block->next;
|
||||||
|
old_block->next = new_block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_block->next = old_block;
|
||||||
|
*nextfree = new_block;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If the block found is just the right size, remove it from
|
||||||
|
the free list. Otherwise, split it. */
|
||||||
|
if (old_size <= real_size + sizeof (struct freelist_entry))
|
||||||
|
{
|
||||||
|
*nextfree = block->next;
|
||||||
|
return (void *)&block->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t newsize = old_size - real_size;
|
||||||
|
fle newnext = block->next;
|
||||||
|
*nextfree = (fle)((size_t)block + real_size);
|
||||||
|
(*nextfree)->size = newsize;
|
||||||
|
(*nextfree)->next = newnext;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
block->size = real_size;
|
||||||
|
return (void *)&block->next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_VALLOC
|
||||||
|
void *
|
||||||
|
valloc (size_t sz)
|
||||||
|
{
|
||||||
|
return memalign (128, sz);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef DEFINE_PVALLOC
|
||||||
|
void *
|
||||||
|
pvalloc (size_t sz)
|
||||||
|
{
|
||||||
|
return memalign (128, sz + M_ALIGN (sz, 128));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_MALLINFO
|
||||||
|
#include "malloc.h"
|
||||||
|
|
||||||
|
struct mallinfo
|
||||||
|
mallinfo (void)
|
||||||
|
{
|
||||||
|
struct mallinfo r;
|
||||||
|
fle fr;
|
||||||
|
size_t free_size;
|
||||||
|
size_t total_size;
|
||||||
|
size_t free_blocks;
|
||||||
|
|
||||||
|
memset (&r, 0, sizeof (r));
|
||||||
|
|
||||||
|
free_size = 0;
|
||||||
|
free_blocks = 0;
|
||||||
|
for (fr = __malloc_freelist; fr; fr = fr->next)
|
||||||
|
{
|
||||||
|
free_size += fr->size;
|
||||||
|
free_blocks++;
|
||||||
|
if (! fr->next)
|
||||||
|
{
|
||||||
|
int atend;
|
||||||
|
if (MALLOC_DIRECTION > 0)
|
||||||
|
atend = (void *)((size_t)fr + fr->size) == __malloc_end;
|
||||||
|
else
|
||||||
|
atend = (void *)fr == __malloc_end;
|
||||||
|
if (atend)
|
||||||
|
r.keepcost = fr->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MALLOC_DIRECTION > 0)
|
||||||
|
total_size = (char *)__malloc_end - (char *)&__malloc_start;
|
||||||
|
else
|
||||||
|
total_size = (char *)&__malloc_start - (char *)__malloc_end;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* Fixme: should walk through all the in-use blocks and see if
|
||||||
|
they're valid. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
r.arena = total_size;
|
||||||
|
r.fordblks = free_size;
|
||||||
|
r.uordblks = total_size - free_size;
|
||||||
|
r.ordblks = free_blocks;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_MALLOC_STATS
|
||||||
|
#include "malloc.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
malloc_stats(void)
|
||||||
|
{
|
||||||
|
struct mallinfo i;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = stderr;
|
||||||
|
i = mallinfo();
|
||||||
|
fprintf (fp, "malloc has reserved %u bytes between %p and %p\n",
|
||||||
|
i.arena, &__malloc_start, __malloc_end);
|
||||||
|
fprintf (fp, "there are %u bytes free in %u chunks\n",
|
||||||
|
i.fordblks, i.ordblks);
|
||||||
|
fprintf (fp, "of which %u bytes are at the end of the reserved space\n",
|
||||||
|
i.keepcost);
|
||||||
|
fprintf (fp, "and %u bytes are in use.\n", i.uordblks);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_MALLOC_USABLE_SIZE
|
||||||
|
size_t
|
||||||
|
malloc_usable_size (void *block_p)
|
||||||
|
{
|
||||||
|
fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next));
|
||||||
|
return block->size - sizeof (size_t);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_MALLOPT
|
||||||
|
int
|
||||||
|
mallopt (int n, int v)
|
||||||
|
{
|
||||||
|
(void)n; (void)v;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
BIN
Tests/isa/testC
BIN
Tests/isa/testC
Binary file not shown.
1
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/.gitignore
vendored
Normal file
1
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.txt
|
||||||
5181
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/Memaccess.txt
Normal file
5181
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/Memaccess.txt
Normal file
File diff suppressed because it is too large
Load Diff
22001
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/glibc.txt
Normal file
22001
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/glibc.txt
Normal file
File diff suppressed because it is too large
Load Diff
5680
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/memaccess
Normal file
5680
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/memaccess
Normal file
File diff suppressed because it is too large
Load Diff
10563
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/regular-c.txt
Normal file
10563
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/regular-c.txt
Normal file
File diff suppressed because it is too large
Load Diff
5795
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/test
Normal file
5795
builds/RV64ACDFIMSUxCHERI_Toooba_bluesim/test
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -60,12 +60,12 @@ import TlbTypes::*;
|
|||||||
import SynthParam::*;
|
import SynthParam::*;
|
||||||
import VerificationPacket::*;
|
import VerificationPacket::*;
|
||||||
import Performance::*;
|
import Performance::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
import GenerateHPMVector::*;
|
import GenerateHPMVector::*;
|
||||||
`endif
|
// `endif
|
||||||
import HasSpecBits::*;
|
import HasSpecBits::*;
|
||||||
import Exec::*;
|
import Exec::*;
|
||||||
import FetchStage::*;
|
import FetchStage::*;
|
||||||
@@ -212,10 +212,10 @@ interface Core;
|
|||||||
interface Vector #(SupSize, Get #(Trace_Data2)) v_to_TV;
|
interface Vector #(SupSize, Get #(Trace_Data2)) v_to_TV;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method Action events_llc(EventsLL events);
|
method Action events_llc(EventsLL events);
|
||||||
method Action events_tgc(EventsTGC events);
|
method Action events_tgc(EventsTGC events);
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
// fixpoint to instantiate modules
|
// fixpoint to instantiate modules
|
||||||
@@ -268,9 +268,9 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
Vector #(SupSize, FIFOF #(Trace_Data2)) v_f_to_TV <- replicateM (mkFIFOF);
|
Vector #(SupSize, FIFOF #(Trace_Data2)) v_f_to_TV <- replicateM (mkFIFOF);
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsCore)) hpm_core_events <- mkDRegOR (2, unpack (0));
|
Array #(Reg #(EventsCore)) hpm_core_events <- mkDRegOR (2, unpack (0));
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
SpecTagManager specTagManager <- mkSpecTagManager;
|
SpecTagManager specTagManager <- mkSpecTagManager;
|
||||||
ReorderBufferSynth rob <- mkReorderBufferSynth;
|
ReorderBufferSynth rob <- mkReorderBufferSynth;
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
Vector#(SupSize, Bag#(BagSz, CapMem, CapMem)) bags;
|
Vector#(SupSize, Bag#(BagSz, CapMem, CapMem)) bags;
|
||||||
for(Integer i = 0; i < valueof(SupSize); i=i+1) begin
|
for(Integer i = 0; i < valueof(SupSize); i=i+1) begin
|
||||||
@@ -309,7 +309,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
returnBags[i] <- mkSmallBag;
|
returnBags[i] <- mkSmallBag;
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// We have two scoreboards: one conservative and other aggressive
|
// We have two scoreboards: one conservative and other aggressive
|
||||||
// - Aggressive sb is checked at rename stage, so inst after rename may be issued early
|
// - Aggressive sb is checked at rename stage, so inst after rename may be issued early
|
||||||
@@ -437,7 +437,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
method Bool pauseExecute = globalSpecUpdate.pendingIncorrectSpec;
|
method Bool pauseExecute = globalSpecUpdate.pendingIncorrectSpec;
|
||||||
method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put;
|
method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put;
|
||||||
method doStats = doStatsReg._read;
|
method doStats = doStatsReg._read;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method Bool checkTarget(CapMem ppc);
|
method Bool checkTarget(CapMem ppc);
|
||||||
Bool ret = False;
|
Bool ret = False;
|
||||||
@@ -454,7 +454,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
return ret;
|
return ret;
|
||||||
endmethod
|
endmethod
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
endinterface);
|
endinterface);
|
||||||
aluExe[i] <- mkAluExePipeline(aluExeInput);
|
aluExe[i] <- mkAluExePipeline(aluExeInput);
|
||||||
// truly call fetch method to train branch predictor
|
// truly call fetch method to train branch predictor
|
||||||
@@ -512,12 +512,12 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
method setRegReadyAggr_forward = writeAggr(forwardWrAggrPort);
|
method setRegReadyAggr_forward = writeAggr(forwardWrAggrPort);
|
||||||
method writeRegFile = writeCons(memWrConsPort);
|
method writeRegFile = writeCons(memWrConsPort);
|
||||||
method doStats = doStatsReg._read;
|
method doStats = doStatsReg._read;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method rob_getPredPC = rob.getOrigPredPC[valueof(AluExeNum)].get; // last getOrigPredPC port
|
method rob_getPredPC = rob.getOrigPredPC[valueof(AluExeNum)].get; // last getOrigPredPC port
|
||||||
method rob_getOrig_Inst = rob.getOrig_Inst[valueof(AluExeNum)].get; // last getOrig_Inst port
|
method rob_getOrig_Inst = rob.getOrig_Inst[valueof(AluExeNum)].get; // last getOrig_Inst port
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
endinterface);
|
endinterface);
|
||||||
let memExe <- mkMemExePipeline(memExeInput);
|
let memExe <- mkMemExePipeline(memExeInput);
|
||||||
|
|
||||||
@@ -580,7 +580,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
|
|
||||||
// performance counters
|
// performance counters
|
||||||
Reg#(Bool) doStats = coreFix.doStatsIfc; // whether data is collected
|
Reg#(Bool) doStats = coreFix.doStatsIfc; // whether data is collected
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// OOO execute stag (in AluExePipeline and MemExePipeline)
|
// OOO execute stag (in AluExePipeline and MemExePipeline)
|
||||||
|
|
||||||
// commit stage (many in CommitStage.bsv)
|
// commit stage (many in CommitStage.bsv)
|
||||||
@@ -608,7 +608,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
|
|
||||||
// FIFO of perf resp
|
// FIFO of perf resp
|
||||||
FIFO#(ProcPerfResp) perfRespQ <- mkFIFO1;
|
FIFO#(ProcPerfResp) perfRespQ <- mkFIFO1;
|
||||||
`endif
|
// `endif
|
||||||
// FIFO of perf req
|
// FIFO of perf req
|
||||||
FIFO#(ProcPerfReq) perfReqQ <- mkFIFO1;
|
FIFO#(ProcPerfReq) perfReqQ <- mkFIFO1;
|
||||||
|
|
||||||
@@ -721,7 +721,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
`endif
|
`endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method Action updateTargets(Vector#(SupSize, Maybe#(CapMem)) targets);
|
method Action updateTargets(Vector#(SupSize, Maybe#(CapMem)) targets);
|
||||||
for(Integer i = 0; i < valueof(SupSize); i=i+1) begin
|
for(Integer i = 0; i < valueof(SupSize); i=i+1) begin
|
||||||
@@ -739,7 +739,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
end
|
end
|
||||||
endmethod
|
endmethod
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef INCLUDE_TANDEM_VERIF
|
`ifdef INCLUDE_TANDEM_VERIF
|
||||||
interface v_to_TV = map (toPut, v_f_to_TV);
|
interface v_to_TV = map (toPut, v_f_to_TV);
|
||||||
@@ -842,7 +842,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
fetchStage.flush_predictors;
|
fetchStage.flush_predictors;
|
||||||
// $display ("%0d: %m.rule flushBrPred", cur_cycle);
|
// $display ("%0d: %m.rule flushBrPred", cur_cycle);
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef SELF_INV_CACHE
|
`ifdef SELF_INV_CACHE
|
||||||
// Use wires to capture flush regs and empty signals. This is ok because
|
// Use wires to capture flush regs and empty signals. This is ok because
|
||||||
@@ -914,7 +914,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
endrule
|
endrule
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// incr cycle count
|
// incr cycle count
|
||||||
(* fire_when_enabled, no_implicit_conditions *)
|
(* fire_when_enabled, no_implicit_conditions *)
|
||||||
rule incCycleCnt(doStats);
|
rule incCycleCnt(doStats);
|
||||||
@@ -1170,9 +1170,9 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
perfRespQ.enq(r);
|
perfRespQ.enq(r);
|
||||||
end
|
end
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// Performance counters
|
// Performance counters
|
||||||
// Each cache and TLB pair uses the same struct (EventsCache), but the cache accesses
|
// Each cache and TLB pair uses the same struct (EventsCache), but the cache accesses
|
||||||
@@ -1220,7 +1220,7 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
rule rl_send_perf_evts;
|
rule rl_send_perf_evts;
|
||||||
csrf.send_performance_events (events);
|
csrf.send_performance_events (events);
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef INCLUDE_GDB_CONTROL
|
`ifdef INCLUDE_GDB_CONTROL
|
||||||
// ================================================================
|
// ================================================================
|
||||||
@@ -1531,18 +1531,18 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
|
|
||||||
interface CoreIndInv coreIndInv;
|
interface CoreIndInv coreIndInv;
|
||||||
method ActionValue#(ProcPerfResp) perfResp;
|
method ActionValue#(ProcPerfResp) perfResp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
let r = perfReqQ.first;
|
// let r = perfReqQ.first;
|
||||||
return ProcPerfResp {
|
// return ProcPerfResp {
|
||||||
loc: r.loc,
|
// loc: r.loc,
|
||||||
pType: r.pType,
|
// pType: r.pType,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method terminate = csrf.terminate;
|
method terminate = csrf.terminate;
|
||||||
@@ -1602,9 +1602,9 @@ module mkCore#(CoreId coreId)(Core);
|
|||||||
interface v_to_TV = map (toGet, v_f_to_TV);
|
interface v_to_TV = map (toGet, v_f_to_TV);
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method events_llc = events_llc_reg._write;
|
method events_llc = events_llc_reg._write;
|
||||||
method events_tgc = events_tgc_reg._write;
|
method events_tgc = events_tgc_reg._write;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -58,10 +58,10 @@ import ISA_Decls_CHERI::*;
|
|||||||
|
|
||||||
import Cur_Cycle :: *;
|
import Cur_Cycle :: *;
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor :: *;
|
import PerformanceMonitor :: *;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// Project imports from Toooba
|
// Project imports from Toooba
|
||||||
@@ -184,10 +184,10 @@ interface CsrFile;
|
|||||||
method Action dcsr_cause_write (Bit #(3) dcsr_cause);
|
method Action dcsr_cause_write (Bit #(3) dcsr_cause);
|
||||||
|
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
(* always_ready, always_enabled *)
|
(* always_ready, always_enabled *)
|
||||||
method Action send_performance_events (Vector #(No_Of_Evts, Bit #(Report_Width)) evts);
|
method Action send_performance_events (Vector #(No_Of_Evts, Bit #(Report_Width)) evts);
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
// Fancy Reg functions
|
// Fancy Reg functions
|
||||||
@@ -242,7 +242,7 @@ function Reg#(t) addWriteSideEffect(Reg#(t) r, Action a);
|
|||||||
endinterface);
|
endinterface);
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
interface PerfCountersVec;
|
interface PerfCountersVec;
|
||||||
interface Vector#(No_Of_Ctrs, Reg#(Data)) counter_vec;
|
interface Vector#(No_Of_Ctrs, Reg#(Data)) counter_vec;
|
||||||
interface Vector#(No_Of_Ctrs, Reg#(Data)) event_vec;
|
interface Vector#(No_Of_Ctrs, Reg#(Data)) event_vec;
|
||||||
@@ -289,7 +289,7 @@ module mkPerfCountersToooba (PerfCountersVec);
|
|||||||
endinterface;
|
endinterface;
|
||||||
method send_performance_events = perf_counters.send_performance_events;
|
method send_performance_events = perf_counters.send_performance_events;
|
||||||
endmodule
|
endmodule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
function Bool has_csr_permission(CSR csr, Bit#(2) prv, Bool write);
|
function Bool has_csr_permission(CSR csr, Bit#(2) prv, Bool write);
|
||||||
Bit#(12) csr_index = pack(csr);
|
Bit#(12) csr_index = pack(csr);
|
||||||
@@ -754,7 +754,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
|||||||
Reg #(Data) rg_dscratch1 <- mkConfigRegU;
|
Reg #(Data) rg_dscratch1 <- mkConfigRegU;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
PerfCountersVec perf_counters <- mkPerfCountersToooba;
|
PerfCountersVec perf_counters <- mkPerfCountersToooba;
|
||||||
|
|
||||||
//Reg #(Bit #(2)) rg_ctr_inhib_lsb <- mkReg (0);
|
//Reg #(Bit #(2)) rg_ctr_inhib_lsb <- mkReg (0);
|
||||||
@@ -762,7 +762,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
|||||||
//Bit #(3) ctr_inhibit_lsb = { rg_ctr_inhib_lsb [1], 0, rg_ctr_inhib_lsb [0] };
|
//Bit #(3) ctr_inhibit_lsb = { rg_ctr_inhib_lsb [1], 0, rg_ctr_inhib_lsb [0] };
|
||||||
//Word ctr_inhibit = zeroExtend ({ perf_counters.read_ctr_inhibit, ctr_inhibit_lsb });
|
//Word ctr_inhibit = zeroExtend ({ perf_counters.read_ctr_inhibit, ctr_inhibit_lsb });
|
||||||
//CSR_Addr no_of_ctrs = fromInteger (valueOf (No_Of_Ctrs));
|
//CSR_Addr no_of_ctrs = fromInteger (valueOf (No_Of_Ctrs));
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef SECURITY
|
`ifdef SECURITY
|
||||||
// sanctum machine CSRs
|
// sanctum machine CSRs
|
||||||
@@ -832,25 +832,25 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
|||||||
Reg#(CapReg) mScratchC_reg <- mkCsrReg(nullCap);
|
Reg#(CapReg) mScratchC_reg <- mkCsrReg(nullCap);
|
||||||
Ehr#(2, CapReg) mepcc_reg <- mkConfigEhr(defaultValue);
|
Ehr#(2, CapReg) mepcc_reg <- mkConfigEhr(defaultValue);
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
// Performance monitoring
|
// Performance monitoring
|
||||||
Reg#(Bit#(1)) mcountinhibit_cy_reg <- mkCsrReg(0);
|
Reg#(Bit#(1)) mcountinhibit_cy_reg <- mkCsrReg(0);
|
||||||
Reg#(Bit#(1)) mcountinhibit_ir_reg <- mkCsrReg(0);
|
Reg#(Bit#(1)) mcountinhibit_ir_reg <- mkCsrReg(0);
|
||||||
Reg#(Data) mcountinhibit_reg = concatReg5(readOnlyReg(32'h00000000), perf_counters.inhibit, mcountinhibit_ir_reg, readOnlyReg(1'b0), mcountinhibit_cy_reg);
|
Reg#(Data) mcountinhibit_reg = concatReg5(readOnlyReg(32'h00000000), perf_counters.inhibit, mcountinhibit_ir_reg, readOnlyReg(1'b0), mcountinhibit_cy_reg);
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
rule incCycle;
|
rule incCycle;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
if(!unpack(mcountinhibit_cy_reg)) mcycle_ehr[1] <= mcycle_ehr[1] + 1;
|
if(!unpack(mcountinhibit_cy_reg)) mcycle_ehr[1] <= mcycle_ehr[1] + 1;
|
||||||
`else
|
// `else
|
||||||
mcycle_ehr[1] <= mcycle_ehr[1] + 1;
|
// mcycle_ehr[1] <= mcycle_ehr[1] + 1;
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// Function for getting a csr given an index
|
// Function for getting a csr given an index
|
||||||
function Reg#(Data) get_csr(CSR csr);
|
function Reg#(Data) get_csr(CSR csr);
|
||||||
Reg#(Data) ret = readOnlyReg(64'b0);
|
Reg#(Data) ret = readOnlyReg(64'b0);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
let c = csr.addr;
|
let c = csr.addr;
|
||||||
if ((csrAddrMHPMCOUNTER3.addr <= c) && (c <= csrAddrMHPMCOUNTER31.addr))
|
if ((csrAddrMHPMCOUNTER3.addr <= c) && (c <= csrAddrMHPMCOUNTER31.addr))
|
||||||
ret = perf_counters.counter_vec[c-csrAddrMHPMCOUNTER3.addr];
|
ret = perf_counters.counter_vec[c-csrAddrMHPMCOUNTER3.addr];
|
||||||
@@ -858,7 +858,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
|||||||
ret = perf_counters.event_vec[c - csrAddrMHPMEVENT3.addr];
|
ret = perf_counters.event_vec[c - csrAddrMHPMEVENT3.addr];
|
||||||
if ((csrAddrHPMCOUNTER3.addr <= c) && (c <= csrAddrHPMCOUNTER31.addr))
|
if ((csrAddrHPMCOUNTER3.addr <= c) && (c <= csrAddrHPMCOUNTER31.addr))
|
||||||
ret = perf_counters.counter_vec[c-csrAddrHPMCOUNTER3.addr];
|
ret = perf_counters.counter_vec[c-csrAddrHPMCOUNTER3.addr];
|
||||||
`endif
|
// `endif
|
||||||
return (case (csr)
|
return (case (csr)
|
||||||
// User CSRs
|
// User CSRs
|
||||||
csrAddrFFLAGS: fflags_csr;
|
csrAddrFFLAGS: fflags_csr;
|
||||||
@@ -901,10 +901,10 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
|||||||
csrAddrMIMPID: mimpid_csr;
|
csrAddrMIMPID: mimpid_csr;
|
||||||
csrAddrMHARTID: mhartid_csr;
|
csrAddrMHARTID: mhartid_csr;
|
||||||
csrAddrMCCSR: mccsr_csr;
|
csrAddrMCCSR: mccsr_csr;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
//csrAddrMCOUNTERINHIBIT: perf_counters.inhibit;
|
//csrAddrMCOUNTERINHIBIT: perf_counters.inhibit;
|
||||||
csrAddrMCOUNTERINHIBIT: mcountinhibit_reg;
|
csrAddrMCOUNTERINHIBIT: mcountinhibit_reg;
|
||||||
`endif
|
// `endif
|
||||||
`ifdef SECURITY
|
`ifdef SECURITY
|
||||||
csrAddrMEVBASE: mevbase_csr;
|
csrAddrMEVBASE: mevbase_csr;
|
||||||
csrAddrMEVMASK: mevmask_csr;
|
csrAddrMEVMASK: mevmask_csr;
|
||||||
@@ -1396,11 +1396,11 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
|||||||
};
|
};
|
||||||
|
|
||||||
method Action incInstret(SupCnt x);
|
method Action incInstret(SupCnt x);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
if(!unpack(mcountinhibit_ir_reg)) minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x);
|
if(!unpack(mcountinhibit_ir_reg)) minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x);
|
||||||
`else
|
// `else
|
||||||
minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x);
|
// minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x);
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Action setTime(Data t);
|
method Action setTime(Data t);
|
||||||
@@ -1473,7 +1473,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
|||||||
|
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method send_performance_events = perf_counters.send_performance_events;
|
method send_performance_events = perf_counters.send_performance_events;
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ import MMIOAddrs::*;
|
|||||||
import MMIOCore::*;
|
import MMIOCore::*;
|
||||||
import DramCommon::*;
|
import DramCommon::*;
|
||||||
import Performance::*;
|
import Performance::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// ----------------
|
// ----------------
|
||||||
// From Tooba
|
// From Tooba
|
||||||
@@ -180,7 +180,7 @@ module mkProc (Proc_IFC);
|
|||||||
statReqs.deq;
|
statReqs.deq;
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Reg#(EventsTGC) events_tgc_reg <- mkRegU;
|
Reg#(EventsTGC) events_tgc_reg <- mkRegU;
|
||||||
rule broadcastPerfEvents;
|
rule broadcastPerfEvents;
|
||||||
for(Integer j = 0; j < valueof(CoreNum); j = j+1) begin
|
for(Integer j = 0; j < valueof(CoreNum); j = j+1) begin
|
||||||
@@ -188,7 +188,7 @@ module mkProc (Proc_IFC);
|
|||||||
core[j].events_tgc(events_tgc_reg);
|
core[j].events_tgc(events_tgc_reg);
|
||||||
end
|
end
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// Stub out deadlock and renameDebug interfaces
|
// Stub out deadlock and renameDebug interfaces
|
||||||
@@ -361,9 +361,9 @@ module mkProc (Proc_IFC);
|
|||||||
interface v_to_TV = core [0].v_to_TV;
|
interface v_to_TV = core [0].v_to_TV;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method events_tgc = events_tgc_reg._write;
|
method events_tgc = events_tgc_reg._write;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
endmodule: mkProc
|
endmodule: mkProc
|
||||||
|
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ import Fabric_Defs :: *;
|
|||||||
import SoC_Map :: *;
|
import SoC_Map :: *;
|
||||||
import CCTypes :: *;
|
import CCTypes :: *;
|
||||||
import ProcTypes :: *;
|
import ProcTypes :: *;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef INCLUDE_GDB_CONTROL
|
`ifdef INCLUDE_GDB_CONTROL
|
||||||
import DM_CPU_Req_Rsp :: *;
|
import DM_CPU_Req_Rsp :: *;
|
||||||
@@ -140,9 +140,9 @@ interface Proc_IFC;
|
|||||||
interface Vector #(SupSize, Get #(Trace_Data2)) v_to_TV;
|
interface Vector #(SupSize, Get #(Trace_Data2)) v_to_TV;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method Action events_tgc(EventsTGC events);
|
method Action events_tgc(EventsTGC events);
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
|
|||||||
@@ -78,9 +78,9 @@ import CacheCore :: *;
|
|||||||
// ----------------
|
// ----------------
|
||||||
// From RISCY-ooo
|
// From RISCY-ooo
|
||||||
import ProcTypes :: *;
|
import ProcTypes :: *;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// ----------------
|
// ----------------
|
||||||
// From Toooba
|
// From Toooba
|
||||||
@@ -241,7 +241,7 @@ module mkCoreW_reset #(Reset porReset)
|
|||||||
mkConnection (tagController.master, tag_controller_deburster.slave, reset_by all_harts_reset);
|
mkConnection (tagController.master, tag_controller_deburster.slave, reset_by all_harts_reset);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
rule report_tagController_events;
|
rule report_tagController_events;
|
||||||
EventsCacheCore cache_core_evts = tagController.events;
|
EventsCacheCore cache_core_evts = tagController.events;
|
||||||
EventsTGC evts = unpack(0);
|
EventsTGC evts = unpack(0);
|
||||||
@@ -256,7 +256,7 @@ module mkCoreW_reset #(Reset porReset)
|
|||||||
`endif
|
`endif
|
||||||
proc.events_tgc(evts);
|
proc.events_tgc(evts);
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// PLIC (Platform-Level Interrupt Controller)
|
// PLIC (Platform-Level Interrupt Controller)
|
||||||
PLIC_IFC_16_CoreNumX2_7 plic <- mkPLIC_16_CoreNumX2_7 (reset_by all_harts_reset);
|
PLIC_IFC_16_CoreNumX2_7 plic <- mkPLIC_16_CoreNumX2_7 (reset_by all_harts_reset);
|
||||||
|
|||||||
@@ -60,11 +60,11 @@ import Performance::*;
|
|||||||
import LatencyTimer::*;
|
import LatencyTimer::*;
|
||||||
import RandomReplace::*;
|
import RandomReplace::*;
|
||||||
import Prefetcher::*;
|
import Prefetcher::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
export ICRqStuck(..);
|
export ICRqStuck(..);
|
||||||
export IPRqStuck(..);
|
export IPRqStuck(..);
|
||||||
@@ -105,9 +105,9 @@ interface IBank#(
|
|||||||
// performance
|
// performance
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
method Data getPerfData(L1IPerfType t);
|
method Data getPerfData(L1IPerfType t);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1I events;
|
method EventsL1I events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
module mkIBank#(
|
module mkIBank#(
|
||||||
@@ -199,27 +199,27 @@ module mkIBank#(
|
|||||||
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer;
|
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer;
|
||||||
Count#(Bit#(32)) addedCRqs <- mkCount(0);
|
Count#(Bit#(32)) addedCRqs <- mkCount(0);
|
||||||
Count#(Bit#(32)) removedCRqs <- mkCount(0);
|
Count#(Bit#(32)) removedCRqs <- mkCount(0);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Reg#(Bool) doStats <- mkConfigReg(True);
|
Reg#(Bool) doStats <- mkConfigReg(True);
|
||||||
Count#(Data) ldCnt <- mkCount(0);
|
Count#(Data) ldCnt <- mkCount(0);
|
||||||
Count#(Data) ldMissCnt <- mkCount(0);
|
Count#(Data) ldMissCnt <- mkCount(0);
|
||||||
Count#(Data) ldMissLat <- mkCount(0);
|
Count#(Data) ldMissLat <- mkCount(0);
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsL1I)) perf_events <- mkDRegOR (2, unpack (0));
|
Array #(Reg #(EventsL1I)) perf_events <- mkDRegOR (2, unpack (0));
|
||||||
`endif
|
// `endif
|
||||||
function Action incrReqCnt;
|
function Action incrReqCnt;
|
||||||
action
|
action
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
ldCnt.incr(1);
|
ldCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1I events = unpack (0);
|
EventsL1I events = unpack (0);
|
||||||
events.evt_LD = 1;
|
events.evt_LD = 1;
|
||||||
perf_events[0] <= events;
|
perf_events[0] <= events;
|
||||||
`endif
|
// `endif
|
||||||
noAction;
|
noAction;
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
@@ -227,18 +227,18 @@ module mkIBank#(
|
|||||||
function Action incrMissCnt(cRqIdxT idx);
|
function Action incrMissCnt(cRqIdxT idx);
|
||||||
action
|
action
|
||||||
let lat <- latTimer.done(idx);
|
let lat <- latTimer.done(idx);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
ldMissLat.incr(zeroExtend(lat));
|
ldMissLat.incr(zeroExtend(lat));
|
||||||
ldMissCnt.incr(1);
|
ldMissCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1I events = unpack (0);
|
EventsL1I events = unpack (0);
|
||||||
events.evt_LD_MISS_LAT = saturating_truncate(lat);
|
events.evt_LD_MISS_LAT = saturating_truncate(lat);
|
||||||
events.evt_LD_MISS = 1;
|
events.evt_LD_MISS = 1;
|
||||||
perf_events[1] <= events;
|
perf_events[1] <= events;
|
||||||
`endif
|
// `endif
|
||||||
noAction;
|
noAction;
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
@@ -906,26 +906,26 @@ module mkIBank#(
|
|||||||
`endif
|
`endif
|
||||||
|
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Data getPerfData(L1IPerfType t);
|
method Data getPerfData(L1IPerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
L1ILdCnt: ldCnt;
|
L1ILdCnt: ldCnt;
|
||||||
L1ILdMissCnt: ldMissCnt;
|
L1ILdMissCnt: ldMissCnt;
|
||||||
L1ILdMissLat: ldMissLat;
|
L1ILdMissLat: ldMissLat;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1I events = perf_events[0];
|
method EventsL1I events = perf_events[0];
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -63,11 +63,11 @@ import Performance::*;
|
|||||||
import LatencyTimer::*;
|
import LatencyTimer::*;
|
||||||
import RandomReplace::*;
|
import RandomReplace::*;
|
||||||
import Prefetcher::*;
|
import Prefetcher::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
export L1CRqStuck(..);
|
export L1CRqStuck(..);
|
||||||
export L1PRqStuck(..);
|
export L1PRqStuck(..);
|
||||||
@@ -111,9 +111,9 @@ interface L1Bank#(
|
|||||||
// performance
|
// performance
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
method Data getPerfData(L1DPerfType t);
|
method Data getPerfData(L1DPerfType t);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1D events;
|
method EventsL1D events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -207,7 +207,7 @@ module mkL1Bank#(
|
|||||||
|
|
||||||
// performance
|
// performance
|
||||||
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
|
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
Count#(Data) ldCnt <- mkCount(0);
|
Count#(Data) ldCnt <- mkCount(0);
|
||||||
Count#(Data) stCnt <- mkCount(0);
|
Count#(Data) stCnt <- mkCount(0);
|
||||||
@@ -218,13 +218,13 @@ module mkL1Bank#(
|
|||||||
Count#(Data) ldMissLat <- mkCount(0);
|
Count#(Data) ldMissLat <- mkCount(0);
|
||||||
Count#(Data) stMissLat <- mkCount(0);
|
Count#(Data) stMissLat <- mkCount(0);
|
||||||
Count#(Data) amoMissLat <- mkCount(0);
|
Count#(Data) amoMissLat <- mkCount(0);
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsL1D)) perf_events <- mkDRegOR (2, unpack (0));
|
Array #(Reg #(EventsL1D)) perf_events <- mkDRegOR (2, unpack (0));
|
||||||
`endif
|
// `endif
|
||||||
function Action incrReqCnt(MemOp op);
|
function Action incrReqCnt(MemOp op);
|
||||||
action
|
action
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
case(op)
|
case(op)
|
||||||
Ld: ldCnt.incr(1);
|
Ld: ldCnt.incr(1);
|
||||||
@@ -232,8 +232,8 @@ action
|
|||||||
Lr, Sc, Amo: amoCnt.incr(1);
|
Lr, Sc, Amo: amoCnt.incr(1);
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1D events = unpack (0);
|
EventsL1D events = unpack (0);
|
||||||
case(op)
|
case(op)
|
||||||
Ld: events.evt_LD = 1;
|
Ld: events.evt_LD = 1;
|
||||||
@@ -241,7 +241,7 @@ action
|
|||||||
Lr, Sc, Amo: events.evt_AMO = 1;
|
Lr, Sc, Amo: events.evt_AMO = 1;
|
||||||
endcase
|
endcase
|
||||||
perf_events[0] <= events;
|
perf_events[0] <= events;
|
||||||
`endif
|
// `endif
|
||||||
noAction;
|
noAction;
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
@@ -249,7 +249,7 @@ endfunction
|
|||||||
function Action incrMissCnt(MemOp op, cRqIdxT idx);
|
function Action incrMissCnt(MemOp op, cRqIdxT idx);
|
||||||
action
|
action
|
||||||
let lat <- latTimer.done(idx);
|
let lat <- latTimer.done(idx);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
case(op)
|
case(op)
|
||||||
Ld: begin
|
Ld: begin
|
||||||
@@ -266,8 +266,8 @@ action
|
|||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1D events = unpack (0);
|
EventsL1D events = unpack (0);
|
||||||
case(op)
|
case(op)
|
||||||
Ld: begin
|
Ld: begin
|
||||||
@@ -284,7 +284,7 @@ action
|
|||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
perf_events[1] <= events;
|
perf_events[1] <= events;
|
||||||
`endif
|
// `endif
|
||||||
noAction;
|
noAction;
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
@@ -1233,16 +1233,16 @@ endfunction
|
|||||||
`endif
|
`endif
|
||||||
|
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Data getPerfData(L1DPerfType t);
|
method Data getPerfData(L1DPerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
L1DLdCnt: ldCnt;
|
L1DLdCnt: ldCnt;
|
||||||
L1DStCnt: stCnt;
|
L1DStCnt: stCnt;
|
||||||
L1DAmoCnt: amoCnt;
|
L1DAmoCnt: amoCnt;
|
||||||
@@ -1252,13 +1252,13 @@ endfunction
|
|||||||
L1DLdMissLat: ldMissLat;
|
L1DLdMissLat: ldMissLat;
|
||||||
L1DStMissLat: stMissLat;
|
L1DStMissLat: stMissLat;
|
||||||
L1DAmoMissLat: amoMissLat;
|
L1DAmoMissLat: amoMissLat;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1D events = perf_events[0];
|
method EventsL1D events = perf_events[0];
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
@@ -1495,7 +1495,7 @@ module mkL1Cache#(
|
|||||||
end
|
end
|
||||||
return fold(\+ , d);
|
return fold(\+ , d);
|
||||||
endmethod
|
endmethod
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1D events;
|
method EventsL1D events;
|
||||||
EventsL1D ret = unpack(0);
|
EventsL1D ret = unpack(0);
|
||||||
for(Integer i = 0; i < valueof(bankNum); i = i+1) begin
|
for(Integer i = 0; i < valueof(bankNum); i = i+1) begin
|
||||||
@@ -1503,5 +1503,5 @@ module mkL1Cache#(
|
|||||||
end
|
end
|
||||||
return ret;
|
return ret;
|
||||||
endmethod
|
endmethod
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ import ConfigReg::*;
|
|||||||
import RandomReplace::*;
|
import RandomReplace::*;
|
||||||
import Prefetcher::*;
|
import Prefetcher::*;
|
||||||
import ProcTypes::*;
|
import ProcTypes::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
export LLCRqStuck(..);
|
export LLCRqStuck(..);
|
||||||
export LLBank(..);
|
export LLBank(..);
|
||||||
@@ -111,9 +111,9 @@ interface LLBank#(
|
|||||||
// performance
|
// performance
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
method Data getPerfData(LLCPerfType t);
|
method Data getPerfData(LLCPerfType t);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsLL events;
|
method EventsLL events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -241,7 +241,7 @@ module mkLLBank#(
|
|||||||
PrefetcherVector#(TDiv#(childNum, 2)) dataPrefetchers <- mkPrefetcherVector(mkLLDPrefetcher);
|
PrefetcherVector#(TDiv#(childNum, 2)) dataPrefetchers <- mkPrefetcherVector(mkLLDPrefetcher);
|
||||||
PrefetcherVector#(TDiv#(childNum, 2)) instrPrefetchers <- mkPrefetcherVector(mkLLIPrefetcher);
|
PrefetcherVector#(TDiv#(childNum, 2)) instrPrefetchers <- mkPrefetcherVector(mkLLIPrefetcher);
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Reg#(Bool) doStats <- mkConfigReg(True);
|
Reg#(Bool) doStats <- mkConfigReg(True);
|
||||||
Count#(Data) dmaMemLdCnt <- mkCount(0);
|
Count#(Data) dmaMemLdCnt <- mkCount(0);
|
||||||
Count#(Data) dmaMemLdLat <- mkCount(0);
|
Count#(Data) dmaMemLdLat <- mkCount(0);
|
||||||
@@ -257,14 +257,14 @@ module mkLLBank#(
|
|||||||
Count#(Data) upRespDataCnt <- mkCount(0);
|
Count#(Data) upRespDataCnt <- mkCount(0);
|
||||||
Count#(Data) dmaLdReqCnt <- mkCount(0);
|
Count#(Data) dmaLdReqCnt <- mkCount(0);
|
||||||
Count#(Data) dmaStReqCnt <- mkCount(0);
|
Count#(Data) dmaStReqCnt <- mkCount(0);
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsLL)) perf_events <- mkDRegOR (2, unpack (0));
|
Array #(Reg #(EventsLL)) perf_events <- mkDRegOR (2, unpack (0));
|
||||||
`endif
|
// `endif
|
||||||
function Action incrMissCnt(cRqIndexT idx, Bool isDma, Bool isInstructionAccess);
|
function Action incrMissCnt(cRqIndexT idx, Bool isDma, Bool isInstructionAccess);
|
||||||
action
|
action
|
||||||
let lat <- latTimer.done(idx);
|
let lat <- latTimer.done(idx);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(isDma) begin
|
if(isDma) begin
|
||||||
dmaMemLdCnt.incr(1);
|
dmaMemLdCnt.incr(1);
|
||||||
@@ -279,13 +279,13 @@ action
|
|||||||
normalMemLdLat.incr(zeroExtend(lat));
|
normalMemLdLat.incr(zeroExtend(lat));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsLL events = unpack (0);
|
EventsLL events = unpack (0);
|
||||||
events.evt_LD_MISS_LAT = saturating_truncate(lat); // Don't support seperate DMA counts.
|
events.evt_LD_MISS_LAT = saturating_truncate(lat); // Don't support seperate DMA counts.
|
||||||
events.evt_LD_MISS = 1;
|
events.evt_LD_MISS = 1;
|
||||||
perf_events[1] <= events;
|
perf_events[1] <= events;
|
||||||
`endif
|
// `endif
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ endfunction
|
|||||||
);
|
);
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf stats: insert new cRq fails because of full MSHR
|
// perf stats: insert new cRq fails because of full MSHR
|
||||||
rule cRqTransfer_new_child_block(
|
rule cRqTransfer_new_child_block(
|
||||||
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Child) && doStats
|
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Child) && doStats
|
||||||
@@ -504,7 +504,7 @@ endfunction
|
|||||||
mshrBlocks.incr(1);
|
mshrBlocks.incr(1);
|
||||||
end
|
end
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// insert new cRq from DMA to MSHR and send to pipeline
|
// insert new cRq from DMA to MSHR and send to pipeline
|
||||||
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
|
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
|
||||||
@@ -536,7 +536,7 @@ endfunction
|
|||||||
fshow(r), " ; ",
|
fshow(r), " ; ",
|
||||||
fshow(cRq)
|
fshow(cRq)
|
||||||
);
|
);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(write) begin
|
if(write) begin
|
||||||
dmaStReqCnt.incr(1);
|
dmaStReqCnt.incr(1);
|
||||||
@@ -545,10 +545,10 @@ endfunction
|
|||||||
dmaLdReqCnt.incr(1);
|
dmaLdReqCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf stats: insert new cRq fails because of full MSHR
|
// perf stats: insert new cRq fails because of full MSHR
|
||||||
rule cRqTransfer_new_dma_block(
|
rule cRqTransfer_new_dma_block(
|
||||||
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma) && doStats
|
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma) && doStats
|
||||||
@@ -568,7 +568,7 @@ endfunction
|
|||||||
mshrBlocks.incr(1);
|
mshrBlocks.incr(1);
|
||||||
end
|
end
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// send downgrade resp from child to pipeline
|
// send downgrade resp from child to pipeline
|
||||||
rule cRsTransfer;
|
rule cRsTransfer;
|
||||||
@@ -577,14 +577,14 @@ endfunction
|
|||||||
pipeline.send(CRs (cRs));
|
pipeline.send(CRs (cRs));
|
||||||
if (verbose)
|
if (verbose)
|
||||||
$display("%t LL %m cRsTransfer: ", $time, fshow(cRs));
|
$display("%t LL %m cRsTransfer: ", $time, fshow(cRs));
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
downRespCnt.incr(1);
|
downRespCnt.incr(1);
|
||||||
if(isValid(cRs.data)) begin
|
if(isValid(cRs.data)) begin
|
||||||
downRespDataCnt.incr(1);
|
downRespDataCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule discardPrefetchRqResult(rsToCIndexQ.notEmpty && cRqIsPrefetch[rsToCIndexQ.first.cRqId]);
|
rule discardPrefetchRqResult(rsToCIndexQ.notEmpty && cRqIsPrefetch[rsToCIndexQ.first.cRqId]);
|
||||||
@@ -596,14 +596,14 @@ endfunction
|
|||||||
|
|
||||||
// mem resp for child req, will refill cache, send it to pipeline
|
// mem resp for child req, will refill cache, send it to pipeline
|
||||||
(* descending_urgency = "mRsTransfer, cRsTransfer, discardPrefetchRqResult, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma, createInstrPrefetchRq, createDataPrefetchRq" *)
|
(* descending_urgency = "mRsTransfer, cRsTransfer, discardPrefetchRqResult, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma, createInstrPrefetchRq, createDataPrefetchRq" *)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// stop mshr block stats when other higher priority req is being sent to
|
// stop mshr block stats when other higher priority req is being sent to
|
||||||
// pipeline
|
// pipeline
|
||||||
(* preempts = "mRsTransfer, cRqTransfer_new_child_block" *)
|
(* preempts = "mRsTransfer, cRqTransfer_new_child_block" *)
|
||||||
(* preempts = "mRsTransfer, cRqTransfer_new_dma_block" *)
|
(* preempts = "mRsTransfer, cRqTransfer_new_dma_block" *)
|
||||||
(* preempts = "cRsTransfer, cRqTransfer_new_child_block" *)
|
(* preempts = "cRsTransfer, cRqTransfer_new_child_block" *)
|
||||||
(* preempts = "cRsTransfer, cRqTransfer_new_dma_block" *)
|
(* preempts = "cRsTransfer, cRqTransfer_new_dma_block" *)
|
||||||
`endif
|
// `endif
|
||||||
rule mRsTransfer(rsFromMQ.first.id.refill);
|
rule mRsTransfer(rsFromMQ.first.id.refill);
|
||||||
// get mem resp cRq index & data
|
// get mem resp cRq index & data
|
||||||
rsFromMQ.deq;
|
rsFromMQ.deq;
|
||||||
@@ -742,11 +742,11 @@ endfunction
|
|||||||
toMQ.enq(msg);
|
toMQ.enq(msg);
|
||||||
// don't deq info, do ld next time
|
// don't deq info, do ld next time
|
||||||
doLdAfterReplace <= True;
|
doLdAfterReplace <= True;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsLL events = unpack (0);
|
EventsLL events = unpack (0);
|
||||||
events.evt_ST_MISS = 1;
|
events.evt_ST_MISS = 1;
|
||||||
perf_events[0] <= events;
|
perf_events[0] <= events;
|
||||||
`endif
|
// `endif
|
||||||
if (verbose)
|
if (verbose)
|
||||||
$display("%t LL %m sendToM: rep then ld: rep: ", $time, fshow(msg));
|
$display("%t LL %m sendToM: rep then ld: rep: ", $time, fshow(msg));
|
||||||
end
|
end
|
||||||
@@ -832,14 +832,14 @@ endfunction
|
|||||||
}));
|
}));
|
||||||
// release MSHR entry
|
// release MSHR entry
|
||||||
cRqMshr.sendRsToDmaC.releaseEntry(n);
|
cRqMshr.sendRsToDmaC.releaseEntry(n);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
upRespCnt.incr(1);
|
upRespCnt.incr(1);
|
||||||
if(isValid(rsData)) begin
|
if(isValid(rsData)) begin
|
||||||
upRespDataCnt.incr(1);
|
upRespDataCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// send downgrade req to child
|
// send downgrade req to child
|
||||||
@@ -930,11 +930,11 @@ endfunction
|
|||||||
);
|
);
|
||||||
// change round-robin
|
// change round-robin
|
||||||
whichCRq <= whichCRq == fromInteger(valueOf(cRqNum) - 1) ? 0 : whichCRq + 1;
|
whichCRq <= whichCRq == fromInteger(valueOf(cRqNum) - 1) ? 0 : whichCRq + 1;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
downReqCnt.incr(1);
|
downReqCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// Final stage of pipeline: process all kinds of msg
|
// Final stage of pipeline: process all kinds of msg
|
||||||
@@ -1657,16 +1657,16 @@ endfunction
|
|||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Data getPerfData(LLCPerfType t);
|
method Data getPerfData(LLCPerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
LLCDmaMemLdCnt: dmaMemLdCnt;
|
LLCDmaMemLdCnt: dmaMemLdCnt;
|
||||||
LLCDmaMemLdLat: dmaMemLdLat;
|
LLCDmaMemLdLat: dmaMemLdLat;
|
||||||
LLCNormalMemLdCnt: normalMemLdCnt;
|
LLCNormalMemLdCnt: normalMemLdCnt;
|
||||||
@@ -1681,13 +1681,13 @@ endfunction
|
|||||||
LLCUpRespDataCnt: upRespDataCnt;
|
LLCUpRespDataCnt: upRespDataCnt;
|
||||||
LLCDmaLdReqCnt: dmaLdReqCnt;
|
LLCDmaLdReqCnt: dmaLdReqCnt;
|
||||||
LLCDmaStReqCnt: dmaStReqCnt;
|
LLCDmaStReqCnt: dmaStReqCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsLL events = perf_events[0];
|
method EventsLL events = perf_events[0];
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// Scheduling notes
|
// Scheduling notes
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ module mkSelfInvIBank#(
|
|||||||
Fifo#(1, DebugICacheResp) cRqDoneQ <- mkBypassFifo;
|
Fifo#(1, DebugICacheResp) cRqDoneQ <- mkBypassFifo;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
Count#(Data) ldCnt <- mkCount(0);
|
Count#(Data) ldCnt <- mkCount(0);
|
||||||
Count#(Data) ldMissCnt <- mkCount(0);
|
Count#(Data) ldMissCnt <- mkCount(0);
|
||||||
@@ -186,7 +186,7 @@ module mkSelfInvIBank#(
|
|||||||
end
|
end
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
function tagT getTag(Addr a) = truncateLSB(a);
|
function tagT getTag(Addr a) = truncateLSB(a);
|
||||||
|
|
||||||
@@ -210,10 +210,10 @@ module mkSelfInvIBank#(
|
|||||||
}));
|
}));
|
||||||
// enq to indexQ for in order resp
|
// enq to indexQ for in order resp
|
||||||
cRqIndexQ.enq(n);
|
cRqIndexQ.enq(n);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: cRq type
|
// performance counter: cRq type
|
||||||
incrReqCnt;
|
incrReqCnt;
|
||||||
`endif
|
// `endif
|
||||||
if (verbose)
|
if (verbose)
|
||||||
$display("%t I %m cRqTransfer: ", $time,
|
$display("%t I %m cRqTransfer: ", $time,
|
||||||
fshow(n), " ; ",
|
fshow(n), " ; ",
|
||||||
@@ -267,10 +267,10 @@ module mkSelfInvIBank#(
|
|||||||
fshow(slot), " ; ",
|
fshow(slot), " ; ",
|
||||||
fshow(cRqToP)
|
fshow(cRqToP)
|
||||||
);
|
);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: start miss timer
|
// performance counter: start miss timer
|
||||||
latTimer.start(n);
|
latTimer.start(n);
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// last stage of pipeline: process req
|
// last stage of pipeline: process req
|
||||||
@@ -475,10 +475,10 @@ module mkSelfInvIBank#(
|
|||||||
"pRs must be a hit"
|
"pRs must be a hit"
|
||||||
);
|
);
|
||||||
cRqHit(cOwner, procRq);
|
cRqHit(cOwner, procRq);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: miss cRq
|
// performance counter: miss cRq
|
||||||
incrMissCnt(cOwner);
|
incrMissCnt(cOwner);
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
doAssert(False, ("pRs owner must match some cRq"));
|
doAssert(False, ("pRs owner must match some cRq"));
|
||||||
@@ -498,11 +498,11 @@ module mkSelfInvIBank#(
|
|||||||
waitReconcileDone <= True;
|
waitReconcileDone <= True;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
$display("%t I %m startReconcile", $time);
|
$display("%t I %m startReconcile", $time);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
reconcileCnt.incr(1);
|
reconcileCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
rule completeReconcile(needReconcile && waitReconcileDone && pipeline.reconcile_done);
|
rule completeReconcile(needReconcile && waitReconcileDone && pipeline.reconcile_done);
|
||||||
needReconcile <= False;
|
needReconcile <= False;
|
||||||
@@ -573,21 +573,21 @@ module mkSelfInvIBank#(
|
|||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Data getPerfData(L1IPerfType t);
|
method Data getPerfData(L1IPerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
L1ILdCnt: ldCnt;
|
L1ILdCnt: ldCnt;
|
||||||
L1ILdMissCnt: ldMissCnt;
|
L1ILdMissCnt: ldMissCnt;
|
||||||
L1ILdMissLat: ldMissLat;
|
L1ILdMissLat: ldMissLat;
|
||||||
L1IReconcileCnt: reconcileCnt;
|
L1IReconcileCnt: reconcileCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ module mkSelfInvL1Bank#(
|
|||||||
Reg#(Bool) waitReconcileDone <- mkReg(False);
|
Reg#(Bool) waitReconcileDone <- mkReg(False);
|
||||||
|
|
||||||
// performance
|
// performance
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
Count#(Data) ldCnt <- mkCount(0);
|
Count#(Data) ldCnt <- mkCount(0);
|
||||||
Count#(Data) stCnt <- mkCount(0);
|
Count#(Data) stCnt <- mkCount(0);
|
||||||
@@ -260,7 +260,7 @@ module mkSelfInvL1Bank#(
|
|||||||
end
|
end
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
function tagT getTag(Addr a) = truncateLSB(a);
|
function tagT getTag(Addr a) = truncateLSB(a);
|
||||||
|
|
||||||
@@ -296,10 +296,10 @@ module mkSelfInvL1Bank#(
|
|||||||
addr: r.addr,
|
addr: r.addr,
|
||||||
mshrIdx: n
|
mshrIdx: n
|
||||||
}));
|
}));
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: cRq type
|
// performance counter: cRq type
|
||||||
incrReqCnt(r.op);
|
incrReqCnt(r.op);
|
||||||
`endif
|
// `endif
|
||||||
if (verbose)
|
if (verbose)
|
||||||
$display("%t L1 %m cRqTransfer_new: ", $time,
|
$display("%t L1 %m cRqTransfer_new: ", $time,
|
||||||
fshow(n), " ; ",
|
fshow(n), " ; ",
|
||||||
@@ -422,10 +422,10 @@ module mkSelfInvL1Bank#(
|
|||||||
fshow(cRqToP)
|
fshow(cRqToP)
|
||||||
);
|
);
|
||||||
doAssert(slot.cs == I, "we always self-inv before req to parent");
|
doAssert(slot.cs == I, "we always self-inv before req to parent");
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: start miss timer
|
// performance counter: start miss timer
|
||||||
latTimer.start(n);
|
latTimer.start(n);
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// last stage of pipeline: process req
|
// last stage of pipeline: process req
|
||||||
@@ -550,11 +550,11 @@ module mkSelfInvL1Bank#(
|
|||||||
);
|
);
|
||||||
// release MSHR entry
|
// release MSHR entry
|
||||||
cRqMshr.pipelineResp.releaseEntry(n);
|
cRqMshr.pipelineResp.releaseEntry(n);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats && needSelfInv) begin
|
if(doStats && needSelfInv) begin
|
||||||
selfInvCnt.incr(1);
|
selfInvCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
processAmo <= Valid (AmoHitInfo {
|
processAmo <= Valid (AmoHitInfo {
|
||||||
@@ -871,10 +871,10 @@ module mkSelfInvL1Bank#(
|
|||||||
("pRs must be a hit")
|
("pRs must be a hit")
|
||||||
);
|
);
|
||||||
cRqHit(cOwner, procRq, True);
|
cRqHit(cOwner, procRq, True);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: miss cRq
|
// performance counter: miss cRq
|
||||||
incrMissCnt(procRq.op, cOwner);
|
incrMissCnt(procRq.op, cOwner);
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
doAssert(False, ("pRs owner must match some cRq"));
|
doAssert(False, ("pRs owner must match some cRq"));
|
||||||
@@ -966,11 +966,11 @@ module mkSelfInvL1Bank#(
|
|||||||
waitReconcileDone <= True;
|
waitReconcileDone <= True;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
$display("%t L1 %m startReconcile", $time);
|
$display("%t L1 %m startReconcile", $time);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
reconcileCnt.incr(1);
|
reconcileCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
rule completeReconcile(needReconcile && waitReconcileDone && pipeline.reconcile_done);
|
rule completeReconcile(needReconcile && waitReconcileDone && pipeline.reconcile_done);
|
||||||
needReconcile <= False;
|
needReconcile <= False;
|
||||||
@@ -1021,16 +1021,16 @@ module mkSelfInvL1Bank#(
|
|||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Data getPerfData(L1DPerfType t);
|
method Data getPerfData(L1DPerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
L1DLdCnt: ldCnt;
|
L1DLdCnt: ldCnt;
|
||||||
L1DStCnt: stCnt;
|
L1DStCnt: stCnt;
|
||||||
L1DAmoCnt: amoCnt;
|
L1DAmoCnt: amoCnt;
|
||||||
@@ -1042,7 +1042,7 @@ module mkSelfInvL1Bank#(
|
|||||||
L1DAmoMissLat: amoMissLat;
|
L1DAmoMissLat: amoMissLat;
|
||||||
L1DSelfInvCnt: selfInvCnt;
|
L1DSelfInvCnt: selfInvCnt;
|
||||||
L1DReconcileCnt: reconcileCnt;
|
L1DReconcileCnt: reconcileCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ module mkSelfInvLLBank#(
|
|||||||
`endif
|
`endif
|
||||||
|
|
||||||
// performance
|
// performance
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
Count#(Data) dmaMemLdCnt <- mkCount(0);
|
Count#(Data) dmaMemLdCnt <- mkCount(0);
|
||||||
Count#(Data) dmaMemLdLat <- mkCount(0);
|
Count#(Data) dmaMemLdLat <- mkCount(0);
|
||||||
@@ -245,7 +245,7 @@ module mkSelfInvLLBank#(
|
|||||||
end
|
end
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
function tagT getTag(Addr a) = truncateLSB(a);
|
function tagT getTag(Addr a) = truncateLSB(a);
|
||||||
|
|
||||||
@@ -373,7 +373,7 @@ module mkSelfInvLLBank#(
|
|||||||
);
|
);
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf stats: insert new cRq fails because of full MSHR
|
// perf stats: insert new cRq fails because of full MSHR
|
||||||
rule cRqTransfer_new_child_block(
|
rule cRqTransfer_new_child_block(
|
||||||
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Child) && doStats
|
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Child) && doStats
|
||||||
@@ -392,7 +392,7 @@ module mkSelfInvLLBank#(
|
|||||||
mshrBlocks.incr(1);
|
mshrBlocks.incr(1);
|
||||||
end
|
end
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// insert new cRq from DMA to MSHR and send to pipeline
|
// insert new cRq from DMA to MSHR and send to pipeline
|
||||||
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
|
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
|
||||||
@@ -422,7 +422,7 @@ module mkSelfInvLLBank#(
|
|||||||
fshow(r), " ; ",
|
fshow(r), " ; ",
|
||||||
fshow(cRq)
|
fshow(cRq)
|
||||||
);
|
);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(write) begin
|
if(write) begin
|
||||||
dmaStReqCnt.incr(1);
|
dmaStReqCnt.incr(1);
|
||||||
@@ -431,10 +431,10 @@ module mkSelfInvLLBank#(
|
|||||||
dmaLdReqCnt.incr(1);
|
dmaLdReqCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf stats: insert new cRq fails because of full MSHR
|
// perf stats: insert new cRq fails because of full MSHR
|
||||||
rule cRqTransfer_new_dma_block(
|
rule cRqTransfer_new_dma_block(
|
||||||
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma) && doStats
|
!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma) && doStats
|
||||||
@@ -454,7 +454,7 @@ module mkSelfInvLLBank#(
|
|||||||
mshrBlocks.incr(1);
|
mshrBlocks.incr(1);
|
||||||
end
|
end
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// send downgrade resp from child to pipeline
|
// send downgrade resp from child to pipeline
|
||||||
rule cRsTransfer;
|
rule cRsTransfer;
|
||||||
@@ -462,26 +462,26 @@ module mkSelfInvLLBank#(
|
|||||||
cRsFromCT cRs = rsFromCQ.first;
|
cRsFromCT cRs = rsFromCQ.first;
|
||||||
pipeline.send(CRs (cRs));
|
pipeline.send(CRs (cRs));
|
||||||
$display("%t LL %m cRsTransfer: ", $time, fshow(cRs));
|
$display("%t LL %m cRsTransfer: ", $time, fshow(cRs));
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
downRespCnt.incr(1);
|
downRespCnt.incr(1);
|
||||||
if(isValid(cRs.data)) begin
|
if(isValid(cRs.data)) begin
|
||||||
downRespDataCnt.incr(1);
|
downRespDataCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// mem resp for child req, will refill cache, send it to pipeline
|
// mem resp for child req, will refill cache, send it to pipeline
|
||||||
(* descending_urgency = "mRsTransfer, cRsTransfer, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma" *)
|
(* descending_urgency = "mRsTransfer, cRsTransfer, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma" *)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// stop mshr block stats when other higher priority req is being sent to
|
// stop mshr block stats when other higher priority req is being sent to
|
||||||
// pipeline
|
// pipeline
|
||||||
(* preempts = "mRsTransfer, cRqTransfer_new_child_block" *)
|
(* preempts = "mRsTransfer, cRqTransfer_new_child_block" *)
|
||||||
(* preempts = "mRsTransfer, cRqTransfer_new_dma_block" *)
|
(* preempts = "mRsTransfer, cRqTransfer_new_dma_block" *)
|
||||||
(* preempts = "cRsTransfer, cRqTransfer_new_child_block" *)
|
(* preempts = "cRsTransfer, cRqTransfer_new_child_block" *)
|
||||||
(* preempts = "cRsTransfer, cRqTransfer_new_dma_block" *)
|
(* preempts = "cRsTransfer, cRqTransfer_new_dma_block" *)
|
||||||
`endif
|
// `endif
|
||||||
rule mRsTransfer(rsFromMQ.first.id.refill);
|
rule mRsTransfer(rsFromMQ.first.id.refill);
|
||||||
// get mem resp cRq index & data
|
// get mem resp cRq index & data
|
||||||
rsFromMQ.deq;
|
rsFromMQ.deq;
|
||||||
@@ -504,10 +504,10 @@ module mkSelfInvLLBank#(
|
|||||||
fshow(cRq), " ; ",
|
fshow(cRq), " ; ",
|
||||||
fshow(cSlot), " ; "
|
fshow(cSlot), " ; "
|
||||||
);
|
);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: normal miss lat and cnt
|
// performance counter: normal miss lat and cnt
|
||||||
incrMissCnt(n, False);
|
incrMissCnt(n, False);
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// this mem resp is just for a DMA req, won't go into pipeline to refill cache
|
// this mem resp is just for a DMA req, won't go into pipeline to refill cache
|
||||||
@@ -518,10 +518,10 @@ module mkSelfInvLLBank#(
|
|||||||
// save data into cRq mshr & send to DMA resp IndexQ
|
// save data into cRq mshr & send to DMA resp IndexQ
|
||||||
cRqMshr.mRsDeq.setData(mRs.id.mshrIdx, Valid (mRs.data));
|
cRqMshr.mRsDeq.setData(mRs.id.mshrIdx, Valid (mRs.data));
|
||||||
rsLdToDmaIndexQ_mRsDeq.enq(mRs.id.mshrIdx);
|
rsLdToDmaIndexQ_mRsDeq.enq(mRs.id.mshrIdx);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: dma miss lat and cnt
|
// performance counter: dma miss lat and cnt
|
||||||
incrMissCnt(mRs.id.mshrIdx, True);
|
incrMissCnt(mRs.id.mshrIdx, True);
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// send rd/wr to mem
|
// send rd/wr to mem
|
||||||
@@ -558,10 +558,10 @@ module mkSelfInvLLBank#(
|
|||||||
$display("%t LL %m sendToM: load only: ", $time, fshow(msg));
|
$display("%t LL %m sendToM: load only: ", $time, fshow(msg));
|
||||||
doAssert(!isValid(data), "cannot have data");
|
doAssert(!isValid(data), "cannot have data");
|
||||||
doAssert(!doLdAfterReplace, "doLdAfterReplace should be false");
|
doAssert(!doLdAfterReplace, "doLdAfterReplace should be false");
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: start miss timer
|
// performance counter: start miss timer
|
||||||
latTimer.start(n);
|
latTimer.start(n);
|
||||||
`endif
|
// `endif
|
||||||
`ifdef DEBUG_DMA
|
`ifdef DEBUG_DMA
|
||||||
if(cRq.id matches tagged Dma .dmaId) begin
|
if(cRq.id matches tagged Dma .dmaId) begin
|
||||||
dmaRdMissQ.enq(dmaId); // DMA read takes effect
|
dmaRdMissQ.enq(dmaId); // DMA read takes effect
|
||||||
@@ -603,10 +603,10 @@ module mkSelfInvLLBank#(
|
|||||||
toMInfoQ.deq;
|
toMInfoQ.deq;
|
||||||
doLdAfterReplace <= False;
|
doLdAfterReplace <= False;
|
||||||
$display("%t LL %m sendToM: rep then ld: ld: ", $time, fshow(msg));
|
$display("%t LL %m sendToM: rep then ld: ld: ", $time, fshow(msg));
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: start miss timer
|
// performance counter: start miss timer
|
||||||
latTimer.start(n);
|
latTimer.start(n);
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin // do write back part
|
else begin // do write back part
|
||||||
toMemT msg = Wb (WbMemRs {
|
toMemT msg = Wb (WbMemRs {
|
||||||
@@ -698,14 +698,14 @@ module mkSelfInvLLBank#(
|
|||||||
}));
|
}));
|
||||||
// release MSHR entry
|
// release MSHR entry
|
||||||
cRqMshr.sendRsToDmaC.releaseEntry(n);
|
cRqMshr.sendRsToDmaC.releaseEntry(n);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
upRespCnt.incr(1);
|
upRespCnt.incr(1);
|
||||||
if(isValid(rsData)) begin
|
if(isValid(rsData)) begin
|
||||||
upRespDataCnt.incr(1);
|
upRespDataCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// send downgrade req to child
|
// send downgrade req to child
|
||||||
@@ -787,11 +787,11 @@ module mkSelfInvLLBank#(
|
|||||||
);
|
);
|
||||||
// change round-robin
|
// change round-robin
|
||||||
whichCRq <= whichCRq == fromInteger(valueOf(cRqNum) - 1) ? 0 : whichCRq + 1;
|
whichCRq <= whichCRq == fromInteger(valueOf(cRqNum) - 1) ? 0 : whichCRq + 1;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
downReqCnt.incr(1);
|
downReqCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// Final stage of pipeline: process all kinds of msg
|
// Final stage of pipeline: process all kinds of msg
|
||||||
@@ -1417,16 +1417,16 @@ module mkSelfInvLLBank#(
|
|||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
method Action setPerfStatus(Bool stats);
|
method Action setPerfStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Data getPerfData(LLCPerfType t);
|
method Data getPerfData(LLCPerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
LLCDmaMemLdCnt: dmaMemLdCnt;
|
LLCDmaMemLdCnt: dmaMemLdCnt;
|
||||||
LLCDmaMemLdLat: dmaMemLdLat;
|
LLCDmaMemLdLat: dmaMemLdLat;
|
||||||
LLCNormalMemLdCnt: normalMemLdCnt;
|
LLCNormalMemLdCnt: normalMemLdCnt;
|
||||||
@@ -1439,7 +1439,7 @@ module mkSelfInvLLBank#(
|
|||||||
LLCUpRespDataCnt: upRespDataCnt;
|
LLCUpRespDataCnt: upRespDataCnt;
|
||||||
LLCDmaLdReqCnt: dmaLdReqCnt;
|
LLCDmaLdReqCnt: dmaLdReqCnt;
|
||||||
LLCDmaStReqCnt: dmaStReqCnt;
|
LLCDmaStReqCnt: dmaStReqCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ import Bypass::*;
|
|||||||
import CHERICap::*;
|
import CHERICap::*;
|
||||||
import CHERICC_Fat::*;
|
import CHERICC_Fat::*;
|
||||||
import ISA_Decls_CHERI::*;
|
import ISA_Decls_CHERI::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
import DReg::*;
|
import DReg::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
|
|
||||||
import Cur_Cycle :: *;
|
import Cur_Cycle :: *;
|
||||||
@@ -220,14 +220,14 @@ interface AluExeInput;
|
|||||||
// performance
|
// performance
|
||||||
method Bool doStats;
|
method Bool doStats;
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
// check previous branch targets
|
// check previous branch targets
|
||||||
method Bool checkTarget(CapMem ppc);
|
method Bool checkTarget(CapMem ppc);
|
||||||
// check (previous) return targets
|
// check (previous) return targets
|
||||||
method Bool checkReturnTarget(CapMem ppc);
|
method Bool checkReturnTarget(CapMem ppc);
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
interface AluExePipeline;
|
interface AluExePipeline;
|
||||||
@@ -237,11 +237,11 @@ interface AluExePipeline;
|
|||||||
interface SpeculationUpdate specUpdate;
|
interface SpeculationUpdate specUpdate;
|
||||||
method Data getPerf(ExeStagePerfType t);
|
method Data getPerf(ExeStagePerfType t);
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method EventsTransExe events;
|
method EventsTransExe events;
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
||||||
@@ -260,18 +260,18 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
Integer exeSendBypassPort = 0;
|
Integer exeSendBypassPort = 0;
|
||||||
Integer finishSendBypassPort = 1;
|
Integer finishSendBypassPort = 1;
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
Array#(Reg#(EventsTransExe)) events_reg <- mkDRegOR(2, unpack(0));
|
Array#(Reg#(EventsTransExe)) events_reg <- mkDRegOR(2, unpack(0));
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counters
|
// performance counters
|
||||||
Count#(Data) exeRedirectBrCnt <- mkCount(0);
|
Count#(Data) exeRedirectBrCnt <- mkCount(0);
|
||||||
Count#(Data) exeRedirectJrCnt <- mkCount(0);
|
Count#(Data) exeRedirectJrCnt <- mkCount(0);
|
||||||
Count#(Data) exeRedirectOtherCnt <- mkCount(0);
|
Count#(Data) exeRedirectOtherCnt <- mkCount(0);
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
rule doDispatchAlu;
|
rule doDispatchAlu;
|
||||||
rsAlu.doDispatch;
|
rsAlu.doDispatch;
|
||||||
@@ -336,7 +336,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
let ppc = inIfc.rob_getPredPC(x.tag);
|
let ppc = inIfc.rob_getPredPC(x.tag);
|
||||||
let orig_inst = inIfc.rob_getOrig_Inst (x.tag);
|
let orig_inst = inIfc.rob_getOrig_Inst (x.tag);
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
let ppc_addr = getAddr(ppc);
|
let ppc_addr = getAddr(ppc);
|
||||||
let pc_addr = getAddr(pc);
|
let pc_addr = getAddr(pc);
|
||||||
@@ -361,7 +361,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef KONATA
|
`ifdef KONATA
|
||||||
$display("KONATAE\t%0d\t%0d\t0\tAlu1", cur_cycle, x.u_id);
|
$display("KONATAE\t%0d\t%0d\t0\tAlu1", cur_cycle, x.u_id);
|
||||||
@@ -511,7 +511,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
$display("KONATAS\t%0d\t%0d\t0\tAlu4\t%0d", cur_cycle, x.u_id, cur_cycle);
|
$display("KONATAS\t%0d\t%0d\t0\tAlu4\t%0d", cur_cycle, x.u_id, cur_cycle);
|
||||||
$fflush;
|
$fflush;
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
// get PC and PPC
|
// get PC and PPC
|
||||||
let pc = getAddr(x.controlFlow.pc);
|
let pc = getAddr(x.controlFlow.pc);
|
||||||
@@ -523,7 +523,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
events_reg[0] <= events;
|
events_reg[0] <= events;
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
let train_spec_bits = 0;
|
let train_spec_bits = 0;
|
||||||
`ifdef NO_SPEC_TRAINING
|
`ifdef NO_SPEC_TRAINING
|
||||||
@@ -554,7 +554,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
$display("alu mispredict pc: %x, nextPc: %x, %d",
|
$display("alu mispredict pc: %x, nextPc: %x, %d",
|
||||||
x.controlFlow.pc, x.controlFlow.nextPc, cur_cycle);
|
x.controlFlow.pc, x.controlFlow.nextPc, cur_cycle);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter
|
// performance counter
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
case(x.iType)
|
case(x.iType)
|
||||||
@@ -563,7 +563,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
default: exeRedirectOtherCnt.incr(1);
|
default: exeRedirectOtherCnt.incr(1);
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else (* nosplit *) begin
|
else (* nosplit *) begin
|
||||||
// release spec tag
|
// release spec tag
|
||||||
@@ -603,19 +603,19 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
|
|||||||
|
|
||||||
method Data getPerf(ExeStagePerfType t);
|
method Data getPerf(ExeStagePerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
ExeRedirectBr: exeRedirectBrCnt;
|
ExeRedirectBr: exeRedirectBrCnt;
|
||||||
ExeRedirectJr: exeRedirectJrCnt;
|
ExeRedirectJr: exeRedirectJrCnt;
|
||||||
ExeRedirectOther: exeRedirectOtherCnt;
|
ExeRedirectOther: exeRedirectOtherCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method events = events_reg[0];
|
method events = events_reg[0];
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -66,9 +66,9 @@ import CHERICap::*;
|
|||||||
import CHERICC_Fat::*;
|
import CHERICC_Fat::*;
|
||||||
import ISA_Decls_CHERI::*;
|
import ISA_Decls_CHERI::*;
|
||||||
import RegFile::*; // Just for the interface
|
import RegFile::*; // Just for the interface
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef RVFI
|
`ifdef RVFI
|
||||||
import RVFI_DII_Types::*;
|
import RVFI_DII_Types::*;
|
||||||
@@ -151,14 +151,14 @@ interface CommitInput;
|
|||||||
// deadlock check
|
// deadlock check
|
||||||
method Bool checkDeadlock;
|
method Bool checkDeadlock;
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
// update branch targets
|
// update branch targets
|
||||||
method Action updateTargets(Vector#(SupSize, Maybe#(CapMem)) targets);
|
method Action updateTargets(Vector#(SupSize, Maybe#(CapMem)) targets);
|
||||||
// update return targets
|
// update return targets
|
||||||
method Action updateReturnTargets(Vector#(SupSize, Maybe#(CapMem)) returnTargets);
|
method Action updateReturnTargets(Vector#(SupSize, Maybe#(CapMem)) returnTargets);
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef INCLUDE_TANDEM_VERIF
|
`ifdef INCLUDE_TANDEM_VERIF
|
||||||
interface Vector #(SupSize, Put #(Trace_Data2)) v_to_TV;
|
interface Vector #(SupSize, Put #(Trace_Data2)) v_to_TV;
|
||||||
@@ -197,9 +197,9 @@ interface CommitStage;
|
|||||||
method Bool is_debug_halted;
|
method Bool is_debug_halted;
|
||||||
method Action debug_resume;
|
method Action debug_resume;
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsCore events;
|
method EventsCore events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
// we apply actions the end of commit rule
|
// we apply actions the end of commit rule
|
||||||
@@ -422,7 +422,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
end
|
end
|
||||||
|
|
||||||
// commit stage performance counters
|
// commit stage performance counters
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// inst
|
// inst
|
||||||
Count#(Data) instCnt <- mkCount(0);
|
Count#(Data) instCnt <- mkCount(0);
|
||||||
Count#(Data) userInstCnt <- mkCount(0);
|
Count#(Data) userInstCnt <- mkCount(0);
|
||||||
@@ -451,11 +451,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
Count#(Data) flushSecurityCnt <- mkCount(0);
|
Count#(Data) flushSecurityCnt <- mkCount(0);
|
||||||
Count#(Data) flushBPCnt <- mkCount(0);
|
Count#(Data) flushBPCnt <- mkCount(0);
|
||||||
Count#(Data) flushCacheCnt <- mkCount(0);
|
Count#(Data) flushCacheCnt <- mkCount(0);
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Reg#(EventsCore) events_reg <- mkDReg(unpack(0));
|
Reg#(EventsCore) events_reg <- mkDReg(unpack(0));
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef RVFI
|
`ifdef RVFI
|
||||||
// RVFI trace report. Not an input?
|
// RVFI trace report. Not an input?
|
||||||
@@ -568,11 +568,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
if(flushTlb) begin
|
if(flushTlb) begin
|
||||||
`endif
|
`endif
|
||||||
inIfc.setFlushTlbs;
|
inIfc.setFlushTlbs;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
flushTlbCnt.incr(1);
|
flushTlbCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
// notify TLB to keep update of CSR changes
|
// notify TLB to keep update of CSR changes
|
||||||
inIfc.setUpdateVMInfo;
|
inIfc.setUpdateVMInfo;
|
||||||
@@ -596,28 +596,28 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
// valid because these wrong path inst/req will not interfere with
|
// valid because these wrong path inst/req will not interfere with
|
||||||
// whatever CSR changes we are making now.
|
// whatever CSR changes we are making now.
|
||||||
if(flushSecurity) begin
|
if(flushSecurity) begin
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
flushSecurityCnt.incr(1);
|
flushSecurityCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifndef DISABLE_SECURE_FLUSH_BP
|
`ifndef DISABLE_SECURE_FLUSH_BP
|
||||||
inIfc.setFlushBrPred;
|
inIfc.setFlushBrPred;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
flushBPCnt.incr(1);
|
flushBPCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifndef DISABLE_SECURE_FLUSH_CACHE
|
`ifndef DISABLE_SECURE_FLUSH_CACHE
|
||||||
inIfc.setFlushCaches;
|
inIfc.setFlushCaches;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
flushCacheCnt.incr(1);
|
flushCacheCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`endif
|
`endif
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -734,7 +734,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
// faulting mem inst may have claimed phy reg, we should not commit it;
|
// faulting mem inst may have claimed phy reg, we should not commit it;
|
||||||
// instead, we kill the renaming by calling killAll
|
// instead, we kill the renaming by calling killAll
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter
|
// performance counter
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
if(trap matches tagged Exception .e) begin
|
if(trap matches tagged Exception .e) begin
|
||||||
@@ -744,15 +744,15 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
interruptCnt.incr(1);
|
interruptCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
events.evt_TRAP = 1;
|
events.evt_TRAP = 1;
|
||||||
if(trap matches tagged Interrupt .i) begin
|
if(trap matches tagged Interrupt .i) begin
|
||||||
events.evt_INTERRUPT = 1;
|
events.evt_INTERRUPT = 1;
|
||||||
end
|
end
|
||||||
events_reg <= events;
|
events_reg <= events;
|
||||||
`endif
|
// `endif
|
||||||
// checks
|
// checks
|
||||||
doAssert(x.rob_inst_state == Executed, "must be executed");
|
doAssert(x.rob_inst_state == Executed, "must be executed");
|
||||||
doAssert(x.spec_bits == 0, "cannot have spec bits");
|
doAssert(x.spec_bits == 0, "cannot have spec bits");
|
||||||
@@ -873,7 +873,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
// the killed Ld should have claimed phy reg, we should not commit it;
|
// the killed Ld should have claimed phy reg, we should not commit it;
|
||||||
// instead, we have kill the renaming by calling killAll
|
// instead, we have kill the renaming by calling killAll
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
case(killBy)
|
case(killBy)
|
||||||
Ld: comLdKillByLdCnt.incr(1);
|
Ld: comLdKillByLdCnt.incr(1);
|
||||||
@@ -881,7 +881,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
Cache: comLdKillByCacheCnt.incr(1);
|
Cache: comLdKillByCacheCnt.incr(1);
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// checks
|
// checks
|
||||||
doAssert(!x.epochIncremented, "cannot increment epoch before");
|
doAssert(!x.epochIncremented, "cannot increment epoch before");
|
||||||
@@ -1027,7 +1027,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
$fflush;
|
$fflush;
|
||||||
printCommits[0][1] <= tagged Valid x.u_id;
|
printCommits[0][1] <= tagged Valid x.u_id;
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
comSysCnt.incr(1);
|
comSysCnt.incr(1);
|
||||||
// inst count stats
|
// inst count stats
|
||||||
@@ -1036,14 +1036,14 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
userInstCnt.incr(1);
|
userInstCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
case(x.iType)
|
case(x.iType)
|
||||||
Fence, FenceI, SFence: events.evt_FENCE = 1;
|
Fence, FenceI, SFence: events.evt_FENCE = 1;
|
||||||
endcase
|
endcase
|
||||||
events_reg <= events;
|
events_reg <= events;
|
||||||
`endif
|
// `endif
|
||||||
`ifdef CHECK_DEADLOCK
|
`ifdef CHECK_DEADLOCK
|
||||||
commitInst.send;
|
commitInst.send;
|
||||||
if(csrf.decodeInfo.prv == 0) begin
|
if(csrf.decodeInfo.prv == 0) begin
|
||||||
@@ -1148,22 +1148,22 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
Data po_mstatus = ?;
|
Data po_mstatus = ?;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
// update targets vector
|
// update targets vector
|
||||||
Vector#(SupSize, Maybe#(CapMem)) targets;
|
Vector#(SupSize, Maybe#(CapMem)) targets;
|
||||||
// update return targets vector
|
// update return targets vector
|
||||||
Vector#(SupSize, Maybe#(CapMem)) returnTargets;
|
Vector#(SupSize, Maybe#(CapMem)) returnTargets;
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
// compute what actions to take
|
// compute what actions to take
|
||||||
for(Integer i = 0; i < valueof(SupSize); i = i+1) begin
|
for(Integer i = 0; i < valueof(SupSize); i = i+1) begin
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
Maybe#(CapMem) tar = tagged Invalid;
|
Maybe#(CapMem) tar = tagged Invalid;
|
||||||
Maybe#(CapMem) retTar = tagged Invalid;
|
Maybe#(CapMem) retTar = tagged Invalid;
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
if(!stop && rob.deqPort[i].canDeq) begin
|
if(!stop && rob.deqPort[i].canDeq) begin
|
||||||
let x = rob.deqPort[i].deq_data;
|
let x = rob.deqPort[i].deq_data;
|
||||||
let inst_tag = rob.deqPort[i].getDeqInstTag;
|
let inst_tag = rob.deqPort[i].getDeqInstTag;
|
||||||
@@ -1207,7 +1207,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
// inst can be committed, deq it
|
// inst can be committed, deq it
|
||||||
rob.deqPort[i].deq;
|
rob.deqPort[i].deq;
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
// return address stack link reg is x1 or x5
|
// return address stack link reg is x1 or x5
|
||||||
function Bool linkedR(Maybe#(ArchRIndx) register);
|
function Bool linkedR(Maybe#(ArchRIndx) register);
|
||||||
@@ -1230,7 +1230,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// every inst here should have been renamed, commit renaming
|
// every inst here should have been renamed, commit renaming
|
||||||
regRenamingTable.commit[i].commit;
|
regRenamingTable.commit[i].commit;
|
||||||
@@ -1328,12 +1328,12 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
`endif
|
`endif
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
targets[i] = tar;
|
targets[i] = tar;
|
||||||
returnTargets[i] = retTar;
|
returnTargets[i] = retTar;
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
rg_serial_num <= rg_serial_num + instret;
|
rg_serial_num <= rg_serial_num + instret;
|
||||||
|
|
||||||
@@ -1359,7 +1359,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter
|
// performance counter
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
// branch stats
|
// branch stats
|
||||||
@@ -1379,8 +1379,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
supComUserCnt.incr(1);
|
supComUserCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
events.evt_BRANCH = zeroExtend(brCnt);
|
events.evt_BRANCH = zeroExtend(brCnt);
|
||||||
events.evt_JAL = zeroExtend(jmpCnt);
|
events.evt_JAL = zeroExtend(jmpCnt);
|
||||||
@@ -1400,7 +1400,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
inIfc.updateTargets(targets);
|
inIfc.updateTargets(targets);
|
||||||
inIfc.updateReturnTargets(returnTargets);
|
inIfc.updateReturnTargets(returnTargets);
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef RVFI
|
`ifdef RVFI
|
||||||
rvfiQ.enq(rvfis);
|
rvfiQ.enq(rvfis);
|
||||||
@@ -1446,7 +1446,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
|
|
||||||
method Data getPerf(ComStagePerfType t);
|
method Data getPerf(ComStagePerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
InstCnt: instCnt;
|
InstCnt: instCnt;
|
||||||
UserInstCnt: userInstCnt;
|
UserInstCnt: userInstCnt;
|
||||||
SupComUserCnt: supComUserCnt;
|
SupComUserCnt: supComUserCnt;
|
||||||
@@ -1468,7 +1468,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
FlushSecurityCnt: flushSecurityCnt;
|
FlushSecurityCnt: flushSecurityCnt;
|
||||||
FlushBPCnt: flushBPCnt;
|
FlushBPCnt: flushBPCnt;
|
||||||
FlushCacheCnt: flushCacheCnt;
|
FlushCacheCnt: flushCacheCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
@@ -1509,8 +1509,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
|
|||||||
endmethod
|
endmethod
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method events = events_reg;
|
method events = events_reg;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -165,9 +165,9 @@ interface FetchStage;
|
|||||||
|
|
||||||
// performance
|
// performance
|
||||||
interface Perf#(DecStagePerfType) perf;
|
interface Perf#(DecStagePerfType) perf;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method Bool redirect_evt;
|
method Bool redirect_evt;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
// PC "compression" types to facilitate storing common upper PC bits in a
|
// PC "compression" types to facilitate storing common upper PC bits in a
|
||||||
@@ -471,7 +471,7 @@ module mkFetchStage(FetchStage);
|
|||||||
|
|
||||||
// performance counters
|
// performance counters
|
||||||
Fifo#(1, DecStagePerfType) perfReqQ <- mkCFFifo; // perf req FIFO
|
Fifo#(1, DecStagePerfType) perfReqQ <- mkCFFifo; // perf req FIFO
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
// decode stage redirect
|
// decode stage redirect
|
||||||
Count#(Data) decRedirectBrCnt <- mkCount(0);
|
Count#(Data) decRedirectBrCnt <- mkCount(0);
|
||||||
@@ -495,10 +495,10 @@ module mkFetchStage(FetchStage);
|
|||||||
data: d
|
data: d
|
||||||
});
|
});
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Reg#(Bool) redirect_evt_reg <- mkDReg(False);
|
Reg#(Bool) redirect_evt_reg <- mkDReg(False);
|
||||||
`endif
|
// `endif
|
||||||
`ifdef KONATA
|
`ifdef KONATA
|
||||||
Reg#(Bit#(64)) uid <- mkReg(0);
|
Reg#(Bit#(64)) uid <- mkReg(0);
|
||||||
Reg#(Bool) k_reset <- mkReg(True);
|
Reg#(Bool) k_reset <- mkReg(True);
|
||||||
@@ -856,11 +856,11 @@ module mkFetchStage(FetchStage);
|
|||||||
`endif
|
`endif
|
||||||
Maybe#(TrainNAP) trainNAP = Invalid; // training data sent to next addr pred
|
Maybe#(TrainNAP) trainNAP = Invalid; // training data sent to next addr pred
|
||||||
Bool decode_epoch_local = decode_epoch[0]; // next value for decode epoch
|
Bool decode_epoch_local = decode_epoch[0]; // next value for decode epoch
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: inst being redirect by decode stage
|
// performance counter: inst being redirect by decode stage
|
||||||
// Note that only 1 redirection may happen in a cycle
|
// Note that only 1 redirection may happen in a cycle
|
||||||
Maybe#(IType) redirectInst = Invalid;
|
Maybe#(IType) redirectInst = Invalid;
|
||||||
`endif
|
// `endif
|
||||||
Bool likely_epoch_change = False;
|
Bool likely_epoch_change = False;
|
||||||
Maybe#(CapMem) m_push_addr = Invalid;
|
Maybe#(CapMem) m_push_addr = Invalid;
|
||||||
for (Integer i = 0; i < valueof(SupSize); i=i+1) begin
|
for (Integer i = 0; i < valueof(SupSize); i=i+1) begin
|
||||||
@@ -977,11 +977,11 @@ module mkFetchStage(FetchStage);
|
|||||||
// train next addr pred when mispredict
|
// train next addr pred when mispredict
|
||||||
let last_x16_pc = addPc(pc, ((in.inst_kind == Inst_32b) ? 2 : 0));
|
let last_x16_pc = addPc(pc, ((in.inst_kind == Inst_32b) ? 2 : 0));
|
||||||
trainNAP = Valid (TrainNAP {pc: last_x16_pc, nextPc: decode_pred_next_pc});
|
trainNAP = Valid (TrainNAP {pc: last_x16_pc, nextPc: decode_pred_next_pc});
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance stats: record decode redirect
|
// performance stats: record decode redirect
|
||||||
doAssert(redirectInst == Invalid, "at most 1 decode redirect per cycle");
|
doAssert(redirectInst == Invalid, "at most 1 decode redirect per cycle");
|
||||||
redirectInst = Valid (dInst.iType);
|
redirectInst = Valid (dInst.iType);
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
end // if (!isValid(cause))
|
end // if (!isValid(cause))
|
||||||
if (isValid(m_push_addr)) trainInfo.ras = trainInfo.ras + 1;
|
if (isValid(m_push_addr)) trainInfo.ras = trainInfo.ras + 1;
|
||||||
@@ -1049,7 +1049,7 @@ module mkFetchStage(FetchStage);
|
|||||||
if (trainNAP matches tagged Valid .x) begin
|
if (trainNAP matches tagged Valid .x) begin
|
||||||
napTrainByDecQ.enq(x);
|
napTrainByDecQ.enq(x);
|
||||||
end
|
end
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// performance counter: check whether redirect happens
|
// performance counter: check whether redirect happens
|
||||||
if(redirectInst matches tagged Valid .iType &&& doStats) begin
|
if(redirectInst matches tagged Valid .iType &&& doStats) begin
|
||||||
case(iType)
|
case(iType)
|
||||||
@@ -1059,7 +1059,7 @@ module mkFetchStage(FetchStage);
|
|||||||
default: decRedirectOtherCnt.incr(1);
|
default: decRedirectOtherCnt.incr(1);
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule reportDecodePc;
|
rule reportDecodePc;
|
||||||
@@ -1143,9 +1143,9 @@ module mkFetchStage(FetchStage);
|
|||||||
// this redirect may be caused by a trap/system inst in commit stage
|
// this redirect may be caused by a trap/system inst in commit stage
|
||||||
// we conservatively set wait for flush TODO make this an input parameter
|
// we conservatively set wait for flush TODO make this an input parameter
|
||||||
waitForFlush[2] <= True;
|
waitForFlush[2] <= True;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
redirect_evt_reg <= True;
|
redirect_evt_reg <= True;
|
||||||
`endif
|
// `endif
|
||||||
execute_redirect_count <= execute_redirect_count + 1;
|
execute_redirect_count <= execute_redirect_count + 1;
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
@@ -1222,11 +1222,11 @@ module mkFetchStage(FetchStage);
|
|||||||
|
|
||||||
interface Perf perf;
|
interface Perf perf;
|
||||||
method Action setStatus(Bool stats);
|
method Action setStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Action req(DecStagePerfType r);
|
method Action req(DecStagePerfType r);
|
||||||
@@ -1234,26 +1234,26 @@ module mkFetchStage(FetchStage);
|
|||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method ActionValue#(PerfResp#(DecStagePerfType)) resp;
|
method ActionValue#(PerfResp#(DecStagePerfType)) resp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
return PerfResp {
|
// return PerfResp {
|
||||||
pType: perfReqQ.first,
|
// pType: perfReqQ.first,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
method Bool respValid = perfRespQ.notEmpty;
|
method Bool respValid = perfRespQ.notEmpty;
|
||||||
`else
|
// `else
|
||||||
method Bool respValid = perfReqQ.notEmpty;
|
// method Bool respValid = perfReqQ.notEmpty;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method Bool redirect_evt = redirect_evt_reg._read;
|
method Bool redirect_evt = redirect_evt_reg._read;
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -172,13 +172,13 @@ module mkFpuMulDivExePipeline#(FpuMulDivExeInput inIfc)(FpuMulDivExePipeline);
|
|||||||
FpuExec fpuExec <- mkFpuExecPipeline;
|
FpuExec fpuExec <- mkFpuExecPipeline;
|
||||||
|
|
||||||
// fpu/mul/div performance counters
|
// fpu/mul/div performance counters
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Count#(Data) exeIntMulCnt <- mkCount(0);
|
Count#(Data) exeIntMulCnt <- mkCount(0);
|
||||||
Count#(Data) exeIntDivCnt <- mkCount(0);
|
Count#(Data) exeIntDivCnt <- mkCount(0);
|
||||||
Count#(Data) exeFpFmaCnt <- mkCount(0);
|
Count#(Data) exeFpFmaCnt <- mkCount(0);
|
||||||
Count#(Data) exeFpDivCnt <- mkCount(0);
|
Count#(Data) exeFpDivCnt <- mkCount(0);
|
||||||
Count#(Data) exeFpSqrtCnt <- mkCount(0);
|
Count#(Data) exeFpSqrtCnt <- mkCount(0);
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
rule doDispatchFpuMulDiv;
|
rule doDispatchFpuMulDiv;
|
||||||
rsFpuMulDiv.doDispatch;
|
rsFpuMulDiv.doDispatch;
|
||||||
@@ -345,11 +345,11 @@ module mkFpuMulDivExePipeline#(FpuMulDivExeInput inIfc)(FpuMulDivExePipeline);
|
|||||||
`else
|
`else
|
||||||
doFinish(resp.dst, resp.tag, resp.res.data, resp.res.fflags);
|
doFinish(resp.dst, resp.tag, resp.res.data, resp.res.fflags);
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeFpFmaCnt.incr(1);
|
exeFpFmaCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule doFinishFpDiv;
|
rule doFinishFpDiv;
|
||||||
@@ -360,11 +360,11 @@ module mkFpuMulDivExePipeline#(FpuMulDivExeInput inIfc)(FpuMulDivExePipeline);
|
|||||||
`else
|
`else
|
||||||
doFinish(resp.dst, resp.tag, resp.res.data, resp.res.fflags);
|
doFinish(resp.dst, resp.tag, resp.res.data, resp.res.fflags);
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeFpDivCnt.incr(1);
|
exeFpDivCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule doFinishFpSqrt;
|
rule doFinishFpSqrt;
|
||||||
@@ -375,11 +375,11 @@ module mkFpuMulDivExePipeline#(FpuMulDivExeInput inIfc)(FpuMulDivExePipeline);
|
|||||||
`else
|
`else
|
||||||
doFinish(resp.dst, resp.tag, resp.res.data, resp.res.fflags);
|
doFinish(resp.dst, resp.tag, resp.res.data, resp.res.fflags);
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeFpSqrtCnt.incr(1);
|
exeFpSqrtCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule doFinishIntMul;
|
rule doFinishIntMul;
|
||||||
@@ -390,11 +390,11 @@ module mkFpuMulDivExePipeline#(FpuMulDivExeInput inIfc)(FpuMulDivExePipeline);
|
|||||||
`else
|
`else
|
||||||
doFinish(resp.dst, resp.tag, resp.data, 0);
|
doFinish(resp.dst, resp.tag, resp.data, 0);
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeIntMulCnt.incr(1);
|
exeIntMulCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule doFinishIntDiv;
|
rule doFinishIntDiv;
|
||||||
@@ -405,11 +405,11 @@ module mkFpuMulDivExePipeline#(FpuMulDivExeInput inIfc)(FpuMulDivExePipeline);
|
|||||||
`else
|
`else
|
||||||
doFinish(resp.dst, resp.tag, resp.data, 0);
|
doFinish(resp.dst, resp.tag, resp.data, 0);
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeIntDivCnt.incr(1);
|
exeIntDivCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
interface recvBypass = map(getRecvBypassDataIfc, bypassWire);
|
interface recvBypass = map(getRecvBypassDataIfc, bypassWire);
|
||||||
@@ -426,13 +426,13 @@ module mkFpuMulDivExePipeline#(FpuMulDivExeInput inIfc)(FpuMulDivExePipeline);
|
|||||||
|
|
||||||
method Data getPerf(ExeStagePerfType t);
|
method Data getPerf(ExeStagePerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
ExeIntMulCnt: exeIntMulCnt;
|
ExeIntMulCnt: exeIntMulCnt;
|
||||||
ExeIntDivCnt: exeIntDivCnt;
|
ExeIntDivCnt: exeIntDivCnt;
|
||||||
ExeFpFmaCnt: exeFpFmaCnt;
|
ExeFpFmaCnt: exeFpFmaCnt;
|
||||||
ExeFpDivCnt: exeFpDivCnt;
|
ExeFpDivCnt: exeFpDivCnt;
|
||||||
ExeFpSqrtCnt: exeFpSqrtCnt;
|
ExeFpSqrtCnt: exeFpSqrtCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
|
|||||||
@@ -75,12 +75,12 @@ import CHERICap::*;
|
|||||||
import CHERICC_Fat::*;
|
import CHERICC_Fat::*;
|
||||||
import ISA_Decls_CHERI::*;
|
import ISA_Decls_CHERI::*;
|
||||||
import CacheUtils::*;
|
import CacheUtils::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
import DReg::*;
|
import DReg::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
import Cur_Cycle :: *;
|
import Cur_Cycle :: *;
|
||||||
|
|
||||||
@@ -242,12 +242,12 @@ interface MemExeInput;
|
|||||||
// performance
|
// performance
|
||||||
method Bool doStats;
|
method Bool doStats;
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method CapMem rob_getPredPC(InstTag t);
|
method CapMem rob_getPredPC(InstTag t);
|
||||||
method Bit #(32) rob_getOrig_Inst (InstTag t);
|
method Bit #(32) rob_getOrig_Inst (InstTag t);
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
interface MemExePipeline;
|
interface MemExePipeline;
|
||||||
@@ -263,12 +263,12 @@ interface MemExePipeline;
|
|||||||
interface Server#(void, void) reconcile;
|
interface Server#(void, void) reconcile;
|
||||||
`endif
|
`endif
|
||||||
method Data getPerf(ExeStagePerfType t);
|
method Data getPerf(ExeStagePerfType t);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsCore events;
|
method EventsCore events;
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method EventsTransExe events_trans;
|
method EventsTransExe events_trans;
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
||||||
@@ -282,7 +282,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
// These are always included as they are used by both stat counter systems.
|
// These are always included as they are used by both stat counter systems.
|
||||||
LatencyTimer#(LdQSize, 10) ldMemLatTimer <- mkLatencyTimer;
|
LatencyTimer#(LdQSize, 10) ldMemLatTimer <- mkLatencyTimer;
|
||||||
LatencyTimer#(SBSize, 10) stMemLatTimer <- mkLatencyTimer;
|
LatencyTimer#(SBSize, 10) stMemLatTimer <- mkLatencyTimer;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// load issue stall
|
// load issue stall
|
||||||
Count#(Data) exeLdStallByLdCnt <- mkCount(0);
|
Count#(Data) exeLdStallByLdCnt <- mkCount(0);
|
||||||
Count#(Data) exeLdStallByStCnt <- mkCount(0);
|
Count#(Data) exeLdStallByStCnt <- mkCount(0);
|
||||||
@@ -306,14 +306,14 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
Count#(Data) exeFenceCnt <- mkCount(0);
|
Count#(Data) exeFenceCnt <- mkCount(0);
|
||||||
Count#(Data) exeFenceAcqCnt <- mkCount(0);
|
Count#(Data) exeFenceAcqCnt <- mkCount(0);
|
||||||
Count#(Data) exeFenceRelCnt <- mkCount(0);
|
Count#(Data) exeFenceRelCnt <- mkCount(0);
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsCore)) events_reg <- mkDRegOR (5, unpack (0));
|
Array #(Reg #(EventsCore)) events_reg <- mkDRegOR (5, unpack (0));
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
Reg#(EventsTransExe) events_trans_reg <- mkDReg(unpack(0));
|
Reg#(EventsTransExe) events_trans_reg <- mkDReg(unpack(0));
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// reservation station
|
// reservation station
|
||||||
ReservationStationMem rsMem <- mkReservationStationMem;
|
ReservationStationMem rsMem <- mkReservationStationMem;
|
||||||
@@ -377,17 +377,17 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
end
|
end
|
||||||
// perf: load mem latency
|
// perf: load mem latency
|
||||||
let lat <- ldMemLatTimer.done(tag);
|
let lat <- ldMemLatTimer.done(tag);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeLdMemLat.incr(zeroExtend(lat));
|
exeLdMemLat.incr(zeroExtend(lat));
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
events.evt_LOAD_WAIT = saturating_truncate(lat);
|
events.evt_LOAD_WAIT = saturating_truncate(lat);
|
||||||
events.evt_MEM_CAP_LOAD_TAG_SET = (d.tag) ? 1 : 0;
|
events.evt_MEM_CAP_LOAD_TAG_SET = (d.tag) ? 1 : 0;
|
||||||
events_reg[1] <= events;
|
events_reg[1] <= events;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
method Action respLrScAmo(DProcReqId id, MemTaggedData d);
|
method Action respLrScAmo(DProcReqId id, MemTaggedData d);
|
||||||
respLrScAmoQ.enq(d);
|
respLrScAmoQ.enq(d);
|
||||||
@@ -405,17 +405,17 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
end
|
end
|
||||||
// perf: store mem latency
|
// perf: store mem latency
|
||||||
let lat <- stMemLatTimer.done(0);
|
let lat <- stMemLatTimer.done(0);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeStMemLat.incr(zeroExtend(lat));
|
exeStMemLat.incr(zeroExtend(lat));
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
if (pack(waitSt.shiftedBE) == -1) events.evt_MEM_CAP_STORE = 1;
|
if (pack(waitSt.shiftedBE) == -1) events.evt_MEM_CAP_STORE = 1;
|
||||||
events.evt_STORE_WAIT = saturating_truncate(lat);
|
events.evt_STORE_WAIT = saturating_truncate(lat);
|
||||||
events_reg[2] <= events;
|
events_reg[2] <= events;
|
||||||
`endif
|
// `endif
|
||||||
// now figure out the data to be written
|
// now figure out the data to be written
|
||||||
CLineMemDataByteEn be = replicate(replicate(False));
|
CLineMemDataByteEn be = replicate(replicate(False));
|
||||||
Line data = unpack(0);
|
Line data = unpack(0);
|
||||||
@@ -432,17 +432,17 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
if(verbose) $display("[Store resp] idx = %x, ", idx, fshow(e));
|
if(verbose) $display("[Store resp] idx = %x, ", idx, fshow(e));
|
||||||
// perf: store mem latency
|
// perf: store mem latency
|
||||||
let lat <- stMemLatTimer.done(idx);
|
let lat <- stMemLatTimer.done(idx);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeStMemLat.incr(zeroExtend(lat));
|
exeStMemLat.incr(zeroExtend(lat));
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
if (pack(e.byteEn) == -1) events.evt_MEM_CAP_STORE = 1;
|
if (pack(e.byteEn) == -1) events.evt_MEM_CAP_STORE = 1;
|
||||||
events.evt_STORE_WAIT = saturating_truncate(lat);
|
events.evt_STORE_WAIT = saturating_truncate(lat);
|
||||||
events_reg[2] <= events;
|
events_reg[2] <= events;
|
||||||
`endif
|
// `endif
|
||||||
return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry
|
return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry
|
||||||
endmethod
|
endmethod
|
||||||
`endif
|
`endif
|
||||||
@@ -504,12 +504,12 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
spec_bits: x.spec_bits
|
spec_bits: x.spec_bits
|
||||||
});
|
});
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: load to use latency
|
// perf: load to use latency
|
||||||
if(x.data.ldstq_tag matches tagged Ld .idx) begin
|
if(x.data.ldstq_tag matches tagged Ld .idx) begin
|
||||||
ldToUseLatTimer.start(idx);
|
ldToUseLatTimer.start(idx);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef RVFI
|
`ifdef RVFI
|
||||||
@@ -584,11 +584,11 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
if(x.ldstq_tag matches tagged St .stTag) begin
|
if(x.ldstq_tag matches tagged St .stTag) begin
|
||||||
MemTaggedData d = x.mem_func == Amo ? toMemData : shiftData; // XXX don't shift for AMO
|
MemTaggedData d = x.mem_func == Amo ? toMemData : shiftData; // XXX don't shift for AMO
|
||||||
lsq.updateData(stTag, d);
|
lsq.updateData(stTag, d);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
events.evt_MEM_CAP_STORE_TAG_SET = (d.tag) ? 1 : 0;
|
events.evt_MEM_CAP_STORE_TAG_SET = (d.tag) ? 1 : 0;
|
||||||
events_reg[4] <= events;
|
events_reg[4] <= events;
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifdef KONATA
|
`ifdef KONATA
|
||||||
@@ -808,7 +808,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pc = inIfc.rob_getPC(x.tag);
|
let pc = inIfc.rob_getPC(x.tag);
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
function Bool is_16b_inst (Bit #(n) inst);
|
function Bool is_16b_inst (Bit #(n) inst);
|
||||||
return (inst [1:0] != 2'b11);
|
return (inst [1:0] != 2'b11);
|
||||||
@@ -822,7 +822,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
events_trans_reg <= events_trans;
|
events_trans_reg <= events_trans;
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef KONATA
|
`ifdef KONATA
|
||||||
$display("KONATAE\t%0d\t%0d\t0\tMem3", cur_cycle, x.u_id);
|
$display("KONATAE\t%0d\t%0d\t0\tMem3", cur_cycle, x.u_id);
|
||||||
@@ -859,11 +859,11 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
});
|
});
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(isValid(cause) && inIfc.doStats) begin
|
if(isValid(cause) && inIfc.doStats) begin
|
||||||
exeTlbExcepCnt.incr(1);
|
exeTlbExcepCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
//=======================================================
|
//=======================================================
|
||||||
@@ -886,10 +886,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
`else
|
`else
|
||||||
SBSearchRes sbRes = stb.search(info.paddr, info.shiftedBE);
|
SBSearchRes sbRes = stb.search(info.paddr, info.shiftedBE);
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
if (info.shiftedBE == DataMemAccess (unpack(~0))) events.evt_MEM_CAP_LOAD = 1;
|
if (info.shiftedBE == DataMemAccess (unpack(~0))) events.evt_MEM_CAP_LOAD = 1;
|
||||||
`endif
|
// `endif
|
||||||
// search LSQ
|
// search LSQ
|
||||||
LSQIssueLdResult issRes <- lsq.issueLd(info.tag, info.paddr, info.shiftedBE, sbRes);
|
LSQIssueLdResult issRes <- lsq.issueLd(info.tag, info.paddr, info.shiftedBE, sbRes);
|
||||||
if(verbose) begin
|
if(verbose) begin
|
||||||
@@ -903,12 +903,12 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
if(forward.dst matches tagged Valid .dst) begin
|
if(forward.dst matches tagged Valid .dst) begin
|
||||||
inIfc.setRegReadyAggr_forward(dst.indx);
|
inIfc.setRegReadyAggr_forward(dst.indx);
|
||||||
end
|
end
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: load forward
|
// perf: load forward
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeLdForwardCnt.incr(1);
|
exeLdForwardCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else if(issRes == ToCache) begin
|
else if(issRes == ToCache) begin
|
||||||
reqLdQ.enq(tuple4(zeroExtend(info.tag), info.paddr, info.shiftedBE == TagMemAccess, info.pcHash));
|
reqLdQ.enq(tuple4(zeroExtend(info.tag), info.paddr, info.shiftedBE == TagMemAccess, info.pcHash));
|
||||||
@@ -916,7 +916,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
ldMemLatTimer.start(info.tag);
|
ldMemLatTimer.start(info.tag);
|
||||||
end
|
end
|
||||||
else if(issRes matches tagged Stall .stallBy) begin
|
else if(issRes matches tagged Stall .stallBy) begin
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: load stall
|
// perf: load stall
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
case(stallBy)
|
case(stallBy)
|
||||||
@@ -926,14 +926,14 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
default: doAssert(False, "unknow stall reason");
|
default: doAssert(False, "unknow stall reason");
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
doAssert(False, "load is stalled");
|
doAssert(False, "load is stalled");
|
||||||
end
|
end
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
events_reg[0] <= events;
|
events_reg[0] <= events;
|
||||||
`endif
|
// `endif
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -975,14 +975,14 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
inIfc.rob_setExecuted_doFinishMem_RegData (res.instTag, res.data);
|
inIfc.rob_setExecuted_doFinishMem_RegData (res.instTag, res.data);
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: load to use latency
|
// perf: load to use latency
|
||||||
let lat <- ldToUseLatTimer.done(tag);
|
let lat <- ldToUseLatTimer.done(tag);
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeLdToUseLat.incr(zeroExtend(lat));
|
exeLdToUseLat.incr(zeroExtend(lat));
|
||||||
exeLdToUseCnt.incr(1);
|
exeLdToUseCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef RVFI
|
`ifdef RVFI
|
||||||
LdStQTag idx = tagged Ld tag;
|
LdStQTag idx = tagged Ld tag;
|
||||||
memData[pack(idx)] <= truncate(pack(res.data)); // TODO use fromMem?
|
memData[pack(idx)] <= truncate(pack(res.data)); // TODO use fromMem?
|
||||||
@@ -1093,7 +1093,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
if(verbose) $display("[doDeqLdQ_Lr_issue] ", fshow(lsqDeqLd), "; ", fshow(req));
|
if(verbose) $display("[doDeqLdQ_Lr_issue] ", fshow(lsqDeqLd), "; ", fshow(req));
|
||||||
// check
|
// check
|
||||||
doAssert(!isValid(lsqDeqLd.killed), "cannot be killed");
|
doAssert(!isValid(lsqDeqLd.killed), "cannot be killed");
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
if(lsqDeqLd.acq) begin
|
if(lsqDeqLd.acq) begin
|
||||||
exeLrScAmoAcqCnt.incr(1);
|
exeLrScAmoAcqCnt.incr(1);
|
||||||
@@ -1102,7 +1102,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
exeLrScAmoRelCnt.incr(1);
|
exeLrScAmoRelCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef SELF_INV_CACHE
|
`ifdef SELF_INV_CACHE
|
||||||
@@ -1384,7 +1384,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
`endif
|
`endif
|
||||||
);
|
);
|
||||||
if(verbose) $display("[doDeqStQ_Fence] ", fshow(lsqDeqSt));
|
if(verbose) $display("[doDeqStQ_Fence] ", fshow(lsqDeqSt));
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
exeFenceCnt.incr(1);
|
exeFenceCnt.incr(1);
|
||||||
if(lsqDeqSt.acq) begin
|
if(lsqDeqSt.acq) begin
|
||||||
@@ -1394,7 +1394,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
exeFenceRelCnt.incr(1);
|
exeFenceRelCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// issue non-MMIO Sc/Amo without fault when
|
// issue non-MMIO Sc/Amo without fault when
|
||||||
@@ -1437,7 +1437,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
};
|
};
|
||||||
reqLrScAmoQ.enq(req);
|
reqLrScAmoQ.enq(req);
|
||||||
if(verbose) $display("[doDeqStQ_ScAmo_issue] ", fshow(lsqDeqSt), "; ", fshow(req));
|
if(verbose) $display("[doDeqStQ_ScAmo_issue] ", fshow(lsqDeqSt), "; ", fshow(req));
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
if(lsqDeqSt.acq) begin
|
if(lsqDeqSt.acq) begin
|
||||||
exeLrScAmoAcqCnt.incr(1);
|
exeLrScAmoAcqCnt.incr(1);
|
||||||
@@ -1446,7 +1446,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
exeLrScAmoRelCnt.incr(1);
|
exeLrScAmoRelCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef SELF_INV_CACHE
|
`ifdef SELF_INV_CACHE
|
||||||
@@ -1499,16 +1499,16 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
!lsqDeqSt.isMMIO, "must be non-MMIO Sc/Amo");
|
!lsqDeqSt.isMMIO, "must be non-MMIO Sc/Amo");
|
||||||
doAssert(!isValid(lsqDeqSt.fault), "no fault");
|
doAssert(!isValid(lsqDeqSt.fault), "no fault");
|
||||||
// stats for successful SC
|
// stats for successful SC
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats && lsqDeqSt.memFunc == Sc && resp == fromInteger(valueof(ScSuccVal))) begin
|
if(inIfc.doStats && lsqDeqSt.memFunc == Sc && resp == fromInteger(valueof(ScSuccVal))) begin
|
||||||
exeScSuccessCnt.incr(1);
|
exeScSuccessCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsCore events = unpack(0);
|
EventsCore events = unpack(0);
|
||||||
events.evt_SC_SUCCESS = 1;
|
events.evt_SC_SUCCESS = 1;
|
||||||
events_reg[3] <= events;
|
events_reg[3] <= events;
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// issue MMIO St/Amo when
|
// issue MMIO St/Amo when
|
||||||
@@ -1546,7 +1546,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
if(verbose) $display("[doDeqStQ_MMIO_issue] ", fshow(lsqDeqSt), "; ", fshow(req));
|
if(verbose) $display("[doDeqStQ_MMIO_issue] ", fshow(lsqDeqSt), "; ", fshow(req));
|
||||||
// MMIO may cause exception, must have spec tag, and only can be St/Amo
|
// MMIO may cause exception, must have spec tag, and only can be St/Amo
|
||||||
doAssert(lsqDeqSt.memFunc == St || lsqDeqSt.memFunc == Amo, "must be St/Amo");
|
doAssert(lsqDeqSt.memFunc == St || lsqDeqSt.memFunc == Amo, "must be St/Amo");
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
if(lsqDeqSt.acq) begin
|
if(lsqDeqSt.acq) begin
|
||||||
exeLrScAmoAcqCnt.incr(1);
|
exeLrScAmoAcqCnt.incr(1);
|
||||||
@@ -1555,7 +1555,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
exeLrScAmoRelCnt.incr(1);
|
exeLrScAmoRelCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
`ifdef SELF_INV_CACHE
|
`ifdef SELF_INV_CACHE
|
||||||
@@ -1725,7 +1725,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
|
|
||||||
method Data getPerf(ExeStagePerfType t);
|
method Data getPerf(ExeStagePerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
ExeLdStallByLd: exeLdStallByLdCnt;
|
ExeLdStallByLd: exeLdStallByLdCnt;
|
||||||
ExeLdStallBySt: exeLdStallByStCnt;
|
ExeLdStallBySt: exeLdStallByStCnt;
|
||||||
ExeLdStallBySB: exeLdStallBySBCnt;
|
ExeLdStallBySB: exeLdStallBySBCnt;
|
||||||
@@ -1741,14 +1741,14 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
|
|||||||
ExeFenceAcqCnt: exeFenceAcqCnt;
|
ExeFenceAcqCnt: exeFenceAcqCnt;
|
||||||
ExeFenceRelCnt: exeFenceRelCnt;
|
ExeFenceRelCnt: exeFenceRelCnt;
|
||||||
ExeFenceCnt: exeFenceCnt;
|
ExeFenceCnt: exeFenceCnt;
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method events = events_reg[0];
|
method events = events_reg[0];
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
method events_trans = events_trans_reg;
|
method events_trans = events_trans_reg;
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ import ConfigReg::*;
|
|||||||
import CHERICap::*;
|
import CHERICap::*;
|
||||||
import CHERICC_Fat::*;
|
import CHERICC_Fat::*;
|
||||||
import ISA_Decls_CHERI::*;
|
import ISA_Decls_CHERI::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
import DReg::*;
|
import DReg::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
import Cur_Cycle :: *;
|
import Cur_Cycle :: *;
|
||||||
|
|
||||||
@@ -116,9 +116,9 @@ interface RenameStage;
|
|||||||
// performance count
|
// performance count
|
||||||
method Data getPerf(ExeStagePerfType t);
|
method Data getPerf(ExeStagePerfType t);
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsTransExe events;
|
method EventsTransExe events;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// deadlock check
|
// deadlock check
|
||||||
interface Get#(RenameStuck) renameInstStuck;
|
interface Get#(RenameStuck) renameInstStuck;
|
||||||
@@ -150,15 +150,15 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
|
|||||||
|
|
||||||
// performance counter
|
// performance counter
|
||||||
Count#(Data) supRenameCnt <- mkCount(0);
|
Count#(Data) supRenameCnt <- mkCount(0);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
`ifdef SECURITY
|
`ifdef SECURITY
|
||||||
Count#(Data) specNoneCycles <- mkCount(0);
|
Count#(Data) specNoneCycles <- mkCount(0);
|
||||||
Count#(Data) specNonMemCycles <- mkCount(0);
|
Count#(Data) specNonMemCycles <- mkCount(0);
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Reg#(EventsTransExe) events_reg <- mkDReg(unpack(0));
|
Reg#(EventsTransExe) events_reg <- mkDReg(unpack(0));
|
||||||
`endif
|
// `endif
|
||||||
// deadlock check
|
// deadlock check
|
||||||
`ifdef CHECK_DEADLOCK
|
`ifdef CHECK_DEADLOCK
|
||||||
// timer to check deadlock
|
// timer to check deadlock
|
||||||
@@ -421,7 +421,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
|
|||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
`ifdef CONTRACTS_VERIFY
|
`ifdef CONTRACTS_VERIFY
|
||||||
let validPc = (x.orig_inst[1:0] != 2'b11) ? addPc(pc,2) : addPc(pc,4);
|
let validPc = (x.orig_inst[1:0] != 2'b11) ? addPc(pc,2) : addPc(pc,4);
|
||||||
if((ppc != validPc)) begin
|
if((ppc != validPc)) begin
|
||||||
@@ -430,7 +430,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
|
|||||||
events_reg <= events;
|
events_reg <= events;
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef CHECK_DEADLOCK
|
`ifdef CHECK_DEADLOCK
|
||||||
renameCorrectPath.send;
|
renameCorrectPath.send;
|
||||||
@@ -636,11 +636,11 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
|
|||||||
$display("KONATAS\t%0d\t%d\t0\tRnm", cur_cycle, x.u_id);
|
$display("KONATAS\t%0d\t%d\t0\tRnm", cur_cycle, x.u_id);
|
||||||
$fflush;
|
$fflush;
|
||||||
`endif
|
`endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsTransExe events = unpack(0);
|
EventsTransExe events = unpack(0);
|
||||||
events.evt_RENAMED_INST = 1;
|
events.evt_RENAMED_INST = 1;
|
||||||
events_reg <= events;
|
events_reg <= events;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// record if we issue an CSR inst. TODO also for SCRs?
|
// record if we issue an CSR inst. TODO also for SCRs?
|
||||||
if(dInst.iType == Csr) begin
|
if(dInst.iType == Csr) begin
|
||||||
@@ -660,14 +660,14 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
|
|||||||
Bool specNone = !machineMode && csrf.rd(csrAddrMSPEC) == zeroExtend(mSpecNone);
|
Bool specNone = !machineMode && csrf.rd(csrAddrMSPEC) == zeroExtend(mSpecNone);
|
||||||
Bool specNonMem = machineMode || csrf.rd(csrAddrMSPEC) == zeroExtend(mSpecNonMem);
|
Bool specNonMem = machineMode || csrf.rd(csrAddrMSPEC) == zeroExtend(mSpecNonMem);
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
rule incSpecNoneCycles(inIfc.doStats && specNone);
|
rule incSpecNoneCycles(inIfc.doStats && specNone);
|
||||||
specNoneCycles.incr(1);
|
specNoneCycles.incr(1);
|
||||||
endrule
|
endrule
|
||||||
rule incSpecNonMemCycles(inIfc.doStats && specNonMem);
|
rule incSpecNonMemCycles(inIfc.doStats && specNonMem);
|
||||||
specNonMemCycles.incr(1);
|
specNonMemCycles.incr(1);
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// first inst is mem inst
|
// first inst is mem inst
|
||||||
function Bool isMemInst(ExecFunc f);
|
function Bool isMemInst(ExecFunc f);
|
||||||
@@ -1251,20 +1251,20 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
|
|||||||
// otherwise this rule may block other rules forever
|
// otherwise this rule may block other rules forever
|
||||||
when(doCorrectPath, noAction);
|
when(doCorrectPath, noAction);
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(inIfc.doStats) begin
|
if(inIfc.doStats) begin
|
||||||
if(renameCnt > 1) begin
|
if(renameCnt > 1) begin
|
||||||
supRenameCnt.incr(1);
|
supRenameCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`else
|
// `else
|
||||||
supRenameCnt.incr(zeroExtend(renameCnt));
|
// supRenameCnt.incr(zeroExtend(renameCnt));
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsTransExe events = unpack(0);
|
EventsTransExe events = unpack(0);
|
||||||
events.evt_RENAMED_INST = zeroExtend(renameCnt);
|
events.evt_RENAMED_INST = zeroExtend(renameCnt);
|
||||||
events_reg <= events;
|
events_reg <= events;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef CHECK_DEADLOCK
|
`ifdef CHECK_DEADLOCK
|
||||||
if(doCorrectPath) begin
|
if(doCorrectPath) begin
|
||||||
@@ -1284,20 +1284,20 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
|
|||||||
|
|
||||||
method Data getPerf(ExeStagePerfType t);
|
method Data getPerf(ExeStagePerfType t);
|
||||||
return (case(t)
|
return (case(t)
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
SupRenameCnt: supRenameCnt;
|
SupRenameCnt: supRenameCnt;
|
||||||
`ifdef SECURITY
|
`ifdef SECURITY
|
||||||
SpecNoneCycles: specNoneCycles;
|
SpecNoneCycles: specNoneCycles;
|
||||||
SpecNonMemCycles: specNoneCycles;
|
SpecNonMemCycles: specNoneCycles;
|
||||||
`endif
|
`endif
|
||||||
`endif
|
// `endif
|
||||||
default: 0;
|
default: 0;
|
||||||
endcase);
|
endcase);
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method events = events_reg;
|
method events = events_reg;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef INCLUDE_GDB_CONTROL
|
`ifdef INCLUDE_GDB_CONTROL
|
||||||
method Action debug_halt_req ();
|
method Action debug_halt_req ();
|
||||||
|
|||||||
@@ -52,12 +52,12 @@ import LatencyTimer::*;
|
|||||||
import HasSpecBits::*;
|
import HasSpecBits::*;
|
||||||
import Vector::*;
|
import Vector::*;
|
||||||
import Ehr::*;
|
import Ehr::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import CCTypes::*;
|
import CCTypes::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
export DTlbReq(..);
|
export DTlbReq(..);
|
||||||
export DTlbResp(..);
|
export DTlbResp(..);
|
||||||
@@ -123,9 +123,9 @@ interface DTlb#(type instT);
|
|||||||
|
|
||||||
// performance
|
// performance
|
||||||
interface Perf#(L1TlbPerfType) perf;
|
interface Perf#(L1TlbPerfType) perf;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1D events;
|
method EventsL1D events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
typedef FullAssocTlb#(DTlbSize) DTlbArray;
|
typedef FullAssocTlb#(DTlbSize) DTlbArray;
|
||||||
@@ -210,7 +210,7 @@ module mkDTlb#(
|
|||||||
// perf counters
|
// perf counters
|
||||||
LatencyTimer#(DTlbReqNum, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
|
LatencyTimer#(DTlbReqNum, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
|
||||||
Fifo#(1, L1TlbPerfType) perfReqQ <- mkCFFifo;
|
Fifo#(1, L1TlbPerfType) perfReqQ <- mkCFFifo;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Fifo#(1, PerfResp#(L1TlbPerfType)) perfRespQ <- mkCFFifo;
|
Fifo#(1, PerfResp#(L1TlbPerfType)) perfRespQ <- mkCFFifo;
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
Count#(Data) accessCnt <- mkCount(0);
|
Count#(Data) accessCnt <- mkCount(0);
|
||||||
@@ -250,11 +250,12 @@ module mkDTlb#(
|
|||||||
rule incrAllMissCycles(doStats);
|
rule incrAllMissCycles(doStats);
|
||||||
function Bool isMiss(DTlbWait x) = x != None;
|
function Bool isMiss(DTlbWait x) = x != None;
|
||||||
when(all(isMiss, readVReg(pendWait)), allMissCycles.incr(1));
|
when(all(isMiss, readVReg(pendWait)), allMissCycles.incr(1));
|
||||||
|
$display("L1TlballMissCycles = %0d", allMissCycles);
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsL1D)) perf_events <- mkDRegOR (3, unpack (0));
|
Array #(Reg #(EventsL1D)) perf_events <- mkDRegOR (3, unpack (0));
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// do flush: start when all misses resolve
|
// do flush: start when all misses resolve
|
||||||
Bool noMiss = all(\== (False) , readVReg(pendValid_noMiss));
|
Bool noMiss = all(\== (False) , readVReg(pendValid_noMiss));
|
||||||
@@ -265,11 +266,11 @@ module mkDTlb#(
|
|||||||
flushRqToPQ.enq(?);
|
flushRqToPQ.enq(?);
|
||||||
waitFlushP <= True;
|
waitFlushP <= True;
|
||||||
if(verbose) $display("[DTLB] flush begin");
|
if(verbose) $display("[DTLB] flush begin");
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1D ev = unpack(0);
|
EventsL1D ev = unpack(0);
|
||||||
ev.evt_TLB_FLUSH = 1;
|
ev.evt_TLB_FLUSH = 1;
|
||||||
perf_events[2] <= ev;
|
perf_events[2] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule doFinishFlush(needFlush && waitFlushP);
|
rule doFinishFlush(needFlush && waitFlushP);
|
||||||
@@ -365,24 +366,28 @@ module mkDTlb#(
|
|||||||
|
|
||||||
// perf: miss
|
// perf: miss
|
||||||
let lat <- latTimer.done(idx);
|
let lat <- latTimer.done(idx);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(isValid(respForOtherReq)) begin
|
if(isValid(respForOtherReq)) begin
|
||||||
|
$display("L1 TLB miss");
|
||||||
|
$display("L1TLBmissPeerLat = %0d", missPeerLat);
|
||||||
missPeerLat.incr(zeroExtend(lat));
|
missPeerLat.incr(zeroExtend(lat));
|
||||||
missPeerCnt.incr(1);
|
missPeerCnt.incr(1);
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
missParentLat.incr(zeroExtend(lat));
|
missParentLat.incr(zeroExtend(lat));
|
||||||
missParentCnt.incr(1);
|
missParentCnt.incr(1);
|
||||||
|
$display("L1 TLB parent miss");
|
||||||
|
$display("L1TLBmissParentCnt = %0d", missParentCnt);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1D ev = unpack(0);
|
EventsL1D ev = unpack(0);
|
||||||
ev.evt_TLB_MISS_LAT = saturating_truncate(lat);
|
ev.evt_TLB_MISS_LAT = saturating_truncate(lat);
|
||||||
ev.evt_TLB_MISS = 1;
|
ev.evt_TLB_MISS = 1;
|
||||||
perf_events[0] <= ev;
|
perf_events[0] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
// conflict with wrong spec
|
// conflict with wrong spec
|
||||||
wrongSpec_doPRs_conflict.wset(?);
|
wrongSpec_doPRs_conflict.wset(?);
|
||||||
endrule
|
endrule
|
||||||
@@ -573,17 +578,18 @@ module mkDTlb#(
|
|||||||
if(verbose) $display("DTLB %m req (bare): ", fshow(r));
|
if(verbose) $display("DTLB %m req (bare): ", fshow(r));
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: access
|
// perf: access
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
|
$display("L1 TLB inc");
|
||||||
accessCnt.incr(1);
|
accessCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1D ev = unpack(0);
|
EventsL1D ev = unpack(0);
|
||||||
ev.evt_TLB = 1;
|
ev.evt_TLB = 1;
|
||||||
perf_events[1] <= ev;
|
perf_events[1] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
// conflict with wrong spec
|
// conflict with wrong spec
|
||||||
wrongSpec_procReq_conflict.wset(?);
|
wrongSpec_procReq_conflict.wset(?);
|
||||||
endmethod
|
endmethod
|
||||||
@@ -640,11 +646,11 @@ module mkDTlb#(
|
|||||||
|
|
||||||
interface Perf perf;
|
interface Perf perf;
|
||||||
method Action setStatus(Bool stats);
|
method Action setStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Action req(L1TlbPerfType r);
|
method Action req(L1TlbPerfType r);
|
||||||
@@ -652,27 +658,27 @@ module mkDTlb#(
|
|||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method ActionValue#(PerfResp#(L1TlbPerfType)) resp;
|
method ActionValue#(PerfResp#(L1TlbPerfType)) resp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
return PerfResp {
|
// return PerfResp {
|
||||||
pType: perfReqQ.first,
|
// pType: perfReqQ.first,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Bool respValid;
|
method Bool respValid;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
return perfRespQ.notEmpty;
|
return perfRespQ.notEmpty;
|
||||||
`else
|
// `else
|
||||||
return perfReqQ.notEmpty;
|
// return perfReqQ.notEmpty;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1D events = perf_events[0];
|
method EventsL1D events = perf_events[0];
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
186
src_Core/RISCY_OOO/procs/lib/DTlb.bsv.rej
Normal file
186
src_Core/RISCY_OOO/procs/lib/DTlb.bsv.rej
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
diff a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv (rejected hunks)
|
||||||
|
@@ -52,12 +52,12 @@ import LatencyTimer::*;
|
||||||
|
import HasSpecBits::*;
|
||||||
|
import Vector::*;
|
||||||
|
import Ehr::*;
|
||||||
|
-`ifdef PERFORMANCE_MONITORING
|
||||||
|
+// `ifdef PERFORMANCE_MONITORING
|
||||||
|
import PerformanceMonitor::*;
|
||||||
|
import CCTypes::*;
|
||||||
|
import BlueUtils::*;
|
||||||
|
import StatCounters::*;
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
|
||||||
|
export DTlbReq(..);
|
||||||
|
export DTlbResp(..);
|
||||||
|
@@ -123,9 +123,9 @@ interface DTlb#(type instT);
|
||||||
|
|
||||||
|
// performance
|
||||||
|
interface Perf#(L1TlbPerfType) perf;
|
||||||
|
-`ifdef PERFORMANCE_MONITORING
|
||||||
|
+// `ifdef PERFORMANCE_MONITORING
|
||||||
|
method EventsL1D events;
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
typedef FullAssocTlb#(DTlbSize) DTlbArray;
|
||||||
|
@@ -210,7 +210,7 @@ module mkDTlb#(
|
||||||
|
// perf counters
|
||||||
|
LatencyTimer#(DTlbReqNum, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
|
||||||
|
Fifo#(1, L1TlbPerfType) perfReqQ <- mkCFFifo;
|
||||||
|
-`ifdef PERF_COUNT
|
||||||
|
+// `ifdef PERF_COUNT
|
||||||
|
Fifo#(1, PerfResp#(L1TlbPerfType)) perfRespQ <- mkCFFifo;
|
||||||
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
|
Count#(Data) accessCnt <- mkCount(0);
|
||||||
|
@@ -243,10 +243,10 @@ module mkDTlb#(
|
||||||
|
function Bool isMiss(DTlbWait x) = x != None;
|
||||||
|
when(all(isMiss, readVReg(pendWait)), allMissCycles.incr(1));
|
||||||
|
endrule
|
||||||
|
-`endif
|
||||||
|
-`ifdef PERFORMANCE_MONITORING
|
||||||
|
+// `endif
|
||||||
|
+// `ifdef PERFORMANCE_MONITORING
|
||||||
|
Array #(Reg #(EventsL1D)) perf_events <- mkDRegOR (3, unpack (0));
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
|
||||||
|
// do flush: start when all misses resolve
|
||||||
|
Bool noMiss = all(\== (False) , readVReg(pendValid_noMiss));
|
||||||
|
@@ -257,11 +257,11 @@ module mkDTlb#(
|
||||||
|
flushRqToPQ.enq(?);
|
||||||
|
waitFlushP <= True;
|
||||||
|
if(verbose) $display("[DTLB] flush begin");
|
||||||
|
-`ifdef PERFORMANCE_MONITORING
|
||||||
|
+// `ifdef PERFORMANCE_MONITORING
|
||||||
|
EventsL1D ev = unpack(0);
|
||||||
|
ev.evt_TLB_FLUSH = 1;
|
||||||
|
perf_events[2] <= ev;
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
endrule
|
||||||
|
|
||||||
|
rule doFinishFlush(needFlush && waitFlushP);
|
||||||
|
@@ -357,7 +357,7 @@ module mkDTlb#(
|
||||||
|
|
||||||
|
// perf: miss
|
||||||
|
let lat <- latTimer.done(idx);
|
||||||
|
-`ifdef PERF_COUNT
|
||||||
|
+// `ifdef PERF_COUNT
|
||||||
|
if(doStats) begin
|
||||||
|
if(isValid(respForOtherReq)) begin
|
||||||
|
missPeerLat.incr(zeroExtend(lat));
|
||||||
|
@@ -368,13 +368,13 @@ module mkDTlb#(
|
||||||
|
missParentCnt.incr(1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-`endif
|
||||||
|
-`ifdef PERFORMANCE_MONITORING
|
||||||
|
+// `endif
|
||||||
|
+// `ifdef PERFORMANCE_MONITORING
|
||||||
|
EventsL1D ev = unpack(0);
|
||||||
|
ev.evt_TLB_MISS_LAT = saturating_truncate(lat);
|
||||||
|
ev.evt_TLB_MISS = 1;
|
||||||
|
perf_events[0] <= ev;
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
// conflict with wrong spec
|
||||||
|
wrongSpec_doPRs_conflict.wset(?);
|
||||||
|
endrule
|
||||||
|
@@ -508,12 +508,12 @@ module mkDTlb#(
|
||||||
|
$display("[DTLB] req (hit): idx %d; ", idx, fshow(r),
|
||||||
|
"; ", fshow(trans_result));
|
||||||
|
end
|
||||||
|
-`ifdef PERF_COUNT
|
||||||
|
+// `ifdef PERF_COUNT
|
||||||
|
// perf: hit under miss
|
||||||
|
if(doStats && readVReg(pendWait) != replicate(None)) begin
|
||||||
|
hitUnderMissCnt.incr(1);
|
||||||
|
end
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
// page fault
|
||||||
|
@@ -565,17 +565,17 @@ module mkDTlb#(
|
||||||
|
if(verbose) $display("DTLB %m req (bare): ", fshow(r));
|
||||||
|
end
|
||||||
|
|
||||||
|
-`ifdef PERF_COUNT
|
||||||
|
+// `ifdef PERF_COUNT
|
||||||
|
// perf: access
|
||||||
|
if(doStats) begin
|
||||||
|
accessCnt.incr(1);
|
||||||
|
end
|
||||||
|
-`endif
|
||||||
|
-`ifdef PERFORMANCE_MONITORING
|
||||||
|
+// `endif
|
||||||
|
+// `ifdef PERFORMANCE_MONITORING
|
||||||
|
EventsL1D ev = unpack(0);
|
||||||
|
ev.evt_TLB = 1;
|
||||||
|
perf_events[1] <= ev;
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
// conflict with wrong spec
|
||||||
|
wrongSpec_procReq_conflict.wset(?);
|
||||||
|
endmethod
|
||||||
|
@@ -632,11 +632,11 @@ module mkDTlb#(
|
||||||
|
|
||||||
|
interface Perf perf;
|
||||||
|
method Action setStatus(Bool stats);
|
||||||
|
-`ifdef PERF_COUNT
|
||||||
|
+// `ifdef PERF_COUNT
|
||||||
|
doStats <= stats;
|
||||||
|
-`else
|
||||||
|
- noAction;
|
||||||
|
-`endif
|
||||||
|
+// `else
|
||||||
|
+// noAction;
|
||||||
|
+// `endif
|
||||||
|
endmethod
|
||||||
|
|
||||||
|
method Action req(L1TlbPerfType r);
|
||||||
|
@@ -644,27 +644,27 @@ module mkDTlb#(
|
||||||
|
endmethod
|
||||||
|
|
||||||
|
method ActionValue#(PerfResp#(L1TlbPerfType)) resp;
|
||||||
|
-`ifdef PERF_COUNT
|
||||||
|
+// `ifdef PERF_COUNT
|
||||||
|
perfRespQ.deq;
|
||||||
|
return perfRespQ.first;
|
||||||
|
-`else
|
||||||
|
- perfReqQ.deq;
|
||||||
|
- return PerfResp {
|
||||||
|
- pType: perfReqQ.first,
|
||||||
|
- data: 0
|
||||||
|
- };
|
||||||
|
-`endif
|
||||||
|
+// `else
|
||||||
|
+// perfReqQ.deq;
|
||||||
|
+// return PerfResp {
|
||||||
|
+// pType: perfReqQ.first,
|
||||||
|
+// data: 0
|
||||||
|
+// };
|
||||||
|
+// `endif
|
||||||
|
endmethod
|
||||||
|
|
||||||
|
method Bool respValid;
|
||||||
|
-`ifdef PERF_COUNT
|
||||||
|
+// `ifdef PERF_COUNT
|
||||||
|
return perfRespQ.notEmpty;
|
||||||
|
-`else
|
||||||
|
- return perfReqQ.notEmpty;
|
||||||
|
-`endif
|
||||||
|
+// `else
|
||||||
|
+// return perfReqQ.notEmpty;
|
||||||
|
+// `endif
|
||||||
|
endmethod
|
||||||
|
endinterface
|
||||||
|
-`ifdef PERFORMANCE_MONITORING
|
||||||
|
+// `ifdef PERFORMANCE_MONITORING
|
||||||
|
method EventsL1D events = perf_events[0];
|
||||||
|
-`endif
|
||||||
|
+// `endif
|
||||||
|
endmodule
|
||||||
@@ -50,12 +50,12 @@ import Cntrs::*;
|
|||||||
import SafeCounter::*;
|
import SafeCounter::*;
|
||||||
import CacheUtils::*;
|
import CacheUtils::*;
|
||||||
import LatencyTimer::*;
|
import LatencyTimer::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import CCTypes::*;
|
import CCTypes::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// currently blocking
|
// currently blocking
|
||||||
typedef `L1_TLB_SIZE ITlbSize;
|
typedef `L1_TLB_SIZE ITlbSize;
|
||||||
@@ -92,9 +92,9 @@ interface ITlb;
|
|||||||
|
|
||||||
// performance
|
// performance
|
||||||
interface Perf#(L1TlbPerfType) perf;
|
interface Perf#(L1TlbPerfType) perf;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1I events;
|
method EventsL1I events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
typedef FullAssocTlb#(ITlbSize) ITlbArray;
|
typedef FullAssocTlb#(ITlbSize) ITlbArray;
|
||||||
@@ -134,7 +134,7 @@ module mkITlb(ITlb::ITlb);
|
|||||||
// perf counters
|
// perf counters
|
||||||
LatencyTimer#(2, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
|
LatencyTimer#(2, 12) latTimer <- mkLatencyTimer; // max latency: 4K cycles
|
||||||
Fifo#(1, L1TlbPerfType) perfReqQ <- mkCFFifo;
|
Fifo#(1, L1TlbPerfType) perfReqQ <- mkCFFifo;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Fifo#(1, PerfResp#(L1TlbPerfType)) perfRespQ <- mkCFFifo;
|
Fifo#(1, PerfResp#(L1TlbPerfType)) perfRespQ <- mkCFFifo;
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
Count#(Data) accessCnt <- mkCount(0);
|
Count#(Data) accessCnt <- mkCount(0);
|
||||||
@@ -154,10 +154,10 @@ module mkITlb(ITlb::ITlb);
|
|||||||
data: d
|
data: d
|
||||||
});
|
});
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsL1I)) perf_events <- mkDRegOR (3, unpack (0));
|
Array #(Reg #(EventsL1I)) perf_events <- mkDRegOR (3, unpack (0));
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// do flush: only start when all misses resolve
|
// do flush: only start when all misses resolve
|
||||||
rule doStartFlush(needFlush && !waitFlushP && !isValid(miss));
|
rule doStartFlush(needFlush && !waitFlushP && !isValid(miss));
|
||||||
@@ -166,11 +166,11 @@ module mkITlb(ITlb::ITlb);
|
|||||||
flushRqToPQ.enq(?);
|
flushRqToPQ.enq(?);
|
||||||
waitFlushP <= True;
|
waitFlushP <= True;
|
||||||
if(verbose) $display("ITLB %m: flush begin");
|
if(verbose) $display("ITLB %m: flush begin");
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1I ev = unpack(0);
|
EventsL1I ev = unpack(0);
|
||||||
ev.evt_TLB_FLUSH = 1;
|
ev.evt_TLB_FLUSH = 1;
|
||||||
perf_events[2] <= ev;
|
perf_events[2] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule doFinishFlush(needFlush && waitFlushP && !isValid(miss));
|
rule doFinishFlush(needFlush && waitFlushP && !isValid(miss));
|
||||||
@@ -225,17 +225,17 @@ module mkITlb(ITlb::ITlb);
|
|||||||
miss <= Invalid;
|
miss <= Invalid;
|
||||||
|
|
||||||
let lat <- latTimer.done(0);
|
let lat <- latTimer.done(0);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
missLat.incr(zeroExtend(lat));
|
missLat.incr(zeroExtend(lat));
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1I ev = unpack(0);
|
EventsL1I ev = unpack(0);
|
||||||
ev.evt_TLB_MISS_LAT = saturating_truncate(lat);
|
ev.evt_TLB_MISS_LAT = saturating_truncate(lat);
|
||||||
ev.evt_TLB_MISS = 1;
|
ev.evt_TLB_MISS = 1;
|
||||||
perf_events[0] <= ev;
|
perf_events[0] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// we check no pending req only at Commit when Fetch1 stage has been
|
// we check no pending req only at Commit when Fetch1 stage has been
|
||||||
@@ -345,11 +345,11 @@ module mkITlb(ITlb::ITlb);
|
|||||||
$display("ITLB %m req (miss): ", fshow(vaddr));
|
$display("ITLB %m req (miss): ", fshow(vaddr));
|
||||||
end
|
end
|
||||||
latTimer.start(0);
|
latTimer.start(0);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
missCnt.incr(1);
|
missCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
@@ -358,16 +358,16 @@ module mkITlb(ITlb::ITlb);
|
|||||||
if (verbose) $display("ITLB %m req (bare): ", fshow(vaddr));
|
if (verbose) $display("ITLB %m req (bare): ", fshow(vaddr));
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
accessCnt.incr(1);
|
accessCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsL1I ev = unpack(0);
|
EventsL1I ev = unpack(0);
|
||||||
ev.evt_TLB = 1;
|
ev.evt_TLB = 1;
|
||||||
perf_events[1] <= ev;
|
perf_events[1] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
interface Get response = toGet(hitQ);
|
interface Get response = toGet(hitQ);
|
||||||
@@ -384,11 +384,11 @@ module mkITlb(ITlb::ITlb);
|
|||||||
|
|
||||||
interface Perf perf;
|
interface Perf perf;
|
||||||
method Action setStatus(Bool stats);
|
method Action setStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Action req(L1TlbPerfType r);
|
method Action req(L1TlbPerfType r);
|
||||||
@@ -396,27 +396,27 @@ module mkITlb(ITlb::ITlb);
|
|||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method ActionValue#(PerfResp#(L1TlbPerfType)) resp;
|
method ActionValue#(PerfResp#(L1TlbPerfType)) resp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
return PerfResp {
|
// return PerfResp {
|
||||||
pType: perfReqQ.first,
|
// pType: perfReqQ.first,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Bool respValid;
|
method Bool respValid;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
return perfRespQ.notEmpty;
|
return perfRespQ.notEmpty;
|
||||||
`else
|
// `else
|
||||||
return perfReqQ.notEmpty;
|
// return perfReqQ.notEmpty;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1I events = perf_events[0];
|
method EventsL1I events = perf_events[0];
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ import SelfInvL1Pipe::*;
|
|||||||
import SelfInvL1Bank::*;
|
import SelfInvL1Bank::*;
|
||||||
import SelfInvIPipe::*;
|
import SelfInvIPipe::*;
|
||||||
import SelfInvIBank::*;
|
import SelfInvIBank::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
export L1Num;
|
export L1Num;
|
||||||
export LgL1WayNum;
|
export LgL1WayNum;
|
||||||
@@ -188,9 +188,9 @@ interface DCoCache;
|
|||||||
method Bool flush_done;
|
method Bool flush_done;
|
||||||
method Action resetLinkAddr;
|
method Action resetLinkAddr;
|
||||||
interface Perf#(L1DPerfType) perf;
|
interface Perf#(L1DPerfType) perf;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1D events;
|
method EventsL1D events;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
interface ChildCacheToParent#(L1Way, void) to_parent;
|
interface ChildCacheToParent#(L1Way, void) to_parent;
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ module mkDCoCache#(L1ProcResp#(DProcReqId) procResp)(DCoCache);
|
|||||||
|
|
||||||
// perf counters
|
// perf counters
|
||||||
Fifo#(1, L1DPerfType) perfReqQ <- mkCFFifo;
|
Fifo#(1, L1DPerfType) perfReqQ <- mkCFFifo;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Fifo#(1, PerfResp#(L1DPerfType)) perfRespQ <- mkCFFifo;
|
Fifo#(1, PerfResp#(L1DPerfType)) perfRespQ <- mkCFFifo;
|
||||||
|
|
||||||
rule doPerf;
|
rule doPerf;
|
||||||
@@ -219,7 +219,7 @@ module mkDCoCache#(L1ProcResp#(DProcReqId) procResp)(DCoCache);
|
|||||||
data: d
|
data: d
|
||||||
});
|
});
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef SELF_INV_CACHE
|
`ifdef SELF_INV_CACHE
|
||||||
// change the reconcile ifc to a FIFO ifc to avoid scheduling issues
|
// change the reconcile ifc to a FIFO ifc to avoid scheduling issues
|
||||||
@@ -261,28 +261,28 @@ module mkDCoCache#(L1ProcResp#(DProcReqId) procResp)(DCoCache);
|
|||||||
perfReqQ.enq(r);
|
perfReqQ.enq(r);
|
||||||
endmethod
|
endmethod
|
||||||
method ActionValue#(PerfResp#(L1DPerfType)) resp;
|
method ActionValue#(PerfResp#(L1DPerfType)) resp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
return PerfResp {
|
// return PerfResp {
|
||||||
pType: perfReqQ.first,
|
// pType: perfReqQ.first,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
method Bool respValid;
|
method Bool respValid;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
return perfRespQ.notEmpty;
|
return perfRespQ.notEmpty;
|
||||||
`else
|
// `else
|
||||||
return perfReqQ.notEmpty;
|
// return perfReqQ.notEmpty;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1D events = cache.events;
|
method EventsL1D events = cache.events;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
interface to_parent = cache.to_parent;
|
interface to_parent = cache.to_parent;
|
||||||
|
|
||||||
@@ -382,9 +382,9 @@ interface ICoCache;
|
|||||||
method Action flush;
|
method Action flush;
|
||||||
method Bool flush_done;
|
method Bool flush_done;
|
||||||
interface Perf#(L1IPerfType) perf;
|
interface Perf#(L1IPerfType) perf;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1I events;
|
method EventsL1I events;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
interface ChildCacheToParent#(L1Way, void) to_parent;
|
interface ChildCacheToParent#(L1Way, void) to_parent;
|
||||||
|
|
||||||
@@ -407,7 +407,7 @@ module mkICoCache(ICoCache);
|
|||||||
let cache <- mkIBankWrapper;
|
let cache <- mkIBankWrapper;
|
||||||
|
|
||||||
Fifo#(1, L1IPerfType) perfReqQ <- mkCFFifo;
|
Fifo#(1, L1IPerfType) perfReqQ <- mkCFFifo;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Fifo#(1, PerfResp#(L1IPerfType)) perfRespQ <- mkCFFifo;
|
Fifo#(1, PerfResp#(L1IPerfType)) perfRespQ <- mkCFFifo;
|
||||||
|
|
||||||
rule doPerf;
|
rule doPerf;
|
||||||
@@ -418,7 +418,7 @@ module mkICoCache(ICoCache);
|
|||||||
data: d
|
data: d
|
||||||
});
|
});
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
interface Server to_proc;
|
interface Server to_proc;
|
||||||
interface request = cache.to_proc.req;
|
interface request = cache.to_proc.req;
|
||||||
@@ -436,28 +436,28 @@ module mkICoCache(ICoCache);
|
|||||||
perfReqQ.enq(r);
|
perfReqQ.enq(r);
|
||||||
endmethod
|
endmethod
|
||||||
method ActionValue#(PerfResp#(L1IPerfType)) resp;
|
method ActionValue#(PerfResp#(L1IPerfType)) resp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
return PerfResp {
|
// return PerfResp {
|
||||||
pType: perfReqQ.first,
|
// pType: perfReqQ.first,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
method Bool respValid;
|
method Bool respValid;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
return perfRespQ.notEmpty;
|
return perfRespQ.notEmpty;
|
||||||
`else
|
// `else
|
||||||
return perfReqQ.notEmpty;
|
// return perfReqQ.notEmpty;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsL1I events = cache.events;
|
method EventsL1I events = cache.events;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
interface to_parent = cache.to_parent;
|
interface to_parent = cache.to_parent;
|
||||||
|
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ import SetAssocTlb::*;
|
|||||||
import L2SetAssocTlb::*;
|
import L2SetAssocTlb::*;
|
||||||
import TranslationCache::*;
|
import TranslationCache::*;
|
||||||
import LatencyTimer::*;
|
import LatencyTimer::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import PerformanceMonitor::*;
|
import PerformanceMonitor::*;
|
||||||
import CCTypes::*;
|
import CCTypes::*;
|
||||||
import BlueUtils::*;
|
import BlueUtils::*;
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// for SV39 only
|
// for SV39 only
|
||||||
|
|
||||||
@@ -120,9 +120,9 @@ interface L2Tlb;
|
|||||||
|
|
||||||
// performace
|
// performace
|
||||||
interface Perf#(L2TlbPerfType) perf;
|
interface Perf#(L2TlbPerfType) perf;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsLL events;
|
method EventsLL events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
typedef FullAssocTlb#(`L2_TLB_HUGE_SIZE) L2FullAssocTlb;
|
typedef FullAssocTlb#(`L2_TLB_HUGE_SIZE) L2FullAssocTlb;
|
||||||
@@ -220,7 +220,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
|
|
||||||
// FIFO for perf req
|
// FIFO for perf req
|
||||||
Fifo#(1, L2TlbPerfType) perfReqQ <- mkCFFifo;
|
Fifo#(1, L2TlbPerfType) perfReqQ <- mkCFFifo;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Fifo#(1, PerfResp#(L2TlbPerfType)) perfRespQ <- mkCFFifo;
|
Fifo#(1, PerfResp#(L2TlbPerfType)) perfRespQ <- mkCFFifo;
|
||||||
Reg#(Bool) doStats <- mkConfigReg(False);
|
Reg#(Bool) doStats <- mkConfigReg(False);
|
||||||
Count#(Data) instMissCnt <- mkCount(0);
|
Count#(Data) instMissCnt <- mkCount(0);
|
||||||
@@ -285,10 +285,10 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
data: d
|
data: d
|
||||||
});
|
});
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
Array #(Reg #(EventsLL)) perf_events <- mkDRegOR (3, unpack (0));
|
Array #(Reg #(EventsLL)) perf_events <- mkDRegOR (3, unpack (0));
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// when flushing is true, since both I and D TLBs have finished flush and
|
// when flushing is true, since both I and D TLBs have finished flush and
|
||||||
// is waiting for L2 to flush, all I/D TLB req must have been responded.
|
// is waiting for L2 to flush, all I/D TLB req must have been responded.
|
||||||
@@ -301,11 +301,11 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
// check no req
|
// check no req
|
||||||
doAssert(!rqFromCQ.notEmpty, "cannot have new req");
|
doAssert(!rqFromCQ.notEmpty, "cannot have new req");
|
||||||
doAssert(readVEhr(0, pendValid) == replicate(False), "cannot have pending req");
|
doAssert(readVEhr(0, pendValid) == replicate(False), "cannot have pending req");
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsLL ev = unpack(0);
|
EventsLL ev = unpack(0);
|
||||||
ev.evt_TLB_FLUSH = 1;
|
ev.evt_TLB_FLUSH = 1;
|
||||||
perf_events[2] <= ev;
|
perf_events[2] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
rule doWaitFlush(flushing && waitFlushDone && tlb4KB.flush_done && transCache.flush_done);
|
rule doWaitFlush(flushing && waitFlushDone && tlb4KB.flush_done && transCache.flush_done);
|
||||||
@@ -377,7 +377,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
});
|
});
|
||||||
// req is done
|
// req is done
|
||||||
pendValid_tlbResp[idx] <= False;
|
pendValid_tlbResp[idx] <= False;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: hit under miss
|
// perf: hit under miss
|
||||||
function Bool otherMiss(L2TlbReqIdx i);
|
function Bool otherMiss(L2TlbReqIdx i);
|
||||||
return pendValid_tlbResp[i] && pendWait_tlbResp[i] != None && i != idx;
|
return pendValid_tlbResp[i] && pendWait_tlbResp[i] != None && i != idx;
|
||||||
@@ -386,7 +386,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
if(any(otherMiss, idxVec)) begin
|
if(any(otherMiss, idxVec)) begin
|
||||||
hitUnderMissCnt.incr(1);
|
hitUnderMissCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -410,7 +410,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
pageHit(entry);
|
pageHit(entry);
|
||||||
tlb4KB.deqResp(Invalid); // just deq 4KB array
|
tlb4KB.deqResp(Invalid); // just deq 4KB array
|
||||||
tlbMG.updateRepByHit(respMG.index); // update replacement in MG array
|
tlbMG.updateRepByHit(respMG.index); // update replacement in MG array
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(cRq.child == I) begin
|
if(cRq.child == I) begin
|
||||||
instHugePageHitCnt.incr(1);
|
instHugePageHitCnt.incr(1);
|
||||||
@@ -419,12 +419,12 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
dataHugePageHitCnt.incr(1);
|
dataHugePageHitCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsLL ev = unpack(0);
|
EventsLL ev = unpack(0);
|
||||||
ev.evt_TLB = 1;
|
ev.evt_TLB = 1;
|
||||||
perf_events[1] <= ev;
|
perf_events[1] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else if(resp4KB.hit) begin
|
else if(resp4KB.hit) begin
|
||||||
// hit on 4KB page
|
// hit on 4KB page
|
||||||
@@ -433,11 +433,11 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
pageHit(entry);
|
pageHit(entry);
|
||||||
// update 4KB array replacement, no need to touch MG array
|
// update 4KB array replacement, no need to touch MG array
|
||||||
tlb4KB.deqResp(Valid (resp4KB.way));
|
tlb4KB.deqResp(Valid (resp4KB.way));
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsLL ev = unpack(0);
|
EventsLL ev = unpack(0);
|
||||||
ev.evt_TLB = 1;
|
ev.evt_TLB = 1;
|
||||||
perf_events[1] <= ev;
|
perf_events[1] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
// miss, deq resp
|
// miss, deq resp
|
||||||
@@ -446,7 +446,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
transCache.req(cRq.vpn, vm_info.asid);
|
transCache.req(cRq.vpn, vm_info.asid);
|
||||||
transCacheReqQ.enq(idx);
|
transCacheReqQ.enq(idx);
|
||||||
// perf: TLB miss
|
// perf: TLB miss
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
latTimer.start(idx);
|
latTimer.start(idx);
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(cRq.child == I) begin
|
if(cRq.child == I) begin
|
||||||
@@ -456,12 +456,12 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
dataMissCnt.incr(1);
|
dataMissCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsLL ev = unpack(0);
|
EventsLL ev = unpack(0);
|
||||||
ev.evt_TLB_MISS = 1;
|
ev.evt_TLB_MISS = 1;
|
||||||
perf_events[0] <= ev;
|
perf_events[0] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
@@ -517,11 +517,11 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
// duplicate req
|
// duplicate req
|
||||||
pendWait_transCacheResp[idx] <= WaitPeer (i);
|
pendWait_transCacheResp[idx] <= WaitPeer (i);
|
||||||
doAssert(pendValid_transCacheResp[i], "peer must be valid");
|
doAssert(pendValid_transCacheResp[i], "peer must be valid");
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
peerSavedMemReqCnt.incr(1);
|
peerSavedMemReqCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
// no one has requested before, req memory
|
// no one has requested before, req memory
|
||||||
@@ -536,7 +536,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
fshow(vm_info), "; ", fshow(resp), "; ",
|
fshow(vm_info), "; ", fshow(resp), "; ",
|
||||||
fshow(level), "; ", fshow(pteAddr));
|
fshow(level), "; ", fshow(pteAddr));
|
||||||
end
|
end
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: saved page walks
|
// perf: saved page walks
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
Data saved = zeroExtend(maxPageWalkLevel - level);
|
Data saved = zeroExtend(maxPageWalkLevel - level);
|
||||||
@@ -545,9 +545,10 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
dataSavedPageWalks.incr(saved);
|
dataSavedPageWalks.incr(saved);
|
||||||
|
$display("L2TlbdataSavedPageWalks = %0d", dataPageWalks);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
// page walk is preempted by tlb resp rule and trans cache resp rule, i.e.,
|
// page walk is preempted by tlb resp rule and trans cache resp rule, i.e.,
|
||||||
@@ -588,10 +589,10 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
// req is done
|
// req is done
|
||||||
pendValid_pageWalk[idx] <= False;
|
pendValid_pageWalk[idx] <= False;
|
||||||
pendWait_pageWalk[idx] <= None;
|
pendWait_pageWalk[idx] <= None;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// incr miss latency
|
// incr miss latency
|
||||||
incrMissLat(cRq.child, idx);
|
incrMissLat(cRq.child, idx);
|
||||||
`endif
|
// `endif
|
||||||
endaction
|
endaction
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -656,11 +657,11 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
// walk
|
// walk
|
||||||
if(otherReqSamePTE(idx, newPTEAddr, readVReg(pendWait_pageWalk)) matches tagged Valid .i) begin
|
if(otherReqSamePTE(idx, newPTEAddr, readVReg(pendWait_pageWalk)) matches tagged Valid .i) begin
|
||||||
pendWait_pageWalk[idx] <= WaitPeer (i);
|
pendWait_pageWalk[idx] <= WaitPeer (i);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
peerSavedMemReqCnt.incr(1);
|
peerSavedMemReqCnt.incr(1);
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
memReqQ.enq(TlbMemReq {
|
memReqQ.enq(TlbMemReq {
|
||||||
@@ -695,17 +696,17 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
child: cRq.child,
|
child: cRq.child,
|
||||||
entry: Valid (entry)
|
entry: Valid (entry)
|
||||||
});
|
});
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
// page table walks are counted as accesses
|
// page table walks are counted as accesses
|
||||||
EventsLL ev = unpack(0);
|
EventsLL ev = unpack(0);
|
||||||
ev.evt_TLB = 1;
|
ev.evt_TLB = 1;
|
||||||
perf_events[1] <= ev;
|
perf_events[1] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
// update TLB array
|
// update TLB array
|
||||||
if(entry.level > 0) begin
|
if(entry.level > 0) begin
|
||||||
// add to mega/giga page tlb
|
// add to mega/giga page tlb
|
||||||
tlbMG.addEntry(entry);
|
tlbMG.addEntry(entry);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(cRq.child == I) begin
|
if(cRq.child == I) begin
|
||||||
instHugePageMissCnt.incr(1);
|
instHugePageMissCnt.incr(1);
|
||||||
@@ -714,12 +715,12 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
dataHugePageMissCnt.incr(1);
|
dataHugePageMissCnt.incr(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
EventsLL ev = unpack(0);
|
EventsLL ev = unpack(0);
|
||||||
ev.evt_TLB_MISS = 1;
|
ev.evt_TLB_MISS = 1;
|
||||||
perf_events[0] <= ev;
|
perf_events[0] <= ev;
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
// 4KB page, add to 4KB TLB
|
// 4KB page, add to 4KB TLB
|
||||||
@@ -728,13 +729,13 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
// req is done
|
// req is done
|
||||||
pendValid_pageWalk[idx] <= False;
|
pendValid_pageWalk[idx] <= False;
|
||||||
pendWait_pageWalk[idx] <= None;
|
pendWait_pageWalk[idx] <= None;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// incr miss latency
|
// incr miss latency
|
||||||
incrMissLat(cRq.child, idx);
|
incrMissLat(cRq.child, idx);
|
||||||
`endif
|
// `endif
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
// perf: page walk done once
|
// perf: page walk done once
|
||||||
if(doStats) begin
|
if(doStats) begin
|
||||||
if(cRq.child == I) begin
|
if(cRq.child == I) begin
|
||||||
@@ -742,9 +743,10 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
dataPageWalks.incr(1);
|
dataPageWalks.incr(1);
|
||||||
|
$display("L2TlbdataPageWalks = %0d", dataPageWalks);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
// `endif
|
||||||
endrule
|
endrule
|
||||||
|
|
||||||
method Action updateVMInfo(VMInfo vmI, VMInfo vmD); //if(!isValid(pendReq));
|
method Action updateVMInfo(VMInfo vmI, VMInfo vmD); //if(!isValid(pendReq));
|
||||||
@@ -776,11 +778,11 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
|
|
||||||
interface Perf perf;
|
interface Perf perf;
|
||||||
method Action setStatus(Bool stats);
|
method Action setStatus(Bool stats);
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
doStats <= stats;
|
doStats <= stats;
|
||||||
`else
|
// `else
|
||||||
noAction;
|
// noAction;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Action req(L2TlbPerfType r);
|
method Action req(L2TlbPerfType r);
|
||||||
@@ -788,27 +790,27 @@ module mkL2Tlb(L2Tlb::L2Tlb);
|
|||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method ActionValue#(PerfResp#(L2TlbPerfType)) resp;
|
method ActionValue#(PerfResp#(L2TlbPerfType)) resp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
return PerfResp {
|
// return PerfResp {
|
||||||
pType: perfReqQ.first,
|
// pType: perfReqQ.first,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
|
|
||||||
method Bool respValid;
|
method Bool respValid;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
return perfRespQ.notEmpty;
|
return perfRespQ.notEmpty;
|
||||||
`else
|
// `else
|
||||||
return perfReqQ.notEmpty;
|
// return perfReqQ.notEmpty;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsLL events = perf_events[0];
|
method EventsLL events = perf_events[0];
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ import SelfInvLLBank::*;
|
|||||||
import L1CoCache::*;
|
import L1CoCache::*;
|
||||||
import LLCDmaConnect::*;
|
import LLCDmaConnect::*;
|
||||||
import Performance::*;
|
import Performance::*;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
import StatCounters::*;
|
import StatCounters::*;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
// Last-Level
|
// Last-Level
|
||||||
|
|
||||||
@@ -257,9 +257,9 @@ interface LLCache;
|
|||||||
interface Get#(LLCStuck) cRqStuck;
|
interface Get#(LLCStuck) cRqStuck;
|
||||||
// performance
|
// performance
|
||||||
interface Perf#(LLCPerfType) perf;
|
interface Perf#(LLCPerfType) perf;
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsLL events;
|
method EventsLL events;
|
||||||
`endif
|
// `endif
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
`ifdef SECURITY
|
`ifdef SECURITY
|
||||||
@@ -315,7 +315,7 @@ module mkLLCache(LLCache);
|
|||||||
|
|
||||||
// perf counters
|
// perf counters
|
||||||
Fifo#(1, LLCPerfType) perfReqQ <- mkCFFifo;
|
Fifo#(1, LLCPerfType) perfReqQ <- mkCFFifo;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
Fifo#(1, PerfResp#(LLCPerfType)) perfRespQ <- mkCFFifo;
|
Fifo#(1, PerfResp#(LLCPerfType)) perfRespQ <- mkCFFifo;
|
||||||
|
|
||||||
rule doPerf;
|
rule doPerf;
|
||||||
@@ -326,7 +326,7 @@ module mkLLCache(LLCache);
|
|||||||
data: d
|
data: d
|
||||||
});
|
});
|
||||||
endrule
|
endrule
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
`ifdef SECURITY
|
`ifdef SECURITY
|
||||||
`ifndef DISABLE_SECURE_LLC
|
`ifndef DISABLE_SECURE_LLC
|
||||||
@@ -449,26 +449,26 @@ module mkLLCache(LLCache);
|
|||||||
perfReqQ.enq(r);
|
perfReqQ.enq(r);
|
||||||
endmethod
|
endmethod
|
||||||
method ActionValue#(PerfResp#(LLCPerfType)) resp;
|
method ActionValue#(PerfResp#(LLCPerfType)) resp;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
perfRespQ.deq;
|
perfRespQ.deq;
|
||||||
return perfRespQ.first;
|
return perfRespQ.first;
|
||||||
`else
|
// `else
|
||||||
perfReqQ.deq;
|
// perfReqQ.deq;
|
||||||
return PerfResp {
|
// return PerfResp {
|
||||||
pType: perfReqQ.first,
|
// pType: perfReqQ.first,
|
||||||
data: 0
|
// data: 0
|
||||||
};
|
// };
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
method Bool respValid;
|
method Bool respValid;
|
||||||
`ifdef PERF_COUNT
|
// `ifdef PERF_COUNT
|
||||||
return perfRespQ.notEmpty;
|
return perfRespQ.notEmpty;
|
||||||
`else
|
// `else
|
||||||
return perfReqQ.notEmpty;
|
// return perfReqQ.notEmpty;
|
||||||
`endif
|
// `endif
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
method EventsLL events = cache.events;
|
method EventsLL events = cache.events;
|
||||||
`endif
|
// `endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -1070,11 +1070,11 @@ endfunction
|
|||||||
|
|
||||||
function x addPc(x cap, Bit#(12) inc) provisos (Add#(f, 12, c), CHERICap::CHERICap#(x, a, b, c, d, e)) = setAddrUnsafe(cap, getAddr(cap) + signExtend(inc));
|
function x addPc(x cap, Bit#(12) inc) provisos (Add#(f, 12, c), CHERICap::CHERICap#(x, a, b, c, d, e)) = setAddrUnsafe(cap, getAddr(cap) + signExtend(inc));
|
||||||
|
|
||||||
`ifdef PERFORMANCE_MONITORING
|
// `ifdef PERFORMANCE_MONITORING
|
||||||
typedef 8 Report_Width;
|
typedef 8 Report_Width;
|
||||||
typedef 64 Counter_Width;
|
typedef 64 Counter_Width;
|
||||||
typedef 29 No_Of_Ctrs;
|
typedef 29 No_Of_Ctrs;
|
||||||
`endif
|
// `endif
|
||||||
|
|
||||||
function Bit#(outWidth) hash(Bit#(inWidth) in)
|
function Bit#(outWidth) hash(Bit#(inWidth) in)
|
||||||
provisos(Add#(a__, inWidth, TMul#(TDiv#(inWidth, outWidth), outWidth)),
|
provisos(Add#(a__, inWidth, TMul#(TDiv#(inWidth, outWidth), outWidth)),
|
||||||
|
|||||||
Reference in New Issue
Block a user