Merge branch 'fix-tests'
[soc.git] / src / soc / simulator / program.py
1 import tempfile
2 import subprocess
3 import struct
4 import os
5
6 filedir = os.path.dirname(os.path.realpath(__file__))
7 memmap = os.path.join(filedir, "memmap")
8
9 bigendian = True
10 endian_fmt = "elf64-big"
11 obj_fmt = "-be"
12
13
14 class Program:
15 def __init__(self, instructions):
16 if isinstance(instructions, list):
17 instructions = '\n'.join(instructions)
18 self.assembly = instructions + '\n' # plus final newline
19 self._assemble()
20
21 def __enter__(self):
22 return self
23
24 def __exit__(self, type, value, traceback):
25 self.close()
26
27 def _get_binary(self, elffile):
28 self.binfile = tempfile.NamedTemporaryFile(suffix=".bin")
29 args = ["powerpc64-linux-gnu-objcopy",
30 "-O", "binary",
31 "-I", endian_fmt,
32 elffile.name,
33 self.binfile.name]
34 subprocess.check_output(args)
35
36 def _link(self, ofile):
37 with tempfile.NamedTemporaryFile(suffix=".elf") as elffile:
38 args = ["powerpc64-linux-gnu-ld",
39 "-o", elffile.name,
40 "-T", memmap,
41 ofile.name]
42 subprocess.check_output(args)
43 self._get_binary(elffile)
44
45 def _assemble(self):
46 with tempfile.NamedTemporaryFile(suffix=".o") as outfile:
47 args = ["powerpc64-linux-gnu-as",
48 '-mpower9',
49 obj_fmt,
50 "-o",
51 outfile.name]
52 p = subprocess.Popen(args, stdin=subprocess.PIPE)
53 p.communicate(self.assembly.encode('utf-8'))
54 assert(p.wait() == 0)
55 self._link(outfile)
56
57 def generate_instructions(self):
58 while True:
59 data = self.binfile.read(4)
60 if not data:
61 break
62 yield struct.unpack('<i', data)[0]
63
64 def reset(self):
65 self.binfile.seek(0)
66
67 def size(self):
68 curpos = self.binfile.tell()
69 self.binfile.seek(0, 2) # Seek to end of file
70 size = self.binfile.tell()
71 self.binfile.seek(curpos, 0)
72 return size
73
74 def close(self):
75 self.binfile.close()