├── __init__.py
├── stdf
├── __init__.py
├── stdf_writer.py
├── stdf_reader.py
└── stdf_v4.json
├── tests
├── __init__.py
├── .cache
│ └── v
│ │ └── cache
│ │ └── lastfailed
├── stdf_test.json
├── test_reads.py
└── test_writes.py
├── MANIFEST.in
├── .idea
└── vcs.xml
├── README.md
├── LICENSE.txt
├── sample.py
└── setup.py
/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/stdf/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include *.md *.txt
--------------------------------------------------------------------------------
/tests/.cache/v/cache/lastfailed:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # STDF Reader
2 | This library is meant to read the binary STDF file (*.std), which is
3 | the standard test data format commonly used by Automated Test Equipment
4 | such as Teradyne, Advantest and LTX testers.
5 |
6 | ### Installation
7 | pip install stdf
8 |
9 | ### Usage
10 | from stdf.stdf_reader import Reader()
11 | stdf = Reader()
12 | stdf.load_stdf_file(stdf_file='input_file.std')
13 |
14 | for rec_name, header, body in stdf:
15 | # iterate stdf file record by record, starting from 'FAR' record.
16 |
17 | if rec_name == 'FAR':
18 | # body is a dictionary with field name as keys.
19 | cpu_type = body['CPU_TYPE']
20 |
21 | ### Documentation
22 | Visit https://pythonhosted.org/stdf/
23 |
24 | ### Limitation
25 | - STDF V4 format only.
26 | - Python 3.3 and above.
27 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2016 Cahyo Primawidodo
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation
6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
7 | to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of
10 | the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
13 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
15 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 | THE SOFTWARE.
--------------------------------------------------------------------------------
/tests/stdf_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "T1U": {
3 | "rec_typ": 11,
4 | "rec_sub": 1,
5 | "body": [
6 | ["UNSIGNED_1", "U1"],
7 | ["UNSIGNED_2", "U2"],
8 | ["UNSIGNED_4", "U4"]
9 | ]
10 | },
11 |
12 | "T1I": {
13 | "rec_typ": 11,
14 | "rec_sub": 2,
15 | "body": [
16 | ["SIGNED_1", "I1"],
17 | ["SIGNED_2", "I2"],
18 | ["SIGNED_4", "I4"]
19 | ]
20 | },
21 |
22 | "T1F": {
23 | "rec_typ": 11,
24 | "rec_sub": 3,
25 | "body": [
26 | ["FLOAT", "R4"],
27 | ["DOUBLE", "R8"]
28 | ]
29 | },
30 |
31 | "T1N": {
32 | "rec_typ": 11,
33 | "rec_sub": 4,
34 | "body": [
35 | ["NIBBLE_1", "N1"],
36 | ["NIBBLE_2", "N1"]
37 | ]
38 | },
39 |
40 | "TCn": {
41 | "rec_typ": 11,
42 | "rec_sub": 5,
43 | "body": [
44 | ["STRING_1", "Cn"],
45 | ["STRING_2", "Cn"],
46 | ["STRING_7", "Cn"]
47 | ]
48 | },
49 |
50 | "TBn": {
51 | "rec_typ": 11,
52 | "rec_sub": 6,
53 | "body": [
54 | ["BYTE_1", "Bn"],
55 | ["BYTE_2", "Bn"],
56 | ["BYTE_7", "Bn"]
57 | ]
58 | },
59 |
60 | "TA1": {
61 | "rec_typ": 11,
62 | "rec_sub": 7,
63 | "body": [
64 | ["ARR_ICNT", "U1"],
65 | ["ARR_U1", "K0U1"],
66 | ["ARR_U2", "K0U2"],
67 | ["ARR_I1", "K0I1"],
68 | ["ARR_I2", "K0I2"],
69 | ["ARR_R4", "K0R4"],
70 | ["ARR_R8", "K0R8"]
71 | ]
72 | },
73 |
74 | "TA2": {
75 | "rec_typ": 11,
76 | "rec_sub": 8,
77 | "body": [
78 | ["ARR_ICNT", "U1"],
79 | ["ARR_N1", "K0N1"],
80 | ["ARR_Cn", "K0Cn"],
81 | ["ARR_Bn", "K0Bn"]
82 | ]
83 | }
84 | }
--------------------------------------------------------------------------------
/sample.py:
--------------------------------------------------------------------------------
1 | """The MIT License (MIT)
2 | Copyright (c) 2016 Cahyo Primawidodo
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation
6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
7 | to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of
10 | the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
13 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
15 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 | THE SOFTWARE."""
17 |
18 | from stdf.stdf_reader import Reader
19 | from stdf.stdf_writer import Writer
20 | import logging
21 | from pathlib import Path
22 |
23 | __author__ = 'cahyo primawidodo 2016'
24 |
25 |
26 | if __name__ == '__main__':
27 |
28 | logging.basicConfig(level=logging.INFO)
29 |
30 | p = Path('/Users/cahyo/Documents/data/oca')
31 | in_file = str(p / 'ASETKH-UFLX0058_1_WSBU-NN450-12B-04p1_1_DP5403.K2_15_20150303175521.stdf')
32 |
33 | stdf = Reader()
34 | stdf.load_stdf_file(stdf_file=in_file)
35 |
36 | with open('output.txt', mode='wt', encoding='utf-8') as fout:
37 | for rec_name, header, body in stdf:
38 |
39 | for r in rec_name:
40 | fout.write(r)
41 |
42 | if fout.tell() % 100 == 0:
43 | fout.write('\n')
44 |
45 | for k, v in body.items():
46 | fout.write('.')
47 |
48 | if fout.tell() % 100 == 0:
49 | fout.write('\n')
50 |
--------------------------------------------------------------------------------
/tests/test_reads.py:
--------------------------------------------------------------------------------
1 | """The MIT License (MIT)
2 | Copyright (c) 2016 Cahyo Primawidodo
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation
6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
7 | to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of
10 | the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
13 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
15 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 | THE SOFTWARE."""
17 |
18 | import pytest
19 | import struct
20 | import io
21 | from stdf.stdf_reader import Reader
22 |
23 | @pytest.fixture()
24 | def rd():
25 | return Reader('/Users/cahyo/Dropbox/programming/python/STDFReader/tests/stdf_test.json')
26 |
27 |
28 | def test_read_unsigned(rd):
29 |
30 | r = struct.pack('/my_data'
101 | # data_files=[('my_data', ['data/data_file'])],
102 |
103 | # To provide executable scripts, use entry points in preference to the
104 | # "scripts" keyword. Entry points provide cross-platform support and allow
105 | # pip to create the appropriate form of executable for the target platform.
106 | entry_points={
107 | 'console_scripts': [
108 | 'stdf=stdf_reader:Reader',
109 | ],
110 | },
111 | )
--------------------------------------------------------------------------------
/tests/test_writes.py:
--------------------------------------------------------------------------------
1 | """The MIT License (MIT)
2 | Copyright (c) 2016 Cahyo Primawidodo
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation
6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
7 | to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of
10 | the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
13 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
15 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 | THE SOFTWARE."""
17 |
18 | import pytest
19 | import struct
20 | from stdf.stdf_writer import Writer
21 |
22 | @pytest.fixture()
23 | def w():
24 | return Writer('/Users/cahyo/Dropbox/programming/python/STDFReader/tests/stdf_test.json')
25 |
26 |
27 | def test_write_unsigned(w):
28 | data = {
29 | 'UNSIGNED_1': 0x81,
30 | 'UNSIGNED_2': 0x8001,
31 | 'UNSIGNED_4': 0x80000001
32 | }
33 |
34 | r = w.pack_record('T1U', data)
35 | u = struct.unpack(' bytearray:
148 | body_fmt = ''
149 | body_data = []
150 | odd_nibble = True
151 |
152 | for field_name, fmt_raw in field_fmt:
153 | item = field_data[field_name]
154 |
155 | if fmt_raw.startswith('K'):
156 | mo = re.match('^K([0xn])(\w{2})', fmt_raw)
157 | n = self.__get_multiplier(field_name, body_data)
158 | fmt_act = mo.group(2)
159 |
160 | for i in range(n):
161 |
162 | fmt, dat, odd_nibble = self.__construct_body(fmt_act, item[i], body_data, odd_nibble)
163 |
164 | body_fmt += fmt
165 | body_data.extend(dat)
166 |
167 | else:
168 | fmt, dat, odd_nibble = self.__construct_body(fmt_raw, item, body_data, odd_nibble)
169 |
170 | body_fmt += fmt
171 | body_data.extend(dat)
172 |
173 | return body_fmt, body_data
174 |
175 | @staticmethod
176 | def _pack_header(length, typ, sub) -> bytearray:
177 | header_fmt = 'HBB'
178 | header_data = [length, typ, sub]
179 | return header_fmt, header_data
180 |
181 | def pack_record(self, rec_name, data):
182 |
183 | mapping = self.STDF_TYPE[rec_name]['body']
184 | fmt_b, data_b = self._pack_body(mapping, data)
185 |
186 | rec_len = struct.calcsize('HBB' + fmt_b) - 4
187 | rec_typ = self.STDF_TYPE[rec_name]['rec_typ']
188 | rec_sub = self.STDF_TYPE[rec_name]['rec_sub']
189 | fmt_h, data_h = self._pack_header(rec_len, rec_typ, rec_sub)
190 |
191 | fmt = fmt_h + fmt_b
192 | *d, = data_h + data_b
193 |
194 | return struct.pack(self.e + fmt, *d)
195 |
196 | def pack_FAR(self):
197 |
198 | r = self.pack_record('FAR', {'CPU_TYPE': 2, 'STDF_VER': 4})
199 | return r
200 |
--------------------------------------------------------------------------------
/stdf/stdf_reader.py:
--------------------------------------------------------------------------------
1 | """The MIT License (MIT)
2 | Copyright (c) 2016 Cahyo Primawidodo
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation
6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
7 | to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of
10 | the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
13 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
15 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 | THE SOFTWARE."""
17 |
18 | import json
19 | import io
20 | import struct
21 | import logging
22 | import re
23 | import math
24 | from os import path
25 |
26 | __author__ = 'cahyo primawidodo 2016'
27 |
28 |
29 | class Reader:
30 | HEADER_SIZE = 4
31 |
32 | def __init__(self, stdf_ver_json=None):
33 | self.log = logging.getLogger(self.__class__.__name__)
34 | self.STDF_TYPE = {}
35 | self.STDF_IO = io.BytesIO(b'')
36 | self.REC_NAME = {}
37 | self.FMT_MAP = {}
38 | self.e = '<'
39 |
40 | self.body_start = 0
41 |
42 | self._load_byte_fmt_mapping()
43 | self._load_stdf_type(json_file=stdf_ver_json)
44 |
45 | def _load_stdf_type(self, json_file):
46 |
47 | if json_file is None:
48 | here = path.abspath(path.dirname(__file__))
49 | input_file = path.join(here, 'stdf_v4.json')
50 | else:
51 | input_file = json_file
52 |
53 | self.log.info('loading STDF configuration file = {}'.format(input_file))
54 | with open(input_file) as fp:
55 | self.STDF_TYPE = json.load(fp)
56 |
57 | for k, v in self.STDF_TYPE.items():
58 | typ_sub = (v['rec_typ'], v['rec_sub'])
59 | self.REC_NAME[typ_sub] = k
60 |
61 | def _load_byte_fmt_mapping(self):
62 | self.FMT_MAP = {
63 | "U1": "B",
64 | "U2": "H",
65 | "U4": "I",
66 | "U8": "Q",
67 | "I1": "b",
68 | "I2": "h",
69 | "I4": "i",
70 | "I8": "q",
71 | "R4": "f",
72 | "R8": "d",
73 | "B1": "B",
74 | "C1": "c",
75 | "N1": "B"
76 | }
77 |
78 | def load_stdf_file(self, stdf_file):
79 | self.log.info('opening STDF file = {}'.format(stdf_file))
80 | with open(stdf_file, mode='rb') as fs:
81 | self.STDF_IO = io.BytesIO(fs.read())
82 | self.log.info('detecting STDF file size = {}'.format(len(self.STDF_IO.getvalue())))
83 |
84 | def read_record(self):
85 | header = self._read_and_unpack_header()
86 |
87 | if header:
88 | rec_size, _, _ = header
89 | self.log.debug('BODY start at tell={:0>8}'.format(self.STDF_IO.tell()))
90 | body_raw = self._read_body(rec_size)
91 | rec_name, body = self._unpack_body(header, body_raw)
92 | self.log.debug('BODY end at tell={:0>8}'.format(self.STDF_IO.tell()))
93 |
94 | if rec_name == 'FAR':
95 | self.__set_endian(body['CPU_TYPE'])
96 |
97 | return rec_name, header, body
98 |
99 | else:
100 | self.log.info('closing STDF_IO at tell={:0>8}'.format(self.STDF_IO.tell()))
101 | self.STDF_IO.close()
102 | return False
103 |
104 | def _read_and_unpack_header(self):
105 | header_raw = self.STDF_IO.read(self.HEADER_SIZE)
106 |
107 | header = False
108 | if header_raw:
109 | header = struct.unpack(self.e + 'HBB', header_raw)
110 | rec_name = self.REC_NAME.setdefault((header[1], header[2]), 'UNK')
111 | self.log.debug('len={:0>3}, rec={}'.format(header[0], rec_name))
112 |
113 | return header
114 |
115 | def _read_body(self, rec_size):
116 | self.body_start = self.STDF_IO.tell()
117 | body_raw = io.BytesIO(self.STDF_IO.read(rec_size))
118 | assert len(body_raw.getvalue()) == rec_size
119 | return body_raw
120 |
121 | def _unpack_body(self, header, body_raw):
122 | rec_len, rec_typ, rec_sub = header
123 | typ_sub = (rec_typ, rec_sub)
124 | rec_name = self.REC_NAME.setdefault(typ_sub, 'UNK')
125 | max_tell = rec_len
126 | odd_nibble = True
127 |
128 | body = {}
129 | if rec_name in self.STDF_TYPE:
130 | for field, fmt_raw in self.STDF_TYPE[rec_name]['body']:
131 | self.log.debug('field={}, fmt_raw={}'.format(field, fmt_raw))
132 |
133 | if fmt_raw == 'N1' and not odd_nibble:
134 | pass
135 | elif body_raw.tell() >= max_tell:
136 | break
137 |
138 | array_data = []
139 | if fmt_raw.startswith('K'):
140 | mo = re.match('^K([0xn])(\w{2})', fmt_raw)
141 | n = self.__get_multiplier(field, body)
142 | fmt_act = mo.group(2)
143 |
144 | for i in range(n):
145 | data, odd_nibble = self.__get_data(fmt_act, body_raw, odd_nibble)
146 | array_data.append(data)
147 |
148 | body[field] = array_data
149 | odd_nibble = True
150 |
151 | elif fmt_raw.startswith('V'):
152 | vn_map = ['B0', 'U1', 'U2', 'U4', 'I1', 'I2',
153 | 'I4', 'R4', 'R8', 'Cn', 'Bn', 'Dn', 'N1']
154 | n, = struct.unpack('H', body_raw.read(2))
155 |
156 | for i in range(n):
157 | idx, = struct.unpack(self.e + 'B', body_raw.read(1))
158 | fmt_vn = vn_map[idx]
159 |
160 | data, odd_nibble = self.__get_data(fmt_vn, body_raw, odd_nibble)
161 | array_data.append(data)
162 |
163 | body[field] = array_data
164 | odd_nibble = True
165 |
166 | else:
167 | body[field], odd_nibble = self.__get_data(fmt_raw, body_raw, odd_nibble)
168 |
169 | else:
170 | self.log.warn('record name={} ({}, {}), not found in self.STDF_TYPE'.format(rec_name, rec_typ, rec_sub))
171 |
172 | body_raw.close()
173 | return rec_name, body
174 |
175 | def __get_data(self, fmt_act, body_raw, odd_nibble):
176 | data = 0
177 | if fmt_act == 'N1':
178 | if odd_nibble:
179 | nibble, = struct.unpack(self.e + 'B', body_raw.read(1))
180 | _, data = nibble >> 4, nibble & 0xF
181 | odd_nibble = False
182 | else:
183 | body_raw.seek(-1, 1)
184 | nibble, = struct.unpack(self.e + 'B', body_raw.read(1))
185 | data, _ = nibble >> 4, nibble & 0xF
186 | odd_nibble = True
187 | else:
188 | fmt, buf = self.__get_format_and_buffer(fmt_act, body_raw)
189 |
190 | if fmt:
191 | d = struct.unpack(fmt, buf)
192 | data = d[0] if len(d) == 1 else d
193 | odd_nibble = True
194 |
195 | return data, odd_nibble
196 |
197 | def __get_format_and_buffer(self, fmt_raw, body_raw):
198 | fmt = self.__get_format(fmt_raw, body_raw)
199 | if fmt:
200 | size = struct.calcsize(fmt)
201 | buf = body_raw.read(size)
202 | self.log.debug('fmt={}, buf={}'.format(fmt, buf))
203 | return fmt, buf
204 | else:
205 | return 0, 0
206 |
207 | def __get_format(self, fmt_raw, body_raw):
208 | self.log.debug('fmt_raw={}, body_raw={}'.format(fmt_raw, body_raw))
209 |
210 | if fmt_raw in self.FMT_MAP:
211 | return self.FMT_MAP[fmt_raw]
212 |
213 | elif fmt_raw == 'Sn':
214 | buf = body_raw.read(2)
215 | n, = struct.unpack(self.e + 'H', buf)
216 | posfix = 's'
217 |
218 | elif fmt_raw == 'Cn':
219 | buf = body_raw.read(1)
220 | n, = struct.unpack(self.e + 'B', buf)
221 | posfix = 's'
222 |
223 | elif fmt_raw == 'Bn':
224 | buf = body_raw.read(1)
225 | n, = struct.unpack(self.e + 'B', buf)
226 | posfix = 'B'
227 |
228 | elif fmt_raw == 'Dn':
229 | buf = body_raw.read(2)
230 | h, = struct.unpack(self.e + 'H', buf)
231 | n = math.ceil(h/8)
232 | posfix = 'B'
233 | else:
234 | raise ValueError(fmt_raw, body_raw.tell(), body_raw.__sizeof__())
235 |
236 | return str(n) + posfix if n else ''
237 |
238 | def __set_endian(self, cpu_type):
239 | if cpu_type == 1:
240 | self.e = '>'
241 | elif cpu_type == 2:
242 | self.e = '<'
243 | else:
244 | self.log.critical('Value of FAR: CPU_TYPE is not 1 or 2. Invalid endian.')
245 | raise IOError(cpu_type)
246 |
247 | @staticmethod
248 | def __get_multiplier(field, body):
249 | if field == 'SITE_NUM':
250 | return body['SITE_CNT'] # SDR (1, 80)
251 |
252 | elif field == 'PMR_INDX':
253 | return body['INDX_CNT'] # PGR (1, 62)
254 |
255 | elif field in ['GRP_INDX', 'GRP_MODE', 'GRP_RADX', 'PGM_CHAR', 'RTN_CHAR', 'PGM_CHAL', 'RTN_CHAL']:
256 | return body['GRP_CNT'] # PLR (1, 63)
257 |
258 | elif field in ['RTN_INDX', 'RTN_STAT']:
259 | return body['RTN_ICNT'] # FTR (15, 20)
260 |
261 | elif field in ['PGM_INDX', 'PGM_STAT']:
262 | return body['PGM_ICNT'] # FTR (15, 20)
263 |
264 | elif field in ['RTN_STAT', 'RTN_INDX']:
265 | return body['RTN_ICNT'] # MPR (15, 15)
266 |
267 | elif field in ['RTN_RSLT']:
268 | return body['RSLT_CNT'] # MPR (15, 15)
269 |
270 | elif field in ['UPD_NAM']:
271 | return body['UPD_CNT'] # VUR (0, 30)
272 |
273 | elif field in ["PAT_BGN", "PAT_END", "PAT_FILE", "PAT_FILE", "PAT_LBL", "FILE_UID", "ATPG_DSC", "SRC_ID"]:
274 | return body["LOCP_CNT"] # PSR (1, 90)
275 |
276 | elif field in ["PMR_INDX", "ATPG_NAM"]:
277 | return body["LOCM_CNT"] # NMR (1, 91)
278 |
279 | elif field in ["CHN_LIST"]:
280 | return body["CHN_CNT"] # SSR (1, 93)
281 |
282 | elif field in ["M_CLKS"]:
283 | return body["MSTR_CNT"] # CDR (1, 94)
284 |
285 | elif field in ["S_CLKS"]:
286 | return body["SLAV_CNT"] # CDR (1, 94)
287 |
288 | elif field in ["CELL_LST"]:
289 | return body["LST_CNT"] # CDR (1, 94)
290 |
291 | else:
292 | raise ValueError
293 |
294 | def __iter__(self):
295 | return self
296 |
297 | def __next__(self):
298 | r = self.read_record()
299 | if r:
300 | return r
301 | else:
302 | raise StopIteration
303 |
--------------------------------------------------------------------------------
/stdf/stdf_v4.json:
--------------------------------------------------------------------------------
1 | {
2 | "FAR": {
3 | "rec_typ": 0,
4 | "rec_sub": 10,
5 | "body": [
6 | ["CPU_TYPE", "U1"],
7 | ["STDF_VER", "U1"]
8 | ]
9 | },
10 |
11 | "ATR": {
12 | "rec_typ": 0,
13 | "rec_sub": 20,
14 | "body": [
15 | ["MOD_TIM", "U4"],
16 | ["CMD_LINE", "Cn"]
17 | ]
18 | },
19 |
20 | "VUR": {
21 | "rec_typ": 0,
22 | "rec_sub": 30,
23 | "body": [
24 | ["UPD_CNT", "U1"],
25 | ["UPD_NAM", "K0Cn"]
26 | ]
27 | },
28 |
29 | "MIR": {
30 | "rec_typ": 1,
31 | "rec_sub": 10,
32 | "body": [
33 | ["SETUP_T", "U4"],
34 | ["START_T", "U4"],
35 | ["STAT_NUM", "U1"],
36 | ["MODE_COD", "C1"],
37 | ["RTST_COD", "C1"],
38 | ["PROT_COD", "C1"],
39 | ["BURN_TIM", "U2"],
40 | ["CMOD_COD", "C1"],
41 | ["LOT_ID", "Cn"],
42 | ["PART_TYP", "Cn"],
43 | ["NODE_NAM", "Cn"],
44 | ["TSTR_TYP", "Cn"],
45 | ["JOB_NAM", "Cn"],
46 | ["JOB_REV", "Cn"],
47 | ["SBLOT_ID", "Cn"],
48 | ["OPER_NAM", "Cn"],
49 | ["EXEC_TYP", "Cn"],
50 | ["EXEC_VER", "Cn"],
51 | ["TEST_COD", "Cn"],
52 | ["TST_TEMP", "Cn"],
53 | ["USER_TXT", "Cn"],
54 | ["AUX_FILE", "Cn"],
55 | ["PKG_TYP", "Cn"],
56 | ["FAMLY_ID", "Cn"],
57 | ["DATE_COD", "Cn"],
58 | ["FACIL_ID", "Cn"],
59 | ["FLOOR_ID", "Cn"],
60 | ["PROC_ID", "Cn"],
61 | ["OPER_FRQ", "Cn"],
62 | ["SPEC_NAM", "Cn"],
63 | ["SPEC_VER", "Cn"],
64 | ["FLOW_ID", "Cn"],
65 | ["SETUP_ID", "Cn"],
66 | ["DSGN_REV", "Cn"],
67 | ["ENG_ID", "Cn"],
68 | ["ROM_COD", "Cn"],
69 | ["SERL_NUM", "Cn"],
70 | ["SUPR_NAM", "Cn"]
71 | ]
72 | },
73 |
74 | "MRR": {
75 | "rec_typ": 1,
76 | "rec_sub": 20,
77 | "body": [
78 | ["FINISH_T", "U4"],
79 | ["DISP_COD", "C1"],
80 | ["USR_DESC", "Cn"],
81 | ["EXC_DESC", "Cn"]
82 | ]
83 | },
84 |
85 | "PCR": {
86 | "rec_typ": 1,
87 | "rec_sub": 30,
88 | "body": [
89 | ["HEAD_NUM", "U1"],
90 | ["SITE_NUM", "U1"],
91 | ["PART_CNT", "U4"],
92 | ["RTST_CNT", "U4"],
93 | ["ABRT_CNT", "U4"],
94 | ["GOOD_CNT", "U4"],
95 | ["FUNC_CNT", "U4"]
96 | ]
97 | },
98 |
99 | "HBR": {
100 | "rec_typ": 1,
101 | "rec_sub": 40,
102 | "body": [
103 | ["HEAD_NUM", "U1"],
104 | ["SITE_NUM", "U1"],
105 | ["HBIN_NUM", "U2"],
106 | ["HBIN_CNT", "U4"],
107 | ["HBIN_PF", "C1"],
108 | ["HBIN_NAM", "Cn"]
109 | ]
110 | },
111 |
112 | "SBR": {
113 | "rec_typ": 1,
114 | "rec_sub": 50,
115 | "body": [
116 | ["HEAD_NUM", "U1"],
117 | ["SITE_NUM", "U1"],
118 | ["SBIN_NUM", "U2"],
119 | ["SBIN_CNT", "U4"],
120 | ["SBIN_PF", "C1"],
121 | ["SBIN_NAM", "Cn"]
122 | ]
123 | },
124 |
125 | "PMR": {
126 | "rec_typ": 1,
127 | "rec_sub": 60,
128 | "body": [
129 | ["PMR_INDX", "U2"],
130 | ["CHAN_TYP", "U2"],
131 | ["CHAN_NAM", "Cn"],
132 | ["PHY_NAM", "Cn"],
133 | ["LOG_NAM", "Cn"],
134 | ["HEAD_NUM", "U1"],
135 | ["SITE_NUM", "U1"]
136 | ]
137 | },
138 |
139 | "PGR": {
140 | "rec_typ": 1,
141 | "rec_sub": 62,
142 | "body": [
143 | ["GRP_INDX", "U2"],
144 | ["GRP_NAM", "Cn"],
145 | ["INDX_CNT", "U2"],
146 | ["PMR_INDX", "K0U2"]
147 | ]
148 | },
149 |
150 | "PLR": {
151 | "rec_typ": 1,
152 | "rec_sub": 63,
153 | "body": [
154 | ["GRP_CNT", "U2"],
155 | ["GRP_INDX", "K0U2"],
156 | ["GRP_MODE", "K0U2"],
157 | ["GRP_RADX", "K0U1"],
158 | ["PGM_CHAR", "K0Cn"],
159 | ["RTN_CHAR", "K0Cn"],
160 | ["PGM_CHAL", "K0Cn"],
161 | ["RTN_CHAL", "K0Cn"]
162 | ]
163 | },
164 |
165 | "RDR": {
166 | "rec_typ": 1,
167 | "rec_sub": 70,
168 | "body": [
169 | ["NUM_BINS", "U2"],
170 | ["RTST_BIN", "K0U2"]
171 | ]
172 | },
173 |
174 | "SDR": {
175 | "rec_typ": 1,
176 | "rec_sub": 80,
177 | "body": [
178 | ["HEAD_NUM", "U1"],
179 | ["SITE_GRP", "U1"],
180 | ["SITE_CNT", "U1"],
181 | ["SITE_NUM", "K0U1"],
182 | ["HAND_TYP", "Cn"],
183 | ["HAND_ID", "Cn"],
184 | ["CARD_TYP", "Cn"],
185 | ["CARD_ID", "Cn"],
186 | ["LOAD_TYP", "Cn"],
187 | ["LOAD_ID", "Cn"],
188 | ["DIB_TYP", "Cn"],
189 | ["DIB_ID", "Cn"],
190 | ["CABL_TYP", "Cn"],
191 | ["CABL_ID", "Cn"],
192 | ["CONT_TYP", "Cn"],
193 | ["CONT_ID", "Cn"],
194 | ["LASR_TYP", "Cn"],
195 | ["LASR_ID", "Cn"],
196 | ["EXTR_TYP", "Cn"],
197 | ["EXTR_ID", "Cn"]
198 | ]
199 | },
200 |
201 | "PSR": {
202 | "rec_typ": 1,
203 | "rec_sub": 90,
204 | "body": [
205 | ["CONT_FLG", "B1"],
206 | ["PSR_INDX", "U2"],
207 | ["PSR_NAM", "Cn"],
208 | ["OPT_FLG", "B1"],
209 | ["TOTP_CNT", "U2"],
210 | ["LOCP_CNT", "U2"],
211 | ["PAT_BGN", "K0U8"],
212 | ["PAT_END", "K0U8"],
213 | ["PAT_FILE", "K0Cn"],
214 | ["PAT_FILE", "K0Cn"],
215 | ["PAT_LBL", "K0Cn"],
216 | ["FILE_UID", "K0Cn"],
217 | ["ATPG_DSC", "K0Cn"],
218 | ["SRC_ID", "K0Cn"]
219 | ]
220 | },
221 |
222 | "NMR": {
223 | "rec_typ": 1,
224 | "rec_sub": 91,
225 | "body": [
226 | ["CONT_FLG", "B1"],
227 | ["NMR_INDX", "U2"],
228 | ["TOTM_CNT", "U2"],
229 | ["LOCM_CNT", "U2"],
230 | ["PMR_INDX", "K0U2"],
231 | ["ATPG_NAM", "K0Cn"]
232 | ]
233 | },
234 |
235 | "CNR": {
236 | "rec_typ": 1,
237 | "rec_sub": 92,
238 | "body": [
239 | ["CHN_NUM", "U2"],
240 | ["BIT_POS", "U4"],
241 | ["CELL_NAM", "Sn"]
242 | ]
243 | },
244 |
245 | "SSR": {
246 | "rec_typ": 1,
247 | "rec_sub": 93,
248 | "body": [
249 | ["SSR_NAM", "Cn"],
250 | ["CHN_CNT", "U2"],
251 | ["CHN_LIST", "K0U2"]
252 | ]
253 | },
254 |
255 | "CDR": {
256 | "rec_typ": 1,
257 | "rec_sub": 94,
258 | "body": [
259 | ["CONT_FLG", "B1"],
260 | ["CDR_INDX", "U2"],
261 | ["CHN_NAM", "Cn"],
262 | ["CHN_LEN", "U4"],
263 | ["SIN_PIN", "U2"],
264 | ["SOUT_PIN", "U2"],
265 | ["MSTR_CNT", "U1"],
266 | ["M_CLKS", "K0U2"],
267 | ["SLAV_CNT", "U1"],
268 | ["S_CLKS", "K0U2"],
269 | ["INV_VAL", "U1"],
270 | ["LST_CNT", "U2"],
271 | ["CELL_LST", "K0Sn"]
272 | ]
273 | },
274 |
275 | "WIR": {
276 | "rec_typ": 2,
277 | "rec_sub": 10,
278 | "body": [
279 | ["HEAD_NUM", "U1"],
280 | ["SITE_GRP", "U1"],
281 | ["START_T", "U4"],
282 | ["WAFER_ID", "Cn"]
283 | ]
284 | },
285 |
286 | "WRR": {
287 | "rec_typ": 2,
288 | "rec_sub": 20,
289 | "body": [
290 | ["HEAD_NUM", "U1"],
291 | ["SITE_GRP", "U1"],
292 | ["FINISH_T", "U4"],
293 | ["PART_CNT", "U4"],
294 | ["RTST_CNT", "U4"],
295 | ["ABRT_CNT", "U4"],
296 | ["GOOD_CNT", "U4"],
297 | ["FUNC_CNT", "U4"],
298 | ["WAFER_ID", "Cn"],
299 | ["FABWF_ID", "Cn"],
300 | ["FRAME_ID", "Cn"],
301 | ["MASK_ID", "Cn"],
302 | ["USR_DESC", "Cn"],
303 | ["EXC_DESC", "Cn"]
304 | ]
305 | },
306 |
307 | "WCR": {
308 | "rec_typ": 2,
309 | "rec_sub": 30,
310 | "body": [
311 | ["WAFR_SIZ", "R4"],
312 | ["DIE_HT", "R4"],
313 | ["DIE_WID", "R4"],
314 | ["WF_UNITS", "U1"],
315 | ["WF_FLAT", "C1"],
316 | ["CENTER_X", "I2"],
317 | ["CENTER_Y", "I2"],
318 | ["POS_X", "C1"],
319 | ["POS_Y", "C1"]
320 | ]
321 | },
322 |
323 | "PIR": {
324 | "rec_typ": 5,
325 | "rec_sub": 10,
326 | "body": [
327 | ["HEAD_NUM", "U1"],
328 | ["SITE_NUM", "U1"]
329 | ]
330 | },
331 |
332 | "PRR": {
333 | "rec_typ": 5,
334 | "rec_sub": 20,
335 | "body": [
336 | ["HEAD_NUM", "U1"],
337 | ["SITE_NUM", "U1"],
338 | ["PART_FLG", "B1"],
339 | ["NUM_TEST", "U2"],
340 | ["HARD_BIN", "U2"],
341 | ["SOFT_BIN", "U2"],
342 | ["X_COORD", "I2"],
343 | ["Y_COORD", "I2"],
344 | ["TEST_T", "U4"],
345 | ["PART_ID", "Cn"],
346 | ["PART_TXT", "Cn"],
347 | ["PART_FIX", "Bn"]
348 | ]
349 | },
350 |
351 | "TSR": {
352 | "rec_typ": 10,
353 | "rec_sub": 30,
354 | "body": [
355 | ["HEAD_NUM", "U1"],
356 | ["SITE_NUM", "U1"],
357 | ["TEST_TYP", "C1"],
358 | ["TEST_NUM", "U4"],
359 | ["EXEC_CNT", "U4"],
360 | ["FAIL_CNT", "U4"],
361 | ["ALRM_CNT", "U4"],
362 | ["TEST_NAM", "Cn"],
363 | ["SEQ_NAME", "Cn"],
364 | ["TEST_LBL", "Cn"],
365 | ["OPT_FLAG", "B1"],
366 | ["TEST_TIM", "R4"],
367 | ["TEST_MIN", "R4"],
368 | ["TEST_MAX", "R4"],
369 | ["TST_SUMS", "R4"],
370 | ["TST_SQRS", "R4"]
371 | ]
372 | },
373 |
374 | "PTR": {
375 | "rec_typ": 15,
376 | "rec_sub": 10,
377 | "body": [
378 | ["TEST_NUM","U4"],
379 | ["HEAD_NUM","U1"],
380 | ["SITE_NUM","U1"],
381 | ["TEST_FLG","B1"],
382 | ["PARM_FLG","B1"],
383 | ["RESULT","R4"],
384 | ["TEST_TXT","Cn"],
385 | ["ALARM_ID","Cn"],
386 | ["OPT_FLAG","B1"],
387 | ["RES_SCAL","I1"],
388 | ["LLM_SCAL","I1"],
389 | ["HLM_SCAL","I1"],
390 | ["LO_LIMIT","R4"],
391 | ["HI_LIMIT","R4"],
392 | ["UNITS","Cn"],
393 | ["C_RESFMT","Cn"],
394 | ["C_LLMFMT","Cn"],
395 | ["C_HLMFMT","Cn"],
396 | ["LO_SPEC","R4"],
397 | ["HI_SPEC","R4"]
398 | ]
399 | },
400 |
401 | "MPR": {
402 | "rec_typ": 15,
403 | "rec_sub": 15,
404 | "body": [
405 | ["TEST_NUM","U4"],
406 | ["HEAD_NUM","U1"],
407 | ["SITE_NUM","U1"],
408 | ["TEST_FLG","B1"],
409 | ["PARM_FLG","B1"],
410 | ["RTN_ICNT","U2"],
411 | ["RSLT_CNT","U2"],
412 | ["RTN_STAT","K0N1"],
413 | ["RTN_RSLT","K0R4"],
414 | ["TEST_TXT","Cn"],
415 | ["ALARM_ID","Cn"],
416 | ["OPT_FLAG","B1"],
417 | ["RES_SCAL","I1"],
418 | ["LLM_SCAL","I1"],
419 | ["HLM_SCAL","I1"],
420 | ["LO_LIMIT","R4"],
421 | ["HI_LIMIT","R4"],
422 | ["START_IN","R4"],
423 | ["INCR_IN","R4"],
424 | ["RTN_INDX","K0U2"],
425 | ["UNITS","Cn"],
426 | ["UNITS_IN","Cn"],
427 | ["C_RESFMT","Cn"],
428 | ["C_LLMFMT","Cn"],
429 | ["C_HLMFMT","Cn"],
430 | ["LO_SPEC","R4"],
431 | ["HI_SPEC","R4"]
432 | ]
433 | },
434 |
435 | "FTR": {
436 | "rec_typ": 15,
437 | "rec_sub": 20,
438 | "body": [
439 | ["TEST_NUM","U4"],
440 | ["HEAD_NUM","U1"],
441 | ["SITE_NUM","U1"],
442 | ["TEST_FLG","B1"],
443 | ["OPT_FLAG","B1"],
444 | ["CYCL_CNT","U4"],
445 | ["REL_VADR","U4"],
446 | ["REPT_CNT","U4"],
447 | ["NUM_FAIL","U4"],
448 | ["XFAIL_AD","I4"],
449 | ["YFAIL_AD","I4"],
450 | ["VECT_OFF","I2"],
451 | ["RTN_ICNT","U2"],
452 | ["PGM_ICNT","U2"],
453 | ["RTN_INDX","K0U2"],
454 | ["RTN_STAT","K0N1"],
455 | ["PGM_INDX","K0U2"],
456 | ["PGM_STAT","K0N1"],
457 | ["FAIL_PIN","Dn"],
458 | ["VECT_NAM","Cn"],
459 | ["TIME_SET","Cn"],
460 | ["OP_CODE","Cn"],
461 | ["TEST_TXT","Cn"],
462 | ["ALARM_ID","Cn"],
463 | ["PROG_TXT","Cn"],
464 | ["RSLT_TXT","Cn"],
465 | ["PATG_NUM","U1"],
466 | ["SPIN_MAP","Dn"]
467 | ]
468 | },
469 |
470 | "STR": {
471 | "rec_typ": 15,
472 | "rec_sub": 30,
473 | "body": [
474 | ["HEAD_NUM","U1"],
475 | ["SITE_NUM","U1"],
476 | ["TEST_TYP","C1"],
477 | ["TEST_NUM","U4"],
478 | ["EXEC_CNT","U4"],
479 | ["FAIL_CNT","U4"],
480 | ["ALRM_CNT","U4"],
481 | ["TEST_NAM","Cn"],
482 | ["SEQ_NAME","Cn"],
483 | ["TEST_LBL","Cn"],
484 | ["OPT_FLAG","B1"],
485 | ["TEST_TIM","R4"],
486 | ["TEST_MIN","R4"],
487 | ["TEST_MAX","R4"],
488 | ["TST_SUMS","R4"],
489 | ["TST_SQRS","R4"]
490 | ]
491 | },
492 |
493 | "BPS": {
494 | "rec_typ": 20,
495 | "rec_sub": 10,
496 | "body": [
497 | ["SEQ_NAME","Cn"]
498 | ]
499 | },
500 |
501 | "EPS": {
502 | "rec_typ": 20,
503 | "rec_sub": 20,
504 | "body": [
505 |
506 | ]
507 | },
508 |
509 | "GDR": {
510 | "rec_typ": 50,
511 | "rec_sub": 10,
512 | "body": [
513 | ["GEN_DATA", "Vn"]
514 | ]
515 | },
516 |
517 | "DTR": {
518 | "rec_typ": 50,
519 | "rec_sub": 30,
520 | "body": [
521 | ["TEXT_DAT", "Cn"]
522 | ]
523 | }
524 |
525 | }
--------------------------------------------------------------------------------