taracpu 1.0.0__tar.gz

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 (49) hide show
  1. taracpu-1.0.0/PKG-INFO +105 -0
  2. taracpu-1.0.0/README.md +95 -0
  3. taracpu-1.0.0/pyproject.toml +29 -0
  4. taracpu-1.0.0/setup.cfg +4 -0
  5. taracpu-1.0.0/src/__init__.py +1 -0
  6. taracpu-1.0.0/src/assembler/__init__.py +1 -0
  7. taracpu-1.0.0/src/assembler/asm.py +241 -0
  8. taracpu-1.0.0/src/assets/delete.jpeg +0 -0
  9. taracpu-1.0.0/src/assets/logo/logo1.png +0 -0
  10. taracpu-1.0.0/src/assets/logo/logo2.png +0 -0
  11. taracpu-1.0.0/src/assets/logo/logo2_cropped.png +0 -0
  12. taracpu-1.0.0/src/assets/logo/logo2_text.png +0 -0
  13. taracpu-1.0.0/src/assets/rename.png +0 -0
  14. taracpu-1.0.0/src/examples/__init__.py +1 -0
  15. taracpu-1.0.0/src/examples/examples.py +17 -0
  16. taracpu-1.0.0/src/examples/progs/binary_search.tara +71 -0
  17. taracpu-1.0.0/src/examples/progs/display_bouncing_ball.tara +349 -0
  18. taracpu-1.0.0/src/examples/progs/display_rectangle.tara +70 -0
  19. taracpu-1.0.0/src/examples/progs/display_triangle.tara +80 -0
  20. taracpu-1.0.0/src/examples/progs/drawline.tara +380 -0
  21. taracpu-1.0.0/src/examples/progs/factorial_via_mul_n_6.tara +9 -0
  22. taracpu-1.0.0/src/examples/progs/fibonacci_n_10.tara +14 -0
  23. taracpu-1.0.0/src/examples/progs/gcd_a_48_b_18.tara +12 -0
  24. taracpu-1.0.0/src/examples/progs/generate_prime.tara +62 -0
  25. taracpu-1.0.0/src/examples/progs/image.tara +18 -0
  26. taracpu-1.0.0/src/examples/progs/matrix_multiplication.tara +224 -0
  27. taracpu-1.0.0/src/examples/progs/ping_pong.tara +206 -0
  28. taracpu-1.0.0/src/examples/progs/prime_test_n_17.tara +19 -0
  29. taracpu-1.0.0/src/examples/progs/sort_bubble.tara +49 -0
  30. taracpu-1.0.0/src/examples/progs/sort_insertion.tara +52 -0
  31. taracpu-1.0.0/src/examples/progs/testprog.tara +1 -0
  32. taracpu-1.0.0/src/paths.py +30 -0
  33. taracpu-1.0.0/src/run_sim.py +14 -0
  34. taracpu-1.0.0/src/simulation/__init__.py +1 -0
  35. taracpu-1.0.0/src/simulation/cpu.py +246 -0
  36. taracpu-1.0.0/src/ui/__init__.py +1 -0
  37. taracpu-1.0.0/src/ui/app.py +673 -0
  38. taracpu-1.0.0/src/ui/assets.py +49 -0
  39. taracpu-1.0.0/src/ui/isa_dialog.py +121 -0
  40. taracpu-1.0.0/src/ui/panels.py +2988 -0
  41. taracpu-1.0.0/src/ui/theme.py +322 -0
  42. taracpu-1.0.0/taracpu/__init__.py +3 -0
  43. taracpu-1.0.0/taracpu/__main__.py +3 -0
  44. taracpu-1.0.0/taracpu.egg-info/PKG-INFO +105 -0
  45. taracpu-1.0.0/taracpu.egg-info/SOURCES.txt +47 -0
  46. taracpu-1.0.0/taracpu.egg-info/dependency_links.txt +1 -0
  47. taracpu-1.0.0/taracpu.egg-info/entry_points.txt +2 -0
  48. taracpu-1.0.0/taracpu.egg-info/requires.txt +2 -0
  49. taracpu-1.0.0/taracpu.egg-info/top_level.txt +2 -0
taracpu-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: taracpu
3
+ Version: 1.0.0
4
+ Summary: TARA CPU Simulator — 16-bit RISC teaching architecture (CS2300 at IIT Madras)
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: PyQt5>=5.15
9
+ Requires-Dist: matplotlib>=3.5
10
+
11
+ # TARA CPU Simulator (CS2300 at IIT Madras)
12
+
13
+ A full-featured desktop simulator for the **TARA (Teaching Architecture for RISC Assembly)** ISA from CS2300 taught at IIT Madras, refer https://cse.iitm.ac.in/~ayon/courses/CS2300/CS2300.html
14
+
15
+ ## Features
16
+ - **Syntax-highlighted assembly editor** with line numbers and 6 built-in example programs
17
+ - **One-click assembler** with error reporting
18
+ - **Machine code listing** with hex + colored binary fields, synchronized to PC
19
+ - **Register file view** — 8 registers in a 4x2 visual bank, with change highlighting
20
+ - **Memory viewer** — browse all 2 KB of byte-addressable memory, with optional Matplotlib colormap heatmap
21
+ - **Display panel** — 64x64 memory-mapped raster with 1-bit packed pixels and directional input byte
22
+ - **Instruction decode panel** — shows format, fields, and human-readable effect
23
+ - **Execution log** — per-instruction trace with register changes
24
+ - **Step / Run / Stop / Reset** controls
25
+ - **Save Machine State / Boot State** controls for pausing and continuing later
26
+ - **Variable clock** — 1 Hz to max speed via presets or custom frequency, adjustable while running
27
+
28
+ ## How to Run
29
+
30
+ ```bash
31
+ pip install PyQt5 matplotlib
32
+ python3 run_sim.py
33
+ # or as a package:
34
+ python3 -m src.run_sim
35
+ ```
36
+
37
+ ## Classroom Font Settings
38
+
39
+ The editor, machine-code listing, memory heatmap matrix, and register file use larger classroom-friendly defaults. You can also edit `config/ui_settings.json` before starting the simulator:
40
+
41
+ ```json
42
+ {
43
+ "base_font_size": 14,
44
+ "editor_font_size": 15,
45
+ "listing_font_size": 12,
46
+ "memory_font_size": 12,
47
+ "register_font_size": 16
48
+ }
49
+ ```
50
+
51
+ The editor, listing, and memory matrix also have `A-` / `A+` controls in the UI; those changes are saved back to the config file.
52
+
53
+ ## Project Layout
54
+
55
+ ```text
56
+ src/
57
+ assembler/ TARA assembler
58
+ simulation/ CPU core and ISA behavior
59
+ ui/ PyQt application, panels, theme, dialogs
60
+ examples/ bundled example programs
61
+ assets/logo/ application logos
62
+ config/
63
+ memory/ memory CSV dumps
64
+ cpu_state/ machine-state JSON dumps
65
+ ```
66
+
67
+ ## Workflow
68
+
69
+ 1. Write or load assembly code in the **editor** (left panel)
70
+ 2. Click **⚙ Assemble & Load** — errors appear below the editor
71
+ 3. Use **⏭ Step** to execute one instruction at a time
72
+ 4. Or click **▶ Run** with a chosen clock frequency
73
+ 5. Watch registers, memory, listing highlight, and the decode panel update in real time
74
+ 6. Click **💾 Save Machine State** to write registers, PC, memory, counters, and source to JSON
75
+ 7. Later click **⤴ Boot State** to restore the JSON state and continue computation
76
+ 8. Click **↺ Reset** to reload the program and start over
77
+
78
+ ## TARA ISA Quick Reference
79
+
80
+ | Format | Instructions | Encoding |
81
+ |--------|-------------|---------|
82
+ | F0 | NOP, HLT, RET | `op[15:11] 00000000000` |
83
+ | F1 | ADD, SUB, MUL, AND, OR, XOR, SLT | `op rd rsA rsB 00` |
84
+ | F2 | MOV, NOT | `op rd rs 00000` |
85
+ | F3 | LIL, LIH, ADDI, SHL, SHR | `op rd imm8` |
86
+ | F4 | LDW, STW, LDB, STB | `op rdata rbase off5` |
87
+ | F5 | BZ, BN | `op rtest rel8` |
88
+ | F6 | JMP, CALL | `op rel11` |
89
+ | F7 | PUSH, POP | `op rstk 00000000` |
90
+
91
+ ## Memory Map
92
+ | Range | Use |
93
+ |-------|-----|
94
+ | 0x000–0x3FF | Program code |
95
+ | 0x400–0x4FF | Data / arrays |
96
+ | 0x500–0x5FE | Stack (R7) |
97
+ | 0x5FF | Display keyboard byte: bit0=left, bit1=right, bit2=up, bit3=down |
98
+ | 0x600–0x7FF | Display framebuffer, 64x64 pixels, 1 bit per pixel, 8 pixels per byte. Pixel values: 0 off, 1 on. |
99
+
100
+ ## Register Conventions
101
+ | Reg | Convention |
102
+ |-----|-----------|
103
+ | R0–R5 | General purpose |
104
+ | R6 | Link register (CALL/RET) |
105
+ | R7 | Stack pointer (PUSH/POP) |
@@ -0,0 +1,95 @@
1
+ # TARA CPU Simulator (CS2300 at IIT Madras)
2
+
3
+ A full-featured desktop simulator for the **TARA (Teaching Architecture for RISC Assembly)** ISA from CS2300 taught at IIT Madras, refer https://cse.iitm.ac.in/~ayon/courses/CS2300/CS2300.html
4
+
5
+ ## Features
6
+ - **Syntax-highlighted assembly editor** with line numbers and 6 built-in example programs
7
+ - **One-click assembler** with error reporting
8
+ - **Machine code listing** with hex + colored binary fields, synchronized to PC
9
+ - **Register file view** — 8 registers in a 4x2 visual bank, with change highlighting
10
+ - **Memory viewer** — browse all 2 KB of byte-addressable memory, with optional Matplotlib colormap heatmap
11
+ - **Display panel** — 64x64 memory-mapped raster with 1-bit packed pixels and directional input byte
12
+ - **Instruction decode panel** — shows format, fields, and human-readable effect
13
+ - **Execution log** — per-instruction trace with register changes
14
+ - **Step / Run / Stop / Reset** controls
15
+ - **Save Machine State / Boot State** controls for pausing and continuing later
16
+ - **Variable clock** — 1 Hz to max speed via presets or custom frequency, adjustable while running
17
+
18
+ ## How to Run
19
+
20
+ ```bash
21
+ pip install PyQt5 matplotlib
22
+ python3 run_sim.py
23
+ # or as a package:
24
+ python3 -m src.run_sim
25
+ ```
26
+
27
+ ## Classroom Font Settings
28
+
29
+ The editor, machine-code listing, memory heatmap matrix, and register file use larger classroom-friendly defaults. You can also edit `config/ui_settings.json` before starting the simulator:
30
+
31
+ ```json
32
+ {
33
+ "base_font_size": 14,
34
+ "editor_font_size": 15,
35
+ "listing_font_size": 12,
36
+ "memory_font_size": 12,
37
+ "register_font_size": 16
38
+ }
39
+ ```
40
+
41
+ The editor, listing, and memory matrix also have `A-` / `A+` controls in the UI; those changes are saved back to the config file.
42
+
43
+ ## Project Layout
44
+
45
+ ```text
46
+ src/
47
+ assembler/ TARA assembler
48
+ simulation/ CPU core and ISA behavior
49
+ ui/ PyQt application, panels, theme, dialogs
50
+ examples/ bundled example programs
51
+ assets/logo/ application logos
52
+ config/
53
+ memory/ memory CSV dumps
54
+ cpu_state/ machine-state JSON dumps
55
+ ```
56
+
57
+ ## Workflow
58
+
59
+ 1. Write or load assembly code in the **editor** (left panel)
60
+ 2. Click **⚙ Assemble & Load** — errors appear below the editor
61
+ 3. Use **⏭ Step** to execute one instruction at a time
62
+ 4. Or click **▶ Run** with a chosen clock frequency
63
+ 5. Watch registers, memory, listing highlight, and the decode panel update in real time
64
+ 6. Click **💾 Save Machine State** to write registers, PC, memory, counters, and source to JSON
65
+ 7. Later click **⤴ Boot State** to restore the JSON state and continue computation
66
+ 8. Click **↺ Reset** to reload the program and start over
67
+
68
+ ## TARA ISA Quick Reference
69
+
70
+ | Format | Instructions | Encoding |
71
+ |--------|-------------|---------|
72
+ | F0 | NOP, HLT, RET | `op[15:11] 00000000000` |
73
+ | F1 | ADD, SUB, MUL, AND, OR, XOR, SLT | `op rd rsA rsB 00` |
74
+ | F2 | MOV, NOT | `op rd rs 00000` |
75
+ | F3 | LIL, LIH, ADDI, SHL, SHR | `op rd imm8` |
76
+ | F4 | LDW, STW, LDB, STB | `op rdata rbase off5` |
77
+ | F5 | BZ, BN | `op rtest rel8` |
78
+ | F6 | JMP, CALL | `op rel11` |
79
+ | F7 | PUSH, POP | `op rstk 00000000` |
80
+
81
+ ## Memory Map
82
+ | Range | Use |
83
+ |-------|-----|
84
+ | 0x000–0x3FF | Program code |
85
+ | 0x400–0x4FF | Data / arrays |
86
+ | 0x500–0x5FE | Stack (R7) |
87
+ | 0x5FF | Display keyboard byte: bit0=left, bit1=right, bit2=up, bit3=down |
88
+ | 0x600–0x7FF | Display framebuffer, 64x64 pixels, 1 bit per pixel, 8 pixels per byte. Pixel values: 0 off, 1 on. |
89
+
90
+ ## Register Conventions
91
+ | Reg | Convention |
92
+ |-----|-----------|
93
+ | R0–R5 | General purpose |
94
+ | R6 | Link register (CALL/RET) |
95
+ | R7 | Stack pointer (PUSH/POP) |
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "taracpu"
7
+ version = "1.0.0"
8
+ description = "TARA CPU Simulator — 16-bit RISC teaching architecture (CS2300 at IIT Madras)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ dependencies = [
13
+ "PyQt5>=5.15",
14
+ "matplotlib>=3.5",
15
+ ]
16
+
17
+ [project.scripts]
18
+ taracpu = "taracpu:main"
19
+
20
+ [tool.setuptools.packages.find]
21
+ where = ["."]
22
+ include = ["src*", "taracpu*"]
23
+
24
+ [tool.setuptools.package-data]
25
+ "src" = [
26
+ "assets/*",
27
+ "assets/logo/*",
28
+ "examples/progs/*.tara",
29
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,241 @@
1
+ """
2
+ TARA Assembler
3
+ Converts TARA assembly text into 16-bit machine words.
4
+ Supports labels, comments (;), and all instruction formats.
5
+ """
6
+
7
+ import re
8
+ from src.simulation.cpu import OP, FMT, sext
9
+
10
+ class AssemblerError(Exception):
11
+ def __init__(self, msg, line=None):
12
+ self.msg = msg
13
+ self.line = line
14
+ super().__init__(msg)
15
+
16
+ def __str__(self):
17
+ return f"Line {self.line}: {self.msg}" if self.line else self.msg
18
+
19
+
20
+ def parse_reg(tok):
21
+ """Parse Rn or rn → integer 0-7."""
22
+ tok = tok.strip().upper()
23
+ if tok.startswith('R') and tok[1:].isdigit():
24
+ n = int(tok[1:])
25
+ if 0 <= n <= 7:
26
+ return n
27
+ raise AssemblerError(f"Invalid register '{tok}'")
28
+
29
+
30
+ def parse_int(tok, label_map=None, pc=None):
31
+ """Parse a literal integer or label reference."""
32
+ tok = tok.strip()
33
+ if tok.startswith('0x') or tok.startswith('0X'):
34
+ return int(tok, 16)
35
+ if tok.startswith('0b') or tok.startswith('0B'):
36
+ return int(tok, 2)
37
+ if tok.lstrip('-').isdigit():
38
+ return int(tok)
39
+ if label_map is not None and tok in label_map:
40
+ return label_map[tok]
41
+ raise AssemblerError(f"Cannot parse value '{tok}'")
42
+
43
+
44
+ def parse_mem(tok):
45
+ """Parse off(Rbase) → (offset_str, reg_str)."""
46
+ m = re.match(r'^(-?\d+|0x[0-9a-fA-F]+)\(([Rr]\d)\)$', tok.strip())
47
+ if not m:
48
+ raise AssemblerError(f"Invalid memory operand '{tok}'")
49
+ return m.group(1), m.group(2)
50
+
51
+
52
+ OPERAND_COUNTS = {
53
+ 'NOP': 0, 'HLT': 0, 'RET': 0,
54
+ 'ADD': 3, 'SUB': 3, 'MUL': 3, 'AND': 3, 'OR': 3, 'XOR': 3, 'SLT': 3,
55
+ 'MOV': 2, 'NOT': 2,
56
+ 'LIL': 2, 'LIH': 2, 'ADDI': 2, 'SHL': 2, 'SHR': 2,
57
+ 'LDW': 2, 'LDB': 2, 'STW': 2, 'STB': 2,
58
+ 'BZ': 2, 'BN': 2,
59
+ 'JMP': 1, 'CALL': 1,
60
+ 'PUSH': 1, 'POP': 1,
61
+ }
62
+
63
+
64
+ def _parse_operands(ops_str, mnem):
65
+ operands = [o.strip() for o in ops_str.split(',') if o.strip()]
66
+ expected = OPERAND_COUNTS[mnem]
67
+ if len(operands) != expected:
68
+ suffix = "" if expected == 1 else "s"
69
+ raise AssemblerError(
70
+ f"{mnem} expects {expected} operand{suffix}, got {len(operands)}"
71
+ )
72
+ return operands
73
+
74
+
75
+ def _label_rel(target_s, iaddr, label_map):
76
+ """Resolve a branch/jump target to a signed word-offset relative to iaddr+2."""
77
+ if target_s in label_map:
78
+ return (label_map[target_s] - (iaddr + 2)) // 2
79
+ return parse_int(target_s, label_map)
80
+
81
+
82
+ def _encode_f0(op):
83
+ return (op << 11)
84
+
85
+ def _encode_f1(op, rd, rA, rB):
86
+ return (op << 11) | (rd << 8) | (rA << 5) | (rB << 2)
87
+
88
+ def _encode_f2(op, rd, rs):
89
+ return (op << 11) | (rd << 8) | (rs << 5)
90
+
91
+ def _encode_f3(op, rd, imm8):
92
+ imm8 = imm8 & 0xFF
93
+ return (op << 11) | (rd << 8) | imm8
94
+
95
+ def _encode_f4(op, rdata, rbase, off5):
96
+ off5 = off5 & 0x1F
97
+ return (op << 11) | (rdata << 8) | (rbase << 5) | off5
98
+
99
+ def _encode_f5(op, rtest, rel8):
100
+ rel8 = rel8 & 0xFF
101
+ return (op << 11) | (rtest << 8) | rel8
102
+
103
+ def _encode_f6(op, rel11):
104
+ rel11 = rel11 & 0x7FF
105
+ return (op << 11) | rel11
106
+
107
+ def _encode_f7(op, rstk):
108
+ return (op << 11) | (rstk << 8)
109
+
110
+
111
+ def assemble(source):
112
+ """
113
+ Assemble source text → (words, listing, errors)
114
+ words : list of (byte_addr, 16-bit int)
115
+ listing: list of dict per assembled instruction
116
+ errors : list of AssemblerError
117
+ """
118
+ lines = source.splitlines()
119
+ errors = []
120
+ label_map = {} # label → byte address
121
+ parsed = [] # list of (lineno, addr, mnemonic, operands_str, original)
122
+
123
+ # ── Pass 1: strip comments, collect labels, count addresses ───────────────
124
+ addr = 0
125
+ for lineno, raw in enumerate(lines, 1):
126
+ line = raw.split(';')[0].strip()
127
+ if not line:
128
+ continue
129
+
130
+ # Extract label(s)
131
+ while ':' in line:
132
+ colon = line.index(':')
133
+ label = line[:colon].strip()
134
+ if label:
135
+ label_map[label] = addr
136
+ line = line[colon+1:].strip()
137
+
138
+ if not line:
139
+ continue
140
+
141
+ parts = line.split(None, 1)
142
+ mnem = parts[0].upper()
143
+ ops = parts[1].strip() if len(parts) > 1 else ''
144
+
145
+ if mnem not in OP:
146
+ errors.append(AssemblerError(f"Unknown mnemonic '{mnem}'", lineno))
147
+ continue
148
+
149
+ parsed.append((lineno, addr, mnem, ops, raw.rstrip()))
150
+ addr += 2
151
+
152
+ # ── Pass 2: encode instructions ───────────────────────────────────────────
153
+ words = []
154
+ listing = []
155
+
156
+ for (lineno, iaddr, mnem, ops_str, original) in parsed:
157
+ opcode = OP[mnem]
158
+ word = 0
159
+ err = None
160
+
161
+ try:
162
+ operands = _parse_operands(ops_str, mnem)
163
+ if mnem in ('NOP', 'HLT', 'RET'):
164
+ word = _encode_f0(opcode)
165
+
166
+ elif mnem in ('ADD', 'SUB', 'MUL', 'AND', 'OR', 'XOR', 'SLT'):
167
+ # rd, rA, rB
168
+ rd = parse_reg(operands[0])
169
+ rA = parse_reg(operands[1])
170
+ rB = parse_reg(operands[2])
171
+ word = _encode_f1(opcode, rd, rA, rB)
172
+
173
+ elif mnem in ('MOV', 'NOT'):
174
+ # rd, rs
175
+ rd = parse_reg(operands[0])
176
+ rs = parse_reg(operands[1])
177
+ word = _encode_f2(opcode, rd, rs)
178
+
179
+ elif mnem in ('LIL', 'LIH', 'ADDI'):
180
+ rd = parse_reg(operands[0])
181
+ imm = parse_int(operands[1], label_map)
182
+ word = _encode_f3(opcode, rd, imm)
183
+
184
+ elif mnem in ('SHL', 'SHR'):
185
+ # rd, shamt
186
+ rd = parse_reg(operands[0])
187
+ shamt = parse_int(operands[1], label_map)
188
+ word = _encode_f3(opcode, rd, shamt)
189
+
190
+ elif mnem in ('LDW', 'LDB'):
191
+ # rd, off(rbase)
192
+ rd = parse_reg(operands[0])
193
+ off_s, base_s = parse_mem(operands[1])
194
+ off = parse_int(off_s, label_map)
195
+ rbase = parse_reg(base_s)
196
+ word = _encode_f4(opcode, rd, rbase, off)
197
+
198
+ elif mnem in ('STW', 'STB'):
199
+ # rs, off(rbase)
200
+ rs = parse_reg(operands[0])
201
+ off_s, base_s = parse_mem(operands[1])
202
+ off = parse_int(off_s, label_map)
203
+ rbase = parse_reg(base_s)
204
+ word = _encode_f4(opcode, rs, rbase, off)
205
+
206
+ elif mnem in ('BZ', 'BN'):
207
+ rtest = parse_reg(operands[0])
208
+ rel = _label_rel(operands[1], iaddr, label_map)
209
+ word = _encode_f5(opcode, rtest, rel)
210
+
211
+ elif mnem in ('JMP', 'CALL'):
212
+ rel = _label_rel(operands[0], iaddr, label_map)
213
+ word = _encode_f6(opcode, rel)
214
+
215
+ elif mnem in ('PUSH', 'POP'):
216
+ rs = parse_reg(operands[0])
217
+ word = _encode_f7(opcode, rs)
218
+
219
+ else:
220
+ raise AssemblerError(f"Unhandled mnemonic '{mnem}'")
221
+
222
+ except (AssemblerError, ValueError, IndexError) as e:
223
+ if not isinstance(e, AssemblerError):
224
+ e = AssemblerError(str(e))
225
+ e.line = lineno
226
+ errors.append(e)
227
+ err = e
228
+ word = 0xDEAD
229
+
230
+ words.append((iaddr, word))
231
+ listing.append({
232
+ 'lineno': lineno,
233
+ 'addr': iaddr,
234
+ 'word': word,
235
+ 'mnem': mnem,
236
+ 'ops': ops_str,
237
+ 'original': original,
238
+ 'error': bool(err),
239
+ })
240
+
241
+ return words, listing, errors, label_map
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,17 @@
1
+ from pathlib import Path
2
+
3
+ from src.paths import PROGS_DIR
4
+
5
+
6
+ def _display_name(path):
7
+ return path.stem.replace('_', ' ').title()
8
+
9
+
10
+ def load_examples():
11
+ examples = {}
12
+ progs = Path(PROGS_DIR)
13
+ if not progs.exists():
14
+ return examples
15
+ for path in sorted(progs.glob('*.tara')):
16
+ examples[_display_name(path)] = path.read_text(encoding='utf-8', errors='replace')
17
+ return examples
@@ -0,0 +1,71 @@
1
+ ; Binary search for a sorted byte array.
2
+ ;
3
+ ; Interface at label "search":
4
+ ; R0 = starting byte address of sorted array
5
+ ; R1 = number of elements
6
+ ; R2 = search key
7
+ ;
8
+ ; Return value:
9
+ ; R3 = index of matching element, or 0xFFFF if not found
10
+ ;
11
+ ; The demo setup below searches for 7 in [1,3,5,7,9,11] at 0x0400.
12
+ ; After HLT, R3 contains 3.
13
+
14
+ ; ---- Demo setup -----------------------------------------------------
15
+ LIL R0, 0
16
+ LIH R0, 4 ; R0 = 0x0400
17
+ LIL R1, 6 ; N = 6 byte elements
18
+ LIL R2, 7 ; key = 7
19
+
20
+ LIL R3, 1
21
+ STB R3, 0(R0)
22
+ LIL R3, 3
23
+ STB R3, 1(R0)
24
+ LIL R3, 5
25
+ STB R3, 2(R0)
26
+ LIL R3, 7
27
+ STB R3, 3(R0)
28
+ LIL R3, 9
29
+ STB R3, 4(R0)
30
+ LIL R3, 11
31
+ STB R3, 5(R0)
32
+
33
+ ; ---- Binary search --------------------------------------------------
34
+ ; R3 = result index
35
+ ; R4 = low index
36
+ ; R5 = high index
37
+ ; R6 = mid index
38
+ ; R7 = scratch / loaded array value
39
+
40
+ search: LIL R3, 255
41
+ LIH R3, 255 ; default result = 0xFFFF (not found)
42
+ LIL R4, 0 ; low = 0
43
+ MOV R5, R1
44
+ ADDI R5, -1 ; high = N - 1
45
+
46
+ loop: SUB R7, R5, R4
47
+ BN R7, done ; high < low
48
+
49
+ MOV R6, R4
50
+ ADD R6, R6, R5
51
+ SHR R6, 1 ; mid = (low + high) / 2
52
+
53
+ ADD R7, R0, R6
54
+ LDB R7, 0(R7) ; R7 = A[mid]
55
+ SUB R7, R7, R2 ; compare A[mid] - key
56
+
57
+ BZ R7, found
58
+ BN R7, go_right ; A[mid] < key
59
+
60
+ MOV R5, R6 ; A[mid] > key, high = mid - 1
61
+ ADDI R5, -1
62
+ JMP loop
63
+
64
+ go_right:
65
+ MOV R4, R6 ; low = mid + 1
66
+ ADDI R4, 1
67
+ JMP loop
68
+
69
+ found: MOV R3, R6
70
+
71
+ done: HLT