Type.py (7832:de7601e6e19d) Type.py (8086:bf0335d98250)
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
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
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
106 self.data_members = orderdict()
107
108 # Methods
109 self.methods = {}
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
146 def dataMemberAdd(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
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''')
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
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
292 # create a static factory method and a clone member
293 code('''
294static ${{self.c_ident}}*
295create()
296{
297 return new ${{self.c_ident}}();
298}
299
300${{self.c_ident}}*
301clone() const
302{
303 return new ${{self.c_ident}}(*this);
304}
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
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"
167 def methodAdd(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
175 def enumAdd(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):
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 if self.isMessage:
265 code('proc_id = other.proc_id;')
266
267 code.dedent()
268 code('}')
269
270 # ******** Full init constructor ********
271 if not self.isGlobal:
272 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
273 for dm in self.data_members.itervalues() ]
274
275 if self.isMessage:
276 params.append('const unsigned local_proc_id')
277
278 params = ', '.join(params)
279 code('${{self.c_ident}}($params)')
280
281 # Call superclass constructor
282 if "interface" in self:
283 code(' : ${{self["interface"]}}()')
284
285 code('{')
286 code.indent()
287 for dm in self.data_members.values():
288 code('m_${{dm.ident}} = local_${{dm.ident}};')
289 if "nextLineCallHack" in dm:
290 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
291
292 if self.isMessage:
293 code('proc_id = local_proc_id;')
294
295 code.dedent()
296 code('}')
297
298 # create a static factory method and a clone member
299 code('''
300static ${{self.c_ident}}*
301create()
302{
303 return new ${{self.c_ident}}();
304}
305
306${{self.c_ident}}*
307clone() const
308{
309 return new ${{self.c_ident}}(*this);
310}
311''')
312
313 if not self.isGlobal:
314 # const Get methods for each field
315 code('// Const accessors methods for each field')
316 for dm in self.data_members.values():
317 code('''
318/** \\brief Const accessor method for ${{dm.ident}} field.
319 * \\return ${{dm.ident}} field
320 */
321const ${{dm.type.c_ident}}&
322get${{dm.ident}}() const
323{
324 return m_${{dm.ident}};
325}
326''')
327
328 # Non-const Get methods for each field
329 code('// Non const Accessors methods for each field')
330 for dm in self.data_members.values():
331 code('''
332/** \\brief Non-const accessor method for ${{dm.ident}} field.
333 * \\return ${{dm.ident}} field
334 */
335${{dm.type.c_ident}}&
336get${{dm.ident}}()
337{
338 return m_${{dm.ident}};
339}
340''')
341
342 #Set methods for each field
343 code('// Mutator methods for each field')
344 for dm in self.data_members.values():
345 code('''
346/** \\brief Mutator method for ${{dm.ident}} field */
347void
348set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
349{
350 m_${{dm.ident}} = local_${{dm.ident}};
351}
352''')
353
354 code('void print(std::ostream& out) const;')
355 code.dedent()
356 code(' //private:')
357 code.indent()
358
359 # Data members for each field
360 for dm in self.data_members.values():
361 if "abstract" not in dm:
362 const = ""
363 init = ""
364
365 # global structure
366 if self.isGlobal:
367 const = "static const "
368
369 # init value
370 if dm.init_code:
371 # only global structure can have init value here
372 assert self.isGlobal
373 init = " = %s" % (dm.init_code)
374
375 if "desc" in dm:
376 code('/** ${{dm["desc"]}} */')
377
378 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
379
380 if self.isMessage:
381 code('unsigned proc_id;')
382
383 code.dedent()
384 code('};')
385
386 code('''
387inline std::ostream&
388operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
389{
390 obj.print(out);
391 out << std::flush;
392 return out;
393}
394
395#endif // __${{self.c_ident}}_HH__
396''')
397
398 code.write(path, "%s.hh" % self.c_ident)
399
400 def printTypeCC(self, path):
401 code = self.symtab.codeFormatter()
402
403 code('''
404/** \\file ${{self.c_ident}}.cc
405 *
406 * Auto generated C++ code started by $__file__:$__line__
407 */
408
409#include <iostream>
410
411#include "mem/protocol/${{self.c_ident}}.hh"
412
413using namespace std;
414''')
415
416 code('''
417/** \\brief Print the state of this object */
418void
419${{self.c_ident}}::print(ostream& out) const
420{
421 out << "[${{self.c_ident}}: ";
422''')
423
424 # For each field
425 code.indent()
426 for dm in self.data_members.values():
427 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
428
429 if self.isMessage:
430 code('out << "Time = " << getTime() << " ";')
431 code.dedent()
432
433 # Trailer
434 code('''
435 out << "]";
436}''')
437
438 code.write(path, "%s.cc" % self.c_ident)
439
440 def printEnumHH(self, path):
441 code = self.symtab.codeFormatter()
442 code('''
443/** \\file ${{self.c_ident}}.hh
444 *
445 * Auto generated C++ code started by $__file__:$__line__
446 */
447
448#ifndef __${{self.c_ident}}_HH__
449#define __${{self.c_ident}}_HH__
450
451#include <iostream>
452#include <string>
453
454#include "mem/ruby/common/Global.hh"
455''')
456 if self.isStateDecl:
457 code('#include "mem/protocol/AccessPermission.hh"')
449
458
459 code('''
460
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
461// Class definition
462/** \\enum ${{self.c_ident}}
463 * \\brief ${{self.desc}}
464 */
465enum ${{self.c_ident}} {
466 ${{self.c_ident}}_FIRST,
467''')
468
469 code.indent()
470 # For each field
471 for i,(ident,enum) in enumerate(self.enums.iteritems()):
472 desc = enum.get("desc", "No description avaliable")
473 if i == 0:
474 init = ' = %s_FIRST' % self.c_ident
475 else:
476 init = ''
477 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
478 code.dedent()
479 code('''
480 ${{self.c_ident}}_NUM
481};
482
483// Code to convert from a string to the enumeration
484${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
485
486// Code to convert state to a string
487std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
488
489// Code to increment an enumeration type
490${{self.c_ident}} &operator++(${{self.c_ident}} &e);
491''')
492
493 # MachineType hack used to set the base component id for each Machine
494 if self.isMachineType:
495 code('''
496int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
497MachineType ${{self.c_ident}}_from_base_level(int);
498int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
499int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
500''')
501
502 for enum in self.enums.itervalues():
503 code('#define MACHINETYPE_${{enum.ident}} 1')
504
505 if self.isStateDecl:
506 code('''
507
508// Code to convert the current state to an access permission
509AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
510
511''')
512
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 <cassert>
512#include <iostream>
513#include <string>
514
515#include "base/misc.hh"
516#include "mem/protocol/${{self.c_ident}}.hh"
517
518using namespace std;
519
520''')
521
513 # Trailer
514 code('''
515std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
516
517#endif // __${{self.c_ident}}_HH__
518''')
519
520 code.write(path, "%s.hh" % self.c_ident)
521
522 def printEnumCC(self, path):
523 code = self.symtab.codeFormatter()
524 code('''
525/** \\file ${{self.c_ident}}.hh
526 *
527 * Auto generated C++ code started by $__file__:$__line__
528 */
529
530#include <cassert>
531#include <iostream>
532#include <string>
533
534#include "base/misc.hh"
535#include "mem/protocol/${{self.c_ident}}.hh"
536
537using namespace std;
538
539''')
540
541 if self.isStateDecl:
542 code('''
543// Code to convert the current state to an access permission
544AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
545{
546 switch(obj) {
547''')
548 # For each case
549 code.indent()
550 for statePerm in self.statePermPairs:
551 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
552 code(' return AccessPermission_${{statePerm[1]}};')
553 code.dedent()
554 code ('''
555 default:
556 panic("Unknown state access permission converstion for ${{self.c_ident}}");
557 }
558}
559
560''')
561
522 if self.isMachineType:
523 for enum in self.enums.itervalues():
524 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
525
526 code('''
527// Code for output operator
528ostream&
529operator<<(ostream& out, const ${{self.c_ident}}& obj)
530{
531 out << ${{self.c_ident}}_to_string(obj);
532 out << flush;
533 return out;
534}
535
536// Code to convert state to a string
537string
538${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
539{
540 switch(obj) {
541''')
542
543 # For each field
544 code.indent()
545 for enum in self.enums.itervalues():
546 code(' case ${{self.c_ident}}_${{enum.ident}}:')
547 code(' return "${{enum.ident}}";')
548 code.dedent()
549
550 # Trailer
551 code('''
552 default:
553 panic("Invalid range for type ${{self.c_ident}}");
554 }
555}
556
557// Code to convert from a string to the enumeration
558${{self.c_ident}}
559string_to_${{self.c_ident}}(const string& str)
560{
561''')
562
563 # For each field
564 start = ""
565 code.indent()
566 for enum in self.enums.itervalues():
567 code('${start}if (str == "${{enum.ident}}") {')
568 code(' return ${{self.c_ident}}_${{enum.ident}};')
569 start = "} else "
570 code.dedent()
571
572 code('''
573 } else {
574 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
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 panic("Invalid range for type ${{self.c_ident}}");
617 }
618}
619
620/** \\brief returns the machine type for each base vector index used by NetDest
621 *
622 * \\return the MachineType
623 */
624MachineType
625${{self.c_ident}}_from_base_level(int type)
626{
627 switch(type) {
628''')
629
630 # For each field
631 code.indent()
632 for i,enum in enumerate(self.enums.itervalues()):
633 code(' case $i:')
634 code(' return ${{self.c_ident}}_${{enum.ident}};')
635 code.dedent()
636
637 # Trailer
638 code('''
639 default:
640 panic("Invalid range for type ${{self.c_ident}}");
641 }
642}
643
644/** \\brief The return value indicates the number of components created
645 * before a particular machine\'s components
646 *
647 * \\return the base number of components for each machine
648 */
649int
650${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
651{
652 int base = 0;
653 switch(obj) {
654''')
655
656 # For each field
657 code.indent()
658 code(' case ${{self.c_ident}}_NUM:')
659 for enum in reversed(self.enums.values()):
660 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
661 code(' case ${{self.c_ident}}_${{enum.ident}}:')
662 code(' break;')
663 code.dedent()
664
665 code('''
666 default:
667 panic("Invalid range for type ${{self.c_ident}}");
668 }
669
670 return base;
671}
672
673/** \\brief returns the total number of components for each machine
674 * \\return the total number of components for each machine
675 */
676int
677${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
678{
679 switch(obj) {
680''')
681
682 # For each field
683 for enum in self.enums.itervalues():
684 code('''
685 case ${{self.c_ident}}_${{enum.ident}}:
686 return ${{enum.ident}}_Controller::getNumControllers();
687''')
688
689 # total num
690 code('''
691 case ${{self.c_ident}}_NUM:
692 default:
693 panic("Invalid range for type ${{self.c_ident}}");
694 }
695}
696''')
697
698 # Write the file
699 code.write(path, "%s.cc" % self.c_ident)
700
701__all__ = [ "Type" ]
562 if self.isMachineType:
563 for enum in self.enums.itervalues():
564 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
565
566 code('''
567// Code for output operator
568ostream&
569operator<<(ostream& out, const ${{self.c_ident}}& obj)
570{
571 out << ${{self.c_ident}}_to_string(obj);
572 out << flush;
573 return out;
574}
575
576// Code to convert state to a string
577string
578${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
579{
580 switch(obj) {
581''')
582
583 # For each field
584 code.indent()
585 for enum in self.enums.itervalues():
586 code(' case ${{self.c_ident}}_${{enum.ident}}:')
587 code(' return "${{enum.ident}}";')
588 code.dedent()
589
590 # Trailer
591 code('''
592 default:
593 panic("Invalid range for type ${{self.c_ident}}");
594 }
595}
596
597// Code to convert from a string to the enumeration
598${{self.c_ident}}
599string_to_${{self.c_ident}}(const string& str)
600{
601''')
602
603 # For each field
604 start = ""
605 code.indent()
606 for enum in self.enums.itervalues():
607 code('${start}if (str == "${{enum.ident}}") {')
608 code(' return ${{self.c_ident}}_${{enum.ident}};')
609 start = "} else "
610 code.dedent()
611
612 code('''
613 } else {
614 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
615 }
616}
617
618// Code to increment an enumeration type
619${{self.c_ident}}&
620operator++(${{self.c_ident}}& e)
621{
622 assert(e < ${{self.c_ident}}_NUM);
623 return e = ${{self.c_ident}}(e+1);
624}
625''')
626
627 # MachineType hack used to set the base level and number of
628 # components for each Machine
629 if self.isMachineType:
630 code('''
631/** \\brief returns the base vector index for each machine type to be
632 * used by NetDest
633 *
634 * \\return the base vector index for each machine type to be used by NetDest
635 * \\see NetDest.hh
636 */
637int
638${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
639{
640 switch(obj) {
641''')
642
643 # For each field
644 code.indent()
645 for i,enum in enumerate(self.enums.itervalues()):
646 code(' case ${{self.c_ident}}_${{enum.ident}}:')
647 code(' return $i;')
648 code.dedent()
649
650 # total num
651 code('''
652 case ${{self.c_ident}}_NUM:
653 return ${{len(self.enums)}};
654
655 default:
656 panic("Invalid range for type ${{self.c_ident}}");
657 }
658}
659
660/** \\brief returns the machine type for each base vector index used by NetDest
661 *
662 * \\return the MachineType
663 */
664MachineType
665${{self.c_ident}}_from_base_level(int type)
666{
667 switch(type) {
668''')
669
670 # For each field
671 code.indent()
672 for i,enum in enumerate(self.enums.itervalues()):
673 code(' case $i:')
674 code(' return ${{self.c_ident}}_${{enum.ident}};')
675 code.dedent()
676
677 # Trailer
678 code('''
679 default:
680 panic("Invalid range for type ${{self.c_ident}}");
681 }
682}
683
684/** \\brief The return value indicates the number of components created
685 * before a particular machine\'s components
686 *
687 * \\return the base number of components for each machine
688 */
689int
690${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
691{
692 int base = 0;
693 switch(obj) {
694''')
695
696 # For each field
697 code.indent()
698 code(' case ${{self.c_ident}}_NUM:')
699 for enum in reversed(self.enums.values()):
700 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
701 code(' case ${{self.c_ident}}_${{enum.ident}}:')
702 code(' break;')
703 code.dedent()
704
705 code('''
706 default:
707 panic("Invalid range for type ${{self.c_ident}}");
708 }
709
710 return base;
711}
712
713/** \\brief returns the total number of components for each machine
714 * \\return the total number of components for each machine
715 */
716int
717${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
718{
719 switch(obj) {
720''')
721
722 # For each field
723 for enum in self.enums.itervalues():
724 code('''
725 case ${{self.c_ident}}_${{enum.ident}}:
726 return ${{enum.ident}}_Controller::getNumControllers();
727''')
728
729 # total num
730 code('''
731 case ${{self.c_ident}}_NUM:
732 default:
733 panic("Invalid range for type ${{self.c_ident}}");
734 }
735}
736''')
737
738 # Write the file
739 code.write(path, "%s.cc" % self.c_ident)
740
741__all__ = [ "Type" ]