leftovers

This commit is contained in:
2026-05-12 11:53:02 +02:00
parent e181656f04
commit 275ca96e74
12 changed files with 1316 additions and 1 deletions
+6
View File
@@ -209,3 +209,9 @@ $RECYCLE.BIN/
.DS_Store
_NCrunch*
venv
env
.env
.enviroment
__pycache__
View File
Binary file not shown.
+677
View File
@@ -0,0 +1,677 @@
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
import re
from dataclasses import dataclass
from typing import Dict, List, Optional, Tuple
from enum import Enum
class CPUMode(Enum):
SIMPLE = "simple"
X86 = "x86"
ARM = "arm"
@dataclass
class CPUState:
"""Complete CPU state representation"""
registers: Dict[str, int]
memory: bytearray
ip: int
sp: int
flags: Dict[str, bool]
halted: bool
mode: CPUMode
def __init__(self, mem_size=65536, mode=CPUMode.SIMPLE):
self.registers = {f"R{i}": 0 for i in range(8)}
self.memory = bytearray(mem_size)
self.ip = 0
self.sp = mem_size - 4 # Stack starts at top
self.flags = {"Z": False, "N": False, "C": False, "O": False}
self.halted = False
self.mode = mode
self.bp = mem_size - 4 # Base pointer
class Breakpoint:
def __init__(self, address=None, label=None, condition=None):
self.address = address
self.label = label
self.condition = condition
self.enabled = True
class Instruction:
def __init__(self, opcode, operands, line_num, label=None, comment=None):
self.opcode = opcode
self.operands = operands
self.line_num = line_num
self.label = label
self.comment = comment
self.address = 0
class AssemblyDebugger:
def __init__(self, mode=CPUMode.SIMPLE):
self.cpu = CPUState(mode=mode)
self.instructions: List[Instruction] = []
self.labels: Dict[str, int] = {}
self.breakpoints: List[Breakpoint] = []
self.execution_history: List[str] = []
self.source_lines: List[str] = []
self.pipeline_enabled = False
self.cache_enabled = False
def reset(self):
"""Reset CPU to initial state"""
mem_size = len(self.cpu.memory)
mode = self.cpu.mode
self.cpu = CPUState(mem_size, mode)
self.execution_history.clear()
def parse_assembly(self, code: str) -> Tuple[bool, str]:
"""Parse assembly code into instructions"""
self.instructions.clear()
self.labels.clear()
self.source_lines = code.split('\n')
address = 0
for line_num, line in enumerate(self.source_lines, 1):
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith(';'):
continue
# Extract comment
comment = None
if ';' in line:
line, comment = line.split(';', 1)
line = line.strip()
comment = comment.strip()
# Check for label
label = None
if ':' in line:
label, line = line.split(':', 1)
label = label.strip()
self.labels[label] = address
line = line.strip()
if not line:
continue
# Parse instruction
parts = line.split(None, 1)
if not parts:
continue
opcode = parts[0].upper()
operands = []
if len(parts) > 1:
operands = [op.strip() for op in parts[1].split(',')]
instr = Instruction(opcode, operands, line_num, label, comment)
instr.address = address
self.instructions.append(instr)
# Estimate instruction size (simplified)
address += 4
return True, "Assembly parsed successfully"
def parse_operand(self, operand: str) -> Tuple[str, int]:
"""Parse operand and return (type, value)"""
operand = operand.strip()
# Register
if operand.upper() in self.cpu.registers or operand.upper() in ['SP', 'BP', 'IP']:
return ('register', operand.upper())
# Memory reference [addr] or [register]
if operand.startswith('[') and operand.endswith(']'):
inner = operand[1:-1].strip()
# [register+offset] or [register-offset]
if '+' in inner or '-' in inner:
return ('memory_offset', inner)
# [register]
if inner.upper() in self.cpu.registers or inner.upper() in ['SP', 'BP']:
return ('memory_reg', inner.upper())
# [address]
try:
addr = self.parse_number(inner)
return ('memory', addr)
except:
return ('error', f"Invalid memory reference: {operand}")
# Immediate value
try:
value = self.parse_number(operand)
return ('immediate', value)
except:
pass
# Label
if operand in self.labels:
return ('label', self.labels[operand])
return ('error', f"Invalid operand: {operand}")
def parse_number(self, s: str) -> int:
"""Parse number in various formats"""
s = s.strip()
if s.startswith('0x') or s.startswith('0X'):
return int(s, 16)
elif s.startswith('0b') or s.startswith('0B'):
return int(s, 2)
else:
return int(s)
def get_operand_value(self, operand: str) -> int:
"""Get the value of an operand"""
op_type, value = self.parse_operand(operand)
if op_type == 'register':
if value == 'SP':
return self.cpu.sp
elif value == 'BP':
return self.cpu.bp
elif value == 'IP':
return self.cpu.ip
return self.cpu.registers[value]
elif op_type == 'immediate' or op_type == 'label':
return value
elif op_type == 'memory':
return self.read_memory(value, 4)
elif op_type == 'memory_reg':
addr = self.get_operand_value(value)
return self.read_memory(addr, 4)
elif op_type == 'memory_offset':
# Parse BP+4 or SP-8 etc
if '+' in value:
reg, offset = value.split('+')
addr = self.get_operand_value(reg.strip()) + self.parse_number(offset.strip())
else:
reg, offset = value.split('-')
addr = self.get_operand_value(reg.strip()) - self.parse_number(offset.strip())
return self.read_memory(addr, 4)
raise ValueError(f"Cannot get value of operand: {operand}")
def set_operand_value(self, operand: str, value: int):
"""Set the value of an operand"""
op_type, op_value = self.parse_operand(operand)
# Ensure value is in 32-bit range
value = value & 0xFFFFFFFF
if op_type == 'register':
if op_value == 'SP':
self.cpu.sp = value
elif op_value == 'BP':
self.cpu.bp = value
elif op_value == 'IP':
self.cpu.ip = value
else:
self.cpu.registers[op_value] = value
elif op_type == 'memory':
self.write_memory(op_value, value, 4)
elif op_type == 'memory_reg':
addr = self.get_operand_value(op_value)
self.write_memory(addr, value, 4)
elif op_type == 'memory_offset':
if '+' in op_value:
reg, offset = op_value.split('+')
addr = self.get_operand_value(reg.strip()) + self.parse_number(offset.strip())
else:
reg, offset = op_value.split('-')
addr = self.get_operand_value(reg.strip()) - self.parse_number(offset.strip())
self.write_memory(addr, value, 4)
else:
raise ValueError(f"Cannot set value of operand: {operand}")
def read_memory(self, address: int, size: int) -> int:
"""Read from memory (little-endian)"""
if address < 0 or address + size > len(self.cpu.memory):
raise ValueError(f"Memory access violation at 0x{address:08X}")
value = 0
for i in range(size):
value |= self.cpu.memory[address + i] << (i * 8)
return value
def write_memory(self, address: int, value: int, size: int):
"""Write to memory (little-endian)"""
if address < 0 or address + size > len(self.cpu.memory):
raise ValueError(f"Memory access violation at 0x{address:08X}")
for i in range(size):
self.cpu.memory[address + i] = (value >> (i * 8)) & 0xFF
def update_flags(self, result: int, original_bits=32):
"""Update CPU flags based on result"""
mask = (1 << original_bits) - 1
result = result & mask
self.cpu.flags['Z'] = (result == 0)
self.cpu.flags['N'] = (result & (1 << (original_bits - 1))) != 0
# Carry handled by individual operations
def execute_instruction(self, instr: Instruction) -> Tuple[bool, str]:
"""Execute a single instruction and return detailed explanation"""
explanation = []
try:
# Save state before execution
old_registers = self.cpu.registers.copy()
old_flags = self.cpu.flags.copy()
old_sp = self.cpu.sp
old_ip = self.cpu.ip
explanation.append(f"▶ EXECUTING: {instr.opcode} {', '.join(instr.operands)}")
if instr.comment:
explanation.append(f" Comment: {instr.comment}")
# Execute based on opcode
if instr.opcode == 'MOV':
src_val = self.get_operand_value(instr.operands[1])
explanation.append(f" Moving value {src_val} (0x{src_val:08X}) to {instr.operands[0]}")
self.set_operand_value(instr.operands[0], src_val)
elif instr.opcode == 'ADD':
dst_val = self.get_operand_value(instr.operands[0])
src_val = self.get_operand_value(instr.operands[1])
result = dst_val + src_val
explanation.append(f" {dst_val} + {src_val} = {result & 0xFFFFFFFF}")
self.cpu.flags['C'] = result > 0xFFFFFFFF
self.set_operand_value(instr.operands[0], result)
self.update_flags(result)
elif instr.opcode == 'SUB':
dst_val = self.get_operand_value(instr.operands[0])
src_val = self.get_operand_value(instr.operands[1])
result = dst_val - src_val
explanation.append(f" {dst_val} - {src_val} = {result & 0xFFFFFFFF}")
self.cpu.flags['C'] = result < 0
self.set_operand_value(instr.operands[0], result)
self.update_flags(result)
elif instr.opcode == 'MUL':
dst_val = self.get_operand_value(instr.operands[0])
src_val = self.get_operand_value(instr.operands[1])
result = dst_val * src_val
explanation.append(f" {dst_val} × {src_val} = {result & 0xFFFFFFFF}")
self.cpu.flags['C'] = result > 0xFFFFFFFF
self.set_operand_value(instr.operands[0], result)
self.update_flags(result)
elif instr.opcode == 'DIV':
dst_val = self.get_operand_value(instr.operands[0])
src_val = self.get_operand_value(instr.operands[1])
if src_val == 0:
return False, "❌ DIVISION BY ZERO"
result = dst_val // src_val
explanation.append(f" {dst_val} ÷ {src_val} = {result}")
self.set_operand_value(instr.operands[0], result)
self.update_flags(result)
elif instr.opcode == 'CMP':
val1 = self.get_operand_value(instr.operands[0])
val2 = self.get_operand_value(instr.operands[1])
result = val1 - val2
explanation.append(f" Comparing {val1} with {val2}: difference = {result}")
self.cpu.flags['Z'] = (val1 == val2)
self.cpu.flags['N'] = (result < 0)
self.cpu.flags['C'] = (val1 < val2)
explanation.append(f" Flags set: Z={int(self.cpu.flags['Z'])}, N={int(self.cpu.flags['N'])}, C={int(self.cpu.flags['C'])}")
elif instr.opcode == 'JMP':
target = self.labels.get(instr.operands[0])
if target is None:
return False, f"❌ Unknown label: {instr.operands[0]}"
explanation.append(f" Unconditional jump to {instr.operands[0]} (address 0x{target:04X})")
self.cpu.ip = target
return True, '\n'.join(explanation)
elif instr.opcode == 'JE' or instr.opcode == 'JZ':
target = self.labels.get(instr.operands[0])
if target is None:
return False, f"❌ Unknown label: {instr.operands[0]}"
if self.cpu.flags['Z']:
explanation.append(f" Zero flag is SET → Taking jump to {instr.operands[0]}")
self.cpu.ip = target
return True, '\n'.join(explanation)
else:
explanation.append(f" Zero flag is CLEAR → Not jumping, continuing to next instruction")
elif instr.opcode == 'JNE' or instr.opcode == 'JNZ':
target = self.labels.get(instr.operands[0])
if target is None:
return False, f"❌ Unknown label: {instr.operands[0]}"
if not self.cpu.flags['Z']:
explanation.append(f" Zero flag is CLEAR → Taking jump to {instr.operands[0]}")
self.cpu.ip = target
return True, '\n'.join(explanation)
else:
explanation.append(f" Zero flag is SET → Not jumping, continuing to next instruction")
elif instr.opcode == 'JG':
target = self.labels.get(instr.operands[0])
if target is None:
return False, f"❌ Unknown label: {instr.operands[0]}"
if not self.cpu.flags['Z'] and not self.cpu.flags['N']:
explanation.append(f" Greater than condition met → Taking jump")
self.cpu.ip = target
return True, '\n'.join(explanation)
else:
explanation.append(f" Greater than condition not met → Not jumping")
elif instr.opcode == 'JL':
target = self.labels.get(instr.operands[0])
if target is None:
return False, f"❌ Unknown label: {instr.operands[0]}"
if self.cpu.flags['N']:
explanation.append(f" Less than condition met → Taking jump")
self.cpu.ip = target
return True, '\n'.join(explanation)
else:
explanation.append(f" Less than condition not met → Not jumping")
elif instr.opcode == 'PUSH':
value = self.get_operand_value(instr.operands[0])
self.cpu.sp -= 4
explanation.append(f" Pushing value {value} (0x{value:08X}) onto stack")
explanation.append(f" Stack pointer: 0x{old_sp:04X} → 0x{self.cpu.sp:04X}")
self.write_memory(self.cpu.sp, value, 4)
elif instr.opcode == 'POP':
if self.cpu.sp >= len(self.cpu.memory) - 4:
return False, "❌ STACK UNDERFLOW"
value = self.read_memory(self.cpu.sp, 4)
explanation.append(f" Popping value {value} (0x{value:08X}) from stack")
self.set_operand_value(instr.operands[0], value)
old_sp = self.cpu.sp
self.cpu.sp += 4
explanation.append(f" Stack pointer: 0x{old_sp:04X} → 0x{self.cpu.sp:04X}")
elif instr.opcode == 'CALL':
target = self.labels.get(instr.operands[0])
if target is None:
return False, f"❌ Unknown label: {instr.operands[0]}"
# Push return address
return_addr = self.cpu.ip + 4
self.cpu.sp -= 4
self.write_memory(self.cpu.sp, return_addr, 4)
explanation.append(f" Calling function {instr.operands[0]}")
explanation.append(f" Return address 0x{return_addr:04X} pushed to stack")
explanation.append(f" Jumping to 0x{target:04X}")
self.cpu.ip = target
return True, '\n'.join(explanation)
elif instr.opcode == 'RET':
if self.cpu.sp >= len(self.cpu.memory) - 4:
return False, "❌ STACK UNDERFLOW on RET"
return_addr = self.read_memory(self.cpu.sp, 4)
self.cpu.sp += 4
explanation.append(f" Returning to address 0x{return_addr:04X}")
self.cpu.ip = return_addr
return True, '\n'.join(explanation)
elif instr.opcode == 'LOAD':
addr_val = self.get_operand_value(instr.operands[1])
value = self.read_memory(addr_val, 4)
explanation.append(f" Loading value {value} (0x{value:08X}) from memory[0x{addr_val:04X}]")
self.set_operand_value(instr.operands[0], value)
elif instr.opcode == 'STORE':
addr_val = self.get_operand_value(instr.operands[0])
value = self.get_operand_value(instr.operands[1])
explanation.append(f" Storing value {value} (0x{value:08X}) to memory[0x{addr_val:04X}]")
self.write_memory(addr_val, value, 4)
elif instr.opcode == 'HLT':
explanation.append(" Halting CPU")
self.cpu.halted = True
return True, '\n'.join(explanation)
else:
return False, f"❌ Unknown instruction: {instr.opcode}"
# Advance IP if not already modified by jump/call/ret
if self.cpu.ip == old_ip:
self.cpu.ip += 4
# Show what changed
changes = []
for reg, val in self.cpu.registers.items():
if val != old_registers[reg]:
changes.append(f" {reg}: 0x{old_registers[reg]:08X} → 0x{val:08X}")
if self.cpu.sp != old_sp:
changes.append(f" SP: 0x{old_sp:04X} → 0x{self.cpu.sp:04X}")
if self.cpu.ip != old_ip and instr.opcode not in ['JMP', 'JE', 'JNE', 'JG', 'JL', 'CALL', 'RET']:
changes.append(f" IP: 0x{old_ip:04X} → 0x{self.cpu.ip:04X}")
flag_changes = []
for flag, val in self.cpu.flags.items():
if val != old_flags[flag]:
flag_changes.append(f"{flag}={int(val)}")
if flag_changes:
changes.append(f" FLAGS: {' '.join(flag_changes)}")
if changes:
explanation.append("\n🔄 CHANGES:")
explanation.extend(changes)
else:
explanation.append("\n (No register or flag changes)")
return True, '\n'.join(explanation)
except Exception as e:
return False, f"❌ ERROR: {str(e)}"
def find_instruction_at_ip(self) -> Optional[Instruction]:
"""Find instruction at current IP"""
for instr in self.instructions:
if instr.address == self.cpu.ip:
return instr
return None
def check_breakpoints(self) -> Optional[Breakpoint]:
"""Check if any breakpoint is hit"""
for bp in self.breakpoints:
if not bp.enabled:
continue
if bp.address is not None and bp.address == self.cpu.ip:
return bp
if bp.condition:
# Evaluate condition (simplified)
try:
# Replace register names with values
cond = bp.condition
for reg in self.cpu.registers:
cond = cond.replace(reg, str(self.cpu.registers[reg]))
if eval(cond):
return bp
except:
pass
return None
def get_state_display(self) -> str:
"""Get formatted CPU state"""
lines = []
lines.append("REGISTERS:")
# Show registers in rows of 4
for i in range(0, 8, 4):
reg_line = " "
for j in range(4):
if i + j < 8:
reg = f"R{i+j}"
val = self.cpu.registers[reg]
reg_line += f"{reg}=0x{val:08X} "
lines.append(reg_line)
lines.append(f" SP=0x{self.cpu.sp:04X} BP=0x{self.cpu.bp:04X} IP=0x{self.cpu.ip:04X}")
flags_str = ' '.join([f"{k}={int(v)}" for k, v in self.cpu.flags.items()])
lines.append(f" FLAGS: {flags_str}")
# Show stack
lines.append("\nSTACK (top 16 bytes):")
for addr in range(self.cpu.sp, min(self.cpu.sp + 16, len(self.cpu.memory)), 4):
value = self.read_memory(addr, 4)
ascii_repr = ''.join([chr(b) if 32 <= b < 127 else '.'
for b in self.cpu.memory[addr:addr+4]])
lines.append(f" 0x{addr:04X}: {value:08X} {ascii_repr}")
return '\n'.join(lines)
def compile_c_to_asm(self, c_code: str) -> str:
"""Simple C to Assembly compiler (educational)"""
output = []
output.append("C → ASSEMBLY COMPILATION")
output.append("=" * 50)
output.append("")
# Very simplified C parser for educational purposes
# Handle simple function definitions
# Example: int add(int a, int b) { return a + b; }
func_pattern = r'(\w+)\s+(\w+)\s*\(([^)]*)\)\s*\{([^}]*)\}'
matches = re.findall(func_pattern, c_code, re.DOTALL)
if not matches:
output.append("❌ No functions found or unsupported C syntax")
return '\n'.join(output)
for return_type, func_name, params, body in matches:
output.append(f"FUNCTION: {func_name}")
output.append("")
# Parse parameters
param_list = [p.strip() for p in params.split(',') if p.strip()]
param_names = []
for p in param_list:
parts = p.split()
if len(parts) >= 2:
param_names.append(parts[-1])
# Stack frame explanation
output.append("STACK FRAME LAYOUT:")
output.append(" [BP+0] ← saved BP")
output.append(" [BP-4] ← return address")
offset = -8
var_offsets = {}
for param in param_names:
output.append(f" [BP{offset}] ← {param}")
var_offsets[param] = offset
offset -= 4
output.append("")
output.append("GENERATED ASSEMBLY:")
output.append("")
# Function prologue
asm = []
asm.append(f"{func_name}:")
asm.append(" PUSH BP")
asm.append(" MOV BP, SP")
# Parse body for return statement
return_match = re.search(r'return\s+([^;]+);', body)
if return_match:
expr = return_match.group(1).strip()
# Simple expression parsing
if '+' in expr:
parts = expr.split('+')
var1 = parts[0].strip()
var2 = parts[1].strip()
asm.append(f" ; Calculate {var1} + {var2}")
asm.append(f" MOV R0, [BP{var_offsets.get(var1, -8)}]")
asm.append(f" ADD R0, [BP{var_offsets.get(var2, -12)}]")
asm.append(" ; Result in R0")
elif '-' in expr:
parts = expr.split('-')
var1 = parts[0].strip()
var2 = parts[1].strip()
asm.append(f" ; Calculate {var1} - {var2}")
asm.append(f" MOV R0, [BP{var_offsets.get(var1, -8)}]")
asm.append(f" SUB R0, [BP{var_offsets.get(var2, -12)}]")
elif expr in var_offsets:
asm.append(f" ; Return {expr}")
asm.append(f" MOV R0, [BP{var_offsets[expr]}]")
else:
# Try to parse as number
try:
val = int(expr)
asm.append(f" ; Return constant {val}")
asm.append(f" MOV R0, {val}")
except:
asm.append(f" ; Return expression: {expr}")
asm.append(f" MOV R0, 0 ; SIMPLIFIED")
# Function epilogue
asm.append(" POP BP")
asm.append(" RET")
output.extend(asm)
output.append("")
output.append("=" * 50)
output.append("✓ Compilation complete. Copy assembly code to execute.")
return '\n'.join(output)
class DebuggerGUI:
def __init__(self, root):
self.root = root
self.root.title("🧠 Assembly Debugger & CPU Simulator")
self.root.geometry("1400x900")
self.debugger = AssemblyDebugger()
self.running = False
self.stepping = False
self.setup_ui()
self.show_startup_message()
def setup_ui(self):
# Main container with paned window
main_paned = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL)
main_paned.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# Left panel - Code editor
left_frame = ttk.Frame(main_paned)
main_paned.add(left_frame, weight=1)
# Code input
ttk.Label(left_frame, text="Assembly Code:", font=('Courier', 10, 'bold')).pack(anchor='w')
self.code_text = scrolledtext.ScrolledText(left_frame, width=50, height=25,
font=('Courier', 10))
self.code_text.pack(fill=tk.BOTH, expand=True, pady=5)
# Sample code
sample = """; Simple addition example
+36
View File
@@ -0,0 +1,36 @@
import csv
import random
import json
import sys
use_json = "-json" in sys.argv
try:
with open("oesterreich.csv", "r", newline="", encoding="latin-1") as f:
reader = csv.reader(f, delimiter=";")
rows = list(reader)[1:] # Header entfernen
topo = []
for row in rows:
if row[0]: # Gebirge
topo.append(row[0])
if row[2]: # Landschaften
topo.append(row[2])
topo = list(set(topo)) # Duplikate entfernen
result = []
for i in range(17):
result.append(random.sample(topo, 6))
if use_json:
with open("topo.json", "w", encoding="utf-8") as f:
json.dump(result, f, ensure_ascii=False, indent=2)
else:
with open("topo.txt", "w", encoding="utf-8") as f:
for row in result:
f.write(", ".join(row) + "\n")
except Exception as e:
print("Exception:", e)
+79
View File
@@ -0,0 +1,79 @@
Gebirge;Flüsse;Landschaften;Städte
Bregenzer Wald;Donau;Pinzgau;Bregenz
Rätikon;Inn;Pongau;Lustenau
Silvretta;Salzach;Lungau;Dorbbirn
Lechtaler Alpen;Enns;Tennengau;Feldkirch
Ötztaler Alpen;Traun;Flachgau;Bludenz
Stubaier Alpen;Große Mühl;;Schruns
Karwendel;Bregenzerach;;Telfs
Zillertaler Alpen; Ill;;Innsbruck
Kitzbüheler Aplen;Lech;;Imst
Hohe Tauern;Sill (Wipptal);;Reutte
Karnische Alpen;Große Ache;;Schwaz
Tennengebrige;Drau;;Wörgl
Dachstein;Mur;;Kufstein
Totes Gebirge;Mürz;;Kitzbühel
Sengsengebirge;Kamp;;Kaprun
Deferegger Gebirge;Leitha;;Lienz
Gurktaler Alpen;Lafnitz;;Zell am See
Saualpe;Raab;;Saalfelden
Packalpe;Gurk;;Radstadt
Koralpe;Lavant;;Tamsweg
Karawanken;;;Braunau
Fischbacher Alpen;;;Ried im Innkreis
Leithagebirge;;;Schärding
;;;Rohrbach
;;;Grieskirchen
;;;Völklabruck
;;;Wels
;;;Eferding
;;;Freistadt
;;;Gmunden
;;;Bad Ischl
;;;Enns
;;;Linz
;;;Zwettl
;;;Waidhofen an der Thaya
;;;Horn
;;;Krems
;;;Melk
;;;Hollabrunn
;;;St. Pölten
;;;Klosterneuburg
;;;Wien
;;;Gänserndorf
;;;Mistelbach
;;;Wiener Neustadt
;;;Liezen
;;;Bad Aussee
;;;Murau
;;;Judenburg
;;;Knittelfeld
;;;Leoben
;;;Bruck an der Mur
;;;Mürzzuschlag
;;;Kapfenberg
;;;Graz
;;;Hartberg
;;;Weiz
;;;Fürstenfeld
;;;Feldbach
;;;Radkersburg
;;;Leibnitz
;;;Deutschlandsberg
;;;Voitsberg
;;;Köflach
;;;Eisenstadt
;;;Oberpullendorf
;;;Bruck an der Leitha
;;;Neusiedl am See
;;;Oberwart
;;;Güssing
;;;Hermagor
;;;Villach
;;;Spital an der Drau
;;;Feldkirchen
;;;Klagenfurt
;;;Wolfsberg
;;;Völkermarkt
;;;St. Veit an der Glan
1 Gebirge Flüsse Landschaften Städte
2 Bregenzer Wald Donau Pinzgau Bregenz
3 Rätikon Inn Pongau Lustenau
4 Silvretta Salzach Lungau Dorbbirn
5 Lechtaler Alpen Enns Tennengau Feldkirch
6 Ötztaler Alpen Traun Flachgau Bludenz
7 Stubaier Alpen Große Mühl Schruns
8 Karwendel Bregenzerach Telfs
9 Zillertaler Alpen Ill Innsbruck
10 Kitzbüheler Aplen Lech Imst
11 Hohe Tauern Sill (Wipptal) Reutte
12 Karnische Alpen Große Ache Schwaz
13 Tennengebrige Drau Wörgl
14 Dachstein Mur Kufstein
15 Totes Gebirge Mürz Kitzbühel
16 Sengsengebirge Kamp Kaprun
17 Deferegger Gebirge Leitha Lienz
18 Gurktaler Alpen Lafnitz Zell am See
19 Saualpe Raab Saalfelden
20 Packalpe Gurk Radstadt
21 Koralpe Lavant Tamsweg
22 Karawanken Braunau
23 Fischbacher Alpen Ried im Innkreis
24 Leithagebirge Schärding
25 Rohrbach
26 Grieskirchen
27 Völklabruck
28 Wels
29 Eferding
30 Freistadt
31 Gmunden
32 Bad Ischl
33 Enns
34 Linz
35 Zwettl
36 Waidhofen an der Thaya
37 Horn
38 Krems
39 Melk
40 Hollabrunn
41 St. Pölten
42 Klosterneuburg
43 Wien
44 Gänserndorf
45 Mistelbach
46 Wiener Neustadt
47 Liezen
48 Bad Aussee
49 Murau
50 Judenburg
51 Knittelfeld
52 Leoben
53 Bruck an der Mur
54 Mürzzuschlag
55 Kapfenberg
56 Graz
57 Hartberg
58 Weiz
59 Fürstenfeld
60 Feldbach
61 Radkersburg
62 Leibnitz
63 Deutschlandsberg
64 Voitsberg
65 Köflach
66 Eisenstadt
67 Oberpullendorf
68 Bruck an der Leitha
69 Neusiedl am See
70 Oberwart
71 Güssing
72 Hermagor
73 Villach
74 Spital an der Drau
75 Feldkirchen
76 Klagenfurt
77 Wolfsberg
78 Völkermarkt
79 St. Veit an der Glan
+138
View File
@@ -0,0 +1,138 @@
[
[
"Tennengau",
"Bregenzer Wald",
"Rätikon",
"Hohe Tauern",
"Dachstein",
"Stubaier Alpen"
],
[
"Pinzgau",
"Gurktaler Alpen",
"Flachgau",
"Silvretta",
"Karwendel",
"Koralpe"
],
[
"Fischbacher Alpen",
"Dachstein",
"Gurktaler Alpen",
"Karwendel",
"Rätikon",
"Koralpe"
],
[
"Lungau",
"Tennengebrige",
"Koralpe",
"Sengsengebirge",
"Zillertaler Alpen",
"Bregenzer Wald"
],
[
"Kitzbüheler Aplen",
"Karawanken",
"Deferegger Gebirge",
"Leithagebirge",
"Silvretta",
"Bregenzer Wald"
],
[
"Packalpe",
"Stubaier Alpen",
"Lechtaler Alpen",
"Karnische Alpen",
"Silvretta",
"Hohe Tauern"
],
[
"Leithagebirge",
"Saualpe",
"Karnische Alpen",
"Dachstein",
"Fischbacher Alpen",
"Hohe Tauern"
],
[
"Tennengau",
"Karwendel",
"Ötztaler Alpen",
"Silvretta",
"Tennengebrige",
"Hohe Tauern"
],
[
"Tennengau",
"Packalpe",
"Hohe Tauern",
"Ötztaler Alpen",
"Zillertaler Alpen",
"Kitzbüheler Aplen"
],
[
"Lungau",
"Saualpe",
"Sengsengebirge",
"Koralpe",
"Leithagebirge",
"Ötztaler Alpen"
],
[
"Pinzgau",
"Lungau",
"Rätikon",
"Bregenzer Wald",
"Saualpe",
"Koralpe"
],
[
"Karwendel",
"Zillertaler Alpen",
"Stubaier Alpen",
"Karawanken",
"Koralpe",
"Pongau"
],
[
"Karawanken",
"Karnische Alpen",
"Kitzbüheler Aplen",
"Karwendel",
"Pinzgau",
"Silvretta"
],
[
"Stubaier Alpen",
"Kitzbüheler Aplen",
"Totes Gebirge",
"Lechtaler Alpen",
"Koralpe",
"Rätikon"
],
[
"Silvretta",
"Dachstein",
"Flachgau",
"Kitzbüheler Aplen",
"Koralpe",
"Tennengebrige"
],
[
"Zillertaler Alpen",
"Packalpe",
"Kitzbüheler Aplen",
"Tennengau",
"Leithagebirge",
"Stubaier Alpen"
],
[
"Totes Gebirge",
"Bregenzer Wald",
"Saualpe",
"Tennengau",
"Tennengebrige",
"Gurktaler Alpen"
]
]
+17
View File
@@ -0,0 +1,17 @@
Lungau, Saualpe, Zillertaler Alpen, Tennengau, Koralpe, Deferegger Gebirge
Deferegger Gebirge, Stubaier Alpen, Kitzbüheler Aplen, Lechtaler Alpen, Leithagebirge, Silvretta
Lechtaler Alpen, Rätikon, Flachgau, Tennengau, Saualpe, Zillertaler Alpen
Fischbacher Alpen, Tennengau, Ötztaler Alpen, Dachstein, Gurktaler Alpen, Deferegger Gebirge
Silvretta, Lungau, Packalpe, Saualpe, Karawanken, Ötztaler Alpen
Totes Gebirge, Silvretta, Packalpe, Koralpe, Leithagebirge, Saualpe
Packalpe, Dachstein, Sengsengebirge, Pongau, Leithagebirge, Tennengebrige
Silvretta, Fischbacher Alpen, Koralpe, Gurktaler Alpen, Karnische Alpen, Deferegger Gebirge
Deferegger Gebirge, Rätikon, Saualpe, Zillertaler Alpen, Karnische Alpen, Bregenzer Wald
Karwendel, Dachstein, Tennengau, Deferegger Gebirge, Pongau, Lungau
Dachstein, Lungau, Karnische Alpen, Pinzgau, Zillertaler Alpen, Stubaier Alpen
Karwendel, Saualpe, Flachgau, Lungau, Hohe Tauern, Tennengebrige
Karwendel, Fischbacher Alpen, Bregenzer Wald, Hohe Tauern, Karawanken, Koralpe
Leithagebirge, Sengsengebirge, Stubaier Alpen, Tennengau, Silvretta, Saualpe
Tennengau, Karawanken, Silvretta, Sengsengebirge, Tennengebrige, Lechtaler Alpen
Karnische Alpen, Karwendel, Zillertaler Alpen, Kitzbüheler Aplen, Silvretta, Sengsengebirge
Gurktaler Alpen, Stubaier Alpen, Tennengau, Saualpe, Packalpe, Tennengebrige
+212
View File
@@ -0,0 +1,212 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <immintrin.h>
#include <stdint.h>
#include <math.h>
#include <thread>
#include <vector>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#define WIDTH 1280
#define HEIGHT 800
#define MAX_ITER 1000
static uint32_t framebuffer[WIDTH * HEIGHT];
static double centerX = -0.5;
static double centerY = 0.0;
static double scale = 3.0 / WIDTH;
static int dragging = 0;
static int lastX, lastY;
static int numThreads = std::thread::hardware_concurrency();
static void render_tile(int yStart, int yEnd)
{
__m256d two = _mm256_set1_pd(2.0);
__m256d four = _mm256_set1_pd(4.0);
for (int y = yStart; y < yEnd; y++)
{
double ci_scalar = centerY + (y - HEIGHT / 2.0) * scale;
__m256d ci = _mm256_set1_pd(ci_scalar);
for (int x = 0; x < WIDTH; x += 4)
{
__m256d cr = _mm256_set_pd(
centerX + (x + 3 - WIDTH / 2.0) * scale,
centerX + (x + 2 - WIDTH / 2.0) * scale,
centerX + (x + 1 - WIDTH / 2.0) * scale,
centerX + (x + 0 - WIDTH / 2.0) * scale
);
__m256d zr = _mm256_setzero_pd();
__m256d zi = _mm256_setzero_pd();
int iter[4] = { 0,0,0,0 };
for (int i = 0; i < MAX_ITER; i++)
{
__m256d zr2 = _mm256_mul_pd(zr, zr);
__m256d zi2 = _mm256_mul_pd(zi, zi);
__m256d mag = _mm256_add_pd(zr2, zi2);
__m256d mask = _mm256_cmp_pd(mag, four, _CMP_LT_OS);
if (_mm256_movemask_pd(mask) == 0)
break;
__m256d zrzi = _mm256_mul_pd(zr, zi);
zi = _mm256_add_pd(_mm256_mul_pd(two, zrzi), ci);
zr = _mm256_add_pd(_mm256_sub_pd(zr2, zi2), cr);
for (int k = 0; k < 4; k++)
if (iter[k] < MAX_ITER)
iter[k]++;
}
for (int k = 0; k < 4; k++)
{
double smooth = iter[k];
if (iter[k] < MAX_ITER)
{
double zr_s = ((double*)&zr)[k];
double zi_s = ((double*)&zi)[k];
double mag = sqrt(zr_s * zr_s + zi_s * zi_s);
smooth = iter[k] + 1 - log2(log2(mag));
}
uint8_t c = (uint8_t)(255.0 * smooth / MAX_ITER);
framebuffer[y * WIDTH + x + k] =
(c << 16) | (c << 8) | c;
}
}
}
}
static void render_mandelbrot()
{
std::vector<std::thread> threads;
int tile = HEIGHT / numThreads;
for (int i = 0; i < numThreads; i++)
{
int yStart = i * tile;
int yEnd = (i == numThreads - 1) ? HEIGHT : yStart + tile;
threads.emplace_back(render_tile, yStart, yEnd);
}
for (auto& t : threads)
t.join();
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_MOUSEWHEEL:
{
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
scale *= (delta > 0) ? 0.8 : 1.25;
render_mandelbrot();
InvalidateRect(hwnd, NULL, FALSE);
break;
}
case WM_LBUTTONDOWN:
dragging = 1;
lastX = LOWORD(lParam);
lastY = HIWORD(lParam);
break;
case WM_MOUSEMOVE:
if (dragging)
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
centerX -= (x - lastX) * scale;
centerY -= (y - lastY) * scale;
lastX = x;
lastY = y;
render_mandelbrot();
InvalidateRect(hwnd, NULL, FALSE);
}
break;
case WM_LBUTTONUP:
dragging = 0;
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = WIDTH;
bmi.bmiHeader.biHeight = -HEIGHT;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
StretchDIBits(hdc,
0, 0, WIDTH, HEIGHT,
0, 0, WIDTH, HEIGHT,
framebuffer,
&bmi,
DIB_RGB_COLORS,
SRCCOPY);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
render_mandelbrot();
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = "MandelbrotSIMD";
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0,
"MandelbrotSIMD",
"Mandelbrot Explorer (SIMD + Threads)",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
WIDTH, HEIGHT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
+9
View File
@@ -9,5 +9,14 @@
<Property name="Executable" value="C:\Users\Sebastian\Desktop\INF6B\simulations\donut.c\donut.exe" />
<Property name="Arguments" value="" />
</Option>
<Option name="RestoreBreakpoints">
<Property name="Breakpoints" />
</Option>
<Option name="RestoreCommandHistory">
<Property name="History">
<Property value="p" />
<Property value="help" />
</Property>
</Option>
</TargetOptions>
</TargetConfig>
+41
View File
@@ -0,0 +1,41 @@
import numpy as np
import matplotlib.pyplot as plt
# Setting parameters (these values can be changed)
x_domain, y_domain = np.linspace(-2, 2, 500), np.linspace(-2, 2, 500)
bound = 2
max_iterations = 50 # any positive integer value
colormap = "nipy_spectral" # set to any matplotlib valid colormap
func = lambda z, p, c: z**p + c
# Computing 2D array to represent the Mandelbrot set
iteration_array = []
for y in y_domain:
row = []
for x in x_domain:
z = 0
p = 2
c = complex(x, y)
for iteration_number in range(max_iterations):
if abs(z) >= bound:
row.append(iteration_number)
break
else:
try:
z = func(z, p, c)
except (ValueError, ZeroDivisionError):
z = c
else:
row.append(0)
iteration_array.append(row)
# Plotting the data
ax = plt.axes()
ax.set_aspect("equal")
graph = ax.pcolormesh(x_domain, y_domain, iteration_array, cmap=colormap)
plt.colorbar(graph)
plt.xlabel("Real-Axis")
plt.ylabel("Imaginary-Axis")
plt.show()
+100
View File
@@ -0,0 +1,100 @@
import tkinter as tk
import turtle
import math
# ---------- Tk setup ----------
root = tk.Tk()
root.title("Turtle Function Inspector")
# ---------- Canvas ----------
canvas = tk.Canvas(root, width=600, height=600)
canvas.grid(row=0, column=0, rowspan=6)
screen = turtle.TurtleScreen(canvas)
screen.setworldcoordinates(-300, -300, 300, 300)
t = turtle.RawTurtle(screen)
t.speed(0)
t.hideturtle()
# ---------- Globals ----------
scale = 40 # zoom level
# ---------- Drawing ----------
def draw_axes():
t.clear()
t.color("black")
t.penup()
t.goto(-300, 0)
t.pendown()
t.goto(300, 0)
t.penup()
t.goto(0, -300)
t.pendown()
t.goto(0, 300)
def plot_function():
draw_axes()
expr = func_entry.get()
t.color("blue")
t.penup()
first = True
for px in range(-300, 300):
try:
x = px / scale
y = eval(expr, {"x": x, "math": math})
py = y * scale
if abs(py) > 300:
raise ValueError
if first:
t.goto(px, py)
t.pendown()
first = False
else:
t.goto(px, py)
except:
t.penup()
first = True
# ---------- Zoom ----------
def zoom_in():
global scale
scale *= 1.25
plot_function()
def zoom_out():
global scale
scale /= 1.25
plot_function()
# ---------- Mouse inspection ----------
info = tk.Label(root, text="x=0 y=0")
info.grid(row=5, column=1)
def inspect(event):
x = (event.x - 300) / scale
try:
y = eval(func_entry.get(), {"x": x, "math": math})
info.config(text=f"x={x:.3f} y={y:.3f}")
except:
info.config(text="undefined")
canvas.bind("<Motion>", inspect)
# ---------- Controls ----------
tk.Label(root, text="f(x) =").grid(row=0, column=1)
func_entry = tk.Entry(root, width=20)
func_entry.insert(0, "math.sin(x)")
func_entry.grid(row=1, column=1)
tk.Button(root, text="Plot", command=plot_function).grid(row=2, column=1)
tk.Button(root, text="Zoom +", command=zoom_in).grid(row=3, column=1)
tk.Button(root, text="Zoom -", command=zoom_out).grid(row=4, column=1)
plot_function()
root.mainloop()