d77f9d7839777c3bd607d04cdfc4c617c3dc4268
[soc.git] / src / soc / simulator / program.py
1 """POWER Program
2
3 takes powerpc assembly instructions and turns them into LE/BE binary
4 data. calls powerpc64-linux-gnu-as, ld and objcopy to do so.
5 """
6
7 import tempfile
8 import subprocess
9 import struct
10 import os
11 import sys
12
13 filedir = os.path.dirname(os.path.realpath(__file__))
14 memmap = os.path.join(filedir, "memmap")
15
16
17 class Program:
18 def __init__(self, instructions, bigendian):
19 self.bigendian = bigendian
20 if self.bigendian:
21 self.endian_fmt = "elf64-big"
22 self.obj_fmt = "-be"
23 self.ld_fmt = "-EB"
24 else:
25 self.ld_fmt = "-EL"
26 self.endian_fmt = "elf64-little"
27 self.obj_fmt = "-le"
28
29 if isinstance(instructions, str): # filename
30 # read instructions into a BytesIO to avoid "too many open files"
31 with open(instructions, "rb") as f:
32 b = f.read()
33 self.binfile = BytesIO(b, 'rb')
34 self.assembly = '' # noo disassemble number fiiive
35 print("program", self.binfile)
36 else:
37 if isinstance(instructions, list):
38 instructions = '\n'.join(instructions)
39 self.assembly = instructions + '\n' # plus final newline
40 self._assemble()
41 self._instructions = list(self._get_instructions())
42
43 def __enter__(self):
44 return self
45
46 def __exit__(self, type, value, traceback):
47 self.close()
48
49 def _get_binary(self, elffile):
50 self.binfile = tempfile.NamedTemporaryFile(suffix=".bin")
51 args = ["powerpc64-linux-gnu-objcopy",
52 "-O", "binary",
53 "-I", self.endian_fmt,
54 elffile.name,
55 self.binfile.name]
56 subprocess.check_output(args)
57
58 def _link(self, ofile):
59 with tempfile.NamedTemporaryFile(suffix=".elf") as elffile:
60 args = ["powerpc64-linux-gnu-ld",
61 self.ld_fmt,
62 "-o", elffile.name,
63 "-T", memmap,
64 ofile.name]
65 subprocess.check_output(args)
66 self._get_binary(elffile)
67
68 def _assemble(self):
69 with tempfile.NamedTemporaryFile(suffix=".o") as outfile:
70 args = ["powerpc64-linux-gnu-as",
71 '-mpower9',
72 self.obj_fmt,
73 "-o",
74 outfile.name]
75 p = subprocess.Popen(args, stdin=subprocess.PIPE)
76 p.communicate(self.assembly.encode('utf-8'))
77 if p.wait() != 0:
78 print("Error in program:")
79 print(self.assembly)
80 sys.exit(1)
81 self._link(outfile)
82
83 def _get_instructions(self):
84 while True:
85 data = self.binfile.read(4)
86 if not data:
87 break
88 yield struct.unpack('<I', data)[0] # unsigned int
89
90 def generate_instructions(self):
91 yield from self._instructions
92
93 def reset(self):
94 self.binfile.seek(0)
95
96 def size(self):
97 curpos = self.binfile.tell()
98 self.binfile.seek(0, 2) # Seek to end of file
99 size = self.binfile.tell()
100 self.binfile.seek(curpos, 0)
101 return size
102
103 def close(self):
104 self.binfile.close()