Type.py (9219:258753d3bc47) Type.py (9298:9a087e046c58)
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 orderdict
29
30from slicc.util import PairContainer
31from slicc.symbols.Symbol import Symbol
32
33class DataMember(PairContainer):
34 def __init__(self, ident, type, pairs, init_code):
35 super(DataMember, self).__init__(pairs)
36 self.ident = ident
37 self.type = type
38 self.init_code = init_code
39
40class Enumeration(PairContainer):
41 def __init__(self, ident, pairs):
42 super(Enumeration, self).__init__(pairs)
43 self.ident = ident
44
45class Method(object):
46 def __init__(self, return_type, param_types):
47 self.return_type = return_type
48 self.param_types = param_types
49
50class Type(Symbol):
51 def __init__(self, table, ident, location, pairs, machine=None):
52 super(Type, self).__init__(table, ident, location, pairs)
53 self.c_ident = ident
54 self.abstract_ident = ""
55 if machine:
56 if self.isExternal or self.isPrimitive:
57 if "external_name" in self:
58 self.c_ident = self["external_name"]
59 else:
60 # Append with machine name
61 self.c_ident = "%s_%s" % (machine, ident)
62
63 self.pairs.setdefault("desc", "No description avaliable")
64
65 # check for interface that this Type implements
66 if "interface" in self:
67 interface = self["interface"]
68 if interface in ("Message", "NetworkMessage"):
69 self["message"] = "yes"
70 if interface == "NetworkMessage":
71 self["networkmessage"] = "yes"
72
73 # FIXME - all of the following id comparisons are fragile hacks
74 if self.ident in ("CacheMemory", "NewCacheMemory",
75 "TLCCacheMemory", "DNUCACacheMemory",
76 "DNUCABankCacheMemory", "L2BankCacheMemory",
77 "CompressedCacheMemory", "PrefetchCacheMemory"):
78 self["cache"] = "yes"
79
80 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
81 self["tbe"] = "yes"
82
83 if self.ident == "NewTBETable":
84 self["newtbe"] = "yes"
85
86 if self.ident == "TimerTable":
87 self["timer"] = "yes"
88
89 if self.ident == "DirectoryMemory":
90 self["dir"] = "yes"
91
92 if self.ident == "PersistentTable":
93 self["persistent"] = "yes"
94
95 if self.ident == "Prefetcher":
96 self["prefetcher"] = "yes"
97
98 if self.ident == "DNUCA_Movement":
99 self["mover"] = "yes"
100
101 self.isMachineType = (ident == "MachineType")
102
103 self.isStateDecl = ("state_decl" in self)
104 self.statePermPairs = []
105
106 self.data_members = orderdict()
107
108 # Methods
109 self.methods = {}
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 orderdict
29
30from slicc.util import PairContainer
31from slicc.symbols.Symbol import Symbol
32
33class DataMember(PairContainer):
34 def __init__(self, ident, type, pairs, init_code):
35 super(DataMember, self).__init__(pairs)
36 self.ident = ident
37 self.type = type
38 self.init_code = init_code
39
40class Enumeration(PairContainer):
41 def __init__(self, ident, pairs):
42 super(Enumeration, self).__init__(pairs)
43 self.ident = ident
44
45class Method(object):
46 def __init__(self, return_type, param_types):
47 self.return_type = return_type
48 self.param_types = param_types
49
50class Type(Symbol):
51 def __init__(self, table, ident, location, pairs, machine=None):
52 super(Type, self).__init__(table, ident, location, pairs)
53 self.c_ident = ident
54 self.abstract_ident = ""
55 if machine:
56 if self.isExternal or self.isPrimitive:
57 if "external_name" in self:
58 self.c_ident = self["external_name"]
59 else:
60 # Append with machine name
61 self.c_ident = "%s_%s" % (machine, ident)
62
63 self.pairs.setdefault("desc", "No description avaliable")
64
65 # check for interface that this Type implements
66 if "interface" in self:
67 interface = self["interface"]
68 if interface in ("Message", "NetworkMessage"):
69 self["message"] = "yes"
70 if interface == "NetworkMessage":
71 self["networkmessage"] = "yes"
72
73 # FIXME - all of the following id comparisons are fragile hacks
74 if self.ident in ("CacheMemory", "NewCacheMemory",
75 "TLCCacheMemory", "DNUCACacheMemory",
76 "DNUCABankCacheMemory", "L2BankCacheMemory",
77 "CompressedCacheMemory", "PrefetchCacheMemory"):
78 self["cache"] = "yes"
79
80 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
81 self["tbe"] = "yes"
82
83 if self.ident == "NewTBETable":
84 self["newtbe"] = "yes"
85
86 if self.ident == "TimerTable":
87 self["timer"] = "yes"
88
89 if self.ident == "DirectoryMemory":
90 self["dir"] = "yes"
91
92 if self.ident == "PersistentTable":
93 self["persistent"] = "yes"
94
95 if self.ident == "Prefetcher":
96 self["prefetcher"] = "yes"
97
98 if self.ident == "DNUCA_Movement":
99 self["mover"] = "yes"
100
101 self.isMachineType = (ident == "MachineType")
102
103 self.isStateDecl = ("state_decl" in self)
104 self.statePermPairs = []
105
106 self.data_members = orderdict()
107
108 # Methods
109 self.methods = {}
110 self.functions = {}
110
111 # Enums
112 self.enums = orderdict()
113
114 @property
115 def isPrimitive(self):
116 return "primitive" in self
117 @property
118 def isNetworkMessage(self):
119 return "networkmessage" in self
120 @property
121 def isMessage(self):
122 return "message" in self
123 @property
124 def isBuffer(self):
125 return "buffer" in self
126 @property
127 def isInPort(self):
128 return "inport" in self
129 @property
130 def isOutPort(self):
131 return "outport" in self
132 @property
133 def isEnumeration(self):
134 return "enumeration" in self
135 @property
136 def isExternal(self):
137 return "external" in self
138 @property
139 def isGlobal(self):
140 return "global" in self
141 @property
142 def isInterface(self):
143 return "interface" in self
144
145 # Return false on error
111
112 # Enums
113 self.enums = orderdict()
114
115 @property
116 def isPrimitive(self):
117 return "primitive" in self
118 @property
119 def isNetworkMessage(self):
120 return "networkmessage" in self
121 @property
122 def isMessage(self):
123 return "message" in self
124 @property
125 def isBuffer(self):
126 return "buffer" in self
127 @property
128 def isInPort(self):
129 return "inport" in self
130 @property
131 def isOutPort(self):
132 return "outport" in self
133 @property
134 def isEnumeration(self):
135 return "enumeration" in self
136 @property
137 def isExternal(self):
138 return "external" in self
139 @property
140 def isGlobal(self):
141 return "global" in self
142 @property
143 def isInterface(self):
144 return "interface" in self
145
146 # Return false on error
146 def dataMemberAdd(self, ident, type, pairs, init_code):
147 def addDataMember(self, ident, type, pairs, init_code):
147 if ident in self.data_members:
148 return False
149
150 member = DataMember(ident, type, pairs, init_code)
151 self.data_members[ident] = member
152
153 return True
154
155 def dataMemberType(self, ident):
156 return self.data_members[ident].type
157
158 def methodId(self, name, param_type_vec):
159 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
160
161 def methodIdAbstract(self, name, param_type_vec):
162 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
163
164 def statePermPairAdd(self, state_name, perm_name):
165 self.statePermPairs.append([state_name, perm_name])
166
148 if ident in self.data_members:
149 return False
150
151 member = DataMember(ident, type, pairs, init_code)
152 self.data_members[ident] = member
153
154 return True
155
156 def dataMemberType(self, ident):
157 return self.data_members[ident].type
158
159 def methodId(self, name, param_type_vec):
160 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
161
162 def methodIdAbstract(self, name, param_type_vec):
163 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
164
165 def statePermPairAdd(self, state_name, perm_name):
166 self.statePermPairs.append([state_name, perm_name])
167
167 def methodAdd(self, name, return_type, param_type_vec):
168 def addMethod(self, name, return_type, param_type_vec):
168 ident = self.methodId(name, param_type_vec)
169 if ident in self.methods:
170 return False
171
172 self.methods[ident] = Method(return_type, param_type_vec)
173 return True
174
169 ident = self.methodId(name, param_type_vec)
170 if ident in self.methods:
171 return False
172
173 self.methods[ident] = Method(return_type, param_type_vec)
174 return True
175
175 def enumAdd(self, ident, pairs):
176 # Ideally either this function or the one above should exist. But
177 # methods and functions have different structures right now.
178 # Hence, these are different, at least for the time being.
179 def addFunc(self, func):
180 ident = self.methodId(func.ident, func.param_types)
181 if ident in self.functions:
182 return False
183
184 self.functions[ident] = func
185 return True
186
187 def addEnum(self, ident, pairs):
176 if ident in self.enums:
177 return False
178
179 self.enums[ident] = Enumeration(ident, pairs)
180
181 # Add default
182 if "default" not in self:
183 self["default"] = "%s_NUM" % self.c_ident
184
185 return True
186
187 def writeCodeFiles(self, path, includes):
188 if self.isExternal:
189 # Do nothing
190 pass
191 elif self.isEnumeration:
192 self.printEnumHH(path)
193 self.printEnumCC(path)
194 else:
195 # User defined structs and messages
196 self.printTypeHH(path)
197 self.printTypeCC(path)
198
199 def printTypeHH(self, path):
200 code = self.symtab.codeFormatter()
201 code('''
202/** \\file ${{self.c_ident}}.hh
203 *
204 *
205 * Auto generated C++ code started by $__file__:$__line__
206 */
207
208#ifndef __${{self.c_ident}}_HH__
209#define __${{self.c_ident}}_HH__
210
211#include <iostream>
212
213#include "mem/ruby/common/Global.hh"
214''')
215
216 for dm in self.data_members.values():
217 if not dm.type.isPrimitive:
218 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
219
220 parent = ""
221 if "interface" in self:
222 code('#include "mem/protocol/$0.hh"', self["interface"])
223 parent = " : public %s" % self["interface"]
224
225 code('''
226$klass ${{self.c_ident}}$parent
227{
228 public:
229 ${{self.c_ident}}()
230 {
231''', klass="class")
232
233 code.indent()
234 if not self.isGlobal:
235 code.indent()
236 for dm in self.data_members.values():
237 ident = dm.ident
238 if "default" in dm:
239 # look for default value
240 code('m_$ident = ${{dm["default"]}}; // default for this field')
241 elif "default" in dm.type:
242 # Look for the type default
243 tid = dm.type.c_ident
244 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
245 else:
246 code('// m_$ident has no default')
247 code.dedent()
248 code('}')
249
250 # ******** Copy constructor ********
251 if not self.isGlobal:
252 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
253
254 # Call superclass constructor
255 if "interface" in self:
256 code(' : ${{self["interface"]}}(other)')
257
258 code('{')
259 code.indent()
260
261 for dm in self.data_members.values():
262 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
263
264 code.dedent()
265 code('}')
266
267 # ******** Full init constructor ********
268 if not self.isGlobal:
269 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
270 for dm in self.data_members.itervalues() ]
271
272 params = ', '.join(params)
273 code('${{self.c_ident}}($params)')
274
275 # Call superclass constructor
276 if "interface" in self:
277 code(' : ${{self["interface"]}}()')
278
279 code('{')
280 code.indent()
281 for dm in self.data_members.values():
282 code('m_${{dm.ident}} = local_${{dm.ident}};')
283 if "nextLineCallHack" in dm:
284 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
285
286 code.dedent()
287 code('}')
288
289 # create a static factory method and a clone member
290 code('''
291static ${{self.c_ident}}*
292create()
293{
294 return new ${{self.c_ident}}();
295}
296
297${{self.c_ident}}*
298clone() const
299{
300 return new ${{self.c_ident}}(*this);
301}
302''')
303
304 if not self.isGlobal:
305 # const Get methods for each field
306 code('// Const accessors methods for each field')
307 for dm in self.data_members.values():
308 code('''
309/** \\brief Const accessor method for ${{dm.ident}} field.
310 * \\return ${{dm.ident}} field
311 */
312const ${{dm.type.c_ident}}&
313get${{dm.ident}}() const
314{
315 return m_${{dm.ident}};
316}
317''')
318
319 # Non-const Get methods for each field
320 code('// Non const Accessors methods for each field')
321 for dm in self.data_members.values():
322 code('''
323/** \\brief Non-const accessor method for ${{dm.ident}} field.
324 * \\return ${{dm.ident}} field
325 */
326${{dm.type.c_ident}}&
327get${{dm.ident}}()
328{
329 return m_${{dm.ident}};
330}
331''')
332
333 #Set methods for each field
334 code('// Mutator methods for each field')
335 for dm in self.data_members.values():
336 code('''
337/** \\brief Mutator method for ${{dm.ident}} field */
338void
339set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
340{
341 m_${{dm.ident}} = local_${{dm.ident}};
342}
343''')
344
345 code('void print(std::ostream& out) const;')
346 code.dedent()
347 code(' //private:')
348 code.indent()
349
350 # Data members for each field
351 for dm in self.data_members.values():
352 if "abstract" not in dm:
353 const = ""
354 init = ""
355
356 # global structure
357 if self.isGlobal:
358 const = "static const "
359
360 # init value
361 if dm.init_code:
362 # only global structure can have init value here
363 assert self.isGlobal
364 init = " = %s" % (dm.init_code)
365
366 if "desc" in dm:
367 code('/** ${{dm["desc"]}} */')
368
369 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
370
188 if ident in self.enums:
189 return False
190
191 self.enums[ident] = Enumeration(ident, pairs)
192
193 # Add default
194 if "default" not in self:
195 self["default"] = "%s_NUM" % self.c_ident
196
197 return True
198
199 def writeCodeFiles(self, path, includes):
200 if self.isExternal:
201 # Do nothing
202 pass
203 elif self.isEnumeration:
204 self.printEnumHH(path)
205 self.printEnumCC(path)
206 else:
207 # User defined structs and messages
208 self.printTypeHH(path)
209 self.printTypeCC(path)
210
211 def printTypeHH(self, path):
212 code = self.symtab.codeFormatter()
213 code('''
214/** \\file ${{self.c_ident}}.hh
215 *
216 *
217 * Auto generated C++ code started by $__file__:$__line__
218 */
219
220#ifndef __${{self.c_ident}}_HH__
221#define __${{self.c_ident}}_HH__
222
223#include <iostream>
224
225#include "mem/ruby/common/Global.hh"
226''')
227
228 for dm in self.data_members.values():
229 if not dm.type.isPrimitive:
230 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
231
232 parent = ""
233 if "interface" in self:
234 code('#include "mem/protocol/$0.hh"', self["interface"])
235 parent = " : public %s" % self["interface"]
236
237 code('''
238$klass ${{self.c_ident}}$parent
239{
240 public:
241 ${{self.c_ident}}()
242 {
243''', klass="class")
244
245 code.indent()
246 if not self.isGlobal:
247 code.indent()
248 for dm in self.data_members.values():
249 ident = dm.ident
250 if "default" in dm:
251 # look for default value
252 code('m_$ident = ${{dm["default"]}}; // default for this field')
253 elif "default" in dm.type:
254 # Look for the type default
255 tid = dm.type.c_ident
256 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
257 else:
258 code('// m_$ident has no default')
259 code.dedent()
260 code('}')
261
262 # ******** Copy constructor ********
263 if not self.isGlobal:
264 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
265
266 # Call superclass constructor
267 if "interface" in self:
268 code(' : ${{self["interface"]}}(other)')
269
270 code('{')
271 code.indent()
272
273 for dm in self.data_members.values():
274 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
275
276 code.dedent()
277 code('}')
278
279 # ******** Full init constructor ********
280 if not self.isGlobal:
281 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
282 for dm in self.data_members.itervalues() ]
283
284 params = ', '.join(params)
285 code('${{self.c_ident}}($params)')
286
287 # Call superclass constructor
288 if "interface" in self:
289 code(' : ${{self["interface"]}}()')
290
291 code('{')
292 code.indent()
293 for dm in self.data_members.values():
294 code('m_${{dm.ident}} = local_${{dm.ident}};')
295 if "nextLineCallHack" in dm:
296 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
297
298 code.dedent()
299 code('}')
300
301 # create a static factory method and a clone member
302 code('''
303static ${{self.c_ident}}*
304create()
305{
306 return new ${{self.c_ident}}();
307}
308
309${{self.c_ident}}*
310clone() const
311{
312 return new ${{self.c_ident}}(*this);
313}
314''')
315
316 if not self.isGlobal:
317 # const Get methods for each field
318 code('// Const accessors methods for each field')
319 for dm in self.data_members.values():
320 code('''
321/** \\brief Const accessor method for ${{dm.ident}} field.
322 * \\return ${{dm.ident}} field
323 */
324const ${{dm.type.c_ident}}&
325get${{dm.ident}}() const
326{
327 return m_${{dm.ident}};
328}
329''')
330
331 # Non-const Get methods for each field
332 code('// Non const Accessors methods for each field')
333 for dm in self.data_members.values():
334 code('''
335/** \\brief Non-const accessor method for ${{dm.ident}} field.
336 * \\return ${{dm.ident}} field
337 */
338${{dm.type.c_ident}}&
339get${{dm.ident}}()
340{
341 return m_${{dm.ident}};
342}
343''')
344
345 #Set methods for each field
346 code('// Mutator methods for each field')
347 for dm in self.data_members.values():
348 code('''
349/** \\brief Mutator method for ${{dm.ident}} field */
350void
351set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
352{
353 m_${{dm.ident}} = local_${{dm.ident}};
354}
355''')
356
357 code('void print(std::ostream& out) const;')
358 code.dedent()
359 code(' //private:')
360 code.indent()
361
362 # Data members for each field
363 for dm in self.data_members.values():
364 if "abstract" not in dm:
365 const = ""
366 init = ""
367
368 # global structure
369 if self.isGlobal:
370 const = "static const "
371
372 # init value
373 if dm.init_code:
374 # only global structure can have init value here
375 assert self.isGlobal
376 init = " = %s" % (dm.init_code)
377
378 if "desc" in dm:
379 code('/** ${{dm["desc"]}} */')
380
381 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
382
383 # Prototypes for functions defined for the Type
384 for item in self.functions:
385 proto = self.functions[item].prototype
386 if proto:
387 code('$proto')
388
371 code.dedent()
372 code('};')
373
374 code('''
375inline std::ostream&
376operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
377{
378 obj.print(out);
379 out << std::flush;
380 return out;
381}
382
383#endif // __${{self.c_ident}}_HH__
384''')
385
386 code.write(path, "%s.hh" % self.c_ident)
387
388 def printTypeCC(self, path):
389 code = self.symtab.codeFormatter()
390
391 code('''
392/** \\file ${{self.c_ident}}.cc
393 *
394 * Auto generated C++ code started by $__file__:$__line__
395 */
396
397#include <iostream>
398
399#include "mem/protocol/${{self.c_ident}}.hh"
400
401using namespace std;
402''')
403
404 code('''
405/** \\brief Print the state of this object */
406void
407${{self.c_ident}}::print(ostream& out) const
408{
409 out << "[${{self.c_ident}}: ";
410''')
411
412 # For each field
413 code.indent()
414 for dm in self.data_members.values():
415 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
416
417 if self.isMessage:
418 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";')
419 code.dedent()
420
421 # Trailer
422 code('''
423 out << "]";
424}''')
425
389 code.dedent()
390 code('};')
391
392 code('''
393inline std::ostream&
394operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
395{
396 obj.print(out);
397 out << std::flush;
398 return out;
399}
400
401#endif // __${{self.c_ident}}_HH__
402''')
403
404 code.write(path, "%s.hh" % self.c_ident)
405
406 def printTypeCC(self, path):
407 code = self.symtab.codeFormatter()
408
409 code('''
410/** \\file ${{self.c_ident}}.cc
411 *
412 * Auto generated C++ code started by $__file__:$__line__
413 */
414
415#include <iostream>
416
417#include "mem/protocol/${{self.c_ident}}.hh"
418
419using namespace std;
420''')
421
422 code('''
423/** \\brief Print the state of this object */
424void
425${{self.c_ident}}::print(ostream& out) const
426{
427 out << "[${{self.c_ident}}: ";
428''')
429
430 # For each field
431 code.indent()
432 for dm in self.data_members.values():
433 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
434
435 if self.isMessage:
436 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";')
437 code.dedent()
438
439 # Trailer
440 code('''
441 out << "]";
442}''')
443
444 # print the code for the functions in the type
445 for item in self.functions:
446 code(self.functions[item].generateCode())
447
426 code.write(path, "%s.cc" % self.c_ident)
427
428 def printEnumHH(self, path):
429 code = self.symtab.codeFormatter()
430 code('''
431/** \\file ${{self.c_ident}}.hh
432 *
433 * Auto generated C++ code started by $__file__:$__line__
434 */
435
436#ifndef __${{self.c_ident}}_HH__
437#define __${{self.c_ident}}_HH__
438
439#include <iostream>
440#include <string>
441
442''')
443 if self.isStateDecl:
444 code('#include "mem/protocol/AccessPermission.hh"')
445
446 if self.isMachineType:
447 code('#include "base/misc.hh"')
448 code('#include "mem/protocol/GenericMachineType.hh"')
449 code('#include "mem/ruby/common/Address.hh"')
450 code('struct MachineID;')
451
452 code('''
453
454// Class definition
455/** \\enum ${{self.c_ident}}
456 * \\brief ${{self.desc}}
457 */
458enum ${{self.c_ident}} {
459 ${{self.c_ident}}_FIRST,
460''')
461
462 code.indent()
463 # For each field
464 for i,(ident,enum) in enumerate(self.enums.iteritems()):
465 desc = enum.get("desc", "No description avaliable")
466 if i == 0:
467 init = ' = %s_FIRST' % self.c_ident
468 else:
469 init = ''
470 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
471 code.dedent()
472 code('''
473 ${{self.c_ident}}_NUM
474};
475
476// Code to convert from a string to the enumeration
477${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
478
479// Code to convert state to a string
480std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
481
482// Code to increment an enumeration type
483${{self.c_ident}} &operator++(${{self.c_ident}} &e);
484''')
485
486 # MachineType hack used to set the base component id for each Machine
487 if self.isMachineType:
488 code('''
489int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
490MachineType ${{self.c_ident}}_from_base_level(int);
491int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
492int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
493''')
494
495 for enum in self.enums.itervalues():
496 if enum.ident == "DMA":
497 code('''
498MachineID map_Address_to_DMA(const Address &addr);
499''')
500 code('''
501
502MachineID get${{enum.ident}}MachineID(NodeID RubyNode);
503''')
504
505 code('''
506inline GenericMachineType
507ConvertMachToGenericMach(MachineType machType)
508{
509''')
510 for enum in self.enums.itervalues():
511 code('''
512 if (machType == MachineType_${{enum.ident}})
513 return GenericMachineType_${{enum.ident}};
514''')
515 code('''
516 panic("cannot convert to a GenericMachineType");
517}
518''')
519
520 if self.isStateDecl:
521 code('''
522
523// Code to convert the current state to an access permission
524AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
525
526''')
527
528 # Trailer
529 code('''
530std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
531
532#endif // __${{self.c_ident}}_HH__
533''')
534
535 code.write(path, "%s.hh" % self.c_ident)
536
537 def printEnumCC(self, path):
538 code = self.symtab.codeFormatter()
539 code('''
540/** \\file ${{self.c_ident}}.hh
541 *
542 * Auto generated C++ code started by $__file__:$__line__
543 */
544
545#include <cassert>
546#include <iostream>
547#include <string>
548
549#include "base/misc.hh"
550#include "mem/protocol/${{self.c_ident}}.hh"
551
552using namespace std;
553
554''')
555
556 if self.isStateDecl:
557 code('''
558// Code to convert the current state to an access permission
559AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
560{
561 switch(obj) {
562''')
563 # For each case
564 code.indent()
565 for statePerm in self.statePermPairs:
566 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
567 code(' return AccessPermission_${{statePerm[1]}};')
568 code.dedent()
569 code ('''
570 default:
571 panic("Unknown state access permission converstion for ${{self.c_ident}}");
572 }
573}
574
575''')
576
577 if self.isMachineType:
578 for enum in self.enums.itervalues():
579 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
580 code('#include "mem/ruby/system/MachineID.hh"')
581
582 code('''
583// Code for output operator
584ostream&
585operator<<(ostream& out, const ${{self.c_ident}}& obj)
586{
587 out << ${{self.c_ident}}_to_string(obj);
588 out << flush;
589 return out;
590}
591
592// Code to convert state to a string
593string
594${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
595{
596 switch(obj) {
597''')
598
599 # For each field
600 code.indent()
601 for enum in self.enums.itervalues():
602 code(' case ${{self.c_ident}}_${{enum.ident}}:')
603 code(' return "${{enum.ident}}";')
604 code.dedent()
605
606 # Trailer
607 code('''
608 default:
609 panic("Invalid range for type ${{self.c_ident}}");
610 }
611}
612
613// Code to convert from a string to the enumeration
614${{self.c_ident}}
615string_to_${{self.c_ident}}(const string& str)
616{
617''')
618
619 # For each field
620 start = ""
621 code.indent()
622 for enum in self.enums.itervalues():
623 code('${start}if (str == "${{enum.ident}}") {')
624 code(' return ${{self.c_ident}}_${{enum.ident}};')
625 start = "} else "
626 code.dedent()
627
628 code('''
629 } else {
630 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
631 }
632}
633
634// Code to increment an enumeration type
635${{self.c_ident}}&
636operator++(${{self.c_ident}}& e)
637{
638 assert(e < ${{self.c_ident}}_NUM);
639 return e = ${{self.c_ident}}(e+1);
640}
641''')
642
643 # MachineType hack used to set the base level and number of
644 # components for each Machine
645 if self.isMachineType:
646 code('''
647/** \\brief returns the base vector index for each machine type to be
648 * used by NetDest
649 *
650 * \\return the base vector index for each machine type to be used by NetDest
651 * \\see NetDest.hh
652 */
653int
654${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
655{
656 switch(obj) {
657''')
658
659 # For each field
660 code.indent()
661 for i,enum in enumerate(self.enums.itervalues()):
662 code(' case ${{self.c_ident}}_${{enum.ident}}:')
663 code(' return $i;')
664 code.dedent()
665
666 # total num
667 code('''
668 case ${{self.c_ident}}_NUM:
669 return ${{len(self.enums)}};
670
671 default:
672 panic("Invalid range for type ${{self.c_ident}}");
673 }
674}
675
676/** \\brief returns the machine type for each base vector index used by NetDest
677 *
678 * \\return the MachineType
679 */
680MachineType
681${{self.c_ident}}_from_base_level(int type)
682{
683 switch(type) {
684''')
685
686 # For each field
687 code.indent()
688 for i,enum in enumerate(self.enums.itervalues()):
689 code(' case $i:')
690 code(' return ${{self.c_ident}}_${{enum.ident}};')
691 code.dedent()
692
693 # Trailer
694 code('''
695 default:
696 panic("Invalid range for type ${{self.c_ident}}");
697 }
698}
699
700/** \\brief The return value indicates the number of components created
701 * before a particular machine\'s components
702 *
703 * \\return the base number of components for each machine
704 */
705int
706${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
707{
708 int base = 0;
709 switch(obj) {
710''')
711
712 # For each field
713 code.indent()
714 code(' case ${{self.c_ident}}_NUM:')
715 for enum in reversed(self.enums.values()):
716 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
717 code(' case ${{self.c_ident}}_${{enum.ident}}:')
718 code(' break;')
719 code.dedent()
720
721 code('''
722 default:
723 panic("Invalid range for type ${{self.c_ident}}");
724 }
725
726 return base;
727}
728
729/** \\brief returns the total number of components for each machine
730 * \\return the total number of components for each machine
731 */
732int
733${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
734{
735 switch(obj) {
736''')
737
738 # For each field
739 for enum in self.enums.itervalues():
740 code('''
741 case ${{self.c_ident}}_${{enum.ident}}:
742 return ${{enum.ident}}_Controller::getNumControllers();
743''')
744
745 # total num
746 code('''
747 case ${{self.c_ident}}_NUM:
748 default:
749 panic("Invalid range for type ${{self.c_ident}}");
750 }
751}
752''')
753
754 for enum in self.enums.itervalues():
755 if enum.ident == "DMA":
756 code('''
757MachineID
758map_Address_to_DMA(const Address &addr)
759{
760 MachineID dma = {MachineType_DMA, 0};
761 return dma;
762}
763''')
764
765 code('''
766
767MachineID
768get${{enum.ident}}MachineID(NodeID RubyNode)
769{
770 MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
771 return mach;
772}
773''')
774
775 # Write the file
776 code.write(path, "%s.cc" % self.c_ident)
777
778__all__ = [ "Type" ]
448 code.write(path, "%s.cc" % self.c_ident)
449
450 def printEnumHH(self, path):
451 code = self.symtab.codeFormatter()
452 code('''
453/** \\file ${{self.c_ident}}.hh
454 *
455 * Auto generated C++ code started by $__file__:$__line__
456 */
457
458#ifndef __${{self.c_ident}}_HH__
459#define __${{self.c_ident}}_HH__
460
461#include <iostream>
462#include <string>
463
464''')
465 if self.isStateDecl:
466 code('#include "mem/protocol/AccessPermission.hh"')
467
468 if self.isMachineType:
469 code('#include "base/misc.hh"')
470 code('#include "mem/protocol/GenericMachineType.hh"')
471 code('#include "mem/ruby/common/Address.hh"')
472 code('struct MachineID;')
473
474 code('''
475
476// Class definition
477/** \\enum ${{self.c_ident}}
478 * \\brief ${{self.desc}}
479 */
480enum ${{self.c_ident}} {
481 ${{self.c_ident}}_FIRST,
482''')
483
484 code.indent()
485 # For each field
486 for i,(ident,enum) in enumerate(self.enums.iteritems()):
487 desc = enum.get("desc", "No description avaliable")
488 if i == 0:
489 init = ' = %s_FIRST' % self.c_ident
490 else:
491 init = ''
492 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
493 code.dedent()
494 code('''
495 ${{self.c_ident}}_NUM
496};
497
498// Code to convert from a string to the enumeration
499${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
500
501// Code to convert state to a string
502std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
503
504// Code to increment an enumeration type
505${{self.c_ident}} &operator++(${{self.c_ident}} &e);
506''')
507
508 # MachineType hack used to set the base component id for each Machine
509 if self.isMachineType:
510 code('''
511int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
512MachineType ${{self.c_ident}}_from_base_level(int);
513int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
514int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
515''')
516
517 for enum in self.enums.itervalues():
518 if enum.ident == "DMA":
519 code('''
520MachineID map_Address_to_DMA(const Address &addr);
521''')
522 code('''
523
524MachineID get${{enum.ident}}MachineID(NodeID RubyNode);
525''')
526
527 code('''
528inline GenericMachineType
529ConvertMachToGenericMach(MachineType machType)
530{
531''')
532 for enum in self.enums.itervalues():
533 code('''
534 if (machType == MachineType_${{enum.ident}})
535 return GenericMachineType_${{enum.ident}};
536''')
537 code('''
538 panic("cannot convert to a GenericMachineType");
539}
540''')
541
542 if self.isStateDecl:
543 code('''
544
545// Code to convert the current state to an access permission
546AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
547
548''')
549
550 # Trailer
551 code('''
552std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
553
554#endif // __${{self.c_ident}}_HH__
555''')
556
557 code.write(path, "%s.hh" % self.c_ident)
558
559 def printEnumCC(self, path):
560 code = self.symtab.codeFormatter()
561 code('''
562/** \\file ${{self.c_ident}}.hh
563 *
564 * Auto generated C++ code started by $__file__:$__line__
565 */
566
567#include <cassert>
568#include <iostream>
569#include <string>
570
571#include "base/misc.hh"
572#include "mem/protocol/${{self.c_ident}}.hh"
573
574using namespace std;
575
576''')
577
578 if self.isStateDecl:
579 code('''
580// Code to convert the current state to an access permission
581AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
582{
583 switch(obj) {
584''')
585 # For each case
586 code.indent()
587 for statePerm in self.statePermPairs:
588 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
589 code(' return AccessPermission_${{statePerm[1]}};')
590 code.dedent()
591 code ('''
592 default:
593 panic("Unknown state access permission converstion for ${{self.c_ident}}");
594 }
595}
596
597''')
598
599 if self.isMachineType:
600 for enum in self.enums.itervalues():
601 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
602 code('#include "mem/ruby/system/MachineID.hh"')
603
604 code('''
605// Code for output operator
606ostream&
607operator<<(ostream& out, const ${{self.c_ident}}& obj)
608{
609 out << ${{self.c_ident}}_to_string(obj);
610 out << flush;
611 return out;
612}
613
614// Code to convert state to a string
615string
616${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
617{
618 switch(obj) {
619''')
620
621 # For each field
622 code.indent()
623 for enum in self.enums.itervalues():
624 code(' case ${{self.c_ident}}_${{enum.ident}}:')
625 code(' return "${{enum.ident}}";')
626 code.dedent()
627
628 # Trailer
629 code('''
630 default:
631 panic("Invalid range for type ${{self.c_ident}}");
632 }
633}
634
635// Code to convert from a string to the enumeration
636${{self.c_ident}}
637string_to_${{self.c_ident}}(const string& str)
638{
639''')
640
641 # For each field
642 start = ""
643 code.indent()
644 for enum in self.enums.itervalues():
645 code('${start}if (str == "${{enum.ident}}") {')
646 code(' return ${{self.c_ident}}_${{enum.ident}};')
647 start = "} else "
648 code.dedent()
649
650 code('''
651 } else {
652 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
653 }
654}
655
656// Code to increment an enumeration type
657${{self.c_ident}}&
658operator++(${{self.c_ident}}& e)
659{
660 assert(e < ${{self.c_ident}}_NUM);
661 return e = ${{self.c_ident}}(e+1);
662}
663''')
664
665 # MachineType hack used to set the base level and number of
666 # components for each Machine
667 if self.isMachineType:
668 code('''
669/** \\brief returns the base vector index for each machine type to be
670 * used by NetDest
671 *
672 * \\return the base vector index for each machine type to be used by NetDest
673 * \\see NetDest.hh
674 */
675int
676${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
677{
678 switch(obj) {
679''')
680
681 # For each field
682 code.indent()
683 for i,enum in enumerate(self.enums.itervalues()):
684 code(' case ${{self.c_ident}}_${{enum.ident}}:')
685 code(' return $i;')
686 code.dedent()
687
688 # total num
689 code('''
690 case ${{self.c_ident}}_NUM:
691 return ${{len(self.enums)}};
692
693 default:
694 panic("Invalid range for type ${{self.c_ident}}");
695 }
696}
697
698/** \\brief returns the machine type for each base vector index used by NetDest
699 *
700 * \\return the MachineType
701 */
702MachineType
703${{self.c_ident}}_from_base_level(int type)
704{
705 switch(type) {
706''')
707
708 # For each field
709 code.indent()
710 for i,enum in enumerate(self.enums.itervalues()):
711 code(' case $i:')
712 code(' return ${{self.c_ident}}_${{enum.ident}};')
713 code.dedent()
714
715 # Trailer
716 code('''
717 default:
718 panic("Invalid range for type ${{self.c_ident}}");
719 }
720}
721
722/** \\brief The return value indicates the number of components created
723 * before a particular machine\'s components
724 *
725 * \\return the base number of components for each machine
726 */
727int
728${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
729{
730 int base = 0;
731 switch(obj) {
732''')
733
734 # For each field
735 code.indent()
736 code(' case ${{self.c_ident}}_NUM:')
737 for enum in reversed(self.enums.values()):
738 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
739 code(' case ${{self.c_ident}}_${{enum.ident}}:')
740 code(' break;')
741 code.dedent()
742
743 code('''
744 default:
745 panic("Invalid range for type ${{self.c_ident}}");
746 }
747
748 return base;
749}
750
751/** \\brief returns the total number of components for each machine
752 * \\return the total number of components for each machine
753 */
754int
755${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
756{
757 switch(obj) {
758''')
759
760 # For each field
761 for enum in self.enums.itervalues():
762 code('''
763 case ${{self.c_ident}}_${{enum.ident}}:
764 return ${{enum.ident}}_Controller::getNumControllers();
765''')
766
767 # total num
768 code('''
769 case ${{self.c_ident}}_NUM:
770 default:
771 panic("Invalid range for type ${{self.c_ident}}");
772 }
773}
774''')
775
776 for enum in self.enums.itervalues():
777 if enum.ident == "DMA":
778 code('''
779MachineID
780map_Address_to_DMA(const Address &addr)
781{
782 MachineID dma = {MachineType_DMA, 0};
783 return dma;
784}
785''')
786
787 code('''
788
789MachineID
790get${{enum.ident}}MachineID(NodeID RubyNode)
791{
792 MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
793 return mach;
794}
795''')
796
797 # Write the file
798 code.write(path, "%s.cc" % self.c_ident)
799
800__all__ = [ "Type" ]