saving current changes
This commit is contained in:
@@ -20,10 +20,10 @@ void free(void * __capability ptr);
|
|||||||
void * __capability malloc(size_t size);
|
void * __capability malloc(size_t size);
|
||||||
|
|
||||||
/* Initializes vector or matrix, sequentially, with indices. */
|
/* Initializes vector or matrix, sequentially, with indices. */
|
||||||
void init_seq(double * __capability a, const unsigned n_rows_a, const unsigned n_cols_a) {
|
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 i = 0; i < n_rows_a; i++) {
|
||||||
for (size_t j = 0; j < n_cols_a; j++) {
|
for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
a[i*n_cols_a + j] = 2.0;
|
a[i*n_cols_a + j] = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ void init_seq(double * __capability a, const unsigned n_rows_a, const unsigned n
|
|||||||
It's also flat in memory, i.e., 1-D, but it should be looked at as a transpose
|
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.
|
of m, meaning, n_rows_t == n_cols_m, and n_cols_t == n_rows_m.
|
||||||
The original matrix m stays intact. */
|
The original matrix m stays intact. */
|
||||||
double __capability * transpose(const double __capability *m, const unsigned n_rows_m, const unsigned n_cols_m, double __capability *t) {
|
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 i = 0; i < n_rows_m; i++) {
|
||||||
for (size_t j = 0; j < n_cols_m; j++) {
|
for (size_t j = 0; j < n_cols_m; j++) {
|
||||||
t[j*n_rows_m + i] = m[i*n_cols_m + j];
|
t[j*n_rows_m + i] = m[i*n_cols_m + j];
|
||||||
@@ -63,25 +63,27 @@ double __capability * transpose(const double __capability *m, const unsigned n_r
|
|||||||
/* Dot product of two arrays, or matrix product
|
/* Dot product of two arrays, or matrix product
|
||||||
* Allocates and returns an array.
|
* Allocates and returns an array.
|
||||||
* This variant doesn't transpose matrix b, and it's a lot slower. */
|
* This variant doesn't transpose matrix b, and it's a lot slower. */
|
||||||
double * __capability dot_simple(const double * __capability a, const unsigned n_rows_a, const unsigned n_cols_a,\
|
int * __capability dot_simple(const int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a,\
|
||||||
const double * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
const int * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
||||||
|
|
||||||
if (n_cols_a != n_rows_b) {
|
if (n_cols_a != n_rows_b) {
|
||||||
// printf("#columns A must be equal to #rows B!\n");
|
// printf("#columns A must be equal to #rows B!\n");
|
||||||
// system("pause");
|
// system("pause");
|
||||||
// exit(-2);
|
// exit(-2);
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
double *__capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
int * __capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
||||||
if (c == NULL) {
|
if (c == NULL) {
|
||||||
// printf("Couldn't allocate memory!\n");
|
// printf("Couldn't allocate memory!\n");
|
||||||
// system("pause");
|
// system("pause");
|
||||||
// exit(-1);
|
// exit(-1);
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < n_rows_a; i++) {
|
for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
for (size_t k = 0; k < n_cols_b; k++) {
|
for (size_t k = 0; k < n_cols_b; k++) {
|
||||||
double sum = 0.0;
|
int sum = 0;
|
||||||
for (size_t j = 0; j < n_cols_a; j++) {
|
for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
sum += a[i*n_cols_a + j] * b[j*n_cols_b + k];
|
sum += a[i*n_cols_a + j] * b[j*n_cols_b + k];
|
||||||
}
|
}
|
||||||
@@ -95,8 +97,8 @@ double * __capability dot_simple(const double * __capability a, const unsigned n
|
|||||||
/* Dot product of two arrays, or matrix product
|
/* Dot product of two arrays, or matrix product
|
||||||
* Allocates and returns an array.
|
* Allocates and returns an array.
|
||||||
* This variant transposes matrix b, and it's a lot faster. */
|
* This variant transposes matrix b, and it's a lot faster. */
|
||||||
double * __capability dot(const double __capability *a, const unsigned n_rows_a, const unsigned n_cols_a, \
|
int * __capability dot(const int * __capability a, const unsigned n_rows_a, const unsigned n_cols_a, \
|
||||||
const double * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
const int * __capability b, const unsigned n_rows_b, const unsigned n_cols_b) {
|
||||||
|
|
||||||
if (n_cols_a != n_rows_b) {
|
if (n_cols_a != n_rows_b) {
|
||||||
// printf("#columns A must be equal to #rows B!\n");
|
// printf("#columns A must be equal to #rows B!\n");
|
||||||
@@ -104,9 +106,9 @@ double * __capability dot(const double __capability *a, const unsigned n_rows_a
|
|||||||
// exit(-2);
|
// exit(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
double * __capability bt = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
int * __capability bt = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
||||||
|
|
||||||
double * __capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
int * __capability c = malloc(n_rows_a * n_cols_b * sizeof(*c));
|
||||||
|
|
||||||
if ((c == NULL) || (bt == NULL)) {
|
if ((c == NULL) || (bt == NULL)) {
|
||||||
// printf("Couldn't allocate memory!\n");
|
// printf("Couldn't allocate memory!\n");
|
||||||
@@ -118,7 +120,7 @@ double * __capability dot(const double __capability *a, const unsigned n_rows_a
|
|||||||
|
|
||||||
for (size_t i = 0; i < n_rows_a; i++) {
|
for (size_t i = 0; i < n_rows_a; i++) {
|
||||||
for (size_t k = 0; k < n_cols_b; k++) {
|
for (size_t k = 0; k < n_cols_b; k++) {
|
||||||
double sum = 0.0;
|
int sum = 0;
|
||||||
for (size_t j = 0; j < n_cols_a; j++) {
|
for (size_t j = 0; j < n_cols_a; j++) {
|
||||||
sum += a[i*n_cols_a + j] * bt[k*n_rows_b + j];
|
sum += a[i*n_cols_a + j] * bt[k*n_rows_b + j];
|
||||||
}
|
}
|
||||||
@@ -149,18 +151,18 @@ int main(void) {
|
|||||||
// srand(0);
|
// srand(0);
|
||||||
|
|
||||||
/* For measuring time */
|
/* For measuring time */
|
||||||
double t0, t1;
|
int t0, t1;
|
||||||
|
|
||||||
const unsigned scale = 14;
|
const unsigned scale = 20;
|
||||||
const unsigned n_rows_a = 4 * scale;
|
const unsigned n_rows_a = 4 * scale;
|
||||||
const unsigned n_cols_a = 3 * scale;
|
const unsigned n_cols_a = 3 * scale;
|
||||||
const unsigned n_rows_b = 3 * scale;
|
const unsigned n_rows_b = 3 * scale;
|
||||||
const unsigned n_cols_b = 2 * scale;
|
const unsigned n_cols_b = 2 * scale;
|
||||||
|
|
||||||
double __capability *a = malloc(n_rows_a * n_cols_a * sizeof(*a));
|
int __capability *a = malloc(n_rows_a * n_cols_a * sizeof(*a));
|
||||||
double __capability *b = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
int __capability *b = malloc(n_rows_b * n_cols_b * sizeof(*b));
|
||||||
double __capability *c = NULL;
|
int __capability *c = NULL;
|
||||||
double __capability *d = NULL;
|
int __capability *d = NULL;
|
||||||
|
|
||||||
if (!a || !b) {
|
if (!a || !b) {
|
||||||
// printf("Couldn't allocate memory!\n");
|
// printf("Couldn't allocate memory!\n");
|
||||||
|
|||||||
@@ -384,13 +384,13 @@ int bench() {
|
|||||||
wkq = pkt(wkq, I_DEVA, K_DEV);
|
wkq = pkt(wkq, 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);
|
// createtask(I_HANDLERA, 2000, wkq, S_WAITPKT, handlerfn, 0, 0);
|
||||||
|
|
||||||
wkq = pkt(0, I_DEVB, K_DEV);
|
// wkq = pkt(0, I_DEVB, K_DEV);
|
||||||
wkq = pkt(wkq, I_DEVB, K_DEV);
|
// wkq = pkt(wkq, 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);
|
// createtask(I_HANDLERB, 3000, wkq, S_WAITPKT, handlerfn, 0, 0);
|
||||||
|
|
||||||
// wkq = 0;
|
// wkq = 0;
|
||||||
// createtask(I_DEVA, 4000, wkq, S_WAIT, devfn, 0, 0);
|
// createtask(I_DEVA, 4000, wkq, S_WAIT, devfn, 0, 0);
|
||||||
@@ -434,9 +434,9 @@ int inner_loop(int inner) {
|
|||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
//INITREGULARALLOC();
|
//INITREGULARALLOC();
|
||||||
int iterations = 10;
|
int iterations = 1;
|
||||||
int warmup = 0;
|
int warmup = 0;
|
||||||
int inner_iterations = 10;
|
int inner_iterations = 1;
|
||||||
|
|
||||||
// parse_argv(argc, argv, &iterations, &warmup, &inner_iterations);
|
// parse_argv(argc, argv, &iterations, &warmup, &inner_iterations);
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,5 @@ SECTIONS
|
|||||||
_end = .;
|
_end = .;
|
||||||
|
|
||||||
__malloc_start = .;
|
__malloc_start = .;
|
||||||
. = . + 0x100000;
|
. = . + 0x10000;
|
||||||
|
|
||||||
/* End of uninitalized data segement */
|
|
||||||
_end = .;
|
|
||||||
}
|
}
|
||||||
@@ -63,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);
|
||||||
|
|||||||
@@ -32,6 +32,23 @@ void tiny_free(void*);
|
|||||||
// void * __capability next;
|
// void * __capability next;
|
||||||
// } free_node_t;
|
// } 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
|
||||||
@@ -51,46 +68,66 @@ static inline void * __capability add_delta(void * __capability cap, int offset)
|
|||||||
|
|
||||||
|
|
||||||
// Malloc wrapper
|
// 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;
|
||||||
|
|
||||||
uintptr_t raw = (uintptr_t)tiny_malloc(size);
|
uintptr_t raw_phys = (uintptr_t)phys_ptr;
|
||||||
|
intptr_t p_base = compute_physical_base(size);
|
||||||
|
intptr_t delta = p_base - (intptr_t)raw_phys;
|
||||||
|
|
||||||
// void *__capability cap = (void *__capability)raw;
|
void * __capability cap = cheri_ddc_get();
|
||||||
void *__capability cap = cheri_ddc_get();
|
cap = cheri_address_set(cap, raw_phys);
|
||||||
|
|
||||||
// // Set address from raw pointer
|
cap = add_delta(cap, (int)delta);
|
||||||
cap = cheri_address_set(cap, raw);
|
|
||||||
|
|
||||||
int delta = 12;
|
size_t aligned_size = cheri_representable_length(size);
|
||||||
|
cap = cheri_bounds_set(cap, aligned_size);
|
||||||
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;
|
return cap;
|
||||||
}
|
}
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user