Source code for eight_bit_computer.main

"""
Top level interface for the module
"""

import os

from .assembler import process_assembly_lines
from .assembly_summary import generate_assembly_summary
from .exceptions import AssemblyError
from .number_utils import number_to_bitstring
from . import export
from . import rom


[docs]def assemble( input_filepath, output_filename_base=None, output_dir=None, output_format="logisim" ): """ Read an assembly file and write out equivalent machine code. Args: input_filepath (str): The location of the assembly file. output_filename_base (str) (optional): The location to write out the machine code (without extension). If nothing is passed, the output path will be the input filename with the extension changed to mc. output_dir (str) (optional): The directory to write the assembled code into. output_format (str) (optional): How to format the output. ``logisim`` or ``arduino``. """ # Does input file exist if not os.path.isfile(input_filepath): print "Input file: {input_filepath} does not exist.".format( input_filepath=input_filepath) return # Does input file have the correct extension if not input_filepath.endswith(".asm"): print "Input file must have a .asm extension." return # Is output format correct output_formats = ["logisim", "arduino"] if output_format not in output_formats: formats_str = " ".join(["'{name}'".format(name=name) for name in output_formats]) print "Output format must be one of: {output_formats}.".format( output_formats=formats_str ) return # Generate output filename if output_filename_base is None: output_filename_base = os.path.splitext(os.path.basename(input_filepath))[0] # Generate output dir if output_dir is None: output_dir = "./" else: if not os.path.isdir(output_dir): print "Output directory: {output_dir} does not exist.".format( output_dir=output_dir ) return # Do assembly lines = filepath_to_lines(input_filepath) try: assembly_line_infos = process_assembly_lines(lines) except AssemblyError as inst: print inst.args[0] return if output_format == "logisim": write_bitstrings_to_logisim(assembly_line_infos, output_dir, output_filename_base) if output_format == "arduino": write_bitstrings_to_arduino(assembly_line_infos, output_dir, output_filename_base) print "\n\nAssembly summary:\n" print generate_assembly_summary(assembly_line_infos)
[docs]def write_bitstrings_to_logisim(assembly_line_infos, output_dir, output_filename_base): """ Write machine code and variable bitstrings to logisim format. Args: assembly_line_infos (list(dict)): List of dictionaries of information about the parsed assembly. output_dir (str): The directory to write the assembled code into. output_filename_base (str): the basename (no extension) for the logisim file. """ file_contents = export.gen_logisim_program_file(assembly_line_infos) file_name = output_filename_base + ".mc" file_path = os.path.join(output_dir, file_name) with open(file_path, "w") as file: file.write(file_contents) completion_msg = ( "Assembly complete. Assembly file written to: {output_filepath}.".format( output_filepath=file_path ) ) print completion_msg
[docs]def write_bitstrings_to_arduino(assembly_line_infos, output_dir, output_filename_base): """ Write machine code and variable bitstrings to arduino format. Args: assembly_line_infos (list(dict)): List of dictionaries of information about the parsed assembly. output_dir (str): The directory to write the assembled code into. output_filename_base (str): The filename (with no extension) for the file. """ h_filename = "prog_{}.h".format(output_filename_base) cpp_filename = "prog_{}.cpp".format(output_filename_base) h_file_contents = export.gen_arduino_program_h_file(output_filename_base) cpp_file_contents = export.gen_arduino_program_cpp_file(assembly_line_infos, output_filename_base, h_filename) h_filepath = os.path.join(output_dir, h_filename) cpp_filepath = os.path.join(output_dir, cpp_filename) with open(h_filepath, "w") as h_file: h_file.write(h_file_contents) with open(cpp_filepath, "w") as cpp_file: cpp_file.write(cpp_file_contents) completion_msg = ( "Assembly complete. Assembly files written to: {h_filepath} and ." "{cpp_filepath}".format(h_filepath=h_filepath, cpp_filepath=cpp_filepath) ) print completion_msg
[docs]def filepath_to_lines(input_filepath): """ Take a filepath and get all the lines of the file. The lines returned have the newline stripped. Args: input_filepath (str): Path to the file of disk to read. Returns: list(str): Lines of the file. """ with open(input_filepath) as file: lines = file.read().splitlines() return lines
[docs]def get_mc_filename(asm_path): """ Get the filename for the machine code. This is the assembly filename with .asm replaced with .mc Args: asm_path (str): Path to the assembly file. Returns: str: Path to the machine code file. """ filename = os.path.basename(asm_path) return "{basename}.mc".format(basename=filename[:-4])
[docs]def gen_roms(output_dir=".", file_prefix=None, output_format="logisim"): """ Write files containing microcode for drive the roms. Args: output_dir (str) (optional): The directory to write the roms into. file_prefix (str) (optional): The prefix for the rom files. output_format (str) (optional): How to format the output. ``logisim`` or ``arduino``. """ if not os.path.isdir(output_dir): print "Output directory: {output_dir} does not exist.".format( output_dir=output_dir ) return if file_prefix is None: file_prefix = "" rom_data = rom.get_rom() rom_slices = rom.slice_rom(rom_data) for rom_index, rom_slice in rom_slices.iteritems(): slice_bitstrings = [romdata.data for romdata in rom_slice] file_basename = "{file_prefix}mc_rom_{rom_index}".format( file_prefix=file_prefix, rom_index=rom_index ) if output_format == "logisim": output = export.bitstrings_to_logisim(slice_bitstrings) filepath = os.path.join(output_dir, file_basename) with open(filepath, "w") as romfile: romfile.write(output) elif output_format == "arduino": rom_var_name = "MC_ROM_{rom_index}".format(rom_index=rom_index) export.write_arduino_pair( slice_bitstrings, output_dir, file_basename, rom_var_name, rom_index, ) decimal_rom_index = len(rom_slices) decimal_rom = rom.get_decimal_rom() decimal_file_basename = "{file_prefix}decimal_rom".format( file_prefix=file_prefix, ) decimal_bitstrings = [ decimal_rom_entry.data for decimal_rom_entry in decimal_rom ] if output_format == "logisim": output = export.bitstrings_to_logisim(decimal_bitstrings) filepath = os.path.join(output_dir, decimal_file_basename) with open(filepath, "w") as decimal_rom_file: decimal_rom_file.write(output) elif output_format == "arduino": rom_var_name = "DECIMAL_ROM" export.write_arduino_pair( decimal_bitstrings, output_dir, decimal_file_basename, rom_var_name, decimal_rom_index, ) msg = "ROM writing complete. ROMs written to {output_dir}".format( output_dir=output_dir ) print msg