nodes.gen.py 9.32 KB
Newer Older
1
#!/usr/bin/env python
Benoit Perrot's avatar
Benoit Perrot committed
2
##
Benoit Perrot's avatar
Benoit Perrot committed
3
## This file is part of Nolimips, a MIPS simulator with unlimited registers
Benoit Perrot's avatar
Benoit Perrot committed
4
## Copyright (C) 2003, 2004 Benoit Perrot <benoit@lrde.epita.fr>
Benoit Perrot's avatar
Benoit Perrot committed
5
##
Benoit Perrot's avatar
Benoit Perrot committed
6
## Nolimips is free software; you can redistribute it and/or modify
Benoit Perrot's avatar
Benoit Perrot committed
7
8
9
10
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## 
Benoit Perrot's avatar
Benoit Perrot committed
11
## Nolimips is distributed in the hope that it will be useful,
Benoit Perrot's avatar
Benoit Perrot committed
12
13
14
15
16
17
18
19
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
20

Benoit Perrot's avatar
Benoit Perrot committed
21
22
import sys, os
import string
23

Benoit Perrot's avatar
Benoit Perrot committed
24
import nolimips
Benoit Perrot's avatar
Benoit Perrot committed
25

Benoit Perrot's avatar
Benoit Perrot committed
26
#### Nolimips' instruction classes generator ---------------
27

Benoit Perrot's avatar
Benoit Perrot committed
28
29
30
31
32
if __name__ != "__main__" or len(sys.argv) != 2:
  print "Usage: .. SRCDIR"
  sys.exit(1)
srcdir = sys.argv[1]

Benoit Perrot's avatar
Benoit Perrot committed
33
## Generate the class corresponding to an instruction
34
35
36
37
38
39
format_type_to_enum = {
  "register": "r_type",
  "immediate": "i_type",
  "jump": "j_type",
  }

Benoit Perrot's avatar
Benoit Perrot committed
40
def class_generate(inst):
41

Benoit Perrot's avatar
Benoit Perrot committed
42
  ## Shortands
Benoit Perrot's avatar
Benoit Perrot committed
43
44
45
46
  class_id = nolimips.class_id(inst.opcode)
  define_id = nolimips.define_id(inst.opcode)
  file_id = nolimips.file_id(inst.opcode)
  banner = nolimips.license + "\n// Generated, do not edit by hand."
Benoit Perrot's avatar
Benoit Perrot committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  format = inst.format
  
  ## Open header, inline and implementation files
  header = file(file_id + ".hh.tmp", "w")
  inline = file(file_id + ".hxx.tmp", "w")
  impl = file(file_id + ".cc.tmp", "w")
  
  for f, ext, brief in [(header, "hh",  "Declare the interface"),
                        (inline, "hxx", "Inline methods"),
                        (impl,   "cc",  "Implementation")]:
    sys.stdout = f
    print banner
    # Document the file
    print "/** \\file inst/" + file_id + "." + ext
    print "    \\brief " + brief + " of " + class_id + " */"
    # Open multiple inclusion protection
    if ext != "cc":
      print "#ifndef INST_" + string.upper(inst.opcode + "_" + ext)
      print "# define INST_" + string.upper(inst.opcode + "_" + ext)

  sys.stdout = header
68
  print """
Benoit Perrot's avatar
Benoit Perrot committed
69
70
71
72
73
74
75
76
77
78
79
80
# include \"inst/register.hh\"
# include \"inst/exp.hh\"
# include \"inst/inst.hh\"
# include \"inst/visitor.hh\"
"""
  for f in [inline, impl]:
    sys.stdout = f
    print "#include \"inst/" + file_id + ".hh\""
  # Open namespace
  for f in [header, inline, impl]:
    sys.stdout = f
    print "\nnamespace inst\n{\n"
81
82
83


  ## Declare class
Benoit Perrot's avatar
Benoit Perrot committed
84
85
86
87
  sys.stdout = header
  print "  /// Declare " + class_id + "."
  print "  /** " + inst.desc + "  */"
  print "  class " + class_id + ":"
88
89
  print "    public Inst"
  print "  {"
Benoit Perrot's avatar
Benoit Perrot committed
90
91
92
  
  # Constructor and destructor
  args = ""
93
  init = ""
Benoit Perrot's avatar
Benoit Perrot committed
94
  dels = ""
Benoit Perrot's avatar
Benoit Perrot committed
95
  for attribute in format.attributes:
Benoit Perrot's avatar
Benoit Perrot committed
96
97
98
    
    if attribute.type == "Register":
      args = args + "const " + attribute.type + " &"
Benoit Perrot's avatar
Benoit Perrot committed
99
100
    elif attribute.type == "Exp":
      args = args + "const CountedExp &"
Benoit Perrot's avatar
Benoit Perrot committed
101
102
103
    else:
      args = args + attribute.type + " *"
    args = args + attribute.name + ", "
Benoit Perrot's avatar
Benoit Perrot committed
104
105
    init = init + attribute.name + "_(" + attribute.name + "), "
  args = string.rstrip(args, ", ")
106
  init = string.rstrip(init, ", ")
Benoit Perrot's avatar
Benoit Perrot committed
107
108
109
110
111
112
113
114
115
116
117
  sys.stdout = header
  print """    /** \\name Ctor & dtor.
        \\{ */
  public:"""
  print "    /// Construct a(n) " + class_id + " node."
  print "    " + class_id + "(" + args + ");"
  print "    /// Destroy a(n) " + class_id + " node."
  print "    virtual ~" + class_id + "();"
  print "    /** \\} */"
  sys.stdout = inline
  print "  inline"
118
119
120
  print "  " + class_id + "::" + class_id + "(" + args + ")" + ":"
  if init == "":
    print "    Inst(" + format_type_to_enum[format.type] + ")"
121
  else:
122
123
    print "    Inst(" + format_type_to_enum[format.type] + "),"
  print "    " + init
Benoit Perrot's avatar
Benoit Perrot committed
124
125
126
  print "  {}\n"
  sys.stdout = impl
  print "  " + class_id + "::~" + class_id + "()"
Benoit Perrot's avatar
Benoit Perrot committed
127
128
129
  print "  {"
  for attribute in format.attributes:
    # FIXME: there should be some preconditions
Benoit Perrot's avatar
Benoit Perrot committed
130
131
    if attribute.type != "Register" and attribute.type != "Exp":
      print "    delete " + attribute.name + "_;"
Benoit Perrot's avatar
Benoit Perrot committed
132
  print "  }\n"
Benoit Perrot's avatar
Benoit Perrot committed
133
134
135

  # Methods: accessors
  sys.stdout = header
136
  print """
Benoit Perrot's avatar
Benoit Perrot committed
137
138
    /** \\name Accessors.
        \\{ */
139
  public:"""
Benoit Perrot's avatar
Benoit Perrot committed
140
  for attribute in format.attributes:
Benoit Perrot's avatar
Benoit Perrot committed
141
142
143
144
145
146
147
148
149
150
    for c in ["const ", ""]:
      sys.stdout = header
      print "    /// Return " + string.lower (attribute.name)
      print "    " + c + attribute.type + \
            " &\t\tget_" + attribute.name + "() " + c + ";"
      sys.stdout = inline
      print "  inline"
      print "  " + c + attribute.type + " &"
      print "  " + class_id + "::get_" + attribute.name + "() " + c
      print "  {"
Benoit Perrot's avatar
Benoit Perrot committed
151
152
153
154
      if attribute.type == "Register":
        print "    return " + attribute.name + "_;"
      else:
        print "    return *" + attribute.name + "_;"
Benoit Perrot's avatar
Benoit Perrot committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
      print "  }"
  sys.stdout = header
  print "    /** \\} */"
  
  # Method: visitor entry point
  sys.stdout = inline
  print ""
  sys.stdout = impl
  print "  void"
  print "  " + class_id + "::accept (ConstVisitor& v) const"
  print """  {
    v.visit(*this);
  }"""
  print "  void"
  print "  " + class_id + "::accept (Visitor& v)"
  print """  {
    v.visit(*this);
  }"""
  sys.stdout = header
174
  print """
Benoit Perrot's avatar
Benoit Perrot committed
175
176
    /** \\name Visitors entry point.
        \\{ */
177
  public:
Benoit Perrot's avatar
Benoit Perrot committed
178
179
180
181
182
183
    /// Accept a const visitor \\a v.
    virtual void accept(ConstVisitor& v) const;
    /// Accept a non-const visitor \\a v.
    virtual void accept(Visitor& v);
    /** \\} */
"""
184

Benoit Perrot's avatar
Benoit Perrot committed
185
186
187
188
189
190
191
  # Method: print
  sys.stdout = header
  print """  public:
    /// Print this
    virtual void\tprint(std::ostream &ostr) const;
"""
  sys.stdout = impl
192
  print """
Benoit Perrot's avatar
Benoit Perrot committed
193
194
195
  void"""
  print "  " + class_id + "::print(std::ostream &ostr) const"
  print "  {"
196
  s = ""
Benoit Perrot's avatar
Benoit Perrot committed
197
198
  i = 0
  while i < len(format.attributes):
Benoit Perrot's avatar
Benoit Perrot committed
199
200
201
    if (i < len(format.attributes) - 1) and \
           (format.attributes[i].type == "Exp") and \
           (format.attributes[i + 1].type == "Register"):
Benoit Perrot's avatar
Benoit Perrot committed
202
      s = s + " << *" + format.attributes[i].name + "_" + \
Benoit Perrot's avatar
Benoit Perrot committed
203
204
          " << '(' << " + format.attributes[i + 1].name + "_ << ')' "
      i = i + 1
205
    else:
Benoit Perrot's avatar
Benoit Perrot committed
206
207
208
209
210
      s = s + " << "
      if format.attributes[i].type != "Register":
        s = s + "*"
      s = s + format.attributes[i].name + "_ << \", \""
    i = i + 1
211
  s = string.rstrip(s, "<< \", \"")
Benoit Perrot's avatar
Benoit Perrot committed
212
213
214
215
216
217
218
219
220
  print "    ostr << \"" + inst.opcode + "\\t\"" + s + ";"
  print "  }"

  # Declare attributes
  sys.stdout = header
  if len(format.attributes) > 0:
    print "  protected:"
    for attribute in format.attributes:
      id = attribute.name + "_"
Benoit Perrot's avatar
Benoit Perrot committed
221
222
      if attribute.type == "Register":
        print "    " + attribute.type + "\t" + id + ";"
Benoit Perrot's avatar
Benoit Perrot committed
223
224
      elif attribute.type == "Exp":
        print "    CountedExp\t" + id + ";"
Benoit Perrot's avatar
Benoit Perrot committed
225
226
227
      else:
        print "    " + attribute.type + "\t*" + id + ";"

Benoit Perrot's avatar
Benoit Perrot committed
228
  # End of declaration
229
230
231
  print "  };"


Benoit Perrot's avatar
Benoit Perrot committed
232
233
234
235
236
237
238
239
240
241
242
243
  ## Close files
  for f, ext in [(header, "hh"), (inline, "hxx"), (impl, "cc")]:
    # Close namespace and inclusion protection system
    sys.stdout = f
    print "\n} // namespace inst"
    if ext != "cc":
      if ext == "hh":
        print "\n# include \"inst/" + file_id + ".hxx\""
      print "\n#endif // !INST_" + string.upper(inst.opcode + "_" + ext)
    # Check differences between old and new files
    sys.stdout = sys.__stdout__
    f.close()
Benoit Perrot's avatar
Benoit Perrot committed
244
245
    nolimips.lazy_overwrite(srcdir + os.sep + file_id + "." + ext,
                            file_id + "." + ext + ".tmp")
Benoit Perrot's avatar
Benoit Perrot committed
246
247
248
    os.remove(file_id + "." + ext + ".tmp")

## Main --------------------------------
Benoit Perrot's avatar
Benoit Perrot committed
249
parser = nolimips.InstructionSetParser()
250
251
instructions = parser.parse(sys.stdin)

Benoit Perrot's avatar
Benoit Perrot committed
252
## Generate classes files
253
254
for inst in instructions:
  if inst.level == "native":
Benoit Perrot's avatar
Benoit Perrot committed
255
    class_generate(inst)
256

Benoit Perrot's avatar
Benoit Perrot committed
257
## Generate all-includer
Benoit Perrot's avatar
Benoit Perrot committed
258
sys.stdout = file("all.hh.tmp", "w")
Benoit Perrot's avatar
Benoit Perrot committed
259
print nolimips.license
260
261
262
263
264
265
print "#ifndef INST_ALL_HH"
print "# define INST_ALL_HH"
for inst in instructions:
  if inst.level == "native":
    print "#  include \"inst/" + inst.opcode + ".hh\""
print "#endif // !INST_ALL_HH"
Benoit Perrot's avatar
Benoit Perrot committed
266
267
sys.stdout.close()
sys.stdout = sys.__stdout__
Benoit Perrot's avatar
Benoit Perrot committed
268
nolimips.lazy_overwrite(srcdir + os.sep + "all.hh", "all.hh.tmp")
Benoit Perrot's avatar
Benoit Perrot committed
269
os.remove("all.hh.tmp")
270

Benoit Perrot's avatar
Benoit Perrot committed
271
## Generate all-declarator
Benoit Perrot's avatar
Benoit Perrot committed
272
sys.stdout = file("decl.hh.tmp", "w")
Benoit Perrot's avatar
Benoit Perrot committed
273
print nolimips.license
274
275
276
277
278
279
280
281
print "#ifndef INST_DECL_HH"
print "# define INST_DECL_HH"
print """
namespace inst
{
"""
for inst in instructions:
  if inst.level == "native":
Benoit Perrot's avatar
Benoit Perrot committed
282
    print "  class " + nolimips.class_id(inst.opcode) + ";"
283
284
285
286
287
print """
} // namespace inst

#endif // !INST_DECL_HH
"""
Benoit Perrot's avatar
Benoit Perrot committed
288
289
sys.stdout.close()
sys.stdout = sys.__stdout__
Benoit Perrot's avatar
Benoit Perrot committed
290
nolimips.lazy_overwrite(srcdir + os.sep + "decl.hh", "decl.hh.tmp")
Benoit Perrot's avatar
Benoit Perrot committed
291
os.remove("decl.hh.tmp")
292

Benoit Perrot's avatar
Benoit Perrot committed
293
## Generate visitor
Benoit Perrot's avatar
Benoit Perrot committed
294
sys.stdout = file("visitor.hh.tmp", "w")
Benoit Perrot's avatar
Benoit Perrot committed
295
print nolimips.license
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
print """#ifndef INST_VISITOR_HH
# define INST_VISITOR_HH

# include \"misc/select_const.hh\"

# include \"inst/decl.hh\"

namespace inst
{

  template <typename K>
  class GenVisitor
  {
  public:
    virtual ~GenVisitor()
    {
    }

  public:
  """
for inst in instructions:
  if inst.level == "native":
    print "    virtual void\tvisit(typename select_const<K, " \
Benoit Perrot's avatar
Benoit Perrot committed
319
          + nolimips.class_id(inst.opcode) + ">::type&) = 0;"
320
321
322
323
324
325
326
327
328
print """
  };

  typedef GenVisitor<const_kind> ConstVisitor;
  typedef GenVisitor<non_const_kind> Visitor;

} // namespace inst

#endif // !INST_VISITOR_HH"""
Benoit Perrot's avatar
Benoit Perrot committed
329
330
sys.stdout.close()
sys.stdout = sys.__stdout__
Benoit Perrot's avatar
Benoit Perrot committed
331
nolimips.lazy_overwrite(srcdir + os.sep + "visitor.hh", "visitor.hh.tmp")
Benoit Perrot's avatar
Benoit Perrot committed
332
os.remove("visitor.hh.tmp")