build_attributes_json Subroutine

public subroutine build_attributes_json(layer, op_type, attr_json)

Build JSON string for layer attributes

Arguments

Type IntentOptional Attributes Name
class(base_layer_type), intent(in) :: layer

Layer supplying ONNX attribute metadata

character(len=*), intent(in) :: op_type

ONNX operation type used to handle special cases

character(len=4096), intent(out) :: attr_json

Serialized JSON fragment containing the emitted attributes


Source Code

  subroutine build_attributes_json(layer, op_type, attr_json)
    !! Build JSON string for layer attributes
    implicit none

    ! Arguments
    class(base_layer_type), intent(in) :: layer
    !! Layer supplying ONNX attribute metadata
    character(*), intent(in) :: op_type
    !! ONNX operation type used to handle special cases
    character(4096), intent(out) :: attr_json
    !! Serialized JSON fragment containing the emitted attributes

    ! Local variables
    type(onnx_attribute_type), allocatable, dimension(:) :: attributes
    !! Attribute list returned by the layer
    integer :: i, j, itmp1
    !! Attribute index, value index, and temporary integer count
    character(256) :: buffer
    !! Temporary string buffer for serialised scalar values
    integer, allocatable :: ivar_list(:)
    !! Parsed integer attribute payload for INTS-valued attributes
    real(real32), allocatable :: rvar_list(:)
    !! Placeholder for future real-valued list attributes
    character(10) :: type_lw
    !! Lower-case attribute type string used in the select case

    attr_json = ''

    ! For Gemm, add transB attribute
    if(trim(op_type) .eq. 'Gemm')then
       attr_json = '        "attribute": [' // &
            '{"name": "alpha", "f": 1.0, "type": "FLOAT"}, ' // &
            '{"name": "beta", "f": 1.0, "type": "FLOAT"}, ' // &
            '{"name": "transB", "i": "1", "type": "INT"}]'
       return
    end if

    attributes = layer%get_attributes()
    if(.not.allocated(attributes) .or. size(attributes) .eq. 0) return

    attr_json = '        "attribute": ['
    do i = 1, size(attributes)
       if(i .gt. 1) attr_json = trim(attr_json) // ', '
       attr_json = trim(attr_json) // '{"name": "' // &
            trim(attributes(i)%name) // '"'

       type_lw = trim(adjustl(attributes(i)%type))
       select case(type_lw)
       case('int')
          attr_json = trim(attr_json) // ', "i": "' // &
               trim(adjustl(attributes(i)%val)) // '", "type": "INT"}'
       case('ints')
          ! Parse multiple ints
          itmp1 = 1
          do j = 1, len_trim(attributes(i)%val)
             if(attributes(i)%val(j:j) .eq. ' ') itmp1 = itmp1 + 1
          end do
          allocate(ivar_list(itmp1))
          read(attributes(i)%val, *) ivar_list
          attr_json = trim(attr_json) // ', "ints": ['
          do j = 1, itmp1
             if(j .gt. 1) attr_json = trim(attr_json) // ', '
             write(buffer, '("""",I0,"""")') ivar_list(j)
             attr_json = trim(attr_json) // trim(adjustl(buffer))
          end do
          attr_json = trim(attr_json) // '], "type": "INTS"}'
          deallocate(ivar_list)
       case('float')
          attr_json = trim(attr_json) // ', "f": ' // &
               trim(adjustl(attributes(i)%val)) // ', "type": "FLOAT"}'
       case('string')
          ! Base64 encode the string value
          call encode_string_base64( &
               trim(adjustl(attributes(i)%val)), buffer)
          attr_json = trim(attr_json) // ', "s": "' // &
               trim(buffer) // '", "type": "STRING"}'
       case default
          attr_json = trim(attr_json) // '}'
       end select
    end do
    attr_json = trim(attr_json) // ']'

  end subroutine build_attributes_json