Skip to content

Commit 39cc78c

Browse files
committed
Rearrange LABELS to remove 2 instructions from the decode hot path
1 parent 4e61987 commit 39cc78c

File tree

5 files changed

+97
-49
lines changed

5 files changed

+97
-49
lines changed

python/src/mlogv32/preprocessor/app.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def _render_template(
263263
check_unsaved_variables(worker_ast)
264264
print(
265265
f"""\
266-
Code size:
266+
Worker:
267267
Instructions: {len(list(n for n in worker_ast if isinstance(n, Statement)))} / 1000
268268
Bytes: {len(worker_code.encode())} / {1024 * 100}"""
269269
)
@@ -287,6 +287,14 @@ def _render_template(
287287
**config.inputs,
288288
)
289289

290+
controller_ast = parse_mlog(controller_code)
291+
print(
292+
f"""\
293+
Controller:
294+
Instructions: {len(list(n for n in controller_ast if isinstance(n, Statement)))} / 1000
295+
Bytes: {len(controller_code.encode())} / {1024 * 100}"""
296+
)
297+
290298
# preprocess other code snippets
291299

292300
debugger_code, _, _ = _render_template(config.templates.debugger)

python/src/mlogv32/preprocessor/models.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import math
34
from contextlib import contextmanager
45
from contextvars import ContextVar
56
from pathlib import Path
@@ -52,6 +53,8 @@ class Instruction(BaseModel):
5253
label: str
5354
count: int = Field(default=1, ge=1)
5455
up_to: int | None = None
56+
align: int = Field(default=1, ge=1)
57+
address: int | None = None
5558

5659
class CSR(BaseModel):
5760
read: CSRLocation
@@ -65,9 +68,18 @@ def _resolve_instructions(cls, instructions: list[Instruction]):
6568
address = 0
6669

6770
for i, value in enumerate(instructions):
71+
value = value.model_copy()
72+
if value.address is None:
73+
value.address = math.ceil(address / value.align) * value.align
74+
elif value.address < address:
75+
raise ValueError(
76+
f"Instruction {i} is at address {value.address}, but the previous instruction was at address {address}"
77+
)
78+
address = value.address
79+
6880
if value.up_to is not None:
69-
value = value.model_copy()
7081
assert value.up_to is not None
82+
assert value.align == 1, "Align != 1 is not supported with up_to"
7183

7284
if value.up_to < address:
7385
raise ValueError(
@@ -77,7 +89,7 @@ def _resolve_instructions(cls, instructions: list[Instruction]):
7789
value.count = value.up_to - address + 1
7890

7991
result.append(value)
80-
address += value.count
92+
address += value.count * value.align
8193

8294
return result
8395

src/cpu/controller.mlog.jinja

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,22 @@ init_incr__not_null:
113113

114114
# initialize label lookup table
115115

116-
#% set ns = namespace(i=0, loop=0)
116+
#% set ns = namespace(loop=0)
117117
#% for instruction in instructions
118+
#% set ns.i = instruction.address
118119
# {{ instruction.label }}
119120
#%#- unroll the loop if it's equal or better in terms of code size, else generate a loop
120121
#% if instruction.count <= 4
121122
#% for _ in range(instruction.count)
122123
write {{labels[instruction.label]}} {{LABELS}} {{ns.i}}
123-
#% set ns.i = ns.i + 1
124+
#% set ns.i = ns.i + instruction.align
124125
#% endfor
125126
#% else
126127
set i {{ns.i}}
127-
#% set ns.i = ns.i + instruction.count
128+
#% set ns.i = ns.i + instruction.count * instruction.align
128129
init_labels__loop{{ns.loop}}:
129130
write {{labels[instruction.label]}} {{LABELS}} i
130-
op add i i 1
131+
op add i i {{instruction.align}}
131132
jump init_labels__loop{{ns.loop}} lessThan i {{ns.i}}
132133
#% set ns.loop = ns.loop + 1
133134
#% endif
@@ -389,6 +390,7 @@ set {{SINGLE_STEP_SWITCH}} null
389390
set {{POWER_SWITCH}} null
390391
set {{PAUSE_SWITCH}} null
391392
set {{labels[instruction.label]}} null
393+
set {{instruction.align}} null
392394
set {{loop.index0}} null
393395
set {{ns.i}} null
394396
set {{value}} null

src/cpu/cpu.yaml

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,68 @@ inputs:
3434
UART_TX_WRITE: 511
3535

3636
instructions:
37+
# decoders
38+
- label: decode_LOAD
39+
align: 4
40+
- label: decode_illegal_instruction # LOAD-FP
41+
align: 4
42+
- label: decode_custom-0
43+
align: 4
44+
- label: decode_MISC-MEM
45+
align: 4
46+
- label: decode_OP-IMM
47+
align: 4
48+
- label: decode_AUIPC
49+
align: 4
50+
- label: decode_illegal_instruction # OP-IMM-32
51+
align: 4
52+
- label: decode_illegal_instruction # 48b
53+
align: 4
54+
- label: decode_STORE
55+
align: 4
56+
- label: decode_illegal_instruction # STORE-FP
57+
align: 4
58+
- label: decode_illegal_instruction # custom-1
59+
align: 4
60+
- label: decode_AMO
61+
align: 4
62+
- label: decode_OP
63+
align: 4
64+
- label: decode_LUI
65+
align: 4
66+
- label: decode_illegal_instruction
67+
align: 4
68+
count: 10
69+
# OP-32
70+
# 64b
71+
# MADD
72+
# MSUB
73+
# NMSUB
74+
# NMADD
75+
# OP-FP
76+
# OP-V
77+
# custom-2/rv128
78+
# 48b
79+
- label: decode_BRANCH
80+
align: 4
81+
- label: decode_JALR
82+
align: 4
83+
- label: decode_illegal_instruction # reserved
84+
align: 4
85+
- label: decode_JAL
86+
align: 4
87+
- label: decode_SYSTEM
88+
align: 4
89+
- label: decode_illegal_instruction
90+
align: 4
91+
count: 3
92+
# OP-VE
93+
# custom-3/rv128
94+
# >=80b
95+
3796
# runtime handlers
3897
- label: BEQ
98+
address: 128
3999
- label: BNE
40100
- label: JAL
41101
- label: JALR
@@ -101,43 +161,8 @@ instructions:
101161
- label: SRAI
102162
- label: ILLEGAL_OP
103163
- label: MLOGSYS
104-
# padding
105164
- label: ILLEGAL_OP
106-
up_to: 127
107-
# decoders, starting at index 128
108-
- label: decode_LOAD
109-
- label: decode_illegal_instruction # LOAD-FP
110-
- label: decode_custom-0
111-
- label: decode_MISC-MEM
112-
- label: decode_OP-IMM
113-
- label: decode_AUIPC
114-
- label: decode_illegal_instruction # OP-IMM-32
115-
- label: decode_illegal_instruction # 48b
116-
- label: decode_STORE
117-
- label: decode_illegal_instruction # STORE-FP
118-
- label: decode_illegal_instruction # custom-1
119-
- label: decode_AMO
120-
- label: decode_OP
121-
- label: decode_LUI
122-
- label: decode_illegal_instruction # OP-32
123-
count: 10
124-
# 64b
125-
# MADD
126-
# MSUB
127-
# NMSUB
128-
# NMADD
129-
# OP-FP
130-
# OP-V
131-
# custom-2/rv128
132-
# 48b
133-
- label: decode_BRANCH
134-
- label: decode_JALR
135-
- label: decode_illegal_instruction # reserved
136-
- label: decode_JAL
137-
- label: decode_SYSTEM
138-
- label: decode_illegal_instruction # OP-VE
139-
- label: decode_illegal_instruction # custom-3/rv128
140-
- label: decode_illegal_instruction # >=80b
165+
up_to: 255
141166

142167
csrs:
143168
# -- unprivileged --

src/cpu/worker.mlog.jinja

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,10 @@ main__no_breakpoint:
323323

324324
#% do reset_locals()
325325
# jump to instruction handler
326-
op add $index op_id 64 # op_id is in the range [-64, 63]
326+
# op_id is in the range [-64, 63]
327+
# and the instruction handlers in {{LABELS}} start at index 128
328+
# so we need to add 64 + 128 = 192
329+
op add $index op_id 192
327330
read @counter {{LABELS}} $index
328331

329332
# this is a normal length for a label
@@ -1100,11 +1103,9 @@ decode:
11001103
op shr $$funct3 value 12
11011104
op and $$funct3 $$funct3 0b111
11021105

1103-
# jump table based on (opcode >> 2) since the low 2 bits don't matter
1104-
# the jump table is stored in LABELS by the controller, starting at index 128
1105-
op and $tmp value 0b1111111
1106-
op shr $tmp $tmp 2
1107-
op add $tmp $tmp 128
1106+
# jump table based on opcode[6:2] since the low 2 bits have already been checked
1107+
# the jump table is stored in LABELS by the controller, starting at index 0 at multiples of 4
1108+
op and $tmp value 0b1111100
11081109
read @counter {{LABELS}} $tmp
11091110

11101111
decode_LUI:

0 commit comments

Comments
 (0)