7f3e54c79d8abcc7008a48108c5fb0761ea4cb01
1 #
2 # Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions an
14 # limitations under the License.
15 #
16 #
17 # Utility functions for LASM
18 #
19 # Common functions used in main entry and command parser
20 #
22 import inspect
24 segment_addr = 0
25 sram_addr = 0
26 MAX_SRAM_SIZE = 96
28 segments = {} # { "segment":address}
29 labels = {} # { "key":address }
30 errors = {} # { command: error }
31 codes = [] # output program code
32 INVALID_ADDR = 0xFF
34 LF = '\n'
35 CRLF = '\r\n'
38 #
39 # Error handling functions
40 #
42 # Make error format
43 def put_error(command, message):
44 errors.update({command: message})
47 # Print out errors
48 def report_error(ln, line):
49 for cmd, msg in errors.iteritems():
50 print """
51 Error! Line number: %d
52 %s
53 %s %s
54 """ % (ln, line, cmd, msg)
57 #
58 # Segment functions
59 #
61 # Initialize segment list
62 def init_segment():
63 global segment_addr, segments
64 segment_addr = 0
65 segments = {}
68 # Add segment structure
69 # Format: { segment name:address }
70 def add_segment_list(name):
71 global segment_addr
72 segment_addr = get_sram_address()
73 segments.update({name: segment_addr})
76 # Return the address of the latest segment
77 def get_segment_address():
78 global segment_addr
79 return segment_addr
82 #
83 # SRAM functions
84 #
86 # Initialize SRAM
87 def init_sram_address():
88 global sram_addr
89 sram_addr = 0
92 # Increase SRAM address
93 def inc_sram_address():
94 global sram_addr
95 sram_addr += 1
98 # Get SRAM address
99 def get_sram_address():
100 global sram_addr
101 return sram_addr
104 #
105 # Program engine code functions
106 #
108 # Initialize code
109 def init_code():
110 global codes
111 codes = []
114 # Put word bytes
115 def put_code(word):
116 codes.append((word & 0xFF00) >> 8)
117 codes.append(word & 0x00FF)
118 inc_sram_address()
121 #
122 # Label functions
123 #
125 # Initialize label list
126 def init_label_list():
127 global labels
128 labels = {}
131 # Add label information
132 # Format: { label name:address }
133 def add_label_list(key):
134 addr = get_sram_address()
135 labels.update({key: addr})
138 # Get address of label
139 # Invalid address returns if the label is not found
140 def get_address_of_label(label, func_name):
141 for key in labels:
142 if label == key:
143 return labels.get(key)
145 if not func_name:
146 func_name = get_caller_func_name()
148 put_error(func_name, 'can not find %s' % label)
149 return INVALID_ADDR
152 # Calculate offset address
153 # Returns (label address - segment address)
154 def get_offset_address_of_label(key):
155 addr = get_address_of_label(key, get_caller_func_name())
156 if addr == INVALID_ADDR:
157 return INVALID_ADDR
159 offset = addr - get_segment_address()
160 if offset < 0:
161 return INVALID_ADDR
163 return offset
166 # Trace the stack to get name of the caller
167 def get_caller_func_name():
168 return inspect.stack()[2][3]
171 #
172 # Output file generation functions
173 #
175 # Convert value to binary type - fill with zeros
176 def bin_format(val, bit):
177 return '{:b}'.format(val).zfill(bit)
180 # Convert value to hex type - fill with zero
181 def hex_format(val):
182 return '{:X}'.format(val).zfill(2)
185 # Generate binary file
186 # Format:
187 # segment code
188 # sram code (up to 96 * 2 byte)
189 def generate_bin(src):
190 fname = src[:-3] + 'bin'
191 f = open(fname, 'w')
193 # Update segment code
194 for item in segments:
195 bits = bin_format(segments.get(item), 8)
196 f.write(bits)
197 f.write(LF)
199 # Fill the default segment value
200 MAX_SEGMENTS = 3
201 DEFAULT_SEG_VAL = MAX_SRAM_SIZE - 1
202 for x in range(len(segments), MAX_SEGMENTS):
203 bits = bin_format(DEFAULT_SEG_VAL, 8)
204 f.write(bits)
205 f.write(LF)
207 # Update word code
208 count = 0
209 sram_size = 0
210 for x in codes:
211 bits = bin_format(x, 8)
212 f.write(bits)
213 count += 1
214 if count % 2 == 0:
215 f.write(LF)
216 sram_size += 1
218 # Fill zero for last area
219 for n in range(sram_size, MAX_SRAM_SIZE):
220 f.write(bin_format(0, 16))
221 f.write(LF)
223 f.close()
226 # Generate hex file
227 # Format:
228 # sram code (up to 96 * 2 byte)
229 # @ <segment address> <segment name>
230 def generate_hex(src):
231 fname = src[:-3] + 'hex'
232 f = open(fname, 'w')
234 # Update byte code
235 count = 0
236 sram_size = 0
237 for x in codes:
238 f.write(hex_format(x))
239 f.write(' ')
240 count += 1
241 if count % 2 == 0:
242 sram_size += 1
243 if count % 16 == 0:
244 f.write(CRLF)
246 # Fill zero for last area
247 for n in range(sram_size, MAX_SRAM_SIZE):
248 for a in range(0, 2): # make two bytes
249 f.write(hex_format(0))
250 f.write(' ')
251 count += 1
252 if count % 16 == 0:
253 f.write(CRLF)
255 # Update segment code
256 for item in segments:
257 code = hex_format(segments.get(item))
258 form = "@ %s %s" % (code, item)
259 f.write(form)
260 f.write(CRLF)
262 f.close()
265 #
266 # Other utils
267 #
269 # Get number type by reading suffix
270 def number_type(val):
271 return val[-1]
274 # Check the value is float type or not
275 def is_float(val):
276 try:
277 float(val)
278 return True
279 except ValueError:
280 return False
283 # XXXXb or XXXXB is binary
284 # XXXXh or XXXXH is hex
285 # XXXX is decimal
286 def format_number(val):
287 t = number_type(val)
288 if t == "b" or t == "B": # binary
289 code = int(val[:-1], 2)
290 elif t == "h" or t == "H": # hex
291 code = int(val[:-1], 16)
292 else: # decimal
293 code = int(val, 10)
294 return code