Mercurial > lcfOS
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 |