code-shuffle on testing to prepare loading large files into memory
[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 bigendian = True
17 endian_fmt = "elf64-big"
18 obj_fmt = "-be"
19
20
21 class Program:
22 def __init__(self, instructions):
23 if isinstance(instructions, str): # filename
24 self.binfile = open(instructions, "rb")
25 self.assembly = '' # noo disassemble number fiiive
26 print ("program", self.binfile)
27 else:
28 if isinstance(instructions, list):
29 instructions = '\n'.join(instructions)
30 self.assembly = instructions + '\n' # plus final newline
31 self._assemble()
32 self._instructions = list(self._get_instructions())
33
34 def __enter__(self):
35 return self
36
37 def __exit__(self, type, value, traceback):
38 self.close()
39
40 def _get_binary(self, elffile):
41 self.binfile = tempfile.NamedTemporaryFile(suffix=".bin")
42 args = ["powerpc64-linux-gnu-objcopy",
43 "-O", "binary",
44 "-I", endian_fmt,
45 elffile.name,
46 self.binfile.name]
47 subprocess.check_output(args)
48
49 def _link(self, ofile):
50 with tempfile.NamedTemporaryFile(suffix=".elf") as elffile:
51 args = ["powerpc64-linux-gnu-ld",
52 "-o", elffile.name,
53 "-T", memmap,
54 ofile.name]
55 subprocess.check_output(args)
56 self._get_binary(elffile)
57
58 def _assemble(self):
59 with tempfile.NamedTemporaryFile(suffix=".o") as outfile:
60 args = ["powerpc64-linux-gnu-as",
61 '-mpower9',
62 obj_fmt,
63 "-o",
64 outfile.name]
65 p = subprocess.Popen(args, stdin=subprocess.PIPE)
66 p.communicate(self.assembly.encode('utf-8'))
67 if p.wait() != 0:
68 print("Error in program:")
69 print(self.assembly)
70 sys.exit(1)
71 self._link(outfile)
72
73 def _get_instructions(self):
74 while True:
75 data = self.binfile.read(4)
76 if not data:
77 break
78 yield struct.unpack('<i', data)[0]
79
80 def generate_instructions(self):
81 yield from self._instructions
82
83 def reset(self):
84 self.binfile.seek(0)
85
86 def size(self):
87 curpos = self.binfile.tell()
88 self.binfile.seek(0, 2) # Seek to end of file
89 size = self.binfile.tell()
90 self.binfile.seek(curpos, 0)
91 return size
92
93 def close(self):
94 self.binfile.close()