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