Exemple #1
0
 def __init__(self):
     self.private = "public"
     self.address = 0
     self.param_key = []
     self.params = VarTable()
     self.return_type = SparkyType()
     self.varTable = VarTable()
     self.funMemory = MemoryMap("function")
     self.tempMemory = MemoryMap("temporal")
Exemple #2
0
def main():
    mem = Memory(32 * 1024 * 1024)
    high = Memory(32 * 1024 * 1024)
    m = MemoryMap([
        (0, mem),
        (0xffffffff - len(high) + 1, high),
        (40000000, SimpleIO()),
    ])
    with open(sys.argv[1], 'rb') as f:
        mem.write_bin(0, f.read())
    cpu = CPU(m, debug_trace=False)
    while not cpu.ebreak:
        cpu.step()
    print(cpu.regs)
Exemple #3
0
 def __init__(self):
     self.BASE = 0  # Starting location for Quadruples //list starts with empty so its -1
     self.Quads = []
     self.globalMemory = MemoryMap("program")
     self.ConsMemory = MemoryMap("Constant")
     self.varTable = VarTable()
     self.funDir = FunctionDirectory()
     self.ClassDir = ClassTable()
     self.semanticCube = SemanticCube()
     self.pJumps = []  #
     self.VP = []  # Polish vector
     self.pOper = []
     self.pType = []
     self.pArray = []
     self.pIDs = []
     self.pEras = []
     self.pendingQuads = []
     self.current_quad = ()
     self.current_param_num = 0
     self.current_class = Class()
     self.current_object = Object()
     self.current_var = Var()
     self.current_function = Function()
     self.current_params = VarTable()
     self.current_type = SparkyType()
     self.local_class_func = FunctionDirectory()
     self.local_func = Function()
     self.local_class = Class()
     self.local_type = SparkyType()
     self.current_value = 0
     self.current_class_name = ""
     self.current_var_name = ""
     self.current_function_name = ""
     self.called_function = Function()
     self.current_scope = ""  # Working inside the global program
     self.class_stage = False  # Working either in a class or a function
     self.current_id_is_func = False
Exemple #4
0
 def __init__(self):
     self.funDir = FunctionDirectory()
     self.varTable = VarTable()
     self.claMemory = MemoryMap("class")
Exemple #5
0
    def __init__(self,
                 arch,
                 listfile,
                 binfile,
                 options,
                 logLevel=0,
                 logfile=None):
        self.options = options
        self.verbose = options.verbose
        self.debug = options.debug
        self.logfile = logfile
        self.assembler = None
        self.arch = arch
        self.listfile = listfile
        self.binfile = binfile
        self.srcfile = None
        self.opcodes = OPCODES[self.arch]
        self.symtab = SymbolTable(self)
        self.linenum = 0
        self.global_linenum = 0
        self.mode = OpcodeType.BASIC
        self.memmap = MemoryMap(arch, options.verbose)
        self.lastEbank = 0
        self.previousWasEbankEquals = False
        self.previousWasSbankEquals = False
        self.previousWasIndex = False
        self.code = []
        self.records = []
        self.srcline = None
        self.interpMode = False
        self.interpInstCount = 0
        self.interpArgs = 0
        self.interpArgCount = 0
        self.interpArgTypes = [None, None, None, None]
        self.interpArgCodes = [0, 0, 0, 0]
        self.interpArgIncrement = [False, False, False, False]
        self.indexed = False
        self.currentRecord = None
        self.previousRecord = None
        self.addSymbol = True
        self.reparse = False
        self.passnum = 0
        self.complementNext = False  # STADR complements the following instruction(s).
        self.errorMsg = None
        self.warningMsg = None

        # Log level:
        #  0 - None.
        #  1 - Errors.
        #  2 - Warnings.
        #  3 - Info messages.
        #  4 - Bank changes, binary generation.
        #  5 - LOC changes, detailed interpretive logging.
        #  6 - Symbol information, address conversion.
        #  7 - Parser operation.
        #  8 - Symbol resolution.
        self.logLevel = logLevel

        self.loc = 0  # Assembler PC, i.e. current position in erasable or fixed memory.
        self.ebank = 0  # Current E-Bank.
        self.fbank = 0  # Current F-Bank.
        self.super = 0  # Superbank bit (0/1).
        self.lastSuper = 0

        self.ebankloc = {}  # Saved current location for each erasable bank.
        self.fbankloc = {}  # Saved current location for each fixed bank.

        for bank in range(len(self.memmap.banks[MemoryType.ERASABLE])):
            self.ebankloc[bank] = 0
        for bank in range(len(self.memmap.banks[MemoryType.FIXED])):
            self.fbankloc[bank] = 0

        self.errors = 0
        self.warnings = 0
Exemple #6
0
class Context:
    def __init__(self,
                 arch,
                 listfile,
                 binfile,
                 options,
                 logLevel=0,
                 logfile=None):
        self.options = options
        self.verbose = options.verbose
        self.debug = options.debug
        self.logfile = logfile
        self.assembler = None
        self.arch = arch
        self.listfile = listfile
        self.binfile = binfile
        self.srcfile = None
        self.opcodes = OPCODES[self.arch]
        self.symtab = SymbolTable(self)
        self.linenum = 0
        self.global_linenum = 0
        self.mode = OpcodeType.BASIC
        self.memmap = MemoryMap(arch, options.verbose)
        self.lastEbank = 0
        self.previousWasEbankEquals = False
        self.previousWasSbankEquals = False
        self.previousWasIndex = False
        self.code = []
        self.records = []
        self.srcline = None
        self.interpMode = False
        self.interpInstCount = 0
        self.interpArgs = 0
        self.interpArgCount = 0
        self.interpArgTypes = [None, None, None, None]
        self.interpArgCodes = [0, 0, 0, 0]
        self.interpArgIncrement = [False, False, False, False]
        self.indexed = False
        self.currentRecord = None
        self.previousRecord = None
        self.addSymbol = True
        self.reparse = False
        self.passnum = 0
        self.complementNext = False  # STADR complements the following instruction(s).
        self.errorMsg = None
        self.warningMsg = None

        # Log level:
        #  0 - None.
        #  1 - Errors.
        #  2 - Warnings.
        #  3 - Info messages.
        #  4 - Bank changes, binary generation.
        #  5 - LOC changes, detailed interpretive logging.
        #  6 - Symbol information, address conversion.
        #  7 - Parser operation.
        #  8 - Symbol resolution.
        self.logLevel = logLevel

        self.loc = 0  # Assembler PC, i.e. current position in erasable or fixed memory.
        self.ebank = 0  # Current E-Bank.
        self.fbank = 0  # Current F-Bank.
        self.super = 0  # Superbank bit (0/1).
        self.lastSuper = 0

        self.ebankloc = {}  # Saved current location for each erasable bank.
        self.fbankloc = {}  # Saved current location for each fixed bank.

        for bank in range(len(self.memmap.banks[MemoryType.ERASABLE])):
            self.ebankloc[bank] = 0
        for bank in range(len(self.memmap.banks[MemoryType.FIXED])):
            self.fbankloc[bank] = 0

        self.errors = 0
        self.warnings = 0

    def __str__(self):
        text = ""
        text += "options: %s\n" % self.options
        text += "logfile: %s" % self.logfile
        text += "arch=%d\n" % self.arch
        text += "listfile: %s\n" % self.listfile
        text += "binfile: %s\n" % self.binfile
        text += "srcfile: %s\n" % self.srcfile
        text += "linenum=%d\n" % self.linenum
        text += "global_linenum=%d\n" % self.global_linenum
        text += "mode=%d\n" % self.mode
        text += "lastEbank=%s\n" % self.lastEbank
        text += "previousWasEbankEquals=%s\n" % self.previousWasEbankEquals
        text += "previousWasSbankEquals=%s\n" % self.previousWasSbankEquals
        text += "previousWasIndex=%s\n" % self.previousWasIndex
        text += "code: %s\n" % self.code
        text += "srcline: %s\n" % self.srcline
        text += "interpMode=%s\n" % self.interpMode
        text += "interpInstCount=%d\n" % self.interpInstCount
        text += "interpArgs=%d\n" % self.interpArgs
        text += "interpArgCount=%d\n" % self.interpArgCount
        text += "interpArgTypes: %s\n" % self.interpArgTypes
        text += "interpArgCodes: %s\n" % self.interpArgCodes
        text += "interpArgIncrement: %s\n" % self.interpArgIncrement
        text += "indexed=%s\n" % self.indexed
        text += "currentRecord: %s\n" % self.currentRecord
        text += "currentRecord.type:  %s (%d)\n" % (RecordType.toString(
            self.currentRecord.type), self.currentRecord.type)
        text += "previousRecord: %s\n" % self.previousRecord
        text += "previousRecord.type: %s (%d)\n" % (RecordType.toString(
            self.previousRecord.type), self.previousRecord.type)
        text += "addSymbol=%s\n" % self.addSymbol
        text += "reparse=%s\n" % self.reparse
        text += "passnum=%d\n" % self.passnum
        text += "complementNext=%s\n" % self.complementNext
        text += "logLevel=%d\n" % self.logLevel
        text += "loc=%06o\n" % self.loc
        text += "ebank=%02o\n" % self.ebank
        text += "fbank=%02o\n" % self.fbank
        text += "super=%s\n" % self.super
        text += "ebankloc: %s\n" % self.ebankloc
        text += "fbankloc: %s\n" % self.fbankloc
        text += "errors=%d\n" % self.errors
        text += "warnings=%d\n" % self.warnings
        return text

    def reset(self):
        self.linenum = 0
        self.global_linenum = 0
        self.mode = OpcodeType.BASIC
        self.lastEbank = 0
        self.previousWasEbankEquals = False
        self.previousWasSbankEquals = False
        self.previousWasIndex = False
        self.code = []
        self.srcline = None
        self.interpMode = False
        self.interpInstCount = 0
        self.interpArgs = 0
        self.interpArgCount = 0
        self.interpArgTypes = [None, None, None, None]
        self.interpArgCodes = [0, 0, 0, 0]
        self.interpArgIncrement = [False, False, False, False]
        self.indexed = False
        self.currentRecord = None
        self.previousRecord = None
        self.addSymbol = True
        self.reparse = False
        self.loc = 0
        self.super = 1
        self.ebank = 0
        self.fbank = 0
        self.complementNext = False

    def load(self, record, partial=True):
        self.linenum = record.linenum
        self.global_linenum = record.global_linenum
        self.code = record.code
        self.srcline = record.srcline
        self.loc = record.loc
        self.errorMsg = record.errorMsg
        self.warningMsg = record.warningMsg
        if partial == False:
            self.mode = record.mode
            self.lastEbank = record.lastEbank
            self.previousWasEbankEquals = record.previousWasEbankEquals
            self.previousWasSbankEquals = record.previousWasSbankEquals
            self.previousWasIndex = record.previousWasIndex
            self.complementNext = record.complementNext
            self.super = record.super
            self.ebank = record.ebank
            self.fbank = record.fbank

    def save(self, record, partial=True):
        record.linenum = self.linenum
        record.global_linenum = self.global_linenum
        record.code = self.code
        record.srcline = self.srcline
        record.errorMsg = self.errorMsg
        record.warningMsg = self.warningMsg
        if partial == False:
            record.lastEbank = self.lastEbank
            record.previousWasEbankEquals = self.previousWasEbankEquals
            record.previousWasSbankEquals = self.previousWasSbankEquals
            record.previousWasIndex = self.previousWasIndex
            record.complementNext = self.complementNext
            record.mode = self.mode
            record.loc = self.loc
            record.super = self.super
            record.ebank = self.ebank
            record.fbank = self.fbank

    def setLoc(self, loc):
        if not self.memmap.isValid(loc):
            self.error("trying to set loc to an invalid address (%06o)" % loc)
        if not self.reparse:
            self.log(5, "changing loc from %06o to %06o" % (self.loc, loc))
            self.loc = loc

    def incrLoc(self, delta):
        if not self.memmap.isValid(self.loc + delta):
            self.error("trying to set loc to an invalid address (%06o)" %
                       (self.loc + delta))
        if not self.reparse:
            self.log(
                5, "incrementing loc from %06o to %06o (delta=%04o)" %
                (self.loc, self.loc + delta, delta))
            self.loc += delta

    def switchEBank(self, bank):
        pa = self.ebankloc[bank]
        self.printBanks()
        self.switchEBankPA(pa)

    def saveCurrentBank(self):
        (bank, offset) = self.memmap.pseudoToBankOffset(self.loc)
        if bank != None and offset != None:
            if self.memmap.isErasable(self.loc):
                if offset > self.ebankloc[bank]:
                    self.log(
                        4, "saving EB %02o: %04o -> %04o" %
                        (bank, self.ebankloc[bank], offset))
                    self.ebankloc[bank] = offset
            else:
                if offset > self.fbankloc[bank]:
                    self.log(
                        4, "saving FB %02o: %04o -> %04o" %
                        (bank, self.fbankloc[bank], offset))
                    self.fbankloc[bank] = offset
        else:
            self.error("invalid address %06o" % self.loc)

    def switchEBankPA(self, pa):
        if not self.reparse:
            self.lastEbank = self.ebank
            self.saveCurrentBank()
            self.ebank = self.memmap.pseudoToBank(pa)
            self.log(
                4, "switched EB: %02o -> %02o" % (self.lastEbank, self.ebank))
            if self.memmap.isErasable(self.loc):
                # Only change LOC if it is currently erasable. This allows us to move LOC up through the various
                # erasable banks at the start as symbols are defined. Later, in fixed banks, you do not want an
                # EBANK= to affect LOC.
                self.setLoc(
                    self.memmap.segmentedToPseudo(MemoryType.ERASABLE,
                                                  self.ebank,
                                                  self.ebankloc[self.ebank]))
            self.previousWasEbankEquals = True
            self.printBanks()

    def revertEbank(self):
        if not self.reparse:
            self.printBanks()
            if self.previousWasEbankEquals == True:
                self.saveCurrentBank()
                self.ebank = self.lastEbank
                self.log(
                    4,
                    "reverted EB: %02o -> %02o" % (self.lastEbank, self.ebank))
                if self.memmap.isErasable(self.loc):
                    self.setLoc(
                        self.memmap.segmentedToPseudo(
                            MemoryType.ERASABLE, self.lastEbank,
                            self.ebankloc[self.lastEbank]))
                self.previousWasEbankEquals = False

    def revertSuper(self):
        if not self.reparse:
            self.printBanks()
            if self.previousWasSbankEquals == True:
                self.saveCurrentBank()
                self.super = self.lastSuper
                self.log(
                    4, "reverted SB: %o -> %o" % (self.lastSuper, self.super))
                self.previousWasSbankEquals = False

    def switchFBank(self, bank=None):
        if not self.reparse:
            if bank != None:
                self.saveCurrentBank()
                oldbank = self.fbank
                self.fbank = bank
                self.log(4,
                         "switched FB: %02o -> %02o" % (oldbank, self.fbank))
                if bank > 037:
                    self.super = 1
                    self.log(3, "BANK: setting superbit to 1")
            self.setLoc(
                self.memmap.segmentedToPseudo(MemoryType.FIXED, self.fbank,
                                              self.fbankloc[self.fbank]))
            self.log(
                4, "switched FB to %s" %
                (self.memmap.pseudoToSegmentedString(self.loc)))

    def getBankCount(self, memtype, bank):
        if memtype == MemoryType.ERASABLE:
            return self.ebankloc[bank]
        else:
            return self.fbankloc[bank]

    def getBankSize(self, memtype, bank):
        return self.memmap.banks[memtype][bank].size

    def printBanks(self):
        text = "LOC=%06o EB=%02o FB=%02o SB=%o " % (self.loc, self.ebank,
                                                    self.fbank, self.super)
        text += "EBs: "
        for eb in self.ebankloc.keys():
            if self.ebankloc[eb] > 0:
                text += "%02o:%04o " % (eb, self.ebankloc[eb])
        text += "FBs: "
        for fb in self.fbankloc.keys():
            if self.fbankloc[fb] > 0:
                text += "%02o:%04o " % (fb, self.fbankloc[fb])
        self.log(4, text)
Exemple #7
0
    def __init__(self, test_vectors_file=None, debug=False):
        self.debug = debug

        self.test_vectors_file = test_vectors_file
        mkdir_safe(config.gen_path)
        mkdir_safe(os.path.join(config.gen_path, config.vhdl_path))
        mkdir_safe(os.path.join(config.gen_path, 'c'))
        mkdir_safe(os.path.join(config.gen_path, config.ipcore_path))

        if self.test_vectors_file:
            global_symb = {}
            execfile(self.test_vectors_file, global_symb)
            self.test_vectors = global_symb['test_vectors']
        else:
            self.test_vectors = None

        self.ast_list = []
        if config.design_tool == 'pa':
            from poroto.plan_ahead import PlanAhead
            self.designer = PlanAhead()
        elif config.design_tool == 'ghdl':
            from poroto.ghdl import Ghdl
            self.designer = Ghdl()
        else:
            raise Exception("Unknown design tool '%s'" % config.design_tool)
        FunctionInstance.designer = self.designer
        self.registers_map = RegisterMap(self.debug)
        self.mems_map = MemoryMap(self.debug)
        self.functions = FunctionsRegistry(self.designer, self.mems_map,
                                           self.debug)
        self.streams_map = StreamMap(self.mems_map, self.functions, self.debug)
        self.pragma_registry = PragmaRegistry(self.debug)
        if config.converter == 'roccc':
            self.converter = ROCCC(self.debug)
        else:
            raise Exception("Unknown converter '%s'" % config.converter)
        self.converter.init(self.pragma_registry)
        if config.device_vendor == "xilinx":
            from poroto.xilinx import XilinxPlatform
            self.platform = XilinxPlatform(self.designer, self.debug)
        elif config.device_vendor == "sim":
            from poroto.sim import SimPlatform
            self.platform = SimPlatform(self.designer, self.debug)
        else:
            raise Exception("Unknown device vendor '%s'" %
                            config.platform_vendor)
        if config.sdk == "alphadata":
            from poroto.alphadata import AlphaDataSDK
            self.sdk = AlphaDataSDK(self.platform, self.designer,
                                    self.functions.functions,
                                    self.registers_map, self.mems_map,
                                    self.streams_map, self.test_vectors,
                                    self.debug)
        elif config.sdk == "none":
            from poroto.none import NoneSDK
            self.sdk = NoneSDK(self.platform, self.designer,
                               self.functions.functions, self.registers_map,
                               self.mems_map, self.streams_map,
                               self.test_vectors, self.debug)
        elif config.sdk == "riffa":
            from poroto.riffa import RiffaSDK
            self.sdk = RiffaSDK(self.platform, self.designer,
                                self.functions.functions, self.registers_map,
                                self.mems_map, self.streams_map,
                                self.test_vectors, self.debug)
        else:
            raise Exception("Unknown sdk '%s'" % config.sdk)
        self.pragma_registry.add_pragma_type('file',
                                             FilePragmaHandler(self.debug))
        self.pragma_registry.add_pragma_type('template',
                                             TemplatePragmaHandler(self.debug))
        self.pragma_registry.add_pragma_type(
            'memory',
            MemoryPragmaHandler(self.functions, self.mems_map, self.sdk,
                                self.debug))
        self.pragma_registry.add_pragma_type(
            'stream', StreamPragmaHandler(self.streams_map, self.debug))
        self.pragma_registry.add_pragma_type('latency',
                                             LatencyPragmaHandler(self.debug))
        self.pragma_registry.add_pragma_type('array',
                                             ArrayPragmaHandler(self.debug))
        array.init(self.platform, self.converter, self.functions,
                   self.mems_map, self.streams_map)
        IPInstance.converter = self.converter
        FileTemplate.platform = self.platform
Exemple #8
0
    def __init__(self, arch, listfile, binfile, options, logLevel=0, logfile=None):
        self.options = options
        self.verbose = options.verbose
        self.debug = options.debug
        self.logfile = logfile
        self.assembler = None
        self.arch = arch
        self.listfile = listfile
        self.binfile = binfile
        self.srcfile = None
        self.opcodes = OPCODES[self.arch]
        self.symtab = SymbolTable(self)
        self.linenum = 0
        self.global_linenum = 0
        self.mode = OpcodeType.BASIC
        self.memmap = MemoryMap(arch, options.verbose)
        self.lastEbank = 0
        self.previousWasEbankEquals = False
        self.previousWasSbankEquals = False
        self.previousWasIndex = False
        self.code = []
        self.records = []
        self.srcline = None
        self.interpMode = False
        self.interpInstCount = 0
        self.interpArgs = 0
        self.interpArgCount = 0
        self.interpArgTypes = [None, None, None, None]
        self.interpArgCodes = [0, 0, 0, 0]
        self.interpArgIncrement = [False, False, False, False]
        self.indexed = False
        self.currentRecord = None
        self.previousRecord = None
        self.addSymbol = True
        self.reparse = False
        self.passnum = 0
        self.complementNext = False  # STADR complements the following instruction(s).
        self.errorMsg = None
        self.warningMsg = None

        # Log level:
        #  0 - None.
        #  1 - Errors.
        #  2 - Warnings.
        #  3 - Info messages.
        #  4 - Bank changes, binary generation.
        #  5 - LOC changes, detailed interpretive logging.
        #  6 - Symbol information, address conversion.
        #  7 - Parser operation.
        #  8 - Symbol resolution.
        self.logLevel = logLevel

        self.loc = 0  # Assembler PC, i.e. current position in erasable or fixed memory.
        self.ebank = 0  # Current E-Bank.
        self.fbank = 0  # Current F-Bank.
        self.super = 0  # Superbank bit (0/1).
        self.lastSuper = 0

        self.ebankloc = {}  # Saved current location for each erasable bank.
        self.fbankloc = {}  # Saved current location for each fixed bank.

        for bank in range(len(self.memmap.banks[MemoryType.ERASABLE])):
            self.ebankloc[bank] = 0
        for bank in range(len(self.memmap.banks[MemoryType.FIXED])):
            self.fbankloc[bank] = 0

        self.errors = 0
        self.warnings = 0
Exemple #9
0
class Context:
    def __init__(self, arch, listfile, binfile, options, logLevel=0, logfile=None):
        self.options = options
        self.verbose = options.verbose
        self.debug = options.debug
        self.logfile = logfile
        self.assembler = None
        self.arch = arch
        self.listfile = listfile
        self.binfile = binfile
        self.srcfile = None
        self.opcodes = OPCODES[self.arch]
        self.symtab = SymbolTable(self)
        self.linenum = 0
        self.global_linenum = 0
        self.mode = OpcodeType.BASIC
        self.memmap = MemoryMap(arch, options.verbose)
        self.lastEbank = 0
        self.previousWasEbankEquals = False
        self.previousWasSbankEquals = False
        self.previousWasIndex = False
        self.code = []
        self.records = []
        self.srcline = None
        self.interpMode = False
        self.interpInstCount = 0
        self.interpArgs = 0
        self.interpArgCount = 0
        self.interpArgTypes = [None, None, None, None]
        self.interpArgCodes = [0, 0, 0, 0]
        self.interpArgIncrement = [False, False, False, False]
        self.indexed = False
        self.currentRecord = None
        self.previousRecord = None
        self.addSymbol = True
        self.reparse = False
        self.passnum = 0
        self.complementNext = False  # STADR complements the following instruction(s).
        self.errorMsg = None
        self.warningMsg = None

        # Log level:
        #  0 - None.
        #  1 - Errors.
        #  2 - Warnings.
        #  3 - Info messages.
        #  4 - Bank changes, binary generation.
        #  5 - LOC changes, detailed interpretive logging.
        #  6 - Symbol information, address conversion.
        #  7 - Parser operation.
        #  8 - Symbol resolution.
        self.logLevel = logLevel

        self.loc = 0  # Assembler PC, i.e. current position in erasable or fixed memory.
        self.ebank = 0  # Current E-Bank.
        self.fbank = 0  # Current F-Bank.
        self.super = 0  # Superbank bit (0/1).
        self.lastSuper = 0

        self.ebankloc = {}  # Saved current location for each erasable bank.
        self.fbankloc = {}  # Saved current location for each fixed bank.

        for bank in range(len(self.memmap.banks[MemoryType.ERASABLE])):
            self.ebankloc[bank] = 0
        for bank in range(len(self.memmap.banks[MemoryType.FIXED])):
            self.fbankloc[bank] = 0

        self.errors = 0
        self.warnings = 0

    def __str__(self):
        text = ""
        text += "options: %s\n" % self.options
        text += "logfile: %s" % self.logfile
        text += "arch=%d\n" % self.arch
        text += "listfile: %s\n" % self.listfile
        text += "binfile: %s\n" % self.binfile
        text += "srcfile: %s\n" % self.srcfile
        text += "linenum=%d\n" % self.linenum
        text += "global_linenum=%d\n" % self.global_linenum
        text += "mode=%d\n" % self.mode
        text += "lastEbank=%s\n" % self.lastEbank
        text += "previousWasEbankEquals=%s\n" % self.previousWasEbankEquals
        text += "previousWasSbankEquals=%s\n" % self.previousWasSbankEquals
        text += "previousWasIndex=%s\n" % self.previousWasIndex
        text += "code: %s\n" % self.code
        text += "srcline: %s\n" % self.srcline
        text += "interpMode=%s\n" % self.interpMode
        text += "interpInstCount=%d\n" % self.interpInstCount
        text += "interpArgs=%d\n" % self.interpArgs
        text += "interpArgCount=%d\n" % self.interpArgCount
        text += "interpArgTypes: %s\n" % self.interpArgTypes
        text += "interpArgCodes: %s\n" % self.interpArgCodes
        text += "interpArgIncrement: %s\n" % self.interpArgIncrement
        text += "indexed=%s\n" % self.indexed
        text += "currentRecord: %s\n" % self.currentRecord
        text += "currentRecord.type:  %s (%d)\n" % (
            RecordType.toString(self.currentRecord.type),
            self.currentRecord.type,
        )
        text += "previousRecord: %s\n" % self.previousRecord
        text += "previousRecord.type: %s (%d)\n" % (
            RecordType.toString(self.previousRecord.type),
            self.previousRecord.type,
        )
        text += "addSymbol=%s\n" % self.addSymbol
        text += "reparse=%s\n" % self.reparse
        text += "passnum=%d\n" % self.passnum
        text += "complementNext=%s\n" % self.complementNext
        text += "logLevel=%d\n" % self.logLevel
        text += "loc=%06o\n" % self.loc
        text += "ebank=%02o\n" % self.ebank
        text += "fbank=%02o\n" % self.fbank
        text += "super=%s\n" % self.super
        text += "ebankloc: %s\n" % self.ebankloc
        text += "fbankloc: %s\n" % self.fbankloc
        text += "errors=%d\n" % self.errors
        text += "warnings=%d\n" % self.warnings
        return text

    def reset(self):
        self.linenum = 0
        self.global_linenum = 0
        self.mode = OpcodeType.BASIC
        self.lastEbank = 0
        self.previousWasEbankEquals = False
        self.previousWasSbankEquals = False
        self.previousWasIndex = False
        self.code = []
        self.srcline = None
        self.interpMode = False
        self.interpInstCount = 0
        self.interpArgs = 0
        self.interpArgCount = 0
        self.interpArgTypes = [None, None, None, None]
        self.interpArgCodes = [0, 0, 0, 0]
        self.interpArgIncrement = [False, False, False, False]
        self.indexed = False
        self.currentRecord = None
        self.previousRecord = None
        self.addSymbol = True
        self.reparse = False
        self.loc = 0
        self.super = 1
        self.ebank = 0
        self.fbank = 0
        self.complementNext = False

    def load(self, record, partial=True):
        self.linenum = record.linenum
        self.global_linenum = record.global_linenum
        self.code = record.code
        self.srcline = record.srcline
        self.loc = record.loc
        self.errorMsg = record.errorMsg
        self.warningMsg = record.warningMsg
        if partial == False:
            self.mode = record.mode
            self.lastEbank = record.lastEbank
            self.previousWasEbankEquals = record.previousWasEbankEquals
            self.previousWasSbankEquals = record.previousWasSbankEquals
            self.previousWasIndex = record.previousWasIndex
            self.complementNext = record.complementNext
            self.super = record.super
            self.ebank = record.ebank
            self.fbank = record.fbank

    def save(self, record, partial=True):
        record.linenum = self.linenum
        record.global_linenum = self.global_linenum
        record.code = self.code
        record.srcline = self.srcline
        record.errorMsg = self.errorMsg
        record.warningMsg = self.warningMsg
        if partial == False:
            record.lastEbank = self.lastEbank
            record.previousWasEbankEquals = self.previousWasEbankEquals
            record.previousWasSbankEquals = self.previousWasSbankEquals
            record.previousWasIndex = self.previousWasIndex
            record.complementNext = self.complementNext
            record.mode = self.mode
            record.loc = self.loc
            record.super = self.super
            record.ebank = self.ebank
            record.fbank = self.fbank

    def setLoc(self, loc):
        if not self.memmap.isValid(loc):
            self.error("trying to set loc to an invalid address (%06o)" % loc)
        if not self.reparse:
            self.log(5, "changing loc from %06o to %06o" % (self.loc, loc))
            self.loc = loc

    def incrLoc(self, delta):
        if not self.memmap.isValid(self.loc + delta):
            self.error("trying to set loc to an invalid address (%06o)" % (self.loc + delta))
        if not self.reparse:
            self.log(5, "incrementing loc from %06o to %06o (delta=%04o)" % (self.loc, self.loc + delta, delta))
            self.loc += delta

    def switchEBank(self, bank):
        pa = self.ebankloc[bank]
        self.printBanks()
        self.switchEBankPA(pa)

    def saveCurrentBank(self):
        (bank, offset) = self.memmap.pseudoToBankOffset(self.loc)
        if bank != None and offset != None:
            if self.memmap.isErasable(self.loc):
                if offset > self.ebankloc[bank]:
                    self.log(4, "saving EB %02o: %04o -> %04o" % (bank, self.ebankloc[bank], offset))
                    self.ebankloc[bank] = offset
            else:
                if offset > self.fbankloc[bank]:
                    self.log(4, "saving FB %02o: %04o -> %04o" % (bank, self.fbankloc[bank], offset))
                    self.fbankloc[bank] = offset
        else:
            self.error("invalid address %06o" % self.loc)

    def switchEBankPA(self, pa):
        if not self.reparse:
            self.lastEbank = self.ebank
            self.saveCurrentBank()
            self.ebank = self.memmap.pseudoToBank(pa)
            self.log(4, "switched EB: %02o -> %02o" % (self.lastEbank, self.ebank))
            if self.memmap.isErasable(self.loc):
                # Only change LOC if it is currently erasable. This allows us to move LOC up through the various
                # erasable banks at the start as symbols are defined. Later, in fixed banks, you do not want an
                # EBANK= to affect LOC.
                self.setLoc(self.memmap.segmentedToPseudo(MemoryType.ERASABLE, self.ebank, self.ebankloc[self.ebank]))
            self.previousWasEbankEquals = True
            self.printBanks()

    def revertEbank(self):
        if not self.reparse:
            self.printBanks()
            if self.previousWasEbankEquals == True:
                self.saveCurrentBank()
                self.ebank = self.lastEbank
                self.log(4, "reverted EB: %02o -> %02o" % (self.lastEbank, self.ebank))
                if self.memmap.isErasable(self.loc):
                    self.setLoc(
                        self.memmap.segmentedToPseudo(
                            MemoryType.ERASABLE, self.lastEbank, self.ebankloc[self.lastEbank]
                        )
                    )
                self.previousWasEbankEquals = False

    def revertSuper(self):
        if not self.reparse:
            self.printBanks()
            if self.previousWasSbankEquals == True:
                self.saveCurrentBank()
                self.super = self.lastSuper
                self.log(4, "reverted SB: %o -> %o" % (self.lastSuper, self.super))
                self.previousWasSbankEquals = False

    def switchFBank(self, bank=None):
        if not self.reparse:
            if bank != None:
                self.saveCurrentBank()
                oldbank = self.fbank
                self.fbank = bank
                self.log(4, "switched FB: %02o -> %02o" % (oldbank, self.fbank))
                if bank > 037:
                    self.super = 1
                    self.log(3, "BANK: setting superbit to 1")
            self.setLoc(self.memmap.segmentedToPseudo(MemoryType.FIXED, self.fbank, self.fbankloc[self.fbank]))
            self.log(4, "switched FB to %s" % (self.memmap.pseudoToSegmentedString(self.loc)))

    def getBankCount(self, memtype, bank):
        if memtype == MemoryType.ERASABLE:
            return self.ebankloc[bank]
        else:
            return self.fbankloc[bank]

    def getBankSize(self, memtype, bank):
        return self.memmap.banks[memtype][bank].size

    def printBanks(self):
        text = "LOC=%06o EB=%02o FB=%02o SB=%o " % (self.loc, self.ebank, self.fbank, self.super)
        text += "EBs: "
        for eb in self.ebankloc.keys():
            if self.ebankloc[eb] > 0:
                text += "%02o:%04o " % (eb, self.ebankloc[eb])
        text += "FBs: "
        for fb in self.fbankloc.keys():
            if self.fbankloc[fb] > 0:
                text += "%02o:%04o " % (fb, self.fbankloc[fb])
        self.log(4, text)