Ruby: Simplify SLICC and Entry/TBE handling.
[gem5.git] / src / mem / slicc / ast / ChipComponentAccessAST.py
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
28 import re
29
30 from slicc.ast.ExprAST import ExprAST
31 from slicc.symbols import Type
32
33 class ChipComponentAccessAST(ExprAST):
34 def __init__(self, slicc, machine, mach_version, component):
35 super(ChipComponentAccessAST, self).__init__(slicc)
36 self.mach_var = machine
37 self.comp_var = component
38 self.mach_ver_expr = mach_version
39
40 def __repr__(self):
41 return "[ChipAccessExpr: %r]" % self.expr_vec
42
43 def generate(self, code):
44 void_type = self.symtab.find("void", Type)
45
46 mname = self.mach_var.name
47 cname = self.comp_var.name
48 var = self.symtab.machine_components[mname][cname]
49
50 vcode = str(var.code)
51
52 if self.chip_ver_expr is not None:
53 # replace self.chip with specified chip
54 gcode = "g_system.getChip(%s)" % self.chip_ver_expr.inline()
55 vcode = re.sub("m_chip", gcode, vcode)
56
57 # replace default "m_version" with the version we really want
58 gcode = "(%s)" % self.mach_ver_expr.inline()
59 vcode = re.sub("m_version", gcode, vcode)
60
61 return_type, gcode = self.generate_access(var)
62 code("($vcode)$gcode")
63 return return_type
64
65 class ChipMethodAccessAST(ChipComponentAccessAST):
66 def __init__(self, slicc, chip_version, machine, mach_version, component,
67 proc_name, expr_vec):
68 s = super(ChipMethodAccessAST, self)
69 s.__init__(slicc, machine, mach_version, component)
70
71 self.chip_ver_expr = chip_version
72 self.expr_vec = expr_vec
73 self.proc_name = proc_name
74
75 def generate_access(self, var):
76 # generate code
77 paramTypes = []
78 gcode = []
79 for expr in self.expr_vec:
80 t,c = expr.generate()
81 paramTypes.append(t)
82 gcode.append(c)
83
84 methodId = var.type.methodId(self.proc_name, paramTypes)
85
86 # Verify that this is a method of the object
87 if not var.type.methodExist(methodId):
88 self.error("%s: Type '%s' does not have a method '%s'" % \
89 ("Invalid method call", var.type, methodId))
90
91 expected_size = len(var.type.methodParamType(methodId))
92 if len(self.expr_vec) != expected_size:
93 # Right number of parameters
94 self.error("Wrong number of parameters for function name: " +\
95 "'%s', expected: %d, actual: %d",
96 self.proc_name, expected_size, len(self.expr_vec))
97
98 for expr,expected,actual in zip(self.expr_vec,
99 var.type.methodParamType(methodId),
100 paramTypes):
101 # Check the types of the parameter
102 if actual != expected:
103 expr.error("Type mismatch: expected: %s actual: %s",
104 expected, actual)
105
106 # method call
107 code = ".%s(%s)" % (self.proc_name, ', '.join(gcode))
108
109 # Return the return type of the method
110 return var.type.methodReturnType(methodId), code
111
112 class LocalChipMethodAST(ChipMethodAccessAST):
113 # method call from local chip
114 def __init__(self, slicc, machine, mach_version, component, proc_name,
115 expr_vec):
116 s = super(LocalChipMethodAST, self)
117 s.__init__(slicc, None, machine, mach_version, component, proc_name,
118 expr_vec)
119
120 class SpecifiedChipMethodAST(ChipMethodAccessAST):
121 # method call from specified chip
122 def __init__(self, slicc, chip_version, machine, mach_version, component,
123 proc_name, expr_vec):
124 s = super(SpecifiedChipMethodAST, self)
125 s.__init__(slicc, chip_version, machine, mach_version, component,
126 proc_name, expr_vec)
127
128 class ChipMemberAccessAST(ChipComponentAccessAST):
129 # member access from specified chip
130 def __init__(self, chip_version, machine, mach_version, component,
131 field_name):
132 s = super(ChipMemberAccessAST, self)
133 s.__init__(slicc, machine, mach_version, component)
134
135 self.chip_ver_expr = chip_version
136 self.field_name = field_name
137
138 def generate_access(self, var):
139 # Verify that this is a valid field name for this type
140 if not var.type.dataMemberExist(self.field_name):
141 self.error("Invalid object field: " +\
142 "Type '%s' does not have data member %s",
143 var.type, self.field_name)
144
145 code += ").m_%s" % self.field_name
146
147 return var.type.dataMemberType(self.field_name), code
148
149 class LocalChipMemberAST(ChipMemberAccessAST):
150 # member access from local chip
151 def __init__(self, slicc, machine, mach_version, component, field_name):
152 s = super(LocalChipMemberAST, self)
153 s.__init__(slicc, None, machine, mach_version, component, field_name)
154
155 class SpecifiedChipMemberAST(ChipMemberAccessAST):
156 # member access from specified chip
157 def __init__(self, chip_version, machine, mach_version, component,
158 field_name):
159 s = super(SpecifiedChipMemberAST, self)
160 s.__init__(slicc, chip_version, machine, mach_version, component,
161 field_name)