• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2
3import argparse
4import re
5
6
7class Layout(object):
8    def __init__(self, layout, variant=None):
9        self.layout = layout
10        self.variant = variant
11        if '(' in layout:
12            assert variant is None
13            # parse a layout(variant) string
14            match = re.match(r'([^(]+)\(([^)]+)\)', layout)
15            self.layout = match.groups()[0]
16            self.variant = match.groups()[1]
17
18    def __str__(self):
19        if self.variant:
20            return '{}({})'.format(self.layout, self.variant)
21        else:
22            return '{}'.format(self.layout)
23
24
25def read_file(path):
26    '''Returns a list of two-layout tuples [(layout1, layout2), ...]'''
27
28    # This parses both input files, one with two elements, one with four elements,
29    # all separated by tabs
30    pattern = re.compile(r'([^\t]+)\s+([^\t]+)\s*([^\t]*)\s*([^\t]*)')
31
32    layouts = []
33    for line in open(path):
34        match = re.match(pattern, line.strip())
35        groups = [g for g in match.groups() if g]  # drop empty groups
36        if len(groups) == 2:
37            l1 = Layout(groups[0])
38            l2 = Layout(groups[1])
39        else:
40            l1 = Layout(groups[0], groups[1])
41            l2 = Layout(groups[2], groups[3])
42        layouts.append((l1, l2))
43    return layouts
44
45
46# ml_s
47def write_fixed_layout(dest, mappings, write_header):
48    if write_header:
49        dest.write('! model		layout				=	symbols\n')
50    for l1, l2 in mappings:
51        dest.write('  *		{}			=	pc+{}\n'.format(l1, l2))
52
53
54# mln_s
55def write_layout_n(dest, mappings, number, write_header):
56    if write_header:
57        dest.write('! model		layout[{}]	=	symbols\n'.format(number))
58
59    # symbols is one of
60    #   +layout(variant):2 ... where the map-to-layout has a proper variant
61    #   +layout%(v[2]):2 ... where the map-to-layout does not have a variant
62    # and where the number is 1, we have a base and drop the suffix, i.e.
63    # the above becomes
64    #   pc+layout(variant)
65    #   pc+layout%(v[1])
66
67    base = 'pc' if number == 1 else ''
68    suffix = '' if number == 1 else ':{}'.format(number)
69
70    for l1, l2 in mappings:
71        second_layout = str(l2) if l2.variant else '{}%(v[{}])'.format(l2.layout, number)
72        dest.write('  *		{}		=	{}+{}{}\n'.format(l1, base, second_layout, suffix))
73
74
75# mlv_s
76def write_fixed_layout_variant(dest, mappings, write_header):
77    if write_header:
78        dest.write('! model		layout		variant		=	symbols\n')
79    for l1, l2 in mappings:
80        dest.write('  *		{}		{}		=	pc+{}\n'.format(l1.layout, l1.variant, l2))
81
82
83# mlnvn_s
84def write_layout_n_variant_n(dest, mappings, number, write_header):
85    if write_header:
86        dest.write('! model		layout[{}]	variant[{}]	=	symbols\n'.format(number, number))
87
88    # symbols is
89    #   +layout(variant):2
90    # and where the number is 1, we have a base and drop the suffix, i.e.
91    # the above becomes
92    #   pc+layout(variant)
93    # This part is only executed for the variantMappings.lst
94
95    base = 'pc' if number == 1 else ''
96    suffix = '' if number == 1 else ':{}'.format(number)
97
98    for l1, l2 in mappings:
99        second_layout = str(l2) if l2.variant else '{}%(v[{}])'.format(l2.layout, number)
100        dest.write('  *		{}		{}	=	{}+{}{}\n'.format(l1.layout, l1.variant, base, second_layout, suffix))
101
102
103def map_variant(dest, files, want='mls', number=None):
104    for idx, f in enumerate(files):
105        write_header = idx == 0
106
107        mappings = read_file(f)
108        if want == 'mls':
109            if number is None:
110                write_fixed_layout(dest, mappings, write_header)
111            else:
112                write_layout_n(dest, mappings, number, write_header)
113        elif want == 'mlvs':
114            if number is None:
115                write_fixed_layout_variant(dest, mappings, write_header)
116            else:
117                write_layout_n_variant_n(dest, mappings, number, write_header)
118        else:
119            raise NotImplementedError()
120
121
122if __name__ == '__main__':
123    parser = argparse.ArgumentParser('variant mapping script')
124    parser.add_argument('--want', type=str,
125                        choices=['mls', 'mlvs'])
126    parser.add_argument('--number', type=int, default=None)
127
128    parser.add_argument('dest', type=str)
129    parser.add_argument('files', nargs='+', type=str)
130    ns = parser.parse_args()
131
132    with open(ns.dest, 'w') as fd:
133        map_variant(fd, ns.files, ns.want, ns.number)
134