예제 #1
0
def getCPPMemoryIf(self, model, namespace):
    """Creates the necessary structures for communicating with the memory: An
    array in case of an internal memory or a TLM port for TLM memories."""

    archDWordType = self.bitSizes[0]
    archWordType = self.bitSizes[1]
    archHWordType = self.bitSizes[2]
    archByteType = self.bitSizes[3]

    global methodTypes, methodTypeLen
    methodTypes = {
        'read_dword': archDWordType,
        'read_word': archWordType,
        'read_half': archHWordType,
        'read_byte': archByteType,
        'read_instr': archWordType,
        'read_dword_dbg': archDWordType,
        'read_word_dbg': archWordType,
        'read_half_dbg': archHWordType,
        'read_byte_dbg': archByteType,
        'write_dword': archDWordType,
        'write_word': archWordType,
        'write_half': archHWordType,
        'write_byte': archByteType,
        'write_dword_dbg': archDWordType,
        'write_word_dbg': archWordType,
        'write_half_dbg': archHWordType,
        'write_byte_dbg': archByteType
    }
    methodTypeLen = {
        'read_dword': self.wordSize * 2,
        'read_word': self.wordSize,
        'read_half': self.wordSize / 2,
        'read_byte': 1,
        'read_instr': self.wordSize,
        'read_dword_dbg': self.wordSize * 2,
        'read_word_dbg': self.wordSize,
        'read_half_dbg': self.wordSize / 2,
        'read_byte_dbg': 1,
        'write_dword': self.wordSize * 2,
        'write_word': self.wordSize,
        'write_half': self.wordSize / 2,
        'write_byte': 1,
        'write_dword_dbg': self.wordSize * 2,
        'write_word_dbg': self.wordSize,
        'write_half_dbg': self.wordSize / 2,
        'write_byte_dbg': 1
    }

    #---------------------------------------------------------------------------
    ## @name Memory Interface Class
    #  @{

    memoryClasses = []
    memoryIfMembers = []
    emptyBody = cxx_writer.Code('')

    # Methods: read(), write()
    methodsCode = {}
    methodsAttrs = {}
    for methName in readMethodNames + writeMethodNames:
        methodsAttrs[methName] = ['pure', 'noexc']
        methodsCode[methName] = emptyBody
    for methName in readMethodNames_dbg:
        methodsAttrs[methName] = ['virtual']
        methodsCode[methName] = cxx_writer.Code('return this->' +
                                                methName[:-4] + '(address);')
    for methName in writeMethodNames_dbg:
        methodsAttrs[methName] = ['virtual']
        methodsCode[methName] = cxx_writer.Code('this->' + methName[:-4] +
                                                '(address, datum);')
    for methName in genericMethodNames:
        methodsAttrs[methName] = ['pure']
        methodsCode[methName] = emptyBody
    addMemoryMethods(self, memoryIfMembers, methodsCode, methodsAttrs)

    # Methods: swap_endianess()
    for cur_type in [archWordType, archHWordType]:
        swapEndianessCode = str(archByteType) + """ helper_byte = 0;
        for (unsigned i = 0; i < sizeof(""" + str(cur_type) + """)/2; i++) {
            helper_byte = ((""" + str(archByteType) + """ *)&datum)[i];
            ((""" + str(archByteType) + """ *)&datum)[i] = ((""" + str(
            archByteType) + """ *)&datum)[sizeof(""" + str(
                cur_type) + """) -1 -i];
            ((""" + str(archByteType) + """ *)&datum)[sizeof(""" + str(
                    cur_type) + """) -1 -i] = helper_byte;
        }
        """
        swapEndianessBody = cxx_writer.Code(swapEndianessCode)
        swapEndianessParam = cxx_writer.Parameter('datum', cur_type.makeRef())
        swapEndianessMethod = cxx_writer.Method('swap_endianess',
                                                swapEndianessBody,
                                                cxx_writer.voidType,
                                                'public', [swapEndianessParam],
                                                inline=True,
                                                noException=True,
                                                const=True)
        memoryIfMembers.append(swapEndianessMethod)

    # Constructors and Destructors
    memoryIfDtor = cxx_writer.Destructor(emptyBody, 'public', True)

    # Class
    memoryIfClass = cxx_writer.ClassDeclaration('MemoryInterface',
                                                memoryIfMembers,
                                                namespaces=[namespace])
    memoryIfClass.addDestructor(memoryIfDtor)
    memoryClasses.append(memoryIfClass)

    ## @} Memory Interface Class
    #---------------------------------------------------------------------------
    ## @name Local Memory Class
    #  @{

    from registerWriter import registerType, aliasType, registerContainerType
    MemoryToolsIfType = cxx_writer.TemplateType('MemoryToolsIf',
                                                [str(archWordType)],
                                                'common/tools_if.hpp')

    localMemoryMembers = []
    aliasAttrs = []
    aliasParams = []
    aliasInit = []

    # Attributes and Initialization
    if self.memAlias:
        aliasAttrs.append(
            cxx_writer.Attribute('R', registerContainerType.makeRef(),
                                 'private'))
        aliasParams.append(
            cxx_writer.Parameter('R', registerContainerType.makeRef()))
        aliasInit.append('R(R)')

    localMemoryMembers.append(
        cxx_writer.Attribute('debugger', MemoryToolsIfType.makePointer(),
                             'private'))

    # Methods: set_debugger()
    Code = 'this->debugger = debugger;'
    localMemoryMembers.append(
        cxx_writer.Method('set_debugger', cxx_writer.Code(Code),
                          cxx_writer.voidType, 'public', [
                              cxx_writer.Parameter(
                                  'debugger', MemoryToolsIfType.makePointer())
                          ]))

    # Methods: Building Blocks
    checkAddressCode = 'if (address >= this->size) {\nTHROW_ERROR("Address " << std::hex << std::showbase << address << " out of memory.");\n}\n'
    checkAddressCodeException = 'if (address >= this->size) {\nTHROW_EXCEPTION("Address " << std::hex << std::showbase << address << " out of memory.");\n}\n'

    checkWatchPointCode = """if (this->debugger != NULL) {
        this->debugger->notify_address(address, sizeof(datum));
    }
    """

    swapEndianessCode = '// Endianess conversion: The processor is always modeled with the host endianess. In case they are different, the endianess is swapped.\n'
    if self.isBigEndian:
        swapEndianessDefine = '#ifdef LITTLE_ENDIAN_BO\n'
    else:
        swapEndianessDefine = '#ifdef BIG_ENDIAN_BO\n'
    swapEndianessCode += swapEndianessDefine + 'this->swap_endianess(datum);\n#endif\n'

    if self.isBigEndian:
        swapDEndianessCode = '#ifdef LITTLE_ENDIAN_BO\n'
    else:
        swapDEndianessCode = '#ifdef BIG_ENDIAN_BO\n'
    swapDEndianessCode += str(archWordType) + ' datum1 = (' + str(
        archWordType) + ')(datum);\nthis->swap_endianess(datum1);\n'
    swapDEndianessCode += str(archWordType) + ' datum2 = (' + str(
        archWordType) + ')(datum >> ' + str(
            self.wordSize *
            self.byteSize) + ');\nthis->swap_endianess(datum2);\n'
    swapDEndianessCode += 'datum = datum1 | (((' + str(
        archDWordType) + ')datum2) << ' + str(
            self.wordSize * self.byteSize) + ');\n#endif\n'

    endianessCode = {
        'read_dword': swapDEndianessCode,
        'read_word': swapEndianessCode,
        'read_half': swapEndianessCode,
        'read_byte': '',
        'read_instr': swapEndianessCode,
        'read_dword_dbg': swapDEndianessCode,
        'read_word_dbg': swapEndianessCode,
        'read_half_dbg': swapEndianessCode,
        'read_byte_dbg': '',
        'write_dword': swapDEndianessCode,
        'write_word': swapEndianessCode,
        'write_half': swapEndianessCode,
        'write_byte': '',
        'write_dword_dbg': swapDEndianessCode,
        'write_word_dbg': swapEndianessCode,
        'write_half_dbg': swapEndianessCode,
        'write_byte_dbg': ''
    }

    readAliasCode = {}
    readMemAliasCode = ''
    for alias in self.memAlias:
        readMemAliasCode += 'if (address == ' + hex(long(
            alias.address)) + ') {\nreturn this->' + alias.alias + ';\n}\n'
    readAliasCode['read_dword'] = readMemAliasCode
    readAliasCode['read_word'] = readMemAliasCode
    readAliasCode['read_dword_dbg'] = readMemAliasCode
    readAliasCode['read_word_dbg'] = readMemAliasCode
    readAliasCode['read_instr'] = readMemAliasCode
    readMemAliasCode = ''
    for alias in self.memAlias:
        readMemAliasCode += 'if (address == ' + hex(
            long(alias.address)
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn (' + str(
            archHWordType) + ')' + alias.alias + '_temp;\n}\n'
        readMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + self.wordSize / 2
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(
            archHWordType) + ' *)&(' + alias.alias + '_temp)) + 1);\n}\n'
    readAliasCode['read_half_dbg'] = readMemAliasCode
    readAliasCode['read_half'] = readMemAliasCode
    readMemAliasCode = ''
    for alias in self.memAlias:
        readMemAliasCode += 'if (address == ' + hex(
            long(alias.address)
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn (' + str(
            archByteType) + ')' + alias.alias + '_temp;\n}\n'
        readMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 1
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(
            archByteType) + ' *)&(' + alias.alias + '_temp)) + 1);\n}\n'
        readMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 2
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(
            archByteType) + ' *)&(' + alias.alias + '_temp)) + 2);\n}\n'
        readMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 3
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(
            archByteType) + ' *)&(' + alias.alias + '_temp)) + 3);\n}\n'
    readAliasCode['read_byte_dbg'] = readMemAliasCode
    readAliasCode['read_byte'] = readMemAliasCode

    writeAliasCode = {}
    writeMemAliasCode = ''
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address
                 )) + ') {\n this->' + alias.alias + ' = datum;\nreturn;\n}\n'
    writeAliasCode['write_dword'] = writeMemAliasCode
    writeAliasCode['write_word'] = writeMemAliasCode
    writeAliasCode['write_dword_dbg'] = writeMemAliasCode
    writeAliasCode['write_word_dbg'] = writeMemAliasCode
    writeMemAliasCode = swapEndianessDefine
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + self.wordSize / 2
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(
            archHWordType
        ) + ' *)&' + alias.alias + '_temp) = (' + str(
            archHWordType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address)
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archHWordType
        ) + ' *)&' + alias.alias + '_temp) + 1) = (' + str(
            archHWordType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#else\n'
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address)
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(
            archHWordType
        ) + ' *)&' + alias.alias + '_temp) = (' + str(
            archHWordType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + self.wordSize / 2
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archHWordType
        ) + ' *)&' + alias.alias + '_temp) + 1) = (' + str(
            archHWordType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#endif\n'
    writeAliasCode['write_half'] = writeMemAliasCode
    writeAliasCode['write_half_dbg'] = writeMemAliasCode
    writeMemAliasCode = swapEndianessDefine
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 3
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(
            archByteType) + '*)&' + alias.alias + '_temp) = (' + str(
                archByteType) + ')datum;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 2
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archByteType
        ) + '*)&' + alias.alias + '_temp) + 1) = (' + str(
            archByteType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 1
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archByteType
        ) + '*)&' + alias.alias + '_temp) + 2) = (' + str(
            archByteType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address)
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archByteType
        ) + '*)&' + alias.alias + '_temp) + 3) = (' + str(
            archByteType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#else\n'
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address)
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(
            archByteType) + '*)&' + alias.alias + '_temp) = (' + str(
                archByteType) + ')datum;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 1
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archByteType
        ) + '*)&' + alias.alias + '_temp) + 1) = (' + str(
            archByteType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 2
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archByteType
        ) + '*)&' + alias.alias + '_temp) + 2) = (' + str(
            archByteType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(
            long(alias.address) + 3
        ) + ') {\n' + str(
            archWordType
        ) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(
            archByteType
        ) + '*)&' + alias.alias + '_temp) + 3) = (' + str(
            archByteType
        ) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#endif\n'
    writeAliasCode['write_byte'] = writeMemAliasCode
    writeAliasCode['write_byte_dbg'] = writeMemAliasCode

    # If there is no memory or debugging is disabled.
    if not self.memories or not any(memAttr[1] == True
                                    for memAttr in self.memories.values()):
        # Methods: read(), write(), lock(), unlock()
        methodsCode = {}
        methodsAttrs = {}
        for methName in readMethodNames + readMethodNames_dbg:
            methodsAttrs[methName] = []
            if methName.endswith('_gdb'):
                readBody = cxx_writer.Code(
                    readAliasCode[methName] + checkAddressCodeException +
                    '\n' + str(methodTypes[methName]) + ' datum = *(' +
                    str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address);\n' +
                    endianessCode[methName] + '\nreturn datum;')
            else:
                methodsAttrs[methName].append('noexc')
                readBody = cxx_writer.Code(
                    readAliasCode[methName] + checkAddressCode + '\n' +
                    str(methodTypes[methName]) + ' datum = *(' +
                    str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address);\n' +
                    endianessCode[methName] + '\nreturn datum;')
                if methName == 'read_word':
                    methodsAttrs[methName].append('inline')
            readBody.addInclude('common/report.hpp')
            methodsCode[methName] = readBody
        for methName in writeMethodNames + writeMethodNames_dbg:
            methodsAttrs[methName] = []
            if methName.endswith('_gdb'):
                methodsCode[methName] = cxx_writer.Code(
                    writeAliasCode[methName] + checkAddressCodeException +
                    checkWatchPointCode + '\n' + endianessCode[methName] +
                    '\n*(' + str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address) = datum;')
            else:
                methodsAttrs[methName].append('noexc')
                methodsCode[methName] = cxx_writer.Code(
                    writeAliasCode[methName] + checkAddressCode +
                    checkWatchPointCode + '\n' + endianessCode[methName] +
                    '\n*(' + str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address) = datum;')
                if methName == 'write_word':
                    methodsAttrs[methName].append('inline')
        for methName in genericMethodNames:
            methodsAttrs[methName] = []
            methodsCode[methName] = emptyBody
        addMemoryMethods(self, localMemoryMembers, methodsCode, methodsAttrs)

        # Attributes and Initialization
        arrayAttr = cxx_writer.Attribute('memory', cxx_writer.charPtrType,
                                         'private')
        localMemoryMembers.append(arrayAttr)

        sizeAttr = cxx_writer.Attribute('size', cxx_writer.uintType, 'private')
        localMemoryMembers.append(sizeAttr)

        # Constructors and Destructors
        localMemoryCtorParams = [
            cxx_writer.Parameter('size', cxx_writer.uintType)
        ]
        localMemoryCtorBody = cxx_writer.Code(
            'this->memory = new char[size];\nthis->debugger = NULL;')
        localMemoryCtor = cxx_writer.Constructor(
            localMemoryCtorBody, 'public', localMemoryCtorParams + aliasParams,
            ['size(size)'] + aliasInit)
        localMemoryDtorBody = cxx_writer.Code('delete [] this->memory;')
        localMemoryDtor = cxx_writer.Destructor(localMemoryDtorBody, 'public',
                                                True)

        # Class
        localMemoryClass = cxx_writer.ClassDeclaration(
            'LocalMemory',
            localMemoryMembers + aliasAttrs, [memoryIfClass.getType()],
            namespaces=[namespace])
        localMemoryClass.addDocString(
            brief='Memory Interface Class',
            detail=
            'Interface used by the core to communicate with memory. Defines the required TLM ports.'
        )
        localMemoryClass.addConstructor(localMemoryCtor)
        localMemoryClass.addDestructor(localMemoryDtor)
        memoryClasses.append(localMemoryClass)

    # Debugging is enabled.
    else:
        # Methods: read(), write(), lock()
        dumpCode1 = '\n\nMemAccessType dump_info;\n'
        if not self.systemc and not model.startswith(
                'acc') and not model.endswith('AT'):
            dumpCode1 += 'dump_info.simulation_time = cur_cycle;\n'
        else:
            dumpCode1 += 'dump_info.simulation_time = sc_time_stamp().to_double();\n'
        if [
                memName for memName, memAttr in self.memories.items()
                if memAttr[2] != ''
        ]:
            dumpCode1 += 'dump_info.program_counter = this->' + self.memories[
                memName][2] + ';\n'
        else:
            dumpCode1 += 'dump_info.program_counter = 0;\n'
        dumpCode1 += 'for (unsigned i = 0; i < '
        dumpCode2 = """; i++) {
            dump_info.address = address + i;
            dump_info.val = (char)((datum & (0xFF << i*8)) >> i*8);
            this->dump_file.write((char*)&dump_info, sizeof(MemAccessType));
        }
        """
        methodsCode = {}
        methodsAttrs = {}
        for methName in readMethodNames + readMethodNames_dbg:
            methodsAttrs[methName] = ['noexc']
            if methName.endswith('_gdb'):
                readBody = cxx_writer.Code(
                    readAliasCode[methName] + checkAddressCodeException +
                    '\n' + str(methodTypes[methName]) + ' datum = *(' +
                    str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address);\n' +
                    endianessCode[methName] + '\nreturn datum;')
            else:
                readBody = cxx_writer.Code(
                    readAliasCode[methName] + checkAddressCode + '\n' +
                    str(methodTypes[methName]) + ' datum = *(' +
                    str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address);\n' +
                    endianessCode[methName] + '\nreturn datum;')
                if methName == 'read_word':
                    methodsAttrs[methName].append('inline')
            readBody.addInclude('common/report.hpp')
            methodsCode[methName] = readBody
        for methName in writeMethodNames + writeMethodNames_dbg:
            methodsAttrs[methName] = []
            if methName.endswith('_gdb'):
                methodsCode[methName] = cxx_writer.Code(
                    writeAliasCode[methName] + checkAddressCodeException +
                    checkWatchPointCode + '\n' + endianessCode[methName] +
                    '\n*(' + str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address) = datum;' +
                    dumpCode1 + str(methodTypeLen[methName]) + dumpCode2)
            else:
                methodsAttrs[methName].append('noexc')
                methodsCode[methName] = cxx_writer.Code(
                    writeAliasCode[methName] + checkAddressCode +
                    checkWatchPointCode + '\n' + endianessCode[methName] +
                    '\n*(' + str(methodTypes[methName].makePointer()) +
                    ')(this->memory + (unsigned long)address) = datum;' +
                    dumpCode1 + str(methodTypeLen[methName]) + dumpCode2)
                if methName == 'write_word':
                    methodsAttrs[methName].append('inline')
        for methName in genericMethodNames:
            methodsAttrs[methName] = []
            methodsCode[methName] = emptyBody
        addMemoryMethods(self, localMemoryMembers, methodsCode, methodsAttrs)

        # Methods: end_of_simulation()
        endOfSimBody = cxx_writer.Code("""if (this->dump_file) {
           this->dump_file.flush();
           this->dump_file.close();
        }
        """)
        endOfSimMethod = cxx_writer.Method('end_of_simulation', endOfSimBody,
                                           cxx_writer.voidType, 'public')
        localMemoryMembers.append(endOfSimMethod)

        # Attributes and Initialization
        arrayAttr = cxx_writer.Attribute('memory', cxx_writer.charPtrType,
                                         'private')
        localMemoryMembers.append(arrayAttr)

        sizeAttr = cxx_writer.Attribute('size', cxx_writer.uintType, 'private')
        localMemoryMembers.append(sizeAttr)

        dumpFileAttr = cxx_writer.Attribute('dump_file',
                                            cxx_writer.ofstreamType, 'private')
        localMemoryMembers.append(dumpFileAttr)

        if not self.systemc and not model.startswith(
                'acc') and not model.endswith('AT'):
            cycleAttr = cxx_writer.Attribute('cur_cycle',
                                             cxx_writer.uintType.makeRef(),
                                             'private')
            localMemoryCtorParams.append(
                cxx_writer.Parameter('cur_cycle',
                                     cxx_writer.uintType.makeRef()))
            localMemoryCtorInit.append('cur_cycle(cur_cycle)')
            localMemoryMembers.append(cycleAttr)

        if [
                memName for memName, memAttr in self.memories.items()
                if memAttr[2] != ''
        ]:
            # Find out type of fetch register.
            from processor import extractRegInterval
            fetchReg = self.memories[memName][2]
            fetchIndex = extractRegInterval(fetchReg)
            if fetchIndex: fetchReg = fetchReg[0:fetchReg.index('[')]
            fetchType = None
            if fetchReg in [i.name for i in self.regs + self.regBanks]:
                fetchType = registerType
            if fetchType == None and fetchReg in [
                    i.name for i in self.aliasRegs + self.aliasRegBanks
            ]:
                fetchType = aliasType
            localMemoryMembers.append(
                cxx_writer.Attribute(self.memories[memName][2],
                                     fetchType.makeRef(), 'private'))
            pcRegParam = [
                cxx_writer.Parameter(self.memories[memName][2],
                                     fetchType.makeRef())
            ]
            pcRegInit = [
                self.memories[memName][2] + '(' + self.memories[memName][2] +
                ')'
            ]

        # Constructors and Destructors
        localMemoryCtorParams = [
            cxx_writer.Parameter('size', cxx_writer.uintType)
        ]
        localMemoryCtorInit = ['size(size)']
        localMemoryCtorBody = cxx_writer.Code("""this->memory = new char[size];
            this->debugger = NULL;
            this->dump_file.open("memoryDump.dmp", ios::out | ios::binary | ios::ate);
            if (!this->dump_file) {
                THROW_EXCEPTION("Cannot open file memoryDump.dmp for writing.");
            }
        """)
        localMemoryCtor = cxx_writer.Constructor(
            localMemoryCtorBody, 'public',
            localMemoryCtorParams + aliasParams + pcRegParam,
            localMemoryCtorInit + aliasInit + pcRegInit)
        localMemoryDtorBody = cxx_writer.Code("""delete [] this->memory;
        if (this->dump_file) {
           this->dump_file.flush();
           this->dump_file.close();
        }
        """)
        localMemoryDtor = cxx_writer.Destructor(localMemoryDtorBody, 'public',
                                                True)

        # Class
        localMemoryClass = cxx_writer.ClassDeclaration(
            'LocalMemory',
            localMemoryMembers + aliasAttrs, [memoryIfClass.getType()],
            namespaces=[namespace])
        localMemoryClass.addDocString(
            brief='Memory Interface Class',
            detail=
            'Interface used by the core to communicate with memory. Defines the required TLM ports.'
        )
        localMemoryClass.addConstructor(localMemoryCtor)
        localMemoryClass.addDestructor(localMemoryDtor)
        memoryClasses.append(localMemoryClass)

    ## @} Local Memory Class
    #---------------------------------------------------------------------------

    return memoryClasses
예제 #2
0
def getCPPPipeline(self, trace, combinedTrace, model, namespace):
    # Returns the class representing a pipeline stage.

    from registerWriter import registerType, aliasType, registerContainerType
    InstructionType = cxx_writer.Type('Instruction', includes = ['#include \"instructions.hpp\"', 'iomanip'])
    pipeType = cxx_writer.Type('BasePipeStage')

    #---------------------------------------------------------------------------
    ## @name Pipeline Base Class
    #  @{

    pipeClasses = []
    pipeBaseMembers = []
    pipeBaseCtorParams = []
    pipeBaseCtorValues = ''
    pipeBaseCtorInit = []
    pipeBaseCtorCode = ''

    # Attributes and Initialization
    for pipe in self.pipes:
        otherStageAttr = cxx_writer.Attribute('stage_' + pipe.name, pipeType.makePointer(), 'protected')
        pipeBaseMembers.append(otherStageAttr)
        otherStageParam = cxx_writer.Parameter('stage_' + pipe.name, pipeType.makePointer())
        pipeBaseCtorParams.append(otherStageParam)
        pipeBaseCtorValues += 'stage_' + pipe.name + ', '
        pipeBaseCtorInit.append('stage_' + pipe.name + '(stage_' + pipe.name + ')')

    stageAttr = cxx_writer.Attribute('prev_stage', pipeType.makePointer(), 'public')
    pipeBaseMembers.append(stageAttr)
    stageParam = cxx_writer.Parameter('prev_stage', pipeType.makePointer())#, initValue = 'NULL')
    pipeBaseCtorParams.append(stageParam)
    pipeBaseCtorValues += 'prev_stage, '
    pipeBaseCtorInit.append('prev_stage(prev_stage)')

    stageAttr = cxx_writer.Attribute('succ_stage', pipeType.makePointer(), 'public')
    pipeBaseMembers.append(stageAttr)
    stageParam = cxx_writer.Parameter('succ_stage', pipeType.makePointer())#, initValue = 'NULL')
    pipeBaseCtorParams.append(stageParam)
    pipeBaseCtorValues += 'succ_stage, '
    pipeBaseCtorInit.append('succ_stage(succ_stage)')

    stageBeginEventAttr = cxx_writer.Attribute('stage_begin_event', cxx_writer.sc_eventType, 'public')
    pipeBaseMembers.append(stageBeginEventAttr)

    stageEndedEventAttr = cxx_writer.Attribute('stage_end_event', cxx_writer.sc_eventType, 'public')
    pipeBaseMembers.append(stageEndedEventAttr)

    stageBeginningAttr = cxx_writer.Attribute('stage_beginning', cxx_writer.boolType, 'public')
    pipeBaseMembers.append(stageBeginningAttr)
    pipeBaseCtorCode += 'this->stage_beginning = false;\n'

    stageEndedAttrFlag = cxx_writer.Attribute('stage_ended', cxx_writer.boolType, 'public')
    pipeBaseMembers.append(stageEndedAttrFlag)
    pipeBaseCtorCode += 'this->stage_ended = false;\n'

    hasToFlushAttr = cxx_writer.Attribute('has_to_flush', cxx_writer.boolType, 'public')
    pipeBaseMembers.append(hasToFlushAttr)
    pipeBaseCtorCode += 'this->has_to_flush = false;\n'

    stalledAttr = cxx_writer.Attribute('stalled', cxx_writer.boolType, 'public')
    pipeBaseMembers.append(stalledAttr)
    pipeBaseCtorCode += 'this->stalled = false;\n'

    latencyAttr = cxx_writer.Attribute('latency', cxx_writer.sc_timeType, 'protected')
    pipeBaseMembers.append(latencyAttr)
    latencyParam = cxx_writer.Parameter('latency', cxx_writer.sc_timeType.makeRef())
    pipeBaseCtorParams.append(latencyParam)
    pipeBaseCtorValues += 'latency, '
    pipeBaseCtorInit.append('latency(latency)')

    registerAttr = cxx_writer.Attribute('R', registerContainerType.makeRef(), 'protected')
    pipeBaseMembers.append(registerAttr)
    registerParam = cxx_writer.Parameter('R', registerContainerType.makeRef())
    pipeBaseCtorParams.append(registerParam)
    pipeBaseCtorValues += 'R, '
    pipeBaseCtorInit.append('R(R)')

    NOPInstrType = cxx_writer.Type('NOPInstruction', '#include \"instructions.hpp\"')
    NOPInstrAttr = cxx_writer.Attribute('NOP_instr', NOPInstrType.makePointer(), 'public')
    pipeBaseMembers.append(NOPInstrAttr)
    pipeBaseCtorCode += 'this->NOP_instr = NULL;\n'

    # Declare the interrupt instructions if any and the corresponding signal
    # attribute.
    for irq in self.irqs:
        IRQInstrType = cxx_writer.Type(irq.name + 'IntrInstruction', '#include \"instructions.hpp\"')
        IRQInstrAttr = cxx_writer.Attribute(irq.name + '_instr', IRQInstrType.makePointer(), 'public')
        pipeBaseMembers.append(IRQInstrAttr)
        pipeBaseCtorCode += 'this->' + irq.name + '_instr = NULL;\n'

    curInstrAttr = cxx_writer.Attribute('cur_instr', InstructionType.makePointer(), 'public')
    pipeBaseMembers.append(curInstrAttr)
    pipeBaseCtorCode += 'cur_instr = NULL;\n'
    nextInstrAttr = cxx_writer.Attribute('next_instr', InstructionType.makePointer(), 'public')
    pipeBaseMembers.append(nextInstrAttr)
    pipeBaseCtorCode += 'this->next_instr = NULL;\n'

    # Constructors and Destructors
    pipeBaseCtor = cxx_writer.Constructor(cxx_writer.Code(pipeBaseCtorCode), 'public', pipeBaseCtorParams, pipeBaseCtorInit)

    # Methods: flush()
    flushCode = """this->has_to_flush = true;
    if (this->prev_stage != NULL) {
        this->prev_stage->flush();
    }
    """
    flushMethod = cxx_writer.Method('flush', cxx_writer.Code(flushCode), cxx_writer.voidType, 'public', noException = True)
    pipeBaseMembers.append(flushMethod)

    # Class
    pipeBaseClass = cxx_writer.ClassDeclaration('BasePipeStage', pipeBaseMembers, namespaces = [namespace])
    pipeBaseClass.addConstructor(pipeBaseCtor)
    pipeClasses.append(pipeBaseClass)

    ## @} Pipeline Base Class
    #---------------------------------------------------------------------------
    ## @name Pipeline Stage Classes
    #  @{

    from procWriter import pipeFetchAttrs, pipeCtorParams, pipeFetchCtorParams
    hasHazard = False
    hazardStarted = False
    seenStages = 0

    for pipeStage in self.pipes:
        if pipeStage.regsStage:
            if self.pipes.index(pipeStage) + 1 < len(self.pipes):
                # There exist stages between the beginning and the end of the hazard.
                if not self.pipes[self.pipes.index(pipeStage) + 1].wbStage:
                    hasHazard = True

    for pipeStage in self.pipes:
        seenStages += 1
        pipeMembers = []
        pipeCtorInit = []
        if pipeStage.fetchStage:
            for attr in pipeFetchAttrs:
                pipeMembers.append(attr)
                pipeCtorInit.append(attr.name + '(' + attr.name + ')')
        pipeCtorCode = ''

        # Methods: behavior()
        Code = """cur_instr = this->NOP_instr;
        this->next_instr = this->NOP_instr;

        // Wait for SystemC infrastructure, otherwise register callbacks will crash.
        wait(SC_ZERO_TIME);
        """

        if pipeStage.fetchStage:
            Code += 'unsigned num_NOPs = 0;\n'
            if self.instructionCache:
                Code += 'template_map< ' + str(self.bitSizes[1]) + ', CacheElem>::iterator icache_end = this->instr_cache.end();\n\n'

        Code += """while(true) {
        // Wait for other pipeline stages to begin.
        this->wait_pipe_begin();

        unsigned num_cycles = 0;
        """

        if pipeStage.fetchStage:
            Code +='this->instr_executing = true;\n'
            # Tool-induced Stall Detection
            Code += 'bool will_stall = false;\n'
        else:
            Code += """cur_instr = this->next_instr;
            bool instr_annulled = false;
            """

        # Hazard Detection
        if hasHazard and pipeStage.decodeStage:
            Code += """
            // Hazard Detection
            bool was_stalled = this->stalled, will_stall = false;
            // Check read registers.
            if (cur_instr->check_regs() > 0) {
                will_stall = true;
            // Lock write registers: Only if read registers are available, otherwise do not lock yet.
            } else if (!cur_instr->lock_regs()) {
                will_stall = true;
            }

            // Just discovered stall: Stall registers:
            if (!was_stalled && will_stall) {
              R.stall(""" + str(self.pipes.index(pipeStage)) + """);
            // Just discovered end of stall: Advance registers.
            } else if (was_stalled && !will_stall) {
              R.advance();
            }

            // Stall this pipeline stage.
            this->stalled = will_stall;
            """

        if hasHazard:
            Code += 'if (!this->stalled) {\n'

        if pipeStage.fetchStage:
            # Interrupts
            # If an interrupt is raised, we need to deal with it in the correct
            # stage, i.e. we need to create a special instruction that reaches
            # the correct stage and deals with the interrupt properly.
            Code += getInterruptCode(self, trace, pipeStage)
            if self.irqs:
                Code += 'else /* !IRQ */ {\n'

            # Instruction Fetch Address
            Code += getFetchAddressCode(self, model)

            # Logging and Tracing: Update cycle count.
            Code += """// Logging and Tracing: Update cycle count.
            if (cur_PC == this->profiler_start_addr) {
                this->profiler_time_start = sc_time_stamp();
            }
            if (cur_PC == this->profiler_end_addr) {
                this->profiler_time_end = sc_time_stamp();
            }
            """

            # Tools: Check whether the tools require the pipeline to be empty
            # before proceeding with execution.
            Code += """
                #ifndef DISABLE_TOOLS
                // Check whether the tools require the pipeline to be empty before proceeding with execution.
                if (this->tool_manager.is_pipeline_empty(cur_PC)) {
                    // Pipeline is already emptying.
                    if (num_NOPs) {
                        num_NOPs--;
                        will_stall = true;
                        // Just discovered end of stall: Advance registers.
                        if (!num_NOPs) {
                            will_stall = false;
                            // Do not advance registers if stall was initiated in a succeeding stage.
                            if (!this->stalled) {
                                R.advance();
                            }
                        }
                    }
                    // Pipeline has to be emptied.
                    else {
                        num_NOPs = """ + str(len(self.pipes)-self.pipes.index(pipeStage)-1)+ """;
                        // Stall might be shorter if pipeline already contains a bubble for some other reason.
                        BasePipeStage* stage = this->succ_stage;
                        while (stage) {
                            if (stage->cur_instr != this->NOP_instr)
                                break;
                            num_NOPs--;
                            stage = stage->succ_stage;
                        }
                        if (num_NOPs) {
                            // Stall this pipeline stage.
                            will_stall = true;
                            // Just discovered stall: Stall registers:
                            R.stall(""" + str(self.pipes.index(pipeStage)) + """);
                        }
                    }
                } else {
                    num_NOPs = 0;
                }
                if (num_NOPs > 0 && num_NOPs < """ + str(len(self.pipes)) + """) {
                    std::cerr << std::setw(15) << std::left << \"Stage=""" + pipeStage.name + """\" << \", PC=\" << std::hex << std::showbase << std::setw(10) << cur_PC << \", Instruction=NOP       , Mnemonic=NOP: Propagating NOP as required by tools.\" << std::endl;
                    wait(this->latency);
                """

            Code += """} else {
                    num_NOPs = 0;
                #endif
                    // Either the pipeline is actually empty or no tool requires it to be so. Proceed with execution.
                    wait((""" + str(1 - float(seenStages - 1)/(len(self.pipes) - 1)) + """)*this->latency);
            """

            # Tools: Instruction History
            Code += """
            // Tools: Instruction History
            #ifdef ENABLE_HISTORY
            HistoryInstrType instr_queue_elem;
            if (this->history_en) {
                instr_queue_elem.cycle = (unsigned)(sc_time_stamp()/this->latency);
                instr_queue_elem.address = cur_PC;
            }
            #endif
            """

            # Instruction Fetch and Issue
            # Computes the correct memory and/or memory port from which to
            # perform the fetch.
            doFetchCode = getDoFetchCode(self)
            # Perform the fetch only if the cache is not used or if the index of
            # the cache is the current instruction.
            if not (self.instructionCache and self.fastFetch):
                Code += doFetchCode

            # Two fetch paths are possible: the instruction buffer or the normal
            # instruction stream.
            # getPipeInstrIssueCode() executes this stage's instruction behavior.
            if self.instructionCache:
                Code += getCacheInstrFetchCode(self, doFetchCode, trace, combinedTrace, getPipeInstrIssueCode, hasHazard, pipeStage)
            else:
                Code += getDoDecodeCode(self, trace, combinedTrace, getPipeInstrIssueCode, hasHazard, pipeStage)

            if trace:
                if combinedTrace:
                    Code += 'if (cur_instr != this->NOP_instr) {\n'
                Code += 'std::cerr << std::setw(15) << std::left << \"Stage=' + pipeStage.name + '\" << \", PC=\" << std::hex << std::showbase << std::setw(10) << cur_PC << \", Instruction=\" << std::setw(10) << std::left << cur_instr->get_name() << \", Mnemonic=\" << cur_instr->get_mnemonic() << \'.\' << std::endl;\n'
                Code += 'cur_instr->print_trace();\n'
                if combinedTrace:
                    Code += '}\n'

        else:
            Code += 'wait((' + str(1 - float(seenStages - 1)/(len(self.pipes) - 1)) + ')*this->latency);\n'
            if trace:
                if not combinedTrace:
                    Code += 'std::cerr << std::setw(15) << std::left << \"Stage=' + pipeStage.name + '\" << \", PC=\" << std::hex << std::showbase << std::setw(10) << cur_instr->fetch_PC << \", Instruction=\" << std::setw(10) << std::left << cur_instr->get_name() << \", Mnemonic=\" << cur_instr->get_mnemonic() << \'.\' << std::endl;\n'

            # Instruction Issue: Execute this stage's instruction behavior.
            Code += getPipeInstrIssueCode(self, trace, combinedTrace, hasHazard, pipeStage)

        # User-defined Operations
        if pipeStage.operation:
            Code += '\n// User-defined Operations\n'
            Code += 'this->R.set_stage(' + str(self.pipes.index(pipeStage)) + ');\n'
            Code += pipeStage.operation
            Code += 'this->R.unset_stage();\n'

        if pipeStage.fetchStage:
            # Tools: Instruction History
            # Check if it is time to save the instruction queue to file.
            Code += """
            // Tools: Instruction History
            #ifdef ENABLE_HISTORY
            if (this->history_en) {
                // Add current instruction to history queue.
                this->history_instr_queue.push_back(instr_queue_elem);
                // In case a queue dump file has been specified, check if it needs to be saved.
                if (this->history_file) {
                    this->history_undumped_elements++;
                    if (history_undumped_elements == this->history_instr_queue.capacity()) {
                        boost::circular_buffer<HistoryInstrType>::const_iterator history_it, history_end;
                        for (history_it = this->history_instr_queue.begin(), history_end = this->history_instr_queue.end(); history_it != history_end; history_it++) {
                            this->history_file << history_it->get_mnemonic() << std::endl;
                        }
                        this->history_undumped_elements = 0;
                    }
                }
            }
            #endif
            """

        # Synchronize with other stages.
        Code += """// Instruction-induced Latency
        wait((num_cycles + """ + str(float(seenStages - 1)/(len(self.pipes) - 1)) + """)*this->latency);
        """

        if pipeStage.fetchStage:
            Code += """this->num_instructions++;
                #ifndef DISABLE_TOOLS
                } // Pipeline is empty or no tools require it to be so.
                #endif
            """

            # Interrupts
            if self.irqs:
                Code += '} // if (!IRQ)\n'

        if pipeStage.fetchStage or (hasHazard and pipeStage.decodeStage):
            Code += """
            // Stall pipeline stages.
            BasePipeStage* stage = this;
            while (stage) {
                stage->stalled = this->stalled || will_stall;
                stage = stage->prev_stage;
            }
            """

        Code += """
        // Wait for other pipeline stages to end.
        this->wait_pipe_end();
        """

        if not pipeStage.fetchStage:
            Code += """
            // Flush pipeline.
            if (instr_annulled) {
                cur_instr->flush_pipeline = false;
                // Flush preceding pipeline stages.
                this->prev_stage->flush();
                // Flush registers from this stage downwards.
                R.flush(""" + str(self.pipes.index(pipeStage)) + """);
            } else if (cur_instr->flush_pipeline) {
                cur_instr->flush_pipeline = false;
                // Flush preceding pipeline stages.
                this->prev_stage->flush();
                // Flush registers from the preceding stage downwards.
                R.flush(""" + str(self.pipes.index(pipeStage)-1) + """);
            }
            """

        # Stalled Due to Hazard
        if hasHazard:
            Code += """} else {
                // One of the following stages is blocked due to a data hazard, so the current stage is not doing anything.
                wait(this->latency);
            """

            if trace:
                if combinedTrace and pipeStage.fetchStage:
                    Code += 'if (cur_instr != this->NOP_instr) {\n'
                if not combinedTrace or pipeStage.decodeStage:
                    Code += 'std::cerr << std::setw(15) << std::left << \"Stage=' + pipeStage.name + '\" << \", PC=\" << std::hex << std::showbase << std::setw(10) << cur_instr->fetch_PC << \", Instruction=\" << std::setw(10) << std::left << cur_instr->get_name() << \", Mnemonic=\" << cur_instr->get_mnemonic() << \": Stalled on a data hazard.\" << std::endl;\n'
                if pipeStage.decodeStage:
                    Code += 'std::cerr << "                 Stalled registers: " << cur_instr->print_busy_regs() << std::endl;'
                if pipeStage.fetchStage:
                    Code += 'cur_instr->print_trace();\n'
                if combinedTrace and pipeStage.fetchStage:
                    Code += '}\n'

            if pipeStage.fetchStage or pipeStage.decodeStage:
                Code += """
                // Stall pipeline stages.
                BasePipeStage* stage = this;
                while (stage) {
                    stage->stalled = this->stalled || will_stall;
                    stage = stage->prev_stage;
                }
                """

            Code += """
                // Wait for other pipeline stages to end.
                this->wait_pipe_end();
            } // if (this->stalled)
            """

        Code += """
        // Instruction Propagation
        if (this->has_to_flush) {
            if (cur_instr->to_destroy) {
                delete cur_instr;
            } else {
                cur_instr->in_pipeline = false;
            }
            this->has_to_flush = false;
            cur_instr = this->NOP_instr;
            this->next_instr = this->NOP_instr;
            this->succ_stage->next_instr = this->NOP_instr;
        }"""
        if pipeStage.fetchStage or (hasHazard and pipeStage.decodeStage):
            Code += """ else if (will_stall) {
                // Propagate NOP because the stall is caused by the instruction in this stage.
                this->succ_stage->next_instr = this->NOP_instr;
            }"""
        if hasHazard and not pipeStage.decodeStage and pipeStage != self.pipes[-1]:
            Code += """ else if (this->stalled) {
                // Retain next_instr = cur_instr in the following stage.
                this->succ_stage->next_instr = this->succ_stage->cur_instr;
            }"""
        if pipeStage != self.pipes[-1]:
            Code += """ else {
                this->succ_stage->next_instr = cur_instr;
            }
            """

        #if hasHazard and pipeStage.decodeStage:
        #    Code += """ else if (will_stall) {
        #        // Propagate NOP because the stall is caused by the instruction in this stage.
        #        this->succ_stage->next_instr = this->NOP_instr;
        #    } else {
        #        this->succ_stage->next_instr = cur_instr;
        #    }
        #    """
        #elif hasHazard and pipeStage != self.pipes[-1]:
        #    Code += """ else if (this->stalled) {
        #        // Retain next_instr = cur_instr in the following stage.
        #        this->succ_stage->next_instr = this->succ_stage->cur_instr;
        #    } else {
        #        this->succ_stage->next_instr = cur_instr;
        #    }
        #    """
        #elif pipeStage != self.pipes[-1]:
        #    Code += '\nthis->succ_stage->next_instr = cur_instr;\n'

        if pipeStage.fetchStage:
            # Register Propagation and Instruction Execution State
            Code += """
            // Register Propagation
            this->refresh_registers();
            this->instr_executing = false;
            this->instr_end_event.notify();
            """

        if pipeStage.fetchStage and trace and not combinedTrace:
            Code += 'std::cerr << \"------------------------------------------------------------------------\" << std::endl << std::endl;\n'

        Code += '} // while (true)\n'

        if pipeStage.regsStage:
            hazardStarted = True

        behaviorMethod = cxx_writer.Method('behavior', cxx_writer.Code(Code), cxx_writer.voidType, 'public')
        pipeMembers.append(behaviorMethod)
        pipeCtorCode += 'SC_THREAD(behavior);\n'

        # Methods: wait_pipe_begin()
        Code = """this->stage_beginning = true;
        this->stage_begin_event.notify();
        """
        for pipeStageInner in self.pipes:
            if pipeStageInner != pipeStage:
                Code += """if (!this->stage_""" + pipeStageInner.name + """->stage_beginning) {
                    wait(this->stage_""" + pipeStageInner.name + """->stage_begin_event);
                }
                """
        Code += 'this->stage_ended = false;'
        waitPipeBeginMethod = cxx_writer.Method('wait_pipe_begin', cxx_writer.Code(Code), cxx_writer.voidType, 'private', noException = True)
        pipeMembers.append(waitPipeBeginMethod)

        # Methods: wait_pipe_end()
        Code = """this->stage_beginning = false;
        this->stage_ended = true;
        this->stage_end_event.notify();
        """
        for pipeStageInner in self.pipes:
            if pipeStageInner != pipeStage:
                Code += """if (!this->stage_""" + pipeStageInner.name + """->stage_ended) {
                    wait(this->stage_""" + pipeStageInner.name + """->stage_end_event);
                }
                """
        waitPipeEndMethod = cxx_writer.Method('wait_pipe_end', cxx_writer.Code(Code), cxx_writer.voidType, 'private', noException = True)
        pipeMembers.append(waitPipeEndMethod)

        # Methods: refresh_registers() for fetch stage
        # Propagates the register latches forward. Honors bypasses.
        if pipeStage.fetchStage:
            Code = """// Update the registers to propagate the values in the pipeline.
            R.clock_cycle();
            """
            refreshRegistersMethod = cxx_writer.Method('refresh_registers', cxx_writer.Code(Code), cxx_writer.voidType, 'private', noException = True)
            pipeMembers.append(refreshRegistersMethod)

            # Fetch Stage Attributes, Constructors and Destructors
            decoderAttr = cxx_writer.Attribute('decoder', cxx_writer.Type('Decoder', '#include \"decoder.hpp\"'), 'public')
            pipeMembers.append(decoderAttr)

            if self.instructionCache:
                CacheElemType = cxx_writer.Type('CacheElem')
                template_mapType = cxx_writer.TemplateType('template_map', [self.bitSizes[1], CacheElemType], hash_map_include)
                cacheAttr = cxx_writer.Attribute('instr_cache', template_mapType, 'private')
                pipeMembers.append(cacheAttr)

            profilerStartAddrAttr = cxx_writer.Attribute('profiler_start_addr', self.bitSizes[1], 'public')
            pipeMembers.append(profilerStartAddrAttr)
            pipeCtorCode += 'this->profiler_start_addr = (' + str(self.bitSizes[1]) + ')-1;\n'

            profilerEndAddrAttr = cxx_writer.Attribute('profiler_end_addr', self.bitSizes[1], 'public')
            pipeCtorCode += 'this->profiler_end_addr = (' + str(self.bitSizes[1]) + ')-1;\n'
            pipeMembers.append(profilerEndAddrAttr)

            # Here are the attributes for the instruction history queue
            historyFileAttr = cxx_writer.Attribute('history_file', cxx_writer.ofstreamType, 'public')
            pipeMembers.append(historyFileAttr)

            historyEnabledAttr = cxx_writer.Attribute('history_en', cxx_writer.boolType, 'public')
            pipeMembers.append(historyEnabledAttr)
            pipeCtorCode += 'this->history_en = false;\n'

            historyQueueType = cxx_writer.Type('HistoryInstrType', 'modules/instruction.hpp')
            histQueueType = cxx_writer.TemplateType('boost::circular_buffer', [historyQueueType], 'boost/circular_buffer.hpp')
            historyQueueAttr = cxx_writer.Attribute('history_instr_queue', histQueueType, 'public')
            pipeMembers.append(historyQueueAttr)
            pipeCtorCode += 'this->history_instr_queue.set_capacity(1000);\n'

            historyUndumpedElementsAttr = cxx_writer.Attribute('history_undumped_elements', cxx_writer.uintType, 'public')
            pipeMembers.append(historyUndumpedElementsAttr)
            pipeCtorCode += 'this->history_undumped_elements = 0;\n'

            # Close history dump file before destruction.
            pipeDtorCode = """#ifdef ENABLE_HISTORY
            if (this->history_en) {
                // In case a queue dump file has been specified, check if it needs to be saved.
                if (this->history_file) {
                    if (this->history_undumped_elements > 0) {
                        std::vector<std::string> history_vector;
                        boost::circular_buffer<HistoryInstrType>::const_reverse_iterator history_it, history_end;
                        unsigned history_read = 0;
                        for (history_read = 0, history_it = this->history_instr_queue.rbegin(), history_end = this->history_instr_queue.rend(); history_it != history_end && history_read < this->history_undumped_elements; history_it++, history_read++) {
                            history_vector.push_back(history_it->get_mnemonic());
                        }
                        std::vector<std::string>::const_reverse_iterator history_vector_it, history_vector_end;
                        for (history_vector_it = history_vector.rbegin(), history_vector_end = history_vector.rend(); history_vector_it != history_vector_end; history_vector_it++) {
                            this->history_file << *history_vector_it << std::endl;
                        }
                    }
                    this->history_file.flush();
                    this->history_file.close();
                }
            }
            #endif
            """
            # Constructors and Destructors
            pipeCtorInit = ['sc_module(pipe_name)', 'BasePipeStage(' + pipeBaseCtorValues[:-2] + ')'] + pipeCtorInit
            pipeCtorBody = cxx_writer.Code(pipeCtorCode + 'end_module();')
            pipeCtor = cxx_writer.Constructor(pipeCtorBody, 'public', pipeCtorParams + pipeFetchCtorParams, pipeCtorInit)
            pipeDtor = cxx_writer.Destructor(cxx_writer.Code(pipeDtorCode), 'public')
        else:
            # Constructors and Destructors
            pipeCtorInit = ['sc_module(pipe_name)', 'BasePipeStage(' + pipeBaseCtorValues[:-2] + ')'] + pipeCtorInit
            pipeCtorBody = cxx_writer.Code(pipeCtorCode + 'end_module();')
            pipeCtor = cxx_writer.Constructor(pipeCtorBody, 'public', pipeCtorParams, pipeCtorInit)

        # Class
        pipeClass = cxx_writer.SCModule(pipeStage.name + 'PipeStage', pipeMembers, [pipeType], namespaces = [namespace])
        pipeClass.addDocString(brief = 'Pipeline Class', detail = 'Implements a pipeline stage. Addresses hazards.')
        pipeClass.addConstructor(pipeCtor)
        if pipeStage.fetchStage:
            pipeClass.addDestructor(pipeDtor)
        pipeClasses.append(pipeClass)

    ## @} Pipeline Stage Classes
    #---------------------------------------------------------------------------

    return pipeClasses
예제 #3
0
def getCPPMemoryIf(self, model, namespace):
    """Creates the necessary structures for communicating with the memory: An
    array in case of an internal memory or a TLM port for TLM memories."""

    archDWordType = self.bitSizes[0]
    archWordType = self.bitSizes[1]
    archHWordType = self.bitSizes[2]
    archByteType = self.bitSizes[3]

    global methodTypes, methodTypeLen
    methodTypes = {'read_dword': archDWordType, 'read_word': archWordType, 'read_half': archHWordType, 'read_byte': archByteType, 'read_instr': archWordType,
                'read_dword_dbg': archDWordType, 'read_word_dbg': archWordType, 'read_half_dbg': archHWordType, 'read_byte_dbg': archByteType,
                'write_dword': archDWordType, 'write_word': archWordType, 'write_half': archHWordType, 'write_byte': archByteType,
                'write_dword_dbg': archDWordType, 'write_word_dbg': archWordType, 'write_half_dbg': archHWordType, 'write_byte_dbg': archByteType}
    methodTypeLen = {'read_dword': self.wordSize*2, 'read_word': self.wordSize, 'read_half': self.wordSize/2, 'read_byte': 1, 'read_instr': self.wordSize,
                    'read_dword_dbg': self.wordSize*2, 'read_word_dbg': self.wordSize, 'read_half_dbg': self.wordSize/2, 'read_byte_dbg': 1,
                    'write_dword': self.wordSize*2, 'write_word': self.wordSize, 'write_half': self.wordSize/2, 'write_byte': 1,
                    'write_dword_dbg': self.wordSize*2, 'write_word_dbg': self.wordSize, 'write_half_dbg': self.wordSize/2, 'write_byte_dbg': 1}

    #---------------------------------------------------------------------------
    ## @name Memory Interface Class
    #  @{

    memoryClasses = []
    memoryIfMembers = []
    emptyBody = cxx_writer.Code('')

    # Methods: read(), write()
    methodsCode = {}
    methodsAttrs = {}
    for methName in readMethodNames + writeMethodNames:
        methodsAttrs[methName] = ['pure', 'noexc']
        methodsCode[methName] = emptyBody
    for methName in readMethodNames_dbg:
        methodsAttrs[methName] = ['virtual']
        methodsCode[methName] = cxx_writer.Code('return this->' + methName[:-4] + '(address);')
    for methName in writeMethodNames_dbg:
        methodsAttrs[methName] = ['virtual']
        methodsCode[methName] = cxx_writer.Code('this->' + methName[:-4] + '(address, datum);')
    for methName in genericMethodNames:
        methodsAttrs[methName] = ['pure']
        methodsCode[methName] = emptyBody
    addMemoryMethods(self, memoryIfMembers, methodsCode, methodsAttrs)

    # Methods: swap_endianess()
    for cur_type in [archWordType, archHWordType]:
        swapEndianessCode = str(archByteType) + """ helper_byte = 0;
        for (unsigned i = 0; i < sizeof(""" + str(cur_type) + """)/2; i++) {
            helper_byte = ((""" + str(archByteType) + """ *)&datum)[i];
            ((""" + str(archByteType) + """ *)&datum)[i] = ((""" + str(archByteType) + """ *)&datum)[sizeof(""" + str(cur_type) + """) -1 -i];
            ((""" + str(archByteType) + """ *)&datum)[sizeof(""" + str(cur_type) + """) -1 -i] = helper_byte;
        }
        """
        swapEndianessBody = cxx_writer.Code(swapEndianessCode)
        swapEndianessParam = cxx_writer.Parameter('datum', cur_type.makeRef())
        swapEndianessMethod = cxx_writer.Method('swap_endianess', swapEndianessBody, cxx_writer.voidType, 'public', [swapEndianessParam], inline = True, noException = True, const = True)
        memoryIfMembers.append(swapEndianessMethod)

    # Constructors and Destructors
    memoryIfDtor = cxx_writer.Destructor(emptyBody, 'public', True)

    # Class
    memoryIfClass = cxx_writer.ClassDeclaration('MemoryInterface', memoryIfMembers, namespaces = [namespace])
    memoryIfClass.addDestructor(memoryIfDtor)
    memoryClasses.append(memoryIfClass)

    ## @} Memory Interface Class
    #---------------------------------------------------------------------------
    ## @name Local Memory Class
    #  @{

    from registerWriter import registerType, aliasType, registerContainerType
    MemoryToolsIfType = cxx_writer.TemplateType('MemoryToolsIf', [str(archWordType)], 'common/tools_if.hpp')

    localMemoryMembers = []
    aliasAttrs = []
    aliasParams = []
    aliasInit = []

    # Attributes and Initialization
    if self.memAlias:
        aliasAttrs.append(cxx_writer.Attribute('R', registerContainerType.makeRef(), 'private'))
        aliasParams.append(cxx_writer.Parameter('R', registerContainerType.makeRef()))
        aliasInit.append('R(R)')

    localMemoryMembers.append(cxx_writer.Attribute('debugger', MemoryToolsIfType.makePointer(), 'private'))

    # Methods: set_debugger()
    Code = 'this->debugger = debugger;'
    localMemoryMembers.append(cxx_writer.Method('set_debugger', cxx_writer.Code(Code), cxx_writer.voidType, 'public', [cxx_writer.Parameter('debugger', MemoryToolsIfType.makePointer())]))

    # Methods: Building Blocks
    checkAddressCode = 'if (address >= this->size) {\nTHROW_ERROR("Address " << std::hex << std::showbase << address << " out of memory.");\n}\n'
    checkAddressCodeException = 'if (address >= this->size) {\nTHROW_EXCEPTION("Address " << std::hex << std::showbase << address << " out of memory.");\n}\n'

    checkWatchPointCode = """if (this->debugger != NULL) {
        this->debugger->notify_address(address, sizeof(datum));
    }
    """

    swapEndianessCode = '// Endianess conversion: The processor is always modeled with the host endianess. In case they are different, the endianess is swapped.\n'
    if self.isBigEndian:
        swapEndianessDefine = '#ifdef LITTLE_ENDIAN_BO\n'
    else:
        swapEndianessDefine = '#ifdef BIG_ENDIAN_BO\n'
    swapEndianessCode += swapEndianessDefine + 'this->swap_endianess(datum);\n#endif\n'

    if self.isBigEndian:
        swapDEndianessCode = '#ifdef LITTLE_ENDIAN_BO\n'
    else:
        swapDEndianessCode = '#ifdef BIG_ENDIAN_BO\n'
    swapDEndianessCode += str(archWordType) + ' datum1 = (' + str(archWordType) + ')(datum);\nthis->swap_endianess(datum1);\n'
    swapDEndianessCode += str(archWordType) + ' datum2 = (' + str(archWordType) + ')(datum >> ' + str(self.wordSize*self.byteSize) + ');\nthis->swap_endianess(datum2);\n'
    swapDEndianessCode += 'datum = datum1 | (((' + str(archDWordType) + ')datum2) << ' + str(self.wordSize*self.byteSize) + ');\n#endif\n'

    endianessCode = {'read_dword': swapDEndianessCode, 'read_word': swapEndianessCode, 'read_half': swapEndianessCode, 'read_byte': '', 'read_instr': swapEndianessCode,
                'read_dword_dbg': swapDEndianessCode, 'read_word_dbg': swapEndianessCode, 'read_half_dbg': swapEndianessCode, 'read_byte_dbg': '',
                'write_dword': swapDEndianessCode, 'write_word': swapEndianessCode, 'write_half': swapEndianessCode, 'write_byte': '',
                'write_dword_dbg': swapDEndianessCode, 'write_word_dbg': swapEndianessCode, 'write_half_dbg': swapEndianessCode, 'write_byte_dbg': ''}

    readAliasCode = {}
    readMemAliasCode = ''
    for alias in self.memAlias:
        readMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\nreturn this->' + alias.alias + ';\n}\n'
    readAliasCode['read_dword'] = readMemAliasCode
    readAliasCode['read_word'] = readMemAliasCode
    readAliasCode['read_dword_dbg'] = readMemAliasCode
    readAliasCode['read_word_dbg'] = readMemAliasCode
    readAliasCode['read_instr'] = readMemAliasCode
    readMemAliasCode = ''
    for alias in self.memAlias:
        readMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn (' + str(archHWordType) + ')' + alias.alias + '_temp;\n}\n'
        readMemAliasCode += 'if (address == ' + hex(long(alias.address) + self.wordSize/2) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(archHWordType) + ' *)&(' + alias.alias + '_temp)) + 1);\n}\n'
    readAliasCode['read_half_dbg'] = readMemAliasCode
    readAliasCode['read_half'] = readMemAliasCode
    readMemAliasCode = ''
    for alias in self.memAlias:
        readMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn (' + str(archByteType) + ')' + alias.alias + '_temp;\n}\n'
        readMemAliasCode += 'if (address == ' + hex(long(alias.address) + 1) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(archByteType) + ' *)&(' + alias.alias + '_temp)) + 1);\n}\n'
        readMemAliasCode += 'if (address == ' + hex(long(alias.address) + 2) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(archByteType) + ' *)&(' + alias.alias + '_temp)) + 2);\n}\n'
        readMemAliasCode += 'if (address == ' + hex(long(alias.address) + 3) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n' + swapEndianessDefine + 'this->swap_endianess(' + alias.alias + '_temp);\n#endif\nreturn *(((' + str(archByteType) + ' *)&(' + alias.alias + '_temp)) + 3);\n}\n'
    readAliasCode['read_byte_dbg'] = readMemAliasCode
    readAliasCode['read_byte'] = readMemAliasCode

    writeAliasCode = {}
    writeMemAliasCode = ''
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\n this->' + alias.alias + ' = datum;\nreturn;\n}\n'
    writeAliasCode['write_dword'] = writeMemAliasCode
    writeAliasCode['write_word'] = writeMemAliasCode
    writeAliasCode['write_dword_dbg'] = writeMemAliasCode
    writeAliasCode['write_word_dbg'] = writeMemAliasCode
    writeMemAliasCode = swapEndianessDefine
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + self.wordSize/2) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(archHWordType) + ' *)&' + alias.alias + '_temp) = (' + str(archHWordType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archHWordType) + ' *)&' + alias.alias + '_temp) + 1) = (' + str(archHWordType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#else\n'
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(archHWordType) + ' *)&' + alias.alias + '_temp) = (' + str(archHWordType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + self.wordSize/2) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archHWordType) + ' *)&' + alias.alias + '_temp) + 1) = (' + str(archHWordType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#endif\n'
    writeAliasCode['write_half'] = writeMemAliasCode
    writeAliasCode['write_half_dbg'] = writeMemAliasCode
    writeMemAliasCode = swapEndianessDefine
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + 3) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(archByteType) + '*)&' + alias.alias + '_temp) = (' + str(archByteType) + ')datum;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + 2) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archByteType) + '*)&' + alias.alias + '_temp) + 1) = (' + str(archByteType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + 1) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archByteType) + '*)&' + alias.alias + '_temp) + 2) = (' + str(archByteType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archByteType) + '*)&' + alias.alias + '_temp) + 3) = (' + str(archByteType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#else\n'
    for alias in self.memAlias:
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address)) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*((' + str(archByteType) + '*)&' + alias.alias + '_temp) = (' + str(archByteType) + ')datum;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + 1) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archByteType) + '*)&' + alias.alias + '_temp) + 1) = (' + str(archByteType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + 2) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archByteType) + '*)&' + alias.alias + '_temp) + 2) = (' + str(archByteType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
        writeMemAliasCode += 'if (address == ' + hex(long(alias.address) + 3) + ') {\n' + str(archWordType) + ' ' + alias.alias + '_temp = this->' + alias.alias + ';\n*(((' + str(archByteType) + '*)&' + alias.alias + '_temp) + 3) = (' + str(archByteType) + ')datum;\nthis->' + alias.alias + '= ' + alias.alias + '_temp;\nreturn;\n}\n'
    writeMemAliasCode += '#endif\n'
    writeAliasCode['write_byte'] = writeMemAliasCode
    writeAliasCode['write_byte_dbg'] = writeMemAliasCode

    # If there is no memory or debugging is disabled.
    if not self.memories or not any(memAttr[1] == True for memAttr in self.memories.values()):
        # Methods: read(), write(), lock(), unlock()
        methodsCode = {}
        methodsAttrs = {}
        for methName in readMethodNames + readMethodNames_dbg:
            methodsAttrs[methName] = []
            if methName.endswith('_gdb'):
                readBody = cxx_writer.Code(readAliasCode[methName] + checkAddressCodeException + '\n' + str(methodTypes[methName]) + ' datum = *(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address);\n' + endianessCode[methName] + '\nreturn datum;')
            else:
                methodsAttrs[methName].append('noexc')
                readBody = cxx_writer.Code(readAliasCode[methName] + checkAddressCode + '\n' + str(methodTypes[methName]) + ' datum = *(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address);\n' + endianessCode[methName] + '\nreturn datum;')
                if methName == 'read_word':
                    methodsAttrs[methName].append('inline')
            readBody.addInclude('common/report.hpp')
            methodsCode[methName] = readBody
        for methName in writeMethodNames + writeMethodNames_dbg:
            methodsAttrs[methName] = []
            if methName.endswith('_gdb'):
                methodsCode[methName] = cxx_writer.Code(writeAliasCode[methName] + checkAddressCodeException + checkWatchPointCode + '\n' + endianessCode[methName] + '\n*(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address) = datum;')
            else:
                methodsAttrs[methName].append('noexc')
                methodsCode[methName] = cxx_writer.Code(writeAliasCode[methName] + checkAddressCode + checkWatchPointCode + '\n' + endianessCode[methName] + '\n*(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address) = datum;')
                if methName == 'write_word':
                    methodsAttrs[methName].append('inline')
        for methName in genericMethodNames:
            methodsAttrs[methName] = []
            methodsCode[methName] = emptyBody
        addMemoryMethods(self, localMemoryMembers, methodsCode, methodsAttrs)

        # Attributes and Initialization
        arrayAttr = cxx_writer.Attribute('memory', cxx_writer.charPtrType, 'private')
        localMemoryMembers.append(arrayAttr)

        sizeAttr = cxx_writer.Attribute('size', cxx_writer.uintType, 'private')
        localMemoryMembers.append(sizeAttr)

        # Constructors and Destructors
        localMemoryCtorParams = [cxx_writer.Parameter('size', cxx_writer.uintType)]
        localMemoryCtorBody = cxx_writer.Code('this->memory = new char[size];\nthis->debugger = NULL;')
        localMemoryCtor = cxx_writer.Constructor(localMemoryCtorBody, 'public', localMemoryCtorParams + aliasParams, ['size(size)'] + aliasInit)
        localMemoryDtorBody = cxx_writer.Code('delete [] this->memory;')
        localMemoryDtor = cxx_writer.Destructor(localMemoryDtorBody, 'public', True)

        # Class
        localMemoryClass = cxx_writer.ClassDeclaration('LocalMemory', localMemoryMembers + aliasAttrs, [memoryIfClass.getType()], namespaces = [namespace])
        localMemoryClass.addDocString(brief = 'Memory Interface Class', detail = 'Interface used by the core to communicate with memory. Defines the required TLM ports.')
        localMemoryClass.addConstructor(localMemoryCtor)
        localMemoryClass.addDestructor(localMemoryDtor)
        memoryClasses.append(localMemoryClass)

    # Debugging is enabled.
    else:
        # Methods: read(), write(), lock()
        dumpCode1 = '\n\nMemAccessType dump_info;\n'
        if not self.systemc and not model.startswith('acc') and not model.endswith('AT'):
            dumpCode1 += 'dump_info.simulation_time = cur_cycle;\n'
        else:
            dumpCode1 += 'dump_info.simulation_time = sc_time_stamp().to_double();\n'
        if [memName for memName, memAttr in self.memories.items() if memAttr[2] != '']:
            dumpCode1 += 'dump_info.program_counter = this->' + self.memories[memName][2] + ';\n'
        else:
            dumpCode1 += 'dump_info.program_counter = 0;\n'
        dumpCode1 += 'for (unsigned i = 0; i < '
        dumpCode2 = """; i++) {
            dump_info.address = address + i;
            dump_info.val = (char)((datum & (0xFF << i*8)) >> i*8);
            this->dump_file.write((char*)&dump_info, sizeof(MemAccessType));
        }
        """
        methodsCode = {}
        methodsAttrs = {}
        for methName in readMethodNames + readMethodNames_dbg:
            methodsAttrs[methName] = ['noexc']
            if methName.endswith('_gdb'):
                readBody = cxx_writer.Code(readAliasCode[methName] + checkAddressCodeException + '\n' + str(methodTypes[methName]) + ' datum = *(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address);\n' + endianessCode[methName] + '\nreturn datum;')
            else:
                readBody = cxx_writer.Code(readAliasCode[methName] + checkAddressCode + '\n' + str(methodTypes[methName]) + ' datum = *(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address);\n' + endianessCode[methName] + '\nreturn datum;')
                if methName == 'read_word':
                    methodsAttrs[methName].append('inline')
            readBody.addInclude('common/report.hpp')
            methodsCode[methName] = readBody
        for methName in writeMethodNames + writeMethodNames_dbg:
            methodsAttrs[methName] = []
            if methName.endswith('_gdb'):
                methodsCode[methName] = cxx_writer.Code(writeAliasCode[methName] + checkAddressCodeException + checkWatchPointCode + '\n' + endianessCode[methName] + '\n*(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address) = datum;' + dumpCode1 + str(methodTypeLen[methName]) + dumpCode2)
            else:
                methodsAttrs[methName].append('noexc')
                methodsCode[methName] = cxx_writer.Code(writeAliasCode[methName] + checkAddressCode + checkWatchPointCode + '\n' + endianessCode[methName] + '\n*(' + str(methodTypes[methName].makePointer()) + ')(this->memory + (unsigned long)address) = datum;' + dumpCode1 + str(methodTypeLen[methName]) + dumpCode2)
                if methName == 'write_word':
                    methodsAttrs[methName].append('inline')
        for methName in genericMethodNames:
            methodsAttrs[methName] = []
            methodsCode[methName] = emptyBody
        addMemoryMethods(self, localMemoryMembers, methodsCode, methodsAttrs)

        # Methods: end_of_simulation()
        endOfSimBody = cxx_writer.Code("""if (this->dump_file) {
           this->dump_file.flush();
           this->dump_file.close();
        }
        """)
        endOfSimMethod = cxx_writer.Method('end_of_simulation', endOfSimBody, cxx_writer.voidType, 'public')
        localMemoryMembers.append(endOfSimMethod)

        # Attributes and Initialization
        arrayAttr = cxx_writer.Attribute('memory', cxx_writer.charPtrType, 'private')
        localMemoryMembers.append(arrayAttr)

        sizeAttr = cxx_writer.Attribute('size', cxx_writer.uintType, 'private')
        localMemoryMembers.append(sizeAttr)

        dumpFileAttr = cxx_writer.Attribute('dump_file', cxx_writer.ofstreamType, 'private')
        localMemoryMembers.append(dumpFileAttr)

        if not self.systemc and not model.startswith('acc') and not model.endswith('AT'):
            cycleAttr = cxx_writer.Attribute('cur_cycle', cxx_writer.uintType.makeRef(), 'private')
            localMemoryCtorParams.append(cxx_writer.Parameter('cur_cycle', cxx_writer.uintType.makeRef()))
            localMemoryCtorInit.append('cur_cycle(cur_cycle)')
            localMemoryMembers.append(cycleAttr)

        if [memName for memName, memAttr in self.memories.items() if memAttr[2] != '']:
            # Find out type of fetch register.
            from processor import extractRegInterval
            fetchReg = self.memories[memName][2]
            fetchIndex = extractRegInterval(fetchReg)
            if fetchIndex: fetchReg = fetchReg[0:fetchReg.index('[')]
            fetchType = None
            if fetchReg in [i.name for i in self.regs + self.regBanks]:
                fetchType = registerType
            if fetchType == None and fetchReg in [i.name for i in self.aliasRegs + self.aliasRegBanks]:
                fetchType = aliasType
            localMemoryMembers.append(cxx_writer.Attribute(self.memories[memName][2], fetchType.makeRef(), 'private'))
            pcRegParam = [cxx_writer.Parameter(self.memories[memName][2], fetchType.makeRef())]
            pcRegInit = [self.memories[memName][2] + '(' + self.memories[memName][2] + ')']

        # Constructors and Destructors
        localMemoryCtorParams = [cxx_writer.Parameter('size', cxx_writer.uintType)]
        localMemoryCtorInit = ['size(size)']
        localMemoryCtorBody = cxx_writer.Code("""this->memory = new char[size];
            this->debugger = NULL;
            this->dump_file.open("memoryDump.dmp", ios::out | ios::binary | ios::ate);
            if (!this->dump_file) {
                THROW_EXCEPTION("Cannot open file memoryDump.dmp for writing.");
            }
        """)
        localMemoryCtor = cxx_writer.Constructor(localMemoryCtorBody, 'public', localMemoryCtorParams + aliasParams + pcRegParam, localMemoryCtorInit + aliasInit + pcRegInit)
        localMemoryDtorBody = cxx_writer.Code("""delete [] this->memory;
        if (this->dump_file) {
           this->dump_file.flush();
           this->dump_file.close();
        }
        """)
        localMemoryDtor = cxx_writer.Destructor(localMemoryDtorBody, 'public', True)

        # Class
        localMemoryClass = cxx_writer.ClassDeclaration('LocalMemory', localMemoryMembers + aliasAttrs, [memoryIfClass.getType()], namespaces = [namespace])
        localMemoryClass.addDocString(brief = 'Memory Interface Class', detail = 'Interface used by the core to communicate with memory. Defines the required TLM ports.')
        localMemoryClass.addConstructor(localMemoryCtor)
        localMemoryClass.addDestructor(localMemoryDtor)
        memoryClasses.append(localMemoryClass)

    ## @} Local Memory Class
    #---------------------------------------------------------------------------

    return memoryClasses