383
|
1 from baselex import BaseLexer
|
|
2 import pyyacc
|
|
3 from . import make_num
|
|
4
|
382
|
5
|
|
6 class Layout:
|
|
7 def __init__(self):
|
|
8 self.mems = []
|
|
9
|
383
|
10 def add_memory(self, memory):
|
|
11 self.mems.append(memory)
|
|
12
|
382
|
13 def __eq__(self, other):
|
|
14 return self.mems == other.mems
|
|
15
|
383
|
16 def __repr__(self):
|
|
17 return str(self.mems)
|
|
18
|
382
|
19
|
|
20 class Memory:
|
383
|
21 def __init__(self, name):
|
382
|
22 self.inputs = []
|
383
|
23 self.name = name
|
|
24 self.location = 0x0
|
382
|
25 self.size = 0x0
|
|
26
|
|
27 def add_input(self, inp):
|
|
28 assert isinstance(inp, Input)
|
|
29 self.inputs.append(inp)
|
|
30
|
383
|
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)
|
382
|
36
|
|
37 class Input:
|
|
38 pass
|
|
39
|
|
40
|
383
|
41 class Section(Input):
|
382
|
42 def __init__(self, section_name):
|
|
43 self.section_name = section_name
|
|
44
|
383
|
45 def __repr__(self):
|
|
46 return 'Section({})'.format(self.section_name)
|
382
|
47
|
383
|
48
|
|
49 class Align(Input):
|
|
50 def __init__(self, alignment):
|
|
51 self.alignment = alignment
|
|
52
|
|
53 def __repr__(self):
|
|
54 return 'Align({})'.format(self.alignment)
|
382
|
55
|
|
56
|
383
|
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
|
382
|
79
|
|
80
|
|
81 class LayoutParser:
|
383
|
82 def __init__(self, kws):
|
|
83 toks = ['ID', 'NUMBER', '{', '}', '.', ':', '=', '(', ')', pyyacc.EPS, pyyacc.EOF] + kws
|
382
|
84 g = pyyacc.Grammar(toks)
|
383
|
85 g.add_production('layout', ['mem_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)
|
382
|
112
|
|
113
|
383
|
114 class LayoutLoader:
|
|
115 def __init__(self):
|
|
116 self.lexer = LayoutLexer()
|
|
117 self.parser = LayoutParser(self.lexer.kws)
|
382
|
118
|
383
|
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
|