From a7ac313a13f8f82b4b3ca9730bd746392f6600d9 Mon Sep 17 00:00:00 2001 From: Kevin Petit Date: Mon, 8 Jan 2024 15:27:25 +0000 Subject: Move operator pseudocode to separate files This makes it easier to process the pseudocode automatically. Change-Id: I84394192598e589de07d43a7af60b96788e14f86 Signed-off-by: Kevin Petit --- pseudocode/operators/ABS.tosac | 19 ++++++ pseudocode/operators/ADD.tosac | 26 ++++++++ pseudocode/operators/ARGMAX.tosac | 37 ++++++++++++ pseudocode/operators/ARITHMETIC_RIGHT_SHIFT.tosac | 29 +++++++++ pseudocode/operators/AVG_POOL2D.tosac | 50 +++++++++++++++ pseudocode/operators/BITWISE_AND.tosac | 18 ++++++ pseudocode/operators/BITWISE_NOT.tosac | 14 +++++ pseudocode/operators/BITWISE_OR.tosac | 18 ++++++ pseudocode/operators/BITWISE_XOR.tosac | 18 ++++++ pseudocode/operators/CAST.tosac | 27 +++++++++ pseudocode/operators/CEIL.tosac | 14 +++++ pseudocode/operators/CLAMP.tosac | 15 +++++ pseudocode/operators/CLZ.tosac | 14 +++++ pseudocode/operators/CONCAT.tosac | 32 ++++++++++ pseudocode/operators/COND_IF.tosac | 23 +++++++ pseudocode/operators/CONV2D.tosac | 40 ++++++++++++ pseudocode/operators/CONV3D.tosac | 43 +++++++++++++ pseudocode/operators/DEPTHWISE_CONV2D.tosac | 40 ++++++++++++ pseudocode/operators/DIM.tosac | 11 ++++ pseudocode/operators/EQUAL.tosac | 22 +++++++ pseudocode/operators/EXP.tosac | 14 +++++ pseudocode/operators/FFT2D.tosac | 31 ++++++++++ pseudocode/operators/FLOOR.tosac | 14 +++++ pseudocode/operators/FULLY_CONNECTED.tosac | 25 ++++++++ pseudocode/operators/GATHER.tosac | 15 +++++ pseudocode/operators/GREATER.tosac | 22 +++++++ pseudocode/operators/GREATER_EQUAL.tosac | 22 +++++++ pseudocode/operators/INTDIV.tosac | 31 ++++++++++ pseudocode/operators/LOG.tosac | 14 +++++ pseudocode/operators/LOGICAL_AND.tosac | 18 ++++++ pseudocode/operators/LOGICAL_LEFT_SHIFT.tosac | 19 ++++++ pseudocode/operators/LOGICAL_NOT.tosac | 14 +++++ pseudocode/operators/LOGICAL_OR.tosac | 18 ++++++ pseudocode/operators/LOGICAL_RIGHT_SHIFT.tosac | 20 ++++++ pseudocode/operators/LOGICAL_XOR.tosac | 18 ++++++ pseudocode/operators/MATMUL.tosac | 21 +++++++ pseudocode/operators/MAXIMUM.tosac | 18 ++++++ pseudocode/operators/MAX_POOL2D.tosac | 33 ++++++++++ pseudocode/operators/MINIMUM.tosac | 18 ++++++ pseudocode/operators/MUL.tosac | 37 ++++++++++++ pseudocode/operators/NEGATE.tosac | 22 +++++++ pseudocode/operators/PAD.tosac | 27 +++++++++ pseudocode/operators/POW.tosac | 18 ++++++ pseudocode/operators/RECIPROCAL.tosac | 14 +++++ pseudocode/operators/REDUCE_ALL.tosac | 25 ++++++++ pseudocode/operators/REDUCE_ANY.tosac | 25 ++++++++ pseudocode/operators/REDUCE_MAX.tosac | 25 ++++++++ pseudocode/operators/REDUCE_MIN.tosac | 25 ++++++++ pseudocode/operators/REDUCE_PRODUCT.tosac | 25 ++++++++ pseudocode/operators/REDUCE_SUM.tosac | 26 ++++++++ pseudocode/operators/RESCALE.tosac | 58 ++++++++++++++++++ pseudocode/operators/RESHAPE.tosac | 21 +++++++ pseudocode/operators/RESIZE.tosac | 74 +++++++++++++++++++++++ pseudocode/operators/REVERSE.tosac | 16 +++++ pseudocode/operators/RFFT2D.tosac | 24 ++++++++ pseudocode/operators/RSQRT.tosac | 20 ++++++ pseudocode/operators/SCATTER.tosac | 31 ++++++++++ pseudocode/operators/SELECT.tosac | 25 ++++++++ pseudocode/operators/SIGMOID.tosac | 14 +++++ pseudocode/operators/SLICE.tosac | 28 +++++++++ pseudocode/operators/SUB.tosac | 26 ++++++++ pseudocode/operators/TABLE.tosac | 21 +++++++ pseudocode/operators/TANH.tosac | 14 +++++ pseudocode/operators/TILE.tosac | 20 ++++++ pseudocode/operators/TRANSPOSE.tosac | 35 +++++++++++ pseudocode/operators/TRANSPOSE_CONV2D.tosac | 35 +++++++++++ pseudocode/operators/VARIABLE.tosac | 33 ++++++++++ pseudocode/operators/VARIABLE_READ.tosac | 26 ++++++++ pseudocode/operators/VARIABLE_WRITE.tosac | 29 +++++++++ pseudocode/operators/WHILE_LOOP.tosac | 33 ++++++++++ pseudocode/operators/tables/ERF.tosac | 16 +++++ pseudocode/operators/tables/SIGMOID.tosac | 16 +++++ pseudocode/operators/tables/TANH.tosac | 17 ++++++ 73 files changed, 1796 insertions(+) create mode 100644 pseudocode/operators/ABS.tosac create mode 100644 pseudocode/operators/ADD.tosac create mode 100644 pseudocode/operators/ARGMAX.tosac create mode 100644 pseudocode/operators/ARITHMETIC_RIGHT_SHIFT.tosac create mode 100644 pseudocode/operators/AVG_POOL2D.tosac create mode 100644 pseudocode/operators/BITWISE_AND.tosac create mode 100644 pseudocode/operators/BITWISE_NOT.tosac create mode 100644 pseudocode/operators/BITWISE_OR.tosac create mode 100644 pseudocode/operators/BITWISE_XOR.tosac create mode 100644 pseudocode/operators/CAST.tosac create mode 100644 pseudocode/operators/CEIL.tosac create mode 100644 pseudocode/operators/CLAMP.tosac create mode 100644 pseudocode/operators/CLZ.tosac create mode 100644 pseudocode/operators/CONCAT.tosac create mode 100644 pseudocode/operators/COND_IF.tosac create mode 100644 pseudocode/operators/CONV2D.tosac create mode 100644 pseudocode/operators/CONV3D.tosac create mode 100644 pseudocode/operators/DEPTHWISE_CONV2D.tosac create mode 100644 pseudocode/operators/DIM.tosac create mode 100644 pseudocode/operators/EQUAL.tosac create mode 100644 pseudocode/operators/EXP.tosac create mode 100644 pseudocode/operators/FFT2D.tosac create mode 100644 pseudocode/operators/FLOOR.tosac create mode 100644 pseudocode/operators/FULLY_CONNECTED.tosac create mode 100644 pseudocode/operators/GATHER.tosac create mode 100644 pseudocode/operators/GREATER.tosac create mode 100644 pseudocode/operators/GREATER_EQUAL.tosac create mode 100644 pseudocode/operators/INTDIV.tosac create mode 100644 pseudocode/operators/LOG.tosac create mode 100644 pseudocode/operators/LOGICAL_AND.tosac create mode 100644 pseudocode/operators/LOGICAL_LEFT_SHIFT.tosac create mode 100644 pseudocode/operators/LOGICAL_NOT.tosac create mode 100644 pseudocode/operators/LOGICAL_OR.tosac create mode 100644 pseudocode/operators/LOGICAL_RIGHT_SHIFT.tosac create mode 100644 pseudocode/operators/LOGICAL_XOR.tosac create mode 100644 pseudocode/operators/MATMUL.tosac create mode 100644 pseudocode/operators/MAXIMUM.tosac create mode 100644 pseudocode/operators/MAX_POOL2D.tosac create mode 100644 pseudocode/operators/MINIMUM.tosac create mode 100644 pseudocode/operators/MUL.tosac create mode 100644 pseudocode/operators/NEGATE.tosac create mode 100644 pseudocode/operators/PAD.tosac create mode 100644 pseudocode/operators/POW.tosac create mode 100644 pseudocode/operators/RECIPROCAL.tosac create mode 100644 pseudocode/operators/REDUCE_ALL.tosac create mode 100644 pseudocode/operators/REDUCE_ANY.tosac create mode 100644 pseudocode/operators/REDUCE_MAX.tosac create mode 100644 pseudocode/operators/REDUCE_MIN.tosac create mode 100644 pseudocode/operators/REDUCE_PRODUCT.tosac create mode 100644 pseudocode/operators/REDUCE_SUM.tosac create mode 100644 pseudocode/operators/RESCALE.tosac create mode 100644 pseudocode/operators/RESHAPE.tosac create mode 100644 pseudocode/operators/RESIZE.tosac create mode 100644 pseudocode/operators/REVERSE.tosac create mode 100644 pseudocode/operators/RFFT2D.tosac create mode 100644 pseudocode/operators/RSQRT.tosac create mode 100644 pseudocode/operators/SCATTER.tosac create mode 100644 pseudocode/operators/SELECT.tosac create mode 100644 pseudocode/operators/SIGMOID.tosac create mode 100644 pseudocode/operators/SLICE.tosac create mode 100644 pseudocode/operators/SUB.tosac create mode 100644 pseudocode/operators/TABLE.tosac create mode 100644 pseudocode/operators/TANH.tosac create mode 100644 pseudocode/operators/TILE.tosac create mode 100644 pseudocode/operators/TRANSPOSE.tosac create mode 100644 pseudocode/operators/TRANSPOSE_CONV2D.tosac create mode 100644 pseudocode/operators/VARIABLE.tosac create mode 100644 pseudocode/operators/VARIABLE_READ.tosac create mode 100644 pseudocode/operators/VARIABLE_WRITE.tosac create mode 100644 pseudocode/operators/WHILE_LOOP.tosac create mode 100644 pseudocode/operators/tables/ERF.tosac create mode 100644 pseudocode/operators/tables/SIGMOID.tosac create mode 100644 pseudocode/operators/tables/TANH.tosac (limited to 'pseudocode') diff --git a/pseudocode/operators/ABS.tosac b/pseudocode/operators/ABS.tosac new file mode 100644 index 0000000..5f7f56e --- /dev/null +++ b/pseudocode/operators/ABS.tosac @@ -0,0 +1,19 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + if (is_floating_point(in_out_t) && value1 == -0.0) { + value1 = 0.0; + } + if (static_cast(value1) < 0.0) { + value1 = apply_sub_s(0, value1); + } + tensor_write(output, shape, index, value1); +} diff --git a/pseudocode/operators/ADD.tosac b/pseudocode/operators/ADD.tosac new file mode 100644 index 0000000..61db3f6 --- /dev/null +++ b/pseudocode/operators/ADD.tosac @@ -0,0 +1,26 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +if (in_out_t == shape_t) { + ERROR_IF(rank(shape) != 0 || rank(shape1) != 0 || rank(shape2) != 0); + shape_t value1 = tensor_read(input1, [], []); + shape_t value2 = tensor_read(input2, [], []); + shape_t result = apply_add_s(value1, value2); + tensor_write(output, [], [], result); +} else { + ERROR_IF(shape != broadcast_shape(shape1, shape2)); + for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = apply_add_s(value1, value2); + tensor_write(output, shape, index, result); + } +} diff --git a/pseudocode/operators/ARGMAX.tosac b/pseudocode/operators/ARGMAX.tosac new file mode 100644 index 0000000..bbe301f --- /dev/null +++ b/pseudocode/operators/ARGMAX.tosac @@ -0,0 +1,37 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape1)); +if (axis == 0) { + left_shape = []; +} else { + left_shape = shape1[0:axis - 1]; +} +if (axis == rank(shape1)-1) { + right_shape = []; +} else { + right_shape = shape1[axis+1:rank(shape1) - 1]; +} +ERROR_IF(flatten(left_shape, right_shape) != shape); +for_each(left_index in left_shape) { + for_each(right_index in right_shape) { + in_t max_value = minimum_s; + out_t max_index = 0; + for (i = 0; i < shape[axis]; i++) { + dim_t index = flatten(left_index, [i], right_index); + in_t value = tensor_read(input, shape1, index); + if (apply_max_s(value, max_value) != max_value) { + max_value = value; + max_index = i; + } + } + dim_t index = flatten(left_index, right_index); + tensor_write(output, shape, index, max_index); + } +} diff --git a/pseudocode/operators/ARITHMETIC_RIGHT_SHIFT.tosac b/pseudocode/operators/ARITHMETIC_RIGHT_SHIFT.tosac new file mode 100644 index 0000000..4077146 --- /dev/null +++ b/pseudocode/operators/ARITHMETIC_RIGHT_SHIFT.tosac @@ -0,0 +1,29 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + + // Ensure that shift amount is appropriate for the data type + REQUIRE((in_out_t == i32_t && 0 <= value2 && value2 <= 31) || + (in_out_t == i16_t && 0 <= value2 && value2 <= 15) || + (in_out_t == i8_t && 0 <= value2 && value2 <= 7)); + + in_out_t result = apply_arith_rshift(value1, value2); + if (round == true && static_cast(value2) > 0 && + (apply_arith_rshift(value1, apply_sub_s(value2, 1)) & 1 != 0) { + result = result + 1; + } + result = apply_clip_s(result, minimum_s, maximum_s); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/AVG_POOL2D.tosac b/pseudocode/operators/AVG_POOL2D.tosac new file mode 100644 index 0000000..f452d12 --- /dev/null +++ b/pseudocode/operators/AVG_POOL2D.tosac @@ -0,0 +1,50 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_out_t != i8_t && input_zp != 0); // Zero point only for int8_t +ERROR_IF(in_out_t != i8_t && output_zp != 0); // Zero point only for int8_t +ERROR_IF(kernel_y < 1 || kernel_x < 1); // kernel size must be >= 1 +ERROR_IF(stride_y < 1 || stride_x < 1); +ERROR_IF(pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); +// Padding must be less than kernel size to avoid +// a divide-by-zero. +ERROR_IF(pad_right >= kernel_x || pad_left >= kernel_x); +ERROR_IF(pad_top >= kernel_y || pad_bottom >= kernel_y); +ERROR_IF(OH != idiv_check(IH + pad_top + pad_bottom - kernel_y, stride_y) + 1); +ERROR_IF(OW != idiv_check(IW + pad_left + pad_right - kernel_x, stride_x) + 1); + +for_each(0 <= n < N, 0 <= oy < OH, 0 <= ox < OW, 0 <= c < C ) { + in_out_t output_val; + acc_t acc = 0; + int count = 0; + index_t iy = oy * stride_y - pad_top; + index_t ix = ox * stride_x - pad_left; + for_each(0 <= ky < kernel_y, 0 <= kx < kernel_x) { + index_t y = iy + ky; + index_t x = ix + kx; + // Only values from the input tensor are used to calculate the + // average, padding does not count + if (0 <= y < IH and 0 <= x < IW) { + count++; + acc_t value = sign_extend(tensor_read(input, [N,IH,IW,C], [n,y,x,c])); + value = apply_sub_s(value, sign_extend(input_zp)); + acc = apply_add_s(acc, value); + } + } + if (is_float(in_out_t)) { + output_val = acc / static_cast(count); + } else { + scale_t scale = reciprocal_scale(count); + acc = apply_scale_32(acc, scale.multiplier, scale.shift, false); + acc = apply_add_s(acc, sign_extend(output_zp)); + acc = apply_clip_s(acc, minimum_s, maximum_s); + output_val = static_cast(acc); + } + tensor_write(output, [N,OH,OW,C], [n,oy,ox,c], output_val); +} diff --git a/pseudocode/operators/BITWISE_AND.tosac b/pseudocode/operators/BITWISE_AND.tosac new file mode 100644 index 0000000..5efe3ee --- /dev/null +++ b/pseudocode/operators/BITWISE_AND.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = value1 & value2; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/BITWISE_NOT.tosac b/pseudocode/operators/BITWISE_NOT.tosac new file mode 100644 index 0000000..1831e75 --- /dev/null +++ b/pseudocode/operators/BITWISE_NOT.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + in_out_t result = ~value1; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/BITWISE_OR.tosac b/pseudocode/operators/BITWISE_OR.tosac new file mode 100644 index 0000000..b2b7fc6 --- /dev/null +++ b/pseudocode/operators/BITWISE_OR.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = value1 | value2; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/BITWISE_XOR.tosac b/pseudocode/operators/BITWISE_XOR.tosac new file mode 100644 index 0000000..98f0d2c --- /dev/null +++ b/pseudocode/operators/BITWISE_XOR.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = value1 ^ value2; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/CAST.tosac b/pseudocode/operators/CAST.tosac new file mode 100644 index 0000000..f6306b3 --- /dev/null +++ b/pseudocode/operators/CAST.tosac @@ -0,0 +1,27 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_t in = tensor_read(input, shape, index); + out_t out; + if (out_t == bool_t) { + out = (in != 0) ? true : false; + } else if (in_t == bool_t) { + out = (in) ? 1 : 0; + } else if (out_t == fp16_t || out_t == bf16_t || out_t == fp32_t) { + out = round_to_nearest_float(in); + } else if (in_t == fp16_t || in_t == bf16_t || in_t == fp32_t) { + out = apply_clip(round_to_nearest_int(in), minimum, maximum); + } else if (sizeof(out_t) >= sizeof(in_t)) { + out = sign_extend(in); + } else { + out = truncate(in); + } + tensor_write(output, shape, index, out) +} diff --git a/pseudocode/operators/CEIL.tosac b/pseudocode/operators/CEIL.tosac new file mode 100644 index 0000000..890eb8a --- /dev/null +++ b/pseudocode/operators/CEIL.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + in_out_t result = apply_ceil(value1); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/CLAMP.tosac b/pseudocode/operators/CLAMP.tosac new file mode 100644 index 0000000..7a26d50 --- /dev/null +++ b/pseudocode/operators/CLAMP.tosac @@ -0,0 +1,15 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(max_val < min_val); +for_each(index in shape) { + in_out_t value = tensor_read(input, shape, index); + value = apply_clip(value, min_val, max_val); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/CLZ.tosac b/pseudocode/operators/CLZ.tosac new file mode 100644 index 0000000..a3a7180 --- /dev/null +++ b/pseudocode/operators/CLZ.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + in_out_t result = count_leading_zeros(value1); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/CONCAT.tosac b/pseudocode/operators/CONCAT.tosac new file mode 100644 index 0000000..f9329af --- /dev/null +++ b/pseudocode/operators/CONCAT.tosac @@ -0,0 +1,32 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= max(1,rank(shapes1[0]))); +ERROR_IF(shape[axis] != sum(shape_dim(shapes1[k], axis) for all k)) +ERROR_IF(in_out_t == shape_t && rank(shape) > 1); +// The following checks ensure all inputs are compatible for concatenation +for_each(input_shape in shapes1) { + ERROR_IF(rank(input_shape) != rank(shapes1[0])); + for_each(index in input_shape) { + ERROR_IF(index != axis && input_shape[index] != shapes1[0][index]); + } +} +for_each(index1 in shape) { + dim_t index2 = index1; + for (tensor t = 0; t < length(input1); t++) { + // Continue to concatenate along axis from each tensor + // For each output location, we are looking for the + // appropriate input tensor + if (index2[axis] >= 0 && index2[axis] < shape_dim(shapes1[t], axis)) { + in_out_t value = tensor_read(input1[t], shapes1[t], index2); + tensor_write(output, shape, index1, value); + } + index2[axis] = index2[axis] - shape_dim(shapes1[t], axis); + } +} diff --git a/pseudocode/operators/COND_IF.tosac b/pseudocode/operators/COND_IF.tosac new file mode 100644 index 0000000..584cc83 --- /dev/null +++ b/pseudocode/operators/COND_IF.tosac @@ -0,0 +1,23 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(tosa_nesting_depth >= MAX_NESTING); +ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(then_graph)); +ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(else_graph)); +ERROR_IF(tensor_list_shape(output_list) != tosa_output_shape(then_graph)); +ERROR_IF(tensor_list_shape(output_list) != tosa_output_shape(else_graph)); +ERROR_IF(tensor_size(shape) != 1); + +tosa_nesting_depth++; +if (condition[0]) { + tosa_execute_graph(then_graph, input_list, output_list); +} else { + tosa_execute_graph(else_graph, input_list, output_list); +} +tosa_nesting_depth--; diff --git a/pseudocode/operators/CONV2D.tosac b/pseudocode/operators/CONV2D.tosac new file mode 100644 index 0000000..12620e9 --- /dev/null +++ b/pseudocode/operators/CONV2D.tosac @@ -0,0 +1,40 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_t != i8_t && input_zp != 0); // Zero point only for int8_t +ERROR_IF(weight_t != int8_t && weight_zp != 0); +ERROR_IF(pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); +ERROR_IF(stride_y < 1 || stride_x < 1); +ERROR_IF(dilation_y < 1 || dilation_x < 1); +ERROR_IF(OH != idiv_check(IH - 1 + pad_top + pad_bottom - (KH - 1) * dilation_y, stride_y) + 1); +ERROR_IF(OW != idiv_check(IW - 1 + pad_left + pad_right - (KW - 1) * dilation_x, stride_x) + 1); +ERROR_IF(BC != OC && BC != 1); + +for_each(0 <= n < N, 0 <= oy < OH, 0 <= ox < OW; 0 <= oc < OC) { + out_t acc = 0; + index_t iy = oy * stride_y - pad_top; + index_t ix = ox * stride_x - pad_left; + for_each(0 <= ky < KH, 0 <= kx < KW, 0 <= ic < IC) { + index_t y = iy + ky * dilation_y; + index_t x = ix + kx * dilation_x; + if (0 <= y < IH && 0 <= x < IW) { + out_t value = static_cast(tensor_read(input, + [N,IH,IW,IC], + [n,y,x,ic])); + out_t weight = static_cast(tensor_read(weight, + [OC,KH,KW,IC], + [oc,ky,kx,ic])); + value = apply_sub_s(value, static_cast(input_zp)); + weight = apply_sub_s(weight, static_cast(weight_zp)); + acc = apply_add_s(acc, apply_mul_s(value, weight)); + } + } + acc = apply_add_s(acc, bias[(BC == 1) ? 0 : oc]); + tensor_write(output, [N,OH,OW,OC], [n,oy,ox,oc], acc); +} diff --git a/pseudocode/operators/CONV3D.tosac b/pseudocode/operators/CONV3D.tosac new file mode 100644 index 0000000..a0f9130 --- /dev/null +++ b/pseudocode/operators/CONV3D.tosac @@ -0,0 +1,43 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_t != i8_t && input_zp != 0); // Zero point only for int8_t +ERROR_IF(weight_t != i8_t && weight_zp != 0); +ERROR_IF(pad_d0 < 0 || pad_d1 < 0 || pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); +ERROR_IF(stride_d < 1 || stride_y < 1 || stride_x < 1); +ERROR_IF(dilation_d < 1 || dilation_y < 1 || dilation_x < 1); +ERROR_IF(OD != idiv_check(ID - 1 + pad_d0 + pad_d1 - (KD - 1) * dilation_d, stride_d) + 1); +ERROR_IF(OH != idiv_check(IH - 1 + pad_top + pad_bottom - (KH - 1) * dilation_y, stride_y) + 1); +ERROR_IF(OW != idiv_check(IW - 1 + pad_left + pad_right - (KW - 1) * dilation_x, stride_x) + 1); +ERROR_IF(BC != OC && BC != 1); + +for_each(0 <= n < N, 0 <= od < OD, 0 <= oy < OH, 0 <= ox < OW; 0 <= oc < OC) { + out_t acc = 0; + index_t id = od * stride_d - pad_d0; + index_t iy = oy * stride_y - pad_top; + index_t ix = ox * stride_x - pad_left; + for_each(0 <= kd < KD, 0 <= ky < KH, 0 <= kx < KW, 0 <= ic < IC) { + index_t d = id + kd * dilation_d; + index_t y = iy + ky * dilation_y; + index_t x = ix + kx * dilation_x; + if (0 <= x < IW && 0 <= y < IH && 0 <= d < ID) { + out_t value = static_cast(tensor_read(input, + [N,ID,IH,IW,IC], + [n,d,y,x,ic])); + out_t weight = static_cast(tensor_read(weight, + [OC,KD,KH,KW,IC], + [oc,kd,ky,kx,ic])); + value = apply_sub_s(value, static_cast(input_zp)); + weight = apply_sub_s(weight, static_cast(weight_zp)); + acc = apply_add_s(acc, apply_mul_s(value, weight)); + } + } + acc = apply_add_s(acc, bias[(BC == 1) ? 0 : oc]); + tensor_write(output, [N,OD,OH,OW,OC], [n,od,oy,ox,oc], acc); +} diff --git a/pseudocode/operators/DEPTHWISE_CONV2D.tosac b/pseudocode/operators/DEPTHWISE_CONV2D.tosac new file mode 100644 index 0000000..c7a0f0f --- /dev/null +++ b/pseudocode/operators/DEPTHWISE_CONV2D.tosac @@ -0,0 +1,40 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_t != i8_t && input_zp != 0); // Zero point only for int8_t +ERROR_IF(weight_t != i8_t && weight_zp != 0); +ERROR_IF(pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); +ERROR_IF(stride_y < 1 || stride_x < 1); +ERROR_IF(dilation_y < 1 || dilation_x < 1); +ERROR_IF(OH != idiv_check(IH - 1 + pad_top + pad_bottom - (KH - 1) * dilation_y, stride_y) + 1); +ERROR_IF(OW != idiv_check(IW - 1 + pad_left + pad_right - (KW - 1) * dilation_x, stride_x) + 1); +ERROR_IF(BC != C*M && BC != 1); + +for_each(0 <= n < N, 0 <= oy < OH, 0 <= ox < OW; 0 <= c < C, 0 <= m < M) { + out_t acc = 0; + index_t iy = oy * stride_y - pad_top; + index_t ix = ox * stride_x - pad_left; + for_each(0 <= ky < KH, 0 <= kx < KW) { + index_t y = iy + ky * dilation_y; + index_t x = ix + kx * dilation_x; + if (0 <= y < IH && 0 <= x < IW) { + out_t value = static_cast(tensor_read(input, + [N,IH,IW,C], + [n,y,x,c])); + out_t weight = static_cast(tensor_read(weight, + [KH,KW,C,M], + [ky,kx,c,m])); + value = apply_sub_s(value, static_castinput_zp); + weight = apply_sub_s(weight, static_castweight_zp); + acc = apply_add_s(acc, apply_mul_s(value, weight)); + } + } + acc = apply_add_s(acc, bias[(BC == 1) ? 0 : (c * M) + m]); + tensor_write(output, [N,OH,OW,C * M], [n,oy,ox,c * M + m], acc); +} diff --git a/pseudocode/operators/DIM.tosac b/pseudocode/operators/DIM.tosac new file mode 100644 index 0000000..7131173 --- /dev/null +++ b/pseudocode/operators/DIM.tosac @@ -0,0 +1,11 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis >= rank(shape)); +tensor_write(output, [], [], shape_dim(shape, axis)); diff --git a/pseudocode/operators/EQUAL.tosac b/pseudocode/operators/EQUAL.tosac new file mode 100644 index 0000000..67e0b64 --- /dev/null +++ b/pseudocode/operators/EQUAL.tosac @@ -0,0 +1,22 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_t value1 = tensor_read(input1, shape1, index1); + in_t value2 = tensor_read(input2, shape2, index2); + out_t result; + if (isNaN(value1) || isNaN(value2)) + result = False; + else + result = (value1 == value2) ? True : False; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/EXP.tosac b/pseudocode/operators/EXP.tosac new file mode 100644 index 0000000..4ef74a0 --- /dev/null +++ b/pseudocode/operators/EXP.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + in_out_t result = apply_exp(value1); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/FFT2D.tosac b/pseudocode/operators/FFT2D.tosac new file mode 100644 index 0000000..a958aa4 --- /dev/null +++ b/pseudocode/operators/FFT2D.tosac @@ -0,0 +1,31 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(!power_of_two(H)); +ERROR_IF(!power_of_two(W)); + +float sign_val = 1.0; + +if (inverse) { + sign_val = -1.0; +} + +for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W) { + in_out_t sum_real = 0.0; + in_out_t sum_imag = 0.0; + for_each(0 <= iy < H, 0 <= ix < W) { + in_out_t val_real = tensor_read(input_real, [N,H,W], [n,iy,ix]); + in_out_t val_imag = tensor_read(input_imag, [N,H,W], [n,iy,ix]); + float_t a = sign_val * 2 * pi() * ((iy * oy) / H + (ix * ox) / W); + sum_real += val_real * cos(a) + val_imag * sin(a); + sum_imag += -val_real * sin(a) + val_imag * cos(a); + } + tensor_write(output_real, [N,H,W], [n,oy,ox], sum_real); + tensor_write(output_imag, [N,H,W], [n,oy,ox], sum_imag); +} diff --git a/pseudocode/operators/FLOOR.tosac b/pseudocode/operators/FLOOR.tosac new file mode 100644 index 0000000..fc893b6 --- /dev/null +++ b/pseudocode/operators/FLOOR.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + in_out_t result = apply_floor(value1); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/FULLY_CONNECTED.tosac b/pseudocode/operators/FULLY_CONNECTED.tosac new file mode 100644 index 0000000..fbacccc --- /dev/null +++ b/pseudocode/operators/FULLY_CONNECTED.tosac @@ -0,0 +1,25 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_t != i8_t && input_zp != 0); // Zero point only for int8_t +ERROR_IF(weight_t != i8_t && weight_zp != 0); +ERROR_IF(BC != OC && BC != 1); + +for_each(0 <= n < N, 0 <= oc < OC) { + out_t acc = 0; + for_each(0 <= ic < IC) { + out_t value = static_cast(tensor_read(input, [N,IC], [n,ic])); + out_t weight = static_cast(tensor_read(weight, [OC,IC], [oc,ic])); + value = apply_sub_s(value, static_cast(input_zp)); + weight = apply_sub_s(weight, static_cast(weight_zp)); + acc = apply_add_s(acc, apply_mul_s(value, weight)); + } + acc = apply_add_s(acc, bias[(BC == 1) ? 0 : oc]); + tensor_write(output, [N,OC], [n,oc], acc); +} diff --git a/pseudocode/operators/GATHER.tosac b/pseudocode/operators/GATHER.tosac new file mode 100644 index 0000000..82c159d --- /dev/null +++ b/pseudocode/operators/GATHER.tosac @@ -0,0 +1,15 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(0 <= n < N, 0 <= w < W, 0 <= c < C) { + index_t k = tensor_read(indices, [N,W], [n,w]); + REQUIRE(0 <= k && k < K); + in_out_t value = tensor_read(values, [N,K,C], [n,k,c]); + tensor_write(output, [N,W,C], [n,w,c], value); +} diff --git a/pseudocode/operators/GREATER.tosac b/pseudocode/operators/GREATER.tosac new file mode 100644 index 0000000..af8b4c9 --- /dev/null +++ b/pseudocode/operators/GREATER.tosac @@ -0,0 +1,22 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_t value1 = tensor_read(input1, shape1, index1); + in_t value2 = tensor_read(input2, shape2, index2); + out_t result; + if (isNaN(value1) || isNaN(value2)) + result = False; + else + result = (value1 > value2) ? True : False; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/GREATER_EQUAL.tosac b/pseudocode/operators/GREATER_EQUAL.tosac new file mode 100644 index 0000000..e45990d --- /dev/null +++ b/pseudocode/operators/GREATER_EQUAL.tosac @@ -0,0 +1,22 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_t value1 = tensor_read(input1, shape1, index1); + in_t value2 = tensor_read(input2, shape2, index2); + out_t result; + if (isNaN(value1) || isNaN(value2)) + result = False; + else + result = (value1 >= value2) ? True : False; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/INTDIV.tosac b/pseudocode/operators/INTDIV.tosac new file mode 100644 index 0000000..b6d46cc --- /dev/null +++ b/pseudocode/operators/INTDIV.tosac @@ -0,0 +1,31 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +if (in_out_t == shape_t) { + ERROR_IF(rank(shape) != 0 || rank(shape1) != 0 || rank(shape2) != 0); + shape_t value1 = tensor_read(input1, [], []); + shape_t value2 = tensor_read(input2, [], []); + REQUIRE(value2 != 0); + shape_t result = value1 / value2; + tensor_write(output, [], [], result); +} else { + ERROR_IF(shape != broadcast_shape(shape1, shape2)); + for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + REQUIRE(value2 != 0); + // This catches the case where we divide minimum by -1 + // which is not representable in two's complement + REQUIRE(static_cast(value1) / static_cast(value2) <= maximum_s); + in_out_t result = apply_intdiv_s(value1, value2); + tensor_write(output, shape, index, result); + } +} diff --git a/pseudocode/operators/LOG.tosac b/pseudocode/operators/LOG.tosac new file mode 100644 index 0000000..2c56105 --- /dev/null +++ b/pseudocode/operators/LOG.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + in_out_t result = apply_log(value1); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/LOGICAL_AND.tosac b/pseudocode/operators/LOGICAL_AND.tosac new file mode 100644 index 0000000..ff03804 --- /dev/null +++ b/pseudocode/operators/LOGICAL_AND.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = value1 && value2; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/LOGICAL_LEFT_SHIFT.tosac b/pseudocode/operators/LOGICAL_LEFT_SHIFT.tosac new file mode 100644 index 0000000..4057163 --- /dev/null +++ b/pseudocode/operators/LOGICAL_LEFT_SHIFT.tosac @@ -0,0 +1,19 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + REQUIRE(0 <= value2 && value2 <= 31); + in_out_t result = value1 << value2; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/LOGICAL_NOT.tosac b/pseudocode/operators/LOGICAL_NOT.tosac new file mode 100644 index 0000000..b07e668 --- /dev/null +++ b/pseudocode/operators/LOGICAL_NOT.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape1, index); + in_out_t result = !value1; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/LOGICAL_OR.tosac b/pseudocode/operators/LOGICAL_OR.tosac new file mode 100644 index 0000000..4e3aa9e --- /dev/null +++ b/pseudocode/operators/LOGICAL_OR.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = value1 || value2; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/LOGICAL_RIGHT_SHIFT.tosac b/pseudocode/operators/LOGICAL_RIGHT_SHIFT.tosac new file mode 100644 index 0000000..5e80211 --- /dev/null +++ b/pseudocode/operators/LOGICAL_RIGHT_SHIFT.tosac @@ -0,0 +1,20 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + REQUIRE(0 <= static_cast(value2) && static_cast(value2) <= 31); + // Logical shifts happen as unsigned types internally + in_out_t result = apply_logical_rshift(value1, value2); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/LOGICAL_XOR.tosac b/pseudocode/operators/LOGICAL_XOR.tosac new file mode 100644 index 0000000..fbb485b --- /dev/null +++ b/pseudocode/operators/LOGICAL_XOR.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = value1 != value2; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/MATMUL.tosac b/pseudocode/operators/MATMUL.tosac new file mode 100644 index 0000000..3afda4d --- /dev/null +++ b/pseudocode/operators/MATMUL.tosac @@ -0,0 +1,21 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_t != i8_t && (A_zp != 0 || B_zp != 0)); // Zero point only for int8_t +for_each(0 <= n < N, 0 <= h < H, 0 <= w < W) { + out_t acc = 0; + for_each(0 <= c < C) { + out_t value1 = static_cast(tensor_read(A, [N,H,C], [n,h,c])); + out_t value2 = static_cast(tensor_read(B, [N,C,W], [n,c,w])); + value1 = apply_sub_s(value1, static_cast(A_zp)); + value2 = apply_sub_s(value2, static_cast(B_zp)); + acc = apply_add_s(acc, apply_mul_s(value1 * value2)); + } + tensor_write(output, [N,H,W], [n,h,w], acc); +} diff --git a/pseudocode/operators/MAXIMUM.tosac b/pseudocode/operators/MAXIMUM.tosac new file mode 100644 index 0000000..0f4f3b7 --- /dev/null +++ b/pseudocode/operators/MAXIMUM.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = apply_max_s(value1, value2); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/MAX_POOL2D.tosac b/pseudocode/operators/MAX_POOL2D.tosac new file mode 100644 index 0000000..a33b80a --- /dev/null +++ b/pseudocode/operators/MAX_POOL2D.tosac @@ -0,0 +1,33 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(kernel_y < 1 || kernel_x < 1); // kernel size must be >= 1 +ERROR_IF(stride_y < 1 || stride_x < 1); +ERROR_IF(pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); +// Padding must be less than kernel size, otherwise no +// input values will be used. +ERROR_IF(pad_right >= kernel_x || pad_left >= kernel_x); +ERROR_IF(pad_top >= kernel_y || pad_bottom >= kernel_y); +ERROR_IF(OH != idiv_check(IH + pad_top + pad_bottom - kernel_y, stride_y) + 1); +ERROR_IF(OW != idiv_check(IW + pad_left + pad_right - kernel_x, stride_x) + 1); + +for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W, 0 <= c < C ) { + in_out_t acc = minimum_value; + index_t iy = oy * stride_y - pad_top; + index_t ix = ox * stride_x - pad_left; + for_each( 0 <= ky < kernel_y, 0 <= kx < kernel_x ) { + index_t y = iy + ky; + index_t x = ix + kx; + if (y >= 0 && y < IH && x >= 0 && x < IW) { + in_out_t value = tensor_read(input, [N,IH,IW,C], [n,y,x,c]); + acc = apply_max_s(acc, value); + } + } + tensor_write(output, [N,OH,OW,C], [n,oy,ox,c], acc); +} diff --git a/pseudocode/operators/MINIMUM.tosac b/pseudocode/operators/MINIMUM.tosac new file mode 100644 index 0000000..fa47b03 --- /dev/null +++ b/pseudocode/operators/MINIMUM.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = apply_min_s(value1, value2); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/MUL.tosac b/pseudocode/operators/MUL.tosac new file mode 100644 index 0000000..078525e --- /dev/null +++ b/pseudocode/operators/MUL.tosac @@ -0,0 +1,37 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +if (in_out_t == shape_t) { + ERROR_IF(rank(shape) != 0 || rank(shape1) != 0 || rank(shape2) != 0); + shape_t value1 = tensor_read(input1, [], []); + shape_t value2 = tensor_read(input2, [], []); + shape_t result = value1 * value2; + tensor_write(output, [], [], result); +} else { + REQUIRE(0 <= shift && shift <= 63); + REQUIRE(in_t == int32_t || shift == 0); + ERROR_IF(shape != broadcast_shape(shape1, shape2)); + for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_t value1 = tensor_read(input1, shape1, index1); + in_t value2 = tensor_read(input2, shape2, index2); + out_t result; + if (in_t == i32_t && shift > 0) { + int64_t product = sign_extend(value1) * sign_extend(value2); + int64_t round = static_cast(1) << (shift - 1); + product = (product + round) >> shift; + REQUIRE(product >= minimum_s && product <= maximum_s) + result = product; + } else { + result = apply_mul_s(value1, value2); // low 32-bits of result for i32_t + } + tensor_write(output, shape, index, result); + } +} diff --git a/pseudocode/operators/NEGATE.tosac b/pseudocode/operators/NEGATE.tosac new file mode 100644 index 0000000..8c235f1 --- /dev/null +++ b/pseudocode/operators/NEGATE.tosac @@ -0,0 +1,22 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_out_t != i8_t && input1_zp != 0) // Zero point only for int8_t +ERROR_IF(in_out_t != i8_t && output_zp != 0) // Zero point only for int8_t +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape, index); + acc_t value = apply_sub_s(sign_extend(value1), + sign_extend(input1_zp)); + value = apply_sub_s(0, value); + value = apply_add_s(value, sign_extend(output_zp)); + in_out_t result = truncate(apply_clip_s(value, + minimum_s, + maximum_s)); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/PAD.tosac b/pseudocode/operators/PAD.tosac new file mode 100644 index 0000000..4adf114 --- /dev/null +++ b/pseudocode/operators/PAD.tosac @@ -0,0 +1,27 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +// Check output shape matches the padded input shape +ERROR_IF(rank(shape) != rank(shape1)); +for (i = 0; i < rank(shape); i++) { + ERROR_IF(padding[i,0] < 0 || padding[i,1] < 0); + ERROR_IF(shape[i] != padding[i, 0] + shape1[i] + padding[i, 1]); +} +for_each(index in shape) { + dim_t index1 = index; + bool_t is_pad = false; + for(i = 0; i < rank(shape); i++) { + index1[i] = index1[i] - padding[i,0]; + if (index1[i] < 0 || index[i] >= length(shape[i])) { + is_pad = true; + } + } + in_out_t value = is_pad ? pad_const : tensor_read(input1, shape1, index1); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/POW.tosac b/pseudocode/operators/POW.tosac new file mode 100644 index 0000000..6ecc8e6 --- /dev/null +++ b/pseudocode/operators/POW.tosac @@ -0,0 +1,18 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(shape1, shape2)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = apply_pow(value1, value2); + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/RECIPROCAL.tosac b/pseudocode/operators/RECIPROCAL.tosac new file mode 100644 index 0000000..9bc086b --- /dev/null +++ b/pseudocode/operators/RECIPROCAL.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape1, index); + in_out_t result = 1.0 / value1; + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/REDUCE_ALL.tosac b/pseudocode/operators/REDUCE_ALL.tosac new file mode 100644 index 0000000..7438513 --- /dev/null +++ b/pseudocode/operators/REDUCE_ALL.tosac @@ -0,0 +1,25 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape1)); +ERROR_IF(shape[axis] != 1); +left_shape = (axis > 1) ? shape[0:axis-1] : []; +right_shape = (axis < rank(shape)-1) ? shape[axis+1:rank(shape)-1] : []; +for_each(left_index in left_shape) { + for_each(right_index in right_shape) { + in_out_t acc = true; + for (i = 0; i < shape1[axis]; i++) { + index = flatten(left_index, [i], right_index); + in_out_t value = tensor_read(input, shape1, index); + acc = acc && value; + } + out_index = flatten(left_index, [0], right_index); + tensor_write(output, shape, out_index, acc); + } +} diff --git a/pseudocode/operators/REDUCE_ANY.tosac b/pseudocode/operators/REDUCE_ANY.tosac new file mode 100644 index 0000000..3303fac --- /dev/null +++ b/pseudocode/operators/REDUCE_ANY.tosac @@ -0,0 +1,25 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape1)); +ERROR_IF(shape[axis] != 1); +left_shape = (axis > 1) ? shape[0:axis-1] : []; +right_shape = (axis < rank(shape)-1) ? shape[axis+1:rank(shape)-1] : []; +for_each(left_index in left_shape) { + for_each(right_index in right_shape) { + in_out_t acc = false; + for (i = 0; i < shape1[axis]; i++) { + index = flatten(left_index, [i], right_index); + in_out_t value = tensor_read(input, shape1, index); + acc = acc || value; + } + out_index = flatten(left_index, [0], right_index); + tensor_write(output, shape, out_index, acc); + } +} diff --git a/pseudocode/operators/REDUCE_MAX.tosac b/pseudocode/operators/REDUCE_MAX.tosac new file mode 100644 index 0000000..57f291a --- /dev/null +++ b/pseudocode/operators/REDUCE_MAX.tosac @@ -0,0 +1,25 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape1)); +ERROR_IF(shape[axis] != 1); +left_shape = (axis > 1) ? shape[0:axis-1] : []; +right_shape = (axis < rank(shape)-1) ? shape[axis+1:rank(shape)-1] : []; +for_each(left_index in left_shape) { + for_each(right_index in right_shape) { + in_out_t acc = minimum; + for (i = 0; i < shape1[axis]; i++) { + index = flatten(left_index, [i], right_index); + in_out_t value = tensor_read(input, shape1, index); + acc = apply_max_s(acc, value); + } + out_index = flatten(left_index, [0], right_index); + tensor_write(output, shape, out_index, acc); + } +} diff --git a/pseudocode/operators/REDUCE_MIN.tosac b/pseudocode/operators/REDUCE_MIN.tosac new file mode 100644 index 0000000..5eaa702 --- /dev/null +++ b/pseudocode/operators/REDUCE_MIN.tosac @@ -0,0 +1,25 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape1)); +ERROR_IF(shape[axis] != 1); +left_shape = (axis > 1) ? shape[0:axis-1] : []; +right_shape = (axis < rank(shape)-1) ? shape[axis+1:rank(shape)-1] : []; +for_each(left_index in left_shape) { + for_each(right_index in right_shape) { + in_out_t acc = maximum; + for (i = 0; i < shape1[axis]; i++) { + index = flatten(left_index, [i], right_index); + in_out_t value = tensor_read(input, shape1, index); + acc = apply_min_s(acc, value); + } + out_index = flatten(left_index, [0], right_index); + tensor_write(output, shape, out_index, out); + } +} diff --git a/pseudocode/operators/REDUCE_PRODUCT.tosac b/pseudocode/operators/REDUCE_PRODUCT.tosac new file mode 100644 index 0000000..3c867d7 --- /dev/null +++ b/pseudocode/operators/REDUCE_PRODUCT.tosac @@ -0,0 +1,25 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape1)); +ERROR_IF(shape[axis] != 1); +left_shape = (axis > 1) ? shape[0:axis-1] : []; +right_shape = (axis < rank(shape)-1) ? shape[axis+1:rank(shape)-1] : []; +for_each(left_index in left_shape) { + for_each(right_index in right_shape) { + in_out_t acc = 1.0; + for (i = 0; i < shape1[axis]; i++) { + index = flatten(left_index, [i], right_index); + in_out_t value = tensor_read(input, shape1, index); + acc = apply_mul_s(acc, value); + } + out_index = flatten(left_index, [0], right_index); + tensor_write(output, shape, out_index, acc); + } +} diff --git a/pseudocode/operators/REDUCE_SUM.tosac b/pseudocode/operators/REDUCE_SUM.tosac new file mode 100644 index 0000000..2f22ada --- /dev/null +++ b/pseudocode/operators/REDUCE_SUM.tosac @@ -0,0 +1,26 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape1)); +ERROR_IF(shape[axis] != 1); +left_shape = (axis > 1) ? shape[0:axis-1] : []; +right_shape = (axis < rank(shape)-1) ? shape[axis+1:rank(shape)-1] : []; +for_each(left_index in left_shape) { + for_each(right_index in right_shape) { + acc_t acc = 0; + for (i = 0; i < shape1[axis]; i++) { + index = flatten(left_index, [i], right_index); + acc_t value = tensor_read(input, shape1, index); + acc = apply_add_s(acc, value); + } + out_index = flatten(left_index, [0], right_index); + in_out_t result = static_cast(acc); + tensor_write(output, shape, out_index, result); + } +} diff --git a/pseudocode/operators/RESCALE.tosac b/pseudocode/operators/RESCALE.tosac new file mode 100644 index 0000000..86a939b --- /dev/null +++ b/pseudocode/operators/RESCALE.tosac @@ -0,0 +1,58 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + // uint16 values can have zero_point 0 or 32768 + // int8/uint8 can have zero point within their valid range + // No other types can have zero point != 0 + ERROR_IF(in_t != i8_t && + (in_t != i16_t || input_unsigned == False) && input_zp != 0); + ERROR_IF(out_t != i8_t && + (out_t != i16_t || output_unsigned == False) && output_zp != 0); + ERROR_IF(in_t == i16_t && input_unsigned == True && input_zp != 0 && input_zp != 32768); + ERROR_IF(out_t == i16_t && output_unsigned == True && output_zp != 0 && output_zp != 32768); + ERROR_IF(scale32 && in_t == i48_t); + ERROR_IF(!scale32 && double_round); + ERROR_IF(in_t == i16_t && out_t == i32_t && input_unsigned); + ERROR_IF(in_t == i32_t && out_t == i16_t && output_unsigned); + + in_t in_value = tensor_read(input, shape, index); + + int48_t value, extended_in_zp; + if (input_unsigned) { + value = zero_extend(in_value); + extended_in_zp = zero_extend(input_zp); + } + else { + value = sign_extend(value); + extended_in_zp = sign_extend(input_zp); + } + + value = value - extended_in_zp; + int c = (per_channel) ? index[rank(input) - 1] : 0; + int32_t result = (scale32) ? + apply_scale_32(value, multiplier[c], shift[c], double_round) : + apply_scale_16(value, multiplier[c], shift[c]); + + if (output_unsigned) { + int32_t extended_out_zp = zero_extend(output_zp); + result = apply_add_s(result, extended_out_zp); + out_t out = static_cast(apply_clip(result, + minimum_u, + maximum_u)); + } + else { + int32_t extended_out_zp = sign_extend(output_zp); + result = apply_add_s(result, extended_out_zp); + out_t out = static_cast(apply_clip(result, + minimum_s, + maximum_s)); + } + tensor_write(output, shape, index, out); +} diff --git a/pseudocode/operators/RESHAPE.tosac b/pseudocode/operators/RESHAPE.tosac new file mode 100644 index 0000000..41439c3 --- /dev/null +++ b/pseudocode/operators/RESHAPE.tosac @@ -0,0 +1,21 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(tensor_size(shape1) != tensor_size(shape)); + +for_each(index in shape) { + // Calculate flattened index for the output location (index) + size_t offset = tensor_index_to_offset(shape, index); + // Now convert to the location in the input + dim_t tmp_index = tensor_offset_to_index(shape1, offset); + + // Now read/write the value + in_out_t val = tensor_read(input1, shape1, tmp_index); + tensor_write(output, shape, index, val); +} diff --git a/pseudocode/operators/RESIZE.tosac b/pseudocode/operators/RESIZE.tosac new file mode 100644 index 0000000..fd66530 --- /dev/null +++ b/pseudocode/operators/RESIZE.tosac @@ -0,0 +1,74 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +// Ensure the image size is supported by GPU APIs and that for integer +// implementations, position * stride does not overflow int32_t. +ERROR_IF(max(OH,OW,IH,IW) >= 16384); +ERROR_IF(scale_y_n <= 0 || scale_y_d <= 0 || scale_x_n <= 0 || scale_x_d <= 0); +// if in_t=int8_t ensure that an int32_t accumulator can be used +ERROR_IF(scale_y_n > (1 << 11) || scale_x_n > (1 << 11)); +// set a consistent lower limit of 1/16 downscale to simplify implementations +ERROR_IF(scale_y_d >= 16 * scale_y_n || scale_x_d >= 16 * scale_x_n); +ERROR_IF(offset_y < -scale_y_n || offset_y >= 16 * scale_y_n); +ERROR_IF(offset_x < -scale_x_n || offset_x >= 16 * scale_x_n); +ERROR_IF(border_y < -16 * scale_y_n || border_y >= scale_y_n); +ERROR_IF(border_x < -16 * scale_x_n || border_x >= scale_x_n); +ERROR_IF(OH != idiv_check((IH - 1) * scale_y_n - offset_y + border_y, scale_y_d) + 1); +ERROR_IF(OW != idiv_check((IW - 1) * scale_x_n - offset_x + border_x, scale_x_d) + 1); +for_each(0 <= n < N, 0 <= oy < OH, 0 <= ox < OW; 0 <= c < C) { + out_t acc; + resize_t dx, dy; + resize_t unit_x, unit_y; + + unit_x = (is_floating_point(resize_t)) ? 1.0 : scale_x_n; + unit_y = (is_floating_point(resize_t)) ? 1.0 : scale_y_n; + + int32_t y = oy * scale_y_d + offset_y; + int32_t x = ox * scale_x_d + offset_x; + int16_t iy = idiv_floor(y, scale_y_n); + int16_t ix = idiv_floor(x, scale_x_n); + int16_t ry = y - iy * scale_y_n; // (y % scale_y_n) + int16_t rx = x - ix * scale_x_n; // (x % scale_x_n) + + if (is_floating_point(resize_t)) { + dy = static_cast(ry) / static_cast(scale_y_n); + dx = static_cast(rx) / static_cast(scale_x_n); + } else { + dy = ry; + dx = rx; + } + // Note that -1 <= iy < IH and -1 <= ix < IW + int16_t iy0 = apply_max_s(iy, 0); + int16_t iy1 = apply_min_s(iy + 1, IH - 1); + int16_t ix0 = apply_max_s(ix, 0); + int16_t ix1 = apply_min_s(ix + 1, IW - 1); + if (mode==BILINEAR) { + using in_s_t = make_signed(in_t); // Use signed calculations for i8/i16 + in_s_t v00 = static_cast(tensor_read(input, [N,IH,IW,C], [n,iy0,ix0,c])); + in_s_t v01 = static_cast(tensor_read(input, [N,IH,IW,C], [n,iy0,ix1,c])); + in_s_t v10 = static_cast(tensor_read(input, [N,IH,IW,C], [n,iy1,ix0,c])); + in_s_t v11 = static_cast(tensor_read(input, [N,IH,IW,C], [n,iy1,ix1,c])); + acc = v00 * (unit_y - dy) * (unit_x - dx); + acc += v01 * (unit_y - dy) * dx; + acc += v10 * dy * (unit_x - dx); + acc += v11 * dy * dx; + tensor_write(output, [N,OH,OW,C], [n,oy,ox,c], acc); + } else if (mode==NEAREST) { + int32_t iy, ix; + if (is_floating_point(resize_t)) { + iy = (dy >= 0.5) ? iy1 : iy0; + ix = (dx >= 0.5) ? ix1 : ix0; + } else { + iy = (2 * dy >= scale_y_n) ? iy1 : iy0; + ix = (2 * dx >= scale_x_n) ? ix1 : ix0; + } + in_t v = tensor_read(input, [N,IH,IW,C], [n,iy,ix,c]); + tensor_write(output, [N,OH,OW,C], [n,oy,ox,c], v); + } +} diff --git a/pseudocode/operators/REVERSE.tosac b/pseudocode/operators/REVERSE.tosac new file mode 100644 index 0000000..63830d2 --- /dev/null +++ b/pseudocode/operators/REVERSE.tosac @@ -0,0 +1,16 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(axis < 0 || axis >= rank(shape)); +for_each(index in shape) { + dim_t tmp_index = index; + tmp_index[axis] = shape[axis] - 1 - index[axis]; + in_out_t value = tensor_read(input, shape, tmp_index); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/RFFT2D.tosac b/pseudocode/operators/RFFT2D.tosac new file mode 100644 index 0000000..f664826 --- /dev/null +++ b/pseudocode/operators/RFFT2D.tosac @@ -0,0 +1,24 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(!power_of_two(H)); +ERROR_IF(!power_of_two(W)); + +for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W/2 + 1) { + in_out_t sum_real = 0.0; + in_out_t sum_imag = 0.0; + for_each(0 <= iy < H, 0 <= ix < W) { + in_out_t val_real = tensor_read(input_real, [N,H,W], [n,iy,ix]); + float_t a = 2 * pi() * ((iy * oy) / H + (ix * ox) / W); + sum_real += val_real * cos(a); + sum_imag += -val_real * sin(a); + } + tensor_write(output_real, [N,H,W], [n,oy,ox], sum_real); + tensor_write(output_imag, [N,H,W], [n,oy,ox], sum_imag); +} diff --git a/pseudocode/operators/RSQRT.tosac b/pseudocode/operators/RSQRT.tosac new file mode 100644 index 0000000..15d884a --- /dev/null +++ b/pseudocode/operators/RSQRT.tosac @@ -0,0 +1,20 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input1, shape1, index); + in_out_t result; + if (value1 < 0) { + result = NaN; + } + else { + result = 1.0 / apply_sqrt(value1); + } + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/SCATTER.tosac b/pseudocode/operators/SCATTER.tosac new file mode 100644 index 0000000..5027816 --- /dev/null +++ b/pseudocode/operators/SCATTER.tosac @@ -0,0 +1,31 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + + +// The following array is used to check compliance that an output position +// is modified at most once. +bool_t output_modified[N,K,C]; + +// Copy the values_in tensor to the values_out tensor. +// Values not written by the scatter operation are unchanged in the output. +for_each(0 <= n < N, 0 <= k < K, 0 <= c < C) { + in_out_t value = tensor_read(values_in, [N,K,C], [n,k,c]); + tensor_write(values_out, [N,K,C], [n, k, c], value); + output_modified[n,k,c]=false; +} + +// Now perform the SCATTER operation, modifying the positions from the indices tensor +for_each(0 <= n < N, 0 <= w < W, 0 <= c < C) { + index_t k = tensor_read(indices, [N,W], [n,w]); + REQUIRE(0 <= k && k < K); + REQUIRE(output_modified[n,k,c] == false); + in_out_t value = tensor_read(input, [N,W,C], [n,w,c]); + tensor_write(values_out, [N,K,C], [n, k, c], value); + output_modified[n,k,c] = true; +} diff --git a/pseudocode/operators/SELECT.tosac b/pseudocode/operators/SELECT.tosac new file mode 100644 index 0000000..fe8d760 --- /dev/null +++ b/pseudocode/operators/SELECT.tosac @@ -0,0 +1,25 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(shape != broadcast_shape(broadcast_shape(shape1, shape2), shape3)); +for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + dim_t index3 = apply_broadcast(shape, shape3, index); + bool_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t value3 = tensor_read(input3, shape3, index3); + in_out_t result; + if (value1) { + result = value2; + } else { + result = value3; + } + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/SIGMOID.tosac b/pseudocode/operators/SIGMOID.tosac new file mode 100644 index 0000000..048523e --- /dev/null +++ b/pseudocode/operators/SIGMOID.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input, shape, index); + value = sigmoid(value1); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/SLICE.tosac b/pseudocode/operators/SLICE.tosac new file mode 100644 index 0000000..0ae0214 --- /dev/null +++ b/pseudocode/operators/SLICE.tosac @@ -0,0 +1,28 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(rank(shape1) != length(start) || rank(shape1) != length(size)); +ERROR_IF(rank(shape1) != rank(shape)); +// Sanity check the given coordinates, ensure start and end are +// within tensor bounds +for_each(index in rank(shape1)) { + ERROR_IF(start[index] < 0); + ERROR_IF(size[index] <= 0); //Output must be positive size + ERROR_IF(start[index] + size[index] > shape1[index]); + ERROR_IF(shape[index] != size[index]); +} + +for_each(index in shape) { + dim_t tmp_index = index; + for(i = 0; i < rank(shape); i++) { + tmp_index[i] = index[i] + start[i]; + } + in_out_t value = tensor_read(input1, shape1, tmp_index); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/SUB.tosac b/pseudocode/operators/SUB.tosac new file mode 100644 index 0000000..ac88b76 --- /dev/null +++ b/pseudocode/operators/SUB.tosac @@ -0,0 +1,26 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +if (in_out_t == shape_t) { + ERROR_IF(rank(shape) != 0 || rank(shape1) != 0 || rank(shape2) != 0); + shape_t value1 = tensor_read(input1, [], []); + shape_t value2 = tensor_read(input2, [], []); + shape_t result = apply_sub(value1, value2); + tensor_write(output, [], [], result); +} else { + ERROR_IF(shape != broadcast_shape(shape1, shape2)); + for_each(index in shape) { + dim_t index1 = apply_broadcast(shape, shape1, index); + dim_t index2 = apply_broadcast(shape, shape2, index); + in_out_t value1 = tensor_read(input1, shape1, index1); + in_out_t value2 = tensor_read(input2, shape2, index2); + in_out_t result = apply_sub_s(value1, value2); + tensor_write(output, shape, index, result); + } +} diff --git a/pseudocode/operators/TABLE.tosac b/pseudocode/operators/TABLE.tosac new file mode 100644 index 0000000..602d49b --- /dev/null +++ b/pseudocode/operators/TABLE.tosac @@ -0,0 +1,21 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +REQUIRE(length(table) == TABLE_SIZE); +for_each(index in shape) { + in_t value = tensor_read(input, shape, index); + out_t result; + if (in_t == i8_t) { + // value is a signed int, convert to a 0 based index + result = table[static_cast(value) + 128]; + } else { + result = apply_lookup_s(static_cast(table), static_cast(value)); + } + tensor_write(output, shape, index, result); +} diff --git a/pseudocode/operators/TANH.tosac b/pseudocode/operators/TANH.tosac new file mode 100644 index 0000000..1b5edba --- /dev/null +++ b/pseudocode/operators/TANH.tosac @@ -0,0 +1,14 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +for_each(index in shape) { + in_out_t value1 = tensor_read(input, shape, index); + value = tanh(value1); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/TILE.tosac b/pseudocode/operators/TILE.tosac new file mode 100644 index 0000000..d053b8f --- /dev/null +++ b/pseudocode/operators/TILE.tosac @@ -0,0 +1,20 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(rank(shape1) != rank(shape)); + +for_each(index in shape) { + dim_t tmp_index = index; + for(i = 0; i < rank(shape); i++) { + ERROR_IF(shape1[i] * multiples[i] != shape[i]); + tmp_index[i] = index[i] % shape1[i]; + } + in_out_t value = tensor_read(input1, shape1, tmp_index); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/TRANSPOSE.tosac b/pseudocode/operators/TRANSPOSE.tosac new file mode 100644 index 0000000..a8f0815 --- /dev/null +++ b/pseudocode/operators/TRANSPOSE.tosac @@ -0,0 +1,35 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(rank(shape1) != rank(shape)); +ERROR_IF(tensor_size(shape1) != tensor_size(shape)); + +for_each(index in perms) { + // Ensure each perms value is a valid value + ERROR_IF(index >= rank(shape1)); + ERROR_IF(index < 0); + // Ensure ranks aren't repeated + ERROR_IF(indexes_used[index] == true); + indexes_used[index] = true; +} + +// Ensure that the output shapes have the properly +// permuted shapes +for(i = 0; i < rank(shape); i++) { + ERROR_IF(shape1[perms[i]] != shape[i]) +} + +for_each(index in shape) { + dim_t tmp_index = index; + for(i = 0; i < rank(shape); i++) { + tmp_index[perms[i]] = index[i] + } + in_out_t value = tensor_read(input1, shape1, tmp_index); + tensor_write(output, shape, index, value); +} diff --git a/pseudocode/operators/TRANSPOSE_CONV2D.tosac b/pseudocode/operators/TRANSPOSE_CONV2D.tosac new file mode 100644 index 0000000..3aa0e23 --- /dev/null +++ b/pseudocode/operators/TRANSPOSE_CONV2D.tosac @@ -0,0 +1,35 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_t != i8_t && input_zp != 0); // Zero point only allowed for int8_t +ERROR_IF(weight_t != i8_t && weight_zp != 0); +ERROR_IF(out_pad_top <= -KH || out_pad_bottom <= -KH); +ERROR_IF(out_pad_left <= -KW || out_pad_right <= -KW); +ERROR_IF(stride_y < 1 || stride_x < 1); +ERROR_IF(OH != (IH - 1) * stride_y + out_pad_top + out_pad_bottom + KH); +ERROR_IF(OW != (IW - 1) * stride_x + out_pad_left + out_pad_right + KW); +ERROR_IF(BC != OC && BC != 1); + +for_each(index in [N, OH, OW, OC]) { + tensor_write(output, [N,OH,OW,OC], index, bias[(BC == 1) ? 0 : index[3]]) +} +for_each(0 <= n < N, 0 <= iy < IH, 0 <= ix < IW, 0 <= oc < OC, + 0 <= ic < IC, 0 <= ky < KH, 0 <= kx < KW) { + index_t oy = iy * stride_y + out_pad_top + ky; + index_t ox = ix * stride_x + out_pad_left + kx; + if (oy >= 0 && oy < OH && ox >= 0 && ox < OW) { + out_t acc = static_cast(tensor_read(output, [N,OH,OW,OC], [n,oy,ox,oc])); + out_t value = static_cast(tensor_read(input, [N,IH,IW,IC], [n,iy,ix,ic])); + out_t weight = static_cast(tensor_read(weight, [OC,KH,KW,IC], [oc,ky,kx,ic])); + value = apply_sub_s(value, static_cast(input_zp)); + weight = apply_sub_s(weight, static_cast(weight_zp)); + acc = apply_add_s(acc, apply_mul_s(value, weight)); + tensor_write(output, [N,OH,OW,OC], [n,oy,ox,oc], acc); + } +} diff --git a/pseudocode/operators/VARIABLE.tosac b/pseudocode/operators/VARIABLE.tosac new file mode 100644 index 0000000..4d2fce7 --- /dev/null +++ b/pseudocode/operators/VARIABLE.tosac @@ -0,0 +1,33 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + + +tensor_t var_tensor = variable_tensor_lookup(uid); + +// Invocation for the first time +if (var_tensor == NULL) { + // Allocate the persistent mutable memory for the variable tensor + tensor_t var_tensor = variable_tensor_allocate(var_shape, uid); + + if (initial_value != NULL) { + REQUIRE(var_t == in_t); + REQUIRE(var_shape == shape); + for_each (index in shape) { + // Copy data from initial_value to var_tensor + in_t value = tensor_read(initial_value, shape, index); + tensor_write(var_tensor.data, var_shape, index, value); + } + var_tensor.is_written = true; + } +} else { // Variable tensor has already been declared + // It's invalid to declare the second variable with the same uid in a single graph execution, + REQUIRE(!var_tensor.seen); +} + +var_tensor.seen = true; diff --git a/pseudocode/operators/VARIABLE_READ.tosac b/pseudocode/operators/VARIABLE_READ.tosac new file mode 100644 index 0000000..c2e0e38 --- /dev/null +++ b/pseudocode/operators/VARIABLE_READ.tosac @@ -0,0 +1,26 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + + +tensor_t variable_tensor = variable_tensor_lookup(uid); +// Check this variable tensor has been decalred +REQUIRE(variable_tensor != NULL); +// Check this variable tensor has been written +REQUIRE(variable_tensor.is_written); +// Output tensor's shape and variable_tensor's shape have to match +REQUIRE(variable_tensor.shape == shape); +// Output tensor's shape and variable_tensor's type have to match +REQUIRE(variable_tensor.type == out_t); + +for_each (index in shape) { + // Read data from pseudo-buffer resource to the output + out_t value = tensor_read(variable_tensor.data, variable_tensor.shape, index); + tensor_write(input1, shape, index, value); +} + diff --git a/pseudocode/operators/VARIABLE_WRITE.tosac b/pseudocode/operators/VARIABLE_WRITE.tosac new file mode 100644 index 0000000..83c5525 --- /dev/null +++ b/pseudocode/operators/VARIABLE_WRITE.tosac @@ -0,0 +1,29 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + + +tensor_t. variable_tensor = variable_tensor_lookup(uid); +// Check this variable tensor has been declared +REQUIRE(variable_tensor); +// The tensor has to be seen before to be written to +// The seen variable is cleared before each graph execution and set in declaration +REQUIRE(variable_tensor.seen); +// Input tensor's shape and variable_tensor's shape have to match +REQUIRE(variable_tensor.shape == shape); +// Input tensor's shape and variable_tensor's type have to match +REQUIRE(variable_tensor.type == in_t); + +for_each (index in shape) { + // Write data from the input to the pseudo-buffer resource + in_t value = tensor_read(input1, shape, index); + tensor_write(variable_tensor.data, variable_tensor.shape, index, value); +} + +variable_tensor.is_written = true; + diff --git a/pseudocode/operators/WHILE_LOOP.tosac b/pseudocode/operators/WHILE_LOOP.tosac new file mode 100644 index 0000000..dae96d5 --- /dev/null +++ b/pseudocode/operators/WHILE_LOOP.tosac @@ -0,0 +1,33 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(tosa_nesting_depth >= MAX_NESTING); +ERROR_IF(tensor_list_shape(input_list) != tosa_list_shape(output_list)); +ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(cond_graph)); +ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(body_graph)); +ERROR_IF(tensor_list_shape(input_list) != tosa_output_shape(body_graph)); +// Condition graph output must be a single element tensor with a single bool value +ERROR_IF(tensor_size(tosa_output_shape(cond_graph)) != 1); +ERROR_IF(tosa_output_type(cond_graph) != bool_t); + +// The iteration number 'i' is included to give unique names to variables +// in each iteration of the loop and is not required by implementations +int32_t i=0; // iteration number +tensor_list_t list[]; // array of tensor lists indexed by iteration +bool_t *condition[]; // array of condition tensors indexed by iteration +list[i] = input_list; // copy input data as list[0] +tosa_nesting_depth++; +tosa_execute_graph(cond_graph, list[i], [ condition[i] ]); // initial condition +while (condition[i][0]) { + tosa_execute_graph(body_graph, list[i], list[i+1]); + i = i+1; + tosa_execute_graph(cond_graph, list[i], [ condition[i] ]); +} +tosa_nesting_depth--; +output_list = list[i]; diff --git a/pseudocode/operators/tables/ERF.tosac b/pseudocode/operators/tables/ERF.tosac new file mode 100644 index 0000000..0ff29ff --- /dev/null +++ b/pseudocode/operators/tables/ERF.tosac @@ -0,0 +1,16 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +int16_t erf_reference(int16_t x) { // input x range is -256 to + 256 inclusive + F64 v = (double)x / (double)64; + v = erf(v); + return round_to_nearest_int(32768.0 * v); +} + +generate_lookup_table(&erf_table, &erf_reference); diff --git a/pseudocode/operators/tables/SIGMOID.tosac b/pseudocode/operators/tables/SIGMOID.tosac new file mode 100644 index 0000000..dad1e1d --- /dev/null +++ b/pseudocode/operators/tables/SIGMOID.tosac @@ -0,0 +1,16 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +int16_t sigmoid_reference(int16_t x) { // input x range is -256 to + 256 inclusive + fp64_t v = (fp64_t)x / (fp64_t)16; + v = 1.0/(1.0 + exp(-v)); + return round_to_nearest_int(32768.0 * v); +} + +generate_lookup_table(&sigmoid_table, &sigmoid_reference); diff --git a/pseudocode/operators/tables/TANH.tosac b/pseudocode/operators/tables/TANH.tosac new file mode 100644 index 0000000..b45f121 --- /dev/null +++ b/pseudocode/operators/tables/TANH.tosac @@ -0,0 +1,17 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +int16_t tanh_reference(int16_t x) { // input x range is -256 to +256 inclusive + fp64_t v = (fp64_t)x/(fp64_t)32; + v = exp(-2.0*v); + v = (1.0-v)/(1.0+v); + return round_to_nearest_int(32768.0 * v); +} + +generate_lookup_table(&tanh_table, &tanh_reference); -- cgit v1.2.1