codecin 5.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. codecin/__init__.py +27 -0
  2. codecin/aot.py +229 -0
  3. codecin/assembler.py +548 -0
  4. codecin/cache.py +71 -0
  5. codecin/cin.py +2558 -0
  6. codecin/cli.py +282 -0
  7. codecin/config.py +58 -0
  8. codecin/console.py +183 -0
  9. codecin/cpu.py +1654 -0
  10. codecin/crom.py +222 -0
  11. codecin/debugger.py +659 -0
  12. codecin/disasm.py +86 -0
  13. codecin/errors.py +58 -0
  14. codecin/isa.py +457 -0
  15. codecin/jit.py +270 -0
  16. codecin/libcodecin_native.so +0 -0
  17. codecin/logger.py +145 -0
  18. codecin/memory.py +348 -0
  19. codecin/native/aot/aot.go +70 -0
  20. codecin/native/aot/build.go +219 -0
  21. codecin/native/aot/stub_main.go.txt +22 -0
  22. codecin/native/build.ps1 +33 -0
  23. codecin/native/build.sh +48 -0
  24. codecin/native/cmd/codecin/main.go +287 -0
  25. codecin/native/compiler/codegen.go +1938 -0
  26. codecin/native/compiler/compile_test.go +164 -0
  27. codecin/native/compiler/parser.go +1071 -0
  28. codecin/native/compiler/syscalls.go +86 -0
  29. codecin/native/compiler/tokenizer.go +336 -0
  30. codecin/native/compiler/types.go +213 -0
  31. codecin/native/engine/audio.go +152 -0
  32. codecin/native/engine/audio_other.go +46 -0
  33. codecin/native/engine/audio_windows.go +43 -0
  34. codecin/native/engine/canvas.go +271 -0
  35. codecin/native/engine/crom.go +86 -0
  36. codecin/native/engine/encode.go +93 -0
  37. codecin/native/engine/engine_test.go +198 -0
  38. codecin/native/engine/isa_gen.go +445 -0
  39. codecin/native/engine/system.go +190 -0
  40. codecin/native/engine/termux.go +113 -0
  41. codecin/native/engine/version_gen.go +7 -0
  42. codecin/native/engine/vm.go +1157 -0
  43. codecin/native/go.mod +3 -0
  44. codecin/native/ir/ir.go +48 -0
  45. codecin/native/main.go +225 -0
  46. codecin/native.py +336 -0
  47. codecin/registers.py +130 -0
  48. codecin/stats.py +235 -0
  49. codecin-5.4.2.dist-info/METADATA +985 -0
  50. codecin-5.4.2.dist-info/RECORD +54 -0
  51. codecin-5.4.2.dist-info/WHEEL +5 -0
  52. codecin-5.4.2.dist-info/entry_points.txt +2 -0
  53. codecin-5.4.2.dist-info/licenses/LICENSE +7 -0
  54. codecin-5.4.2.dist-info/top_level.txt +1 -0
codecin/crom.py ADDED
@@ -0,0 +1,222 @@
1
+ """CROM 内存镜像 (v3: zlib 压缩 + CRC32 校验) 与 CPUSA 二进制程序格式。
2
+
3
+ 优先调用 Go 原生库 (codecin.native) 进行压缩/解压, 无原生库时回退到 zlib。
4
+ """
5
+
6
+ import struct
7
+ import zlib
8
+ from typing import TYPE_CHECKING, Optional
9
+
10
+ from .errors import CPUSimulatorError
11
+ from .isa import Constants
12
+
13
+ if TYPE_CHECKING:
14
+ from .cpu import CPU
15
+ from .logger import Logger
16
+ from .memory import FastMemory
17
+
18
+ CROM_HEADER_SIZE = 16
19
+ # flags bit0: zlib 压缩; bit1: 尾部携带 MMU 页表元数据 (此时校验和覆盖 payload+尾部)
20
+ CROM_FLAG_COMPRESS = 0x01
21
+ CROM_FLAG_MMU = 0x02
22
+ # 解压/载荷允许超出头部 mem_size 的最大余量 (MMU 页表尾部元数据用)
23
+ CROM_MAX_TRAILER = 4 << 20
24
+
25
+
26
+ def _mmu_trailer(mmu) -> bytes:
27
+ """序列化 MMU 状态: identity(1B) | entries | blacklist (小端)。"""
28
+ parts = [struct.pack('<B', 1 if mmu._identity else 0)]
29
+ entries = sorted(mmu.pages.items())
30
+ parts.append(struct.pack('<I', len(entries)))
31
+ for vpn, (ppn, perms) in entries:
32
+ parts.append(struct.pack('<II3s', vpn, ppn,
33
+ perms.encode('ascii')[:3].ljust(3, b'\x00')))
34
+ black = sorted(mmu._blacklist)
35
+ parts.append(struct.pack('<I', len(black)))
36
+ for vpn in black:
37
+ parts.append(struct.pack('<I', vpn))
38
+ return b''.join(parts)
39
+
40
+
41
+ def _restore_mmu_trailer(mmu, data: bytes) -> None:
42
+ pos = 0
43
+ identity = data[pos]
44
+ pos += 1
45
+ mmu._identity = bool(identity)
46
+ n = struct.unpack_from('<I', data, pos)[0]
47
+ pos += 4
48
+ for _ in range(n):
49
+ vpn, ppn = struct.unpack_from('<II', data, pos)
50
+ perms = data[pos + 8:pos + 11].split(b'\x00', 1)[0].decode('ascii')
51
+ pos += 11
52
+ mmu.map(vpn, ppn, perms or 'rwx')
53
+ nb = struct.unpack_from('<I', data, pos)[0]
54
+ pos += 4
55
+ for _ in range(nb):
56
+ vpn = struct.unpack_from('<I', data, pos)[0]
57
+ pos += 4
58
+ mmu.unmap(vpn << 12)
59
+
60
+
61
+ def save_crom(memory: 'FastMemory', path: str, compress: bool = True,
62
+ logger: Optional['Logger'] = None) -> None:
63
+ mem_data = bytes(memory.get_snapshot())
64
+ trailer = _mmu_trailer(memory.mmu) if memory.mmu is not None else b''
65
+ has_mmu = bool(trailer)
66
+ mmu_flag = CROM_FLAG_MMU if has_mmu else 0x00
67
+
68
+ packed = None
69
+ if not has_mmu:
70
+ # MMU 尾部元数据由 Python 端排版; 含 MMU 时跳过 Go 打包保证格式一致
71
+ try:
72
+ from . import native
73
+ engine = native.get_engine(logger)
74
+ if engine is not None:
75
+ packed = engine.crom_pack(mem_data + trailer, compress)
76
+ except Exception:
77
+ packed = None
78
+
79
+ if packed is None:
80
+ flags = (CROM_FLAG_COMPRESS if compress else 0x00) | mmu_flag
81
+ payload = mem_data + trailer
82
+ body = zlib.compress(payload, level=6) if compress else payload
83
+ checksum = zlib.crc32(body) & 0xFFFFFFFF
84
+ header = (Constants.CROM_MAGIC
85
+ + struct.pack('<B', Constants.CROM_VERSION)
86
+ + struct.pack('<I', len(mem_data))
87
+ + struct.pack('<B', flags)
88
+ + struct.pack('<I', checksum)
89
+ + b'\x00\x00')
90
+ packed = header + body
91
+
92
+ with open(path, 'wb') as f:
93
+ f.write(packed)
94
+ if logger:
95
+ logger.info(f".crom saved to {path} ({len(packed)} bytes, "
96
+ f"compressed={compress}, mmu={has_mmu})")
97
+
98
+
99
+ def load_crom(memory: 'FastMemory', path: str,
100
+ logger: Optional['Logger'] = None,
101
+ enable_mmu: bool = False) -> None:
102
+ with open(path, 'rb') as f:
103
+ data = f.read()
104
+
105
+ if len(data) < 8:
106
+ raise CPUSimulatorError(f".crom file too short: {len(data)} bytes")
107
+
108
+ if data[:4] != Constants.CROM_MAGIC:
109
+ # 旧版裸格式: 前 4 字节为 mem_size。
110
+ # 要求声明长度与文件实际内容一致, 否则任意文件 (例如 "NOTACROMFILE")
111
+ # 都会被静默当成内存镜像载入。
112
+ mem_size = struct.unpack('<I', data[:4])[0]
113
+ if mem_size > len(data) - 4:
114
+ raise CPUSimulatorError(
115
+ f"Not a .crom file: 声明的 mem_size={mem_size} "
116
+ f"超过文件实际内容 ({len(data) - 4} bytes)")
117
+ memory.load_bytes(0, data[4:4 + mem_size])
118
+ if logger:
119
+ logger.info(f"Loaded legacy .crom: {min(mem_size, len(data) - 4)} bytes")
120
+ return
121
+
122
+ version = data[4]
123
+ if version != Constants.CROM_VERSION:
124
+ raise CPUSimulatorError(f"Unsupported .crom version: {version}")
125
+ if len(data) < CROM_HEADER_SIZE:
126
+ raise CPUSimulatorError(".crom header incomplete")
127
+
128
+ mem_size = struct.unpack('<I', data[5:9])[0]
129
+ flags = data[9]
130
+ compressed = bool(flags & CROM_FLAG_COMPRESS)
131
+ has_mmu = bool(flags & CROM_FLAG_MMU)
132
+ checksum = struct.unpack('<I', data[10:14])[0]
133
+ body = data[CROM_HEADER_SIZE:]
134
+
135
+ if zlib.crc32(body) & 0xFFFFFFFF != checksum:
136
+ raise CPUSimulatorError(".crom checksum mismatch (file corrupted?)")
137
+
138
+ if compressed:
139
+ # 解压上限 = 头部 mem_size + MMU trailer 余量: 防止 zip bomb
140
+ # (旧实现 zlib.decompress 无上限, 65KB 文件可解出数百 MB)。
141
+ limit = mem_size + CROM_MAX_TRAILER
142
+ try:
143
+ d = zlib.decompressobj()
144
+ raw = d.decompress(body, limit)
145
+ if d.unconsumed_tail:
146
+ raise CPUSimulatorError(
147
+ f".crom 解压超过头部声明的大小 ({limit} bytes): 疑似损坏或恶意文件")
148
+ raw += d.flush()
149
+ except zlib.error as e:
150
+ raise CPUSimulatorError(
151
+ f"Failed to decompress .crom: {e}") from e
152
+ if len(raw) > limit:
153
+ raise CPUSimulatorError(
154
+ f".crom 解压超过头部声明的大小 ({limit} bytes)")
155
+ else:
156
+ raw = body
157
+ if len(raw) > mem_size + CROM_MAX_TRAILER:
158
+ raise CPUSimulatorError(
159
+ f".crom 载荷超过头部声明的大小 ({mem_size} bytes)")
160
+
161
+ memory.load_bytes(0, raw[:min(mem_size, len(raw))])
162
+ if has_mmu and enable_mmu:
163
+ from .memory import Mmu
164
+ mmu = Mmu(max(mem_size, len(memory)))
165
+ _restore_mmu_trailer(mmu, raw[mem_size:])
166
+ memory.attach_mmu(mmu)
167
+ elif has_mmu:
168
+ # 文件带 MMU 元数据但调用方未启用: 忽略之, 仍加载物理内容
169
+ if logger:
170
+ logger.info(".crom 含 MMU 页表但未启用 (enable_mmu=False), 跳过")
171
+ if logger:
172
+ logger.info(f"Loaded .crom v3: {min(mem_size, len(raw))} bytes, "
173
+ f"compressed={compressed}, mmu={has_mmu and enable_mmu}")
174
+
175
+
176
+ # ==================== CPUSA 二进制程序 ====================
177
+
178
+ def save_bin(cpu: 'CPU', path: str, logger: Optional['Logger'] = None) -> None:
179
+ from .native import encode_program
180
+ all_labels = dict(cpu.labels)
181
+ all_labels.update(cpu.data_labels)
182
+ bytecode = encode_program(cpu.instructions, cpu.entry_pc, all_labels)
183
+ mem_image = bytes(cpu.memory.get_snapshot())
184
+
185
+ with open(path, 'wb') as f:
186
+ f.write(Constants.MAGIC_NUMBER) # 5B
187
+ f.write(struct.pack('<B', Constants.BIN_VERSION)) # 1B
188
+ f.write(struct.pack('<I', len(mem_image))) # 4B
189
+ f.write(struct.pack('<I', cpu.entry_pc)) # 4B
190
+ f.write(struct.pack('<Q', cpu.sp)) # 8B
191
+ f.write(struct.pack('<I', len(bytecode))) # 4B
192
+ f.write(b'\x00' * 8) # 保留
193
+ f.write(mem_image)
194
+ f.write(bytecode)
195
+ if logger:
196
+ logger.info(f"Binary saved to {path} ({len(bytecode)} bytecode bytes)")
197
+
198
+
199
+ def load_bin(cpu: 'CPU', path: str) -> None:
200
+ from .native import decode_program
201
+ with open(path, 'rb') as f:
202
+ magic = f.read(5)
203
+ if magic != Constants.MAGIC_NUMBER:
204
+ raise CPUSimulatorError("Invalid binary file (bad magic)")
205
+ version = struct.unpack('<B', f.read(1))[0]
206
+ if version != Constants.BIN_VERSION:
207
+ raise CPUSimulatorError(f"Unsupported binary version: {version}")
208
+ mem_size = struct.unpack('<I', f.read(4))[0]
209
+ entry = struct.unpack('<I', f.read(4))[0]
210
+ sp = struct.unpack('<Q', f.read(8))[0]
211
+ bc_len = struct.unpack('<I', f.read(4))[0]
212
+ f.read(8)
213
+ mem_image = f.read(mem_size)
214
+ bytecode = f.read(bc_len)
215
+
216
+ if len(mem_image) > len(cpu.memory):
217
+ cpu.memory.resize(len(mem_image))
218
+ cpu.config.mem_size = len(mem_image)
219
+ cpu.memory.load_bytes(0, mem_image)
220
+ cpu.instructions, cpu.entry_pc = decode_program(bytecode)
221
+ cpu.pc = entry
222
+ cpu.sp = sp