diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/c/loop_exception.expect | 23 | ||||
| -rw-r--r-- | test/c/loop_exception.sail | 205 | ||||
| -rwxr-xr-x | test/c/run_tests.sh | 61 | ||||
| -rw-r--r-- | test/c/sail.h | 932 |
4 files changed, 264 insertions, 957 deletions
diff --git a/test/c/loop_exception.expect b/test/c/loop_exception.expect new file mode 100644 index 00000000..dea35e86 --- /dev/null +++ b/test/c/loop_exception.expect @@ -0,0 +1,23 @@ +i = 1 +i = 2 +i = 3 +i = 3 +i = 2 +i = 1 +j = 1 +j = 2 +j = 3 +k = 0x01 +k = 0x02 +k = 0x03 +Caught +Looping +Caught inner exception +Caught outer exception +Outer handler +Outer handler +Once +Once +ok +ok +R = 3 diff --git a/test/c/loop_exception.sail b/test/c/loop_exception.sail new file mode 100644 index 00000000..945754f2 --- /dev/null +++ b/test/c/loop_exception.sail @@ -0,0 +1,205 @@ +default Order dec + +$include <flow.sail> +$include <arith.sail> +$include <vector_dec.sail> +$include <string.sail> + +$include <exception_basic.sail> + +val highest_set_bit : forall ('n : Int), 'n >= 0. bits('n) -> int + +overload ~ = {not_bool} + +function highest_set_bit x = { + foreach (i from ('n - 1) to 0 by 1 in dec) + if x[i] == bitone then return(i) else (); + return -1 +} + +val throws : unit -> unit effect {escape} + +function throws() = throw Exception() + +register R : int + +/* + * Modelling bug described in commit 45554f2893667d951e39c8049631a986c1683857 + */ +val fetch_and_execute : unit -> bool effect {escape, wreg, rreg} + +function fetch_and_execute() = +{ + R = R + 1; + try { + if (R >= 3) then { + throws() + }; + true + } catch { + Exception() => false + } +} + +val main : unit -> unit effect {escape, wreg, rreg} + +function main() = +{ + R = 0; + + /* + * Expect: "i = 1", "i = 2" and "i = 3" + */ + foreach (i from 1 to 3) { + print_int("i = ", i) + }; + + /* + * Expect: "i = 3", "i = 2" and "i = 1" + */ + foreach (i from 3 to 1 by 1 in dec) { + print_int("i = ", i) + }; + + assert(highest_set_bit(0b1) == 0); + assert(highest_set_bit(0b0010) == 1); + assert(highest_set_bit(0b10000) == 4); + assert(highest_set_bit(0x8000_0000_0000_0000) == 63); + assert(highest_set_bit(0x1_0000_0000_0000_0000) == 64); + + /* + * Expect: "j = 1", "j = 2" and "j = 3" + */ + j : int = 0; + + while j < 3 do { + j = j + 1; + print_int("j = ", j); + }; + + /* + * Expect: "k = 0x01", "k = 0x02" and "k = 0x03" + */ + k : bits(8) = 0x00; + + while unsigned(k) < 3 do { + k = k + 1; + print_bits("k = ", k); + }; + + /* + * Expect: "Caught" + */ + try { + while true do { + throw Exception(); + assert(false, "Unreachable") + } + } catch { + Exception() => print_endline("Caught") + }; + + /* + * Expect: "Looping" + */ + caught : bool = false; + + while ~(caught) do { + try { + print_endline("Looping"); + throw Exception(); + assert(false, "Unreachable") + } catch { + Exception() => caught = true + } + }; + + /* + * Expect "Caught inner exception", "Caught outer exception" + */ + try { + try throw Exception() + catch { + Exception() => { + print_endline("Caught inner exception"); + throw Exception() + } + } + } catch { + Exception() => print_endline("Caught outer exception") + }; + + /* + * Expect "Outer handler" + */ + try { + try throw Exception() + catch { + /* Exception in catch guard will throw to outer handler */ + Exception() if { throw Exception(); false } => { + assert(false, "Unreachable"); + throw Exception() + }, + _ => assert(false, "Unreachable") + } + } catch { + Exception() => print_endline("Outer handler") + }; + + /* + * Expect "Outer handler" + */ + try { + try throws() + catch { + /* Exception in catch guard will throw to outer handler */ + Exception() if { throws(); true } => { + assert(false, "Unreachable"); + throws() + }, + _ => assert(false, "Unreachable") + } + } catch { + Exception() => print_endline("Outer handler") + }; + + /* + * Expect "Once" + */ + repeat { + print_endline("Once") + } until true; + + /* + * Expect "Once" + */ + once : bool = false; + + repeat { + print_endline("Once"); + try throw Exception() catch { + _ => once = true, + _ => once = false + } + } until once; + + /* + * Expect "ok" + */ + if try true catch { _ => false } then { + print_endline("ok") + }; + + /* + * Expect "ok" + */ + if try throw Exception() catch { _ => true } then { + print_endline("ok") + }; + + /* + * Expect "R = 3" + */ + while fetch_and_execute() do (); + print_int("R = ", R); +}
\ No newline at end of file diff --git a/test/c/run_tests.sh b/test/c/run_tests.sh index e85881f5..e1a1a1ce 100755 --- a/test/c/run_tests.sh +++ b/test/c/run_tests.sh @@ -47,36 +47,47 @@ function finish_suite { printf "<testsuites>\n" >> $DIR/tests.xml shopt -s nullglob; -for file in $DIR/*.sail; -do - if $SAILDIR/sail -no_warn -c $file 1> ${file%.sail}.c 2> /dev/null; - then - green "compiling $(basename $file)" "ok"; - if gcc ${file%.sail}.c -lgmp; + +function run_c_tests { + for file in $DIR/*.sail; + do + if $SAILDIR/sail -no_warn -c $SAIL_OPTS $file 1> ${file%.sail}.c 2> /dev/null; then - green "compiling $(basename ${file%.sail}.c)" "ok"; - $DIR/a.out 1> ${file%.sail}.result 2> /dev/null; - if diff ${file%.sail}.result ${file%.sail}.expect; - then - green "executing $(basename ${file%.sail})" "ok" - else - red "executing $(basename ${file%.sail})" "fail" - fi; - if valgrind -q --leak-check=full --errors-for-leak-kinds=all --error-exitcode=1 $DIR/a.out 1> /dev/null 2> /dev/null; + green "compiling $(basename $file) ($SAIL_OPTS)" "ok"; + if gcc $CC_OPTS ${file%.sail}.c -lgmp -I $SAILDIR/lib; then - green "executing $(basename ${file%.sail}) with valgrind" "ok" + green "compiling $(basename ${file%.sail}.c) ($CC_OPTS)" "ok"; + $DIR/a.out 1> ${file%.sail}.result 2> /dev/null; + if diff ${file%.sail}.result ${file%.sail}.expect; + then + green "executing $(basename ${file%.sail})" "ok" + else + red "executing $(basename ${file%.sail})" "fail" + fi; + if valgrind -q --leak-check=full --errors-for-leak-kinds=all --error-exitcode=1 $DIR/a.out 1> /dev/null 2> /dev/null; + then + green "executing $(basename ${file%.sail}) with valgrind" "ok" + else + red "executing $(basename ${file%.sail}) with valgrind" "fail" + fi else - red "executing $(basename ${file%.sail}) with valgrind" "fail" + red "compiling generated C" "fail" fi else - red "compiling generated C" "fail" - fi - else - red "compiling $file" "fail" - fi; - rm -f ${file%.sail}.c - rm -f ${file%.sail}.result -done + red "compiling $file" "fail" + fi; + rm -f ${file%.sail}.c + rm -f ${file%.sail}.result + done +} + +SAIL_OPTS="" +CC_OPTS="-O0" +run_c_tests + +SAIL_OPTS="-O" +CC_OPTS="-O2" +run_c_tests finish_suite "C testing" diff --git a/test/c/sail.h b/test/c/sail.h deleted file mode 100644 index b5328377..00000000 --- a/test/c/sail.h +++ /dev/null @@ -1,932 +0,0 @@ -#ifndef SAIL_LIB -#define SAIL_LIB - -#include<stdio.h> -#include<inttypes.h> -#include<stdlib.h> -#include<stdbool.h> -#include<string.h> -#include<gmp.h> - -typedef int unit; - -#define UNIT 0 - -unit undefined_unit(const unit u) { - return UNIT; -} - -typedef struct { - mp_bitcnt_t len; - mpz_t *bits; -} bv_t; - -typedef char *sail_string; - -// This function should be called whenever a pattern match failure -// occurs. Pattern match failures are always fatal. -void sail_match_failure(sail_string msg) { - fprintf(stderr, "Pattern match failure in %s\n", msg); - exit(EXIT_FAILURE); -} - -unit sail_assert(bool b, sail_string msg) { - if (b) return UNIT; - fprintf(stderr, "Assertion failed: %s\n", msg); - exit(EXIT_FAILURE); -} - -unit sail_exit(const unit u) { - fprintf(stderr, "exit\n"); - exit(EXIT_SUCCESS); -} - -void elf_entry(mpz_t *rop, const unit u) { - mpz_set_ui(*rop, 0x400130ul); -} - -void elf_tohost(mpz_t *rop, const unit u) { - mpz_set_ui(*rop, 0x0ul); -} - -// Sail bits are mapped to uint64_t where bitzero = 0ul and bitone = 1ul -bool eq_bit(const uint64_t a, const uint64_t b) { - return a == b; -} - -uint64_t undefined_bit(unit u) { return 0; } - -// ***** Sail booleans ***** - -bool not(const bool b) { - return !b; -} - -bool and_bool(const bool a, const bool b) { - return a && b; -} - -bool or_bool(const bool a, const bool b) { - return a || b; -} - -bool eq_bool(const bool a, const bool b) { - return a == b; -} - -bool undefined_bool(const unit u) { - return false; -} - -// ***** Sail strings ***** -void init_sail_string(sail_string *str) { - char *istr = (char *) malloc(1 * sizeof(char)); - istr[0] = '\0'; - *str = istr; -} - -void reinit_sail_string(sail_string *str) { - free(*str); - char *istr = (char *) malloc(1 * sizeof(char)); - istr[0] = '\0'; - *str = istr; -} - -void set_sail_string(sail_string *str1, const sail_string str2) { - size_t len = strlen(str2); - *str1 = realloc(*str1, len + 1); - *str1 = strcpy(*str1, str2); -} - -void clear_sail_string(sail_string *str) { - free(*str); -} - -bool eq_string(const sail_string str1, const sail_string str2) { - return strcmp(str1, str2) == 0; -} - -unit print_endline(const sail_string str) { - printf("%s\n", str); - return UNIT; -} - -unit print_string(const sail_string str1, const sail_string str2) { - printf("%s%s\n", str1, str2); - return UNIT; -} - -unit prerr_endline(const sail_string str) { - fprintf(stderr, "%s\n", str); - return UNIT; -} - -unit print_int(const sail_string str, const mpz_t op) { - fputs(str, stdout); - mpz_out_str(stdout, 10, op); - putchar('\n'); - return UNIT; -} - -unit print_int64(const sail_string str, const int64_t op) { - printf("%s%" PRId64 "\n", str, op); - return UNIT; -} - -unit sail_putchar(const mpz_t op) { - char c = (char) mpz_get_ui(op); - putchar(c); -} - -// ***** Arbitrary precision integers ***** - -// We wrap around the GMP functions so they follow a consistent naming -// scheme that is shared with the other builtin sail types. - -void set_mpz_t(mpz_t *rop, const mpz_t op) { - mpz_set(*rop, op); -} - -void init_mpz_t(mpz_t *op) { - mpz_init(*op); -} - -void reinit_mpz_t(mpz_t *op) { - mpz_set_ui(*op, 0); -} - -void clear_mpz_t(mpz_t *op) { - mpz_clear(*op); -} - -void init_mpz_t_of_int64_t(mpz_t *rop, int64_t op) { - mpz_init_set_si(*rop, op); -} - -void reinit_mpz_t_of_int64_t(mpz_t *rop, int64_t op) { - mpz_set_si(*rop, op); -} - -void init_mpz_t_of_sail_string(mpz_t *rop, sail_string str) { - mpz_init_set_str(*rop, str, 10); -} - -void reinit_mpz_t_of_sail_string(mpz_t *rop, sail_string str) { - mpz_set_str(*rop, str, 10); -} - -int64_t convert_int64_t_of_mpz_t(const mpz_t op) { - return mpz_get_si(op); -} - -void convert_mpz_t_of_int64_t(mpz_t *rop, const int64_t op) { - mpz_set_si(*rop, op); -} - -// ***** Sail builtins for integers ***** - -bool eq_int(const mpz_t op1, const mpz_t op2) { - return !abs(mpz_cmp(op1, op2)); -} - -bool lt(const mpz_t op1, const mpz_t op2) { - return mpz_cmp(op1, op2) < 0; -} - -bool gt(const mpz_t op1, const mpz_t op2) { - return mpz_cmp(op1, op2) > 0; -} - -bool lteq(const mpz_t op1, const mpz_t op2) { - return mpz_cmp(op1, op2) <= 0; -} - -bool gteq(const mpz_t op1, const mpz_t op2) { - return mpz_cmp(op1, op2) >= 0; -} - -void shl_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) { - mpz_mul_2exp(*rop, op1, mpz_get_ui(op2)); -} - -void undefined_int(mpz_t *rop, const unit u) { - mpz_set_ui(*rop, 0ul); -} - -void undefined_range(mpz_t *rop, const mpz_t l, const mpz_t u) { - mpz_set(*rop, l); -} - -void add_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) -{ - mpz_add(*rop, op1, op2); -} - -void sub_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) -{ - mpz_sub(*rop, op1, op2); -} - -void mult_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) -{ - mpz_mul(*rop, op1, op2); -} - -void div_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) -{ - mpz_tdiv_q(*rop, op1, op2); -} - -void mod_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) -{ - mpz_tdiv_r(*rop, op1, op2); -} - -void max_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) { - if (lt(op1, op2)) { - mpz_set(*rop, op2); - } else { - mpz_set(*rop, op1); - } -} - -void min_int(mpz_t *rop, const mpz_t op1, const mpz_t op2) { - if (gt(op1, op2)) { - mpz_set(*rop, op2); - } else { - mpz_set(*rop, op1); - } -} - -void neg_int(mpz_t *rop, const mpz_t op) { - mpz_neg(*rop, op); -} - -void abs_int(mpz_t *rop, const mpz_t op) { - mpz_abs(*rop, op); -} - -void pow2(mpz_t *rop, mpz_t exp) { - uint64_t exp_ui = mpz_get_ui(exp); - mpz_t base; - mpz_init_set_ui(base, 2ul); - mpz_pow_ui(*rop, base, exp_ui); - mpz_clear(base); -} - -// ***** Sail bitvectors ***** - -unit print_bits(const sail_string str, const bv_t op) -{ - fputs(str, stdout); - - if (op.len % 4 == 0) { - fputs("0x", stdout); - mpz_t buf; - mpz_init_set(buf, *op.bits); - - char *hex = malloc((op.len / 4) * sizeof(char)); - - for (int i = 0; i < op.len / 4; ++i) { - char c = (char) ((0xF & mpz_get_ui(buf)) + 0x30); - hex[i] = (c < 0x3A) ? c : c + 0x7; - mpz_fdiv_q_2exp(buf, buf, 4); - } - - for (int i = op.len / 4; i > 0; --i) { - fputc(hex[i - 1], stdout); - } - - free(hex); - mpz_clear(buf); - } else { - fputs("0b", stdout); - for (int i = op.len; i > 0; --i) { - fputc(mpz_tstbit(*op.bits, i - 1) + 0x30, stdout); - } - } - - fputs("\n", stdout); -} - -void length_bv_t(mpz_t *rop, const bv_t op) { - mpz_set_ui(*rop, op.len); -} - -void init_bv_t(bv_t *rop) { - rop->bits = malloc(sizeof(mpz_t)); - rop->len = 0; - mpz_init(*rop->bits); -} - -void reinit_bv_t(bv_t *rop) { - rop->len = 0; - mpz_set_ui(*rop->bits, 0); -} - -void init_bv_t_of_uint64_t(bv_t *rop, const uint64_t op, const uint64_t len, const bool direction) { - rop->bits = malloc(sizeof(mpz_t)); - rop->len = len; - mpz_init_set_ui(*rop->bits, op); -} - -void reinit_bv_t_of_uint64_t(bv_t *rop, const uint64_t op, const uint64_t len, const bool direction) { - rop->len = len; - mpz_set_ui(*rop->bits, op); -} - -void set_bv_t(bv_t *rop, const bv_t op) { - rop->len = op.len; - mpz_set(*rop->bits, *op.bits); -} - -void append_64(bv_t *rop, const bv_t op, const uint64_t chunk) { - rop->len = rop->len + 64ul; - mpz_mul_2exp(*rop->bits, *op.bits, 64ul); - mpz_add_ui(*rop->bits, *rop->bits, chunk); -} - -void append(bv_t *rop, const bv_t op1, const bv_t op2) { - rop->len = op1.len + op2.len; - mpz_mul_2exp(*rop->bits, *op1.bits, op2.len); - mpz_add(*rop->bits, *rop->bits, *op2.bits); -} - -void replicate_bits(bv_t *rop, const bv_t op1, const mpz_t op2) { - uint64_t op2_ui = mpz_get_ui(op2); - rop->len = op1.len * op2_ui; - mpz_set(*rop->bits, *op1.bits); - for (int i = 1; i < op2_ui; i++) { - mpz_mul_2exp(*rop->bits, *rop->bits, op1.len); - mpz_ior(*rop->bits, *rop->bits, *op1.bits); - } -} - -uint64_t fast_replicate_bits(const uint64_t shift, const uint64_t v, const int64_t times) { - uint64_t r = 0; - for (int i = 0; i < times; ++i) { - r |= v << shift; - } - return r; -} - -void slice(bv_t *rop, const bv_t op, const mpz_t start_mpz, const mpz_t len_mpz) -{ - uint64_t start = mpz_get_ui(start_mpz); - uint64_t len = mpz_get_ui(len_mpz); - - mpz_set_ui(*rop->bits, 0ul); - rop->len = len; - - for (uint64_t i = 0; i < len; i++) { - if (mpz_tstbit(*op.bits, i + start)) mpz_setbit(*rop->bits, i); - } -} - -uint64_t convert_uint64_t_of_bv_t(const bv_t op) { - return mpz_get_ui(*op.bits); -} - -void zeros(bv_t *rop, const mpz_t op) { - rop->len = mpz_get_ui(op); - mpz_set_ui(*rop->bits, 0ul); -} - -void zero_extend(bv_t *rop, const bv_t op, const mpz_t len) { - rop->len = mpz_get_ui(len); - mpz_set(*rop->bits, *op.bits); -} - -/* FIXME */ -void sign_extend(bv_t *rop, const bv_t op, const mpz_t len) { - rop->len = mpz_get_ui(len); - mpz_set(*rop->bits, *op.bits); -} - -void clear_bv_t(bv_t *rop) { - mpz_clear(*rop->bits); - free(rop->bits); -} - -void undefined_bv_t(bv_t *rop, mpz_t len, int bit) { - zeros(rop, len); -} - -void mask(bv_t *rop) { - if (mpz_sizeinbase(*rop->bits, 2) > rop->len) { - mpz_t m; - mpz_init(m); - mpz_ui_pow_ui(m, 2ul, rop->len); - mpz_sub_ui(m, m, 1ul); - mpz_and(*rop->bits, *rop->bits, m); - mpz_clear(m); - } -} - -void truncate(bv_t *rop, const bv_t op, const mpz_t len) { - rop->len = mpz_get_ui(len); - mpz_set(*rop->bits, *op.bits); - mask(rop); -} - -void and_bits(bv_t *rop, const bv_t op1, const bv_t op2) { - rop->len = op1.len; - mpz_and(*rop->bits, *op1.bits, *op2.bits); -} - -void or_bits(bv_t *rop, const bv_t op1, const bv_t op2) { - rop->len = op1.len; - mpz_ior(*rop->bits, *op1.bits, *op2.bits); -} - -void not_bits(bv_t *rop, const bv_t op) { - rop->len = op.len; - mpz_com(*rop->bits, *op.bits); -} - -void xor_bits(bv_t *rop, const bv_t op1, const bv_t op2) { - rop->len = op1.len; - mpz_xor(*rop->bits, *op1.bits, *op2.bits); -} - -mpz_t eq_bits_test; - -bool eq_bits(const bv_t op1, const bv_t op2) -{ - for (mp_bitcnt_t i = 0; i < op1.len; i++) { - if (mpz_tstbit(*op1.bits, i) != mpz_tstbit(*op2.bits, i)) return false; - } - return true; -} - -// These aren't very efficient, but they work. Question is how best to -// do these given GMP uses a sign bit representation? -void sail_uint(mpz_t *rop, const bv_t op) { - mpz_set_ui(*rop, 0ul); - for (mp_bitcnt_t i = 0; i < op.len; ++i) { - if (mpz_tstbit(*op.bits, i)) { - mpz_setbit(*rop, i); - } else { - mpz_clrbit(*rop, i); - } - } -} - -void sint(mpz_t *rop, const bv_t op) -{ - mpz_set_ui(*rop, 0ul); - if (mpz_tstbit(*op.bits, op.len - 1)) { - for (mp_bitcnt_t i = 0; i < op.len; ++i) { - if (mpz_tstbit(*op.bits, i)) { - mpz_clrbit(*rop, i); - } else { - mpz_setbit(*rop, i); - } - }; - mpz_add_ui(*rop, *rop, 1ul); - mpz_neg(*rop, *rop); - } else { - for (mp_bitcnt_t i = 0; i < op.len; ++i) { - if (mpz_tstbit(*op.bits, i)) { - mpz_setbit(*rop, i); - } else { - mpz_clrbit(*rop, i); - } - } - } -} - -void add_bits(bv_t *rop, const bv_t op1, const bv_t op2) { - rop->len = op1.len; - mpz_add(*rop->bits, *op1.bits, *op2.bits); -} - -void add_bits_int(bv_t *rop, const bv_t op1, const mpz_t op2) { - rop->len = op1.len; - mpz_add(*rop->bits, *op1.bits, op2); -} - -void sub_bits_int(bv_t *rop, const bv_t op1, const mpz_t op2) { - printf("sub_bits_int\n"); - rop->len = op1.len; - mpz_sub(*rop->bits, *op1.bits, op2); -} - -// Takes a slice of the (two's complement) binary representation of -// integer n, starting at bit start, and of length len. With the -// argument in the following order: -// -// get_slice_int(len, n, start) -// -// For example: -// -// get_slice_int(8, 1680, 4) = -// -// 11 0 -// V V -// get_slice_int(8, 0b0110_1001_0000, 4) = 0b0110_1001 -// <-------^ -// (8 bit) 4 -// -void get_slice_int(bv_t *rop, const mpz_t len_mpz, const mpz_t n, const mpz_t start_mpz) -{ - uint64_t start = mpz_get_ui(start_mpz); - uint64_t len = mpz_get_ui(len_mpz); - - mpz_set_ui(*rop->bits, 0ul); - rop->len = len; - - for (uint64_t i = 0; i < len; i++) { - if (mpz_tstbit(n, i + start)) mpz_setbit(*rop->bits, i); - } -} - -// Set slice uses the same indexing scheme as get_slice_int, but it -// puts a bitvector slice into an integer rather than returning it. -void set_slice_int(mpz_t *rop, - const mpz_t len_mpz, - const mpz_t n, - const mpz_t start_mpz, - const bv_t slice) -{ - uint64_t start = mpz_get_ui(start_mpz); - - mpz_set(*rop, n); - - for (uint64_t i = 0; i < slice.len; i++) { - if (mpz_tstbit(*slice.bits, i)) { - mpz_setbit(*rop, i + start); - } else { - mpz_clrbit(*rop, i + start); - } - } -} - -void vector_update_subrange_bv_t(bv_t *rop, - const bv_t op, - const mpz_t n_mpz, - const mpz_t m_mpz, - const bv_t slice) -{ - uint64_t n = mpz_get_ui(n_mpz); - uint64_t m = mpz_get_ui(m_mpz); - - mpz_set(*rop->bits, *op.bits); - - for (uint64_t i = 0; i < n - (m - 1ul); i++) { - if (mpz_tstbit(*slice.bits, i)) { - mpz_setbit(*rop->bits, i + m); - } else { - mpz_clrbit(*rop->bits, i + m); - } - } -} - -void vector_subrange_bv_t(bv_t *rop, const bv_t op, const mpz_t n_mpz, const mpz_t m_mpz) -{ - uint64_t n = mpz_get_ui(n_mpz); - uint64_t m = mpz_get_ui(m_mpz); - - mpz_set_ui(*rop->bits, 0ul); - rop->len = n - (m - 1ul); - - for (uint64_t i = 0; i < rop->len; i++) { - if (mpz_tstbit(*op.bits, i + m)) { - mpz_setbit(*rop->bits, i); - } else { - mpz_clrbit(*rop->bits, i); - } - } -} - -int bitvector_access(const bv_t op, const mpz_t n_mpz) { - uint64_t n = mpz_get_ui(n_mpz); - return mpz_tstbit(*op.bits, n); -} - -// Like slice but slices from a hexadecimal string. -void hex_slice (bv_t *rop, const sail_string hex, const mpz_t len_mpz, const mpz_t start_mpz) { - mpz_t op; - mpz_init_set_str(op, hex, 0); - get_slice_int(rop, len_mpz, op, start_mpz); - mpz_clear(op); -} - -void set_slice (bv_t *rop, - const mpz_t len_mpz, - const mpz_t slen_mpz, - const bv_t op, - const mpz_t start_mpz, - const bv_t slice) -{ - uint64_t start = mpz_get_ui(start_mpz); - - mpz_set(*rop->bits, *op.bits); - rop->len = op.len; - - for (uint64_t i = 0; i < slice.len; i++) { - if (mpz_tstbit(*slice.bits, i)) { - mpz_setbit(*rop->bits, i + start); - } else { - mpz_clrbit(*rop->bits, i + start); - } - } -} - -// ***** Real number implementation ***** - -#define REAL_FLOAT - -#ifdef REAL_FLOAT - -typedef mpf_t real; - -#define FLOAT_PRECISION 255 - -void init_real(real *rop) { - mpf_init(*rop); -} - -void reinit_real(real *rop) { - mpf_set_ui(*rop, 0); -} - -void clear_real(real *rop) { - mpf_clear(*rop); -} - -void set_real(real *rop, const real op) { - mpf_set(*rop, op); -} - -void undefined_real(real *rop, unit u) { - mpf_set_ui(*rop, 0ul); -} - -void neg_real(real *rop, const real op) { - mpf_neg(*rop, op); -} - -void mult_real(real *rop, const real op1, const real op2) { - mpf_mul(*rop, op1, op2); -} - -void sub_real(real *rop, const real op1, const real op2) { - mpf_sub(*rop, op1, op2); -} - -void add_real(real *rop, const real op1, const real op2) { - mpf_add(*rop, op1, op2); -} - -void div_real(real *rop, const real op1, const real op2) { - mpf_div(*rop, op1, op2); -} - -void sqrt_real(real *rop, const real op) { - mpf_sqrt(*rop, op); -} - -void abs_real(real *rop, const real op) { - mpf_abs(*rop, op); -} - -void round_up(mpz_t *rop, const real op) { - mpf_t x; - mpf_init(x); - mpf_ceil(x, op); - mpz_set_ui(*rop, mpf_get_ui(x)); - mpf_clear(x); -} - -void round_down(mpz_t *rop, const real op) { - mpf_t x; - mpf_init(x); - mpf_floor(x, op); - mpz_set_ui(*rop, mpf_get_ui(x)); - mpf_clear(x); -} - -void to_real(real *rop, const mpz_t op) { - mpf_set_z(*rop, op); -} - -bool eq_real(const real op1, const real op2) { - return mpf_cmp(op1, op2) == 0; -} - -bool lt_real(const real op1, const real op2) { - return mpf_cmp(op1, op2) < 0; -} - -bool gt_real(const real op1, const real op2) { - return mpf_cmp(op1, op2) > 0; -} - -bool lteq_real(const real op1, const real op2) { - return mpf_cmp(op1, op2) <= 0; -} - -bool gteq_real(const real op1, const real op2) { - return mpf_cmp(op1, op2) >= 0; -} - -void real_power(real *rop, const real base, const mpz_t exp) { - uint64_t exp_ui = mpz_get_ui(exp); - mpf_pow_ui(*rop, base, exp_ui); -} - -void init_real_of_sail_string(real *rop, const sail_string op) { - // FIXME - mpf_init(*rop); -} - -#endif - -#endif - -/* ***** Sail memory builtins ***** */ - -/* We organise memory available to the sail model into a linked list - of dynamically allocated MASK + 1 size blocks. The most recently - written block is moved to the front of the list, so contiguous - accesses should be as fast as possible. */ - -struct block { - uint64_t block_id; - uint8_t *mem; - struct block *next; -}; - -struct block *sail_memory = NULL; - -/* Must be one less than a power of two. */ -uint64_t MASK = 0xFFFFul; - -// All sail vectors are at least 64-bits, but only the bottom 8 bits -// are used in the second argument. -void write_mem(uint64_t address, uint64_t byte) -{ - uint64_t mask = address & ~MASK; - uint64_t offset = address & MASK; - - struct block *prev = NULL; - struct block *current = sail_memory; - - while (current != NULL) { - if (current->block_id == mask) { - current->mem[offset] = (uint8_t) byte; - - /* Move the accessed block to the front of the block list */ - if (prev != NULL) { - prev->next = current->next; - } - current->next = sail_memory->next; - sail_memory = current; - - return; - } else { - prev = current; - current = current->next; - } - } - - /* If we couldn't find a block matching the mask, allocate a new - one, write the byte, and put it at the front of the block - list. */ - struct block *new_block = malloc(sizeof(struct block)); - new_block->block_id = mask; - new_block->mem = calloc(MASK + 1, sizeof(uint8_t)); - new_block->mem[offset] = byte; - new_block->next = sail_memory; - sail_memory = new_block; -} - -uint64_t read_mem(uint64_t address) -{ - uint64_t mask = address & ~MASK; - uint64_t offset = address & MASK; - - struct block *current = sail_memory; - - while (current != NULL) { - if (current->block_id == mask) { - return (uint64_t) current->mem[offset]; - } else { - current = current->next; - } - } - - return 0; -} - -void kill_mem() -{ - while (sail_memory != NULL) { - struct block *next = sail_memory->next; - - free(sail_memory->mem); - free(sail_memory); - - sail_memory = next; - } -} - -// ***** ARM Memory builtins ***** - -// These memory builtins are intended to match the semantics for the -// __ReadRAM and __WriteRAM functions in ASL. - -unit write_ram(const mpz_t addr_size, // Either 32 or 64 - const mpz_t data_size_mpz, // Number of bytes - const bv_t hex_ram, // Currently unused - const bv_t addr_bv, - const bv_t data) -{ - uint64_t addr = mpz_get_ui(*addr_bv.bits); - uint64_t data_size = mpz_get_ui(data_size_mpz); - - mpz_t buf; - mpz_init_set(buf, *data.bits); - - uint64_t byte; - for(uint64_t i = 0; i < data_size; ++i) { - // Take the 8 low bits of buf and write to addr. - byte = mpz_get_ui(buf) & 0xFF; - write_mem(addr + i, byte); - - // Then shift buf 8 bits right, and increment addr. - mpz_fdiv_q_2exp(buf, buf, 8); - } - - mpz_clear(buf); - return UNIT; -} - -void read_ram(bv_t *data, - const mpz_t addr_size, - const mpz_t data_size_mpz, - const bv_t hex_ram, - const bv_t addr_bv) -{ - uint64_t addr = mpz_get_ui(*addr_bv.bits); - uint64_t data_size = mpz_get_ui(data_size_mpz); - - mpz_set_ui(*data->bits, 0); - data->len = data_size * 8; - - mpz_t byte; - mpz_init(byte); - for(uint64_t i = data_size; i > 0; --i) { - mpz_set_ui(byte, read_mem(addr + (i - 1))); - mpz_mul_2exp(*data->bits, *data->bits, 8); - mpz_add(*data->bits, *data->bits, byte); - } - - mpz_clear(byte); -} - -void load_image(char *file) { - FILE *fp = fopen(file, "r"); - - if (!fp) { - fprintf(stderr, "Image file %s could not be loaded\n", file); - exit(EXIT_FAILURE); - } - - char *addr = NULL; - char *data = NULL; - size_t len = 0; - - while (true) { - ssize_t addr_len = getline(&addr, &len, fp); - if (addr_len == -1) break; - ssize_t data_len = getline(&data, &len, fp); - if (data_len == -1) break; - - write_mem((uint64_t) atoll(addr), (uint64_t) atoll(data)); - } - - free(addr); - free(data); - fclose(fp); -} - -void load_instr(uint64_t addr, uint32_t instr) { - write_mem(addr , instr & 0xFF); - write_mem(addr + 1, instr >> 8 & 0xFF); - write_mem(addr + 2, instr >> 16 & 0xFF); - write_mem(addr + 3, instr >> 24 & 0xFF); -} - -// ***** Setup and cleanup functions for library code ***** - -void setup_library(void) { - mpf_set_default_prec(FLOAT_PRECISION); - mpz_init(eq_bits_test); -} - -void cleanup_library(void) { - mpz_clear(eq_bits_test); - kill_mem(); -} |
