Type.py (6999:f226c098c393) Type.py (7002:48a19d52d939)
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}}_H
203#define ${{self.c_ident}}_H
204
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}}_H
203#define ${{self.c_ident}}_H
204
205#include <iostream>
206
205#include "mem/ruby/common/Global.hh"
206#include "mem/gems_common/Allocator.hh"
207''')
208
209 for dm in self.data_members.values():
210 if not dm.type.isPrimitive:
211 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
212
213 parent = ""
214 if "interface" in self:
215 code('#include "mem/protocol/$0.hh"', self["interface"])
216 parent = " : public %s" % self["interface"]
217
218 code('''
219$klass ${{self.c_ident}}$parent {
220 public:
221 ${{self.c_ident}}()
222''', klass="class")
223
224 # Call superclass constructor
225 if "interface" in self:
226 code(' : ${{self["interface"]}}()')
227
228 code.indent()
229 code("{")
230 if not self.isGlobal:
231 code.indent()
232 for dm in self.data_members.values():
233 ident = dm.ident
234 if "default" in dm:
235 # look for default value
236 code('m_$ident = ${{dm["default"]}}; // default for this field')
237 elif "default" in dm.type:
238 # Look for the type default
239 tid = dm.type.c_ident
240 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
241 else:
242 code('// m_$ident has no default')
243 code.dedent()
244 code('}')
245
246 # ******** Default destructor ********
247 code('~${{self.c_ident}}() { };')
248
249 # ******** Full init constructor ********
250 if not self.isGlobal:
251 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
252 for dm in self.data_members.itervalues() ]
253
254 if self.isMessage:
255 params.append('const unsigned local_proc_id')
256
257 params = ', '.join(params)
258 code('${{self.c_ident}}($params)')
259
260 # Call superclass constructor
261 if "interface" in self:
262 code(' : ${{self["interface"]}}()')
263
264 code('{')
265 code.indent()
266 for dm in self.data_members.values():
267 code('m_${{dm.ident}} = local_${{dm.ident}};')
268 if "nextLineCallHack" in dm:
269 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
270
271 if self.isMessage:
272 code('proc_id = local_proc_id;')
273
274 code.dedent()
275 code('}')
276
277 # create a static factory method
278 if "interface" in self:
279 code('''
280static ${{self["interface"]}}* create() {
281 return new ${{self.c_ident}}();
282}
283''')
284
285 # ******** Message member functions ********
286 # FIXME: those should be moved into slicc file, slicc should
287 # support more of the c++ class inheritance
288
289 if self.isMessage:
290 code('''
291Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }
292void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }
293static Allocator<${{self.c_ident}}>* s_allocator_ptr;
294static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }}
295''')
296
297 if not self.isGlobal:
298 # const Get methods for each field
299 code('// Const accessors methods for each field')
300 for dm in self.data_members.values():
301 code('''
302/** \\brief Const accessor method for ${{dm.ident}} field.
303 * \\return ${{dm.ident}} field
304 */
305const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; }
306''')
307
308 # Non-const Get methods for each field
309 code('// Non const Accessors methods for each field')
310 for dm in self.data_members.values():
311 code('''
312/** \\brief Non-const accessor method for ${{dm.ident}} field.
313 * \\return ${{dm.ident}} field
314 */
315${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; }
316''')
317
318 #Set methods for each field
319 code('// Mutator methods for each field')
320 for dm in self.data_members.values():
321 code('''
322/** \\brief Mutator method for ${{dm.ident}} field */
323void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; }
324''')
325
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 public:
223 ${{self.c_ident}}()
224''', klass="class")
225
226 # Call superclass constructor
227 if "interface" in self:
228 code(' : ${{self["interface"]}}()')
229
230 code.indent()
231 code("{")
232 if not self.isGlobal:
233 code.indent()
234 for dm in self.data_members.values():
235 ident = dm.ident
236 if "default" in dm:
237 # look for default value
238 code('m_$ident = ${{dm["default"]}}; // default for this field')
239 elif "default" in dm.type:
240 # Look for the type default
241 tid = dm.type.c_ident
242 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
243 else:
244 code('// m_$ident has no default')
245 code.dedent()
246 code('}')
247
248 # ******** Default destructor ********
249 code('~${{self.c_ident}}() { };')
250
251 # ******** Full init constructor ********
252 if not self.isGlobal:
253 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
254 for dm in self.data_members.itervalues() ]
255
256 if self.isMessage:
257 params.append('const unsigned local_proc_id')
258
259 params = ', '.join(params)
260 code('${{self.c_ident}}($params)')
261
262 # Call superclass constructor
263 if "interface" in self:
264 code(' : ${{self["interface"]}}()')
265
266 code('{')
267 code.indent()
268 for dm in self.data_members.values():
269 code('m_${{dm.ident}} = local_${{dm.ident}};')
270 if "nextLineCallHack" in dm:
271 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
272
273 if self.isMessage:
274 code('proc_id = local_proc_id;')
275
276 code.dedent()
277 code('}')
278
279 # create a static factory method
280 if "interface" in self:
281 code('''
282static ${{self["interface"]}}* create() {
283 return new ${{self.c_ident}}();
284}
285''')
286
287 # ******** Message member functions ********
288 # FIXME: those should be moved into slicc file, slicc should
289 # support more of the c++ class inheritance
290
291 if self.isMessage:
292 code('''
293Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }
294void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }
295static Allocator<${{self.c_ident}}>* s_allocator_ptr;
296static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }}
297''')
298
299 if not self.isGlobal:
300 # const Get methods for each field
301 code('// Const accessors methods for each field')
302 for dm in self.data_members.values():
303 code('''
304/** \\brief Const accessor method for ${{dm.ident}} field.
305 * \\return ${{dm.ident}} field
306 */
307const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; }
308''')
309
310 # Non-const Get methods for each field
311 code('// Non const Accessors methods for each field')
312 for dm in self.data_members.values():
313 code('''
314/** \\brief Non-const accessor method for ${{dm.ident}} field.
315 * \\return ${{dm.ident}} field
316 */
317${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; }
318''')
319
320 #Set methods for each field
321 code('// Mutator methods for each field')
322 for dm in self.data_members.values():
323 code('''
324/** \\brief Mutator method for ${{dm.ident}} field */
325void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; }
326''')
327
326 code('void print(ostream& out) const;')
328 code('void print(std::ostream& out) const;')
327 code.dedent()
328 code(' //private:')
329 code.indent()
330
331 # Data members for each field
332 for dm in self.data_members.values():
333 if "abstract" not in dm:
334 const = ""
335 init = ""
336
337 # global structure
338 if self.isGlobal:
339 const = "static const "
340
341 # init value
342 if dm.init_code:
343 # only global structure can have init value here
344 assert self.isGlobal
345 init = " = %s" % (dm.init_code)
346
347 desc = ""
348 if "desc" in dm:
349 desc = '/**< %s */' % dm["desc"]
350
351 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc')
352
353 if self.isMessage:
354 code('unsigned proc_id;')
355
356 code.dedent()
357 code('};')
358
359 code('''
360// Output operator declaration
329 code.dedent()
330 code(' //private:')
331 code.indent()
332
333 # Data members for each field
334 for dm in self.data_members.values():
335 if "abstract" not in dm:
336 const = ""
337 init = ""
338
339 # global structure
340 if self.isGlobal:
341 const = "static const "
342
343 # init value
344 if dm.init_code:
345 # only global structure can have init value here
346 assert self.isGlobal
347 init = " = %s" % (dm.init_code)
348
349 desc = ""
350 if "desc" in dm:
351 desc = '/**< %s */' % dm["desc"]
352
353 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc')
354
355 if self.isMessage:
356 code('unsigned proc_id;')
357
358 code.dedent()
359 code('};')
360
361 code('''
362// Output operator declaration
361ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
363std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
362
363// Output operator definition
364extern inline
364
365// Output operator definition
366extern inline
365ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
367std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
366{
367 obj.print(out);
368{
369 obj.print(out);
368 out << flush;
370 out << std::flush;
369 return out;
370}
371
372#endif // ${{self.c_ident}}_H
373''')
374
375 code.write(path, "%s.hh" % self.c_ident)
376
377 def printTypeCC(self, path):
378 code = self.symtab.codeFormatter()
379
380 code('''
381/** \\file ${{self.c_ident}}.cc
382 *
383 * Auto generated C++ code started by $__file__:$__line__
384 */
385
371 return out;
372}
373
374#endif // ${{self.c_ident}}_H
375''')
376
377 code.write(path, "%s.hh" % self.c_ident)
378
379 def printTypeCC(self, path):
380 code = self.symtab.codeFormatter()
381
382 code('''
383/** \\file ${{self.c_ident}}.cc
384 *
385 * Auto generated C++ code started by $__file__:$__line__
386 */
387
388#include <iostream>
389
386#include "mem/protocol/${{self.c_ident}}.hh"
390#include "mem/protocol/${{self.c_ident}}.hh"
391
392using namespace std;
387''')
388
389 if self.isMessage:
390 code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
391 code('''
392/** \\brief Print the state of this object */
393void ${{self.c_ident}}::print(ostream& out) const
394{
395 out << "[${{self.c_ident}}: ";
396''')
397
398 # For each field
399 code.indent()
400 for dm in self.data_members.values():
401 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
402
403 if self.isMessage:
404 code('out << "Time = " << getTime() << " ";')
405 code.dedent()
406
407 # Trailer
408 code('''
409 out << "]";
410}''')
411
412 code.write(path, "%s.cc" % self.c_ident)
413
414 def printEnumHH(self, path):
415 code = self.symtab.codeFormatter()
416 code('''
417/** \\file ${{self.c_ident}}.hh
418 *
419 * Auto generated C++ code started by $__file__:$__line__
420 */
421#ifndef ${{self.c_ident}}_H
422#define ${{self.c_ident}}_H
423
393''')
394
395 if self.isMessage:
396 code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
397 code('''
398/** \\brief Print the state of this object */
399void ${{self.c_ident}}::print(ostream& out) const
400{
401 out << "[${{self.c_ident}}: ";
402''')
403
404 # For each field
405 code.indent()
406 for dm in self.data_members.values():
407 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
408
409 if self.isMessage:
410 code('out << "Time = " << getTime() << " ";')
411 code.dedent()
412
413 # Trailer
414 code('''
415 out << "]";
416}''')
417
418 code.write(path, "%s.cc" % self.c_ident)
419
420 def printEnumHH(self, path):
421 code = self.symtab.codeFormatter()
422 code('''
423/** \\file ${{self.c_ident}}.hh
424 *
425 * Auto generated C++ code started by $__file__:$__line__
426 */
427#ifndef ${{self.c_ident}}_H
428#define ${{self.c_ident}}_H
429
430#include <iostream>
431#include <string>
432
424#include "mem/ruby/common/Global.hh"
425
426/** \\enum ${{self.c_ident}}
427 * \\brief ${{self.desc}}
428 */
429enum ${{self.c_ident}} {
430 ${{self.c_ident}}_FIRST,
431''')
432
433 code.indent()
434 # For each field
435 for i,(ident,enum) in enumerate(self.enums.iteritems()):
436 desc = enum.get("desc", "No description avaliable")
437 if i == 0:
438 init = ' = %s_FIRST' % self.c_ident
439 else:
440 init = ''
441 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
442 code.dedent()
443 code('''
444 ${{self.c_ident}}_NUM
445};
433#include "mem/ruby/common/Global.hh"
434
435/** \\enum ${{self.c_ident}}
436 * \\brief ${{self.desc}}
437 */
438enum ${{self.c_ident}} {
439 ${{self.c_ident}}_FIRST,
440''')
441
442 code.indent()
443 # For each field
444 for i,(ident,enum) in enumerate(self.enums.iteritems()):
445 desc = enum.get("desc", "No description avaliable")
446 if i == 0:
447 init = ' = %s_FIRST' % self.c_ident
448 else:
449 init = ''
450 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
451 code.dedent()
452 code('''
453 ${{self.c_ident}}_NUM
454};
446${{self.c_ident}} string_to_${{self.c_ident}}(const string& str);
447string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
455${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
456std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
448${{self.c_ident}} &operator++(${{self.c_ident}} &e);
449''')
450
451 # MachineType hack used to set the base component id for each Machine
452 if self.isMachineType:
453 code('''
454int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
455MachineType ${{self.c_ident}}_from_base_level(int);
456int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
457int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
458''')
459
460 for enum in self.enums.itervalues():
461 code('#define MACHINETYPE_${{enum.ident}} 1')
462
463 # Trailer
464 code('''
457${{self.c_ident}} &operator++(${{self.c_ident}} &e);
458''')
459
460 # MachineType hack used to set the base component id for each Machine
461 if self.isMachineType:
462 code('''
463int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
464MachineType ${{self.c_ident}}_from_base_level(int);
465int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
466int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
467''')
468
469 for enum in self.enums.itervalues():
470 code('#define MACHINETYPE_${{enum.ident}} 1')
471
472 # Trailer
473 code('''
465ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
474std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
466
467#endif // ${{self.c_ident}}_H
468''')
469
470 code.write(path, "%s.hh" % self.c_ident)
471
472 def printEnumCC(self, path):
473 code = self.symtab.codeFormatter()
474 code('''
475/** \\file ${{self.c_ident}}.hh
476 *
477 * Auto generated C++ code started by $__file__:$__line__
478 */
479
475
476#endif // ${{self.c_ident}}_H
477''')
478
479 code.write(path, "%s.hh" % self.c_ident)
480
481 def printEnumCC(self, path):
482 code = self.symtab.codeFormatter()
483 code('''
484/** \\file ${{self.c_ident}}.hh
485 *
486 * Auto generated C++ code started by $__file__:$__line__
487 */
488
489#include <iostream>
490#include <string>
491
480#include "mem/protocol/${{self.c_ident}}.hh"
481
492#include "mem/protocol/${{self.c_ident}}.hh"
493
494using namespace std;
495
482''')
483
484 if self.isMachineType:
485 for enum in self.enums.itervalues():
486 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
487
488 code('''
489ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
490{
491 out << ${{self.c_ident}}_to_string(obj);
492 out << flush;
493 return out;
494}
495
496string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
497{
498 switch(obj) {
499''')
500
501 # For each field
502 code.indent()
503 for enum in self.enums.itervalues():
504 code(' case ${{self.c_ident}}_${{enum.ident}}:')
505 code(' return "${{enum.ident}}";')
506 code.dedent()
507
508 # Trailer
509 code('''
510 default:
511 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
512 return "";
513 }
514}
515
516${{self.c_ident}} string_to_${{self.c_ident}}(const string& str)
517{
518''')
519
520 # For each field
521 code.indent()
522 code("if (false) {")
523 start = "} else "
524 for enum in self.enums.itervalues():
525 code('${start}if (str == "${{enum.ident}}") {')
526 code(' return ${{self.c_ident}}_${{enum.ident}};')
527 code.dedent()
528
529 code('''
530 } else {
531 WARN_EXPR(str);
532 ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
533 }
534}
535
536${{self.c_ident}}& operator++(${{self.c_ident}}& e) {
537 assert(e < ${{self.c_ident}}_NUM);
538 return e = ${{self.c_ident}}(e+1);
539}
540''')
541
542 # MachineType hack used to set the base level and number of
543 # components for each Machine
544 if self.isMachineType:
545 code('''
546/** \\brief returns the base vector index for each machine type to be used by NetDest
547 *
548 * \\return the base vector index for each machine type to be used by NetDest
549 * \\see NetDest.hh
550 */
551int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
552{
553 switch(obj) {
554''')
555
556 # For each field
557 code.indent()
558 for i,enum in enumerate(self.enums.itervalues()):
559 code(' case ${{self.c_ident}}_${{enum.ident}}:')
560 code(' return $i;')
561 code.dedent()
562
563 # total num
564 code('''
565 case ${{self.c_ident}}_NUM:
566 return ${{len(self.enums)}};
567
568 default:
569 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
570 return -1;
571 }
572}
573
574/** \\brief returns the machine type for each base vector index used by NetDest
575 *
576 * \\return the MachineTYpe
577 */
578MachineType ${{self.c_ident}}_from_base_level(int type)
579{
580 switch(type) {
581''')
582
583 # For each field
584 code.indent()
585 for i,enum in enumerate(self.enums.itervalues()):
586 code(' case $i:')
587 code(' return ${{self.c_ident}}_${{enum.ident}};')
588 code.dedent()
589
590 # Trailer
591 code('''
592 default:
593 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
594 return MachineType_NUM;
595 }
596}
597
598/** \\brief The return value indicates the number of components created
599 * before a particular machine\'s components
600 *
601 * \\return the base number of components for each machine
602 */
603int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
604{
605 int base = 0;
606 switch(obj) {
607''')
608
609 # For each field
610 code.indent()
611 code(' case ${{self.c_ident}}_NUM:')
612 for enum in reversed(self.enums.values()):
613 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
614 code(' case ${{self.c_ident}}_${{enum.ident}}:')
615 code(' break;')
616 code.dedent()
617
618 code('''
619 default:
620 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
621 return -1;
622 }
623
624 return base;
625}
626
627/** \\brief returns the total number of components for each machine
628 * \\return the total number of components for each machine
629 */
630int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
631{
632 switch(obj) {
633''')
634
635 # For each field
636 for enum in self.enums.itervalues():
637 code('''
638 case ${{self.c_ident}}_${{enum.ident}}:
639 return ${{enum.ident}}_Controller::getNumControllers();
640''')
641
642 # total num
643 code('''
644 case ${{self.c_ident}}_NUM:
645 default:
646 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
647 return -1;
648 }
649}
650''')
651
652 # Write the file
653 code.write(path, "%s.cc" % self.c_ident)
654
655__all__ = [ "Type" ]
496''')
497
498 if self.isMachineType:
499 for enum in self.enums.itervalues():
500 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
501
502 code('''
503ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
504{
505 out << ${{self.c_ident}}_to_string(obj);
506 out << flush;
507 return out;
508}
509
510string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
511{
512 switch(obj) {
513''')
514
515 # For each field
516 code.indent()
517 for enum in self.enums.itervalues():
518 code(' case ${{self.c_ident}}_${{enum.ident}}:')
519 code(' return "${{enum.ident}}";')
520 code.dedent()
521
522 # Trailer
523 code('''
524 default:
525 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
526 return "";
527 }
528}
529
530${{self.c_ident}} string_to_${{self.c_ident}}(const string& str)
531{
532''')
533
534 # For each field
535 code.indent()
536 code("if (false) {")
537 start = "} else "
538 for enum in self.enums.itervalues():
539 code('${start}if (str == "${{enum.ident}}") {')
540 code(' return ${{self.c_ident}}_${{enum.ident}};')
541 code.dedent()
542
543 code('''
544 } else {
545 WARN_EXPR(str);
546 ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
547 }
548}
549
550${{self.c_ident}}& operator++(${{self.c_ident}}& e) {
551 assert(e < ${{self.c_ident}}_NUM);
552 return e = ${{self.c_ident}}(e+1);
553}
554''')
555
556 # MachineType hack used to set the base level and number of
557 # components for each Machine
558 if self.isMachineType:
559 code('''
560/** \\brief returns the base vector index for each machine type to be used by NetDest
561 *
562 * \\return the base vector index for each machine type to be used by NetDest
563 * \\see NetDest.hh
564 */
565int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
566{
567 switch(obj) {
568''')
569
570 # For each field
571 code.indent()
572 for i,enum in enumerate(self.enums.itervalues()):
573 code(' case ${{self.c_ident}}_${{enum.ident}}:')
574 code(' return $i;')
575 code.dedent()
576
577 # total num
578 code('''
579 case ${{self.c_ident}}_NUM:
580 return ${{len(self.enums)}};
581
582 default:
583 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
584 return -1;
585 }
586}
587
588/** \\brief returns the machine type for each base vector index used by NetDest
589 *
590 * \\return the MachineTYpe
591 */
592MachineType ${{self.c_ident}}_from_base_level(int type)
593{
594 switch(type) {
595''')
596
597 # For each field
598 code.indent()
599 for i,enum in enumerate(self.enums.itervalues()):
600 code(' case $i:')
601 code(' return ${{self.c_ident}}_${{enum.ident}};')
602 code.dedent()
603
604 # Trailer
605 code('''
606 default:
607 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
608 return MachineType_NUM;
609 }
610}
611
612/** \\brief The return value indicates the number of components created
613 * before a particular machine\'s components
614 *
615 * \\return the base number of components for each machine
616 */
617int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
618{
619 int base = 0;
620 switch(obj) {
621''')
622
623 # For each field
624 code.indent()
625 code(' case ${{self.c_ident}}_NUM:')
626 for enum in reversed(self.enums.values()):
627 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
628 code(' case ${{self.c_ident}}_${{enum.ident}}:')
629 code(' break;')
630 code.dedent()
631
632 code('''
633 default:
634 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
635 return -1;
636 }
637
638 return base;
639}
640
641/** \\brief returns the total number of components for each machine
642 * \\return the total number of components for each machine
643 */
644int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
645{
646 switch(obj) {
647''')
648
649 # For each field
650 for enum in self.enums.itervalues():
651 code('''
652 case ${{self.c_ident}}_${{enum.ident}}:
653 return ${{enum.ident}}_Controller::getNumControllers();
654''')
655
656 # total num
657 code('''
658 case ${{self.c_ident}}_NUM:
659 default:
660 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
661 return -1;
662 }
663}
664''')
665
666 # Write the file
667 code.write(path, "%s.cc" % self.c_ident)
668
669__all__ = [ "Type" ]