From 2cd29cbd4c8f9a186b6480afd4e27ceee872d307 Mon Sep 17 00:00:00 2001 From: Thomas Walker Lynch Date: Mon, 17 Feb 2025 09:44:14 +0000 Subject: [PATCH] testing environment setup and namespace template for N32 tests --- .../{fill_template.py => fill_template} | 0 "developer/tool\360\237\226\211/clean" | 25 + "developer/tool\360\237\226\211/makefile" | 2 +- "developer/tool\360\237\226\211/release" | 16 +- .../tool\360\237\226\211/release_clean" | 30 ++ "developer/tool\360\237\226\211/release_ls" | 23 + release/x86_64/fedora41/glibc_2.40/libN.a | Bin 16002 -> 11716 bytes tester/cc/N32.lib.c | 457 ------------------ tester/cc/test_N32PN.cli.c | 364 ++++++++++++++ .../test_N32.cli.c" | 0 tester/python/#fill_templates.py# | 24 + tester/python/fill_template | 24 + tester/python/template_test_N32.py | 381 +++++++++++++++ "tester/tool\360\237\226\211/clean" | 25 + "tester/tool\360\237\226\211/make" | 4 +- "tester/tool\360\237\226\211/makefile" | 9 +- .../tool\360\237\226\211/release" | 2 +- "tester/tool\360\237\226\211/release_clean" | 28 ++ .../tool\360\237\226\211/release_pull" | 11 +- "tool_shared/bespoke\360\237\226\211/env" | 10 +- 20 files changed, 944 insertions(+), 491 deletions(-) rename developer/python/{fill_template.py => fill_template} (100%) create mode 100755 "developer/tool\360\237\226\211/clean" create mode 100755 "developer/tool\360\237\226\211/release_clean" create mode 100755 "developer/tool\360\237\226\211/release_ls" delete mode 100644 tester/cc/N32.lib.c create mode 100644 tester/cc/test_N32PN.cli.c rename "tester/cc\360\237\226\211/test_N32.cli.c" => "tester/deprecated\360\237\226\211/test_N32.cli.c" (100%) create mode 100644 tester/python/#fill_templates.py# create mode 100755 tester/python/fill_template create mode 100644 tester/python/template_test_N32.py create mode 100755 "tester/tool\360\237\226\211/clean" rename "tester/tool\360\237\226\211/release_test" => "tester/tool\360\237\226\211/release" (94%) create mode 100755 "tester/tool\360\237\226\211/release_clean" rename "tester/tool\360\237\226\211/pull_release" => "tester/tool\360\237\226\211/release_pull" (74%) diff --git a/developer/python/fill_template.py b/developer/python/fill_template similarity index 100% rename from developer/python/fill_template.py rename to developer/python/fill_template diff --git "a/developer/tool\360\237\226\211/clean" "b/developer/tool\360\237\226\211/clean" new file mode 100755 index 0000000..cbb86b8 --- /dev/null +++ "b/developer/tool\360\237\226\211/clean" @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +script_afp=$(realpath "${BASH_SOURCE[0]}") + +# input guards + + env_must_be="developer/tool🖉/env" + if [ "$ENV" != "$env_must_be" ]; then + echo "$(script_fp):: error: must be run in the $env_must_be environment" + exit 1 + fi + +set -e +set -x + + +cd "$REPO_HOME"/developer || exit 1 + +# remove library pulled from release and other scratchpad files + rm_na scratchpad/{makefile-cc.deps,*.o} || true + +# remove built executables + rm_na -f machine/* || true + +set +x +echo "$(script_fn) done." diff --git "a/developer/tool\360\237\226\211/makefile" "b/developer/tool\360\237\226\211/makefile" index 64bb614..56f2283 100644 --- "a/developer/tool\360\237\226\211/makefile" +++ "b/developer/tool\360\237\226\211/makefile" @@ -7,7 +7,7 @@ CFLAGS+=-Werror -include "$(RT-INCOMMON)/make/RT_0.h" LINKFLAGS+= -l$(PROJECT) LIBFILE=$(LIBDIR)/lib$(PROJECT).a -include $(RT-INCOMMON)/make/targets +include $(RT-INCOMMON)/make/targets_developer -include $(DEPFILE) diff --git "a/developer/tool\360\237\226\211/release" "b/developer/tool\360\237\226\211/release" index feb8bcf..8dc8993 100755 --- "a/developer/tool\360\237\226\211/release" +++ "b/developer/tool\360\237\226\211/release" @@ -11,9 +11,6 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") exit 1 fi -set -e -set -x - cd "$REPO_HOME"/developer || exit 1 if [ ! -d scratchpad ]; then @@ -21,15 +18,16 @@ set -x exit 1 fi +#set -e +#set -x + release_dir=$(release_dir) mkdir -p ${release_dir} - install_file scratchpad/libN.a ${release_dir} "ug+r" - - # header files - install_file {cc,cc🖉}/*.lib.c ${release_dir} "ug+r" - + install_file scratchpad/libN.a ${release_dir} "ug+r" || true + install_file cc🖉/*.lib.c ${release_dir} "ug+r" || true + install_file cc/*.lib.c ${release_dir} "ug+r" || true -set +x +#set +x echo "$(script_fn) done." diff --git "a/developer/tool\360\237\226\211/release_clean" "b/developer/tool\360\237\226\211/release_clean" new file mode 100755 index 0000000..52309e6 --- /dev/null +++ "b/developer/tool\360\237\226\211/release_clean" @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +script_afp=$(realpath "${BASH_SOURCE[0]}") + +# before running this, make library is built and is in the scratchpad directory + +# input guards + + env_must_be="developer/tool🖉/env" + if [ "$ENV" != "$env_must_be" ]; then + echo "$(script_fp):: error: must be run in the $env_must_be environment" + exit 1 + fi + +set -e +set -x + + cd "$REPO_HOME"/developer || exit 1 + + release_dir=$(release_dir) + + if [ ! -d ${release_dir} ]; then + echo "$(script_fp):: no release directory: " ${release_dir} + exit 1 + fi + + rm_na -rf ${release_dir}/* + +set +x +echo "$(script_fn) done." + diff --git "a/developer/tool\360\237\226\211/release_ls" "b/developer/tool\360\237\226\211/release_ls" new file mode 100755 index 0000000..52550b6 --- /dev/null +++ "b/developer/tool\360\237\226\211/release_ls" @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +script_afp=$(realpath "${BASH_SOURCE[0]}") + +# before running this, make library is built and is in the scratchpad directory + +# input guards + + env_must_be="developer/tool🖉/env" + if [ "$ENV" != "$env_must_be" ]; then + echo "$(script_fp):: error: must be run in the $env_must_be environment" + exit 1 + fi + + release_dir=$(release_dir) + + if [ ! -d ${release_dir} ]; then + echo "$(script_fp):: no release directory: " ${release_dir} + exit 1 + fi + + ls $@ ${release_dir} + + diff --git a/release/x86_64/fedora41/glibc_2.40/libN.a b/release/x86_64/fedora41/glibc_2.40/libN.a index 281841616e4f46c16fce99ea4aae41826b1aab65..15d0154df816a488f0fdd628ecd6deadac4e32e9 100644 GIT binary patch delta 2092 zcmb_cOHUI~6ux)b*ul~U3^J{QWk?AWLJOr0Z8wFTxG4`~Vq!xr&>%_aB)~=!7($G) z5|Z-+x-c46#-t04MkL0CE4p*xO5?^vV_dtb_end1#{wpqx!-xroHO73?%7=Xba$u2 zN+jd4c+4<{40<&_4I?p}WM0F#cNrnnjgX_`?Ax=C&{?-{9wByH5*)JzLkOLIXQCsM znUAmM%+ktgzO;&j{jjiXN^F)266TA=95HjVi-(y@eJisvT&zQqY0l+W3%UIAa{d8N zfbYTf1yNwWATv-VHf(Q!+q?yiSqmK6THvlFT9!lB0fo@2v?*jEB`pzaEIAUlm*h4t z$uTR*p{*o$v639Jl81@5pXOfp5p1(E95?omw70-a-T{NG0fub#nTM5Uh*g(aw&FG? z{0cS?WSFa=1->nj;^J(?9HcspCSoZrXV?$;l#w`iokMuHGU}`;FrD!EH6r3xAfwYWfpxQqPxPY zi}elURNb1)u>7>!-EY&I{mmjk_x!gYIS#9#`ltr8}=t4Q1@iPuB z{S*$ZK))vT|2P_P3Ovpz{tTne&S(9dj$`#}h#&4{6c!qbvymf#XEKSbE@B>lS8VUPZ7Ei9Mw01+ZQ~+sLEB7oG$uxGE3$D z5P1(aX_et_Rl#Fm={I1rCyBS9>K?89>)F5xx&%9(G`tOsH^_dR$UfvJL#Scm92q&# z?7UO?-S<_2v?~OE22?1ywqQN1Lc|w>mvmJP_!4e`8TFbaKSdg3qmA;yK%Ew5UffjW p$6iz+gT2E+3J}HmaDXwg7f}^h*T=ydO~QeDtnxUzfno3Z&;NLiPK5vf literal 16002 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 Y{69G9Z{sI&f>PWVP2;2o*2qc!3m?5w@&Et; diff --git a/tester/cc/N32.lib.c b/tester/cc/N32.lib.c deleted file mode 100644 index fba3c21..0000000 --- a/tester/cc/N32.lib.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - N32 - a processor native type - - For binary operations: a op b -> c - - See the document on the proper use of the Natural types. - - On the subject of multiple pointers indicating the same location in memory: - - When a routine has multiple results, and one or more of the result location - pointers point to the same storage, the routine will either return an error - status, or have defined behavior. - - When a routine has multiple operands, in any combination, those - pointers can point to the same location, and the routine will - function as advertised. - - When an operand functions as both an input and a result, perhaps due - to a result pointer pointing to the same place as an operand - pointer, the routine will function as advertised. (Internally the - routine might make a temporary copy of the operand to accomplish - this.) - -*/ - -#define N32·DEBUG - -#ifndef FACE -#define N32·IMPLEMENTATION -#define FACE -#endif - -//-------------------------------------------------------------------------------- -// Interface - -#ifndef N32·FACE -#define N32·FACE - - #include - #include - #include - #include - - //---------------------------------------- - // Instance Data (Declaration Only) - - typedef uint32_t Extent; - typedef uint32_t Digit; - - typedef struct N32·T N32·T; - - extern N32·T *N32·zero; - extern N32·T *N32·one; - extern N32·T *N32·all_one_bit; - extern N32·T *N32·lsb; - extern N32·T *N32·msb; - - //---------------------------------------- - // Return/Error Status and handlers - - typedef enum{ - N32·Status·ok = 0 - ,N32·Status·overflow = 1 - ,N32·Status·accumulator1_overflow = 2 - ,N32·Status·carry = 3 - ,N32·Status·borrow = 4 - ,N32·Status·undefined_divide_by_zero = 5 - ,N32·Status·undefined_modulus_zero = 6 - ,N32·Status·gt_max_shift_count = 7 - ,N32·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value - ,N32·Status·one_word_product = 9 - ,N32·Status·two_word_product = 10 - } N32·Status; - - typedef enum{ - N32·Order_lt = -1 - ,N32·Order_eq = 0 - ,N32·Order_gt = 1 - } N32·Order; - - typedef N32·T *( *N32·Allocate_MemoryFault )(Extent); - - //---------------------------------------- - // Interface - - typedef struct{ - - N32·T *(*allocate_array_zero)(Extent, N32·Allocate_MemoryFault); - N32·T *(*allocate_array)(Extent, N32·Allocate_MemoryFault); - void (*deallocate)(N32·T*); - - void (*copy)(N32·T*, N32·T*); - void (*bit_and)(N32·T*, N32·T*, N32·T*); - void (*bit_or)(N32·T*, N32·T*, N32·T*); - void (*bit_complement)(N32·T*, N32·T*); - void (*bit_twos_complement)(N32·T*, N32·T*); - N32·Order (*compare)(N32·T*, N32·T*); - bool (*lt)(N32·T*, N32·T*); - bool (*gt)(N32·T*, N32·T*); - bool (*eq)(N32·T*, N32·T*); - bool (*eq_zero)(N32·T*); - N32·Status (*accumulate)(N32·T *accumulator1 ,N32·T *accumulator0 ,...); - N32·Status (*add)(N32·T*, N32·T*, N32·T*); - bool (*increment)(N32·T *a); - N32·Status (*subtract)(N32·T*, N32·T*, N32·T*); - N32·Status (*multiply)(N32·T*, N32·T*, N32·T*, N32·T*); - N32·Status (*divide)(N32·T*, N32·T*, N32·T*, N32·T*); - N32·Status (*modulus)(N32·T*, N32·T*, N32·T*); - N32·Status (*shift_left)(Extent, N32·T*, N32·T*, N32·T*); - N32·Status (*shift_right)(Extent, N32·T*, N32·T*, N32·T*); - N32·Status (*arithmetic_shift_right)(Extent, N32·T*, N32·T*); - - N32·T* (*access)(N32·T*, Extent); - void (*from_uint32)(N32·T *destination ,uint32_t value); - } N32·Λ; - - Local const N32·Λ N32·λ; // initialized in the LOCAL section - -#endif - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef N32·IMPLEMENTATION - - // this part goes into the library - #ifndef LOCAL - - #include - #include - - struct N32·T{ - Digit d0; - }; - - N32·T N32·constant[4] = { - {.d0 = 0}, - {.d0 = 1}, - {.d0 = ~(uint32_t)0}, - {.d0 = 1 << 31} - }; - - N32·T *N32·zero = &N32·constant[0]; - N32·T *N32·one = &N32·constant[1]; - N32·T *N32·all_one_bit = &N32·constant[2]; - N32·T *N32·msb = &N32·constant[3]; - N32·T *N32·lsb = &N32·constant[1]; - - // the allocate an array of N32 - N32·T *N32·allocate_array(Extent extent ,N32·Allocate_MemoryFault memory_fault){ - N32·T *instance = malloc((extent + 1) * sizeof(N32·T) ); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - N32·T *N32·allocate_array_zero(Extent extent ,N32·Allocate_MemoryFault memory_fault){ - N32·T *instance = calloc( extent + 1 ,sizeof(N32·T) ); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - void N32·deallocate(N32·T *unencumbered){ - free(unencumbered); - } - - #endif - - // This part is included after the library user's code - #ifdef LOCAL - - // instance - - struct N32·T{ - Digit d0; - }; - - // temporary variables - // making these LOCAL rather than reserving one block in the library is thread safe - // allocating a block once is more efficient - // library code writes these, they are not on the interface - - Local N32·T N32·t[4]; - - - // allocation - - extern N32·T *N32·allocate_array(Extent, N32·Allocate_MemoryFault); - extern N32·T *N32·allocate_array_zero(Extent, N32·Allocate_MemoryFault); - extern void N32·deallocate(N32·T *); - - // so the user can access numbers in an array allocation - Local N32·T* N32·access(N32·T *array ,Extent index){ - return &array[index]; - } - - Local void N32·from_uint32(N32·T *destination ,uint32_t value){ - if(destination == NULL) return; - destination->d0 = value; - } - - // copy, convenience copy - - Local void N32·copy(N32·T *destination ,N32·T *source){ - if(source == destination) return; // that was easy! - *destination = *source; - } - - Local void N32·set_to_zero(N32·T *instance){ - instance->d0 = 0; - } - - Local void N32·set_to_one(N32·T *instance){ - instance->d0 = 1; - } - - // bit operations - - Local void N32·bit_and(N32·T *result, N32·T *a, N32·T *b){ - result->d0 = a->d0 & b->d0; - } - - // result can be one of the operands - Local void N32·bit_or(N32·T *result, N32·T *a, N32·T *b){ - result->d0 = a->d0 | b->d0; - } - - // result can the same as the operand - Local void N32·bit_complement(N32·T *result, N32·T *a){ - result->d0 = ~a->d0; - } - - // result can the same as the operand - Local void N32·bit_twos_complement(N32·T *result ,N32·T *a){ - result->d0 = ~a->d0 + 1; - } - - // test functions - - Local N32·Order N32·compare(N32·T *a, N32·T *b){ - if(a->d0 < b->d0) return N32·Order_lt; - if(a->d0 > b->d0) return N32·Order_gt; - return N32·Order_eq; - } - - Local bool N32·lt(N32·T *a ,N32·T *b){ - return a->d0 < b->d0; - } - - Local bool N32·gt(N32·T *a ,N32·T *b){ - return a->d0 > b->d0; - } - - Local bool N32·eq(N32·T *a ,N32·T *b){ - return a->d0 == b->d0; - } - - Local bool N32·eq_zero(N32·T *a){ - return a->d0 == 0; - } - - - // arithmetic operations - - // For a large number of summands for the lower precision Natural implementations, for accumulate/add/sub, the 'overflow' operand could overflow and thus this routine will halt and return N32·Status·accumulator1_overflow - // - // When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value. - Local N32·Status N32·accumulate(N32·T *accumulator1 ,N32·T *accumulator0 ,...){ - - va_list args; - va_start(args ,accumulator0); - uint32_t sum = accumulator0->d0; - uint32_t carry = 0; - N32·T *current; - - while( (current = va_arg(args ,N32·T *)) ){ - sum += current->d0; - if(sum < current->d0){ // Accumulator1 into carry - (carry)++; - if(carry == 0){ - va_end(args); - return N32·Status·accumulator1_overflow; - } - } - } - va_end(args); - - // wipes out prior value of accumulator1 - accumulator1->d0 = carry; - - return N32·Status·ok; - } - - Local N32·Status N32·add(N32·T *sum ,N32·T *a ,N32·T *b){ - uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0; - sum->d0 = (uint32_t)result; - return (result >> 32) ? N32·Status·carry : N32·Status·ok; - } - - Local bool N32·increment(N32·T *a){ - a->d0++; - return a->d0 == 0; - } - - Local N32·Status N32·subtract(N32·T *difference ,N32·T *a ,N32·T *b){ - uint64_t diff = (uint64_t) a->d0 - (uint64_t) b->d0; - difference->d0 = (uint32_t)diff; - return (diff > a->d0) ? N32·Status·borrow : N32·Status·ok; - } - - - Local N32·Status N32·multiply(N32·T *product1 ,N32·T *product0 ,N32·T *a ,N32·T *b){ - uint64_t product = (uint64_t)a->d0 * (uint64_t)b->d0; - product0->d0 = (uint32_t)product; - product1->d0 = (uint32_t)(product >> 32); - - if(product1->d0 == 0) return N32·Status·one_word_product; - return N32·Status·two_word_product; - } - - Local N32·Status N32·divide(N32·T *remainder ,N32·T *quotient ,N32·T *a ,N32·T *b){ - if(b->d0 == 0) return N32·Status·undefined_divide_by_zero; - - quotient->d0 = a->d0 / b->d0; - remainder->d0 = a->d0 - (quotient->d0 * b->d0); - - return N32·Status·ok; - } - - Local N32·Status N32·modulus(N32·T *remainder ,N32·T *a ,N32·T *b){ - if(b->d0 == 0) return N32·Status·undefined_modulus_zero; - uint32_t quotient = a->d0 / b->d0; - remainder->d0 = a->d0 - (quotient * b->d0); - return N32·Status·ok; - } - - // bit motion - - typedef uint32_t (*ShiftOp)(uint32_t, uint32_t); - - Local uint32_t shift_left_op(uint32_t value, uint32_t amount){ - return value << amount; - } - - Local uint32_t shift_right_op(uint32_t value, uint32_t amount){ - return value >> amount; - } - - // modifies all three of its operands - // in the case of duplicate operands this is the order: first modifies operand, then fill, then spill, - Local N32·Status N32·shift - ( - uint32_t shift_count - ,N32·T *spill - ,N32·T *operand - ,N32·T *fill - ,ShiftOp shift_op - ,ShiftOp complement_shift_op - ){ - - // If no result is needed, return immediately. - if(operand == NULL && spill == NULL) return N32·Status·ok; - - // Treat NULL operand as zero. - if(operand == NULL){ - operand = &N32·t[0]; - N32·copy(operand, N32·zero); - } - - // Shifting more than one word breaks our fill/spill model. - if(shift_count > 31) return N32·Status·gt_max_shift_count; - - // The given operand is still required after it is modified, so we copy it. - N32·T *given_operand = &N32·t[1]; - N32·copy(given_operand, operand); - - // Perform the shift - operand->d0 = shift_op(given_operand->d0, shift_count); - if(fill != NULL){ - fill->d0 = complement_shift_op(fill->d0, (32 - shift_count)); - N32·bit_or(operand, operand, fill); - } - if(spill != NULL){ - spill->d0 = shift_op(spill->d0, shift_count); - spill->d0 += complement_shift_op(given_operand->d0, (32 - shift_count)); - } - - return N32·Status·ok; - } - - // Define concrete shift functions using valid C function pointers - Local N32·Status - N32·shift_left(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){ - return N32·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); - } - - Local N32·Status - N32·shift_right(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){ - return N32·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); - } - - Local N32·Status - N32·arithmetic_shift_right(uint32_t shift_count, N32·T *operand, N32·T *spill){ - - // Guard against excessive shift counts - if(shift_count > 31) return N32·Status·gt_max_shift_count; - - // A NULL operand is treated as zero - if(operand == NULL){ - operand = &N32·t[0]; - N32·copy(operand, N32·zero); - } - - // Pick the fill value based on the sign bit - N32·T *fill = (operand->d0 & 0x80000000) ? N32·all_one_bit : N32·zero; - - // Call shift_right with the appropriate fill - return N32·shift_right(shift_count, spill, operand, fill); - } - - Local const N32·Λ N32·λ = { - - .allocate_array = N32·allocate_array - ,.allocate_array_zero = N32·allocate_array_zero - ,.deallocate = N32·deallocate - - ,.copy = N32·copy - ,.bit_and = N32·bit_and - ,.bit_or = N32·bit_or - ,.bit_complement = N32·bit_complement - ,.bit_twos_complement = N32·bit_twos_complement - ,.compare = N32·compare - ,.lt = N32·lt - ,.gt = N32·gt - ,.eq = N32·eq - ,.eq_zero = N32·eq_zero - ,.accumulate = N32·accumulate - ,.add = N32·add - ,.increment = N32·increment - ,.subtract = N32·subtract - ,.multiply = N32·multiply - ,.divide = N32·divide - ,.modulus = N32·modulus - ,.shift_left = N32·shift_left - ,.shift_right = N32·shift_right - ,.arithmetic_shift_right = N32·arithmetic_shift_right - - ,.access = N32·access - ,.from_uint32 = N32·from_uint32 - }; - - #endif - -#endif diff --git a/tester/cc/test_N32PN.cli.c b/tester/cc/test_N32PN.cli.c new file mode 100644 index 0000000..e17581a --- /dev/null +++ b/tester/cc/test_N32PN.cli.c @@ -0,0 +1,364 @@ +#include +#include +#include +#include + +// Enable interface section +#define FACE +#include "N32PN.lib.c" +#undef FACE + +// Jump buffer for signal handling +static sigjmp_buf jump_buffer; + +// Signal handler for catching fatal errors +void signal_handler(int signal){ + siglongjmp(jump_buffer ,1); // Jump back to test_head on error +} + +// Test function prototypes +bool test_copy(); +bool test_bitwise_operations(); +bool test_comparisons(); +bool test_arithmetic(); +bool test_shifts(); + +// Test array (null-terminated) +typedef bool (*TestFunction)(); +typedef struct{ + TestFunction function; + const char *name; +}TestEntry; + +TestEntry test_list[] = { + {test_copy ,"test_copy"} + ,{test_bitwise_operations ,"test_bitwise_operations"} + ,{test_comparisons ,"test_comparisons"} + ,{test_arithmetic ,"test_arithmetic"} + ,{test_shifts ,"test_shifts"} + ,{NULL ,NULL} // Null termination +}; + +// The test runner +int test_head(){ + int pass_count = 0; + int fail_count = 0; + + // Set up signal handlers + signal(SIGSEGV ,signal_handler); // Catch segmentation faults + signal(SIGFPE ,signal_handler); // Catch floating point errors + signal(SIGABRT ,signal_handler); // Catch abort() calls + + for(TestEntry *entry = test_list; entry->function != NULL; entry++){ + if( sigsetjmp(jump_buffer ,1) == 0 ){ + // Run the test normally + if( !entry->function() ){ + printf("Failed: %s\n" ,entry->name); + fail_count++; + }else{ + pass_count++; + } + }else{ + // If a signal was caught + printf("Failed due to signaling: %s\n" ,entry->name); + fail_count++; + } + } + + printf("Tests passed: %d\n" ,pass_count); + printf("Tests failed: %d\n" ,fail_count); + return (fail_count == 0) ? 0 : 1; +} + +// Main function +int main(int argc ,char **argv){ + return test_head(); +} + +//------------------------------------------------------------------------------ +// Test Implementations +//------------------------------------------------------------------------------ + +bool test_copy(){ + // Allocate memory + N32PN·T *array = N32PN·λ.allocate_array(2 ,NULL); + if( !array ) return false; + + // Access elements via access function + N32PN·T *a = N32PN·λ.access(array ,0); + N32PN·T *b = N32PN·λ.access(array ,1); + + // Assign value and copy + N32PN·λ.from_uint32(a ,42); + N32PN·λ.copy(b ,a); + + bool success = ( N32PN·λ.compare(b ,a) == N32PN·Order_eq ); + N32PN·λ.deallocate(array); + return success; +} + +bool test_arithmetic(){ + // Allocate memory + N32PN·T *array = N32PN·λ.allocate_array(3 ,NULL); + if( !array ) return false; + + N32PN·T *a = N32PN·λ.access(array ,0); + N32PN·T *b = N32PN·λ.access(array ,1); + N32PN·T *result = N32PN·λ.access(array ,2); + + N32PN·λ.from_uint32(a ,20); + N32PN·λ.from_uint32(b ,22); + + if( N32PN·λ.add(result ,a ,b) != N32PN·Status·ok ) return false; + if( N32PN·λ.compare(result ,N32PN·λ.access(array ,0)) != N32PN·Order_gt ) return false; + + if( N32PN·λ.subtract(result ,b ,a) != N32PN·Status·ok ) return false; + if( N32PN·λ.compare(result ,N32PN·λ.access(array ,0)) != N32PN·Order_lt ) return false; + + N32PN·λ.deallocate(array); + return true; +} + +bool test_bitwise_operations(){ + // Allocate memory + N32PN·T *array = N32PN·λ.allocate_array(3, NULL); + if(!array) return false; + + N32PN·T *a = N32PN·λ.access(array, 0); + N32PN·T *b = N32PN·λ.access(array, 1); + N32PN·T *result = N32PN·λ.access(array, 2); + + // a = 0x0F0F0F0F, b = 0xF0F0F0F0 + N32PN·λ.from_uint32(a, 0x0F0F0F0F); + N32PN·λ.from_uint32(b, 0xF0F0F0F0); + + // bit_and => expect 0x00000000 + N32PN·λ.bit_and(result, a, b); + N32PN·λ.from_uint32(a, 0x00000000); + if(N32PN·λ.compare(result, a) != N32PN·Order_eq){ + N32PN·λ.deallocate(array); + return false; + } + + // Reset a to 0x0F0F0F0F for next tests + N32PN·λ.from_uint32(a, 0x0F0F0F0F); + + // bit_or => expect 0xFFFFFFFF + N32PN·λ.bit_or(result, a, b); + N32PN·λ.from_uint32(b, 0xFFFFFFFF); + if(N32PN·λ.compare(result, b) != N32PN·Order_eq){ + N32PN·λ.deallocate(array); + return false; + } + + // bit_complement(a=0x0F0F0F0F) => expect 0xF0F0F0F0 + N32PN·λ.from_uint32(a, 0x0F0F0F0F); + N32PN·λ.bit_complement(result, a); + N32PN·λ.from_uint32(b, 0xF0F0F0F0); + if(N32PN·λ.compare(result, b) != N32PN·Order_eq){ + N32PN·λ.deallocate(array); + return false; + } + + // bit_twos_complement(a=0x0F0F0F0F) => expect 0xF0F0F0F1 + N32PN·λ.from_uint32(a, 0x0F0F0F0F); + N32PN·λ.bit_twos_complement(result, a); + N32PN·λ.from_uint32(b, 0xF0F0F0F1); + if(N32PN·λ.compare(result, b) != N32PN·Order_eq){ + N32PN·λ.deallocate(array); + return false; + } + + N32PN·λ.deallocate(array); + return true; +} + +bool test_comparisons(){ + // Allocate memory + N32PN·T *array = N32PN·λ.allocate_array(3, NULL); + if(!array) return false; + + N32PN·T *a = N32PN·λ.access(array, 0); + N32PN·T *b = N32PN·λ.access(array, 1); + N32PN·T *c = N32PN·λ.access(array, 2); + + // First set: a=0, b=42, c=42 + N32PN·λ.from_uint32(a, 0); + N32PN·λ.from_uint32(b, 42); + N32PN·λ.from_uint32(c, 42); + + // eq_zero(a) => true + if(!N32PN·λ.eq_zero(a)){ + N32PN·λ.deallocate(array); + return false; + } + // eq_zero(b) => false + if(N32PN·λ.eq_zero(b)){ + N32PN·λ.deallocate(array); + return false; + } + // eq(b, c) => true + if(!N32PN·λ.eq(b, c)){ + N32PN·λ.deallocate(array); + return false; + } + // eq(a, b) => false + if(N32PN·λ.eq(a, b)){ + N32PN·λ.deallocate(array); + return false; + } + // compare(a, b) => N32PN·Order_lt + if(N32PN·λ.compare(a, b) != N32PN·Order_lt){ + N32PN·λ.deallocate(array); + return false; + } + // compare(b, a) => N32PN·Order_gt + if(N32PN·λ.compare(b, a) != N32PN·Order_gt){ + N32PN·λ.deallocate(array); + return false; + } + // compare(b, c) => N32PN·Order_eq + if(N32PN·λ.compare(b, c) != N32PN·Order_eq){ + N32PN·λ.deallocate(array); + return false; + } + // lt(a, b) => true, gt(b, a) => true + if(!N32PN·λ.lt(a, b) || !N32PN·λ.gt(b, a)){ + N32PN·λ.deallocate(array); + return false; + } + + // Second set: a=100, b=50 + N32PN·λ.from_uint32(a, 100); + N32PN·λ.from_uint32(b, 50); + if(N32PN·λ.compare(a, b) != N32PN·Order_gt){ + N32PN·λ.deallocate(array); + return false; + } + // eq_zero(a) => false + if(N32PN·λ.eq_zero(a)){ + N32PN·λ.deallocate(array); + return false; + } + // eq_zero(b) => false + if(N32PN·λ.eq_zero(b)){ + N32PN·λ.deallocate(array); + return false; + } + + N32PN·λ.deallocate(array); + return true; +} + +bool test_shifts(){ + // Allocate memory for operand, fill, spill + N32PN·T *array = N32PN·λ.allocate_array(3, NULL); + if(!array) return false; + + N32PN·T *operand = N32PN·λ.access(array, 0); + N32PN·T *fill = N32PN·λ.access(array, 1); + N32PN·T *spill = N32PN·λ.access(array, 2); + + // Subtest A: shift_left(4) with operand=1 => expect operand=16, fill=0, spill=0 + N32PN·λ.from_uint32(operand, 1); + N32PN·λ.from_uint32(fill, 0); + N32PN·λ.from_uint32(spill, 0); + if(N32PN·λ.shift_left(4, spill, operand, fill) != N32PN·Status·ok){ + N32PN·λ.deallocate(array); + return false; + } + N32PN·T *temp = N32PN·λ.allocate_array(1, NULL); + if(!temp){ + N32PN·λ.deallocate(array); + return false; + } + N32PN·λ.from_uint32(temp, 16); + if(N32PN·λ.compare(operand, temp) != N32PN·Order_eq){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + if(N32PN·λ.compare(fill, N32PN·zero) != N32PN·Order_eq){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + if(N32PN·λ.compare(spill, N32PN·zero) != N32PN·Order_eq){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + + // Subtest B: shift_left(1) with operand=0x80000000 => expect operand=0, spill=1 + N32PN·λ.from_uint32(operand, 0x80000000); + N32PN·λ.from_uint32(fill, 0); + N32PN·λ.from_uint32(spill, 0); + if(N32PN·λ.shift_left(1, spill, operand, fill) != N32PN·Status·ok){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + if(!N32PN·λ.eq_zero(operand)){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + N32PN·λ.from_uint32(temp, 1); + if(N32PN·λ.compare(spill, temp) != N32PN·Order_eq){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + + // Subtest C: shift_right(1) with operand=0x80000000 => expect operand=0x40000000, spill=0 + N32PN·λ.from_uint32(operand, 0x80000000); + N32PN·λ.from_uint32(fill, 0); + N32PN·λ.from_uint32(spill, 0); + if(N32PN·λ.shift_right(1, spill, operand, fill) != N32PN·Status·ok){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + N32PN·λ.from_uint32(temp, 0x40000000); + if(N32PN·λ.compare(operand, temp) != N32PN·Order_eq){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + if(!N32PN·λ.eq_zero(spill)){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + + // Subtest D: arithmetic_shift_right(1) with operand=0x80000000 => expect operand=0xC0000000, spill=0 + N32PN·λ.from_uint32(operand, 0x80000000); + N32PN·λ.from_uint32(spill, 0); + if(N32PN·λ.arithmetic_shift_right(1, operand, spill) != N32PN·Status·ok){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + N32PN·λ.from_uint32(temp, 0xC0000000); + if(N32PN·λ.compare(operand, temp) != N32PN·Order_eq){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + if(!N32PN·λ.eq_zero(spill)){ + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return false; + } + + N32PN·λ.deallocate(temp); + N32PN·λ.deallocate(array); + return true; +} + + + +// Include the local section of N32PN.lib.c for testing +#define LOCAL +#include "N32PN.lib.c" +#undef LOCAL diff --git "a/tester/cc\360\237\226\211/test_N32.cli.c" "b/tester/deprecated\360\237\226\211/test_N32.cli.c" similarity index 100% rename from "tester/cc\360\237\226\211/test_N32.cli.c" rename to "tester/deprecated\360\237\226\211/test_N32.cli.c" diff --git a/tester/python/#fill_templates.py# b/tester/python/#fill_templates.py# new file mode 100644 index 0000000..95519a3 --- /dev/null +++ b/tester/python/#fill_templates.py# @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +import sys +from template_test_N32 import test_N32 + +def write(code ,basename): + filepath = "../cc/" + "test_" + basename + ".cli.c" + with open(filepath, "w") as f: + f.write(code) + print("Generated " + filepath) + + +def main(): + """ + generates `.c` source code from templates + """ + + # base line test N32 test + type_name = "N32PN" + code = test_N32(namespace = type_name) + write(code ,type_name); + +if __name__ == "__main__": + main() diff --git a/tester/python/fill_template b/tester/python/fill_template new file mode 100755 index 0000000..95519a3 --- /dev/null +++ b/tester/python/fill_template @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +import sys +from template_test_N32 import test_N32 + +def write(code ,basename): + filepath = "../cc/" + "test_" + basename + ".cli.c" + with open(filepath, "w") as f: + f.write(code) + print("Generated " + filepath) + + +def main(): + """ + generates `.c` source code from templates + """ + + # base line test N32 test + type_name = "N32PN" + code = test_N32(namespace = type_name) + write(code ,type_name); + +if __name__ == "__main__": + main() diff --git a/tester/python/template_test_N32.py b/tester/python/template_test_N32.py new file mode 100644 index 0000000..e2211d4 --- /dev/null +++ b/tester/python/template_test_N32.py @@ -0,0 +1,381 @@ +# {NAMESPACE} must be a N32 type. +# +# test_N32 can be used to test any 32 bit natural number types. As examples: N32PN the processor native type; N32_4_by_8 a 32 bit natural number type made of 4 digits, where each digit is 8 bits. +# + +def test_N32(namespace: str) -> str: + """ + Returns a source code file for cc. + """ + template = template_test_N32() + code = template.format( + NAMESPACE = namespace + ) + return code + +def template_test_N32(): + return r'''#include +#include +#include +#include + +// Enable interface section +#define FACE +#include "{NAMESPACE}.lib.c" +#undef FACE + +// Jump buffer for signal handling +static sigjmp_buf jump_buffer; + +// Signal handler for catching fatal errors +void signal_handler(int signal){{ + siglongjmp(jump_buffer ,1); // Jump back to test_head on error +}} + +// Test function prototypes +bool test_copy(); +bool test_bitwise_operations(); +bool test_comparisons(); +bool test_arithmetic(); +bool test_shifts(); + +// Test array (null-terminated) +typedef bool (*TestFunction)(); +typedef struct{{ + TestFunction function; + const char *name; +}}TestEntry; + +TestEntry test_list[] = {{ + {{test_copy ,"test_copy"}} + ,{{test_bitwise_operations ,"test_bitwise_operations"}} + ,{{test_comparisons ,"test_comparisons"}} + ,{{test_arithmetic ,"test_arithmetic"}} + ,{{test_shifts ,"test_shifts"}} + ,{{NULL ,NULL}} // Null termination +}}; + +// The test runner +int test_head(){{ + int pass_count = 0; + int fail_count = 0; + + // Set up signal handlers + signal(SIGSEGV ,signal_handler); // Catch segmentation faults + signal(SIGFPE ,signal_handler); // Catch floating point errors + signal(SIGABRT ,signal_handler); // Catch abort() calls + + for(TestEntry *entry = test_list; entry->function != NULL; entry++){{ + if( sigsetjmp(jump_buffer ,1) == 0 ){{ + // Run the test normally + if( !entry->function() ){{ + printf("Failed: %s\n" ,entry->name); + fail_count++; + }}else{{ + pass_count++; + }} + }}else{{ + // If a signal was caught + printf("Failed due to signaling: %s\n" ,entry->name); + fail_count++; + }} + }} + + printf("Tests passed: %d\n" ,pass_count); + printf("Tests failed: %d\n" ,fail_count); + return (fail_count == 0) ? 0 : 1; +}} + +// Main function +int main(int argc ,char **argv){{ + return test_head(); +}} + +//------------------------------------------------------------------------------ +// Test Implementations +//------------------------------------------------------------------------------ + +bool test_copy(){{ + // Allocate memory + {NAMESPACE}·T *array = {NAMESPACE}·λ.allocate_array(2 ,NULL); + if( !array ) return false; + + // Access elements via access function + {NAMESPACE}·T *a = {NAMESPACE}·λ.access(array ,0); + {NAMESPACE}·T *b = {NAMESPACE}·λ.access(array ,1); + + // Assign value and copy + {NAMESPACE}·λ.from_uint32(a ,42); + {NAMESPACE}·λ.copy(b ,a); + + bool success = ( {NAMESPACE}·λ.compare(b ,a) == {NAMESPACE}·Order_eq ); + {NAMESPACE}·λ.deallocate(array); + return success; +}} + +bool test_arithmetic(){{ + // Allocate memory + {NAMESPACE}·T *array = {NAMESPACE}·λ.allocate_array(3 ,NULL); + if( !array ) return false; + + {NAMESPACE}·T *a = {NAMESPACE}·λ.access(array ,0); + {NAMESPACE}·T *b = {NAMESPACE}·λ.access(array ,1); + {NAMESPACE}·T *result = {NAMESPACE}·λ.access(array ,2); + + {NAMESPACE}·λ.from_uint32(a ,20); + {NAMESPACE}·λ.from_uint32(b ,22); + + if( {NAMESPACE}·λ.add(result ,a ,b) != {NAMESPACE}·Status·ok ) return false; + if( {NAMESPACE}·λ.compare(result ,{NAMESPACE}·λ.access(array ,0)) != {NAMESPACE}·Order_gt ) return false; + + if( {NAMESPACE}·λ.subtract(result ,b ,a) != {NAMESPACE}·Status·ok ) return false; + if( {NAMESPACE}·λ.compare(result ,{NAMESPACE}·λ.access(array ,0)) != {NAMESPACE}·Order_lt ) return false; + + {NAMESPACE}·λ.deallocate(array); + return true; +}} + +bool test_bitwise_operations(){{ + // Allocate memory + {NAMESPACE}·T *array = {NAMESPACE}·λ.allocate_array(3, NULL); + if(!array) return false; + + {NAMESPACE}·T *a = {NAMESPACE}·λ.access(array, 0); + {NAMESPACE}·T *b = {NAMESPACE}·λ.access(array, 1); + {NAMESPACE}·T *result = {NAMESPACE}·λ.access(array, 2); + + // a = 0x0F0F0F0F, b = 0xF0F0F0F0 + {NAMESPACE}·λ.from_uint32(a, 0x0F0F0F0F); + {NAMESPACE}·λ.from_uint32(b, 0xF0F0F0F0); + + // bit_and => expect 0x00000000 + {NAMESPACE}·λ.bit_and(result, a, b); + {NAMESPACE}·λ.from_uint32(a, 0x00000000); + if({NAMESPACE}·λ.compare(result, a) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + // Reset a to 0x0F0F0F0F for next tests + {NAMESPACE}·λ.from_uint32(a, 0x0F0F0F0F); + + // bit_or => expect 0xFFFFFFFF + {NAMESPACE}·λ.bit_or(result, a, b); + {NAMESPACE}·λ.from_uint32(b, 0xFFFFFFFF); + if({NAMESPACE}·λ.compare(result, b) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + // bit_complement(a=0x0F0F0F0F) => expect 0xF0F0F0F0 + {NAMESPACE}·λ.from_uint32(a, 0x0F0F0F0F); + {NAMESPACE}·λ.bit_complement(result, a); + {NAMESPACE}·λ.from_uint32(b, 0xF0F0F0F0); + if({NAMESPACE}·λ.compare(result, b) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + // bit_twos_complement(a=0x0F0F0F0F) => expect 0xF0F0F0F1 + {NAMESPACE}·λ.from_uint32(a, 0x0F0F0F0F); + {NAMESPACE}·λ.bit_twos_complement(result, a); + {NAMESPACE}·λ.from_uint32(b, 0xF0F0F0F1); + if({NAMESPACE}·λ.compare(result, b) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + {NAMESPACE}·λ.deallocate(array); + return true; +}} + +bool test_comparisons(){{ + // Allocate memory + {NAMESPACE}·T *array = {NAMESPACE}·λ.allocate_array(3, NULL); + if(!array) return false; + + {NAMESPACE}·T *a = {NAMESPACE}·λ.access(array, 0); + {NAMESPACE}·T *b = {NAMESPACE}·λ.access(array, 1); + {NAMESPACE}·T *c = {NAMESPACE}·λ.access(array, 2); + + // First set: a=0, b=42, c=42 + {NAMESPACE}·λ.from_uint32(a, 0); + {NAMESPACE}·λ.from_uint32(b, 42); + {NAMESPACE}·λ.from_uint32(c, 42); + + // eq_zero(a) => true + if(!{NAMESPACE}·λ.eq_zero(a)){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // eq_zero(b) => false + if({NAMESPACE}·λ.eq_zero(b)){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // eq(b, c) => true + if(!{NAMESPACE}·λ.eq(b, c)){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // eq(a, b) => false + if({NAMESPACE}·λ.eq(a, b)){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // compare(a, b) => {NAMESPACE}·Order_lt + if({NAMESPACE}·λ.compare(a, b) != {NAMESPACE}·Order_lt){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // compare(b, a) => {NAMESPACE}·Order_gt + if({NAMESPACE}·λ.compare(b, a) != {NAMESPACE}·Order_gt){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // compare(b, c) => {NAMESPACE}·Order_eq + if({NAMESPACE}·λ.compare(b, c) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // lt(a, b) => true, gt(b, a) => true + if(!{NAMESPACE}·λ.lt(a, b) || !{NAMESPACE}·λ.gt(b, a)){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + // Second set: a=100, b=50 + {NAMESPACE}·λ.from_uint32(a, 100); + {NAMESPACE}·λ.from_uint32(b, 50); + if({NAMESPACE}·λ.compare(a, b) != {NAMESPACE}·Order_gt){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // eq_zero(a) => false + if({NAMESPACE}·λ.eq_zero(a)){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + // eq_zero(b) => false + if({NAMESPACE}·λ.eq_zero(b)){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + {NAMESPACE}·λ.deallocate(array); + return true; +}} + +bool test_shifts(){{ + // Allocate memory for operand, fill, spill + {NAMESPACE}·T *array = {NAMESPACE}·λ.allocate_array(3, NULL); + if(!array) return false; + + {NAMESPACE}·T *operand = {NAMESPACE}·λ.access(array, 0); + {NAMESPACE}·T *fill = {NAMESPACE}·λ.access(array, 1); + {NAMESPACE}·T *spill = {NAMESPACE}·λ.access(array, 2); + + // Subtest A: shift_left(4) with operand=1 => expect operand=16, fill=0, spill=0 + {NAMESPACE}·λ.from_uint32(operand, 1); + {NAMESPACE}·λ.from_uint32(fill, 0); + {NAMESPACE}·λ.from_uint32(spill, 0); + if({NAMESPACE}·λ.shift_left(4, spill, operand, fill) != {NAMESPACE}·Status·ok){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + {NAMESPACE}·T *temp = {NAMESPACE}·λ.allocate_array(1, NULL); + if(!temp){{ + {NAMESPACE}·λ.deallocate(array); + return false; + }} + {NAMESPACE}·λ.from_uint32(temp, 16); + if({NAMESPACE}·λ.compare(operand, temp) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + if({NAMESPACE}·λ.compare(fill, {NAMESPACE}·zero) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + if({NAMESPACE}·λ.compare(spill, {NAMESPACE}·zero) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + // Subtest B: shift_left(1) with operand=0x80000000 => expect operand=0, spill=1 + {NAMESPACE}·λ.from_uint32(operand, 0x80000000); + {NAMESPACE}·λ.from_uint32(fill, 0); + {NAMESPACE}·λ.from_uint32(spill, 0); + if({NAMESPACE}·λ.shift_left(1, spill, operand, fill) != {NAMESPACE}·Status·ok){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + if(!{NAMESPACE}·λ.eq_zero(operand)){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + {NAMESPACE}·λ.from_uint32(temp, 1); + if({NAMESPACE}·λ.compare(spill, temp) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + // Subtest C: shift_right(1) with operand=0x80000000 => expect operand=0x40000000, spill=0 + {NAMESPACE}·λ.from_uint32(operand, 0x80000000); + {NAMESPACE}·λ.from_uint32(fill, 0); + {NAMESPACE}·λ.from_uint32(spill, 0); + if({NAMESPACE}·λ.shift_right(1, spill, operand, fill) != {NAMESPACE}·Status·ok){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + {NAMESPACE}·λ.from_uint32(temp, 0x40000000); + if({NAMESPACE}·λ.compare(operand, temp) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + if(!{NAMESPACE}·λ.eq_zero(spill)){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + // Subtest D: arithmetic_shift_right(1) with operand=0x80000000 => expect operand=0xC0000000, spill=0 + {NAMESPACE}·λ.from_uint32(operand, 0x80000000); + {NAMESPACE}·λ.from_uint32(spill, 0); + if({NAMESPACE}·λ.arithmetic_shift_right(1, operand, spill) != {NAMESPACE}·Status·ok){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + {NAMESPACE}·λ.from_uint32(temp, 0xC0000000); + if({NAMESPACE}·λ.compare(operand, temp) != {NAMESPACE}·Order_eq){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + if(!{NAMESPACE}·λ.eq_zero(spill)){{ + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return false; + }} + + {NAMESPACE}·λ.deallocate(temp); + {NAMESPACE}·λ.deallocate(array); + return true; +}} + + + +// Include the local section of {NAMESPACE}.lib.c for testing +#define LOCAL +#include "{NAMESPACE}.lib.c" +#undef LOCAL +''' diff --git "a/tester/tool\360\237\226\211/clean" "b/tester/tool\360\237\226\211/clean" new file mode 100755 index 0000000..cebc4c0 --- /dev/null +++ "b/tester/tool\360\237\226\211/clean" @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +script_afp=$(realpath "${BASH_SOURCE[0]}") + +# input guards + + env_must_be="tester/tool🖉/env" + if [ "$ENV" != "$env_must_be" ]; then + echo "$(script_fp):: error: must be run in the $env_must_be environment" + exit 1 + fi + +set -e +set -x + + +cd "$REPO_HOME"/tester || exit 1 + +# remove library pulled from release and other scratchpad files + rm_na scratchpad/{makefile-cc.deps,*.o} || true + +# remove built executables + rm_na -f machine/* || true + +set +x +echo "$(script_fn) done." diff --git "a/tester/tool\360\237\226\211/make" "b/tester/tool\360\237\226\211/make" index e0f787f..ed0e7c5 100755 --- "a/tester/tool\360\237\226\211/make" +++ "b/tester/tool\360\237\226\211/make" @@ -12,9 +12,9 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") set -e set -x -cd "$REPO_HOME"/tester || exit 1 + cd "$REPO_HOME"/tester || exit 1 -/bin/make -f tool🖉/makefile $@ + /bin/make -f tool🖉/makefile $@ set +x echo "$(script_fn) done." diff --git "a/tester/tool\360\237\226\211/makefile" "b/tester/tool\360\237\226\211/makefile" index a0da057..9b933d5 100644 --- "a/tester/tool\360\237\226\211/makefile" +++ "b/tester/tool\360\237\226\211/makefile" @@ -1,5 +1,4 @@ - RT-INCOMMON:=$(REPO_HOME)/tool_shared/third_party/RT-project-share/release include $(RT-INCOMMON)/make/environment_RT_0 @@ -8,11 +7,5 @@ CFLAGS+=-Werror -include "$(RT-INCOMMON)/make/RT_0.h" LINKFLAGS+= -l$(PROJECT) LIBFILE=$(LIBDIR)/lib$(PROJECT).a -include $(RT-INCOMMON)/make/targets +include $(RT-INCOMMON)/make/targets_tester -include $(DEPFILE) - - - - - - diff --git "a/tester/tool\360\237\226\211/release_test" "b/tester/tool\360\237\226\211/release" similarity index 94% rename from "tester/tool\360\237\226\211/release_test" rename to "tester/tool\360\237\226\211/release" index 3d31406..ecbf3ff 100755 --- "a/tester/tool\360\237\226\211/release_test" +++ "b/tester/tool\360\237\226\211/release" @@ -1,7 +1,7 @@ #!/usr/bin/env bash script_afp=$(realpath "${BASH_SOURCE[0]}") -# release test machine code +# include tests in the project release # input guards diff --git "a/tester/tool\360\237\226\211/release_clean" "b/tester/tool\360\237\226\211/release_clean" new file mode 100755 index 0000000..2e0da45 --- /dev/null +++ "b/tester/tool\360\237\226\211/release_clean" @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +script_afp=$(realpath "${BASH_SOURCE[0]}") + +# input guards + + env_must_be="tester/tool🖉/env" + if [ "$ENV" != "$env_must_be" ]; then + echo "$(script_fp):: error: must be run in the $env_must_be environment" + exit 1 + fi + +set -e +set -x + + +cd "$REPO_HOME"/tester || exit 1 + +# remove library pulled from release and other scratchpad files + rm_na -rf scratchpad/* || true + +# remove cc files pulled from release + rm_na -f cc/* || true + +# remove built executables + rm_na -f machine/* || true + +set +x +echo "$(script_fn) done." diff --git "a/tester/tool\360\237\226\211/pull_release" "b/tester/tool\360\237\226\211/release_pull" similarity index 74% rename from "tester/tool\360\237\226\211/pull_release" rename to "tester/tool\360\237\226\211/release_pull" index a083b91..7c1182e 100755 --- "a/tester/tool\360\237\226\211/pull_release" +++ "b/tester/tool\360\237\226\211/release_pull" @@ -1,7 +1,7 @@ #!/usr/bin/env bash script_afp=$(realpath "${BASH_SOURCE[0]}") -# before running this script, gather everything needed for the release on the scratchpad +# pulls the library and include files down from the project release directory # input guards @@ -11,9 +11,6 @@ script_afp=$(realpath "${BASH_SOURCE[0]}") exit 1 fi -set -e -set -x - cd "$REPO_HOME"/tester || exit 1 if [ ! -d scratchpad ]; then @@ -28,10 +25,8 @@ set -x exit 1 fi + cp -f ${release_dir}/libN.a scratchpad || true + cp -f ${release_dir}/*.lib.c cc || true - cp ${release_dir}/libN.a scratchpad || true - cp ${release_dir}/*.lib.c cc || true - -set +x echo "$(script_fn) done." diff --git "a/tool_shared/bespoke\360\237\226\211/env" "b/tool_shared/bespoke\360\237\226\211/env" index f9671cc..0ab3899 100644 --- "a/tool_shared/bespoke\360\237\226\211/env" +++ "b/tool_shared/bespoke\360\237\226\211/env" @@ -78,7 +78,7 @@ shopt -s nullglob install_file() { if [ "$#" -lt 3 ]; then - echo "Usage: install_file ... " + echo "env::install_file usage: install_file ... " return 1 fi @@ -87,23 +87,23 @@ shopt -s nullglob sources=("${@:1:$#-2}") # All other arguments are source files if [ ! -d "$target_dp" ]; then - echo "Error: Target directory '$target_dp' does not exist." + echo "env::install_file no install done: target directory '$target_dp' does not exist." return 1 fi for source_fp in "${sources[@]}"; do if [ ! -f "$source_fp" ]; then - echo "Error: Source file '$source_fp' does not exist." + echo "env::install_file: source file '$source_fp' does not exist." return 1 fi target_file="$target_dp/$(basename "$source_fp")" if ! install -m "$perms" "$source_fp" "$target_file"; then - echo "Error: Failed to install $(basename "$source_fp") to $target_dp" + echo "env::install_file: Failed to install $(basename "$source_fp") to $target_dp" return 1 else - echo "Installed $(basename "$source_fp") to $target_dp with permissions $perms" + echo "env::install_file: installed $(basename "$source_fp") to $target_dp with permissions $perms" fi done } -- 2.20.1