| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | module athena__onnx_utils | ||
| 2 | !! Shared utility routines for ONNX JSON export | ||
| 3 | !! | ||
| 4 | !! Contains base64 encoding, node emission helpers, col→row transpose, | ||
| 5 | !! and activation/attribute-building utilities used by both the main | ||
| 6 | !! write_onnx procedure and layer-specific emit_onnx_nodes overrides. | ||
| 7 | use coreutils, only: real32, to_lower | ||
| 8 | use athena__misc_types, only: onnx_node_type, onnx_initialiser_type, & | ||
| 9 | onnx_tensor_type, onnx_attribute_type | ||
| 10 | use athena__base_layer, only: base_layer_type, learnable_layer_type | ||
| 11 | implicit none | ||
| 12 | |||
| 13 | private | ||
| 14 | |||
| 15 | public :: emit_node | ||
| 16 | public :: emit_squeeze_node | ||
| 17 | public :: emit_constant_int64 | ||
| 18 | public :: emit_constant_float | ||
| 19 | public :: emit_constant_of_shape_float | ||
| 20 | public :: emit_activation_node | ||
| 21 | public :: emit_initialisers | ||
| 22 | public :: build_attributes_json | ||
| 23 | public :: col_to_row_major_2d | ||
| 24 | public :: write_json_nodes | ||
| 25 | public :: write_json_initialisers | ||
| 26 | public :: write_json_tensors | ||
| 27 | public :: encode_float32_base64 | ||
| 28 | public :: encode_float32_base64_alloc | ||
| 29 | public :: encode_int64_base64 | ||
| 30 | public :: encode_int64_base64_alloc | ||
| 31 | public :: decode_base64_to_float32 | ||
| 32 | public :: decode_base64_to_int64 | ||
| 33 | public :: row_to_col_major_2d | ||
| 34 | public :: encode_string_base64 | ||
| 35 | public :: base64_encode_bytes | ||
| 36 | public :: base64_encode_bytes_fixed | ||
| 37 | public :: parse_space_separated_ints | ||
| 38 | public :: onnx_to_athena_activation | ||
| 39 | |||
| 40 | contains | ||
| 41 | |||
| 42 | |||
| 43 | !############################################################################### | ||
| 44 | 165 | subroutine emit_node(op_type, name, out1, attr_json, nodes, num_nodes, & | |
| 45 | in1, in2, in3) | ||
| 46 | !! Emit a simple ONNX node (individual string interface) | ||
| 47 | !! Avoids gfortran array constructor issues | ||
| 48 | implicit none | ||
| 49 | |||
| 50 | ! Arguments | ||
| 51 | character(*), intent(in) :: op_type, name, out1, attr_json | ||
| 52 | !! ONNX operation type, node name, output name, and attribute JSON | ||
| 53 | type(onnx_node_type), intent(inout), dimension(:) :: nodes | ||
| 54 | !! Node accumulator array | ||
| 55 | integer, intent(inout) :: num_nodes | ||
| 56 | !! Current number of populated nodes | ||
| 57 | character(*), intent(in), optional :: in1, in2, in3 | ||
| 58 | !! Optional input tensor names | ||
| 59 | |||
| 60 | ! Local variables | ||
| 61 | integer :: n_in | ||
| 62 | !! Number of connected inputs for the emitted node | ||
| 63 | |||
| 64 | 165 | n_in = 0 | |
| 65 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | if(present(in1)) n_in = 1 |
| 66 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 64 times.
|
165 | if(present(in2)) n_in = 2 |
| 67 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 158 times.
|
165 | if(present(in3)) n_in = 3 |
| 68 | |||
| 69 | 165 | num_nodes = num_nodes + 1 | |
| 70 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 165 times.
✓ Branch 7 taken 165 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 165 times.
✗ Branch 10 not taken.
|
165 | nodes(num_nodes)%name = trim(name) |
| 71 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 165 times.
✓ Branch 7 taken 165 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 165 times.
✗ Branch 10 not taken.
|
165 | nodes(num_nodes)%op_type = trim(op_type) |
| 72 |
9/18✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✓ Branch 6 taken 165 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 165 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 165 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 165 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 165 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 165 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 165 times.
|
165 | allocate(nodes(num_nodes)%inputs(n_in)) |
| 73 |
7/14✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 165 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 165 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 165 times.
✓ Branch 15 taken 165 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 165 times.
✗ Branch 18 not taken.
|
165 | if(present(in1)) nodes(num_nodes)%inputs(1) = trim(in1) |
| 74 |
8/14✓ Branch 0 taken 101 times.
✓ Branch 1 taken 64 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 101 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 101 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 101 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 101 times.
✓ Branch 15 taken 101 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 101 times.
✗ Branch 18 not taken.
|
165 | if(present(in2)) nodes(num_nodes)%inputs(2) = trim(in2) |
| 75 |
8/14✓ Branch 0 taken 7 times.
✓ Branch 1 taken 158 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
✓ Branch 15 taken 7 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 7 times.
✗ Branch 18 not taken.
|
165 | if(present(in3)) nodes(num_nodes)%inputs(3) = trim(in3) |
| 76 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 165 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 165 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 165 times.
|
165 | allocate(nodes(num_nodes)%outputs(1)) |
| 77 |
6/12✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 165 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 165 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 165 times.
✓ Branch 13 taken 165 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 165 times.
✗ Branch 16 not taken.
|
165 | nodes(num_nodes)%outputs(1) = trim(out1) |
| 78 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✓ Branch 6 taken 165 times.
✗ Branch 7 not taken.
|
165 | nodes(num_nodes)%attributes_json = attr_json |
| 79 | |||
| 80 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | end subroutine emit_node |
| 81 | !############################################################################### | ||
| 82 | |||
| 83 | |||
| 84 | !############################################################################### | ||
| 85 | 14 | subroutine emit_squeeze_node(name, input, axes_input, output, & | |
| 86 | 14 | nodes, num_nodes) | |
| 87 | !! Emit a Squeeze node (ONNX opset 13+: axes as input) | ||
| 88 | implicit none | ||
| 89 | |||
| 90 | ! Arguments | ||
| 91 | character(*), intent(in) :: name, input, axes_input, output | ||
| 92 | !! Node name, data input, axes input, and output tensor name | ||
| 93 | type(onnx_node_type), intent(inout), dimension(:) :: nodes | ||
| 94 | !! Node accumulator array | ||
| 95 | integer, intent(inout) :: num_nodes | ||
| 96 | !! Current number of populated nodes | ||
| 97 | |||
| 98 | ✗ | call emit_node('Squeeze', name, output, '', nodes, num_nodes, & | |
| 99 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
|
14 | in1=input, in2=axes_input) |
| 100 | |||
| 101 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | end subroutine emit_squeeze_node |
| 102 | !############################################################################### | ||
| 103 | |||
| 104 | |||
| 105 | !############################################################################### | ||
| 106 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | subroutine emit_constant_int64(name, values, dims, & |
| 107 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | nodes, num_nodes, inits, num_inits) |
| 108 | !! Emit a Constant node producing an int64 tensor | ||
| 109 | implicit none | ||
| 110 | |||
| 111 | ! Arguments | ||
| 112 | character(*), intent(in) :: name | ||
| 113 | !! Constant node and output tensor name | ||
| 114 | integer, intent(in) :: values(:), dims(:) | ||
| 115 | !! Constant values and tensor dimensions | ||
| 116 | type(onnx_node_type), intent(inout), dimension(:) :: nodes | ||
| 117 | !! Node accumulator array | ||
| 118 | integer, intent(inout) :: num_nodes | ||
| 119 | !! Current number of populated nodes | ||
| 120 | type(onnx_initialiser_type), intent(inout), dimension(:) :: inits | ||
| 121 | !! Initialiser accumulator array (unused, kept for interface symmetry) | ||
| 122 | integer, intent(inout) :: num_inits | ||
| 123 | !! Current number of populated initialisers (unused) | ||
| 124 | |||
| 125 | ! Local variables | ||
| 126 | character(4096) :: attr_str | ||
| 127 | !! Serialized ONNX attribute JSON for the constant payload | ||
| 128 | character(256) :: raw_b64 | ||
| 129 | !! Base64-encoded raw tensor data | ||
| 130 | integer :: i | ||
| 131 | !! Dimension loop index | ||
| 132 | |||
| 133 | ! Encode int64 values as base64 | ||
| 134 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
|
37 | call encode_int64_base64(values, raw_b64) |
| 135 | |||
| 136 | ! Build dims string | ||
| 137 | 37 | attr_str = ' "attribute": [{"name": "value", "t": {' | |
| 138 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
✓ Branch 9 taken 37 times.
✗ Branch 10 not taken.
|
37 | if(size(dims) .gt. 0)then |
| 139 |
2/4✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
|
37 | attr_str = trim(attr_str) // '"dims": [' |
| 140 |
5/8✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
✓ Branch 9 taken 37 times.
✓ Branch 10 taken 37 times.
|
74 | do i = 1, size(dims) |
| 141 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
37 | if(i .gt. 1) attr_str = trim(attr_str) // ', ' |
| 142 |
3/6✓ Branch 3 taken 37 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 37 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 37 times.
|
74 | write(attr_str, '(A,"""",I0,"""")') trim(attr_str), dims(i) |
| 143 | end do | ||
| 144 |
2/4✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
|
37 | attr_str = trim(attr_str) // '], ' |
| 145 | end if | ||
| 146 | attr_str = trim(attr_str) // '"dataType": 7, "rawData": "' // & | ||
| 147 |
3/6✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 37 times.
✗ Branch 10 not taken.
|
37 | trim(raw_b64) // '"}, "type": "TENSOR"}]' |
| 148 | |||
| 149 | 37 | num_nodes = num_nodes + 1 | |
| 150 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
✓ Branch 7 taken 37 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 37 times.
✗ Branch 10 not taken.
|
37 | nodes(num_nodes)%name = trim(name) |
| 151 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
|
37 | nodes(num_nodes)%op_type = 'Constant' |
| 152 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 37 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 37 times.
|
37 | allocate(nodes(num_nodes)%inputs(0)) |
| 153 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 37 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 37 times.
|
37 | allocate(nodes(num_nodes)%outputs(1)) |
| 154 |
6/12✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 37 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 37 times.
✓ Branch 13 taken 37 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 37 times.
✗ Branch 16 not taken.
|
37 | nodes(num_nodes)%outputs(1) = trim(name) |
| 155 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
✓ Branch 7 taken 37 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 37 times.
✗ Branch 10 not taken.
|
37 | nodes(num_nodes)%attributes_json = trim(attr_str) |
| 156 | |||
| 157 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | end subroutine emit_constant_int64 |
| 158 | !############################################################################### | ||
| 159 | |||
| 160 | |||
| 161 | !############################################################################### | ||
| 162 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | subroutine emit_constant_float(name, values, dims, & |
| 163 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | nodes, num_nodes, inits, num_inits) |
| 164 | !! Emit a Constant node producing a float32 tensor | ||
| 165 | implicit none | ||
| 166 | |||
| 167 | ! Arguments | ||
| 168 | character(*), intent(in) :: name | ||
| 169 | !! Constant node and output tensor name | ||
| 170 | real(real32), intent(in) :: values(:) | ||
| 171 | !! Float32 constant values to embed in the node | ||
| 172 | integer, intent(in) :: dims(:) | ||
| 173 | !! Tensor dimensions for the constant value | ||
| 174 | type(onnx_node_type), intent(inout), dimension(:) :: nodes | ||
| 175 | !! Node accumulator array | ||
| 176 | integer, intent(inout) :: num_nodes | ||
| 177 | !! Current number of populated nodes | ||
| 178 | type(onnx_initialiser_type), intent(inout), dimension(:) :: inits | ||
| 179 | !! Initialiser accumulator array (unused, kept for interface symmetry) | ||
| 180 | integer, intent(inout) :: num_inits | ||
| 181 | !! Current number of populated initialisers (unused) | ||
| 182 | |||
| 183 | ! Local variables | ||
| 184 | character(4096) :: attr_str | ||
| 185 | !! Serialized ONNX attribute JSON for the constant payload | ||
| 186 | character(256) :: raw_b64 | ||
| 187 | !! Base64-encoded raw tensor data | ||
| 188 | integer :: i | ||
| 189 | !! Dimension loop index | ||
| 190 | |||
| 191 |
6/12✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7 times.
|
7 | call encode_float32_base64(values, size(values), raw_b64) |
| 192 | |||
| 193 | 7 | attr_str = ' "attribute": [{"name": "value", "t": {' | |
| 194 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
|
7 | if(size(dims) .gt. 0)then |
| 195 |
2/4✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | attr_str = trim(attr_str) // '"dims": [' |
| 196 |
5/8✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✓ Branch 9 taken 7 times.
✓ Branch 10 taken 7 times.
|
14 | do i = 1, size(dims) |
| 197 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
7 | if(i .gt. 1) attr_str = trim(attr_str) // ', ' |
| 198 |
3/6✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
|
14 | write(attr_str, '(A,"""",I0,"""")') trim(attr_str), dims(i) |
| 199 | end do | ||
| 200 |
2/4✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | attr_str = trim(attr_str) // '], ' |
| 201 | end if | ||
| 202 | attr_str = trim(attr_str) // '"dataType": 1, "rawData": "' // & | ||
| 203 |
3/6✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
|
7 | trim(raw_b64) // '"}, "type": "TENSOR"}]' |
| 204 | |||
| 205 | 7 | num_nodes = num_nodes + 1 | |
| 206 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
|
7 | nodes(num_nodes)%name = trim(name) |
| 207 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
|
7 | nodes(num_nodes)%op_type = 'Constant' |
| 208 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
|
7 | allocate(nodes(num_nodes)%inputs(0)) |
| 209 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
|
7 | allocate(nodes(num_nodes)%outputs(1)) |
| 210 |
6/12✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 7 times.
✓ Branch 13 taken 7 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 7 times.
✗ Branch 16 not taken.
|
7 | nodes(num_nodes)%outputs(1) = trim(name) |
| 211 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
|
7 | nodes(num_nodes)%attributes_json = trim(attr_str) |
| 212 | |||
| 213 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | end subroutine emit_constant_float |
| 214 | !############################################################################### | ||
| 215 | |||
| 216 | |||
| 217 | !############################################################################### | ||
| 218 | 5 | subroutine emit_constant_of_shape_float(name, shape_input, value, output, & | |
| 219 | 5 | nodes, num_nodes, inits, num_inits) | |
| 220 | !! Emit a ConstantOfShape node | ||
| 221 | implicit none | ||
| 222 | |||
| 223 | ! Arguments | ||
| 224 | character(*), intent(in) :: name, shape_input, output | ||
| 225 | !! Node name, shape tensor input, and output tensor name | ||
| 226 | real(real32), intent(in) :: value | ||
| 227 | !! Fill value to use for the generated tensor | ||
| 228 | type(onnx_node_type), intent(inout), dimension(:) :: nodes | ||
| 229 | !! Node accumulator array | ||
| 230 | integer, intent(inout) :: num_nodes | ||
| 231 | !! Current number of populated nodes | ||
| 232 | type(onnx_initialiser_type), intent(inout), dimension(:) :: inits | ||
| 233 | !! Initialiser accumulator array (unused, kept for interface symmetry) | ||
| 234 | integer, intent(inout) :: num_inits | ||
| 235 | !! Current number of populated initialisers (unused) | ||
| 236 | |||
| 237 | ! Local variables | ||
| 238 | character(4096) :: attr_str | ||
| 239 | !! Serialized ONNX attribute JSON for the fill tensor | ||
| 240 | character(256) :: raw_b64 | ||
| 241 | !! Base64-encoded fill value | ||
| 242 | |||
| 243 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
|
10 | call encode_float32_base64([value], 1, raw_b64) |
| 244 | |||
| 245 | attr_str = ' "attribute": [{"name": "value", "t": {' // & | ||
| 246 | '"dims": ["1"], "dataType": 1, "rawData": "' // & | ||
| 247 |
2/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
|
5 | trim(raw_b64) // '"}, "type": "TENSOR"}]' |
| 248 | |||
| 249 | call emit_node('ConstantOfShape', name, output, & | ||
| 250 | ✗ | trim(attr_str), nodes, num_nodes, & | |
| 251 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
|
5 | in1=shape_input) |
| 252 | |||
| 253 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | end subroutine emit_constant_of_shape_float |
| 254 | !############################################################################### | ||
| 255 | |||
| 256 | |||
| 257 | !############################################################################### | ||
| 258 | 12 | subroutine emit_activation_node(name, prefix, input_override, & | |
| 259 | 12 | nodes, num_nodes, max_nodes) | |
| 260 | !! Emit an activation function node | ||
| 261 | use coreutils, only: to_camel_case | ||
| 262 | implicit none | ||
| 263 | |||
| 264 | ! Arguments | ||
| 265 | character(*), intent(in) :: name, prefix, input_override | ||
| 266 | !! Activation name, node prefix, and optional override for the input name | ||
| 267 | type(onnx_node_type), intent(inout), dimension(:) :: nodes | ||
| 268 | !! Node accumulator array | ||
| 269 | integer, intent(inout) :: num_nodes | ||
| 270 | !! Current number of populated nodes | ||
| 271 | integer, intent(in) :: max_nodes | ||
| 272 | !! Maximum number of nodes available in the accumulator | ||
| 273 | |||
| 274 | ! Local variables | ||
| 275 | character(128) :: actv_name, input_n, output_n | ||
| 276 | !! Normalised ONNX op name, input tensor name, and output tensor name | ||
| 277 | character(4096) :: attr_str | ||
| 278 | !! Serialized ONNX attribute JSON for activation-specific options | ||
| 279 | |||
| 280 | actv_name = to_camel_case( & | ||
| 281 | trim(adjustl(name)), & | ||
| 282 |
2/4✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
|
12 | capitalise_first_letter = .true.) |
| 283 | |||
| 284 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
|
12 | if(len_trim(input_override) .gt. 0)then |
| 285 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
5 | input_n = trim(input_override) |
| 286 | else | ||
| 287 |
2/4✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | input_n = trim(prefix) // '_output' |
| 288 | end if | ||
| 289 |
3/6✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
|
12 | output_n = trim(prefix) // '_' // trim(adjustl(name)) // '_output' |
| 290 | |||
| 291 | 12 | attr_str = '' | |
| 292 | ! LeakyRelu needs alpha attribute | ||
| 293 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
|
12 | if(trim(name) .eq. 'leaky_relu')then |
| 294 | ✗ | actv_name = 'LeakyRelu' | |
| 295 | attr_str = ' "attribute": [{"name": "alpha", ' // & | ||
| 296 | ✗ | '"f": 0.01, "type": "FLOAT"}]' | |
| 297 | end if | ||
| 298 | |||
| 299 | call emit_node(trim(actv_name), & | ||
| 300 | trim(prefix)//'_'//trim(adjustl(name)), & | ||
| 301 | ✗ | trim(output_n), trim(attr_str), nodes, num_nodes, & | |
| 302 |
9/18✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 12 times.
✓ Branch 20 taken 12 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 12 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 12 times.
✓ Branch 26 taken 12 times.
✗ Branch 27 not taken.
|
12 | in1=trim(input_n)) |
| 303 | |||
| 304 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | end subroutine emit_activation_node |
| 305 | !############################################################################### | ||
| 306 | |||
| 307 | |||
| 308 | !############################################################################### | ||
| 309 | 10 | subroutine emit_initialisers(layer, prefix, inits, num_inits, max_inits) | |
| 310 | !! Emit initialisers for a learnable layer | ||
| 311 | implicit none | ||
| 312 | |||
| 313 | ! Arguments | ||
| 314 | class(learnable_layer_type), intent(in) :: layer | ||
| 315 | !! Learnable layer containing parameter tensors and shape metadata | ||
| 316 | character(*), intent(in) :: prefix | ||
| 317 | !! Name prefix used to generate exported initialiser names | ||
| 318 | type(onnx_initialiser_type), intent(inout), dimension(:) :: inits | ||
| 319 | !! Initialiser accumulator array | ||
| 320 | integer, intent(inout) :: num_inits | ||
| 321 | !! Current number of populated initialisers | ||
| 322 | integer, intent(in) :: max_inits | ||
| 323 | !! Maximum number of initialisers available in the accumulator | ||
| 324 | |||
| 325 | ! Local variables | ||
| 326 | integer :: i, j, n | ||
| 327 | !! Parameter index, shape index, and flattened tensor size | ||
| 328 | character(128) :: name | ||
| 329 | !! Generated ONNX initialiser name for the current parameter tensor | ||
| 330 | |||
| 331 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if(.not.allocated(layer%params)) return |
| 332 | |||
| 333 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 10 times.
|
36 | do i = 1, size(layer%params) |
| 334 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
|
26 | n = size(layer%params(i)%val, 1) |
| 335 | 26 | num_inits = num_inits + 1 | |
| 336 |
1/2✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
|
26 | write(name, '(A,"_param",I0)') trim(prefix), i |
| 337 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 26 times.
✓ Branch 7 taken 26 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 26 times.
✗ Branch 10 not taken.
|
26 | inits(num_inits)%name = trim(name) |
| 338 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
|
26 | inits(num_inits)%data_type = 1 |
| 339 | |||
| 340 | ! Set dims from weight_shape | ||
| 341 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | if(allocated(layer%weight_shape))then |
| 342 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 11 times.
|
26 | if(i .le. size(layer%weight_shape, 2))then |
| 343 | 15 | j = 0 | |
| 344 |
9/18✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 15 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 15 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 15 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 15 times.
|
15 | allocate(inits(num_inits)%dims(size(layer%weight_shape, 1))) |
| 345 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✓ Branch 6 taken 34 times.
✓ Branch 7 taken 15 times.
|
49 | inits(num_inits)%dims = 0 |
| 346 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 15 times.
|
49 | do j = 1, size(layer%weight_shape, 1) |
| 347 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 34 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 34 times.
✓ Branch 12 taken 34 times.
✗ Branch 13 not taken.
|
49 | if(layer%weight_shape(j,i) .gt. 0)then |
| 348 |
8/16✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 34 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 34 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 34 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 34 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 34 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 34 times.
|
34 | inits(num_inits)%dims(j) = layer%weight_shape(j,i) |
| 349 | end if | ||
| 350 | end do | ||
| 351 | ! Remove zero dims | ||
| 352 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
|
30 | inits(num_inits)%dims = pack(inits(num_inits)%dims, & |
| 353 |
18/32✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 15 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 15 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 15 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 15 times.
✓ Branch 24 taken 34 times.
✓ Branch 25 taken 15 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 15 times.
✓ Branch 29 taken 34 times.
✓ Branch 30 taken 15 times.
✓ Branch 31 taken 15 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 15 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✓ Branch 37 taken 34 times.
✓ Branch 38 taken 15 times.
|
147 | inits(num_inits)%dims .gt. 0) |
| 354 | else | ||
| 355 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
|
11 | allocate(inits(num_inits)%dims(1)) |
| 356 |
6/12✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✓ Branch 13 taken 11 times.
|
22 | inits(num_inits)%dims = [n] |
| 357 | end if | ||
| 358 | else | ||
| 359 | ✗ | allocate(inits(num_inits)%dims(1)) | |
| 360 | ✗ | inits(num_inits)%dims = [n] | |
| 361 | end if | ||
| 362 | |||
| 363 |
9/18✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 26 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 26 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 26 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 26 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 26 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 26 times.
|
26 | allocate(inits(num_inits)%data(n)) |
| 364 | ! Convert column-major to row-major for 2D weight matrices | ||
| 365 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
36 | if(allocated(layer%weight_shape))then |
| 366 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 11 times.
|
26 | if(i .le. size(layer%weight_shape, 2))then |
| 367 |
11/18✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 15 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 15 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 15 times.
✓ Branch 18 taken 34 times.
✓ Branch 19 taken 15 times.
✓ Branch 20 taken 34 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 13 times.
✓ Branch 23 taken 2 times.
|
49 | if(count(layer%weight_shape(:,i) .gt. 0) .eq. 2)then |
| 368 | call col_to_row_major_2d( & | ||
| 369 | 130 | layer%params(i)%val(:,1), & | |
| 370 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
|
13 | inits(num_inits)%data, & |
| 371 | 52 | layer%weight_shape(1,i), & | |
| 372 |
19/38✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 13 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 13 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 13 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 13 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 13 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 13 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 13 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 13 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 13 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 13 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 13 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 13 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 13 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 13 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 13 times.
|
26 | layer%weight_shape(2,i)) |
| 373 | else | ||
| 374 |
14/28✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 2 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 72 times.
✓ Branch 37 taken 2 times.
|
74 | inits(num_inits)%data = layer%params(i)%val(:,1) |
| 375 | end if | ||
| 376 | else | ||
| 377 |
14/28✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 11 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 11 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 11 times.
✓ Branch 30 taken 11 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 11 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 82 times.
✓ Branch 37 taken 11 times.
|
93 | inits(num_inits)%data = layer%params(i)%val(:,1) |
| 378 | end if | ||
| 379 | else | ||
| 380 | ✗ | inits(num_inits)%data = layer%params(i)%val(:,1) | |
| 381 | end if | ||
| 382 | end do | ||
| 383 | |||
| 384 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | end subroutine emit_initialisers |
| 385 | !############################################################################### | ||
| 386 | |||
| 387 | |||
| 388 | !############################################################################### | ||
| 389 | ✗ | subroutine build_attributes_json(layer, op_type, attr_json) | |
| 390 | !! Build JSON string for layer attributes | ||
| 391 | implicit none | ||
| 392 | |||
| 393 | ! Arguments | ||
| 394 | class(base_layer_type), intent(in) :: layer | ||
| 395 | !! Layer supplying ONNX attribute metadata | ||
| 396 | character(*), intent(in) :: op_type | ||
| 397 | !! ONNX operation type used to handle special cases | ||
| 398 | character(4096), intent(out) :: attr_json | ||
| 399 | !! Serialized JSON fragment containing the emitted attributes | ||
| 400 | |||
| 401 | ! Local variables | ||
| 402 | 17 | type(onnx_attribute_type), allocatable, dimension(:) :: attributes | |
| 403 | !! Attribute list returned by the layer | ||
| 404 | integer :: i, j, itmp1 | ||
| 405 | !! Attribute index, value index, and temporary integer count | ||
| 406 | character(256) :: buffer | ||
| 407 | !! Temporary string buffer for serialised scalar values | ||
| 408 | 17 | integer, allocatable :: ivar_list(:) | |
| 409 | !! Parsed integer attribute payload for INTS-valued attributes | ||
| 410 | real(real32), allocatable :: rvar_list(:) | ||
| 411 | !! Placeholder for future real-valued list attributes | ||
| 412 | character(10) :: type_lw | ||
| 413 | !! Lower-case attribute type string used in the select case | ||
| 414 | |||
| 415 | 17 | attr_json = '' | |
| 416 | |||
| 417 | ! For Gemm, add transB attribute | ||
| 418 |
3/4✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 13 times.
|
17 | if(trim(op_type) .eq. 'Gemm')then |
| 419 | attr_json = ' "attribute": [' // & | ||
| 420 | '{"name": "alpha", "f": 1.0, "type": "FLOAT"}, ' // & | ||
| 421 | '{"name": "beta", "f": 1.0, "type": "FLOAT"}, ' // & | ||
| 422 | 4 | '{"name": "transB", "i": "1", "type": "INT"}]' | |
| 423 | 4 | return | |
| 424 | end if | ||
| 425 | |||
| 426 |
11/34✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 29 times.
✓ Branch 12 taken 13 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 29 times.
✓ Branch 28 taken 13 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 29 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 29 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 29 times.
|
84 | attributes = layer%get_attributes() |
| 427 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
|
13 | if(.not.allocated(attributes) .or. size(attributes) .eq. 0) return |
| 428 | |||
| 429 | 8 | attr_json = ' "attribute": [' | |
| 430 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 8 times.
|
37 | do i = 1, size(attributes) |
| 431 |
4/6✓ Branch 0 taken 21 times.
✓ Branch 1 taken 8 times.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
|
29 | if(i .gt. 1) attr_json = trim(attr_json) // ', ' |
| 432 | attr_json = trim(attr_json) // '{"name": "' // & | ||
| 433 |
5/10✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 29 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 29 times.
✓ Branch 12 taken 29 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 29 times.
✗ Branch 16 not taken.
|
29 | trim(attributes(i)%name) // '"' |
| 434 | |||
| 435 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✓ Branch 8 taken 29 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 29 times.
✗ Branch 11 not taken.
|
29 | type_lw = trim(adjustl(attributes(i)%type)) |
| 436 | 8 | select case(type_lw) | |
| 437 | case('int') | ||
| 438 | attr_json = trim(attr_json) // ', "i": "' // & | ||
| 439 |
5/10✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✓ Branch 13 taken 15 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 15 times.
✗ Branch 17 not taken.
|
15 | trim(adjustl(attributes(i)%val)) // '", "type": "INT"}' |
| 440 | case('ints') | ||
| 441 | ! Parse multiple ints | ||
| 442 | 10 | itmp1 = 1 | |
| 443 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 6 taken 30 times.
✓ Branch 7 taken 10 times.
|
40 | do j = 1, len_trim(attributes(i)%val) |
| 444 |
8/14✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 30 times.
✓ Branch 11 taken 30 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 30 times.
✓ Branch 16 taken 10 times.
✓ Branch 17 taken 20 times.
|
40 | if(attributes(i)%val(j:j) .eq. ' ') itmp1 = itmp1 + 1 |
| 445 | end do | ||
| 446 |
7/14✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 10 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 10 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 10 times.
|
10 | allocate(ivar_list(itmp1)) |
| 447 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
|
10 | read(attributes(i)%val, *) ivar_list |
| 448 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | attr_json = trim(attr_json) // ', "ints": [' |
| 449 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
|
30 | do j = 1, itmp1 |
| 450 |
4/6✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
20 | if(j .gt. 1) attr_json = trim(attr_json) // ', ' |
| 451 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
|
20 | write(buffer, '("""",I0,"""")') ivar_list(j) |
| 452 |
3/6✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
|
30 | attr_json = trim(attr_json) // trim(adjustl(buffer)) |
| 453 | end do | ||
| 454 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | attr_json = trim(attr_json) // '], "type": "INTS"}' |
| 455 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | deallocate(ivar_list) |
| 456 | case('float') | ||
| 457 | attr_json = trim(attr_json) // ', "f": ' // & | ||
| 458 | ✗ | trim(adjustl(attributes(i)%val)) // ', "type": "FLOAT"}' | |
| 459 | case('string') | ||
| 460 | ! Base64 encode the string value | ||
| 461 | call encode_string_base64( & | ||
| 462 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
|
4 | trim(adjustl(attributes(i)%val)), buffer) |
| 463 | attr_json = trim(attr_json) // ', "s": "' // & | ||
| 464 |
3/6✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
|
4 | trim(buffer) // '", "type": "STRING"}' |
| 465 | case default | ||
| 466 |
3/9✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
29 | attr_json = trim(attr_json) // '}' |
| 467 | end select | ||
| 468 | end do | ||
| 469 |
2/4✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
8 | attr_json = trim(attr_json) // ']' |
| 470 | |||
| 471 |
10/16✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 29 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 29 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 29 times.
✗ Branch 15 not taken.
|
76 | end subroutine build_attributes_json |
| 472 | !############################################################################### | ||
| 473 | |||
| 474 | |||
| 475 | ! ============================================================================= | ||
| 476 | ! JSON serialisation utilities | ||
| 477 | ! ============================================================================= | ||
| 478 | |||
| 479 | !############################################################################### | ||
| 480 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | subroutine write_json_nodes(unit, nodes, num_nodes) |
| 481 | !! Write nodes array to JSON | ||
| 482 | implicit none | ||
| 483 | |||
| 484 | ! Arguments | ||
| 485 | integer, intent(in) :: unit | ||
| 486 | !! Output unit receiving the JSON text | ||
| 487 | type(onnx_node_type), intent(in), dimension(:) :: nodes | ||
| 488 | !! Node collection to serialise | ||
| 489 | integer, intent(in) :: num_nodes | ||
| 490 | !! Number of populated nodes in the collection | ||
| 491 | |||
| 492 | ! Local variables | ||
| 493 | integer :: i, j | ||
| 494 | !! Node and tensor index counters | ||
| 495 | |||
| 496 | 11 | write(unit, '(A)') ' "node": [' | |
| 497 |
2/2✓ Branch 0 taken 245 times.
✓ Branch 1 taken 11 times.
|
256 | do i = 1, num_nodes |
| 498 | 245 | write(unit, '(A)') ' {' | |
| 499 | ! Write inputs | ||
| 500 |
6/10✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 245 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 245 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 245 times.
✓ Branch 12 taken 201 times.
✓ Branch 13 taken 44 times.
|
245 | if(allocated(nodes(i)%inputs) .and. size(nodes(i)%inputs) .gt. 0)then |
| 501 | 201 | write(unit, '(A)', advance='no') ' "input": [' | |
| 502 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 201 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 201 times.
✓ Branch 6 taken 351 times.
✓ Branch 7 taken 201 times.
|
552 | do j = 1, size(nodes(i)%inputs) |
| 503 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 201 times.
|
351 | if(j .gt. 1) write(unit, '(A)', advance='no') ', ' |
| 504 | 351 | write(unit, '(A,A,A)', advance='no') '"', & | |
| 505 |
5/10✗ Branch 1 not taken.
✓ Branch 2 taken 351 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 351 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 351 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 351 times.
✓ Branch 16 taken 351 times.
✗ Branch 17 not taken.
|
903 | trim(adjustl(nodes(i)%inputs(j))), '"' |
| 506 | end do | ||
| 507 | 201 | write(unit, '(A)') '],' | |
| 508 | end if | ||
| 509 | ! Write outputs | ||
| 510 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 245 times.
✓ Branch 6 taken 245 times.
✗ Branch 7 not taken.
|
245 | if(allocated(nodes(i)%outputs))then |
| 511 | 245 | write(unit, '(A)', advance='no') ' "output": [' | |
| 512 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 245 times.
✓ Branch 6 taken 245 times.
✓ Branch 7 taken 245 times.
|
490 | do j = 1, size(nodes(i)%outputs) |
| 513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
|
245 | if(j .gt. 1) write(unit, '(A)', advance='no') ', ' |
| 514 | 245 | write(unit, '(A,A,A)', advance='no') '"', & | |
| 515 |
5/10✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 245 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 245 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 245 times.
✓ Branch 16 taken 245 times.
✗ Branch 17 not taken.
|
735 | trim(adjustl(nodes(i)%outputs(j))), '"' |
| 516 | end do | ||
| 517 | 245 | write(unit, '(A)') '],' | |
| 518 | end if | ||
| 519 | ! Name | ||
| 520 | 245 | write(unit, '(A,A,A)', advance='no') ' "name": "', & | |
| 521 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 245 times.
✓ Branch 10 taken 245 times.
✗ Branch 11 not taken.
|
490 | trim(adjustl(nodes(i)%name)), '"' |
| 522 | ! OpType | ||
| 523 | 245 | write(unit, '(A)') ',' | |
| 524 | 245 | write(unit, '(A,A,A)', advance='no') ' "opType": "', & | |
| 525 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 245 times.
✓ Branch 10 taken 245 times.
✗ Branch 11 not taken.
|
490 | trim(adjustl(nodes(i)%op_type)), '"' |
| 526 | ! Attributes | ||
| 527 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 245 times.
✓ Branch 6 taken 128 times.
✓ Branch 7 taken 117 times.
|
245 | if(len_trim(nodes(i)%attributes_json) .gt. 0)then |
| 528 | 128 | write(unit, '(A)') ',' | |
| 529 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 128 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 128 times.
✓ Branch 9 taken 128 times.
✗ Branch 10 not taken.
|
128 | write(unit, '(A)') trim(nodes(i)%attributes_json) |
| 530 | else | ||
| 531 | 117 | write(unit, '(A)') '' | |
| 532 | end if | ||
| 533 |
2/2✓ Branch 0 taken 234 times.
✓ Branch 1 taken 11 times.
|
256 | if(i .lt. num_nodes)then |
| 534 | 234 | write(unit, '(A)') ' },' | |
| 535 | else | ||
| 536 | 11 | write(unit, '(A)') ' }' | |
| 537 | end if | ||
| 538 | end do | ||
| 539 | 11 | write(unit, '(A)') ' ]' | |
| 540 | |||
| 541 | 11 | end subroutine write_json_nodes | |
| 542 | !############################################################################### | ||
| 543 | |||
| 544 | |||
| 545 | !############################################################################### | ||
| 546 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | subroutine write_json_initialisers(unit, inits, num_inits) |
| 547 | !! Write initialisers array to JSON with base64-encoded rawData | ||
| 548 | implicit none | ||
| 549 | |||
| 550 | ! Arguments | ||
| 551 | integer, intent(in) :: unit | ||
| 552 | !! Output unit receiving the JSON text | ||
| 553 | type(onnx_initialiser_type), intent(in), dimension(:) :: inits | ||
| 554 | !! Initialiser collection to serialise | ||
| 555 | integer, intent(in) :: num_inits | ||
| 556 | !! Number of populated initialisers in the collection | ||
| 557 | |||
| 558 | ! Local variables | ||
| 559 | integer :: i, j, n | ||
| 560 | !! Initialiser index, dimension index, and raw element count | ||
| 561 | 11 | character(:), allocatable :: raw_b64 | |
| 562 | !! Base64-encoded raw tensor payload | ||
| 563 | |||
| 564 | 11 | write(unit, '(A)') ' "initializer": [' | |
| 565 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 11 times.
|
57 | do i = 1, num_inits |
| 566 | 46 | write(unit, '(A)') ' {' | |
| 567 | ! Dims | ||
| 568 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✓ Branch 6 taken 46 times.
✗ Branch 7 not taken.
|
46 | if(allocated(inits(i)%dims))then |
| 569 | 46 | write(unit, '(A)', advance='no') ' "dims": [' | |
| 570 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✓ Branch 6 taken 87 times.
✓ Branch 7 taken 46 times.
|
133 | do j = 1, size(inits(i)%dims) |
| 571 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 46 times.
|
87 | if(j .gt. 1) write(unit, '(A)', advance='no') ', ' |
| 572 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 87 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 87 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 87 times.
|
133 | write(unit, '("""",I0,"""")' , advance='no') inits(i)%dims(j) |
| 573 | end do | ||
| 574 | 46 | write(unit, '(A)') '],' | |
| 575 | end if | ||
| 576 | ! Data type | ||
| 577 |
2/4✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 46 times.
|
46 | write(unit, '(A,I0,A)') ' "dataType": ', inits(i)%data_type, ',' |
| 578 | ! Name | ||
| 579 | 46 | write(unit, '(A,A,A)') ' "name": "', & | |
| 580 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 46 times.
✓ Branch 10 taken 46 times.
✗ Branch 11 not taken.
|
92 | trim(adjustl(inits(i)%name)), '",' |
| 581 | ! Raw data (base64 encoded) | ||
| 582 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✓ Branch 6 taken 46 times.
✗ Branch 7 not taken.
|
46 | if(allocated(inits(i)%data))then |
| 583 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
|
46 | n = size(inits(i)%data) |
| 584 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✓ Branch 6 taken 35 times.
✓ Branch 7 taken 11 times.
|
46 | call encode_float32_base64_alloc(inits(i)%data, n, raw_b64) |
| 585 | 46 | write(unit, '(A,A,A)') ' "rawData": "', raw_b64, '"' | |
| 586 | ✗ | else if(allocated(inits(i)%int_data))then | |
| 587 | ✗ | n = size(inits(i)%int_data) | |
| 588 | ✗ | call encode_int64_base64_alloc(inits(i)%int_data, n, raw_b64) | |
| 589 | ✗ | write(unit, '(A,A,A)') ' "rawData": "', raw_b64, '"' | |
| 590 | else | ||
| 591 | ✗ | write(unit, '(A)') ' "rawData": ""' | |
| 592 | end if | ||
| 593 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 11 times.
|
57 | if(i .lt. num_inits)then |
| 594 | 35 | write(unit, '(A)') ' },' | |
| 595 | else | ||
| 596 | 11 | write(unit, '(A)') ' }' | |
| 597 | end if | ||
| 598 | end do | ||
| 599 | 11 | write(unit, '(A)') ' ]' | |
| 600 | |||
| 601 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | end subroutine write_json_initialisers |
| 602 | !############################################################################### | ||
| 603 | |||
| 604 | |||
| 605 | !############################################################################### | ||
| 606 | 22 | subroutine write_json_tensors(unit, section_name, tensors, num_tensors) | |
| 607 | !! Write input/output tensor specifications to JSON | ||
| 608 | implicit none | ||
| 609 | |||
| 610 | ! Arguments | ||
| 611 | integer, intent(in) :: unit | ||
| 612 | !! Output unit receiving the JSON text | ||
| 613 | character(*), intent(in) :: section_name | ||
| 614 | !! JSON section name, e.g. input or output | ||
| 615 | type(onnx_tensor_type), intent(in), dimension(:) :: tensors | ||
| 616 | !! Tensor collection to serialise | ||
| 617 | integer, intent(in) :: num_tensors | ||
| 618 | !! Number of populated tensors in the collection | ||
| 619 | |||
| 620 | ! Local variables | ||
| 621 | integer :: i, j | ||
| 622 | !! Tensor and dimension index counters | ||
| 623 | |||
| 624 |
1/2✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
|
22 | write(unit, '(A,A,A)') ' "', trim(section_name), '": [' |
| 625 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 22 times.
|
49 | do i = 1, num_tensors |
| 626 | 27 | write(unit, '(A)') ' {' | |
| 627 | 27 | write(unit, '(A,A,A)') ' "name": "', & | |
| 628 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 27 times.
✓ Branch 10 taken 27 times.
✗ Branch 11 not taken.
|
54 | trim(adjustl(tensors(i)%name)), '",' |
| 629 | 27 | write(unit, '(A)') ' "type": {' | |
| 630 | 27 | write(unit, '(A)') ' "tensorType": {' | |
| 631 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
|
54 | write(unit, '(A,I0,A)') ' "elemType": ', & |
| 632 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
|
81 | tensors(i)%elem_type, ',' |
| 633 | 27 | write(unit, '(A)') ' "shape": {' | |
| 634 | 27 | write(unit, '(A)') ' "dim": [' | |
| 635 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✓ Branch 6 taken 27 times.
✗ Branch 7 not taken.
|
27 | if(allocated(tensors(i)%dims))then |
| 636 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✓ Branch 6 taken 57 times.
✓ Branch 7 taken 27 times.
|
84 | do j = 1, size(tensors(i)%dims) |
| 637 | 57 | write(unit, '(A)') ' {' | |
| 638 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57 times.
✓ Branch 6 taken 51 times.
✓ Branch 7 taken 6 times.
|
57 | if(allocated(tensors(i)%dim_params))then |
| 639 |
6/10✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 51 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 51 times.
✓ Branch 12 taken 24 times.
✓ Branch 13 taken 27 times.
|
51 | if(len_trim(tensors(i)%dim_params(j)) .gt. 0)then |
| 640 | 24 | write(unit, '(A,A,A)') ' "dimParam": "', & | |
| 641 |
5/10✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 24 times.
✓ Branch 16 taken 24 times.
✗ Branch 17 not taken.
|
48 | trim(adjustl(tensors(i)%dim_params(j))), '"' |
| 642 | else | ||
| 643 | write(unit, '(A,"""",I0,"""")') & | ||
| 644 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
|
54 | ' "dimValue": ', & |
| 645 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 27 times.
|
81 | tensors(i)%dims(j) |
| 646 | end if | ||
| 647 | else | ||
| 648 | write(unit, '(A,"""",I0,"""")') & | ||
| 649 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
12 | ' "dimValue": ', & |
| 650 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
|
18 | tensors(i)%dims(j) |
| 651 | end if | ||
| 652 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57 times.
✓ Branch 6 taken 30 times.
✓ Branch 7 taken 27 times.
|
84 | if(j .lt. size(tensors(i)%dims))then |
| 653 | 30 | write(unit, '(A)') ' },' | |
| 654 | else | ||
| 655 | 27 | write(unit, '(A)') ' }' | |
| 656 | end if | ||
| 657 | end do | ||
| 658 | end if | ||
| 659 | 27 | write(unit, '(A)') ' ]' | |
| 660 | 27 | write(unit, '(A)') ' }' | |
| 661 | 27 | write(unit, '(A)') ' }' | |
| 662 | 27 | write(unit, '(A)') ' }' | |
| 663 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 22 times.
|
49 | if(i .lt. num_tensors)then |
| 664 | 5 | write(unit, '(A)') ' },' | |
| 665 | else | ||
| 666 | 22 | write(unit, '(A)') ' }' | |
| 667 | end if | ||
| 668 | end do | ||
| 669 | 22 | write(unit, '(A,A,A)') ' ]' | |
| 670 | |||
| 671 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | end subroutine write_json_tensors |
| 672 | !############################################################################### | ||
| 673 | |||
| 674 | |||
| 675 | ! ============================================================================= | ||
| 676 | ! Data layout utilities | ||
| 677 | ! ============================================================================= | ||
| 678 | |||
| 679 | !############################################################################### | ||
| 680 | 30 | subroutine col_to_row_major_2d(data_in, data_out, m, n) | |
| 681 | !! Convert flat column-major [m,n] to flat row-major [m,n] | ||
| 682 | !! Fortran stores arrays column-major; ONNX rawData expects row-major. | ||
| 683 | implicit none | ||
| 684 | integer, intent(in) :: m, n | ||
| 685 | real(real32), intent(in) :: data_in(m * n) | ||
| 686 | real(real32), intent(out) :: data_out(m * n) | ||
| 687 | integer :: i, j | ||
| 688 |
2/2✓ Branch 0 taken 184 times.
✓ Branch 1 taken 30 times.
|
214 | do i = 1, m |
| 689 |
2/2✓ Branch 0 taken 2807 times.
✓ Branch 1 taken 184 times.
|
3021 | do j = 1, n |
| 690 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 2807 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2807 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2807 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2807 times.
|
2991 | data_out((i-1)*n + j) = data_in((j-1)*m + i) |
| 691 | end do | ||
| 692 | end do | ||
| 693 | 30 | end subroutine col_to_row_major_2d | |
| 694 | !############################################################################### | ||
| 695 | |||
| 696 | |||
| 697 | ! ============================================================================= | ||
| 698 | ! Base64 encoding utilities | ||
| 699 | ! ============================================================================= | ||
| 700 | |||
| 701 | !############################################################################### | ||
| 702 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | subroutine encode_float32_base64(values, n, output) |
| 703 | !! Encode float32 array as base64 string (fixed-length output) | ||
| 704 | use iso_fortran_env, only: int8 | ||
| 705 | implicit none | ||
| 706 | real(real32), intent(in) :: values(:) | ||
| 707 | integer, intent(in) :: n | ||
| 708 | character(256), intent(out) :: output | ||
| 709 | |||
| 710 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | character(:), allocatable :: result |
| 711 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
|
12 | call encode_float32_base64_alloc(values, n, result) |
| 712 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | output = result |
| 713 | |||
| 714 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | end subroutine encode_float32_base64 |
| 715 | !############################################################################### | ||
| 716 | |||
| 717 | |||
| 718 | !############################################################################### | ||
| 719 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | subroutine encode_float32_base64_alloc(values, n, output) |
| 720 | !! Encode float32 array as base64 string (allocatable output) | ||
| 721 | use iso_fortran_env, only: int8, int32 | ||
| 722 | implicit none | ||
| 723 | real(real32), intent(in) :: values(:) | ||
| 724 | integer, intent(in) :: n | ||
| 725 | character(:), allocatable, intent(out) :: output | ||
| 726 | |||
| 727 | 58 | integer(int8), allocatable :: bytes(:) | |
| 728 | integer(int32) :: ival | ||
| 729 | integer :: i, j, nbytes | ||
| 730 | |||
| 731 | 58 | nbytes = n * 4 | |
| 732 |
6/12✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 58 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 58 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 58 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 58 times.
|
58 | allocate(bytes(nbytes)) |
| 733 | |||
| 734 |
2/2✓ Branch 0 taken 3421 times.
✓ Branch 1 taken 58 times.
|
3479 | do i = 1, n |
| 735 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3421 times.
|
3421 | ival = transfer(values(i), ival) |
| 736 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3421 times.
|
3421 | bytes((i-1)*4 + 1) = int(iand(ival, 255), int8) |
| 737 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3421 times.
|
3421 | bytes((i-1)*4 + 2) = int(iand(ishft(ival, -8), 255), int8) |
| 738 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3421 times.
|
3421 | bytes((i-1)*4 + 3) = int(iand(ishft(ival, -16), 255), int8) |
| 739 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3421 times.
|
3479 | bytes((i-1)*4 + 4) = int(iand(ishft(ival, -24), 255), int8) |
| 740 | end do | ||
| 741 | |||
| 742 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | call base64_encode_bytes(bytes, nbytes, output) |
| 743 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | deallocate(bytes) |
| 744 | |||
| 745 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | end subroutine encode_float32_base64_alloc |
| 746 | !############################################################################### | ||
| 747 | |||
| 748 | |||
| 749 | !############################################################################### | ||
| 750 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | subroutine encode_int64_base64(values, output) |
| 751 | !! Encode integer array as base64 int64 string (fixed-length output) | ||
| 752 | use iso_fortran_env, only: int8, int64 | ||
| 753 | implicit none | ||
| 754 | integer, intent(in) :: values(:) | ||
| 755 | character(256), intent(out) :: output | ||
| 756 | |||
| 757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | integer(int8), allocatable :: bytes(:) |
| 758 | integer(int64) :: ival64 | ||
| 759 | integer :: i, j, n, nbytes | ||
| 760 | |||
| 761 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
|
37 | n = size(values) |
| 762 | 37 | nbytes = n * 8 | |
| 763 |
6/12✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 37 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 37 times.
|
37 | allocate(bytes(nbytes)) |
| 764 | |||
| 765 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 37 times.
|
74 | do i = 1, n |
| 766 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
|
37 | ival64 = int(values(i), int64) |
| 767 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 37 times.
|
370 | do j = 0, 7 |
| 768 | ✗ | bytes((i-1)*8 + j + 1) = & | |
| 769 |
5/8✗ Branch 0 not taken.
✓ Branch 1 taken 296 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 296 times.
✓ Branch 4 taken 296 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 37 times.
✓ Branch 7 taken 259 times.
|
333 | int(iand(ishft(ival64, -j*8), int(255, int64)), int8) |
| 770 | end do | ||
| 771 | end do | ||
| 772 | |||
| 773 | 37 | call base64_encode_bytes_fixed(bytes, nbytes, output) | |
| 774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | deallocate(bytes) |
| 775 | |||
| 776 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | end subroutine encode_int64_base64 |
| 777 | !############################################################################### | ||
| 778 | |||
| 779 | |||
| 780 | !############################################################################### | ||
| 781 | ✗ | subroutine encode_int64_base64_alloc(values, n, output) | |
| 782 | !! Encode integer array as base64 int64 string (allocatable output) | ||
| 783 | use iso_fortran_env, only: int8, int64 | ||
| 784 | implicit none | ||
| 785 | integer, intent(in) :: values(:) | ||
| 786 | integer, intent(in) :: n | ||
| 787 | character(:), allocatable, intent(out) :: output | ||
| 788 | |||
| 789 | ✗ | integer(int8), allocatable :: bytes(:) | |
| 790 | integer(int64) :: ival64 | ||
| 791 | integer :: i, j, nbytes | ||
| 792 | |||
| 793 | ✗ | nbytes = n * 8 | |
| 794 | ✗ | allocate(bytes(nbytes)) | |
| 795 | |||
| 796 | ✗ | do i = 1, n | |
| 797 | ✗ | ival64 = int(values(i), int64) | |
| 798 | ✗ | do j = 0, 7 | |
| 799 | ✗ | bytes((i-1)*8 + j + 1) = & | |
| 800 | ✗ | int(iand(ishft(ival64, -j*8), int(255, int64)), int8) | |
| 801 | end do | ||
| 802 | end do | ||
| 803 | |||
| 804 | ✗ | call base64_encode_bytes(bytes, nbytes, output) | |
| 805 | ✗ | deallocate(bytes) | |
| 806 | |||
| 807 | ✗ | end subroutine encode_int64_base64_alloc | |
| 808 | !############################################################################### | ||
| 809 | |||
| 810 | |||
| 811 | !############################################################################### | ||
| 812 | ✗ | subroutine encode_string_base64(str, output) | |
| 813 | !! Encode a string as base64 | ||
| 814 | use iso_fortran_env, only: int8 | ||
| 815 | implicit none | ||
| 816 | character(*), intent(in) :: str | ||
| 817 | character(256), intent(out) :: output | ||
| 818 | |||
| 819 | 4 | integer(int8), allocatable :: bytes(:) | |
| 820 | integer :: i, n | ||
| 821 | |||
| 822 | 4 | n = len_trim(str) | |
| 823 |
6/12✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
|
4 | allocate(bytes(n)) |
| 824 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 4 times.
|
21 | do i = 1, n |
| 825 |
6/12✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 17 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 17 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 17 times.
|
21 | bytes(i) = int(ichar(str(i:i)), int8) |
| 826 | end do | ||
| 827 | |||
| 828 | 4 | call base64_encode_bytes_fixed(bytes, n, output) | |
| 829 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | deallocate(bytes) |
| 830 | |||
| 831 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
8 | end subroutine encode_string_base64 |
| 832 | !############################################################################### | ||
| 833 | |||
| 834 | |||
| 835 | !############################################################################### | ||
| 836 |
1/2✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
|
99 | subroutine base64_encode_bytes(bytes, nbytes, output) |
| 837 | !! Core base64 encoder (allocatable output) | ||
| 838 | use iso_fortran_env, only: int8 | ||
| 839 | implicit none | ||
| 840 | integer(int8), intent(in) :: bytes(:) | ||
| 841 | integer, intent(in) :: nbytes | ||
| 842 | character(:), allocatable, intent(out) :: output | ||
| 843 | |||
| 844 | character(64), parameter :: b64 = & | ||
| 845 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | ||
| 846 | integer :: i, j, ngroups, out_len | ||
| 847 | integer :: b0, b1, b2, idx | ||
| 848 | |||
| 849 | 99 | ngroups = (nbytes + 2) / 3 | |
| 850 | 99 | out_len = ngroups * 4 | |
| 851 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 99 times.
|
99 | allocate(character(out_len) :: output) |
| 852 | |||
| 853 | 99 | j = 1 | |
| 854 |
1/2✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
|
99 | do i = 1, nbytes, 3 |
| 855 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4694 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4694 times.
|
4694 | b0 = iand(int(bytes(i)), 255) |
| 856 |
2/2✓ Branch 0 taken 4673 times.
✓ Branch 1 taken 21 times.
|
4694 | if(i + 1 .le. nbytes)then |
| 857 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4673 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4673 times.
|
4673 | b1 = iand(int(bytes(i+1)), 255) |
| 858 | else | ||
| 859 | 21 | b1 = 0 | |
| 860 | end if | ||
| 861 |
2/2✓ Branch 0 taken 4630 times.
✓ Branch 1 taken 64 times.
|
4694 | if(i + 2 .le. nbytes)then |
| 862 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4630 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4630 times.
|
4630 | b2 = iand(int(bytes(i+2)), 255) |
| 863 | else | ||
| 864 | 64 | b2 = 0 | |
| 865 | end if | ||
| 866 | |||
| 867 | 4694 | idx = ishft(b0, -2) + 1 | |
| 868 |
8/16✓ Branch 0 taken 4694 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4694 times.
✓ Branch 5 taken 4694 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4694 times.
✓ Branch 10 taken 4694 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 4694 times.
✓ Branch 15 taken 4694 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 4694 times.
|
4694 | output(j:j) = b64(idx:idx) |
| 869 | |||
| 870 | 4694 | idx = ior(ishft(iand(b0, 3), 4), ishft(b1, -4)) + 1 | |
| 871 |
8/16✓ Branch 0 taken 4694 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4694 times.
✓ Branch 5 taken 4694 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4694 times.
✓ Branch 10 taken 4694 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 4694 times.
✓ Branch 15 taken 4694 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 4694 times.
|
4694 | output(j+1:j+1) = b64(idx:idx) |
| 872 | |||
| 873 |
2/2✓ Branch 0 taken 4673 times.
✓ Branch 1 taken 21 times.
|
4694 | if(i + 1 .le. nbytes)then |
| 874 | 4673 | idx = ior(ishft(iand(b1, 15), 2), ishft(b2, -6)) + 1 | |
| 875 |
8/16✓ Branch 0 taken 4673 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4673 times.
✓ Branch 5 taken 4673 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4673 times.
✓ Branch 10 taken 4673 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 4673 times.
✓ Branch 15 taken 4673 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 4673 times.
|
4673 | output(j+2:j+2) = b64(idx:idx) |
| 876 | else | ||
| 877 |
4/8✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✓ Branch 5 taken 21 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 21 times.
|
21 | output(j+2:j+2) = '=' |
| 878 | end if | ||
| 879 | |||
| 880 |
2/2✓ Branch 0 taken 4630 times.
✓ Branch 1 taken 64 times.
|
4694 | if(i + 2 .le. nbytes)then |
| 881 | 4630 | idx = iand(b2, 63) + 1 | |
| 882 |
8/16✓ Branch 0 taken 4630 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4630 times.
✓ Branch 5 taken 4630 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4630 times.
✓ Branch 10 taken 4630 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 4630 times.
✓ Branch 15 taken 4630 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 4630 times.
|
4630 | output(j+3:j+3) = b64(idx:idx) |
| 883 | else | ||
| 884 |
4/8✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 64 times.
|
64 | output(j+3:j+3) = '=' |
| 885 | end if | ||
| 886 | |||
| 887 |
2/2✓ Branch 0 taken 99 times.
✓ Branch 1 taken 4595 times.
|
4694 | j = j + 4 |
| 888 | end do | ||
| 889 | |||
| 890 | 99 | end subroutine base64_encode_bytes | |
| 891 | !############################################################################### | ||
| 892 | |||
| 893 | |||
| 894 | !############################################################################### | ||
| 895 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | subroutine base64_encode_bytes_fixed(bytes, nbytes, output) |
| 896 | !! Core base64 encoder (fixed-length output) | ||
| 897 | use iso_fortran_env, only: int8 | ||
| 898 | implicit none | ||
| 899 | integer(int8), intent(in) :: bytes(:) | ||
| 900 | integer, intent(in) :: nbytes | ||
| 901 | character(256), intent(out) :: output | ||
| 902 | |||
| 903 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | character(:), allocatable :: tmp |
| 904 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 41 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 41 times.
|
41 | call base64_encode_bytes(bytes, nbytes, tmp) |
| 905 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | output = tmp |
| 906 | |||
| 907 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | end subroutine base64_encode_bytes_fixed |
| 908 | !############################################################################### | ||
| 909 | |||
| 910 | |||
| 911 | ! ============================================================================= | ||
| 912 | ! Base64 decoding utilities | ||
| 913 | ! ============================================================================= | ||
| 914 | |||
| 915 | !############################################################################### | ||
| 916 | 47 | subroutine base64_decode_bytes(input, bytes, nbytes) | |
| 917 | !! Core base64 decoder | ||
| 918 | use iso_fortran_env, only: int8 | ||
| 919 | implicit none | ||
| 920 | character(*), intent(in) :: input | ||
| 921 | integer(int8), allocatable, intent(out) :: bytes(:) | ||
| 922 | integer, intent(out) :: nbytes | ||
| 923 | |||
| 924 | character(64), parameter :: b64 = & | ||
| 925 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | ||
| 926 | integer :: i, j, in_len, ngroups, pad | ||
| 927 | integer :: v0, v1, v2, v3 | ||
| 928 | |||
| 929 | 47 | in_len = len_trim(input) | |
| 930 | 47 | if(in_len .eq. 0)then | |
| 931 | ✗ | allocate(bytes(0)) | |
| 932 | ✗ | nbytes = 0 | |
| 933 | ✗ | return | |
| 934 | end if | ||
| 935 | |||
| 936 | ! Count padding | ||
| 937 | 47 | pad = 0 | |
| 938 |
6/10✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 47 times.
✓ Branch 10 taken 11 times.
✓ Branch 11 taken 36 times.
|
47 | if(input(in_len:in_len) .eq. '=') pad = pad + 1 |
| 939 |
6/10✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 47 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 42 times.
|
47 | if(in_len .ge. 2 .and. input(in_len-1:in_len-1) .eq. '=') pad = pad + 1 |
| 940 | |||
| 941 | 47 | ngroups = in_len / 4 | |
| 942 | 47 | nbytes = ngroups * 3 - pad | |
| 943 |
6/12✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 47 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 47 times.
|
47 | allocate(bytes(nbytes)) |
| 944 | |||
| 945 | 47 | j = 1 | |
| 946 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | do i = 1, in_len, 4 |
| 947 |
4/8✓ Branch 0 taken 4288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4288 times.
✓ Branch 5 taken 4288 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4288 times.
|
4288 | v0 = index(b64, input(i:i)) - 1 |
| 948 |
4/8✓ Branch 0 taken 4288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4288 times.
✓ Branch 5 taken 4288 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4288 times.
|
4288 | v1 = index(b64, input(i+1:i+1)) - 1 |
| 949 |
6/10✓ Branch 0 taken 4288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4288 times.
✓ Branch 5 taken 4288 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4288 times.
✓ Branch 10 taken 4283 times.
✓ Branch 11 taken 5 times.
|
4288 | if(input(i+2:i+2) .ne. '=')then |
| 950 |
4/8✓ Branch 0 taken 4283 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4283 times.
✓ Branch 5 taken 4283 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4283 times.
|
4283 | v2 = index(b64, input(i+2:i+2)) - 1 |
| 951 | else | ||
| 952 | 5 | v2 = 0 | |
| 953 | end if | ||
| 954 |
6/10✓ Branch 0 taken 4288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4288 times.
✓ Branch 5 taken 4288 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4288 times.
✓ Branch 10 taken 4277 times.
✓ Branch 11 taken 11 times.
|
4288 | if(input(i+3:i+3) .ne. '=')then |
| 955 |
4/8✓ Branch 0 taken 4277 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4277 times.
✓ Branch 5 taken 4277 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4277 times.
|
4277 | v3 = index(b64, input(i+3:i+3)) - 1 |
| 956 | else | ||
| 957 | 11 | v3 = 0 | |
| 958 | end if | ||
| 959 | |||
| 960 |
1/2✓ Branch 0 taken 4288 times.
✗ Branch 1 not taken.
|
4288 | if(j .le. nbytes) & |
| 961 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4288 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4288 times.
|
4288 | bytes(j) = int(ior(ishft(v0, 2), ishft(v1, -4)), int8) |
| 962 |
2/2✓ Branch 0 taken 4283 times.
✓ Branch 1 taken 5 times.
|
4288 | if(j + 1 .le. nbytes) & |
| 963 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4283 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4283 times.
|
4283 | bytes(j+1) = int(ior(ishft(iand(v1, 15), 4), ishft(v2, -2)), int8) |
| 964 |
2/2✓ Branch 0 taken 4277 times.
✓ Branch 1 taken 11 times.
|
4288 | if(j + 2 .le. nbytes) & |
| 965 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4277 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4277 times.
|
4277 | bytes(j+2) = int(ior(ishft(iand(v2, 3), 6), v3), int8) |
| 966 |
2/2✓ Branch 0 taken 4241 times.
✓ Branch 1 taken 47 times.
|
4288 | j = j + 3 |
| 967 | end do | ||
| 968 | |||
| 969 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
|
47 | end subroutine base64_decode_bytes |
| 970 | !############################################################################### | ||
| 971 | |||
| 972 | |||
| 973 | !############################################################################### | ||
| 974 | 47 | subroutine decode_base64_to_float32(input, values, n) | |
| 975 | !! Decode base64 string to float32 array | ||
| 976 | use iso_fortran_env, only: int8, int32 | ||
| 977 | implicit none | ||
| 978 | character(*), intent(in) :: input | ||
| 979 | real(real32), allocatable, intent(out) :: values(:) | ||
| 980 | integer, intent(out) :: n | ||
| 981 | |||
| 982 | 47 | integer(int8), allocatable :: bytes(:) | |
| 983 | integer :: nbytes, i | ||
| 984 | integer(int32) :: ival | ||
| 985 | |||
| 986 | 47 | call base64_decode_bytes(input, bytes, nbytes) | |
| 987 | 47 | n = nbytes / 4 | |
| 988 |
7/14✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 47 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 47 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 47 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 47 times.
|
47 | allocate(values(n)) |
| 989 | |||
| 990 |
2/2✓ Branch 0 taken 3212 times.
✓ Branch 1 taken 47 times.
|
3259 | do i = 1, n |
| 991 | ival = ior(ior(ior( & | ||
| 992 | ✗ | iand(int(bytes((i-1)*4 + 1), int32), 255), & | |
| 993 | ✗ | ishft(iand(int(bytes((i-1)*4 + 2), int32), 255), 8)), & | |
| 994 | ✗ | ishft(iand(int(bytes((i-1)*4 + 3), int32), 255), 16)), & | |
| 995 |
8/16✗ Branch 0 not taken.
✓ Branch 1 taken 3212 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3212 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3212 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3212 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3212 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3212 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3212 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3212 times.
|
3212 | ishft(iand(int(bytes((i-1)*4 + 4), int32), 255), 24)) |
| 996 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 3212 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3212 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3212 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3212 times.
|
3259 | values(i) = transfer(ival, values(i)) |
| 997 | end do | ||
| 998 | |||
| 999 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
|
47 | deallocate(bytes) |
| 1000 | |||
| 1001 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
|
94 | end subroutine decode_base64_to_float32 |
| 1002 | !############################################################################### | ||
| 1003 | |||
| 1004 | |||
| 1005 | !############################################################################### | ||
| 1006 | ✗ | subroutine decode_base64_to_int64(input, values, n) | |
| 1007 | !! Decode base64 string to integer array (from 8-byte int64 encoding) | ||
| 1008 | use iso_fortran_env, only: int8, int64 | ||
| 1009 | implicit none | ||
| 1010 | character(*), intent(in) :: input | ||
| 1011 | integer, allocatable, intent(out) :: values(:) | ||
| 1012 | integer, intent(out) :: n | ||
| 1013 | |||
| 1014 | ✗ | integer(int8), allocatable :: bytes(:) | |
| 1015 | integer :: nbytes, i, j | ||
| 1016 | integer(int64) :: ival64 | ||
| 1017 | |||
| 1018 | ✗ | call base64_decode_bytes(input, bytes, nbytes) | |
| 1019 | ✗ | n = nbytes / 8 | |
| 1020 | ✗ | allocate(values(n)) | |
| 1021 | |||
| 1022 | ✗ | do i = 1, n | |
| 1023 | ✗ | ival64 = 0 | |
| 1024 | ✗ | do j = 0, 7 | |
| 1025 | ival64 = ior(ival64, & | ||
| 1026 | ✗ | ishft(iand(int(bytes((i-1)*8 + j + 1), int64), & | |
| 1027 | ✗ | int(255, int64)), j*8)) | |
| 1028 | end do | ||
| 1029 | ✗ | values(i) = int(ival64) | |
| 1030 | end do | ||
| 1031 | |||
| 1032 | ✗ | deallocate(bytes) | |
| 1033 | |||
| 1034 | ✗ | end subroutine decode_base64_to_int64 | |
| 1035 | !############################################################################### | ||
| 1036 | |||
| 1037 | |||
| 1038 | ! ============================================================================= | ||
| 1039 | ! Reverse data layout utility | ||
| 1040 | ! ============================================================================= | ||
| 1041 | |||
| 1042 | !############################################################################### | ||
| 1043 | 37 | subroutine row_to_col_major_2d(data_in, data_out, m, n) | |
| 1044 | !! Convert flat row-major [m,n] to flat column-major [m,n] | ||
| 1045 | !! Inverse of col_to_row_major_2d. | ||
| 1046 | implicit none | ||
| 1047 | integer, intent(in) :: m, n | ||
| 1048 | real(real32), intent(in) :: data_in(m * n) | ||
| 1049 | real(real32), intent(out) :: data_out(m * n) | ||
| 1050 | integer :: i, j | ||
| 1051 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 37 times.
|
222 | do i = 1, m |
| 1052 |
2/2✓ Branch 0 taken 2413 times.
✓ Branch 1 taken 185 times.
|
2635 | do j = 1, n |
| 1053 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 2413 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2413 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2413 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2413 times.
|
2598 | data_out((j-1)*m + i) = data_in((i-1)*n + j) |
| 1054 | end do | ||
| 1055 | end do | ||
| 1056 | 37 | end subroutine row_to_col_major_2d | |
| 1057 | !############################################################################### | ||
| 1058 | |||
| 1059 | |||
| 1060 | !############################################################################### | ||
| 1061 | 5 | subroutine parse_space_separated_ints(str, values) | |
| 1062 | !! Parse space-separated integers from a string into an allocatable array | ||
| 1063 | implicit none | ||
| 1064 | character(*), intent(in) :: str | ||
| 1065 | integer, allocatable, intent(out) :: values(:) | ||
| 1066 | |||
| 1067 | integer :: i, stat, ival | ||
| 1068 | character(256) :: work | ||
| 1069 | character(32) :: token | ||
| 1070 | |||
| 1071 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
5 | work = trim(adjustl(str)) |
| 1072 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
|
5 | allocate(values(0)) |
| 1073 | |||
| 1074 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12 times.
|
17 | do while(len_trim(work) .gt. 0) |
| 1075 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | i = index(trim(work), ' ') |
| 1076 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
|
12 | if(i .eq. 0)then |
| 1077 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
5 | token = trim(work) |
| 1078 | 5 | work = '' | |
| 1079 | else | ||
| 1080 |
3/6✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
|
7 | token = work(1:i-1) |
| 1081 |
3/6✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
|
7 | work = adjustl(work(i+1:)) |
| 1082 | end if | ||
| 1083 | 12 | read(token, *, iostat=stat) ival | |
| 1084 |
16/26✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
✓ Branch 17 taken 9 times.
✓ Branch 18 taken 12 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 12 times.
✓ Branch 21 taken 21 times.
✓ Branch 22 taken 12 times.
✓ Branch 23 taken 12 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 12 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 12 times.
✓ Branch 29 taken 21 times.
✓ Branch 30 taken 12 times.
|
63 | if(stat .eq. 0) values = [values, ival] |
| 1085 | end do | ||
| 1086 | |||
| 1087 | 5 | end subroutine parse_space_separated_ints | |
| 1088 | !############################################################################### | ||
| 1089 | |||
| 1090 | |||
| 1091 | !############################################################################### | ||
| 1092 | 11 | function onnx_to_athena_activation(optype) result(name) | |
| 1093 | !! Convert an ONNX activation op_type string to the Athena activation name | ||
| 1094 | implicit none | ||
| 1095 | character(*), intent(in) :: optype | ||
| 1096 | character(64) :: name | ||
| 1097 | |||
| 1098 | 11 | select case(trim(optype)) | |
| 1099 | case('LeakyRelu') | ||
| 1100 | ✗ | name = 'leaky_relu' | |
| 1101 | case('Relu') | ||
| 1102 | 5 | name = 'relu' | |
| 1103 | case('Sigmoid') | ||
| 1104 | 2 | name = 'sigmoid' | |
| 1105 | case('Softmax') | ||
| 1106 | 1 | name = 'softmax' | |
| 1107 | case('Tanh') | ||
| 1108 | 2 | name = 'tanh' | |
| 1109 | case('Selu') | ||
| 1110 | ✗ | name = 'selu' | |
| 1111 | case('Swish') | ||
| 1112 | 1 | name = 'swish' | |
| 1113 | case default | ||
| 1114 |
6/14✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
22 | name = to_lower(trim(optype)) |
| 1115 | end select | ||
| 1116 | |||
| 1117 | 11 | end function onnx_to_athena_activation | |
| 1118 | !############################################################################### | ||
| 1119 | |||
| 1120 | |||
| 1121 | end module athena__onnx_utils | ||
| 1122 |