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