RISC-V Dynamic Assembler
?
?
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus
Keyboard Navigation
Global Keys
[, < / ], > Jump to previous / next episodeW, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)
Menu toggling
q Quotes r References f Filter y Link c CreditsIn-Menu Movement
a
w
s
s
d
h
j
k
l
←
↑
↓
↓
→
Quotes and References Menus
Enter Jump to timecodeQuotes, References and Credits Menus
o Open URL (in new tab)Filter Menu
x, Space Toggle category and focus nextX, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus
Filter and Link Menus
z Toggle filter / linking modeCredits Menu
Enter Open URL (in new tab)⏫
Previous: 'RISC-V Toolchain Implementation (Extra)'
⏫
0:08Recap and set the stage for the day
🗩
0:08Recap and set the stage for the day
🗩
0:08Recap and set the stage for the day
🗩
1:38Review the new bits() function to replace the old ad hoc bit manipulation1
📖
1:38Review the new bits() function to replace the old ad hoc bit manipulation1
📖
1:38Review the new bits() function to replace the old ad hoc bit manipulation1
📖
7:56Review step() with a note that the encoding and decoding of instructions are performed separately
📖
7:56Review step() with a note that the encoding and decoding of instructions are performed separately
📖
7:56Review step() with a note that the encoding and decoding of instructions are performed separately
📖
9:35Review encode_instruction() with a few words on software vs hardware decoding2
📖
9:35Review encode_instruction() with a few words on software vs hardware decoding2
📖
9:35Review encode_instruction() with a few words on software vs hardware decoding2
📖
16:11A few words on the benefit of writing the encoder and decoder independently
🗩
16:11A few words on the benefit of writing the encoder and decoder independently
🗩
16:11A few words on the benefit of writing the encoder and decoder independently
🗩
16:59Review the test code for the encoder and decoder
📖
16:59Review the test code for the encoder and decoder
📖
16:59Review the test code for the encoder and decoder
📖
21:49Review the test code for the simulator
📖
21:49Review the test code for the simulator
📖
21:49Review the test code for the simulator
📖
22:42Run the simulator
🏃
22:42Run the simulator
🏃
22:42Run the simulator
🏃
23:24Setup to start writing the main assembler
🗩
23:24Setup to start writing the main assembler
🗩
23:24Setup to start writing the main assembler
🗩
24:59Q&A
🗩
24:59Q&A
🗩
24:59Q&A
🗩
26:26Static assembler
🗩
26:26Static assembler
🗩
26:26Static assembler
🗩
29:41Static assembler, continued
🗩
29:41Static assembler, continued
🗩
29:41Static assembler, continued
🗩
30:53Dynamic assembler
🗩
30:53Dynamic assembler
🗩
30:53Dynamic assembler
🗩
35:35Data labels3
🗩
35:35Data labels3
🗩
35:35Data labels3
🗩
40:38Instruction labels4
🗩
40:38Instruction labels4
🗩
40:38Instruction labels4
🗩
43:50Handling of instruction labels by static vs dynamic assemblers
🗩
43:50Handling of instruction labels by static vs dynamic assemblers
🗩
43:50Handling of instruction labels by static vs dynamic assemblers
🗩
47:58Multi-pass vs back-patching assembling
🗩
47:58Multi-pass vs back-patching assembling
🗩
47:58Multi-pass vs back-patching assembling
🗩
49:57Q&A
🗩
49:57Q&A
🗩
49:57Q&A
🗩
52:28Dive into writing our back-patching dynamic assembler, introducing Asm struct and def_byte(), def_half(), def_word(), def_bytes(), def_str() and check_overflow()
52:28Dive into writing our back-patching dynamic assembler, introducing Asm struct and def_byte(), def_half(), def_word(), def_bytes(), def_str() and check_overflow()
52:28Dive into writing our back-patching dynamic assembler, introducing Asm struct and def_byte(), def_half(), def_word(), def_bytes(), def_str() and check_overflow()
1:02:51Introduce Reg enum, using uint8 as the storage type
1:02:51Introduce Reg enum, using uint8 as the storage type
1:02:51Introduce Reg enum, using uint8 as the storage type
1:05:12Introduce emit_instr() and emission functions for add(), addi() and slli(), renaming the previous def_ functions to emit_*
1:05:12Introduce emit_instr() and emission functions for add(), addi() and slli(), renaming the previous def_ functions to emit_*
1:05:12Introduce emit_instr() and emission functions for add(), addi() and slli(), renaming the previous def_ functions to emit_*
1:10:44Introduce init_asm() and test our assembler
1:10:44Introduce init_asm() and test our assembler
1:10:44Introduce init_asm() and test our assembler
1:12:47Run it to see that it works
🏃
1:12:47Run it to see that it works
🏃
1:12:47Run it to see that it works
🏃
1:13:10Create instruction labels, introducing new_sym(), set_sym_here(), new_sym_here() and related structs
1:13:10Create instruction labels, introducing new_sym(), set_sym_here(), new_sym_here() and related structs
1:13:10Create instruction labels, introducing new_sym(), set_sym_here(), new_sym_here() and related structs
1:29:43Introduce emit_lw() to emit a load global instruction, and emit_auipc() and emit_lw_reg()5
1:29:43Introduce emit_lw() to emit a load global instruction, and emit_auipc() and emit_lw_reg()5
1:29:43Introduce emit_lw() to emit a load global instruction, and emit_auipc() and emit_lw_reg()5
1:36:11Test our label emission, also introducing get_sym_addr() for emit_lw() to call
1:36:11Test our label emission, also introducing get_sym_addr() for emit_lw() to call
1:36:11Test our label emission, also introducing get_sym_addr() for emit_lw() to call
1:39:34Step through new_sym() to see what it produces, and that we may not be sign-extending correctly
🏃
1:39:34Step through new_sym() to see what it produces, and that we may not be sign-extending correctly
🏃
1:39:34Step through new_sym() to see what it produces, and that we may not be sign-extending correctly
🏃
1:44:58Conditional sign-extension of immediates
🗩
1:44:58Conditional sign-extension of immediates
🗩
1:44:58Conditional sign-extension of immediates
🗩
1:49:02Introduce imm_hi() and imm_lo(), and make emit_lw() use imm_lo() in its call to emit_lw_reg()
1:49:02Introduce imm_hi() and imm_lo(), and make emit_lw() use imm_lo() in its call to emit_lw_reg()
1:49:02Introduce imm_hi() and imm_lo(), and make emit_lw() use imm_lo() in its call to emit_lw_reg()
1:51:25Run it to see that it works
🏃
1:51:25Run it to see that it works
🏃
1:51:25Run it to see that it works
🏃
1:52:23Q&A
🗩
1:52:23Q&A
🗩
1:52:23Q&A
🗩
1:52:52Change imm_hi() to straight up return imm + 0x800
1:52:52Change imm_hi() to straight up return imm + 0x800
1:52:52Change imm_hi() to straight up return imm + 0x800
1:53:20Run it to see that this works, and explain why
🏃
1:53:20Run it to see that this works, and explain why
🏃
1:53:20Run it to see that this works, and explain why
🏃
1:55:48Try doing a load of emit_uint32() to test this imm_hi()
1:55:48Try doing a load of emit_uint32() to test this imm_hi()
1:55:48Try doing a load of emit_uint32() to test this imm_hi()
1:56:12Run it to see that this doesn't work
🏃
1:56:12Run it to see that this doesn't work
🏃
1:56:12Run it to see that this doesn't work
🏃
1:56:28Revert imm_hi() to the old bit-shifting version
1:56:28Revert imm_hi() to the old bit-shifting version
1:56:28Revert imm_hi() to the old bit-shifting version
1:57:17Run it to see the same buggy result
🏃
1:57:17Run it to see the same buggy result
🏃
1:57:17Run it to see the same buggy result
🏃
1:57:58Try emitting fewer instructions, to try and determine where it breaks
🏃
🖮
1:57:58Try emitting fewer instructions, to try and determine where it breaks
🏃
🖮
1:57:58Try emitting fewer instructions, to try and determine where it breaks
🏃
🖮
2:00:08Scour the code for the culprit
2:00:08Scour the code for the culprit
2:00:08Scour the code for the culprit
2:01:11Make imm_hi() return imm + 0x800
2:01:11Make imm_hi() return imm + 0x800
2:01:11Make imm_hi() return imm + 0x800
2:02:09Step in to emit_lw() and spot that the addr was at the max capacity of our RAM
2:02:09Step in to emit_lw() and spot that the addr was at the max capacity of our RAM
2:02:09Step in to emit_lw() and spot that the addr was at the max capacity of our RAM
2:02:50Add more RAM
2:02:50Add more RAM
2:02:50Add more RAM
2:03:18Run it to see that this totally works
🏃
2:03:18Run it to see that this totally works
🏃
2:03:18Run it to see that this totally works
🏃
2:04:10Make check_overflow() assert on a bounds-checking failure
2:04:10Make check_overflow() assert on a bounds-checking failure
2:04:10Make check_overflow() assert on a bounds-checking failure
2:04:18Run it with a smaller amount of RAM, and hit that assertion
🏃
2:04:18Run it with a smaller amount of RAM, and hit that assertion
🏃
2:04:18Run it with a smaller amount of RAM, and hit that assertion
🏃
2:04:39Cut over to the extra stream
🗩
2:04:39Cut over to the extra stream
🗩
2:04:39Cut over to the extra stream
🗩
⏬
Next: 'RISC-V Dynamic Assembler (Extra)'
⏬