Skip to content

Commit bbb36e3

Browse files
committed
DO THE THUMB PARTS
1 parent c97685b commit bbb36e3

File tree

8 files changed

+720
-51
lines changed

8 files changed

+720
-51
lines changed

cores/gba/include/gba/cpu/util.svh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
$display("shift_type : %s", ctrl.shift_type.name()); \
5151
$display("shift_use_rxx : %0b", ctrl.shift_use_rxx); \
5252
$display("shift_amount : %0d", ctrl.shift_amount); \
53-
$display("pipeline_flush : %0b", ctrl.pipeline_flush); \
5453
$display("pipeline_advance : %0b", ctrl.pipeline_advance); \
5554
$display("----------------------"); \
5655
$fflush();

cores/gba/rtl/cpu/CPU.sv

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@ module ARM7TMDI (
263263
instr_boundary <= control_signals.pipeline_advance;
264264
end
265265

266+
267+
wire pc_modified = (control_signals.ALU_writeback == ALU_WB_REG_RD && decoder_bus.decoded_regs.Rd == 4'd15) ||
268+
(control_signals.ALU_writeback == ALU_WB_REG_RN && decoder_bus.decoded_regs.Rn == 4'd15) ||
269+
(control_signals.ALU_writeback == ALU_WB_REG_RP && control_signals.Rp_imm == 4'd15);
270+
266271
// ======================================================
267272
// Memory Module
268273
// ======================================================
@@ -369,9 +374,7 @@ module ARM7TMDI (
369374
flush_req <= 1'b1;
370375
end
371376

372-
if ((control_signals.ALU_writeback == ALU_WB_REG_RD && decoder_bus.decoded_regs.Rd == 4'd15) ||
373-
(control_signals.ALU_writeback == ALU_WB_REG_RN && decoder_bus.decoded_regs.Rn == 4'd15) ||
374-
(control_signals.ALU_writeback == ALU_WB_REG_RP && control_signals.Rp_imm == 4'd15)) begin
377+
if (pc_modified) begin
375378

376379
$display("ALU writeback to PC (R15) detected. ALU_writeback=%0d, Rd=%0d, Rn=%0d",
377380
control_signals.ALU_writeback, decoder_bus.decoded_regs.Rd,
@@ -388,9 +391,8 @@ module ARM7TMDI (
388391
unique case (execution_mode)
389392
MODE_ARM: begin
390393
// PC = PC + 4
391-
`WRITE_REG(regs, cpu_mode, 15, read_reg(regs, cpu_mode, 15) + 32'd4, execution_mode,
392-
1'b0)
393-
$display("Incrementing PC to: %0d", read_reg(regs, cpu_mode, 15) + 32'd4);
394+
`WRITE_REG(regs, cpu_mode, 15, bus.addr + 32'd4, execution_mode, 1'b0)
395+
$display("Incrementing PC to: %0d", bus.addr + 32'd4);
394396
$fflush();
395397
end
396398
MODE_THUMB: begin
@@ -492,36 +494,57 @@ module ARM7TMDI (
492494
end else begin
493495
$display("[CPU] addr=%0d", bus.addr);
494496

495-
unique case (control_signals.addr_bus_src)
496-
ADDR_SRC_NONE: begin
497-
// bus.addr <= 32'd0;
498-
end
499-
500-
ADDR_SRC_ALU: begin
501-
$display("[CPU] Driving address bus with ALU result: %0d", alu_bus.result);
497+
if (control_signals.pipeline_advance) begin
498+
bus.addr <= bus.addr + 32'd4;
499+
if (pc_modified) begin
502500
bus.addr <= alu_bus.result;
501+
end else if (flush_req_pending) begin
502+
bus.addr <= read_reg(regs, cpu_mode, 15);
503+
$display(
504+
"Pipeline advance with pending flush request, setting address bus to PC value: 0x%08x",
505+
read_reg(regs, cpu_mode, 15));
503506
end
507+
end else begin
504508

505-
ADDR_SRC_PC: begin
506-
$display("Setting address bus to PC value: 0x%08x", read_reg(regs, cpu_mode, 15));
507-
unique case (execution_mode)
508-
MODE_ARM: bus.addr <= read_reg(regs, cpu_mode, 15) & ~32'd3;
509-
MODE_THUMB: bus.addr <= read_reg(regs, cpu_mode, 15) & ~32'd1;
510-
endcase
511-
end
509+
unique case (control_signals.addr_bus_src)
510+
ADDR_SRC_NONE: begin
511+
// bus.addr <= 32'd0;
512+
end
512513

513-
ADDR_SRC_INCR: begin
514-
unique case (execution_mode)
515-
MODE_ARM: begin
516-
bus.addr <= bus.addr + 32'd4;
517-
end
518-
MODE_THUMB: begin
519-
bus.addr <= bus.addr + 32'd4;
520-
$display("Incrementing address bus for Thumb mode: new addr=%0d", bus.addr);
521-
end
522-
endcase
523-
end
524-
endcase
514+
ADDR_SRC_ALU: begin
515+
$display("[CPU] Driving address bus with ALU result: %0d", alu_bus.result);
516+
bus.addr <= alu_bus.result;
517+
end
518+
519+
ADDR_SRC_PC: begin
520+
$display("Setting address bus to PC value: 0x%08x", read_reg(regs, cpu_mode, 15));
521+
unique case (execution_mode)
522+
MODE_ARM: bus.addr <= read_reg(regs, cpu_mode, 15) & ~32'd3;
523+
MODE_THUMB: bus.addr <= read_reg(regs, cpu_mode, 15) & ~32'd1;
524+
endcase
525+
end
526+
527+
ADDR_SRC_PC_RESTORE: begin
528+
$display("Restoring address bus from PC value: 0x%08x", read_reg(regs, cpu_mode, 15));
529+
unique case (execution_mode)
530+
MODE_ARM: bus.addr <= read_reg(regs, cpu_mode, 15) - 32'd4 & ~32'd3;
531+
MODE_THUMB: bus.addr <= read_reg(regs, cpu_mode, 15) - 32'd4 & ~32'd1;
532+
endcase
533+
end
534+
535+
ADDR_SRC_INCR: begin
536+
unique case (execution_mode)
537+
MODE_ARM: begin
538+
bus.addr <= bus.addr + 32'd4;
539+
end
540+
MODE_THUMB: begin
541+
bus.addr <= bus.addr + 32'd4;
542+
$display("Incrementing address bus for Thumb mode: new addr=%0d", bus.addr);
543+
end
544+
endcase
545+
end
546+
endcase
547+
end
525548
end
526549
end
527550

cores/gba/rtl/cpu/ControlUnit.sv

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ module GBA_ControlUnit (
126126
end else if (flush_cnt == 3'd1) begin
127127
control_signals |= fetch_next_instr();
128128
control_signals.incrementer_writeback = 1;
129-
control_signals.addr_bus_src = ADDR_SRC_PC;
129+
control_signals.addr_bus_src = ADDR_SRC_INCR;
130130
control_signals.pipeline_advance = 1'b1;
131131

132132
$display("[ControlUnit] Flush cycle 2, flushing instruction");
@@ -136,7 +136,7 @@ module GBA_ControlUnit (
136136
// If the condition check fails, we still want to advance the pipeline and fetch the next instruction
137137
control_signals |= fetch_next_instr();
138138
control_signals.incrementer_writeback = 1;
139-
control_signals.addr_bus_src = ADDR_SRC_PC;
139+
control_signals.addr_bus_src = ADDR_SRC_INCR;
140140
control_signals.pipeline_advance = 1'b1;
141141

142142
$display(
@@ -762,10 +762,12 @@ module GBA_ControlUnit (
762762

763763
// First cycle: Prefetch and calculate first address
764764
if (cycle == 8'd0) begin
765-
// Perform a prefetch
766-
control_signals |= fetch_next_instr();
765+
// // Perform a prefetch
766+
// control_signals |= fetch_next_instr();
767+
768+
// // Stash address in PC so we can return later
769+
// control_signals.stash_addr = 1'b1;
767770

768-
// Stash address + 4 in PC so we can return later
769771
control_signals.incrementer_writeback = 1'b1;
770772

771773
// Update address for next cycle
@@ -962,7 +964,7 @@ module GBA_ControlUnit (
962964
end else
963965

964966
// Optionally writeback address to Rn and
965-
// fetch first first word from memory
967+
// write first first word to memory
966968
if (cycle == 8'd1) begin
967969
control_signals.Rp_imm =
968970
get_ith_bit(4'(cycle - 8'd1), decoder_bus.word.arm.block.reg_list);
@@ -996,9 +998,9 @@ module GBA_ControlUnit (
996998
"[ControlUnit] Cycle 1 of STM instruction, address calculation done, preparing for memory write");
997999
end else
9981000

999-
// Latch the last fetched word into the register file and
1001+
// Write the current register into memory and
10001002
// increment address for the next memory access
1001-
if (cycle < 8'd1 + 8'(regs_count)) begin
1003+
if (cycle < 8'(regs_count)) begin
10021004
control_signals.Rp_imm =
10031005
get_ith_bit(4'(cycle - 8'd1), decoder_bus.word.arm.block.reg_list);
10041006

@@ -1014,20 +1016,41 @@ module GBA_ControlUnit (
10141016

10151017
end else
10161018

1017-
// Latch the final fetched word into the register file and
1019+
// Write the current register into memory and
10181020
// update the address bus back to PC for the next instruction
1019-
if (cycle == 8'd1 + 8'(regs_count)) begin
1020-
1021+
if (cycle == 8'(regs_count)) begin
10211022
control_signals.Rp_imm =
10221023
get_ith_bit(4'(cycle - 8'd1), decoder_bus.word.arm.block.reg_list);
10231024

10241025
control_signals.B_bus_source = B_BUS_SRC_REG_RP;
10251026

1026-
control_signals.addr_bus_src = ADDR_SRC_PC;
1027+
control_signals.addr_bus_src = ADDR_SRC_PC_RESTORE;
10271028

10281029
// Write the next word in the block
10291030
control_signals.memory_write_en = 1'b1;
10301031

1032+
$display("[ControlUnit] Cycle %0d of STM instruction, writing register R%0d to data",
1033+
cycle, control_signals.Rp_imm);
1034+
1035+
end else
1036+
1037+
// We do not write this block. Instead we fetch the next instruction
1038+
// from memory and latch it to the fetched IR
1039+
if (cycle == 8'd1 + 8'(regs_count)) begin
1040+
1041+
control_signals |= fetch_next_instr();
1042+
// control_signals.incrementer_writeback = 1'b1;
1043+
1044+
control_signals.Rp_imm =
1045+
get_ith_bit(4'(cycle - 8'd1), decoder_bus.word.arm.block.reg_list);
1046+
1047+
control_signals.B_bus_source = B_BUS_SRC_REG_RP;
1048+
1049+
control_signals.addr_bus_src = ADDR_SRC_INCR;
1050+
1051+
// We do not write the next word in the block
1052+
control_signals.memory_write_en = 1'b0;
1053+
10311054
control_signals.pipeline_advance = 1'b1;
10321055

10331056
$display(

cores/gba/rtl/cpu/control_types.sv

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import gba_cpu_types_pkg::*;
88

99
package gba_control_types_pkg;
1010

11-
typedef enum logic [1:0] {
11+
typedef enum logic [2:0] {
1212
/// Don't change the current address on the address bus
1313
ADDR_SRC_NONE,
1414

@@ -19,7 +19,11 @@ package gba_control_types_pkg;
1919
ADDR_SRC_ALU,
2020

2121
/// Increments the current address on the address bus
22-
ADDR_SRC_INCR
22+
ADDR_SRC_INCR,
23+
24+
/// Places PC - 4 onto the address bus.
25+
/// TODO maybe i can just remove ADDR_SRC_PC and make this the default?
26+
ADDR_SRC_PC_RESTORE
2327
} address_source_t;
2428

2529
typedef enum logic [1:0] {
@@ -218,8 +222,6 @@ package gba_control_types_pkg;
218222
// Pipeline Control
219223
// ======================================================
220224

221-
logic pipeline_flush;
222-
223225
/// Control unit will handle the flush instead of the PC triggering one
224226
logic pipeline_handle_flush;
225227

cores/gba/sim/include/gba.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class GameboyAdvanceHarness {
6464
/// Advances the simulation by one tick (clock).
6565
bool tick();
6666

67+
bool half_tick();
68+
6769
/// Advance the simulation by one SM83 instruction.
6870
bool step();
6971

cores/gba/sim/src/gba.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,15 @@ bool GameboyAdvanceHarness::began_instruction() const {
237237
}
238238
};
239239

240+
bool GameboyAdvanceHarness::half_tick() {
241+
top->clk = 0;
242+
top->eval();
243+
tfp->dump(ctx.time());
244+
ctx.timeInc(5);
245+
246+
return true;
247+
}
248+
240249
bool GameboyAdvanceHarness::tick() {
241250
top->clk = 0;
242251
top->eval();

0 commit comments

Comments
 (0)