Type.py (9206:f6483789d23a) Type.py (9219:258753d3bc47)
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
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):
187 def writeCodeFiles(self, path, includes):
188 if self.isExternal:
189 # Do nothing
190 pass
191 elif self.isEnumeration:
192 self.printEnumHH(path)
193 self.printEnumCC(path)
194 else:
195 # User defined structs and messages
196 self.printTypeHH(path)
197 self.printTypeCC(path)
198
199 def printTypeHH(self, path):
200 code = self.symtab.codeFormatter()
201 code('''
202/** \\file ${{self.c_ident}}.hh
203 *
204 *
205 * Auto generated C++ code started by $__file__:$__line__
206 */
207
208#ifndef __${{self.c_ident}}_HH__
209#define __${{self.c_ident}}_HH__
210
211#include <iostream>
212
213#include "mem/ruby/common/Global.hh"
214''')
215
216 for dm in self.data_members.values():
217 if not dm.type.isPrimitive:
218 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
219
220 parent = ""
221 if "interface" in self:
222 code('#include "mem/protocol/$0.hh"', self["interface"])
223 parent = " : public %s" % self["interface"]
224
225 code('''
226$klass ${{self.c_ident}}$parent
227{
228 public:
229 ${{self.c_ident}}()
230 {
231''', klass="class")
232
233 code.indent()
234 if not self.isGlobal:
235 code.indent()
236 for dm in self.data_members.values():
237 ident = dm.ident
238 if "default" in dm:
239 # look for default value
240 code('m_$ident = ${{dm["default"]}}; // default for this field')
241 elif "default" in dm.type:
242 # Look for the type default
243 tid = dm.type.c_ident
244 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
245 else:
246 code('// m_$ident has no default')
247 code.dedent()
248 code('}')
249
250 # ******** Copy constructor ********
251 if not self.isGlobal:
252 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
253
254 # Call superclass constructor
255 if "interface" in self:
256 code(' : ${{self["interface"]}}(other)')
257
258 code('{')
259 code.indent()
260
261 for dm in self.data_members.values():
262 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
263
264 code.dedent()
265 code('}')
266
267 # ******** Full init constructor ********
268 if not self.isGlobal:
269 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
270 for dm in self.data_members.itervalues() ]
271
272 params = ', '.join(params)
273 code('${{self.c_ident}}($params)')
274
275 # Call superclass constructor
276 if "interface" in self:
277 code(' : ${{self["interface"]}}()')
278
279 code('{')
280 code.indent()
281 for dm in self.data_members.values():
282 code('m_${{dm.ident}} = local_${{dm.ident}};')
283 if "nextLineCallHack" in dm:
284 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
285
286 code.dedent()
287 code('}')
288
289 # create a static factory method and a clone member
290 code('''
291static ${{self.c_ident}}*
292create()
293{
294 return new ${{self.c_ident}}();
295}
296
297${{self.c_ident}}*
298clone() const
299{
300 return new ${{self.c_ident}}(*this);
301}
302''')
303
304 if not self.isGlobal:
305 # const Get methods for each field
306 code('// Const accessors methods for each field')
307 for dm in self.data_members.values():
308 code('''
309/** \\brief Const accessor method for ${{dm.ident}} field.
310 * \\return ${{dm.ident}} field
311 */
312const ${{dm.type.c_ident}}&
313get${{dm.ident}}() const
314{
315 return m_${{dm.ident}};
316}
317''')
318
319 # Non-const Get methods for each field
320 code('// Non const Accessors methods for each field')
321 for dm in self.data_members.values():
322 code('''
323/** \\brief Non-const accessor method for ${{dm.ident}} field.
324 * \\return ${{dm.ident}} field
325 */
326${{dm.type.c_ident}}&
327get${{dm.ident}}()
328{
329 return m_${{dm.ident}};
330}
331''')
332
333 #Set methods for each field
334 code('// Mutator methods for each field')
335 for dm in self.data_members.values():
336 code('''
337/** \\brief Mutator method for ${{dm.ident}} field */
338void
339set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
340{
341 m_${{dm.ident}} = local_${{dm.ident}};
342}
343''')
344
345 code('void print(std::ostream& out) const;')
346 code.dedent()
347 code(' //private:')
348 code.indent()
349
350 # Data members for each field
351 for dm in self.data_members.values():
352 if "abstract" not in dm:
353 const = ""
354 init = ""
355
356 # global structure
357 if self.isGlobal:
358 const = "static const "
359
360 # init value
361 if dm.init_code:
362 # only global structure can have init value here
363 assert self.isGlobal
364 init = " = %s" % (dm.init_code)
365
366 if "desc" in dm:
367 code('/** ${{dm["desc"]}} */')
368
369 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
370
371 code.dedent()
372 code('};')
373
374 code('''
375inline std::ostream&
376operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
377{
378 obj.print(out);
379 out << std::flush;
380 return out;
381}
382
383#endif // __${{self.c_ident}}_HH__
384''')
385
386 code.write(path, "%s.hh" % self.c_ident)
387
388 def printTypeCC(self, path):
389 code = self.symtab.codeFormatter()
390
391 code('''
392/** \\file ${{self.c_ident}}.cc
393 *
394 * Auto generated C++ code started by $__file__:$__line__
395 */
396
397#include <iostream>
398
399#include "mem/protocol/${{self.c_ident}}.hh"
400
401using namespace std;
402''')
403
404 code('''
405/** \\brief Print the state of this object */
406void
407${{self.c_ident}}::print(ostream& out) const
408{
409 out << "[${{self.c_ident}}: ";
410''')
411
412 # For each field
413 code.indent()
414 for dm in self.data_members.values():
415 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
416
417 if self.isMessage:
418 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";')
419 code.dedent()
420
421 # Trailer
422 code('''
423 out << "]";
424}''')
425
426 code.write(path, "%s.cc" % self.c_ident)
427
428 def printEnumHH(self, path):
429 code = self.symtab.codeFormatter()
430 code('''
431/** \\file ${{self.c_ident}}.hh
432 *
433 * Auto generated C++ code started by $__file__:$__line__
434 */
435
436#ifndef __${{self.c_ident}}_HH__
437#define __${{self.c_ident}}_HH__
438
439#include <iostream>
440#include <string>
441
442''')
443 if self.isStateDecl:
444 code('#include "mem/protocol/AccessPermission.hh"')
445
446 if self.isMachineType:
447 code('#include "base/misc.hh"')
448 code('#include "mem/protocol/GenericMachineType.hh"')
449 code('#include "mem/ruby/common/Address.hh"')
450 code('struct MachineID;')
451
452 code('''
453
454// Class definition
455/** \\enum ${{self.c_ident}}
456 * \\brief ${{self.desc}}
457 */
458enum ${{self.c_ident}} {
459 ${{self.c_ident}}_FIRST,
460''')
461
462 code.indent()
463 # For each field
464 for i,(ident,enum) in enumerate(self.enums.iteritems()):
465 desc = enum.get("desc", "No description avaliable")
466 if i == 0:
467 init = ' = %s_FIRST' % self.c_ident
468 else:
469 init = ''
470 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
471 code.dedent()
472 code('''
473 ${{self.c_ident}}_NUM
474};
475
476// Code to convert from a string to the enumeration
477${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
478
479// Code to convert state to a string
480std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
481
482// Code to increment an enumeration type
483${{self.c_ident}} &operator++(${{self.c_ident}} &e);
484''')
485
486 # MachineType hack used to set the base component id for each Machine
487 if self.isMachineType:
488 code('''
489int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
490MachineType ${{self.c_ident}}_from_base_level(int);
491int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
492int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
493''')
494
495 for enum in self.enums.itervalues():
496 if enum.ident == "DMA":
497 code('''
498MachineID map_Address_to_DMA(const Address &addr);
499''')
500 code('''
501
502MachineID get${{enum.ident}}MachineID(NodeID RubyNode);
503''')
504
505 code('''
506inline GenericMachineType
507ConvertMachToGenericMach(MachineType machType)
508{
509''')
510 for enum in self.enums.itervalues():
511 code('''
512 if (machType == MachineType_${{enum.ident}})
513 return GenericMachineType_${{enum.ident}};
514''')
515 code('''
516 panic("cannot convert to a GenericMachineType");
517}
518''')
519
520 if self.isStateDecl:
521 code('''
522
523// Code to convert the current state to an access permission
524AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
525
526''')
527
528 # Trailer
529 code('''
530std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
531
532#endif // __${{self.c_ident}}_HH__
533''')
534
535 code.write(path, "%s.hh" % self.c_ident)
536
537 def printEnumCC(self, path):
538 code = self.symtab.codeFormatter()
539 code('''
540/** \\file ${{self.c_ident}}.hh
541 *
542 * Auto generated C++ code started by $__file__:$__line__
543 */
544
545#include <cassert>
546#include <iostream>
547#include <string>
548
549#include "base/misc.hh"
550#include "mem/protocol/${{self.c_ident}}.hh"
551
552using namespace std;
553
554''')
555
556 if self.isStateDecl:
557 code('''
558// Code to convert the current state to an access permission
559AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
560{
561 switch(obj) {
562''')
563 # For each case
564 code.indent()
565 for statePerm in self.statePermPairs:
566 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
567 code(' return AccessPermission_${{statePerm[1]}};')
568 code.dedent()
569 code ('''
570 default:
571 panic("Unknown state access permission converstion for ${{self.c_ident}}");
572 }
573}
574
575''')
576
577 if self.isMachineType:
578 for enum in self.enums.itervalues():
579 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
580 code('#include "mem/ruby/system/MachineID.hh"')
581
582 code('''
583// Code for output operator
584ostream&
585operator<<(ostream& out, const ${{self.c_ident}}& obj)
586{
587 out << ${{self.c_ident}}_to_string(obj);
588 out << flush;
589 return out;
590}
591
592// Code to convert state to a string
593string
594${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
595{
596 switch(obj) {
597''')
598
599 # For each field
600 code.indent()
601 for enum in self.enums.itervalues():
602 code(' case ${{self.c_ident}}_${{enum.ident}}:')
603 code(' return "${{enum.ident}}";')
604 code.dedent()
605
606 # Trailer
607 code('''
608 default:
609 panic("Invalid range for type ${{self.c_ident}}");
610 }
611}
612
613// Code to convert from a string to the enumeration
614${{self.c_ident}}
615string_to_${{self.c_ident}}(const string& str)
616{
617''')
618
619 # For each field
620 start = ""
621 code.indent()
622 for enum in self.enums.itervalues():
623 code('${start}if (str == "${{enum.ident}}") {')
624 code(' return ${{self.c_ident}}_${{enum.ident}};')
625 start = "} else "
626 code.dedent()
627
628 code('''
629 } else {
630 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
631 }
632}
633
634// Code to increment an enumeration type
635${{self.c_ident}}&
636operator++(${{self.c_ident}}& e)
637{
638 assert(e < ${{self.c_ident}}_NUM);
639 return e = ${{self.c_ident}}(e+1);
640}
641''')
642
643 # MachineType hack used to set the base level and number of
644 # components for each Machine
645 if self.isMachineType:
646 code('''
647/** \\brief returns the base vector index for each machine type to be
648 * used by NetDest
649 *
650 * \\return the base vector index for each machine type to be used by NetDest
651 * \\see NetDest.hh
652 */
653int
654${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
655{
656 switch(obj) {
657''')
658
659 # For each field
660 code.indent()
661 for i,enum in enumerate(self.enums.itervalues()):
662 code(' case ${{self.c_ident}}_${{enum.ident}}:')
663 code(' return $i;')
664 code.dedent()
665
666 # total num
667 code('''
668 case ${{self.c_ident}}_NUM:
669 return ${{len(self.enums)}};
670
671 default:
672 panic("Invalid range for type ${{self.c_ident}}");
673 }
674}
675
676/** \\brief returns the machine type for each base vector index used by NetDest
677 *
678 * \\return the MachineType
679 */
680MachineType
681${{self.c_ident}}_from_base_level(int type)
682{
683 switch(type) {
684''')
685
686 # For each field
687 code.indent()
688 for i,enum in enumerate(self.enums.itervalues()):
689 code(' case $i:')
690 code(' return ${{self.c_ident}}_${{enum.ident}};')
691 code.dedent()
692
693 # Trailer
694 code('''
695 default:
696 panic("Invalid range for type ${{self.c_ident}}");
697 }
698}
699
700/** \\brief The return value indicates the number of components created
701 * before a particular machine\'s components
702 *
703 * \\return the base number of components for each machine
704 */
705int
706${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
707{
708 int base = 0;
709 switch(obj) {
710''')
711
712 # For each field
713 code.indent()
714 code(' case ${{self.c_ident}}_NUM:')
715 for enum in reversed(self.enums.values()):
716 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
717 code(' case ${{self.c_ident}}_${{enum.ident}}:')
718 code(' break;')
719 code.dedent()
720
721 code('''
722 default:
723 panic("Invalid range for type ${{self.c_ident}}");
724 }
725
726 return base;
727}
728
729/** \\brief returns the total number of components for each machine
730 * \\return the total number of components for each machine
731 */
732int
733${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
734{
735 switch(obj) {
736''')
737
738 # For each field
739 for enum in self.enums.itervalues():
740 code('''
741 case ${{self.c_ident}}_${{enum.ident}}:
742 return ${{enum.ident}}_Controller::getNumControllers();
743''')
744
745 # total num
746 code('''
747 case ${{self.c_ident}}_NUM:
748 default:
749 panic("Invalid range for type ${{self.c_ident}}");
750 }
751}
752''')
753
754 for enum in self.enums.itervalues():
755 if enum.ident == "DMA":
756 code('''
757MachineID
758map_Address_to_DMA(const Address &addr)
759{
760 MachineID dma = {MachineType_DMA, 0};
761 return dma;
762}
763''')
764
765 code('''
766
767MachineID
768get${{enum.ident}}MachineID(NodeID RubyNode)
769{
770 MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
771 return mach;
772}
773''')
774
775 # Write the file
776 code.write(path, "%s.cc" % self.c_ident)
777
778__all__ = [ "Type" ]
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 = " << g_system_ptr->clockPeriod() * getTime() << " ";')
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''')
443 if self.isStateDecl:
444 code('#include "mem/protocol/AccessPermission.hh"')
445
446 if self.isMachineType:
447 code('#include "base/misc.hh"')
448 code('#include "mem/protocol/GenericMachineType.hh"')
449 code('#include "mem/ruby/common/Address.hh"')
450 code('struct MachineID;')
451
452 code('''
453
454// Class definition
455/** \\enum ${{self.c_ident}}
456 * \\brief ${{self.desc}}
457 */
458enum ${{self.c_ident}} {
459 ${{self.c_ident}}_FIRST,
460''')
461
462 code.indent()
463 # For each field
464 for i,(ident,enum) in enumerate(self.enums.iteritems()):
465 desc = enum.get("desc", "No description avaliable")
466 if i == 0:
467 init = ' = %s_FIRST' % self.c_ident
468 else:
469 init = ''
470 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
471 code.dedent()
472 code('''
473 ${{self.c_ident}}_NUM
474};
475
476// Code to convert from a string to the enumeration
477${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
478
479// Code to convert state to a string
480std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
481
482// Code to increment an enumeration type
483${{self.c_ident}} &operator++(${{self.c_ident}} &e);
484''')
485
486 # MachineType hack used to set the base component id for each Machine
487 if self.isMachineType:
488 code('''
489int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
490MachineType ${{self.c_ident}}_from_base_level(int);
491int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
492int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
493''')
494
495 for enum in self.enums.itervalues():
496 if enum.ident == "DMA":
497 code('''
498MachineID map_Address_to_DMA(const Address &addr);
499''')
500 code('''
501
502MachineID get${{enum.ident}}MachineID(NodeID RubyNode);
503''')
504
505 code('''
506inline GenericMachineType
507ConvertMachToGenericMach(MachineType machType)
508{
509''')
510 for enum in self.enums.itervalues():
511 code('''
512 if (machType == MachineType_${{enum.ident}})
513 return GenericMachineType_${{enum.ident}};
514''')
515 code('''
516 panic("cannot convert to a GenericMachineType");
517}
518''')
519
520 if self.isStateDecl:
521 code('''
522
523// Code to convert the current state to an access permission
524AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
525
526''')
527
528 # Trailer
529 code('''
530std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
531
532#endif // __${{self.c_ident}}_HH__
533''')
534
535 code.write(path, "%s.hh" % self.c_ident)
536
537 def printEnumCC(self, path):
538 code = self.symtab.codeFormatter()
539 code('''
540/** \\file ${{self.c_ident}}.hh
541 *
542 * Auto generated C++ code started by $__file__:$__line__
543 */
544
545#include <cassert>
546#include <iostream>
547#include <string>
548
549#include "base/misc.hh"
550#include "mem/protocol/${{self.c_ident}}.hh"
551
552using namespace std;
553
554''')
555
556 if self.isStateDecl:
557 code('''
558// Code to convert the current state to an access permission
559AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
560{
561 switch(obj) {
562''')
563 # For each case
564 code.indent()
565 for statePerm in self.statePermPairs:
566 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
567 code(' return AccessPermission_${{statePerm[1]}};')
568 code.dedent()
569 code ('''
570 default:
571 panic("Unknown state access permission converstion for ${{self.c_ident}}");
572 }
573}
574
575''')
576
577 if self.isMachineType:
578 for enum in self.enums.itervalues():
579 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
580 code('#include "mem/ruby/system/MachineID.hh"')
581
582 code('''
583// Code for output operator
584ostream&
585operator<<(ostream& out, const ${{self.c_ident}}& obj)
586{
587 out << ${{self.c_ident}}_to_string(obj);
588 out << flush;
589 return out;
590}
591
592// Code to convert state to a string
593string
594${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
595{
596 switch(obj) {
597''')
598
599 # For each field
600 code.indent()
601 for enum in self.enums.itervalues():
602 code(' case ${{self.c_ident}}_${{enum.ident}}:')
603 code(' return "${{enum.ident}}";')
604 code.dedent()
605
606 # Trailer
607 code('''
608 default:
609 panic("Invalid range for type ${{self.c_ident}}");
610 }
611}
612
613// Code to convert from a string to the enumeration
614${{self.c_ident}}
615string_to_${{self.c_ident}}(const string& str)
616{
617''')
618
619 # For each field
620 start = ""
621 code.indent()
622 for enum in self.enums.itervalues():
623 code('${start}if (str == "${{enum.ident}}") {')
624 code(' return ${{self.c_ident}}_${{enum.ident}};')
625 start = "} else "
626 code.dedent()
627
628 code('''
629 } else {
630 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
631 }
632}
633
634// Code to increment an enumeration type
635${{self.c_ident}}&
636operator++(${{self.c_ident}}& e)
637{
638 assert(e < ${{self.c_ident}}_NUM);
639 return e = ${{self.c_ident}}(e+1);
640}
641''')
642
643 # MachineType hack used to set the base level and number of
644 # components for each Machine
645 if self.isMachineType:
646 code('''
647/** \\brief returns the base vector index for each machine type to be
648 * used by NetDest
649 *
650 * \\return the base vector index for each machine type to be used by NetDest
651 * \\see NetDest.hh
652 */
653int
654${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
655{
656 switch(obj) {
657''')
658
659 # For each field
660 code.indent()
661 for i,enum in enumerate(self.enums.itervalues()):
662 code(' case ${{self.c_ident}}_${{enum.ident}}:')
663 code(' return $i;')
664 code.dedent()
665
666 # total num
667 code('''
668 case ${{self.c_ident}}_NUM:
669 return ${{len(self.enums)}};
670
671 default:
672 panic("Invalid range for type ${{self.c_ident}}");
673 }
674}
675
676/** \\brief returns the machine type for each base vector index used by NetDest
677 *
678 * \\return the MachineType
679 */
680MachineType
681${{self.c_ident}}_from_base_level(int type)
682{
683 switch(type) {
684''')
685
686 # For each field
687 code.indent()
688 for i,enum in enumerate(self.enums.itervalues()):
689 code(' case $i:')
690 code(' return ${{self.c_ident}}_${{enum.ident}};')
691 code.dedent()
692
693 # Trailer
694 code('''
695 default:
696 panic("Invalid range for type ${{self.c_ident}}");
697 }
698}
699
700/** \\brief The return value indicates the number of components created
701 * before a particular machine\'s components
702 *
703 * \\return the base number of components for each machine
704 */
705int
706${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
707{
708 int base = 0;
709 switch(obj) {
710''')
711
712 # For each field
713 code.indent()
714 code(' case ${{self.c_ident}}_NUM:')
715 for enum in reversed(self.enums.values()):
716 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
717 code(' case ${{self.c_ident}}_${{enum.ident}}:')
718 code(' break;')
719 code.dedent()
720
721 code('''
722 default:
723 panic("Invalid range for type ${{self.c_ident}}");
724 }
725
726 return base;
727}
728
729/** \\brief returns the total number of components for each machine
730 * \\return the total number of components for each machine
731 */
732int
733${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
734{
735 switch(obj) {
736''')
737
738 # For each field
739 for enum in self.enums.itervalues():
740 code('''
741 case ${{self.c_ident}}_${{enum.ident}}:
742 return ${{enum.ident}}_Controller::getNumControllers();
743''')
744
745 # total num
746 code('''
747 case ${{self.c_ident}}_NUM:
748 default:
749 panic("Invalid range for type ${{self.c_ident}}");
750 }
751}
752''')
753
754 for enum in self.enums.itervalues():
755 if enum.ident == "DMA":
756 code('''
757MachineID
758map_Address_to_DMA(const Address &addr)
759{
760 MachineID dma = {MachineType_DMA, 0};
761 return dma;
762}
763''')
764
765 code('''
766
767MachineID
768get${{enum.ident}}MachineID(NodeID RubyNode)
769{
770 MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
771 return mach;
772}
773''')
774
775 # Write the file
776 code.write(path, "%s.cc" % self.c_ident)
777
778__all__ = [ "Type" ]