SymbolTable.py revision 6657
1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
2# Copyright (c) 2009 The Hewlett-Packard Development Company
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28from m5.util import code_formatter
29
30from slicc.generate import html
31from slicc.symbols.StateMachine import StateMachine
32from slicc.symbols.Type import Type
33from slicc.util import Location
34
35class SymbolTable(object):
36    def __init__(self):
37        self.sym_vec = []
38        self.sym_map_vec = [ {} ]
39        self.machine_components = {}
40
41        pairs = {}
42        pairs["enumeration"] = "yes"
43        MachineType = Type(self, "MachineType", Location("init", 0), pairs)
44        self.newSymbol(MachineType)
45
46        pairs = {}
47        pairs["primitive"] = "yes"
48        pairs["external"] = "yes"
49        void = Type(self, "void", Location("init", 0), pairs)
50        self.newSymbol(void)
51
52    def __repr__(self):
53        return "[SymbolTable]" # FIXME
54
55    def newSymbol(self, sym):
56        self.registerSym(str(sym), sym)
57        self.sym_vec.append(sym)
58
59    def registerSym(self, id, sym):
60        # Check for redeclaration (in the current frame only)
61        if id in self.sym_map_vec[-1]:
62            sym.error("Symbol '%s' redeclared in same scope.", id)
63
64        # FIXME - warn on masking of a declaration in a previous frame
65        self.sym_map_vec[-1][id] = sym
66
67    def find(self, ident, types=None):
68        for sym_map in reversed(self.sym_map_vec):
69            try:
70                symbol = sym_map[ident]
71            except KeyError:
72                continue
73
74            if types is not None:
75                assert isinstance(symbol, types)
76
77            return symbol
78
79        return None
80
81    def newMachComponentSym(self, symbol):
82        # used to cheat-- that is, access components in other machines
83        machine = self.find("current_machine", StateMachine)
84        if machine:
85            self.machine_components[str(machine)][str(symbol)] = symbol
86
87    def newCurrentMachine(self, sym):
88        self.registerGlobalSym(str(sym), sym)
89        self.registerSym("current_machine", sym)
90        self.sym_vec.append(sym)
91
92        self.machine_components[str(sym)] = {}
93
94    @property
95    def state_machine(self):
96        return self.find("current_machine", StateMachine)
97
98    def pushFrame(self):
99        self.sym_map_vec.append({})
100
101    def popFrame(self):
102        assert len(self.sym_map_vec) > 0
103        self.sym_map_vec.pop()
104
105    def registerGlobalSym(self, ident, symbol):
106        # Check for redeclaration (global frame only)
107        if ident in self.sym_map_vec[0]:
108            symbol.error("Symbol '%s' redeclared in global scope." % ident)
109
110        self.sym_map_vec[0][ident] = symbol
111
112    def getAllType(self, type):
113        for symbol in self.sym_vec:
114            if isinstance(symbol, type):
115                yield symbol
116
117    def writeCodeFiles(self, path):
118        code = code_formatter()
119        code('''
120/** Auto generated C++ code started by $__file__:$__line__ */
121
122#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
123''')
124        for symbol in self.sym_vec:
125            if isinstance(symbol, Type) and not symbol.isPrimitive:
126                code('#include "mem/protocol/${{symbol.c_ident}}.hh"')
127
128        code.write(path, "Types.hh")
129
130        for symbol in self.sym_vec:
131            symbol.writeCodeFiles(path)
132
133        self.writeControllerFactory(path)
134
135    def writeControllerFactory(self, path):
136        code = code_formatter()
137
138        code('''
139/** \\file ControllerFactory.hh
140 * Auto generatred C++ code started by $__file__:$__line__
141 */
142
143#ifndef CONTROLLERFACTORY_H
144#define CONTROLLERFACTORY_H
145
146#include <string>
147class Network;
148class AbstractController;
149
150class ControllerFactory {
151  public:
152    static AbstractController *createController(const std::string &controller_type, const std::string &name);
153};
154#endif // CONTROLLERFACTORY_H''')
155        code.write(path, "ControllerFactory.hh")
156
157        code = code_formatter()
158        code('''
159/** \\file ControllerFactory.cc
160 * Auto generatred C++ code started by $__file__:$__line__
161 */
162
163#include "mem/protocol/ControllerFactory.hh"
164#include "mem/ruby/slicc_interface/AbstractController.hh"
165#include "mem/protocol/MachineType.hh"
166''')
167
168        controller_types = []
169        for symbol in self.getAllType(StateMachine):
170            code('#include "mem/protocol/${{symbol.ident}}_Controller.hh"')
171            controller_types.append(symbol.ident)
172
173        code('''
174AbstractController *ControllerFactory::createController(const std::string &controller_type, const std::string &name) {
175''')
176
177        for ct in controller_types:
178            code('''
179    if (controller_type == "$ct")
180        return new ${ct}_Controller(name);
181''')
182
183        code('''
184    assert(0); // invalid controller type
185    return NULL;
186}
187''')
188        code.write(path, "ControllerFactory.cc")
189
190    def writeHTMLFiles(self, path):
191        machines = list(self.getAllType(StateMachine))
192        if len(machines) > 1:
193            name = "%s_table.html" % machines[0].ident
194        else:
195            name = "empty.html"
196
197        code = code_formatter()
198        code('''
199<html>
200<head>
201<title>$path</title>
202</head>
203<frameset rows="*,30">
204    <frame name="Table" src="$name">
205    <frame name="Status" src="empty.html">
206</frameset>
207</html>
208''')
209        code.write(path, "index.html")
210
211        code = code_formatter()
212        code("<HTML></HTML>")
213        code.write(path, "empty.html")
214
215        for symbol in self.sym_vec:
216            symbol.writeHTMLFiles(path)
217
218__all__ = [ "SymbolTable" ]
219