← Documents Documentation/arch/arm/samsung/clksrc-change-registers.awk GitHub 원문 ↗

Linux 6.18.37 · Architecture

Samsung ARM 클록 소스 레지스터 변환 AWK 스크립트

Samsung ARM의 기존 `clksrc_clk` 초기화 블록을 분석해 MASK 매크로에서 비트 폭·shift를 찾고 새 `.reg_div`·`.reg_src` 구조체 필드를 생성하는 AWK 변환 스크립트를 해설합니다.

Source pathDocumentation/arch/arm/samsung/clksrc-change-registers.awk
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

clksrc-change-registers.awk:1-166

Samsung ARM의 기존 `clksrc_clk` 초기화 블록을 분석해 MASK 매크로에서 비트 폭·shift를 찾고 새 `.reg_div`·`.reg_src` 구조체 필드를 생성하는 AWK 변환 스크립트를 해설합니다.

변환 흐름 요약
레지스터 헤더dmask 연관 배열clksrc_clk C 블록.reg_div / .reg_src 출력

헤더 마스크를 먼저 색인한 뒤 표준 입력의 C 초기화 블록을 변환합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 #!/usr/bin/awk -f
2 #
3 # Copyright 2010 Ben Dooks <[email protected]>
4 #
5 # Released under GPLv2
6
7 # example usage
8 # ./clksrc-change-registers.awk arch/arm/plat-s5pc1xx/include/plat/regs-clock.h < src > dst
9
10 function extract_value(s)
11 {
12 eqat = index(s, "=")
13 comat = index(s, ",")
14 return substr(s, eqat+2, (comat-eqat)-2)
15 }
16
17 function remove_brackets(b)
18 {
19 return substr(b, 2, length(b)-2)
20 }
21
22 function splitdefine(l, p)
23 {
24 r = split(l, tp)
25
26 p[0] = tp[2]
27 p[1] = remove_brackets(tp[3])
28 }
29
30 function find_length(f)
31 {
32 if (0)
33 printf "find_length " f "\n" > "/dev/stderr"
34
35 if (f ~ /0x1/)
36 return 1
37 else if (f ~ /0x3/)
38 return 2
39 else if (f ~ /0x7/)
40 return 3
41 else if (f ~ /0xf/)
42 return 4
43
44 printf "unknown length " f "\n" > "/dev/stderr"
45 exit
46 }
47
48 function find_shift(s)
49 {
50 id = index(s, "<")
51 if (id <= 0) {
52 printf "cannot find shift " s "\n" > "/dev/stderr"
53 exit
54 }
55
56 return substr(s, id+2)
57 }
58
59
60 BEGIN {
61 if (ARGC < 2) {
62 print "too few arguments" > "/dev/stderr"
63 exit
64 }
65
66 # read the header file and find the mask values that we will need
67 # to replace and create an associative array of values
68
69 while (getline line < ARGV[1] > 0) {
70 if (line ~ /\#define.*_MASK/ &&
71 !(line ~ /USB_SIG_MASK/)) {
72 splitdefine(line, fields)
73 name = fields[0]
74 if (0)
75 printf "MASK " line "\n" > "/dev/stderr"
76 dmask[name,0] = find_length(fields[1])
77 dmask[name,1] = find_shift(fields[1])
78 if (0)
79 printf "=> '" name "' LENGTH=" dmask[name,0] " SHIFT=" dmask[name,1] "\n" > "/dev/stderr"
80 } else {
81 }
82 }
83
84 delete ARGV[1]
85 }
86
87 /clksrc_clk.*=.*{/ {
88 shift=""
89 mask=""
90 divshift=""
91 reg_div=""
92 reg_src=""
93 indent=1
94
95 print $0
96
97 for(; indent >= 1;) {
98 if ((getline line) <= 0) {
99 printf "unexpected end of file" > "/dev/stderr"
100 exit 1;
101 }
102
103 if (line ~ /\.shift/) {
104 shift = extract_value(line)
105 } else if (line ~ /\.mask/) {
106 mask = extract_value(line)
107 } else if (line ~ /\.reg_divider/) {
108 reg_div = extract_value(line)
109 } else if (line ~ /\.reg_source/) {
110 reg_src = extract_value(line)
111 } else if (line ~ /\.divider_shift/) {
112 divshift = extract_value(line)
113 } else if (line ~ /{/) {
114 indent++
115 print line
116 } else if (line ~ /}/) {
117 indent--
118
119 if (indent == 0) {
120 if (0) {
121 printf "shift '" shift "' ='" dmask[shift,0] "'\n" > "/dev/stderr"
122 printf "mask '" mask "'\n" > "/dev/stderr"
123 printf "dshft '" divshift "'\n" > "/dev/stderr"
124 printf "rdiv '" reg_div "'\n" > "/dev/stderr"
125 printf "rsrc '" reg_src "'\n" > "/dev/stderr"
126 }
127
128 generated = mask
129 sub(reg_src, reg_div, generated)
130
131 if (0) {
132 printf "/* rsrc " reg_src " */\n"
133 printf "/* rdiv " reg_div " */\n"
134 printf "/* shift " shift " */\n"
135 printf "/* mask " mask " */\n"
136 printf "/* generated " generated " */\n"
137 }
138
139 if (reg_div != "") {
140 printf "\t.reg_div = { "
141 printf ".reg = " reg_div ", "
142 printf ".shift = " dmask[generated,1] ", "
143 printf ".size = " dmask[generated,0] ", "
144 printf "},\n"
145 }
146
147 printf "\t.reg_src = { "
148 printf ".reg = " reg_src ", "
149 printf ".shift = " dmask[mask,1] ", "
150 printf ".size = " dmask[mask,0] ", "
151
152 printf "},\n"
153
154 }
155
156 print line
157 } else {
158 print line
159 }
160
161 if (0)
162 printf indent ":" line "\n" > "/dev/stderr"
163 }
164 }
165
166 // && ! /clksrc_clk.*=.*{/ { print $0 }
167

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

기존 clksrc_clk 필드를 reg_div·reg_src 구조체로 변환하는 절차

1-166

이 AWK 스크립트는 Samsung ARM 플랫폼의 기존 `clksrc_clk` C 초기화 블록을 새 레지스터 서술 형식으로 변환하는 일회성 보조 도구입니다. 첫 번째 명령행 인수로 클록 레지스터 헤더를 읽고, 표준 입력으로 들어오는 C 소스에서 각 `clksrc_clk ... = {` 블록을 찾아 `.reg_div`와 `.reg_src` 중첩 초기화 항목을 생성합니다.

사용 예는 `./clksrc-change-registers.awk arch/arm/plat-s5pc1xx/include/plat/regs-clock.h < src > dst`입니다. 헤더 파일은 `_MASK` 매크로의 비트 폭과 shift를 계산하는 참조 자료이고, `src`는 변환할 원본 C 코드, `dst`는 생성 결과입니다. `USB_SIG_MASK`는 헤더 마스크 수집 대상에서 명시적으로 제외됩니다.

스크립트는 원본 식별자와 표현식을 문자열로 다룹니다. `extract_value()`는 초기화 행의 `=` 뒤부터 `,` 앞까지 값을 추출하고, `splitdefine()`은 `#define` 이름과 괄호 안 표현식을 분리합니다. `find_length()`는 `0x1`, `0x3`, `0x7`, `0xf` 마스크만 각각 1·2·3·4비트로 인식하며 다른 값이면 오류를 출력하고 종료합니다.

헤더 분석부터 C 초기화 생성까지
ARGV[1] 레지스터 헤더_MASK 매크로 필터dmask[name,0]=sizedmask[name,1]=shift
표준 입력 C 소스clksrc_clk 블록 탐색shift/mask/reg_divider/reg_source 수집generated 마스크 이름 생성.reg_div 및 .reg_src 출력표준 출력

헤더의 MASK 매크로를 연관 배열로 만든 뒤 표준 입력의 각 clksrc_clk 블록을 읽어 새 필드를 출력합니다.

보조 함수 다섯 개
함수원문 줄입력과 반환오류 조건
extract_value(s)10-15`=`와 `,` 위치를 찾아 그 사이의 초기화 값을 반환별도 검사 없음
remove_brackets(b)17-20문자열의 첫 문자와 마지막 문자를 제거별도 검사 없음
splitdefine(l, p)22-28공백 분리 후 `p[0]`에 매크로명, `p[1]`에 괄호 제거 표현식 저장별도 검사 없음
find_length(f)30-46마스크 `0x1/3/7/f`를 1/2/3/4비트 길이로 변환미지원 마스크면 `unknown length` 후 종료
find_shift(s)48-57첫 `<` 위치를 찾고 `<<` 뒤의 shift 표현식을 반환`<`가 없으면 `cannot find shift` 후 종료

원문 10-57줄의 함수가 입력 문자열을 어떻게 해석하는지 정리합니다.

BEGIN 헤더 전처리
단계코드·조건결과
인수 검사`ARGC < 2``too few arguments`를 표준 오류에 쓰고 종료
헤더 읽기`getline line < ARGV[1]`첫 인수 파일을 한 줄씩 처리
마스크 필터`#define.*_MASK`이며 `USB_SIG_MASK`가 아님필요한 클록 필드 마스크만 선택
매크로 분리`splitdefine(line, fields)``name`, 마스크 표현식 확보
연관 배열 작성`dmask[name,0]`, `dmask[name,1]`비트 길이와 shift 저장
인수 제거`delete ARGV[1]`헤더가 일반 AWK 입력 파일로 다시 처리되지 않도록 제거

원문 60-85줄에서 첫 번째 인수 파일을 읽어 `dmask` 연관 배열을 만드는 순서입니다.

clksrc_clk 블록에서 수집하는 기존 필드
변수감지 패턴용도
shift`.shift`수집되며 비활성 디버그 출력에서 확인 가능
mask`.mask`소스 레지스터의 MASK 매크로명과 `dmask` 조회 키
reg_div`.reg_divider`새 `.reg_div.reg` 값
reg_src`.reg_source`새 `.reg_src.reg` 값
divshift`.divider_shift`수집되지만 생성 필드 계산에는 직접 사용되지 않고 비활성 디버그 출력에만 등장
indent`{`에서 증가, `}`에서 감소중첩 초기화 블록의 끝을 찾는 깊이 카운터

원문 87-126줄의 상태 변수와 중괄호 깊이 추적을 설명합니다.

새 레지스터 초기화 출력
출력값 계산조건
generated`mask` 문자열에서 `reg_src`를 `reg_div`로 한 번 치환divider 마스크 매크로 이름을 유도
.reg_div.reg기존 `reg_divider` 값`reg_div`가 빈 문자열이 아닐 때만 전체 `.reg_div` 출력
.reg_div.shift`dmask[generated,1]`유도한 divider 마스크의 shift
.reg_div.size`dmask[generated,0]`유도한 divider 마스크의 비트 폭
.reg_src.reg기존 `reg_source` 값항상 `.reg_src` 블록 출력
.reg_src.shift`dmask[mask,1]`기존 source 마스크의 shift
.reg_src.size`dmask[mask,0]`기존 source 마스크의 비트 폭

원문 128-152줄이 기존 필드에서 생성하는 C 구조체 항목입니다.

입력 보존과 오류 처리
상황동작원문 줄
변환 블록 시작시작 행을 즉시 출력하고 내부 행은 `getline`으로 직접 소비87-101
중첩 중괄호깊이를 증가·감소하며 내부 일반 행을 그대로 출력113-118, 156-159
예기치 않은 EOF`unexpected end of file`을 표준 오류에 쓰고 상태 1로 종료97-101
디버그 코드`if (0)` 블록으로 비활성화된 진단 출력 보존32-33, 74-79, 120-137, 161-162
일반 입력 행마지막 패턴이 `clksrc_clk` 시작 행이 아닌 레코드를 그대로 출력166

변환 대상 외의 행과 비정상 입력을 처리하는 규칙입니다.

원문 줄 좌표
원문 줄구성한국어 해설
1-8shebang, 저작권, GPLv2, 사용 예AWK 직접 실행 방식과 헤더·표준 입출력 인자를 설명합니다.
10-28extract_value, remove_brackets, splitdefine초기화 값과 `#define` 표현식을 문자열로 분리합니다.
30-57find_length, find_shiftMASK 폭과 shift를 계산하고 미지원 형식에서 종료합니다.
60-85BEGIN헤더를 읽어 `dmask` 연관 배열을 구성하고 `ARGV[1]`을 삭제합니다.
87-101변환 블록 시작과 EOF 검사상태를 초기화하고 중괄호 블록을 직접 읽습니다.
103-126기존 필드 수집과 깊이 추적shift·mask·divider·source 값을 모읍니다.
128-152generated 계산과 새 필드 출력`.reg_div`와 `.reg_src` 중첩 초기화 코드를 만듭니다.
154-164블록 행 출력과 루프 종료닫는 중괄호와 기타 행을 보존합니다.
166일반 행 통과 규칙변환 블록 시작 행이 아닌 입력 레코드를 출력합니다.

166줄 스크립트를 기능 단위로 나눈 범위입니다.

아래 코드는 Linux v6.18.37 원문 1-166줄 전체입니다. 탭은 표시 안정성을 위해 여덟 칸으로 정규화했지만 AWK 함수명, 변수, 정규식, `getline`, 연관 배열 인덱스, C 필드명, 문자열과 줄 순서는 변경하지 않았습니다.

#!/usr/bin/awk -f
#
# Copyright 2010 Ben Dooks <[email protected]>
#
# Released under GPLv2

# example usage
# ./clksrc-change-registers.awk arch/arm/plat-s5pc1xx/include/plat/regs-clock.h < src > dst

function extract_value(s)
{
    eqat = index(s, "=")
    comat = index(s, ",")
    return substr(s, eqat+2, (comat-eqat)-2)
}

function remove_brackets(b)
{
    return substr(b, 2, length(b)-2)
}

function splitdefine(l, p)
{
    r = split(l, tp)

    p[0] = tp[2]
    p[1] = remove_brackets(tp[3])
}

function find_length(f)
{
    if (0)
        printf "find_length " f "\n" > "/dev/stderr"

    if (f ~ /0x1/)
        return 1
    else if (f ~ /0x3/)
        return 2
    else if (f ~ /0x7/)
        return 3
    else if (f ~ /0xf/)
        return 4

    printf "unknown length " f "\n" > "/dev/stderr"
    exit
}

function find_shift(s)
{
    id = index(s, "<")
    if (id <= 0) {
        printf "cannot find shift " s "\n" > "/dev/stderr"
        exit
    }

    return substr(s, id+2)
}


BEGIN {
    if (ARGC < 2) {
        print "too few arguments" > "/dev/stderr"
        exit
    }

# read the header file and find the mask values that we will need
# to replace and create an associative array of values

    while (getline line < ARGV[1] > 0) {
        if (line ~ /\#define.*_MASK/ &&
            !(line ~ /USB_SIG_MASK/)) {
            splitdefine(line, fields)
            name = fields[0]
            if (0)
                printf "MASK " line "\n" > "/dev/stderr"
            dmask[name,0] = find_length(fields[1])
            dmask[name,1] = find_shift(fields[1])
            if (0)
                printf "=> '" name "' LENGTH=" dmask[name,0] " SHIFT=" dmask[name,1] "\n" > "/dev/stderr"
        } else {
        }
    }

    delete ARGV[1]
}

/clksrc_clk.*=.*{/ {
    shift=""
    mask=""
    divshift=""
    reg_div=""
    reg_src=""
    indent=1

    print $0

    for(; indent >= 1;) {
        if ((getline line) <= 0) {
            printf "unexpected end of file" > "/dev/stderr"
            exit 1;
        }

        if (line ~ /\.shift/) {
            shift = extract_value(line)
        } else if (line ~ /\.mask/) {
            mask = extract_value(line)
        } else if (line ~ /\.reg_divider/) {
            reg_div = extract_value(line)
        } else if (line ~ /\.reg_source/) {
            reg_src = extract_value(line)
        } else if (line ~ /\.divider_shift/) {
            divshift = extract_value(line)
        } else if (line ~ /{/) {
                indent++
                print line
            } else if (line ~ /}/) {
            indent--

            if (indent == 0) {
                if (0) {
                    printf "shift '" shift   "' ='" dmask[shift,0] "'\n" > "/dev/stderr"
                    printf "mask  '" mask    "'\n" > "/dev/stderr"
                    printf "dshft '" divshift "'\n" > "/dev/stderr"
                    printf "rdiv  '" reg_div "'\n" > "/dev/stderr"
                    printf "rsrc  '" reg_src "'\n" > "/dev/stderr"
                }

                generated = mask
                sub(reg_src, reg_div, generated)

                if (0) {
                    printf "/* rsrc " reg_src " */\n"
                    printf "/* rdiv " reg_div " */\n"
                    printf "/* shift " shift " */\n"
                    printf "/* mask " mask " */\n"
                    printf "/* generated " generated " */\n"
                }

                if (reg_div != "") {
                    printf "\t.reg_div = { "
                    printf ".reg = " reg_div ", "
                    printf ".shift = " dmask[generated,1] ", "
                    printf ".size = " dmask[generated,0] ", "
                    printf "},\n"
                }

                printf "\t.reg_src = { "
                printf ".reg = " reg_src ", "
                printf ".shift = " dmask[mask,1] ", "
                printf ".size = " dmask[mask,0] ", "

                printf "},\n"

            }

            print line
        } else {
            print line
        }

        if (0)
            printf indent ":" line "\n" > "/dev/stderr"
    }
}

// && ! /clksrc_clk.*=.*{/ { print $0 }