comparison python/ppci/layout.py @ 383:173e20a47fda

Added linker description loader
author Windel Bouwman
date Sun, 27 Apr 2014 17:40:39 +0200
parents 0c44e494ef58
children d056b552d3f4
comparison
equal deleted inserted replaced
382:0c44e494ef58 383:173e20a47fda
1 from baselex import BaseLexer
2 import pyyacc
3 from . import make_num
4
1 5
2 class Layout: 6 class Layout:
3 def __init__(self): 7 def __init__(self):
4 self.mems = [] 8 self.mems = []
5 9
10 def add_memory(self, memory):
11 self.mems.append(memory)
12
6 def __eq__(self, other): 13 def __eq__(self, other):
7 return self.mems == other.mems 14 return self.mems == other.mems
8 15
16 def __repr__(self):
17 return str(self.mems)
18
9 19
10 class Memory: 20 class Memory:
11 def __init__(self, address=0x0): 21 def __init__(self, name):
12 self.inputs = [] 22 self.inputs = []
13 self.address = address 23 self.name = name
24 self.location = 0x0
14 self.size = 0x0 25 self.size = 0x0
15 26
16 def add_input(self, inp): 27 def add_input(self, inp):
17 assert isinstance(inp, Input) 28 assert isinstance(inp, Input)
18 self.inputs.append(inp) 29 self.inputs.append(inp)
19 30
31 def __repr__(self):
32 return 'MEM {} loc={:08X} size={:08X}'.format(self.name, self.location, self.size) + str(self.inputs)
33
34 def __eq__(self, other):
35 return str(self) == str(other)
20 36
21 class Input: 37 class Input:
22 pass 38 pass
23 39
24 40
25 class SectionInput(Input): 41 class Section(Input):
26 def __init__(self, section_name): 42 def __init__(self, section_name):
27 self.section_name = section_name 43 self.section_name = section_name
28 44
29 45 def __repr__(self):
30 def load_layout(f): 46 return 'Section({})'.format(self.section_name)
31 return deserialize(json.load(f))
32 47
33 48
34 def make_int(txt): 49 class Align(Input):
35 if txt.startswith('0x'): 50 def __init__(self, alignment):
36 return int(txt[2:], 16) 51 self.alignment = alignment
37 else: 52
38 return int(txt) 53 def __repr__(self):
54 return 'Align({})'.format(self.alignment)
55
56
57 class LayoutLexer(BaseLexer):
58 def __init__(self):
59 tok_spec = [
60 ('HEXNUMBER', r'0x[\da-fA-F]+', self.handle_number),
61 ('NUMBER', r'\d+', self.handle_number),
62 ('ID', r'[A-Za-z][A-Za-z\d_]*', self.handle_id),
63 ('SKIP', r'[ \t\r\n]', None),
64 ('LEESTEKEN', r':=|[\.,=:\-+*\[\]/\(\)]|>=|<=|<>|>|<|}|{', lambda typ, val: (val, val)),
65 ('STRING', r"'.*?'", lambda typ, val: (typ, val[1:-1])),
66 ]
67 super().__init__(tok_spec)
68 self.kws = ['MEMORY', 'ALIGN', 'LOCATION','SECTION','SIZE']
69
70 def handle_id(self, typ, val):
71 if val in self.kws:
72 typ = val
73 return typ, val
74
75 def handle_number(self, typ, val):
76 val = make_num(val)
77 typ = 'NUMBER'
78 return typ, val
39 79
40 80
41 class LayoutParser: 81 class LayoutParser:
42 def __init__(self): 82 def __init__(self, kws):
43 toks = ['ID', '{', '}', 'MEMORY', 'ALIGN', '.', pyyacc.EPS, pyyacc.EOF] 83 toks = ['ID', 'NUMBER', '{', '}', '.', ':', '=', '(', ')', pyyacc.EPS, pyyacc.EOF] + kws
44 g = pyyacc.Grammar(toks) 84 g = pyyacc.Grammar(toks)
45 g.add_production('layout', ['MEMORY', '{', 'input_list', '}']) 85 g.add_production('layout', ['mem_list'])
46 g.add_production('input_list', ['MEMORY', '{', 'input_list', '}']) 86 g.add_one_or_more('mem', 'mem_list')
87 g.add_production('mem', ['MEMORY', 'ID', 'LOCATION', '=', 'NUMBER', 'SIZE', '=', 'NUMBER', '{', 'input_list', '}'], self.handle_mem)
88 g.add_one_or_more('input', 'input_list')
89 g.add_production('input', ['ALIGN', '(', 'NUMBER', ')'], self.handle_align)
90 g.add_production('input', ['SECTION', '(', 'ID', ')'], self.handle_section)
91
92 g.start_symbol = 'layout'
93 self.p = g.generate_parser()
94
95 def parse(self, lexer, layout):
96 self.layout = layout
97 self.p.parse(lexer)
98
99 def handle_mem(self, mem_tag, mem_name, loc_tag, eq1, loc, size_tag, eq2, size, lbrace, inps, rbrace):
100 m = Memory(mem_name.val)
101 m.size = size.val
102 m.location = loc.val
103 for inp in inps:
104 m.add_input(inp)
105 self.layout.add_memory(m)
106
107 def handle_align(self, align_tag, lbrace, alignment, rbrace):
108 return Align(alignment.val)
109
110 def handle_section(self, section_tag, lbrace, section_name, rbrace):
111 return Section(section_name.val)
47 112
48 113
49 def deserialize(d): 114 class LayoutLoader:
50 layout = Layout() 115 def __init__(self):
51 for mem_node in d['memories']: 116 self.lexer = LayoutLexer()
52 m = Memory() 117 self.parser = LayoutParser(self.lexer.kws)
53 m.address = make_int(mem_node['address'])
54 m.size = make_int(mem_node['size'])
55 for input_node in mem_node['inputs']:
56 pass
57 return layout
58 118
119 def load_layout(self, f):
120 layout = Layout()
121 self.lexer.feed(f.read()) # TODO: perhaps the read is better in the lexer?
122 self.parser.parse(self.lexer, layout)
123 return layout
124
125 # Single definition:
126 _lloader = LayoutLoader()
127
128
129 def load_layout(f):
130 return _lloader.load_layout(f)
131