def assignindextoinstructions(): maxsize = cfg['instruction_ids'] printverbose('assigning ids to instructions') printverbose('found {} instructions, max is {}', len(instructions), maxsize) usedindices = [None] * maxsize if len(instructions) >= maxsize: raise ValueError('to many instructions') def assign(instruction, index): if index >= maxsize: raise ValueError('index over maxsize') if usedindices[index]: raise ValueError('double assignment of index {}'.format(index)) instruction.index = index usedindices[index] = instruction for i in instructions: if i.index is not None: assign(i, i.index) toassign = sorted([x for x in instructions if x.index is None], key=attrgetter('group')) for instr, index in zip(toassign, (x for x in count(0) if not usedindices[x])): assign(instr, index)
def writeinstructiondatatofile(filename: str): printverbose('writing microcode to file {}', filename) with open(filename, 'w+') as f: for instruction in instructions: f.write('#Instruction {}\n'.format(instruction.name)) for addr, data in instruction.compilemicrocode(flags): f.write('{:5} {:5} # {:0>15b} {:0>32b}\t\t\n'.format(addr, data, addr, data))
def initializefile(name): filename = findfile(name) # strip eventual extension name = os.path.splitext(name)[0] name = name.replace('/', '_') if name in filesIncluded: return filesIncluded[name] if name in filesCurrentlyIncluding: throwhelper.throw('including: {} would cause a dependency loop'.format(name)) printverbose('begins importing of {}', name) filesCurrentlyIncluding.append(name) c = FileCompiler(name, filename) compileOrder.append(c) filesIncluded[name] = c filesCurrentlyIncluding.remove(name) printverbose('end importing of {}', name) return c
def loadconfig(configfilename): # Parse file printverbose('loading configfile: {}', configfilename) betterexec.exec(open(configfilename).read(), description=configfilename) # instructions and registers assume has valid data assignindextoinstructions() printverbose('successful load of configfile')
def asignsegment(self, segment: MemorySegment): if self.currentaddress + segment.size >= self.maxsize: throwhelper.throw('not enough memoey avaliable') else: name = segment.getasignmessage() if not name: name = 'unknown' printverbose('asignning {}, size:{} at address {}', name, segment.size, self.currentaddress) segment.address = self.currentaddress self.currentaddress += segment.size
def dump(): printverbose('dumping global values:') for i in globaldict.items(): printverbose('{}: {}', *i) printverbose()
def compile(filename: str, outputfile: str, directory: str): global phase, cwd cwd = directory filesIncluded.clear() filesCurrentlyIncluding.clear() compileOrder.clear() compilerglobals.dump() totalmemory = cfg['program_size'] printverbose('starting compilation of file {}', filename) printverbose('\nstarting initialization and imports') phase = 0 # load the file and recursively, all its dependencies # filesIncluded and compileOrder is now populated basefile = initializefile(filename) printverbose('ending initialization and imports') printverbose('\ncompileorder is: {}', ', '.join('{}: {}'.format(*v) for v in enumerate(compileOrder, 1))) # perform compilation phase 1 printverbose('\nstarting compilation phase 1') phase = 1 for file in compileOrder: file.compilephase1() printverbose('ending compilation phase 1') printverbose('\nstarting memory asignments') # calculate what memorysegments to include and asign address entryfunction = basefile.components[CodeFunction].get(entryfunctionname, None) if not entryfunction: raise throwhelper.CompileError( 'no entrypoint found. Add a function named {} in file {}'.format( entryfunctionname, basefile.name )) allocator = MemoryAllocator(totalmemory) allocator.allocatealldependents(entryfunction) allocator.asignaddresses(entryfunction) usedmemory = allocator.getusedmemory() printverbose('total memory usage: {}', usedmemory) printverbose('ending memory asignments') CompilerSettings.mem_total = totalmemory CompilerSettings.mem_used = usedmemory CompilerSettings.mem_free = totalmemory - usedmemory CompilerSettings.mem_free_first = allocator.currentaddress CompilerSettings.mem_free_last = totalmemory - 1 printverbose('\nstarting compilation phase 2') phase = 2 for file in compileOrder: file.compilephase2() printverbose('ending compilation phase 2') printverbose('\ncompile successful!') printverbose('\ngenerating output file') filecontent = allocator.generatefilecontent() printverbose('writing output') writetofile(outputfile, filecontent)