6 Commits

Author SHA1 Message Date
2227b084a1 saving current changes 2026-05-20 16:52:35 +01:00
263efec2a5 fixed working version of matrix multiplcation 2026-04-20 13:35:58 +01:00
12ce7e7ade ported over barnes 2026-04-16 13:51:31 +01:00
b14264eb45 ported matrix mul and richards 2026-04-15 17:27:30 +01:00
365a35e61b ported memaccess 2026-04-09 17:03:39 +01:00
746dce577f updated sub module 2026-04-09 14:06:18 +01:00
30 changed files with 2290 additions and 40 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,482 @@
/*
* File: barnes_hut.c
* --------------
* Implements the Barnes Hut algorithm for n-body
* simulation with galaxy-like initial conditions.
* Uses OpenGl and GLUT for graphics. Written by:
* Joel Backsell, Kim Torberntsson & Alexander Bilock.
* Source: https://github.com/KimTorberntsson/Barnes-Hut/blob/master/barnes_hut.c
*/
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <math.h>
// #include <time.h>
// #include <GLUT/glut.h>
#include "barnes_hut.h"
// #include "graphics.h"
void free(void *ptr);
void *malloc(size_t size);
//Some constants and global variables
int N = 10;
const double L = 1, W = 1, dt = 1e-3, alpha = 0.25, V = 50, epsilon = 1e-1, grav = 0.04; //grav should be 100/N
double *x, *y, *u, *v, *force_x, *force_y, *mass;
struct node_t *root;
// -------- Modified by Akilan ----------
double my_sqrt(double x) {
if (x <= 0) return 0;
double guess = x;
for (int i = 0; i < 10; i++) {
guess = 0.5 * (guess + x / guess);
}
return guess;
}
#define 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;
}
double my_cos(double x) {
x = wrap_angle(x);
double x2 = x * x;
return 1
- x2 / 2
+ (x2 * x2) / 24
- (x2 * x2 * x2) / 720;
}
// --------------------------------------
// -------- Modified by Akilan ----------
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
}
// ---------------------------------------
/*
* Function for producing a random number between two double values
*/
double frand(double xmin, double xmax) {
return xmin + (xmax-xmin)*rand_test()/RAND_MAX;
}
/*
* Prints the time between two clocks in seconds
*/
// void print_time(clock_t s, clock_t e)
// {
// printf("Time: %f seconds\n", (double)(e-s)/CLOCKS_PER_SEC);
// }
/*
* This function is called every time GLUT refreshes the display.
*/
// void display(void) {
// //Do a time step
// time_step();
// //Draw points
// drawPoints(x, y, N);
// }
/*
* Updates the positions of the particles of a time step.
*/
void time_step(void) {
//Allocate memory for root
root = malloc(sizeof(struct node_t));
set_node(root);
root->min_x = 0; root->max_x = 1; root->min_y = 0; root->max_y = 1;
//Put particles in tree
for(int i = 0; i < N; i++) {
put_particle_in_tree(i, root);
}
//Calculate mass and center of mass
calculate_mass(root);
calculate_center_of_mass_x(root);
calculate_center_of_mass_y(root);
//Calculate forces
update_forces();
//Update velocities and positions
for(int i = 0; i < N; i++) {
double ax = force_x[i]/mass[i];
double ay = force_y[i]/mass[i];
u[i] += ax*dt;
v[i] += ay*dt;
x[i] += u[i]*dt;
y[i] += v[i]*dt;
/* This of course doesn't make any sense physically,
* but makes sure that the particles stay within the
* bounds. Normally the particles won't leave the
* area anyway.
*/
bounce(&x[i], &y[i], &u[i], &v[i]);
}
//Free memory
free_node(root);
free(root);
}
/*
* If a particle moves beyond any of the boundaries then bounce it back
*/
void bounce(double *x, double *y, double *u, double *v) {
double W = 1.0f, H = 1.0f;
if(*x > W) {
*x = 2*W - *x;
*u = -*u;
}
if(*x < 0) {
*x = -*x;
*u = -*u;
}
if(*y > H) {
*y = 2*H - *y;
*v = -*v;
}
if(*y < 0) {
*y = -*y;
*v = -*v;
}
}
/*
* Puts a particle recursively in the Barnes Hut quad-tree.
*/
void put_particle_in_tree(int new_particle, struct node_t *node) {
//If no particle is assigned to the node
if(!node->has_particle) {
node->particle = new_particle;
node->has_particle = 1;
}
//If the node has no children
else if(!node->has_children) {
//Allocate and initiate children
node->children = malloc(4*sizeof(struct node_t));
for(int i = 0; i < 4; i++) {
set_node(&node->children[i]);
}
//Set boundaries for the children
node->children[0].min_x = node->min_x; node->children[0].max_x = (node->min_x + node->max_x)/2;
node->children[0].min_y = node->min_y; node->children[0].max_y = (node->min_y + node->max_y)/2;
node->children[1].min_x = (node->min_x + node->max_x)/2; node->children[1].max_x = node->max_x;
node->children[1].min_y = node->min_y; node->children[1].max_y = (node->min_y + node->max_y)/2;
node->children[2].min_x = node->min_x; node->children[2].max_x = (node->min_x + node->max_x)/2;
node->children[2].min_y = (node->min_y + node->max_y)/2; node->children[2].max_y = node->max_y;
node->children[3].min_x = (node->min_x + node->max_x)/2; node->children[3].max_x = node->max_x;
node->children[3].min_y = (node->min_y + node->max_y)/2; node->children[3].max_y = node->max_y;
//Put old particle into the appropriate child
place_particle(node->particle, node);
//Put new particle into the appropriate child
place_particle(new_particle, node);
//It now has children
node->has_children = 1;
}
//Add the new particle to the appropriate children
else {
//Put new particle into the appropriate child
place_particle(new_particle, node);
}
}
/*
* Puts a particle in the right child of a node with children.
*/
void place_particle(int particle, struct node_t *node) {
if(x[particle] <= (node->min_x + node->max_x)/2 && y[particle] <= (node->min_y + node->max_y)/2) {
put_particle_in_tree(particle, &node->children[0]);
} else if(x[particle] > (node->min_x + node->max_x)/2 && y[particle] < (node->min_y + node->max_y)/2) {
put_particle_in_tree(particle, &node->children[1]);
} else if(x[particle] < (node->min_x + node->max_x)/2 && y[particle] > (node->min_y + node->max_y)/2) {
put_particle_in_tree(particle, &node->children[2]);
} else {
put_particle_in_tree(particle, &node->children[3]);
}
}
/*
* Sets initial values for a new node
*/
void set_node(struct node_t *node) {
node->has_particle = 0;
node->has_children = 0;
}
/*
* Frees memory for a node and its children recursively.
*/
void free_node(struct node_t *node){
if(node->has_children){
free_node(&node->children[0]);
free_node(&node->children[1]);
free_node(&node->children[2]);
free_node(&node->children[3]);
free(node->children);
}
}
/*
* Displays the boundaries of the tree using OpenGL and GLUT.
* Used for debugging purposes.
*/
// void display_tree(struct node_t *node) {
// drawRect(node->min_x, node->max_x, node->min_y, node->max_y);
// if(node->has_children == 1) {
// for(int i = 0; i < 4; i++) {
// display_tree(&node->children[i]);
// }
// }
// }
/*
* Calculates the total mass for the node. It recursively updates the mass
* of itself and all of its children.
*/
double calculate_mass(struct node_t *node) {
if(!node->has_particle) {
node->total_mass = 0;
} else if(!node->has_children) {
node->total_mass = mass[node->particle];
} else {
node->total_mass = 0;
for(int i = 0; i < 4; i++) {
node->total_mass += calculate_mass(&node->children[i]);
}
}
return node->total_mass;
}
/*
* Calculates the x-position of the centre of mass for the
* node. It recursively updates the position of itself and
* all of its children.
*/
double calculate_center_of_mass_x(struct node_t *node) {
if(!node->has_children) {
node->c_x = x[node->particle];
} else {
node->c_x = 0;
double m_tot = 0;
for(int i = 0; i < 4; i++) {
if(node->children[i].has_particle) {
node->c_x += node->children[i].total_mass*calculate_center_of_mass_x(&node->children[i]);
m_tot += node->children[i].total_mass;
}
}
node->c_x /= m_tot;
}
return node->c_x;
}
/*
* Calculates the y-position of the centre of mass for the
* node. It recursively updates the position of itself and
* all of its children.
*/
double calculate_center_of_mass_y(struct node_t *node) {
if(!node->has_children) {
node->c_y = y[node->particle];
} else {
node->c_y = 0;
double m_tot = 0;
for(int i = 0; i < 4; i++) {
if(node->children[i].has_particle) {
node->c_y += node->children[i].total_mass*calculate_center_of_mass_y(&node->children[i]);
m_tot += node->children[i].total_mass;
}
}
node->c_y /= m_tot;
}
return node->c_y;
}
/*
* Calculates the forces in a time step of all particles in
* the simulation using the Barnes Hut quad tree.
*/
void update_forces(){
for(int i = 0; i < N; i++) {
force_x[i] = 0;
force_y[i] = 0;
update_forces_help(i, root);
}
}
/*
* Help function for calculating the forces recursively
* using the Barnes Hut quad tree.
*/
void update_forces_help(int particle, struct node_t *node) {
//The node is a leaf node with a particle and not the particle itself
if(!node->has_children && node->has_particle && node->particle != particle) {
double r = my_sqrt((x[particle] - node->c_x)*(x[particle] - node->c_x) + (y[particle] - node->c_y)*(y[particle] - node->c_y));
calculate_force(particle, node, r);
}
//The node has children
else if(node->has_children) {
//Calculate r and theta
double r = my_sqrt((x[particle] - node->c_x)*(x[particle] - node->c_x) + (y[particle] - node->c_y)*(y[particle] - node->c_y));
double theta = (node->max_x - node->min_x)/r;
/* If the distance to the node's centre of mass is far enough, calculate the force,
* otherwise traverse further down the tree
*/
if(theta < 0.5){
calculate_force(particle, node, r);
} else {
update_forces_help(particle, &node->children[0]);
update_forces_help(particle, &node->children[1]);
update_forces_help(particle, &node->children[2]);
update_forces_help(particle, &node->children[3]);
}
}
}
/*
* Calculates and updates the force of a particle from a node.
*/
void calculate_force(int particle, struct node_t *node, double r){
double temp = -grav*mass[particle]*node->total_mass/((r + epsilon)*(r + epsilon)*(r + epsilon));
force_x[particle] += (x[particle] - node->c_x)*temp;
force_y[particle] += (y[particle] - node->c_y)*temp;
}
/*
* Main function.
*/
int main(void) {
//The first arguments sets if the graphics should be used
// int graphics = 1;
// if (argc > 1) {
// graphics = atoi(argv[1]);
// }
//The second argument sets the number of time steps
int time_steps = 3;
// if (argc > 2) {
// time_steps = atoi(argv[2]);
// }
//Initiate memory for the vectors
x = (double *)malloc(N*sizeof(double));
y = (double *)malloc(N*sizeof(double));
u = (double *)malloc(N*sizeof(double));
v = (double *)malloc(N*sizeof(double));
// -------- Modified by Akilan ----------
force_x = (double *)malloc(N*sizeof(double));
force_y = (double *)malloc(N*sizeof(double));
// --------------------------------------
mass = (double *)malloc(N*sizeof(double));
//Set the initial values
// for(int i = 0; i < N; i++) {
// mass[i] = 1;
// double R = frand(0, L/4);
// double theta = frand(0, 2*M_PI);
// x[i] = L/2 + R*my_cos(theta);
// y[i] = W/2 + alpha*R*my_sin(theta);
// double R_prim = my_sqrt(pow(x[i] - L/2, 2) + pow(y[i] - W/2, 2));
// u[i] = -V*R_prim*my_sin(theta);
// v[i] = V*R_prim*my_cos(theta);
// }
for (int i = 0; i < N; i++) {
mass[i] = 1;
double R = frand(0, L/4);
double theta = frand(0, 2*PI);
double c = my_cos(theta);
double s = my_sin(theta);
x[i] = L/2 + R * c;
y[i] = W/2 + alpha * R * s;
double dx = x[i] - L/2;
double dy = y[i] - W/2;
double R_prim = my_sqrt(dx*dx + dy*dy);
u[i] = -V * R_prim * s;
v[i] = V * R_prim * c;
}
/* Run the GLUT display function if the graphics mode is on.
* Otherwise just run the simulations without graphics
*/
// if (graphics) {
// // Initialize the graphics routines
// graphicsInit(&argc, argv, display);
// //Used for the display window
// glutMainLoop();
// } else {
//Begin taking time
// long start = clock();
//The main loop
for(int i = 0; i < time_steps; i++) {
time_step();
}
//Stop taking time and print elapsed time
// long stop = clock();
// print_time(start, stop);
// }
//Free memory
free(x);
free(y);
free(u);
free(v);
free(force_x);
free(force_y);
free(mass);
return 0;
}

View File

@@ -0,0 +1,55 @@
/*
* File: barnes_hut.h
* --------------
* Header file for barnes_hut.c
* Written by:
* Joel Backsell, Kim Torberntsson & Alexander Bilock.
*/
#ifndef Barnes_Hut_barnes_hut_h
#define Barnes_Hut_barnes_hut_h
/*
* Struct that represents a node of the Barnes Hut quad tree.
*/
struct node_t {
int particle;
int has_particle;
int has_children;
double min_x, max_x, min_y, max_y, total_mass, c_x, c_y;
struct node_t *children;
};
//Function for producing a random number between two double values.
double frand(double xmin, double xmax);
//Prints the time between two clocks in seconds
// void print_time(clock_t s, clock_t e);
//OpenGL method for displaying the particles
// void display(void);
//Calculates the positions of a time step
// void time_step(void);
//If a particle moves beyond any of the boundaries then bounce it back
void bounce(double *x, double *y, double *u, double *v);
//Functions for handling the placement of particles in the tree
void put_particle_in_tree(int new_particle, struct node_t *node);
void place_particle(int particle, struct node_t *node);
void set_node(struct node_t *node);
void free_node(struct node_t *node);
void display_tree(struct node_t *node);
//Functions for calculating the mass and centre of mass of the tree
double calculate_mass(struct node_t *node);
double calculate_center_of_mass_x(struct node_t *node);
double calculate_center_of_mass_y(struct node_t *node);
//Functions for the force calculations
void update_forces();
void update_forces_help(int particle, struct node_t *node);
void calculate_force(int particle, struct node_t *node, double r);
#endif

View File

@@ -0,0 +1,46 @@
# scp ../../encoding.h home-1:/home/akilan/
# scp ../../entry.S home-1:/home/akilan/
# scp ../../link.ld home-1:/home/akilan/
# scp ../../riscv_test_p.h home-1:/home/akilan/
# scp ../../riscv_test.h home-1:/home/akilan/
# scp ../../string.c home-1:/home/akilan/
# scp ../../vm.c home-1:/home/akilan/
# scp ../../test.S home-1:/home/akilan/
# scp ../../test_macros.h home-1:/home/akilan/
# scp ../../malloc.c home-1:/home/akilan/
# scp ../../test.c home-1:/home/akilan/
scp barnes_hut.c home-1:/home/akilan/
scp barnes_hut.h home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S barnes_hut.c -o testC -lm -lgcc'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,45 @@
scp ../../encoding.h home-1:/home/akilan/
scp ../../entry.S home-1:/home/akilan/
scp ../../link.ld home-1:/home/akilan/
scp ../../riscv_test_p.h home-1:/home/akilan/
scp ../../riscv_test.h home-1:/home/akilan/
scp ../../string.c home-1:/home/akilan/
scp ../../vm.c home-1:/home/akilan/
scp ../../test.S home-1:/home/akilan/
scp ../../test_macros.h home-1:/home/akilan/
scp ../../malloc.c home-1:/home/akilan/
# scp ../../test.c home-1:/home/akilan/
scp glibc.c home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S glibc.c -o testC'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,229 @@
/* Benchmark malloc and free functions.
Copyright (C) 2019-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
// modified by Daan Leijen to fit the bench suite and add lifo/fifo free order.
// #include <pthread.h>
// #include <stdio.h>
// #include <stdlib.h>
// #include <sys/resource.h>
// #include "malloc.h"
// #include <cheriintrin.h>
#include <stdint.h>
#include <stddef.h>
// #define malloc MALLOCCHERI
// #define free FREECHERI
// #include "bench-timing.h"
// #include "json-lib.h"
// void free(void * __capability ptr);
// void * __capability malloc(size_t size);
void* malloc(size_t size);
void free(void *ptr);
/* Benchmark the malloc/free performance of a varying number of blocks of a
given size. This enables performance tracking of the t-cache and fastbins.
It tests 3 different scenarios: single-threaded using main arena,
multi-threaded using thread-arena, and main arena with SINGLE_THREAD_P
false. */
// source: https://github.com/daanx/mimalloc-bench/blob/master/bench/glibc-bench/bench-malloc-thread.c
#define NUM_ITERS 20
#define NUM_ALLOCS 4
#define MAX_ALLOCS 1600
// Daan: disable timing
typedef long timing_t;
#define TIMING_NOW(s)
#define TIMING_DIFF(e,start,stop)
typedef struct
{
size_t iters;
size_t size;
int n;
timing_t elapsed;
} malloc_args;
static void
do_benchmark(malloc_args *args, char **arr)
{
// timing_t start, stop;
size_t iters = args->iters;
size_t size = args->size;
int n = args->n;
// TIMING_NOW (start);
for (int j = 0; j < iters; j++)
{
for (int i = 0; i < n; i++) {
arr[i] = malloc (size);
for(int g = 0; g < size; g++) { arr[i][g] =(char)g; }
}
// free half in fifo order
for (int i = 0; i < n/2; i++) {
free (arr[i]);
arr[i] = NULL;
}
// and the other half in lifo order
for(int i = n-1; i >= n/2; i--) {
free(arr[i]);
arr[i] = NULL;
}
}
// TIMING_NOW (stop);
// TIMING_DIFF (args->elapsed, start, stop);
}
static malloc_args tests[3][NUM_ALLOCS];
static int allocs[NUM_ALLOCS] = { 25, 100, 400, MAX_ALLOCS };
// static void *
// thread_test (void *p)
// {
// char **arr = (char**)p;
// /* Run benchmark multi-threaded. */
// for (int i = 0; i < NUM_ALLOCS; i++)
// do_benchmark (&tests[2][i], arr);
// return p;
// }
void
bench (unsigned long size)
{
size_t iters = NUM_ITERS;
char**arr = (char**)malloc (MAX_ALLOCS * sizeof (void*));
//char * __capability * __capability arr = malloc(MAX_ALLOCS * sizeof(char * __capability));
for (int t = 0; t < 3; t++)
for (int i = 0; i < NUM_ALLOCS; i++)
{
tests[t][i].n = allocs[i];
tests[t][i].size = size;
tests[t][i].iters = iters / allocs[i];
/* Do a quick warmup run. */
if (t == 0)
do_benchmark (&tests[0][i], arr);
}
/* Run benchmark single threaded in main_arena. */
for (int i = 0; i < NUM_ALLOCS; i++)
do_benchmark (&tests[0][i], arr);
/* Run benchmark in a thread_arena. */
// pthread_t t;
// pthread_create (&t, NULL, thread_test, (void*)arr);
// pthread_join (t, NULL);
/* Repeat benchmark in main_arena with SINGLE_THREAD_P == false. */
// for (int i = 0; i < NUM_ALLOCS; i++)
// do_benchmark (&tests[1][i], arr);
free (arr);
arr = NULL;
/*
json_ctx_t json_ctx;
json_init (&json_ctx, 0, stdout);
json_document_begin (&json_ctx);
json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
json_attr_object_begin (&json_ctx, "functions");
json_attr_object_begin (&json_ctx, "malloc");
char s[100];
double iters2 = iters;
json_attr_object_begin (&json_ctx, "");
json_attr_double (&json_ctx, "malloc_block_size", size);
struct rusage usage;
getrusage (RUSAGE_SELF, &usage);
json_attr_double (&json_ctx, "max_rss", usage.ru_maxrss);
for (int i = 0; i < NUM_ALLOCS; i++)
{
sprintf (s, "main_arena_st_allocs_%04d_time", allocs[i]);
json_attr_double (&json_ctx, s, tests[0][i].elapsed / iters2);
}
for (int i = 0; i < NUM_ALLOCS; i++)
{
sprintf (s, "main_arena_mt_allocs_%04d_time", allocs[i]);
json_attr_double (&json_ctx, s, tests[1][i].elapsed / iters2);
}
for (int i = 0; i < NUM_ALLOCS; i++)
{
sprintf (s, "thread_arena__allocs_%04d_time", allocs[i]);
json_attr_double (&json_ctx, s, tests[2][i].elapsed / iters2);
}
json_attr_object_end (&json_ctx);
json_attr_object_end (&json_ctx);
json_attr_object_end (&json_ctx);
json_document_end (&json_ctx);
*/
}
// static void usage (const char *name)
// {
// fprintf (stderr, "%s: <alloc_size>\n", name);
// exit (1);
// }
int main (void)
{
// INITREGULARALLOC();
long size = 3;
// if (argc == 2)
// size = strtol (argv[1], NULL, 0);
// if (argc > 2 || size <= 0)
// usage (argv[0]);
bench (size);
// bench (2*size);
// bench (4*size);
// bench (8*size);
// bench (16*size);
// bench (32*size);
return 0;
}

View File

@@ -0,0 +1,45 @@
scp ../../encoding.h home-1:/home/akilan/
scp ../../entry.S home-1:/home/akilan/
scp ../../link.ld home-1:/home/akilan/
scp ../../riscv_test_p.h home-1:/home/akilan/
scp ../../riscv_test.h home-1:/home/akilan/
scp ../../string.c home-1:/home/akilan/
scp ../../vm.c home-1:/home/akilan/
scp ../../test.S home-1:/home/akilan/
scp ../../test_macros.h home-1:/home/akilan/
scp ../../malloc.c home-1:/home/akilan/
# scp ../../test.c home-1:/home/akilan/
scp matrixmul.c home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S matrixmul.c -o testC'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,205 @@
// 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>
void free(void *ptr);
void *malloc(size_t size);
/* Initializes vector or matrix, sequentially, with indices. */
void init_seq(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] = 2.0;
}
}
}
// 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. */
double *transpose(const double *m, const unsigned n_rows_m, const unsigned n_cols_m, double *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. */
double *dot_simple(const double *a, const unsigned n_rows_a, const unsigned n_cols_a,\
const double *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);
}
double *c = malloc(n_rows_a * n_cols_b * sizeof(*c));
if (c == NULL) {
// printf("Couldn't allocate memory!\n");
// system("pause");
// exit(-1);
}
for (size_t i = 0; i < n_rows_a; i++) {
for (size_t k = 0; k < n_cols_b; k++) {
double sum = 0.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. */
double *dot(const double *a, const unsigned n_rows_a, const unsigned n_cols_a, \
const double *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);
}
double *bt = malloc(n_rows_b * n_cols_b * sizeof(*b));
double *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++) {
double sum = 0.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 */
double t0, t1;
const unsigned scale = 2;
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;
double *a = malloc(n_rows_a * n_cols_a * sizeof(*a));
double *b = malloc(n_rows_b * n_cols_b * sizeof(*b));
double *c = NULL;
double *d = NULL;
if (!a || !b) {
// printf("Couldn't allocate memory!\n");
// 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);
// 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

View File

@@ -0,0 +1,45 @@
scp ../../encoding.h home-1:/home/akilan/
scp ../../entry.S home-1:/home/akilan/
scp ../../link.ld home-1:/home/akilan/
scp ../../riscv_test_p.h home-1:/home/akilan/
scp ../../riscv_test.h home-1:/home/akilan/
scp ../../string.c home-1:/home/akilan/
scp ../../vm.c home-1:/home/akilan/
scp ../../test.S home-1:/home/akilan/
scp ../../test_macros.h home-1:/home/akilan/
scp ../../malloc.c home-1:/home/akilan/
# scp ../../test.c home-1:/home/akilan/
scp memaccess.c home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S memaccess.c -o testC'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,364 @@
/*
memaccesstest.c
Author Alex Bordei at bigstep
All rights reserved.
*/
// source: https://github.com/bigstepinc/memaccesstest/tree/master
// #include <stdio.h>
// #include <cheriintrin.h>
#include <stddef.h>
#include <stdint.h>
// #include <stdlib.h>
// #include <pthread.h>
// #include "config.h"
// #ifndef __MACH__
// #include <time.h>
// #else
// #include <mach/mach_time.h>
// #endif
// #include "malloc.h"
// #define malloc MALLOCCHERI
// #define free FREECHERI
#define NPAD 7
#define MIN_WSS sizeof(struct l)
#define MAX_WSS 32
void free(void *ptr);
void *malloc(size_t size);
// struct l{
// struct l *n;
// struct l *p;
// long int pad[NPAD-1];
// };
struct l{
struct l *n;
struct l *p;
long int pad[NPAD-1];
};
// uint64_t rand64()
// {
// // Combin 4 parts of low 16-bit of each rand()
// uint64_t R0 = (uint64_t)random() << 48;
// uint64_t R1 = (uint64_t)random() << 48 >> 16;
// uint64_t R2 = (uint64_t)random() << 48 >> 32;
// uint64_t R3 = (uint64_t)random() << 48 >> 48;
// return R0 | R1 | R2 | R3;
// };
#ifdef DEBUG
// void print_ll_lin(struct l *root,unsigned long working_set_size)
// {
// struct l *current=root->n;
// unsigned long count;
// printf("0");
// count=0;
// while(current!=root)
// {
// // printf("->%ld",current-root);
// current=current->n;
// count++;
// if(count>working_set_size/sizeof(struct l))
// {
// // printf("Error:cycle!");
// break;
// }
// }
// // printf("\n");
// }
// void print_ll_lin_back(struct l *root,unsigned long working_set_size)
// {
// struct l *current=root->p;
// unsigned long count;
// printf("0");
// count=0;
// while(current!=root)
// {
// // printf("->%ld",current-root);
// current=current->p;
// count++;
// if(count>working_set_size/sizeof(struct l))
// {
// // printf("Error:cycle!");
// break;
// }
// }
// printf("\n");
// }
// void print_ll(struct l *root,unsigned long working_set_size)
// {
// unsigned long i;
// for(i=0;i<(working_set_size/sizeof(struct l));i++)
// printf("DEBUG: %ld<-%ld->%ld\n",(root+i)->p-root,i,((root+i)->n)-root);
// printf("DEBUG ");
// print_ll_lin(root, working_set_size);
// printf("DEBUG ");
// print_ll_lin_back(root, working_set_size);
// }
#endif
// void build_sequencial_ll(struct l * root, long working_set_size)
void build_sequencial_ll(struct l *root, long working_set_size)
{
unsigned long i;
struct l *current;
for(i=0;i<(working_set_size/sizeof(struct l));i++)
{
current=root+i;
if(i==(working_set_size/sizeof(struct l)-1))
current->n=root;
else
current->n=current+1;
if(i==0)
current->p=root+working_set_size/sizeof(struct l)-1;
else
current->p=current-1;
}
}
// void build_random_ll(struct l *root, long working_set_size)
// {
// unsigned long i;
// struct l *a;
// struct l *b;
// struct l *oldan;
// struct l *oldbn;
// struct l *oldap;
// struct l *oldbp;
// unsigned long rnd;
// unsigned long tries;
// build_sequencial_ll(root, working_set_size);
// //construct the array of elements
// //link the list to the next element in the array
// for(i=1;i<(working_set_size/sizeof(struct l)-1);i++)
// {
// a=(root+i);
// b=a;
// tries=5;
// while((b==a || b==root) && tries)
// {
// rnd=rand64() % (working_set_size/sizeof(struct l)-1);
// b=root+rnd;
// tries--;
// }
// if(!tries)
// continue;
// oldan=a->n; //a->n is lost along the way
// oldbn=b->n; //b->n is lost along the way
// oldap=a->p; //a->p is lost along the way
// oldbp=b->p; //b->p is lost along the way
// a->p->n=b;
// b->p->n=a;
// if(b!=oldan)
// {
// b->n=oldan;
// oldan->p=b;
// }
// else
// {
// b->n=a;
// a->p=b;
// }
// if(a!=oldbn)
// {
// a->n=oldbn;
// oldbn->p=a;
// }
// else
// {
// a->n=b;
// b->p=a;
// }
// if(b!=oldap)
// b->p=oldap;
// else
// b->p=a;
// if(a!=oldbp)
// a->p=oldbp;
// else
// a->p=b;
// #ifdef DEBUG
// printf("DEBUG: Round i=%ld\n",i);
// printf("DEBUG: A=%ld B=%ld\n",a-root,b-root);
// print_ll(root, working_set_size);
// #endif
// }
// }
struct thread_start_data
{
struct l *root;
unsigned long working_set_size;
int thread_index;
};
void * walk(void *param)
{
struct thread_start_data *data=param;
unsigned long start,end;
struct l *root=data->root;
// struct l* current=root->n;
struct l *current = root->n;
// #ifdef __MACH__
// start=mach_absolute_time();
// #else
// struct timespec ts;
// clock_gettime(CLOCK_MONOTONIC_RAW,&ts);
// start=ts.tv_nsec;
// #endif
/////////////////////////////////////
//traverse the linked list
while(current!=root)
{
// #ifdef ADDTEST
// current->pad[0]+=current->n->pad[0];
// #endif
// #ifdef INCTEST
// current->pad[0]++;
// #endif
current=current->n;
}
/////////////////////////////////////
// #ifdef __MACH__
// end=mach_absolute_time();
// #else
// clock_gettime(CLOCK_MONOTONIC_RAW,&ts);
// end=ts.tv_nsec;
// #endif
// printf("%d,%ld,%ld,%ld\n",data->thread_index,data->working_set_size, end-start, data->working_set_size/sizeof(struct l));
// free(data);
return NULL;
}
int main(void)
{
// clock_t tic = clock();
// INITREGULARALLOC();
//#ifdef DEBUG
// printf("DEBUG:sizeof(struct l)=%ld\n",sizeof(struct l));
// #endif
struct l *root;
unsigned long working_set_size;
int i;
// struct thread_start_data *tdata;
struct thread_start_data *tdata;
// pthread_t threads[NTHREADS];
root=malloc(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)
{
// #ifdef DEBUG
// printf("DEBUG:Working set size=%ld elements=%ld\n",working_set_size,working_set_size/sizeof(struct l));
// #endif
// clock_t toc = clock();
// printf("Elapsed build get here before ll: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);
// #ifdef RANDOM_LIST
// build_random_ll(root, working_set_size);
// #else
// clock_t tic1 = clock();
build_sequencial_ll(root, working_set_size);
// build_sequencial_ll(root, working_set_size);
// clock_t toc1 = clock();
// printf("Elapsed build ll: %f seconds\n", (double)(toc1 - tic1) / CLOCKS_PER_SEC);
// #endif
// #if NTHREADS>0
// for(i=0;i<NTHREADS;i++)
// {
// tdata= malloc(sizeof(struct thread_start_data));
// tdata->thread_index=i;
// tdata->root=root;
// tdata->working_set_size=working_set_size;
// pthread_create(&threads[i], NULL, walk, (void*) tdata);
// }
// for(i=0;i<NTHREADS;i++)
// pthread_join(threads[i],NULL);
// #else
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 < 64; i++) {
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 < 64; i++) {
// walk(tdata);
// }
// clock_t toc2 = clock();
// printf("Elapsed build walk: %f seconds\n", (double)(toc2 - tic2) / CLOCKS_PER_SEC);
// #endif
}
// printf("-----------------------------------------------");
free(root);
root = NULL;
return 0;
}

View File

@@ -0,0 +1,46 @@
scp ../../encoding.h home-1:/home/akilan/
scp ../../entry.S home-1:/home/akilan/
scp ../../link.ld home-1:/home/akilan/
scp ../../riscv_test_p.h home-1:/home/akilan/
scp ../../riscv_test.h home-1:/home/akilan/
scp ../../string.c home-1:/home/akilan/
scp ../../vm.c home-1:/home/akilan/
scp ../../test.S home-1:/home/akilan/
scp ../../test_macros.h home-1:/home/akilan/
scp ../../malloc.c home-1:/home/akilan/
# scp ../../test.c home-1:/home/akilan/
scp richards.c home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S richards.c -o testC'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,455 @@
// 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* malloc(size_t);
void 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 *)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 *)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(void)
{
//INITREGULARALLOC();
int iterations = 2;
int warmup = 0;
int inner_iterations = 2;
// parse_argv(argc, argv, &iterations, &warmup, &inner_iterations);
// while(1);
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--;
}
}

View File

@@ -15,5 +15,5 @@ SECTIONS
_end = .;
__malloc_start = .;
. = . + 512;
. = . + 0x10000;
}

View File

@@ -4,41 +4,41 @@
void* malloc(size_t size);
int main(void)
{
char* a = malloc(50);
char* b = malloc(160);
// asm volatile("fence rw, rw"); // make sure store completes
// volatile uint64_t* marker = (uint64_t*)0x80001000;
// *marker = 0xCAFEBABECAFED00D; // UNIQUE SIGNATURE
int main(void) {
// char *a = malloc(30);
// char *b = malloc(16);
// if (!a || !b) return;
// // if (!a || !b) return -1;
a[0] = 'A';
// // a[1] = 'C';
// // b[0] = 'B';
// a[0] = 'A';
// a[1] = 'C';
// b[0] = 'B';
// // This will fault (out-of-bounds)
// // a[20] = 'X';
if (a[0] != 'A') {
while (1);
}
// // char* a = malloc(100);
// // char* b = malloc(200);
// if (a[1] != 'C') {
// while (1);
// }
// a[0] = 'A'; // triggers page fault if unmapped
// b[19] = 'Z';
// if (b[0] != 'B') {
// while (1);
// }
// // free(b);
// // b = NULL;
// // if (b[0] == 'B') {
// // while (1);
// // }
// char *c = malloc(16);
// // if (c[0] != 'B') {
// // while (1);
// // }
// for (int i = 0; i < 1000; i++) {
// a[i * 64] = i; // each write new cache line
// }
// while(1);
return 0;
}

View File

@@ -333,7 +333,7 @@ void vm_boot(uintptr_t test_addr)
trapframe_t tf;
memset(&tf, 0, sizeof(tf));
tf.epc = test_addr - DRAM_BASE;
// call test function
// call C benchmark function
main();
pop_tf(&tf);
}

Binary file not shown.

92
analysis/graph.py Normal file
View File

@@ -0,0 +1,92 @@
import matplotlib.pyplot as plt
import numpy as np
performance_data = {
"Mem": {
"regular": {"CPU_cycles": 33940, "L1_DTLB_access": 13202, "L1_DTLB_miss": 36, "L2_DTLB_miss": 10},
"modified": {"CPU_cycles": 2457, "L1_DTLB_access": 151, "L1_DTLB_miss": 0, "L2_DTLB_miss": 0},
},
"Test_C": {
"regular": {"CPU_cycles": 34040, "L1_DTLB_access": 13284, "L1_DTLB_miss": 36, "L2_DTLB_miss": 10},
"modified": {"CPU_cycles": 2789, "L1_DTLB_access": 396, "L1_DTLB_miss": 0, "L2_DTLB_miss": 0},
},
"Glibc": {
"regular": {"CPU_cycles": 36053, "L1_DTLB_access": 14027, "L1_DTLB_miss": 36, "L2_DTLB_miss": 10},
"modified": {"CPU_cycles": 4219, "L1_DTLB_access": 783, "L1_DTLB_miss": 0, "L2_DTLB_miss": 0},
},
"Richards": {
"regular": {"CPU_cycles": 37808, "L1_DTLB_access": 14363, "L1_DTLB_miss": 10, "L2_DTLB_miss": 6},
"modified": {"CPU_cycles": 4433, "L1_DTLB_access": 874, "L1_DTLB_miss": 0, "L2_DTLB_miss": 0},
},
"Matrix_mul": {
"regular": {"CPU_cycles": 42383, "L1_DTLB_access": 17020, "L1_DTLB_miss": 14, "L2_DTLB_miss": 10},
"modified": {"CPU_cycles": 12149, "L1_DTLB_access": 4411, "L1_DTLB_miss": 0, "L2_DTLB_miss": 0},
}
}
def compute_percent_diff(regular, modified):
out = {}
for k in regular:
if k in modified and regular[k] != 0:
out[k] = ((regular[k] - modified[k]) / regular[k]) * 100
elif k in modified and regular[k] == 0 and modified[k] == 0:
out[k] = 0.0
elif k in modified and regular[k] == 0 and modified[k] != 0:
out[k] = -100.0
return out
for t, d in performance_data.items():
d["percent_diff"] = compute_percent_diff(d["regular"], d["modified"])
tests = list(performance_data.keys())
metrics = ["CPU_cycles", "L1_DTLB_access", "L1_DTLB_miss", "L2_DTLB_miss"]
# 1. Summary plot: Percent Improvement for all metrics grouped by test
x = np.arange(len(tests))
width = 0.2
fig, ax = plt.subplots(figsize=(12, 7))
for i, metric in enumerate(metrics):
values = [performance_data[t]["percent_diff"].get(metric, 0) for t in tests]
offset = (i - len(metrics)/2 + 0.5) * width
ax.bar(x + offset, values, width, label=metric.replace('_', ' ').title())
ax.set_ylabel('Percent Improvement (%)')
ax.set_title('Percent Improvement (Regular -> Modified) by Test and Metric')
ax.set_xticks(x)
ax.set_xticklabels(tests)
ax.legend()
ax.set_ylim(0, 110)
ax.grid(axis='y', linestyle='--', alpha=0.7)
fig.tight_layout()
plt.savefig('percent_improvement_summary.png')
# 2. Individual metric plots: Regular vs Modified grouped by test
y_label_map = {
"CPU_cycles": "Cycles",
"L1_DTLB_access": "Access Count",
"L1_DTLB_miss": "Miss Count",
"L2_DTLB_miss": "Miss Count"
}
for metric in metrics:
fig, ax = plt.subplots(figsize=(10, 6))
reg_vals = [performance_data[t]["regular"][metric] for t in tests]
mod_vals = [performance_data[t]["modified"][metric] for t in tests]
x_local = np.arange(len(tests))
w = 0.35
ax.bar(x_local - w/2, reg_vals, w, label='Regular', color='steelblue')
ax.bar(x_local + w/2, mod_vals, w, label='Modified', color='salmon')
# Setting dynamic y-label
ax.set_ylabel(y_label_map.get(metric, metric.replace('_', ' ').title()))
ax.set_title(f'Comparison: {metric.replace("_", " ").title()}')
ax.set_xticks(x_local)
ax.set_xticklabels(tests)
ax.legend()
ax.grid(axis='y', linestyle='--', alpha=0.7)
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig(f'grouped_comparison_{metric}.png')

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

145
analysis/perf_data.py Normal file
View File

@@ -0,0 +1,145 @@
def compute_percent_diff(regular, modified):
percent_diff = {}
for key in regular:
if key in modified and regular[key] != 0:
percent_diff[key] = ((regular[key] - modified[key]) / regular[key]) * 100
return percent_diff
def compute_percent_diff_mod_vs_pte(modified, after_pte):
percent_diff = {}
for key in ["CPU_cycles", "L1_DTLB_access"]:
if key in modified and key in after_pte and modified[key] != 0:
percent_diff[key] = ((modified[key] - after_pte[key]) / modified[key]) * 100
return percent_diff
performance_data = {
"Mem": {
"regular": {
"CPU_cycles": 33940,
"L1_DTLB_access": 13202,
"L1_DTLB_miss": 36,
"L2_DTLB_miss": 10,
},
"modified": {
"CPU_cycles": 2457,
"L1_DTLB_access": 151,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
"after_PTE_setup": {
"CPU_cycles": 531,
"L1_DTLB_access": 25,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
},
"Test_C": {
"regular": {
"CPU_cycles": 34040,
"L1_DTLB_access": 13284,
"L1_DTLB_miss": 36,
"L2_DTLB_miss": 10,
},
"modified": {
"CPU_cycles": 2789,
"L1_DTLB_access": 396,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
"after_PTE_setup": {
"CPU_cycles": 631,
"L1_DTLB_access": 107,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
},
"Glibc": {
"regular": {
"CPU_cycles": 36053,
"L1_DTLB_access": 14027,
"L1_DTLB_miss": 36,
"L2_DTLB_miss": 10,
},
"modified": {
"CPU_cycles": 4219,
"L1_DTLB_access": 783,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
"after_PTE_setup": {
"CPU_cycles": 2644,
"L1_DTLB_access": 850,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
},
"Setup": {
"regular": {
"CPU_cycles": 33409,
"L1_DTLB_access": 13177,
"L1_DTLB_miss": 36,
"L2_DTLB_miss": 10,
}
},
"Richards": {
"regular": {
"CPU_cycles": 37808,
"L1_DTLB_access": 14363,
"L1_DTLB_miss": 10,
"L2_DTLB_miss": 6,
},
"modified": {
"CPU_cycles": 4433,
"L1_DTLB_access": 874,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
"after_PTE_setup": {
"CPU_cycles": 4399,
"L1_DTLB_access": 1186,
},
},
"Matrix_mul": {
"regular": {
"CPU_cycles": 42383,
"L1_DTLB_access": 17020,
"L1_DTLB_miss": 14,
"L2_DTLB_miss": 10,
},
"modified": {
"CPU_cycles": 12149,
"L1_DTLB_access": 4411,
"L1_DTLB_miss": 0,
"L2_DTLB_miss": 0,
},
"after_PTE_setup": {
"CPU_cycles": 8974,
"L1_DTLB_access": 3843,
},
}
}
# Add percentage differences
for test, data in performance_data.items():
if "regular" in data and "modified" in data:
data["percent_diff"] = compute_percent_diff(
data["regular"], data["modified"]
)
# Add modified vs after_PTE_setup percentage differences
for test, data in performance_data.items():
if "modified" in data and "after_PTE_setup" in data:
data["mod_vs_pte_percent_diff"] = compute_percent_diff_mod_vs_pte(
data["modified"], data["after_PTE_setup"]
)
# Example usage:
print(performance_data["Mem"]["percent_diff"])
print(performance_data["Mem"]["mod_vs_pte_percent_diff"])

BIN
builds/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
*.txt

0
richards.txt Normal file
View File

0
richards_reg_10.txt Normal file
View File

View File

@@ -545,6 +545,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
end
else begin
dataSavedPageWalks.incr(saved);
$display("L2TlbdataSavedPageWalks = %0d", dataPageWalks);
end
end
// `endif
@@ -742,6 +743,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
end
else begin
dataPageWalks.incr(1);
$display("L2TlbdataPageWalks = %0d", dataPageWalks);
end
end
// `endif

View File

@@ -1,12 +1,5 @@
Let me know if this message works well on behalf of all of us.
Hi Jan,
This is a very small gesture from Jose, Mathews, Yukang and Akilan. We have transferred 200 pounds equally contributed by all of us. As you are moving in and settling into your new place, we hope this can help you and Samantha cover certain expenses like buying furniture or for your very efficient interrail travel pass in the near future.
We will definetely miss the german embassy in Slatefort. Happy new year in advance from all of us!
Regards,
Jose, Mathews, Yukang and Akilan
(Your UK representation of transportation
reform)
- [ ] Benchmarks to port over:
- [ ] Barnes (3)
- [ ] Matrix multiplication (2)
- [ ] Richards (1)