def __init__(self, base = 0x80400000, mem_base = 0x0F000000, mem_size = 0x00001000): self.mem_base = mem_base self.mem_size = mem_size # assert mem_size <= 4096 self.dma = MMIO(base, 0x100) self.mem = MMIO(self.mem_base, self.mem_size)
class OffsetDAC: def __init__(self): self.m = MMIO(0x83C00000, 0x10000) print("1 %08x" % self.m.read32(0)) print("4 %08x control, clkdiv, enable" % self.m.read32(0x804)) def set_ch(self, ch, val): self.m.write32(0x810 + ch * 4 - 4, val)
def __init__(self, reg_bytes=None, ram=None, dspreg_bytes=None, ipl_ram=None): with open("config/spc700_instructions.json", "r") as f: self.__instructions = load(f) self.init_instructions() self.PC = 0x0200 self.A = 0x00 self.X = 0x00 self.Y = 0x00 self.S = 0x01EF self.P = PSW(0) self.wait = False self.stop = False if reg_bytes is not None: self.__parsebytes(reg_bytes) self.io = MMIO(ram, ipl_ram, dspreg_bytes)
def power_thread(config, regs, exit_event): try: mchbar_mmio = MMIO(0xfed159a0, 8) except MMIOError: print('[E] Unable to open /dev/mem. Try to disable Secure Boot.') sys.exit(1) while not exit_event.is_set(): # if power['method'] == 'polling': power['source'] = 'BATTERY' if is_on_battery() else 'AC' # set temperature trip point writemsr(0x1a2, regs[power['source']]['MSR_TEMPERATURE_TARGET']) # set PL1/2 on MSR writemsr(0x610, regs[power['source']]['MSR_PKG_POWER_LIMIT']) # set MCHBAR register to the same PL1/2 values mchbar_mmio.write32( 0, regs[power['source']]['MSR_PKG_POWER_LIMIT'] & 0xffffffff) mchbar_mmio.write32(4, regs[power['source']]['MSR_PKG_POWER_LIMIT'] >> 32) wait_t = config.getfloat(power['source'], 'Update_Rate_s') enable_hwp_mode = config.getboolean('AC', 'HWP_Mode', fallback=False) if power['source'] == 'AC' and enable_hwp_mode: cpu_usage = float(psutil.cpu_percent(interval=wait_t)) # set full performance mode only when load is greater than this threshold (~ at least 1 core full speed) performance_mode = cpu_usage > 100. / (cpu_count() * 1.25) # check again if we are on AC, since in the meantime we might have switched to BATTERY if not is_on_battery(): set_hwp('performance' if performance_mode else 'balance_performance') else: exit_event.wait(wait_t)
class AdcIf: def __init__(self): self.m = MMIO(0x83C00000, 0x10000) def reset(self): self.m.write32(0, 1) print("%08x" % self.m.read32(4)) self.m.write32(0, 0) print("%08x" % self.m.read32(4))
def power_thread(config, regs, exit_event): try: mchbar_mmio = MMIO(0xFED159A0, 8) except MMIOError: print('[E] Unable to open /dev/mem. Try to disable Secure Boot.') sys.exit(1) while not exit_event.is_set(): # print thermal status if args.debug: thermal_status = get_reset_thermal_status() for index, core_thermal_status in enumerate(thermal_status): for key, value in core_thermal_status.items(): print('[D] core {} thermal status: {} = {}'.format( index, key.replace("_", " "), value)) # switch back to sysfs polling if power['method'] == 'polling': power['source'] = 'BATTERY' if is_on_battery(config) else 'AC' # set temperature trip point if 'MSR_TEMPERATURE_TARGET' in regs[power['source']]: write_value = regs[power['source']]['MSR_TEMPERATURE_TARGET'] writemsr(0x1A2, write_value) if args.debug: read_value = readmsr(0x1A2, 24, 29, flatten=True) match = OK if write_value >> 24 == read_value else ERR print( '[D] TEMPERATURE_TARGET - write {:#x} - read {:#x} - match {}' .format(write_value >> 24, read_value, match)) # set cTDP if 'MSR_CONFIG_TDP_CONTROL' in regs[power['source']]: write_value = regs[power['source']]['MSR_CONFIG_TDP_CONTROL'] writemsr(0x64B, write_value) if args.debug: read_value = readmsr(0x64B, 0, 1, flatten=True) match = OK if write_value == read_value else ERR print( '[D] CONFIG_TDP_CONTROL - write {:#x} - read {:#x} - match {}' .format(write_value, read_value, match)) # set PL1/2 on MSR write_value = regs[power['source']]['MSR_PKG_POWER_LIMIT'] writemsr(0x610, write_value) if args.debug: read_value = readmsr(0x610, 0, 55, flatten=True) match = OK if write_value == read_value else ERR print( '[D] MSR PACKAGE_POWER_LIMIT - write {:#x} - read {:#x} - match {}' .format(write_value, read_value, match)) # set MCHBAR register to the same PL1/2 values mchbar_mmio.write32(0, write_value & 0xFFFFFFFF) mchbar_mmio.write32(4, write_value >> 32) if args.debug: read_value = mchbar_mmio.read32(0) | (mchbar_mmio.read32(4) << 32) match = OK if write_value == read_value else ERR print( '[D] MCHBAR PACKAGE_POWER_LIMIT - write {:#x} - read {:#x} - match {}' .format(write_value, read_value, match)) wait_t = config.getfloat(power['source'], 'Update_Rate_s') enable_hwp_mode = config.getboolean('AC', 'HWP_Mode', fallback=False) if power['source'] == 'AC' and enable_hwp_mode: cpu_usage = cpu_usage_pct(exit_event, interval=wait_t) # set full performance mode only when load is greater than this threshold (~ at least 1 core full speed) performance_mode = cpu_usage > 100.0 / (cpu_count() * 1.25) # check again if we are on AC, since in the meantime we might have switched to BATTERY if not is_on_battery(config): set_hwp('performance' if performance_mode else 'balance_performance') else: exit_event.wait(wait_t)
def power_thread(config, regs, exit_event): try: mchbar_mmio = MMIO(0xFED159A0, 8) except MMIOError: warning( 'Unable to open /dev/mem. TDP override might not work correctly.') warning( 'Try to disable Secure Boot and/or enable CONFIG_DEVMEM in kernel config.' ) mchbar_mmio = None next_hwp_write = 0 while not exit_event.is_set(): # log thermal status if args.debug: thermal_status = get_reset_thermal_status() for index, core_thermal_status in enumerate(thermal_status): for key, value in core_thermal_status.items(): log('[D] core {} thermal status: {} = {}'.format( index, key.replace("_", " "), value)) # switch back to sysfs polling if power['method'] == 'polling': power['source'] = 'BATTERY' if is_on_battery(config) else 'AC' # set temperature trip point if 'MSR_TEMPERATURE_TARGET' in regs[power['source']]: write_value = regs[power['source']]['MSR_TEMPERATURE_TARGET'] writemsr(0x1A2, write_value) if args.debug: read_value = readmsr(0x1A2, 24, 29, flatten=True) match = OK if write_value >> 24 == read_value else ERR log('[D] TEMPERATURE_TARGET - write {:#x} - read {:#x} - match {}' .format(write_value >> 24, read_value, match)) # set cTDP if 'MSR_CONFIG_TDP_CONTROL' in regs[power['source']]: write_value = regs[power['source']]['MSR_CONFIG_TDP_CONTROL'] writemsr(0x64B, write_value) if args.debug: read_value = readmsr(0x64B, 0, 1, flatten=True) match = OK if write_value == read_value else ERR log('[D] CONFIG_TDP_CONTROL - write {:#x} - read {:#x} - match {}' .format(write_value, read_value, match)) # set PL1/2 on MSR write_value = regs[power['source']]['MSR_PKG_POWER_LIMIT'] writemsr(0x610, write_value) if args.debug: read_value = readmsr(0x610, 0, 55, flatten=True) match = OK if write_value == read_value else ERR log('[D] MSR PACKAGE_POWER_LIMIT - write {:#x} - read {:#x} - match {}' .format(write_value, read_value, match)) if mchbar_mmio is not None: # set MCHBAR register to the same PL1/2 values mchbar_mmio.write32(0, write_value & 0xFFFFFFFF) mchbar_mmio.write32(4, write_value >> 32) if args.debug: read_value = mchbar_mmio.read32(0) | ( mchbar_mmio.read32(4) << 32) match = OK if write_value == read_value else ERR log('[D] MCHBAR PACKAGE_POWER_LIMIT - write {:#x} - read {:#x} - match {}' .format(write_value, read_value, match)) wait_t = config.getfloat(power['source'], 'Update_Rate_s') enable_hwp_mode = config.getboolean('AC', 'HWP_Mode', fallback=False) # set HWP less frequently. Just to be safe since (e.g.) TLP might reset this value if (enable_hwp_mode and next_hwp_write <= time() and ((power['method'] == 'dbus' and power['source'] == 'AC') or (power['method'] == 'polling' and not is_on_battery(config)))): set_hwp() next_hwp_write = time() + HWP_INTERVAL else: exit_event.wait(wait_t)
class SPC700(metaclass=InstructionMeta): def __init__(self, reg_bytes=None, ram=None, dspreg_bytes=None, ipl_ram=None): with open("config/spc700_instructions.json", "r") as f: self.__instructions = load(f) self.init_instructions() self.PC = 0x0200 self.A = 0x00 self.X = 0x00 self.Y = 0x00 self.S = 0x01EF self.P = PSW(0) self.wait = False self.stop = False if reg_bytes is not None: self.__parsebytes(reg_bytes) self.io = MMIO(ram, ipl_ram, dspreg_bytes) @property def YA(self): return self.Y << 8 + self.A @YA.setter def YA(self, value): self.Y = value >> 8 self.A = value & 0xFF @property def instructions(self): return self.__instructions def __parsebytes(self, reg_bytes): fmt = "HBBBH" self.PC, self.A, self.X, self.Y, self.S = unpack(fmt, reg_bytes[0:8]) self.S |= (1 << 8) self.P = PSW(reg_bytes[8]) def read(self, address): return self.io.read(address) def write(self, address, data): self.io.write(address, data) def fetch(self): value = self.read(self.PC) self.PC += 1 return value def load(self, address): return self.read(self.P.P << 8 | address) def store(self, address, data): self.write(self.P.P << 8 | address, data) def pull(self): self.S += 1 value = self.read(1 << 8 | self.S) return value def push(self, data): self.write(1 << 8 | self.S, data) self.S -= 1 def idle(self): ## TODO : implement timing pass def init_instructions(self): for i in range(len(self.__instructions)): fn = "lambda self=self : self.instruction" + self.__instructions[ i]["instruction"] + "(" if len(self.__instructions[i]["instruction_args"]) == 0: fn += ")" else: for a in self.__instructions[i]["instruction_args"].split(','): if a in ('A', 'P', 'S', 'X', 'Y'): fn += "'" + a + "'," elif a.startswith("fp"): fn += "self.algorithm" + a[3:-1] + "," elif len(a) >= 2 and a[1] == 'F': if len(a) == 2: fn += str("CZIHBPVN".index(a[0])) + "," else: fn += str("CZIHBPVN".index( a[0])) + "," + a[-1] + "," else: fn += a + "," fn = fn[:-1] + ")" fp = eval(fn) self.__instructions[i]["fp"] = fp def decodePC(self): opcode = self.read(self.PC) instruction = self.__instructions[opcode] decinc = SPC700Instruction( self.PC, instruction, self.io.RAM[self.PC:self.PC + instruction["bytes"]]) self.PC += instruction["bytes"] return decinc def step(self): opcode = self.fetch() instruction = self.__instructions[opcode] decinc = SPC700Instruction( self.PC - 1, instruction, self.io.RAM[self.PC - 1:self.PC - 1 + instruction["bytes"]]) instruction["fp"]() print("{:04X}: {:10} {:20} {}".format( decinc.offset, "{:10}".format(" ".join(["{:02x}".format(b) for b in decinc.bytes])), decinc.tostring(True), "A: {:02X} X: {:02X} Y: {:02X} SP: {:04X} {}".format( self.A, self.X, self.Y, (1 << 8) | self.S, " ".join([ "{}: {}".format("CZIHBPVN"[i], bitget(self.P.value, i)) for i in range(8) ])))) def __repr__(self) -> str: result = "+---------------------------------------+\n" result += "+ SPC700 REGISTERS +\n" result += "+---------------------------------------+\n" result += "| PC | A | X | Y | SP | NVPBHIZC |\n" result += "+---------------------------------------+\n" fmt = "+ {:04X} | {:02X} | {:02X} | {:02X} | {:04X} | {:08b} |\n" result += fmt.format(self.PC, self.A, self.X, self.Y, self.S, self.P.value) result += "+---------------------------------------+\n" result += str(self.io.DSP) return result
class DMA: def __init__(self, base = 0x80400000, mem_base = 0x0F000000, mem_size = 0x00001000): self.mem_base = mem_base self.mem_size = mem_size # assert mem_size <= 4096 self.dma = MMIO(base, 0x100) self.mem = MMIO(self.mem_base, self.mem_size) def read(self): self.dma.write32(0x30, 1<<2) # reset while True: d = self.dma.read32(0x30) if not (d & (1<<2)): break self.dma.write32(0x30, 1) self.dma.write32(0x48, self.mem_base) # print("reading %08x bytes" % self.mem_size) self.dma.write32(0x58, self.mem_size) # print("S2MM_LENGTH: %08x, S2MM_DMACR: %08x, SR %08x, adr %08x" % (self.dma.read32(0x58), self.dma.read32(0x30), self.dma.read32(0x34), self.dma.read32(0x48))) while self.dma.read32(0x30) & 1: print("... going") return self.mem.read(0, self.mem_size)[1024:]
def __init__(self): self.m = MMIO(0x83C00000, 0x10000)
def __init__(self): self.m = MMIO(0x83C00000, 0x10000) print("1 %08x" % self.m.read32(0)) print("4 %08x control, clkdiv, enable" % self.m.read32(0x804))