GCC Code Coverage Report


Directory: src/athena/
File: src/athena/athena_onnx_write_sub.f90
Date: 2026-04-15 16:08:59
Exec Total Coverage
Lines: 338 373 90.6%
Functions: 0 0 -%
Branches: 864 1718 50.3%

Line Branch Exec Source
1 submodule(athena__onnx) athena__onnx_write_submodule
2 !! Submodule containing the ONNX export procedures.
3 !!
4 !! This submodule contains the routines that serialise ATHENA networks
5 !! to the JSON representation used for ONNX interchange.
6 use athena__io_utils, only: athena__version__
7 use athena__base_layer, only: base_layer_type, learnable_layer_type
8 use athena__onnx_nop_utils, only: emit_nop_metadata
9 use athena__misc_types, only: &
10 onnx_attribute_type, onnx_node_type, onnx_initialiser_type, &
11 onnx_tensor_type
12 use coreutils, only: to_lower, to_camel_case, stop_program
13
14 contains
15
16 !###############################################################################
17 11 module subroutine write_onnx(file, network, format)
18 !! Export a network to ONNX JSON format.
19 !!
20 !! GNN layers are exported as standard ONNX operators plus metadata
21 !! needed to reconstruct the original ATHENA layer on import.
22 use athena__onnx_utils, only: write_json_nodes, write_json_initialisers, &
23 write_json_tensors
24 implicit none
25
26 ! Arguments
27 class(network_type), intent(in) :: network
28 !! Instance of the network
29 character(*), intent(in) :: file
30 !! Output file name
31 class(*), optional, intent(in) :: format
32 !! Export format: 'athena_abstract' (default) or 'onnx_expanded'
33
34 ! Local variables
35 11 type(onnx_node_type), allocatable :: nodes(:)
36 !! Exported ONNX nodes
37 11 type(onnx_initialiser_type), allocatable :: inits(:)
38 !! Exported ONNX initialisers
39 11 type(onnx_tensor_type), allocatable :: graph_inputs(:)
40 !! Graph input tensor specifications
41 11 type(onnx_tensor_type), allocatable :: graph_outputs(:)
42 !! Graph output tensor specifications
43 11 character(4096), allocatable :: gnn_metadata(:)
44 !! Metadata entries required to reconstruct ATHENA GNN layers
45 integer :: num_nodes, num_inits, num_inputs, num_outputs, num_gnn_meta
46 !! Numbers of populated export records
47 integer :: max_nodes, max_inits
48 !! Pre-allocation sizes for node and initialiser storage
49 integer :: ifmt
50 !! Integer selector for export format
51
52
53 !---------------------------------------------------------------------------
54 ! Validate the export format and convert to integer selector
55 !---------------------------------------------------------------------------
56 22 ifmt = resolve_onnx_export_format(format)
57
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if(ifmt .eq. 0) return
58
59
60 !--------------------------------------------------------------------------
61 ! Initialise export storage
62 !--------------------------------------------------------------------------
63 call initialise_export_storage( &
64 network, nodes, inits, graph_inputs, graph_outputs, gnn_metadata, &
65
9/56
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ 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 taken 11 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 11 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 33 taken 11 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 11 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✓ Branch 43 taken 11 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 11 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✓ Branch 53 taken 11 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 11 times.
11 max_nodes, max_inits)
66
67 11 num_nodes = 0
68 11 num_inits = 0
69 11 num_inputs = 0
70 11 num_outputs = 0
71 11 num_gnn_meta = 0
72
73
74 !--------------------------------------------------------------------------
75 ! Collect graph content
76 !--------------------------------------------------------------------------
77 call collect_export_nodes( &
78 network, ifmt, nodes, num_nodes, max_nodes, &
79 inits, num_inits, max_inits, &
80 11 gnn_metadata, num_gnn_meta)
81 call build_graph_inputs( &
82 11 network, ifmt, graph_inputs, num_inputs)
83 call build_graph_outputs( &
84 11 network, ifmt, graph_outputs, num_outputs)
85
86
87 !--------------------------------------------------------------------------
88 ! Write the JSON model
89 !--------------------------------------------------------------------------
90 call write_onnx_json_file( &
91 file, ifmt, nodes, num_nodes, inits, num_inits, &
92 graph_inputs, num_inputs, graph_outputs, num_outputs, &
93 11 gnn_metadata, num_gnn_meta)
94
95
35/56
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2100 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 245 times.
✓ Branch 8 taken 1855 times.
✓ Branch 9 taken 245 times.
✓ Branch 10 taken 1855 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2100 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 taken 11 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 11 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1050 times.
✓ Branch 28 taken 11 times.
✓ Branch 29 taken 46 times.
✓ Branch 30 taken 1004 times.
✓ Branch 31 taken 46 times.
✓ Branch 32 taken 1004 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1050 times.
✓ Branch 35 taken 11 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 11 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 105 times.
✓ Branch 40 taken 11 times.
✓ Branch 41 taken 11 times.
✓ Branch 42 taken 94 times.
✓ Branch 43 taken 11 times.
✓ Branch 44 taken 94 times.
✓ Branch 45 taken 11 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 11 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 175 times.
✓ Branch 50 taken 11 times.
✓ Branch 51 taken 16 times.
✓ Branch 52 taken 159 times.
✓ Branch 53 taken 13 times.
✓ Branch 54 taken 162 times.
✓ Branch 55 taken 11 times.
✗ Branch 56 not taken.
3496 end subroutine write_onnx
96 !###############################################################################
97
98
99 !###############################################################################
100 11 function resolve_onnx_export_format(format) result(ifmt)
101 !! Resolve the ONNX export format into the internal integer selector.
102 implicit none
103
104 ! Arguments
105 class(*), optional, intent(in) :: format
106 !! Export format as a string name or integer selector
107
108 integer :: ifmt
109 !! Integer selector for the export format (1=athena_abstract, 2=onnx_expanded)
110
111 ! Local variables
112 character(32) :: format_name
113 !! Normalised string representation of the requested export format
114 character(128) :: err_msg
115 !! Error buffer used for unsupported integer selectors
116
117 11 ifmt = 1
118
119
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
11 if(present(format))then
120 select type(format)
121 type is(character(*))
122
2/4
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 format_name = to_lower(trim(adjustl(format)))
123 9 select case(trim(format_name))
124 case('athena_abstract')
125 ifmt = 1
126 case('onnx_expanded')
127 3 ifmt = 2
128 case default
129 call stop_program('write_onnx: unrecognised export format: ' // &
130 trim(format_name))
131 ifmt = 0
132
2/5
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
6 return
133 end select
134 type is(integer)
135 ifmt = format
136 class default
137 call stop_program('write_onnx: unrecognised export format type')
138 ifmt = 0
139 return
140 end select
141 end if
142
143 11 select case(ifmt)
144 case(1, 2)
145 11 continue
146 case default
147 write(err_msg, '("write_onnx: unrecognised export format selector: ",I0)') ifmt
148 call stop_program(err_msg)
149 ifmt = 0
150
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 return
151 end select
152
153 11 end function resolve_onnx_export_format
154 !###############################################################################
155
156
157 !###############################################################################
158 11 subroutine initialise_export_storage( &
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 network, nodes, inits, graph_inputs, graph_outputs, gnn_metadata, &
160 max_nodes, max_inits)
161 !! Allocate the working arrays used during ONNX export.
162 implicit none
163
164 ! Arguments
165 class(network_type), intent(in) :: network
166 !! Instance of the network
167 type(onnx_node_type), allocatable, intent(out) :: nodes(:)
168 !! Exported node storage
169 type(onnx_initialiser_type), allocatable, intent(out) :: inits(:)
170 !! Exported initialiser storage
171 type(onnx_tensor_type), allocatable, intent(out) :: graph_inputs(:)
172 !! Exported graph input storage
173 type(onnx_tensor_type), allocatable, intent(out) :: graph_outputs(:)
174 !! Exported graph output storage
175 character(4096), allocatable, intent(out) :: gnn_metadata(:)
176 !! Metadata storage for GNN layers
177 integer, intent(out) :: max_nodes, max_inits
178 !! Pre-allocation sizes
179
180 11 max_nodes = network%auto_graph%num_vertices * 60
181 11 max_inits = network%auto_graph%num_vertices * 30
182
183
17/40
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 11 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 11 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 11 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 11 times.
✓ Branch 29 taken 2100 times.
✓ Branch 30 taken 11 times.
✓ Branch 31 taken 2100 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 2100 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 2100 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 2100 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2111 allocate(nodes(max_nodes))
184
17/32
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 11 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 11 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 11 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 11 times.
✓ Branch 29 taken 1050 times.
✓ Branch 30 taken 11 times.
✓ Branch 31 taken 1050 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 1050 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1050 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1050 times.
1061 allocate(inits(max_inits))
185
17/32
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 11 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 11 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 11 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 11 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 11 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 11 times.
✓ Branch 31 taken 175 times.
✓ Branch 32 taken 11 times.
✓ Branch 33 taken 175 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 175 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 175 times.
186 allocate(graph_inputs(network%auto_graph%num_vertices * 5))
186
17/32
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 11 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 11 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 11 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 11 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 11 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 11 times.
✓ Branch 31 taken 105 times.
✓ Branch 32 taken 11 times.
✓ Branch 33 taken 105 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 105 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 105 times.
116 allocate(graph_outputs(network%auto_graph%num_vertices * 3))
187
7/14
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
11 allocate(gnn_metadata(network%auto_graph%num_vertices))
188
189 11 end subroutine initialise_export_storage
190 !###############################################################################
191
192
193 !###############################################################################
194 11 subroutine collect_export_nodes( &
195
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 network, ifmt, nodes, num_nodes, max_nodes, &
196
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 inits, num_inits, max_inits, &
197
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 gnn_metadata, num_gnn_meta)
198 !! Build the ONNX nodes, initialisers and GNN metadata.
199 implicit none
200
201 ! Arguments
202 class(network_type), intent(in) :: network
203 !! Instance of the network
204 integer, intent(in) :: ifmt
205 !! Export format selector
206 type(onnx_node_type), intent(inout) :: nodes(:)
207 !! Exported ONNX nodes
208 integer, intent(inout) :: num_nodes, max_nodes
209 !! Node counter and allocation limit
210 type(onnx_initialiser_type), intent(inout) :: inits(:)
211 !! Exported ONNX initialisers
212 integer, intent(inout) :: num_inits, max_inits
213 !! Initialiser counter and allocation limit
214 character(4096), intent(inout) :: gnn_metadata(:)
215 !! Exported GNN metadata entries
216 integer, intent(inout) :: num_gnn_meta
217 !! Number of metadata entries
218
219 ! Local variables
220 integer :: i, ii, layer_id, layer_num, lid
221 !! Loop index and layer identifier
222 character(128) :: node_name, input_name
223 !! Node name prefix and sequential input name
224 logical :: is_last_layer
225 !! Whether the current NOP is the last non-input layer
226
227
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if(ifmt .eq. 2)then
228 3 layer_num = 0
229 3 input_name = 'input'
230
231
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 do i = 1, network%auto_graph%num_vertices
232
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
6 layer_id = network%auto_graph%vertex(network%vertex_order(i))%id
233
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 3 times.
6 if(trim(network%model(layer_id)%layer%type) .eq. 'inpt') cycle
234
235
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 if(trim(network%model(layer_id)%layer%type) .ne. 'nop')then
236 call stop_program( &
237 'write_onnx: pytorch format supports NOP layers only')
238 return
239 end if
240
241 3 layer_num = layer_num + 1
242 3 write(node_name, '("layer",I0)') layer_num
243
244 3 is_last_layer = .true.
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 do ii = i + 1, network%auto_graph%num_vertices
246 lid = network%auto_graph%vertex(network%vertex_order(ii))%id
247
0/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
3 if(trim(network%model(lid)%layer%type) .ne. 'inpt')then
248 is_last_layer = .false.
249 exit
250 end if
251 end do
252
253 6 call network%model(layer_id)%layer%emit_onnx_nodes( &
254 trim(node_name), nodes, num_nodes, max_nodes, &
255 inits, num_inits, max_inits, input_name=trim(input_name), &
256
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 3 times.
✗ Branch 24 not taken.
3 is_last_layer=is_last_layer, format=ifmt)
257
258 call update_pytorch_prev_output( &
259 6 network%model(layer_id)%layer, trim(node_name), &
260
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
6 is_last_layer, input_name)
261 end do
262
263 3 return
264 end if
265
266
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 8 times.
37 do i = 1, network%auto_graph%num_vertices
267
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 29 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 29 times.
29 layer_id = network%auto_graph%vertex(network%vertex_order(i))%id
268
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 29 times.
29 write(node_name, '("node_",I0)') network%model(layer_id)%layer%id
269
270
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
66 select case(trim(network%model(layer_id)%layer%type))
271 case('inpt')
272 8 cycle
273 case('msgp')
274 call emit_gnn_input_renames( &
275
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
4 network, layer_id, i, nodes, num_nodes)
276 8 call network%model(layer_id)%layer%emit_onnx_nodes( &
277 trim(node_name), nodes, num_nodes, max_nodes, &
278
9/18
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 4 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 4 times.
✓ Branch 23 taken 4 times.
✗ Branch 24 not taken.
4 inits, num_inits, max_inits)
279 call build_gnn_metadata( &
280 8 network%model(layer_id)%layer, trim(node_name), &
281
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
4 gnn_metadata, num_gnn_meta)
282 case('nop')
283 call emit_standard_node_json( &
284 network, layer_id, i, nodes, num_nodes, max_nodes, &
285
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ 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 inits, num_inits, max_inits)
286 call emit_nop_metadata( &
287 8 network%model(layer_id)%layer, trim(node_name), &
288
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
4 gnn_metadata, num_gnn_meta)
289 case default
290 call emit_standard_node_json( &
291 network, layer_id, i, nodes, num_nodes, max_nodes, &
292
11/18
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 13 times.
✗ 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 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.
58 inits, num_inits, max_inits)
293 end select
294 end do
295
296 end subroutine collect_export_nodes
297 !###############################################################################
298
299
300 !###############################################################################
301 subroutine update_pytorch_prev_output(layer, prefix, is_last_layer, output)
302 !! Resolve the downstream tensor name after emitting one PyTorch-format NOP.
303 implicit none
304
305 class(base_layer_type), intent(in) :: layer
306 character(*), intent(in) :: prefix
307 logical, intent(in) :: is_last_layer
308 character(128), intent(inout) :: output
309
310
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(is_last_layer)then
311 3 output = 'output'
312 3 return
313 end if
314
315 select type(layer)
316 class is(learnable_layer_type)
317 if(trim(layer%activation%name) .ne. 'none')then
318 write(output, '("/",A,"/Relu_output_0")') trim(prefix)
319 else
320 write(output, '("/",A,"/Transpose_1_output_0")') trim(prefix)
321 end if
322 class default
323 write(output, '("/",A,"/Transpose_1_output_0")') trim(prefix)
324 end select
325
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 end subroutine update_pytorch_prev_output
327 !###############################################################################
328
329
330 !###############################################################################
331
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 subroutine build_graph_inputs(network, ifmt, graph_inputs, num_inputs)
332 !! Build the ONNX graph input tensor specifications.
333 implicit none
334
335 ! Arguments
336 class(network_type), intent(in) :: network
337 !! Instance of the network
338 integer, intent(in) :: ifmt
339 !! Export format selector
340 type(onnx_tensor_type), intent(inout) :: graph_inputs(:)
341 !! Graph input tensor specifications
342 integer, intent(inout) :: num_inputs
343 !! Number of graph inputs
344
345 ! Local variables
346 integer :: i, j, layer_id
347 !! Loop indices and current layer identifier
348
349
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if(ifmt .eq. 2)then
350
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 do i = 1, network%auto_graph%num_vertices
351
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 layer_id = network%auto_graph%vertex(network%vertex_order(i))%id
352
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 if(trim(network%model(layer_id)%layer%type) .ne. 'inpt') cycle
353 3 num_inputs = 1
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 graph_inputs(1)%name = 'input'
355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 graph_inputs(1)%elem_type = 1
356
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 allocate(graph_inputs(1)%dims(2))
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 graph_inputs(1)%dims = [ &
358
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 6 times.
✓ Branch 19 taken 3 times.
9 1, network%model(layer_id)%layer%input_shape(1)]
359 3 return
360 end do
361 return
362 end if
363
364
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 do i = 1, size(network%root_vertices, dim=1)
365
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
8 layer_id = network%auto_graph%vertex(network%root_vertices(i))%id
366
367
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 6 times.
8 if(network%model(layer_id)%layer%use_graph_output)then
368 2 num_inputs = num_inputs + 1
369
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 write(graph_inputs(num_inputs)%name, '("input_",I0,"_vertex")') &
370
3/6
✗ 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.
4 network%model(layer_id)%layer%id
371
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 graph_inputs(num_inputs)%elem_type = 1
372
5/10
✗ 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.
2 allocate(graph_inputs(num_inputs)%dims(2))
373
5/10
✗ 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.
2 allocate(graph_inputs(num_inputs)%dim_params(2))
374
4/8
✗ 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.
2 graph_inputs(num_inputs)%dim_params(1) = 'num_nodes'
375
4/8
✗ 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.
2 graph_inputs(num_inputs)%dims(1) = -1
376
4/8
✗ 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.
2 graph_inputs(num_inputs)%dim_params(2) = ''
377
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 graph_inputs(num_inputs)%dims(2) = &
378
7/14
✗ 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 14 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
4 network%model(layer_id)%layer%input_shape(1)
379
380
6/10
✗ 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 taken 1 times.
✓ Branch 13 taken 1 times.
2 if(network%model(layer_id)%layer%input_shape(2) .gt. 0)then
381 1 num_inputs = num_inputs + 1
382
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 write(graph_inputs(num_inputs)%name, '("input_",I0,"_edge")') &
383
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
2 network%model(layer_id)%layer%id
384
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 graph_inputs(num_inputs)%elem_type = 1
385
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
1 allocate(graph_inputs(num_inputs)%dims(2))
386
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
1 allocate(graph_inputs(num_inputs)%dim_params(2))
387
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 graph_inputs(num_inputs)%dim_params(1) = 'num_edges'
388
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 graph_inputs(num_inputs)%dims(1) = -1
389
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 graph_inputs(num_inputs)%dim_params(2) = ''
390
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 graph_inputs(num_inputs)%dims(2) = &
391
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
2 network%model(layer_id)%layer%input_shape(2)
392 end if
393
394 2 num_inputs = num_inputs + 1
395
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 write(graph_inputs(num_inputs)%name, &
396 4 '("input_",I0,"_edge_index")') &
397
3/6
✗ 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.
4 network%model(layer_id)%layer%id
398
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 graph_inputs(num_inputs)%elem_type = 7
399
5/10
✗ 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.
2 allocate(graph_inputs(num_inputs)%dims(2))
400
5/10
✗ 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.
2 allocate(graph_inputs(num_inputs)%dim_params(2))
401
4/8
✗ 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.
2 graph_inputs(num_inputs)%dim_params(1) = ''
402
4/8
✗ 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.
2 graph_inputs(num_inputs)%dims(1) = 3
403
4/8
✗ 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.
2 graph_inputs(num_inputs)%dim_params(2) = 'num_csr_entries'
404
4/8
✗ 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.
2 graph_inputs(num_inputs)%dims(2) = -1
405
406 2 num_inputs = num_inputs + 1
407
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 write(graph_inputs(num_inputs)%name, '("input_",I0,"_degree")') &
408
3/6
✗ 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.
4 network%model(layer_id)%layer%id
409
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 graph_inputs(num_inputs)%elem_type = 7
410
5/10
✗ 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.
2 allocate(graph_inputs(num_inputs)%dims(1))
411
5/10
✗ 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.
2 allocate(graph_inputs(num_inputs)%dim_params(1))
412
4/8
✗ 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.
2 graph_inputs(num_inputs)%dim_params(1) = 'num_nodes'
413
4/8
✗ 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.
2 graph_inputs(num_inputs)%dims(1) = -1
414 else
415 6 num_inputs = num_inputs + 1
416
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 write(graph_inputs(num_inputs)%name, '("input_",I0)') &
417
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
12 network%model(layer_id)%layer%id
418
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 graph_inputs(num_inputs)%elem_type = 1
419
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 allocate(graph_inputs(num_inputs)%dims( &
420
11/22
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 6 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 6 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 6 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 6 times.
12 size(network%model(layer_id)%layer%input_shape) + 1))
421
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 allocate(graph_inputs(num_inputs)%dim_params( &
422
11/22
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 6 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 6 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 6 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 6 times.
12 size(network%model(layer_id)%layer%input_shape) + 1))
423
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
6 graph_inputs(num_inputs)%dim_params(1) = 'batch_size'
424
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
6 graph_inputs(num_inputs)%dims(1) = -1
425
426
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 6 times.
16 do j = 1, size(network%model(layer_id)%layer%input_shape)
427
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
10 graph_inputs(num_inputs)%dim_params(j+1) = ''
428
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 graph_inputs(num_inputs)%dims(j+1) = &
429
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 10 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 10 times.
26 network%model(layer_id)%layer%input_shape(j)
430 end do
431 end if
432 end do
433
434 end subroutine build_graph_inputs
435 !###############################################################################
436
437
438 !###############################################################################
439
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 subroutine build_graph_outputs(network, ifmt, graph_outputs, num_outputs)
440 !! Build the ONNX graph output tensor specifications.
441 implicit none
442
443 ! Arguments
444 class(network_type), intent(in) :: network
445 !! Instance of the network
446 integer, intent(in) :: ifmt
447 !! Export format selector
448 type(onnx_tensor_type), intent(inout) :: graph_outputs(:)
449 !! Graph output tensor specifications
450 integer, intent(inout) :: num_outputs
451 !! Number of graph outputs
452
453 ! Local variables
454 integer :: i, j, layer_id
455 !! Loop indices and current layer identifier
456 11 character(:), allocatable :: suffix
457 !! Optional activation suffix for output names
458
459
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if(ifmt .eq. 2)then
460 3 layer_id = 0
461
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 do i = 1, network%auto_graph%num_vertices
462
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 j = network%vertex_order(i)
463
10/14
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✓ Branch 12 taken 6 times.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 3 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 3 times.
✓ Branch 17 taken 3 times.
9 if(all(network%leaf_vertices(:) .ne. j)) cycle
464
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 layer_id = network%auto_graph%vertex(j)%id
465 3 exit
466 end do
467
468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(layer_id .eq. 0) return
469
470 3 num_outputs = 1
471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 graph_outputs(1)%name = 'output'
472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 graph_outputs(1)%elem_type = 1
473
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
3 if(allocated(graph_outputs(1)%dims)) deallocate(graph_outputs(1)%dims)
474
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if(allocated(graph_outputs(1)%dim_params))then
475 deallocate(graph_outputs(1)%dim_params)
476 end if
477
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 allocate(graph_outputs(1)%dims(2))
478
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 allocate(graph_outputs(1)%dim_params(2))
479
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
3 graph_outputs(1)%dim_params(1) = 'batch_size'
480
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
3 graph_outputs(1)%dims(1) = -1
481
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
3 graph_outputs(1)%dim_params(2) = ''
482
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
3 graph_outputs(1)%dims(2) = network%model(layer_id)%layer%output_shape(1)
483 3 return
484 end if
485
486
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 do i = 1, size(network%leaf_vertices, dim=1)
487
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
8 layer_id = network%auto_graph%vertex(network%leaf_vertices(i))%id
488
2/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 suffix = ''
489
490 16 select type(layer => network%model(layer_id)%layer)
491 class is(learnable_layer_type)
492
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(layer%activation%name .ne. 'none')then
493
5/10
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 7 times.
7 suffix = '_' // trim(adjustl(layer%activation%name))
494 end if
495 end select
496
497 8 num_outputs = num_outputs + 1
498
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 write(graph_outputs(num_outputs)%name, '("node_",I0,A,"_output")') &
499
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✓ Branch 13 taken 7 times.
✓ Branch 14 taken 1 times.
16 network%model(layer_id)%layer%id, trim(adjustl(suffix))
500
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 graph_outputs(num_outputs)%elem_type = 1
501
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 allocate(graph_outputs(num_outputs)%dims( &
502
11/22
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 8 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 8 times.
16 size(network%model(layer_id)%layer%output_shape) + 1))
503
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 allocate(graph_outputs(num_outputs)%dim_params( &
504
11/22
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 8 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 8 times.
16 size(network%model(layer_id)%layer%output_shape) + 1))
505
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
8 graph_outputs(num_outputs)%dim_params(1) = 'batch_size'
506
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
8 graph_outputs(num_outputs)%dims(1) = -1
507
508
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 8 times.
25 do j = 1, size(network%model(layer_id)%layer%output_shape)
509
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
9 graph_outputs(num_outputs)%dim_params(j+1) = ''
510
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 graph_outputs(num_outputs)%dims(j+1) = &
511
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 9 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 9 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 9 times.
26 network%model(layer_id)%layer%output_shape(j)
512 end do
513 end do
514
515
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 end subroutine build_graph_outputs
516 !###############################################################################
517
518
519 !###############################################################################
520 11 subroutine write_onnx_json_file( &
521
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 file, ifmt, nodes, num_nodes, inits, num_inits, &
522
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 graph_inputs, num_inputs, graph_outputs, num_outputs, &
523
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 gnn_metadata, num_gnn_meta)
524 !! Write the collected export data to disk.
525 use athena__onnx_utils, only: write_json_nodes, write_json_initialisers, &
526 write_json_tensors
527 implicit none
528
529 ! Arguments
530 character(*), intent(in) :: file
531 !! Output file name
532 integer, intent(in) :: ifmt
533 !! Export format selector
534 type(onnx_node_type), intent(in) :: nodes(:)
535 !! Exported ONNX nodes
536 integer, intent(in) :: num_nodes
537 !! Number of exported nodes
538 type(onnx_initialiser_type), intent(in) :: inits(:)
539 !! Exported ONNX initialisers
540 integer, intent(in) :: num_inits
541 !! Number of exported initialisers
542 type(onnx_tensor_type), intent(in) :: graph_inputs(:)
543 !! Graph input tensor specifications
544 integer, intent(in) :: num_inputs
545 !! Number of graph inputs
546 type(onnx_tensor_type), intent(in) :: graph_outputs(:)
547 !! Graph output tensor specifications
548 integer, intent(in) :: num_outputs
549 !! Number of graph outputs
550 character(4096), intent(in) :: gnn_metadata(:)
551 !! GNN metadata strings
552 integer, intent(in) :: num_gnn_meta
553 !! Number of metadata entries
554
555 ! Local variables
556 integer :: unit, i
557 !! Output unit and loop index
558
559 11 open(newunit=unit, file=file, status='replace')
560 11 write(unit, '(A)') '{'
561
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if(ifmt .eq. 2)then
562 3 write(unit, '(A)') ' "irVersion": "7",'
563 3 write(unit, '(A)') ' "producerName": "pytorch",'
564 3 write(unit, '(A)') ' "producerVersion": "2.7.1",'
565 else
566 8 write(unit, '(A)') ' "irVersion": "8",'
567 8 write(unit, '(A)') ' "producerName": "Athena",'
568 8 write(unit, '(A,A,A)') ' "producerVersion": "', &
569 16 trim(athena__version__), '",'
570 end if
571 11 write(unit, '(A)') ' "graph": {'
572
573
3/6
✗ 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.
11 call write_json_nodes(unit, nodes, num_nodes)
574 11 write(unit, '(A)') ','
575
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if(ifmt .eq. 2)then
576 3 write(unit, '(A)') ' "name": "main_graph",'
577 else
578 8 write(unit, '(A)') ' "name": "athena_network",'
579 end if
580
3/6
✗ 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.
11 call write_json_initialisers(unit, inits, num_inits)
581 11 write(unit, '(A)') ','
582
3/6
✗ 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.
11 call write_json_tensors(unit, 'input', graph_inputs, num_inputs)
583 11 write(unit, '(A)') ','
584
3/6
✗ 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.
11 call write_json_tensors(unit, 'output', graph_outputs, num_outputs)
585
586
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if(ifmt .ne. 2 .and. num_gnn_meta .gt. 0)then
587 6 write(unit, '(A)') ','
588 6 write(unit, '(A)') ' "metadataProps": ['
589
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 do i = 1, num_gnn_meta
590
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if(i .gt. 1) write(unit, '(A)') ','
591
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
14 write(unit, '(A)') trim(gnn_metadata(i))
592 end do
593 6 write(unit, '(A)') ''
594 6 write(unit, '(A)') ' ]'
595 end if
596
597 11 write(unit, '(A)') ' },'
598 11 write(unit, '(A)') ' "opsetImport": ['
599 11 write(unit, '(A)') ' {'
600 11 write(unit, '(A)') ' "version": "17"'
601 11 write(unit, '(A)') ' }'
602 11 write(unit, '(A)') ' ]'
603 11 write(unit, '(A)') '}'
604 11 close(unit)
605
606
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 end subroutine write_onnx_json_file
607 !###############################################################################
608
609
610 !###############################################################################
611 17 subroutine emit_standard_node_json( &
612 network, layer_id, vertex_idx, &
613
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 nodes, num_nodes, max_nodes, &
614
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 inits, num_inits, max_inits)
615 !! Emit ONNX node records for a standard, non-GNN layer.
616 use athena__onnx_utils, only: emit_initialisers, build_attributes_json, &
617 emit_activation_node
618 implicit none
619
620 ! Arguments
621 class(network_type), intent(in) :: network
622 !! Instance of the network
623 integer, intent(in) :: layer_id, vertex_idx
624 !! Layer identifier and vertex position
625 type(onnx_node_type), intent(inout) :: nodes(:)
626 !! Exported ONNX nodes
627 integer, intent(inout) :: num_nodes, max_nodes
628 !! Node counter and allocation limit
629 type(onnx_initialiser_type), intent(inout) :: inits(:)
630 !! Exported ONNX initialisers
631 integer, intent(inout) :: num_inits, max_inits
632 !! Initialiser counter and allocation limit
633
634 ! Local variables
635 character(128) :: node_name, layer_name, input_name
636 !! Temporary strings used to build node names
637 17 character(:), allocatable :: suffix
638 !! Optional activation suffix for an input tensor name
639 integer :: j, input_layer_id, n_inputs
640 !! Loop index, source layer identifier and input count
641 17 character(128), allocatable :: input_list(:)
642 !! Input tensor names
643 character(4096) :: attr_json
644 !! Pre-formatted JSON attributes
645
646
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
17 write(node_name, '("node_", I0)') network%model(layer_id)%layer%id
647
648
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
34 select case(trim(network%model(layer_id)%layer%type))
649 case('full')
650 4 layer_name = 'Gemm'
651 case('conv')
652 2 layer_name = 'Conv'
653 case('pool')
654 layer_name = to_camel_case( &
655 4 trim(adjustl(network%model(layer_id)%layer%subtype)) // '_' // &
656 4 trim(adjustl(network%model(layer_id)%layer%type)), &
657
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
2 capitalise_first_letter = .true.)
658 case('actv')
659 layer_name = to_camel_case( &
660 6 trim(adjustl(network%model(layer_id)%layer%subtype)), &
661
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
3 capitalise_first_letter = .true.)
662 case('flat')
663 2 layer_name = 'Flatten'
664 case('batc')
665 layer_name = 'BatchNormalization'
666 case('drop')
667 layer_name = 'Dropout'
668 case('nop')
669 layer_name = to_camel_case( &
670 8 trim(adjustl(network%model(layer_id)%layer%name)), &
671
4/8
✗ 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.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
4 capitalise_first_letter = .true.)
672 case default
673
7/11
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
34 layer_name = 'Unknown'
674 end select
675
676 17 n_inputs = 0
677
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
17 allocate(input_list(100))
678
679
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 17 times.
127 do j = 1, network%auto_graph%num_vertices
680
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 110 times.
110 input_layer_id = network%auto_graph%vertex(j)%id
681
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 110 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 110 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 110 times.
✓ Branch 12 taken 93 times.
✓ Branch 13 taken 17 times.
110 if(network%auto_graph%adjacency( &
682
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 110 times.
203 j, network%vertex_order(vertex_idx)) .eq. 0) cycle
683
684
12/18
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 17 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 17 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 17 times.
✓ Branch 18 taken 65 times.
✓ Branch 19 taken 6 times.
✓ Branch 20 taken 11 times.
✓ Branch 21 taken 54 times.
✓ Branch 22 taken 6 times.
✓ Branch 23 taken 11 times.
71 if(all(network%auto_graph%adjacency(:,j) .eq. 0))then
685 12 write(input_name, '("input_",I0)') &
686
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 network%model(input_layer_id)%layer%id
687
2/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6 suffix = ''
688 else
689 22 write(input_name, '("node_",I0)') &
690
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
11 network%model(input_layer_id)%layer%id
691
3/8
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
11 suffix = '_output'
692 22 select type(prev => network%model(input_layer_id)%layer)
693 class is(learnable_layer_type)
694
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if(prev%activation%name .ne. 'none')then
695 suffix = '_' // trim(adjustl(prev%activation%name)) // &
696
5/10
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
2 '_output'
697 end if
698 end select
699 end if
700
701 17 n_inputs = n_inputs + 1
702
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 10 taken 17 times.
✗ Branch 11 not taken.
34 write(input_list(n_inputs), '(A,A)') trim(adjustl(input_name)), suffix
703 end do
704
705 34 select type(layer => network%model(layer_id)%layer)
706 class is(learnable_layer_type)
707
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 10 times.
36 do j = 1, size(layer%params)
708 26 n_inputs = n_inputs + 1
709
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✓ Branch 9 taken 26 times.
✗ Branch 10 not taken.
36 write(input_list(n_inputs), '(A,"_param",I0)') trim(node_name), j
710 end do
711 end select
712
713 call build_attributes_json( &
714
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
17 network%model(layer_id)%layer, trim(layer_name), attr_json)
715
716 17 num_nodes = num_nodes + 1
717
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 17 times.
✗ Branch 10 not taken.
17 nodes(num_nodes)%name = trim(node_name)
718
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 17 times.
✗ Branch 10 not taken.
17 nodes(num_nodes)%op_type = trim(layer_name)
719
9/18
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 17 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 17 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 17 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 17 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 17 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 17 times.
17 allocate(nodes(num_nodes)%inputs(n_inputs))
720
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 17 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 17 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 17 times.
✓ Branch 18 taken 17 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 17 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 43 times.
✓ Branch 25 taken 17 times.
60 nodes(num_nodes)%inputs = input_list(1:n_inputs)
721
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 17 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 17 times.
17 allocate(nodes(num_nodes)%outputs(1))
722
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 17 times.
✓ Branch 15 taken 17 times.
✗ Branch 16 not taken.
17 write(nodes(num_nodes)%outputs(1), '(A,"_output")') trim(node_name)
723
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
17 nodes(num_nodes)%attributes_json = attr_json
724
725 34 select type(layer => network%model(layer_id)%layer)
726 class is(learnable_layer_type)
727 call emit_initialisers(layer, trim(node_name), inits, num_inits, &
728
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
10 max_inits)
729
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
20 if(layer%activation%name .ne. 'none')then
730 call emit_activation_node( &
731 layer%activation%name, trim(node_name), '', &
732
4/8
✗ 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 11 taken 7 times.
✗ Branch 12 not taken.
7 nodes, num_nodes, max_nodes)
733 end if
734 end select
735
736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 deallocate(input_list)
737
738
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 end subroutine emit_standard_node_json
739 !###############################################################################
740
741
742 !###############################################################################
743 4 subroutine emit_gnn_input_renames( &
744
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 network, layer_id, vertex_idx, nodes, num_nodes)
745 !! Emit Identity nodes that rename GNN inputs to the expected convention.
746 use athena__onnx_utils, only: emit_node
747 implicit none
748
749 ! Arguments
750 class(network_type), intent(in) :: network
751 !! Instance of the network
752 integer, intent(in) :: layer_id, vertex_idx
753 !! Layer identifier and vertex position
754 type(onnx_node_type), intent(inout) :: nodes(:)
755 !! Exported ONNX nodes
756 integer, intent(inout) :: num_nodes
757 !! Number of exported nodes
758
759 ! Local variables
760 integer :: j, input_layer_id
761 !! Loop index and source layer identifier
762 character(128) :: prefix, vertex_in, edge_in, edge_index_in, degree_in
763 !! Temporary tensor names
764 4 character(:), allocatable :: suffix
765 !! Optional activation suffix for chained vertex inputs
766
767
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 write(prefix, '("node_",I0)') network%model(layer_id)%layer%id
768
769 4 vertex_in = ''
770 4 edge_in = ''
771 4 edge_index_in = ''
772 4 degree_in = ''
773
774
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 do j = 1, network%auto_graph%num_vertices
775
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
14 input_layer_id = network%auto_graph%vertex(j)%id
776
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✓ Branch 12 taken 10 times.
✓ Branch 13 taken 4 times.
14 if(network%auto_graph%adjacency( &
777
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
24 j, network%vertex_order(vertex_idx)) .eq. 0) cycle
778
779
12/18
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 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.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✓ Branch 18 taken 11 times.
✓ Branch 19 taken 2 times.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 9 times.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 2 times.
17 if(all(network%auto_graph%adjacency(:,j) .eq. 0))then
780 4 write(vertex_in, '("input_",I0,"_vertex")') &
781
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 network%model(input_layer_id)%layer%id
782 4 write(edge_in, '("input_",I0,"_edge")') &
783
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 network%model(input_layer_id)%layer%id
784 4 write(edge_index_in, '("input_",I0,"_edge_index")') &
785
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 network%model(input_layer_id)%layer%id
786 4 write(degree_in, '("input_",I0,"_degree")') &
787
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 network%model(input_layer_id)%layer%id
788 else
789
3/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
2 suffix = '_output'
790 4 select type(prev => network%model(input_layer_id)%layer)
791 class is(learnable_layer_type)
792
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(prev%activation%name .ne. 'none')then
793 suffix = '_' // trim(adjustl(prev%activation%name)) // &
794
5/10
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
2 '_output'
795 end if
796 end select
797 4 write(vertex_in, '("node_",I0,A)') &
798
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 network%model(input_layer_id)%layer%id, suffix
799 end if
800 end do
801
802
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(len_trim(vertex_in) .gt. 0)then
803 call emit_node('Identity', trim(prefix)//'_rename_vertex', &
804 trim(prefix)//'_vertex_in', '', nodes, num_nodes, &
805
6/12
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
4 in1=trim(vertex_in))
806 end if
807
808
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if(len_trim(edge_in) .gt. 0)then
809 call emit_node('Identity', trim(prefix)//'_rename_edge', &
810 trim(prefix)//'_edge_in', '', nodes, num_nodes, &
811
6/12
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
2 in1=trim(edge_in))
812 end if
813
814
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if(len_trim(edge_index_in) .gt. 0)then
815 call emit_node('Identity', trim(prefix)//'_rename_edge_index', &
816 trim(prefix)//'_edge_index_in', '', nodes, num_nodes, &
817
6/12
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
2 in1=trim(edge_index_in))
818 end if
819
820
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if(len_trim(degree_in) .gt. 0)then
821 call emit_node('Identity', trim(prefix)//'_rename_degree', &
822 trim(prefix)//'_degree_in', '', nodes, num_nodes, &
823
6/12
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
2 in1=trim(degree_in))
824 end if
825
826
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 end subroutine emit_gnn_input_renames
827 !###############################################################################
828
829
830 !###############################################################################
831 4 subroutine build_gnn_metadata(layer, prefix, metadata, num_meta)
832 !! Build the metadata entry required to reconstruct a GNN layer.
833 implicit none
834
835 ! Arguments
836 class(base_layer_type), intent(in) :: layer
837 !! GNN layer instance
838 character(*), intent(in) :: prefix
839 !! Node prefix used for this exported layer
840 character(4096), intent(inout) :: metadata(:)
841 !! Metadata strings to append to
842 integer, intent(inout) :: num_meta
843 !! Number of metadata entries
844
845 ! Local variables
846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 type(onnx_attribute_type), allocatable :: attrs(:)
847 !! Layer attributes returned by polymorphic dispatch
848 integer :: i
849 !! Loop index
850 character(2048) :: value_str
851 !! Semicolon-separated metadata payload
852
853
11/34
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 16 times.
✓ Branch 12 taken 4 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 16 times.
✓ Branch 28 taken 4 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 16 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 16 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 16 times.
40 attrs = layer%get_attributes()
854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(.not.allocated(attrs) .or. size(attrs) .eq. 0) return
855
856
2/4
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 value_str = 'subtype=' // trim(adjustl(layer%name))
857
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 do i = 1, size(attrs)
858 value_str = trim(value_str) // ';' // trim(attrs(i)%name) // '=' // &
859
8/16
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 16 times.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 16 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 16 times.
✓ Branch 22 taken 16 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 16 times.
✗ Branch 25 not taken.
20 trim(adjustl(attrs(i)%val))
860 end do
861
862 4 num_meta = num_meta + 1
863
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 write(metadata(num_meta), '(A)') &
864 ' {"key": "athena_gnn_' // trim(prefix) // &
865
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
8 '", "value": "' // trim(value_str) // '"}'
866
867
8/14
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 16 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 16 times.
✗ Branch 13 not taken.
28 end subroutine build_gnn_metadata
868 !###############################################################################
869
870
871 !###############################################################################
872
873
874
20/36
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 8 times.
✓ Branch 14 taken 7 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 11 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 11 times.
✓ Branch 23 taken 5 times.
✓ Branch 24 taken 6 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 17 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 17 times.
✓ Branch 32 taken 10 times.
✓ Branch 33 taken 7 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 17 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 17 times.
✓ Branch 41 taken 10 times.
✓ Branch 42 taken 7 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 2 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 2 times.
✓ Branch 50 taken 2 times.
✗ Branch 51 not taken.
58 end submodule athena__onnx_write_submodule
875