diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/sail_lib.ml | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/src/sail_lib.ml b/src/sail_lib.ml new file mode 100644 index 00000000..b4dffba9 --- /dev/null +++ b/src/sail_lib.ml @@ -0,0 +1,477 @@ +module Big_int = Nat_big_num + +type 'a return = { return : 'b . 'a -> 'b } + +let opt_trace = ref false + +let trace_depth = ref 0 +let random = ref false + +let sail_call (type t) (f : _ -> t) = + let module M = + struct exception Return of t end + in + let return = { return = (fun x -> raise (M.Return x)) } in + try + f return + with M.Return x -> x + +let trace str = + if !opt_trace + then + begin + if !trace_depth < 0 then trace_depth := 0 else (); + prerr_endline (String.make (!trace_depth * 2) ' ' ^ str) + end + else () + +let trace_write name str = + trace ("Write: " ^ name ^ " " ^ str) + +let trace_read name str = + trace ("Read: " ^ name ^ " " ^ str) + +let sail_trace_call (type t) (name : string) (in_string : string) (string_of_out : t -> string) (f : _ -> t) = + let module M = + struct exception Return of t end + in + let return = { return = (fun x -> raise (M.Return x)) } in + trace ("Call: " ^ name ^ " " ^ in_string); + incr trace_depth; + let result = try f return with M.Return x -> x in + decr trace_depth; + trace ("Return: " ^ string_of_out result); + result + +let trace_call str = + trace str; incr trace_depth + +type bit = B0 | B1 + +let and_bit = function + | B1, B1 -> B1 + | _, _ -> B0 + +let or_bit = function + | B0, B0 -> B0 + | _, _ -> B1 + +let xor_bit = function + | B1, B0 -> B1 + | B0, B1 -> B1 + | _, _ -> B0 + +let and_vec (xs, ys) = + assert (List.length xs = List.length ys); + List.map2 (fun x y -> and_bit (x, y)) xs ys + +let and_bool (b1, b2) = b1 && b2 + +let or_vec (xs, ys) = + assert (List.length xs = List.length ys); + List.map2 (fun x y -> or_bit (x, y)) xs ys + +let or_bool (b1, b2) = b1 || b2 + +let xor_vec (xs, ys) = + assert (List.length xs = List.length ys); + List.map2 (fun x y -> xor_bit (x, y)) xs ys + +let xor_bool (b1, b2) = (b1 || b2) && (b1 != b2) + +let undefined_bit () = + if !random + then (if Random.bool () then B0 else B1) + else B0 + +let undefined_bool () = + if !random then Random.bool () else false + +let rec undefined_vector (start_index, len, item) = + if Big_int.equal len Big_int.zero + then [] + else item :: undefined_vector (start_index, Big_int.sub len (Big_int.of_int 1), item) + +let undefined_string () = "" + +let undefined_unit () = () + +let undefined_int () = + if !random then Big_int.of_int (Random.int 0xFFFF) else Big_int.zero + +let undefined_nat () = Big_int.zero + +let undefined_range (lo, hi) = lo + +let internal_pick list = + if !random + then List.nth list (Random.int (List.length list)) + else List.nth list 0 + +let eq_int (n, m) = Big_int.equal n m + +let rec drop n xs = + match n, xs with + | 0, xs -> xs + | n, [] -> [] + | n, (x :: xs) -> drop (n -1) xs + +let rec take n xs = + match n, xs with + | 0, xs -> [] + | n, (x :: xs) -> x :: take (n - 1) xs + | n, [] -> [] + +let subrange (list, n, m) = + let n = Big_int.to_int n in + let m = Big_int.to_int m in + List.rev (take (n - (m - 1)) (drop m (List.rev list))) + +let slice (list, n, m) = + let n = Big_int.to_int n in + let m = Big_int.to_int m in + List.rev (take m (drop n (List.rev list))) + +let eq_list (xs, ys) = List.for_all2 (fun x y -> x = y) xs ys + +let access (xs, n) = List.nth (List.rev xs) (Big_int.to_int n) + +let append (xs, ys) = xs @ ys + +let update (xs, n, x) = + let n = (List.length xs - Big_int.to_int n) - 1 in + take n xs @ [x] @ drop (n + 1) xs + +let update_subrange (xs, n, m, ys) = + let rec aux xs o = function + | [] -> xs + | (y :: ys) -> aux (update (xs, o, y)) (Big_int.sub o (Big_int.of_int 1)) ys + in + aux xs n ys + + +let length xs = Big_int.of_int (List.length xs) + +let big_int_of_bit = function + | B0 -> Big_int.zero + | B1 -> (Big_int.of_int 1) + +let uint xs = + let uint_bit x (n, pos) = + Big_int.add n (Big_int.mul (Big_int.pow_int_positive 2 pos) (big_int_of_bit x)), pos + 1 + in + fst (List.fold_right uint_bit xs (Big_int.zero, 0)) + +let sint = function + | [] -> Big_int.zero + | [msb] -> Big_int.negate (big_int_of_bit msb) + | msb :: xs -> + let msb_pos = List.length xs in + let complement = + Big_int.negate (Big_int.mul (Big_int.pow_int_positive 2 msb_pos) (big_int_of_bit msb)) + in + Big_int.add complement (uint xs) + +let add (x, y) = Big_int.add x y +let sub (x, y) = Big_int.sub x y +let mult (x, y) = Big_int.mul x y +let quotient (x, y) = Big_int.div x y +let modulus (x, y) = Big_int.modulus x y + +let add_bit_with_carry (x, y, carry) = + match x, y, carry with + | B0, B0, B0 -> B0, B0 + | B0, B1, B0 -> B1, B0 + | B1, B0, B0 -> B1, B0 + | B1, B1, B0 -> B0, B1 + | B0, B0, B1 -> B1, B0 + | B0, B1, B1 -> B0, B1 + | B1, B0, B1 -> B0, B1 + | B1, B1, B1 -> B1, B1 + +let sub_bit_with_carry (x, y, carry) = + match x, y, carry with + | B0, B0, B0 -> B0, B0 + | B0, B1, B0 -> B0, B1 + | B1, B0, B0 -> B1, B0 + | B1, B1, B0 -> B0, B0 + | B0, B0, B1 -> B1, B0 + | B0, B1, B1 -> B0, B0 + | B1, B0, B1 -> B1, B1 + | B1, B1, B1 -> B1, B0 + +let not_bit = function + | B0 -> B1 + | B1 -> B0 + +let not_vec xs = List.map not_bit xs + +let add_vec_carry (xs, ys) = + assert (List.length xs = List.length ys); + let (carry, result) = + List.fold_right2 (fun x y (c, result) -> let (z, c) = add_bit_with_carry (x, y, c) in (c, z :: result)) xs ys (B0, []) + in + carry, result + +let add_vec (xs, ys) = snd (add_vec_carry (xs, ys)) + +let rec replicate_bits (bits, n) = + if Big_int.less_equal n Big_int.zero + then [] + else bits @ replicate_bits (bits, Big_int.sub n (Big_int.of_int 1)) + +let identity x = x + +let rec bits_of_big_int bit n = + if not (Big_int.equal bit Big_int.zero) + then + begin + if Big_int.greater (Big_int.div n bit) Big_int.zero + then B1 :: bits_of_big_int (Big_int.div bit (Big_int.of_int 2)) (Big_int.sub n bit) + else B0 :: bits_of_big_int (Big_int.div bit (Big_int.of_int 2)) n + end + else [] + +let add_vec_int (v, n) = + let n_bits = bits_of_big_int (Big_int.pow_int_positive 2 (List.length v - 1)) n in + add_vec(v, n_bits) + +let sub_vec (xs, ys) = add_vec (xs, add_vec_int (not_vec ys, (Big_int.of_int 1))) + +let sub_vec_int (v, n) = + let n_bits = bits_of_big_int (Big_int.pow_int_positive 2 (List.length v - 1)) n in + sub_vec(v, n_bits) + +let get_slice_int (n, m, o) = + let bits = bits_of_big_int (Big_int.pow_int_positive 2 (Big_int.add n o |> Big_int.to_int)) (Big_int.abs m) in + let bits = + if Big_int.less m Big_int.zero + then sub_vec (List.map (fun _ -> B0) bits, bits) + else bits + in + let slice = List.rev (take (Big_int.to_int n) (drop (Big_int.to_int o) (List.rev bits))) in + assert (Big_int.equal (Big_int.of_int (List.length slice)) n); + slice + +let hex_char = function + | '0' -> [B0; B0; B0; B0] + | '1' -> [B0; B0; B0; B1] + | '2' -> [B0; B0; B1; B0] + | '3' -> [B0; B0; B1; B1] + | '4' -> [B0; B1; B0; B0] + | '5' -> [B0; B1; B0; B1] + | '6' -> [B0; B1; B1; B0] + | '7' -> [B0; B1; B1; B1] + | '8' -> [B1; B0; B0; B0] + | '9' -> [B1; B0; B0; B1] + | 'A' | 'a' -> [B1; B0; B1; B0] + | 'B' | 'b' -> [B1; B0; B1; B1] + | 'C' | 'c' -> [B1; B1; B0; B0] + | 'D' | 'd' -> [B1; B1; B0; B1] + | 'E' | 'e' -> [B1; B1; B1; B0] + | 'F' | 'f' -> [B1; B1; B1; B1] + +let list_of_string s = + let rec aux i acc = + if i < 0 then acc + else aux (i-1) (s.[i] :: acc) + in aux (String.length s - 1) [] + +let bits_of_string str = + List.concat (List.map hex_char (list_of_string str)) + +let concat_str (str1, str2) = str1 ^ str2 + +let rec break n = function + | [] -> [] + | (_ :: _ as xs) -> [take n xs] @ break n (drop n xs) + +let string_of_bit = function + | B0 -> "0" + | B1 -> "1" + +let string_of_hex = function + | [B0; B0; B0; B0] -> "0" + | [B0; B0; B0; B1] -> "1" + | [B0; B0; B1; B0] -> "2" + | [B0; B0; B1; B1] -> "3" + | [B0; B1; B0; B0] -> "4" + | [B0; B1; B0; B1] -> "5" + | [B0; B1; B1; B0] -> "6" + | [B0; B1; B1; B1] -> "7" + | [B1; B0; B0; B0] -> "8" + | [B1; B0; B0; B1] -> "9" + | [B1; B0; B1; B0] -> "A" + | [B1; B0; B1; B1] -> "B" + | [B1; B1; B0; B0] -> "C" + | [B1; B1; B0; B1] -> "D" + | [B1; B1; B1; B0] -> "E" + | [B1; B1; B1; B1] -> "F" + +let string_of_bits bits = + if List.length bits mod 4 == 0 + then "0x" ^ String.concat "" (List.map string_of_hex (break 4 bits)) + else "0b" ^ String.concat "" (List.map string_of_bit bits) + +let hex_slice (str, n, m) = + let bits = List.concat (List.map hex_char (list_of_string (String.sub str 2 (String.length str - 2)))) in + let padding = replicate_bits([B0], n) in + let bits = padding @ bits in + let slice = List.rev (take (Big_int.to_int n) (drop (Big_int.to_int m) (List.rev bits))) in + slice + +let putchar n = + print_char (char_of_int (Big_int.to_int n)); + flush stdout + +let rec bits_of_int bit n = + if bit <> 0 + then + begin + if n / bit > 0 + then B1 :: bits_of_int (bit / 2) (n - bit) + else B0 :: bits_of_int (bit / 2) n + end + else [] + +let byte_of_int n = bits_of_int 128 n + +module BigIntHash = + struct + type t = Big_int.num + let equal i j = Big_int.equal i j + let hash i = Hashtbl.hash i + end + +module RAM = Hashtbl.Make(BigIntHash) + +let ram : int RAM.t = RAM.create 256 + +let write_ram' (addr_size, data_size, hex_ram, addr, data) = + let data = List.map (fun byte -> Big_int.to_int (uint byte)) (break 8 data) in + let rec write_byte i byte = + trace (Printf.sprintf "Store: %s 0x%02X" (Big_int.to_string (Big_int.add addr (Big_int.of_int i))) byte); + RAM.add ram (Big_int.add addr (Big_int.of_int i)) byte + in + List.iteri write_byte (List.rev data) + +let write_ram (addr_size, data_size, hex_ram, addr, data) = + write_ram' (addr_size, data_size, hex_ram, uint addr, data) + +let wram addr byte = + RAM.add ram addr byte + +let read_ram (addr_size, data_size, hex_ram, addr) = + let addr = uint addr in + let rec read_byte i = + if Big_int.equal i Big_int.zero + then [] + else + begin + let loc = Big_int.sub (Big_int.add addr i) (Big_int.of_int 1) in + let byte = try RAM.find ram loc with Not_found -> 0 in + trace (Printf.sprintf "Load: %s 0x%02X" (Big_int.to_string loc) byte); + byte_of_int byte @ read_byte (Big_int.sub i (Big_int.of_int 1)) + end + in + read_byte data_size + +let rec reverse_endianness bits = + if List.length bits <= 8 then bits else + reverse_endianness (drop 8 bits) @ (take 8 bits) + +(* FIXME: Casts can't be externed *) +let zcast_unit_vec x = [x] + +let shl_int (n, m) = Big_int.shift_left n (Big_int.to_int m) +let shr_int (n, m) = Big_int.shift_right n (Big_int.to_int m) + +let debug (str1, n, str2, v) = prerr_endline (str1 ^ Big_int.to_string n ^ str2 ^ string_of_bits v) + +let eq_string (str1, str2) = String.compare str1 str2 == 0 + +let lt_int (x, y) = Big_int.less x y + +let set_slice (out_len, slice_len, out, n, slice) = + let out = update_subrange(out, Big_int.add n (Big_int.of_int (List.length slice - 1)), n, slice) in + assert (List.length out = Big_int.to_int out_len); + out + +let set_slice_int (_, _, _, _) = assert false + +(* +let eq_real (x, y) = Num.eq_num x y +let lt_real (x, y) = Num.lt_num x y +let gt_real (x, y) = Num.gt_num x y +let lteq_real (x, y) = Num.le_num x y +let gteq_real (x, y) = Num.ge_num x y + +let round_down x = Num.big_int_of_num (Num.floor_num x) +let round_up x = Num.big_int_of_num (Num.ceiling_num x) +let quotient_real (x, y) = Num.div_num x y +let mult_real (x, y) = Num.mult_num x y +let real_power (x, y) = Num.power_num x (Num.num_of_big_int y) +let add_real (x, y) = Num.add_num x y +let sub_real (x, y) = Num.sub_num x y + +let abs_real x = Num.abs_num x + *) + +let lt (x, y) = Big_int.less x y +let gt (x, y) = Big_int.greater x y +let lteq (x, y) = Big_int.less_equal x y +let gteq (x, y) = Big_int.greater_equal x y + +let pow2 x = Big_int.pow_int x 2 + +let max_int (x, y) = Big_int.max x y +let min_int (x, y) = Big_int.min x y +let abs_int x = Big_int.abs x + +(* +let undefined_real () = Num.num_of_int 0 + +let real_of_string str = + try + let point = String.index str '.' in + let whole = Num.num_of_string (String.sub str 0 point) in + let frac_str = String.sub str (point + 1) (String.length str - (point + 1)) in + let frac = Num.div_num (Num.num_of_string frac_str) (Num.num_of_big_int (Big_int.pow_int_positive 10 (String.length frac_str))) in + Num.add_num whole frac + with + | Not_found -> Num.num_of_string str + +(* Not a very good sqrt implementation *) +let sqrt_real x = real_of_string (string_of_float (sqrt (Num.float_of_num x))) + *) + +let print_int (str, x) = + print_endline (str ^ Big_int.to_string x) + +let print_bits (str, xs) = + print_endline (str ^ string_of_bits xs) + +let reg_deref r = !r + +let string_of_zbit = function + | B0 -> "0" + | B1 -> "1" +let string_of_znat n = Big_int.to_string n +let string_of_zint n = Big_int.to_string n +let string_of_zunit () = "()" +let string_of_zbool = function + | true -> "true" + | false -> "false" +(* let string_of_zreal r = Num.string_of_num r *) +let string_of_zstring str = "\"" ^ String.escaped str ^ "\"" + +let rec string_of_list sep string_of = function + | [] -> "" + | [x] -> string_of x + | x::ls -> (string_of x) ^ sep ^ (string_of_list sep string_of ls) + +let zero_extend (vec, n) = + let m = Big_int.to_int n in + if m <= List.length vec + then take m vec + else replicate_bits ([B0], Big_int.of_int (m - List.length vec)) @ vec |
