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
|
383
|
59 class LayoutLexer(BaseLexer):
|
|
60 def __init__(self):
|
|
61 tok_spec = [
|
|
62 ('HEXNUMBER', r'0x[\da-fA-F]+', self.handle_number),
|
|
63 ('NUMBER', r'\d+', self.handle_number),
|
|
64 ('ID', r'[A-Za-z][A-Za-z\d_]*', self.handle_id),
|
|
65 ('SKIP', r'[ \t\r\n]', None),
|
|
66 ('LEESTEKEN', r':=|[\.,=:\-+*\[\]/\(\)]|>=|<=|<>|>|<|}|{', lambda typ, val: (val, val)),
|
|
67 ('STRING', r"'.*?'", lambda typ, val: (typ, val[1:-1])),
|
|
68 ]
|
|
69 super().__init__(tok_spec)
|
|
70 self.kws = ['MEMORY', 'ALIGN', 'LOCATION','SECTION','SIZE']
|
|
71
|
|
72 def handle_id(self, typ, val):
|
|
73 if val in self.kws:
|
|
74 typ = val
|
|
75 return typ, val
|
|
76
|
|
77 def handle_number(self, typ, val):
|
|
78 val = make_num(val)
|
|
79 typ = 'NUMBER'
|
|
80 return typ, val
|
382
|
81
|
|
82
|
|
83 class LayoutParser:
|
383
|
84 def __init__(self, kws):
|
|
85 toks = ['ID', 'NUMBER', '{', '}', '.', ':', '=', '(', ')', pyyacc.EPS, pyyacc.EOF] + kws
|
382
|
86 g = pyyacc.Grammar(toks)
|
383
|
87 g.add_production('layout', ['mem_list'])
|
|
88 g.add_one_or_more('mem', 'mem_list')
|
|
89 g.add_production('mem', ['MEMORY', 'ID', 'LOCATION', '=', 'NUMBER', 'SIZE', '=', 'NUMBER', '{', 'input_list', '}'], self.handle_mem)
|
|
90 g.add_one_or_more('input', 'input_list')
|
|
91 g.add_production('input', ['ALIGN', '(', 'NUMBER', ')'], self.handle_align)
|
|
92 g.add_production('input', ['SECTION', '(', 'ID', ')'], self.handle_section)
|
|
93
|
|
94 g.start_symbol = 'layout'
|
|
95 self.p = g.generate_parser()
|
|
96
|
|
97 def parse(self, lexer, layout):
|
|
98 self.layout = layout
|
|
99 self.p.parse(lexer)
|
|
100
|
|
101 def handle_mem(self, mem_tag, mem_name, loc_tag, eq1, loc, size_tag, eq2, size, lbrace, inps, rbrace):
|
|
102 m = Memory(mem_name.val)
|
|
103 m.size = size.val
|
|
104 m.location = loc.val
|
|
105 for inp in inps:
|
|
106 m.add_input(inp)
|
|
107 self.layout.add_memory(m)
|
|
108
|
|
109 def handle_align(self, align_tag, lbrace, alignment, rbrace):
|
|
110 return Align(alignment.val)
|
|
111
|
|
112 def handle_section(self, section_tag, lbrace, section_name, rbrace):
|
|
113 return Section(section_name.val)
|
382
|
114
|
|
115
|
383
|
116 class LayoutLoader:
|
|
117 def __init__(self):
|
|
118 self.lexer = LayoutLexer()
|
|
119 self.parser = LayoutParser(self.lexer.kws)
|
382
|
120
|
383
|
121 def load_layout(self, f):
|
|
122 layout = Layout()
|
|
123 self.lexer.feed(f.read()) # TODO: perhaps the read is better in the lexer?
|
|
124 self.parser.parse(self.lexer, layout)
|
|
125 return layout
|
|
126
|
|
127 # Single definition:
|
|
128 _lloader = LayoutLoader()
|
|
129
|
|
130
|
|
131 def load_layout(f):
|
|
132 return _lloader.load_layout(f)
|
|
133
|