Type.py (8188:20dbef14192d) Type.py (8266:66a3187a6714)
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
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
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 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
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:
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
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
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 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
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 = " << getTime() << " ";')
418 code('out << "Time = " << getTime() * g_eventQueue_ptr->getClock() << " ";')
419 code.dedent()
420
421 # Trailer
422 code('''
423 out << "]";
424}''')
425
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#include "mem/ruby/common/Global.hh"
443''')
444 if self.isStateDecl:
445 code('#include "mem/protocol/AccessPermission.hh"')
446
447 code('''
448
449// Class definition
450/** \\enum ${{self.c_ident}}
451 * \\brief ${{self.desc}}
452 */
453enum ${{self.c_ident}} {
454 ${{self.c_ident}}_FIRST,
455''')
456
457 code.indent()
458 # For each field
459 for i,(ident,enum) in enumerate(self.enums.iteritems()):
460 desc = enum.get("desc", "No description avaliable")
461 if i == 0:
462 init = ' = %s_FIRST' % self.c_ident
463 else:
464 init = ''
465 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
466 code.dedent()
467 code('''
468 ${{self.c_ident}}_NUM
469};
470
471// Code to convert from a string to the enumeration
472${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
473
474// Code to convert state to a string
475std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
476
477// Code to increment an enumeration type
478${{self.c_ident}} &operator++(${{self.c_ident}} &e);
479''')
480
481 # MachineType hack used to set the base component id for each Machine
482 if self.isMachineType:
483 code('''
484int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
485MachineType ${{self.c_ident}}_from_base_level(int);
486int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
487int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
488''')
489
490 for enum in self.enums.itervalues():
491 code('#define MACHINETYPE_${{enum.ident}} 1')
492
493 if self.isStateDecl:
494 code('''
495
496// Code to convert the current state to an access permission
497AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
498
499''')
500
501 # Trailer
502 code('''
503std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
504
505#endif // __${{self.c_ident}}_HH__
506''')
507
508 code.write(path, "%s.hh" % self.c_ident)
509
510 def printEnumCC(self, path):
511 code = self.symtab.codeFormatter()
512 code('''
513/** \\file ${{self.c_ident}}.hh
514 *
515 * Auto generated C++ code started by $__file__:$__line__
516 */
517
518#include <cassert>
519#include <iostream>
520#include <string>
521
522#include "base/misc.hh"
523#include "mem/protocol/${{self.c_ident}}.hh"
524
525using namespace std;
526
527''')
528
529 if self.isStateDecl:
530 code('''
531// Code to convert the current state to an access permission
532AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
533{
534 switch(obj) {
535''')
536 # For each case
537 code.indent()
538 for statePerm in self.statePermPairs:
539 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
540 code(' return AccessPermission_${{statePerm[1]}};')
541 code.dedent()
542 code ('''
543 default:
544 panic("Unknown state access permission converstion for ${{self.c_ident}}");
545 }
546}
547
548''')
549
550 if self.isMachineType:
551 for enum in self.enums.itervalues():
552 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
553
554 code('''
555// Code for output operator
556ostream&
557operator<<(ostream& out, const ${{self.c_ident}}& obj)
558{
559 out << ${{self.c_ident}}_to_string(obj);
560 out << flush;
561 return out;
562}
563
564// Code to convert state to a string
565string
566${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
567{
568 switch(obj) {
569''')
570
571 # For each field
572 code.indent()
573 for enum in self.enums.itervalues():
574 code(' case ${{self.c_ident}}_${{enum.ident}}:')
575 code(' return "${{enum.ident}}";')
576 code.dedent()
577
578 # Trailer
579 code('''
580 default:
581 panic("Invalid range for type ${{self.c_ident}}");
582 }
583}
584
585// Code to convert from a string to the enumeration
586${{self.c_ident}}
587string_to_${{self.c_ident}}(const string& str)
588{
589''')
590
591 # For each field
592 start = ""
593 code.indent()
594 for enum in self.enums.itervalues():
595 code('${start}if (str == "${{enum.ident}}") {')
596 code(' return ${{self.c_ident}}_${{enum.ident}};')
597 start = "} else "
598 code.dedent()
599
600 code('''
601 } else {
602 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
603 }
604}
605
606// Code to increment an enumeration type
607${{self.c_ident}}&
608operator++(${{self.c_ident}}& e)
609{
610 assert(e < ${{self.c_ident}}_NUM);
611 return e = ${{self.c_ident}}(e+1);
612}
613''')
614
615 # MachineType hack used to set the base level and number of
616 # components for each Machine
617 if self.isMachineType:
618 code('''
619/** \\brief returns the base vector index for each machine type to be
620 * used by NetDest
621 *
622 * \\return the base vector index for each machine type to be used by NetDest
623 * \\see NetDest.hh
624 */
625int
626${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
627{
628 switch(obj) {
629''')
630
631 # For each field
632 code.indent()
633 for i,enum in enumerate(self.enums.itervalues()):
634 code(' case ${{self.c_ident}}_${{enum.ident}}:')
635 code(' return $i;')
636 code.dedent()
637
638 # total num
639 code('''
640 case ${{self.c_ident}}_NUM:
641 return ${{len(self.enums)}};
642
643 default:
644 panic("Invalid range for type ${{self.c_ident}}");
645 }
646}
647
648/** \\brief returns the machine type for each base vector index used by NetDest
649 *
650 * \\return the MachineType
651 */
652MachineType
653${{self.c_ident}}_from_base_level(int type)
654{
655 switch(type) {
656''')
657
658 # For each field
659 code.indent()
660 for i,enum in enumerate(self.enums.itervalues()):
661 code(' case $i:')
662 code(' return ${{self.c_ident}}_${{enum.ident}};')
663 code.dedent()
664
665 # Trailer
666 code('''
667 default:
668 panic("Invalid range for type ${{self.c_ident}}");
669 }
670}
671
672/** \\brief The return value indicates the number of components created
673 * before a particular machine\'s components
674 *
675 * \\return the base number of components for each machine
676 */
677int
678${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
679{
680 int base = 0;
681 switch(obj) {
682''')
683
684 # For each field
685 code.indent()
686 code(' case ${{self.c_ident}}_NUM:')
687 for enum in reversed(self.enums.values()):
688 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
689 code(' case ${{self.c_ident}}_${{enum.ident}}:')
690 code(' break;')
691 code.dedent()
692
693 code('''
694 default:
695 panic("Invalid range for type ${{self.c_ident}}");
696 }
697
698 return base;
699}
700
701/** \\brief returns the total number of components for each machine
702 * \\return the total number of components for each machine
703 */
704int
705${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
706{
707 switch(obj) {
708''')
709
710 # For each field
711 for enum in self.enums.itervalues():
712 code('''
713 case ${{self.c_ident}}_${{enum.ident}}:
714 return ${{enum.ident}}_Controller::getNumControllers();
715''')
716
717 # total num
718 code('''
719 case ${{self.c_ident}}_NUM:
720 default:
721 panic("Invalid range for type ${{self.c_ident}}");
722 }
723}
724''')
725
726 # Write the file
727 code.write(path, "%s.cc" % self.c_ident)
728
729__all__ = [ "Type" ]
419 code.dedent()
420
421 # Trailer
422 code('''
423 out << "]";
424}''')
425
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#include "mem/ruby/common/Global.hh"
443''')
444 if self.isStateDecl:
445 code('#include "mem/protocol/AccessPermission.hh"')
446
447 code('''
448
449// Class definition
450/** \\enum ${{self.c_ident}}
451 * \\brief ${{self.desc}}
452 */
453enum ${{self.c_ident}} {
454 ${{self.c_ident}}_FIRST,
455''')
456
457 code.indent()
458 # For each field
459 for i,(ident,enum) in enumerate(self.enums.iteritems()):
460 desc = enum.get("desc", "No description avaliable")
461 if i == 0:
462 init = ' = %s_FIRST' % self.c_ident
463 else:
464 init = ''
465 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
466 code.dedent()
467 code('''
468 ${{self.c_ident}}_NUM
469};
470
471// Code to convert from a string to the enumeration
472${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
473
474// Code to convert state to a string
475std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
476
477// Code to increment an enumeration type
478${{self.c_ident}} &operator++(${{self.c_ident}} &e);
479''')
480
481 # MachineType hack used to set the base component id for each Machine
482 if self.isMachineType:
483 code('''
484int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
485MachineType ${{self.c_ident}}_from_base_level(int);
486int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
487int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
488''')
489
490 for enum in self.enums.itervalues():
491 code('#define MACHINETYPE_${{enum.ident}} 1')
492
493 if self.isStateDecl:
494 code('''
495
496// Code to convert the current state to an access permission
497AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
498
499''')
500
501 # Trailer
502 code('''
503std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
504
505#endif // __${{self.c_ident}}_HH__
506''')
507
508 code.write(path, "%s.hh" % self.c_ident)
509
510 def printEnumCC(self, path):
511 code = self.symtab.codeFormatter()
512 code('''
513/** \\file ${{self.c_ident}}.hh
514 *
515 * Auto generated C++ code started by $__file__:$__line__
516 */
517
518#include <cassert>
519#include <iostream>
520#include <string>
521
522#include "base/misc.hh"
523#include "mem/protocol/${{self.c_ident}}.hh"
524
525using namespace std;
526
527''')
528
529 if self.isStateDecl:
530 code('''
531// Code to convert the current state to an access permission
532AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
533{
534 switch(obj) {
535''')
536 # For each case
537 code.indent()
538 for statePerm in self.statePermPairs:
539 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
540 code(' return AccessPermission_${{statePerm[1]}};')
541 code.dedent()
542 code ('''
543 default:
544 panic("Unknown state access permission converstion for ${{self.c_ident}}");
545 }
546}
547
548''')
549
550 if self.isMachineType:
551 for enum in self.enums.itervalues():
552 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
553
554 code('''
555// Code for output operator
556ostream&
557operator<<(ostream& out, const ${{self.c_ident}}& obj)
558{
559 out << ${{self.c_ident}}_to_string(obj);
560 out << flush;
561 return out;
562}
563
564// Code to convert state to a string
565string
566${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
567{
568 switch(obj) {
569''')
570
571 # For each field
572 code.indent()
573 for enum in self.enums.itervalues():
574 code(' case ${{self.c_ident}}_${{enum.ident}}:')
575 code(' return "${{enum.ident}}";')
576 code.dedent()
577
578 # Trailer
579 code('''
580 default:
581 panic("Invalid range for type ${{self.c_ident}}");
582 }
583}
584
585// Code to convert from a string to the enumeration
586${{self.c_ident}}
587string_to_${{self.c_ident}}(const string& str)
588{
589''')
590
591 # For each field
592 start = ""
593 code.indent()
594 for enum in self.enums.itervalues():
595 code('${start}if (str == "${{enum.ident}}") {')
596 code(' return ${{self.c_ident}}_${{enum.ident}};')
597 start = "} else "
598 code.dedent()
599
600 code('''
601 } else {
602 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
603 }
604}
605
606// Code to increment an enumeration type
607${{self.c_ident}}&
608operator++(${{self.c_ident}}& e)
609{
610 assert(e < ${{self.c_ident}}_NUM);
611 return e = ${{self.c_ident}}(e+1);
612}
613''')
614
615 # MachineType hack used to set the base level and number of
616 # components for each Machine
617 if self.isMachineType:
618 code('''
619/** \\brief returns the base vector index for each machine type to be
620 * used by NetDest
621 *
622 * \\return the base vector index for each machine type to be used by NetDest
623 * \\see NetDest.hh
624 */
625int
626${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
627{
628 switch(obj) {
629''')
630
631 # For each field
632 code.indent()
633 for i,enum in enumerate(self.enums.itervalues()):
634 code(' case ${{self.c_ident}}_${{enum.ident}}:')
635 code(' return $i;')
636 code.dedent()
637
638 # total num
639 code('''
640 case ${{self.c_ident}}_NUM:
641 return ${{len(self.enums)}};
642
643 default:
644 panic("Invalid range for type ${{self.c_ident}}");
645 }
646}
647
648/** \\brief returns the machine type for each base vector index used by NetDest
649 *
650 * \\return the MachineType
651 */
652MachineType
653${{self.c_ident}}_from_base_level(int type)
654{
655 switch(type) {
656''')
657
658 # For each field
659 code.indent()
660 for i,enum in enumerate(self.enums.itervalues()):
661 code(' case $i:')
662 code(' return ${{self.c_ident}}_${{enum.ident}};')
663 code.dedent()
664
665 # Trailer
666 code('''
667 default:
668 panic("Invalid range for type ${{self.c_ident}}");
669 }
670}
671
672/** \\brief The return value indicates the number of components created
673 * before a particular machine\'s components
674 *
675 * \\return the base number of components for each machine
676 */
677int
678${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
679{
680 int base = 0;
681 switch(obj) {
682''')
683
684 # For each field
685 code.indent()
686 code(' case ${{self.c_ident}}_NUM:')
687 for enum in reversed(self.enums.values()):
688 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
689 code(' case ${{self.c_ident}}_${{enum.ident}}:')
690 code(' break;')
691 code.dedent()
692
693 code('''
694 default:
695 panic("Invalid range for type ${{self.c_ident}}");
696 }
697
698 return base;
699}
700
701/** \\brief returns the total number of components for each machine
702 * \\return the total number of components for each machine
703 */
704int
705${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
706{
707 switch(obj) {
708''')
709
710 # For each field
711 for enum in self.enums.itervalues():
712 code('''
713 case ${{self.c_ident}}_${{enum.ident}}:
714 return ${{enum.ident}}_Controller::getNumControllers();
715''')
716
717 # total num
718 code('''
719 case ${{self.c_ident}}_NUM:
720 default:
721 panic("Invalid range for type ${{self.c_ident}}");
722 }
723}
724''')
725
726 # Write the file
727 code.write(path, "%s.cc" % self.c_ident)
728
729__all__ = [ "Type" ]