Type.py (7055:4e24742201d7) Type.py (7453:1a5db3dd0f62)
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.data_members = orderdict()
104
105 # Methods
106 self.methods = {}
107
108 # Enums
109 self.enums = orderdict()
110
111 @property
112 def isPrimitive(self):
113 return "primitive" in self
114 @property
115 def isNetworkMessage(self):
116 return "networkmessage" in self
117 @property
118 def isMessage(self):
119 return "message" in self
120 @property
121 def isBuffer(self):
122 return "buffer" in self
123 @property
124 def isInPort(self):
125 return "inport" in self
126 @property
127 def isOutPort(self):
128 return "outport" in self
129 @property
130 def isEnumeration(self):
131 return "enumeration" in self
132 @property
133 def isExternal(self):
134 return "external" in self
135 @property
136 def isGlobal(self):
137 return "global" in self
138 @property
139 def isInterface(self):
140 return "interface" in self
141
142 # Return false on error
143 def dataMemberAdd(self, ident, type, pairs, init_code):
144 if ident in self.data_members:
145 return False
146
147 member = DataMember(ident, type, pairs, init_code)
148 self.data_members[ident] = member
149
150 return True
151
152 def dataMemberType(self, ident):
153 return self.data_members[ident].type
154
155 def methodId(self, name, param_type_vec):
156 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
157
158 def methodIdAbstract(self, name, param_type_vec):
159 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
160
161 def methodAdd(self, name, return_type, param_type_vec):
162 ident = self.methodId(name, param_type_vec)
163 if ident in self.methods:
164 return False
165
166 self.methods[ident] = Method(return_type, param_type_vec)
167 return True
168
169 def enumAdd(self, ident, pairs):
170 if ident in self.enums:
171 return False
172
173 self.enums[ident] = Enumeration(ident, pairs)
174
175 # Add default
176 if "default" not in self:
177 self["default"] = "%s_NUM" % self.c_ident
178
179 return True
180
181 def writeCodeFiles(self, path):
182 if self.isExternal:
183 # Do nothing
184 pass
185 elif self.isEnumeration:
186 self.printEnumHH(path)
187 self.printEnumCC(path)
188 else:
189 # User defined structs and messages
190 self.printTypeHH(path)
191 self.printTypeCC(path)
192
193 def printTypeHH(self, path):
194 code = self.symtab.codeFormatter()
195 code('''
196/** \\file ${{self.c_ident}}.hh
197 *
198 *
199 * Auto generated C++ code started by $__file__:$__line__
200 */
201
202#ifndef __${{self.c_ident}}_HH__
203#define __${{self.c_ident}}_HH__
204
205#include <iostream>
206
207#include "mem/ruby/common/Global.hh"
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.data_members = orderdict()
104
105 # Methods
106 self.methods = {}
107
108 # Enums
109 self.enums = orderdict()
110
111 @property
112 def isPrimitive(self):
113 return "primitive" in self
114 @property
115 def isNetworkMessage(self):
116 return "networkmessage" in self
117 @property
118 def isMessage(self):
119 return "message" in self
120 @property
121 def isBuffer(self):
122 return "buffer" in self
123 @property
124 def isInPort(self):
125 return "inport" in self
126 @property
127 def isOutPort(self):
128 return "outport" in self
129 @property
130 def isEnumeration(self):
131 return "enumeration" in self
132 @property
133 def isExternal(self):
134 return "external" in self
135 @property
136 def isGlobal(self):
137 return "global" in self
138 @property
139 def isInterface(self):
140 return "interface" in self
141
142 # Return false on error
143 def dataMemberAdd(self, ident, type, pairs, init_code):
144 if ident in self.data_members:
145 return False
146
147 member = DataMember(ident, type, pairs, init_code)
148 self.data_members[ident] = member
149
150 return True
151
152 def dataMemberType(self, ident):
153 return self.data_members[ident].type
154
155 def methodId(self, name, param_type_vec):
156 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
157
158 def methodIdAbstract(self, name, param_type_vec):
159 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
160
161 def methodAdd(self, name, return_type, param_type_vec):
162 ident = self.methodId(name, param_type_vec)
163 if ident in self.methods:
164 return False
165
166 self.methods[ident] = Method(return_type, param_type_vec)
167 return True
168
169 def enumAdd(self, ident, pairs):
170 if ident in self.enums:
171 return False
172
173 self.enums[ident] = Enumeration(ident, pairs)
174
175 # Add default
176 if "default" not in self:
177 self["default"] = "%s_NUM" % self.c_ident
178
179 return True
180
181 def writeCodeFiles(self, path):
182 if self.isExternal:
183 # Do nothing
184 pass
185 elif self.isEnumeration:
186 self.printEnumHH(path)
187 self.printEnumCC(path)
188 else:
189 # User defined structs and messages
190 self.printTypeHH(path)
191 self.printTypeCC(path)
192
193 def printTypeHH(self, path):
194 code = self.symtab.codeFormatter()
195 code('''
196/** \\file ${{self.c_ident}}.hh
197 *
198 *
199 * Auto generated C++ code started by $__file__:$__line__
200 */
201
202#ifndef __${{self.c_ident}}_HH__
203#define __${{self.c_ident}}_HH__
204
205#include <iostream>
206
207#include "mem/ruby/common/Global.hh"
208#include "mem/gems_common/Allocator.hh"
209''')
210
211 for dm in self.data_members.values():
212 if not dm.type.isPrimitive:
213 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
214
215 parent = ""
216 if "interface" in self:
217 code('#include "mem/protocol/$0.hh"', self["interface"])
218 parent = " : public %s" % self["interface"]
219
220 code('''
221$klass ${{self.c_ident}}$parent
222{
223 public:
224 ${{self.c_ident}}()
225 {
226''', klass="class")
227
228 code.indent()
229 if not self.isGlobal:
230 code.indent()
231 for dm in self.data_members.values():
232 ident = dm.ident
233 if "default" in dm:
234 # look for default value
235 code('m_$ident = ${{dm["default"]}}; // default for this field')
236 elif "default" in dm.type:
237 # Look for the type default
238 tid = dm.type.c_ident
239 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
240 else:
241 code('// m_$ident has no default')
242 code.dedent()
243 code('}')
244
208''')
209
210 for dm in self.data_members.values():
211 if not dm.type.isPrimitive:
212 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
213
214 parent = ""
215 if "interface" in self:
216 code('#include "mem/protocol/$0.hh"', self["interface"])
217 parent = " : public %s" % self["interface"]
218
219 code('''
220$klass ${{self.c_ident}}$parent
221{
222 public:
223 ${{self.c_ident}}()
224 {
225''', klass="class")
226
227 code.indent()
228 if not self.isGlobal:
229 code.indent()
230 for dm in self.data_members.values():
231 ident = dm.ident
232 if "default" in dm:
233 # look for default value
234 code('m_$ident = ${{dm["default"]}}; // default for this field')
235 elif "default" in dm.type:
236 # Look for the type default
237 tid = dm.type.c_ident
238 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
239 else:
240 code('// m_$ident has no default')
241 code.dedent()
242 code('}')
243
244 # ******** Copy constructor ********
245 if not self.isGlobal:
246 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
247
248 # Call superclass constructor
249 if "interface" in self:
250 code(' : ${{self["interface"]}}(other)')
251
252 code('{')
253 code.indent()
254
255 for dm in self.data_members.values():
256 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
257
258 if self.isMessage:
259 code('proc_id = other.proc_id;')
260
261 code.dedent()
262 code('}')
263
245 # ******** Full init constructor ********
246 if not self.isGlobal:
247 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
248 for dm in self.data_members.itervalues() ]
249
250 if self.isMessage:
251 params.append('const unsigned local_proc_id')
252
253 params = ', '.join(params)
254 code('${{self.c_ident}}($params)')
255
256 # Call superclass constructor
257 if "interface" in self:
258 code(' : ${{self["interface"]}}()')
259
260 code('{')
261 code.indent()
262 for dm in self.data_members.values():
263 code('m_${{dm.ident}} = local_${{dm.ident}};')
264 if "nextLineCallHack" in dm:
265 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
266
267 if self.isMessage:
268 code('proc_id = local_proc_id;')
269
270 code.dedent()
271 code('}')
272
264 # ******** Full init constructor ********
265 if not self.isGlobal:
266 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
267 for dm in self.data_members.itervalues() ]
268
269 if self.isMessage:
270 params.append('const unsigned local_proc_id')
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 if self.isMessage:
287 code('proc_id = local_proc_id;')
288
289 code.dedent()
290 code('}')
291
273 # create a static factory method
274 if "interface" in self:
275 code('''
276static ${{self["interface"]}}*
292 # create a static factory method and a clone member
293 code('''
294static ${{self.c_ident}}*
277create()
278{
279 return new ${{self.c_ident}}();
280}
295create()
296{
297 return new ${{self.c_ident}}();
298}
281''')
282
299
283 # ******** Message member functions ********
284 # FIXME: those should be moved into slicc file, slicc should
285 # support more of the c++ class inheritance
286
287 if self.isMessage:
288 code('''
289Message *
300${{self.c_ident}}*
290clone() const
291{
301clone() const
302{
292 checkAllocator();
293 return s_allocator_ptr->allocate(*this);
303 return new ${{self.c_ident}}(*this);
294}
304}
295
296void
297destroy()
298{
299 checkAllocator();
300 s_allocator_ptr->deallocate(this);
301}
302
303static Allocator<${{self.c_ident}}>* s_allocator_ptr;
304
305static void
306checkAllocator()
307{
308 if (s_allocator_ptr == NULL) {
309 s_allocator_ptr = new Allocator<${{self.c_ident}}>;
310 }
311}
312''')
313
314 if not self.isGlobal:
315 # const Get methods for each field
316 code('// Const accessors methods for each field')
317 for dm in self.data_members.values():
318 code('''
319/** \\brief Const accessor method for ${{dm.ident}} field.
320 * \\return ${{dm.ident}} field
321 */
322const ${{dm.type.c_ident}}&
323get${{dm.ident}}() const
324{
325 return m_${{dm.ident}};
326}
327''')
328
329 # Non-const Get methods for each field
330 code('// Non const Accessors methods for each field')
331 for dm in self.data_members.values():
332 code('''
333/** \\brief Non-const accessor method for ${{dm.ident}} field.
334 * \\return ${{dm.ident}} field
335 */
336${{dm.type.c_ident}}&
337get${{dm.ident}}()
338{
339 return m_${{dm.ident}};
340}
341''')
342
343 #Set methods for each field
344 code('// Mutator methods for each field')
345 for dm in self.data_members.values():
346 code('''
347/** \\brief Mutator method for ${{dm.ident}} field */
348void
349set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
350{
351 m_${{dm.ident}} = local_${{dm.ident}};
352}
353''')
354
355 code('void print(std::ostream& out) const;')
356 code.dedent()
357 code(' //private:')
358 code.indent()
359
360 # Data members for each field
361 for dm in self.data_members.values():
362 if "abstract" not in dm:
363 const = ""
364 init = ""
365
366 # global structure
367 if self.isGlobal:
368 const = "static const "
369
370 # init value
371 if dm.init_code:
372 # only global structure can have init value here
373 assert self.isGlobal
374 init = " = %s" % (dm.init_code)
375
376 if "desc" in dm:
377 code('/** ${{dm["desc"]}} */')
378
379 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
380
381 if self.isMessage:
382 code('unsigned proc_id;')
383
384 code.dedent()
385 code('};')
386
387 code('''
388inline std::ostream&
389operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
390{
391 obj.print(out);
392 out << std::flush;
393 return out;
394}
395
396#endif // __${{self.c_ident}}_HH__
397''')
398
399 code.write(path, "%s.hh" % self.c_ident)
400
401 def printTypeCC(self, path):
402 code = self.symtab.codeFormatter()
403
404 code('''
405/** \\file ${{self.c_ident}}.cc
406 *
407 * Auto generated C++ code started by $__file__:$__line__
408 */
409
410#include <iostream>
411
412#include "mem/protocol/${{self.c_ident}}.hh"
413
414using namespace std;
415''')
416
305''')
306
307 if not self.isGlobal:
308 # const Get methods for each field
309 code('// Const accessors methods for each field')
310 for dm in self.data_members.values():
311 code('''
312/** \\brief Const accessor method for ${{dm.ident}} field.
313 * \\return ${{dm.ident}} field
314 */
315const ${{dm.type.c_ident}}&
316get${{dm.ident}}() const
317{
318 return m_${{dm.ident}};
319}
320''')
321
322 # Non-const Get methods for each field
323 code('// Non const Accessors methods for each field')
324 for dm in self.data_members.values():
325 code('''
326/** \\brief Non-const accessor method for ${{dm.ident}} field.
327 * \\return ${{dm.ident}} field
328 */
329${{dm.type.c_ident}}&
330get${{dm.ident}}()
331{
332 return m_${{dm.ident}};
333}
334''')
335
336 #Set methods for each field
337 code('// Mutator methods for each field')
338 for dm in self.data_members.values():
339 code('''
340/** \\brief Mutator method for ${{dm.ident}} field */
341void
342set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
343{
344 m_${{dm.ident}} = local_${{dm.ident}};
345}
346''')
347
348 code('void print(std::ostream& out) const;')
349 code.dedent()
350 code(' //private:')
351 code.indent()
352
353 # Data members for each field
354 for dm in self.data_members.values():
355 if "abstract" not in dm:
356 const = ""
357 init = ""
358
359 # global structure
360 if self.isGlobal:
361 const = "static const "
362
363 # init value
364 if dm.init_code:
365 # only global structure can have init value here
366 assert self.isGlobal
367 init = " = %s" % (dm.init_code)
368
369 if "desc" in dm:
370 code('/** ${{dm["desc"]}} */')
371
372 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
373
374 if self.isMessage:
375 code('unsigned proc_id;')
376
377 code.dedent()
378 code('};')
379
380 code('''
381inline std::ostream&
382operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
383{
384 obj.print(out);
385 out << std::flush;
386 return out;
387}
388
389#endif // __${{self.c_ident}}_HH__
390''')
391
392 code.write(path, "%s.hh" % self.c_ident)
393
394 def printTypeCC(self, path):
395 code = self.symtab.codeFormatter()
396
397 code('''
398/** \\file ${{self.c_ident}}.cc
399 *
400 * Auto generated C++ code started by $__file__:$__line__
401 */
402
403#include <iostream>
404
405#include "mem/protocol/${{self.c_ident}}.hh"
406
407using namespace std;
408''')
409
417 if self.isMessage:
418 code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
419 code('''
420/** \\brief Print the state of this object */
421void
422${{self.c_ident}}::print(ostream& out) const
423{
424 out << "[${{self.c_ident}}: ";
425''')
426
427 # For each field
428 code.indent()
429 for dm in self.data_members.values():
430 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
431
432 if self.isMessage:
433 code('out << "Time = " << getTime() << " ";')
434 code.dedent()
435
436 # Trailer
437 code('''
438 out << "]";
439}''')
440
441 code.write(path, "%s.cc" % self.c_ident)
442
443 def printEnumHH(self, path):
444 code = self.symtab.codeFormatter()
445 code('''
446/** \\file ${{self.c_ident}}.hh
447 *
448 * Auto generated C++ code started by $__file__:$__line__
449 */
450
451#ifndef __${{self.c_ident}}_HH__
452#define __${{self.c_ident}}_HH__
453
454#include <iostream>
455#include <string>
456
457#include "mem/ruby/common/Global.hh"
458
459// Class definition
460/** \\enum ${{self.c_ident}}
461 * \\brief ${{self.desc}}
462 */
463enum ${{self.c_ident}} {
464 ${{self.c_ident}}_FIRST,
465''')
466
467 code.indent()
468 # For each field
469 for i,(ident,enum) in enumerate(self.enums.iteritems()):
470 desc = enum.get("desc", "No description avaliable")
471 if i == 0:
472 init = ' = %s_FIRST' % self.c_ident
473 else:
474 init = ''
475 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
476 code.dedent()
477 code('''
478 ${{self.c_ident}}_NUM
479};
480
481// Code to convert from a string to the enumeration
482${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
483
484// Code to convert state to a string
485std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
486
487// Code to increment an enumeration type
488${{self.c_ident}} &operator++(${{self.c_ident}} &e);
489''')
490
491 # MachineType hack used to set the base component id for each Machine
492 if self.isMachineType:
493 code('''
494int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
495MachineType ${{self.c_ident}}_from_base_level(int);
496int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
497int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
498''')
499
500 for enum in self.enums.itervalues():
501 code('#define MACHINETYPE_${{enum.ident}} 1')
502
503 # Trailer
504 code('''
505std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
506
507#endif // __${{self.c_ident}}_HH__
508''')
509
510 code.write(path, "%s.hh" % self.c_ident)
511
512 def printEnumCC(self, path):
513 code = self.symtab.codeFormatter()
514 code('''
515/** \\file ${{self.c_ident}}.hh
516 *
517 * Auto generated C++ code started by $__file__:$__line__
518 */
519
520#include <iostream>
521#include <string>
522
523#include "mem/protocol/${{self.c_ident}}.hh"
524
525using namespace std;
526
527''')
528
529 if self.isMachineType:
530 for enum in self.enums.itervalues():
531 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
532
533 code('''
534// Code for output operator
535ostream&
536operator<<(ostream& out, const ${{self.c_ident}}& obj)
537{
538 out << ${{self.c_ident}}_to_string(obj);
539 out << flush;
540 return out;
541}
542
543// Code to convert state to a string
544string
545${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
546{
547 switch(obj) {
548''')
549
550 # For each field
551 code.indent()
552 for enum in self.enums.itervalues():
553 code(' case ${{self.c_ident}}_${{enum.ident}}:')
554 code(' return "${{enum.ident}}";')
555 code.dedent()
556
557 # Trailer
558 code('''
559 default:
560 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
561 return "";
562 }
563}
564
565// Code to convert from a string to the enumeration
566${{self.c_ident}}
567string_to_${{self.c_ident}}(const string& str)
568{
569''')
570
571 # For each field
572 start = ""
573 code.indent()
574 for enum in self.enums.itervalues():
575 code('${start}if (str == "${{enum.ident}}") {')
576 code(' return ${{self.c_ident}}_${{enum.ident}};')
577 start = "} else "
578 code.dedent()
579
580 code('''
581 } else {
582 WARN_EXPR(str);
583 ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
584 }
585}
586
587// Code to increment an enumeration type
588${{self.c_ident}}&
589operator++(${{self.c_ident}}& e)
590{
591 assert(e < ${{self.c_ident}}_NUM);
592 return e = ${{self.c_ident}}(e+1);
593}
594''')
595
596 # MachineType hack used to set the base level and number of
597 # components for each Machine
598 if self.isMachineType:
599 code('''
600/** \\brief returns the base vector index for each machine type to be
601 * used by NetDest
602 *
603 * \\return the base vector index for each machine type to be used by NetDest
604 * \\see NetDest.hh
605 */
606int
607${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
608{
609 switch(obj) {
610''')
611
612 # For each field
613 code.indent()
614 for i,enum in enumerate(self.enums.itervalues()):
615 code(' case ${{self.c_ident}}_${{enum.ident}}:')
616 code(' return $i;')
617 code.dedent()
618
619 # total num
620 code('''
621 case ${{self.c_ident}}_NUM:
622 return ${{len(self.enums)}};
623
624 default:
625 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
626 return -1;
627 }
628}
629
630/** \\brief returns the machine type for each base vector index used by NetDest
631 *
632 * \\return the MachineType
633 */
634MachineType
635${{self.c_ident}}_from_base_level(int type)
636{
637 switch(type) {
638''')
639
640 # For each field
641 code.indent()
642 for i,enum in enumerate(self.enums.itervalues()):
643 code(' case $i:')
644 code(' return ${{self.c_ident}}_${{enum.ident}};')
645 code.dedent()
646
647 # Trailer
648 code('''
649 default:
650 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
651 return MachineType_NUM;
652 }
653}
654
655/** \\brief The return value indicates the number of components created
656 * before a particular machine\'s components
657 *
658 * \\return the base number of components for each machine
659 */
660int
661${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
662{
663 int base = 0;
664 switch(obj) {
665''')
666
667 # For each field
668 code.indent()
669 code(' case ${{self.c_ident}}_NUM:')
670 for enum in reversed(self.enums.values()):
671 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
672 code(' case ${{self.c_ident}}_${{enum.ident}}:')
673 code(' break;')
674 code.dedent()
675
676 code('''
677 default:
678 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
679 return -1;
680 }
681
682 return base;
683}
684
685/** \\brief returns the total number of components for each machine
686 * \\return the total number of components for each machine
687 */
688int
689${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
690{
691 switch(obj) {
692''')
693
694 # For each field
695 for enum in self.enums.itervalues():
696 code('''
697 case ${{self.c_ident}}_${{enum.ident}}:
698 return ${{enum.ident}}_Controller::getNumControllers();
699''')
700
701 # total num
702 code('''
703 case ${{self.c_ident}}_NUM:
704 default:
705 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
706 return -1;
707 }
708}
709''')
710
711 # Write the file
712 code.write(path, "%s.cc" % self.c_ident)
713
714__all__ = [ "Type" ]
410 code('''
411/** \\brief Print the state of this object */
412void
413${{self.c_ident}}::print(ostream& out) const
414{
415 out << "[${{self.c_ident}}: ";
416''')
417
418 # For each field
419 code.indent()
420 for dm in self.data_members.values():
421 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
422
423 if self.isMessage:
424 code('out << "Time = " << getTime() << " ";')
425 code.dedent()
426
427 # Trailer
428 code('''
429 out << "]";
430}''')
431
432 code.write(path, "%s.cc" % self.c_ident)
433
434 def printEnumHH(self, path):
435 code = self.symtab.codeFormatter()
436 code('''
437/** \\file ${{self.c_ident}}.hh
438 *
439 * Auto generated C++ code started by $__file__:$__line__
440 */
441
442#ifndef __${{self.c_ident}}_HH__
443#define __${{self.c_ident}}_HH__
444
445#include <iostream>
446#include <string>
447
448#include "mem/ruby/common/Global.hh"
449
450// Class definition
451/** \\enum ${{self.c_ident}}
452 * \\brief ${{self.desc}}
453 */
454enum ${{self.c_ident}} {
455 ${{self.c_ident}}_FIRST,
456''')
457
458 code.indent()
459 # For each field
460 for i,(ident,enum) in enumerate(self.enums.iteritems()):
461 desc = enum.get("desc", "No description avaliable")
462 if i == 0:
463 init = ' = %s_FIRST' % self.c_ident
464 else:
465 init = ''
466 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
467 code.dedent()
468 code('''
469 ${{self.c_ident}}_NUM
470};
471
472// Code to convert from a string to the enumeration
473${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
474
475// Code to convert state to a string
476std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
477
478// Code to increment an enumeration type
479${{self.c_ident}} &operator++(${{self.c_ident}} &e);
480''')
481
482 # MachineType hack used to set the base component id for each Machine
483 if self.isMachineType:
484 code('''
485int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
486MachineType ${{self.c_ident}}_from_base_level(int);
487int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
488int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
489''')
490
491 for enum in self.enums.itervalues():
492 code('#define MACHINETYPE_${{enum.ident}} 1')
493
494 # Trailer
495 code('''
496std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
497
498#endif // __${{self.c_ident}}_HH__
499''')
500
501 code.write(path, "%s.hh" % self.c_ident)
502
503 def printEnumCC(self, path):
504 code = self.symtab.codeFormatter()
505 code('''
506/** \\file ${{self.c_ident}}.hh
507 *
508 * Auto generated C++ code started by $__file__:$__line__
509 */
510
511#include <iostream>
512#include <string>
513
514#include "mem/protocol/${{self.c_ident}}.hh"
515
516using namespace std;
517
518''')
519
520 if self.isMachineType:
521 for enum in self.enums.itervalues():
522 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
523
524 code('''
525// Code for output operator
526ostream&
527operator<<(ostream& out, const ${{self.c_ident}}& obj)
528{
529 out << ${{self.c_ident}}_to_string(obj);
530 out << flush;
531 return out;
532}
533
534// Code to convert state to a string
535string
536${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
537{
538 switch(obj) {
539''')
540
541 # For each field
542 code.indent()
543 for enum in self.enums.itervalues():
544 code(' case ${{self.c_ident}}_${{enum.ident}}:')
545 code(' return "${{enum.ident}}";')
546 code.dedent()
547
548 # Trailer
549 code('''
550 default:
551 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
552 return "";
553 }
554}
555
556// Code to convert from a string to the enumeration
557${{self.c_ident}}
558string_to_${{self.c_ident}}(const string& str)
559{
560''')
561
562 # For each field
563 start = ""
564 code.indent()
565 for enum in self.enums.itervalues():
566 code('${start}if (str == "${{enum.ident}}") {')
567 code(' return ${{self.c_ident}}_${{enum.ident}};')
568 start = "} else "
569 code.dedent()
570
571 code('''
572 } else {
573 WARN_EXPR(str);
574 ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
575 }
576}
577
578// Code to increment an enumeration type
579${{self.c_ident}}&
580operator++(${{self.c_ident}}& e)
581{
582 assert(e < ${{self.c_ident}}_NUM);
583 return e = ${{self.c_ident}}(e+1);
584}
585''')
586
587 # MachineType hack used to set the base level and number of
588 # components for each Machine
589 if self.isMachineType:
590 code('''
591/** \\brief returns the base vector index for each machine type to be
592 * used by NetDest
593 *
594 * \\return the base vector index for each machine type to be used by NetDest
595 * \\see NetDest.hh
596 */
597int
598${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
599{
600 switch(obj) {
601''')
602
603 # For each field
604 code.indent()
605 for i,enum in enumerate(self.enums.itervalues()):
606 code(' case ${{self.c_ident}}_${{enum.ident}}:')
607 code(' return $i;')
608 code.dedent()
609
610 # total num
611 code('''
612 case ${{self.c_ident}}_NUM:
613 return ${{len(self.enums)}};
614
615 default:
616 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
617 return -1;
618 }
619}
620
621/** \\brief returns the machine type for each base vector index used by NetDest
622 *
623 * \\return the MachineType
624 */
625MachineType
626${{self.c_ident}}_from_base_level(int type)
627{
628 switch(type) {
629''')
630
631 # For each field
632 code.indent()
633 for i,enum in enumerate(self.enums.itervalues()):
634 code(' case $i:')
635 code(' return ${{self.c_ident}}_${{enum.ident}};')
636 code.dedent()
637
638 # Trailer
639 code('''
640 default:
641 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
642 return MachineType_NUM;
643 }
644}
645
646/** \\brief The return value indicates the number of components created
647 * before a particular machine\'s components
648 *
649 * \\return the base number of components for each machine
650 */
651int
652${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
653{
654 int base = 0;
655 switch(obj) {
656''')
657
658 # For each field
659 code.indent()
660 code(' case ${{self.c_ident}}_NUM:')
661 for enum in reversed(self.enums.values()):
662 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
663 code(' case ${{self.c_ident}}_${{enum.ident}}:')
664 code(' break;')
665 code.dedent()
666
667 code('''
668 default:
669 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
670 return -1;
671 }
672
673 return base;
674}
675
676/** \\brief returns the total number of components for each machine
677 * \\return the total number of components for each machine
678 */
679int
680${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
681{
682 switch(obj) {
683''')
684
685 # For each field
686 for enum in self.enums.itervalues():
687 code('''
688 case ${{self.c_ident}}_${{enum.ident}}:
689 return ${{enum.ident}}_Controller::getNumControllers();
690''')
691
692 # total num
693 code('''
694 case ${{self.c_ident}}_NUM:
695 default:
696 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
697 return -1;
698 }
699}
700''')
701
702 # Write the file
703 code.write(path, "%s.cc" % self.c_ident)
704
705__all__ = [ "Type" ]