diff --git a/saturn_alu.v b/saturn_alu.v index 6e363a3..e9577bc 100644 --- a/saturn_alu.v +++ b/saturn_alu.v @@ -312,6 +312,7 @@ wire [0:0] alu_start_ev; wire [0:0] start_in_xfr_mode; wire [0:0] start_in_load_ptr_mode; wire [0:0] start_in_ldreg_mode; +wire [0:0] start_in_p_mode; wire [0:0] start_in_jmp_mode; wire [0:0] start_in_alu_mode; @@ -322,10 +323,19 @@ assign alu_start_ev = alu_active && phase_3; assign start_in_xfr_mode = alu_start_ev && i_ins_mem_xfr && !mode_set; assign start_in_load_ptr_mode = alu_start_ev && i_ins_alu_op && op_copy && dest_ptr && src1_IMM && !mode_set; assign start_in_ldreg_mode = alu_start_ev && i_ins_alu_op && op_copy && dest_A_C && src1_IMM && !mode_set; +// there is no need to set a flag for that one +assign start_in_p_mode = alu_start_ev && i_ins_alu_op && op_1_cycle_p && !mode_set; assign start_in_jmp_mode = alu_start_ev && i_ins_alu_op && op_jump && src1_IMM && !mode_set; // this is the last mode in the queue, called when no others have been recognized assign start_in_alu_mode = alu_start_ev && i_ins_alu_op && !mode_set && - !(start_in_load_ptr_mode || start_in_ldreg_mode || start_in_jmp_mode); + !(start_in_load_ptr_mode || start_in_ldreg_mode || + start_in_p_mode || start_in_jmp_mode); + + +assign o_alu_stall_dec = alu_initializing || i_stalled || + stall_modes; + + /* * wires for all modes */ @@ -333,30 +343,52 @@ assign start_in_alu_mode = alu_start_ev && i_ins_alu_op && !mode_set && /* operation */ wire [0:0] op_copy; +wire [0:0] op_inc; +wire [0:0] op_dec; wire [0:0] op_jmp_rel_2; wire [0:0] op_jmp_rel_3; wire [0:0] op_jmp_rel_4; wire [0:0] op_jmp_abs_5; + +wire [0:0] op_inc_p; +wire [0:0] op_dec_p; +wire [0:0] op_set_p; +wire [0:0] op_copy_p_to_c; +wire [0:0] op_copy_c_to_p; + +wire [0:0] op_1_cycle_p; wire [0:0] op_jump; -assign op_copy = (i_alu_op == `ALU_OP_COPY); -assign op_jmp_rel_2 = (i_alu_op == `ALU_OP_JMP_REL2); -assign op_jmp_rel_3 = (i_alu_op == `ALU_OP_JMP_REL3); -assign op_jmp_rel_4 = (i_alu_op == `ALU_OP_JMP_REL4); -assign op_jmp_abs_5 = (i_alu_op == `ALU_OP_JMP_ABS5); -assign op_jump = op_jmp_rel_2 || op_jmp_rel_3 || op_jmp_rel_4 || op_jmp_abs_5; +assign op_copy = (i_alu_op == `ALU_OP_COPY); +assign op_inc = (i_alu_op == `ALU_OP_INC); +assign op_dec = (i_alu_op == `ALU_OP_DEC); +assign op_jmp_rel_2 = (i_alu_op == `ALU_OP_JMP_REL2); +assign op_jmp_rel_3 = (i_alu_op == `ALU_OP_JMP_REL3); +assign op_jmp_rel_4 = (i_alu_op == `ALU_OP_JMP_REL4); +assign op_jmp_abs_5 = (i_alu_op == `ALU_OP_JMP_ABS5); + +assign op_inc_p = op_inc && src1_P && dest_P; +assign op_dec_p = op_dec && src1_P && dest_P; +assign op_set_p = op_copy && src1_IMM && dest_P; +assign op_copy_p_to_c = op_copy && src1_P && dest_C; +assign op_copy_c_to_p = op_copy && src1_C && dest_P; + +assign op_1_cycle_p = op_inc_p || op_dec_p || op_set_p || op_copy_p_to_c || op_copy_c_to_p; +assign op_jump = op_jmp_rel_2 || op_jmp_rel_3 || op_jmp_rel_4 || op_jmp_abs_5; /* source 1 */ wire [0:0] src1_A; wire [0:0] src1_C; wire [0:0] src1_DAT0; wire [0:0] src1_DAT1; +wire [0:0] src1_P; wire [0:0] src1_IMM; assign src1_A = (i_reg_src1 == `ALU_REG_A); assign src1_C = (i_reg_src1 == `ALU_REG_C); assign src1_DAT0 = (i_reg_src1 == `ALU_REG_DAT0); assign src1_DAT1 = (i_reg_src1 == `ALU_REG_DAT1); +assign src1_P = (i_reg_src1 == `ALU_REG_P); assign src1_IMM = (i_reg_src1 == `ALU_REG_IMM); /* destination */ @@ -366,6 +398,7 @@ wire [0:0] dest_D0; wire [0:0] dest_D1; wire [0:0] dest_DAT0; wire [0:0] dest_DAT1; +wire [0:0] dest_P; assign dest_A = (i_reg_dest == `ALU_REG_A); assign dest_C = (i_reg_dest == `ALU_REG_C); @@ -373,6 +406,7 @@ assign dest_D0 = (i_reg_dest == `ALU_REG_D0); assign dest_D1 = (i_reg_dest == `ALU_REG_D1); assign dest_DAT0 = (i_reg_dest == `ALU_REG_DAT0); assign dest_DAT1 = (i_reg_dest == `ALU_REG_DAT1); +assign dest_P = (i_reg_dest == `ALU_REG_P); wire [0:0] dest_A_C; wire [0:0] dest_ptr; @@ -381,6 +415,84 @@ assign dest_A_C = dest_A || dest_C; assign dest_ptr = dest_D0 || dest_D1; +/****************************************************************************** + * + * stuff that doesn't need to access registers + * + *****************************************************************************/ + +reg [0:0] just_reset; + +always @(posedge i_clk) begin + + if (i_reset) begin + just_reset <= 1; + f_mode_xfr <= 0; + f_mode_load_ptr <= 0; + f_mode_ldreg <= 0; + f_mode_jmp <= 0; + f_mode_alu <= 0; + end + + if (just_reset && !i_reset) begin + just_reset <= 0; + $display("ALU_INIT %0d: [%d] CLEARING JUST_RESET", phase, i_cycle_ctr); + end + + /* register to memory transfer + */ + if (start_in_xfr_mode) begin + $display("ALU %0d: [%d] memory transfer started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); + $display("ALU %0d: [%d] addr_src A %b | C %b | D0 %b | D1 %b | b1 %b | b0 %b | src %2b", phase, i_cycle_ctr, + addr_src_A, addr_src_C, addr_src_D0, addr_src_D1, addr_src_xfr_1, addr_src_xfr_0, addr_src); + $display("ALU %0d: [%d] stall the decoder",phase, i_cycle_ctr); + f_mode_xfr <= 1; + end + + if (alu_active && f_mode_xfr && i_bus_done) begin + $display("ALU %0d: [%d] resetting variables after data transfer", phase, i_cycle_ctr); + f_mode_xfr <= 0; + end + + /* load pointer register with value + */ + if (start_in_load_ptr_mode) begin + $display("ALU %0d: [%d] load_ptr mode started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); + f_mode_load_ptr <= 1; + end + + /* load register immediate with 1-16 nibbles + */ + if (start_in_ldreg_mode) begin + $display("ALU %0d: [%d] load register mode started (loading reg %c with %0d nibbles)", + phase, i_cycle_ctr, dest_A?"A":"C", i_field_last - i_field_start + 1); + f_mode_ldreg <= 1; + end + + if (do_load_register_done) begin + $display("ALU %0d: [%d] resetting variables after loading register", phase, i_cycle_ctr); + f_mode_ldreg <= 0; + end + + /* a jump instruction just appeared ! + */ + if (start_in_jmp_mode) begin + $display("ALU %0d: [%d] jmp mode started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); + $display("ALU %0d: [%d] stall the decoder",phase, i_cycle_ctr); + f_mode_jmp <= 1; + end + + /* general ALU mode (when there is no optimization) + */ + if (start_in_alu_mode) begin + $display("ALU %0d: [%d] alu mode started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); + $display("ALU %0d: [%d] stall the decoder",phase, i_cycle_ctr); + f_mode_alu <= 1; + end + +end + + /* module 1: * handles all alu mode timing * @@ -389,17 +501,7 @@ assign dest_ptr = dest_D0 || dest_D1; always @(posedge i_clk) begin - if (i_reset) begin - f_mode_alu <= 0; - end - - if (start_in_alu_mode) begin - $display("ALU %0d: [%d] alu mode started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); - $display("ALU %0d: [%d] stall the decoder",phase, i_cycle_ctr); - f_mode_alu <= 1; - end - - + end /* module 2: @@ -429,9 +531,6 @@ wire [0:0] addr_src_xfr_1; wire [1:0] addr_src_xfr; wire [1:0] addr_src; -wire [0:0] data_src_A; -wire [0:0] data_src_C; - wire [0:0] copy_done; wire [0:0] copy_address; wire [0:0] start_load_dp; @@ -483,7 +582,6 @@ always @(posedge i_clk) begin // initializes modes if (i_reset) begin - f_mode_xfr <= 0; data_counter <= 0; xfr_init_done <= 0; xfr_data_done <= 0; @@ -499,14 +597,6 @@ always @(posedge i_clk) begin * ***************************************************************************/ - if (start_in_xfr_mode) begin - $display("ALU %0d: [%d] memory transfer started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); - $display("ALU %0d: [%d] addr_src A %b | C %b | D0 %b | D1 %b | b1 %b | b0 %b | src %2b", phase, i_cycle_ctr, - addr_src_A, addr_src_C, addr_src_D0, addr_src_D1, addr_src_xfr_1, addr_src_xfr_0, addr_src); - $display("ALU %0d: [%d] stall the decoder",phase, i_cycle_ctr); - f_mode_xfr <= 1; - end - if (start_load_dp) begin o_bus_load_dp <= 1; end @@ -570,7 +660,6 @@ always @(posedge i_clk) begin if (alu_active && i_bus_done) begin $display("ALU %0d: [%d] bus controller is done, cleaning all variables used",phase, i_cycle_ctr); /* variables for the XFR mode */ - f_mode_xfr <= 0; data_counter <= 0; xfr_init_done <= 0; xfr_data_done <= 0; @@ -584,8 +673,8 @@ always @(posedge i_clk) begin end /* - * - * + * moduls 4: + * registers can only be written to here * * * @@ -593,10 +682,14 @@ end * */ +reg [0:0] alu_initializing; + reg [3:0] v_dest_counter; reg [3:0] v_max_counter; wire [2:0] v_dest_counter_ptr; +wire [1:0] v_dest_counter_hst; assign v_dest_counter_ptr = v_dest_counter[2:0]; +assign v_dest_counter_hst = v_dest_counter[1:0]; wire [0:0] do_load_pointer; wire [0:0] do_load_pointer_done; @@ -613,11 +706,38 @@ assign do_load_register_done = alu_active && phase_3 && f_mode_ldreg && (v_dest_ always @(posedge i_clk) begin if (i_reset) begin - v_dest_counter <= 0; - v_max_counter <= 0; - f_mode_load_ptr <= 0; - f_mode_ldreg <= 0; - f_mode_jmp <= 0; + /* initialization procedure */ + alu_initializing <= 1; + CARRY <= 0; + P <= 0; + + /* counters and flags */ + v_dest_counter <= 0; + v_max_counter <= 0; + end + + /* + * Initialization of all registers + * This happens at the same time the first LOAD_PC command goes out + * + */ + if (!i_reset && alu_initializing) begin + $display("ALU_INIT %0d: [%d] init %0d", phase, i_cycle_ctr, v_dest_counter); + A[v_dest_counter] <= 0; + B[v_dest_counter] <= 0; + C[v_dest_counter] <= 0; + D[v_dest_counter] <= 0; + D0[v_dest_counter_ptr] <= 0; + D1[v_dest_counter_ptr] <= 0; + R0[v_dest_counter] <= 0; + R1[v_dest_counter] <= 0; + R2[v_dest_counter] <= 0; + R3[v_dest_counter] <= 0; + R4[v_dest_counter] <= 0; + ST[v_dest_counter] <= 0; + HST[v_dest_counter_hst] <= 0; + alu_initializing <= (v_dest_counter != 15); + v_dest_counter <= v_dest_counter + 1; end /* @@ -626,8 +746,6 @@ always @(posedge i_clk) begin * */ if (start_in_load_ptr_mode) begin - $display("ALU %0d: [%d] load_ptr mode started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); - f_mode_load_ptr <= 1; v_dest_counter <= 0; end @@ -656,9 +774,6 @@ always @(posedge i_clk) begin */ if (start_in_ldreg_mode) begin - $display("ALU %0d: [%d] load register mode started (loading reg %c with %0d nibbles)", - phase, i_cycle_ctr, dest_A?"A":"C", i_field_last - i_field_start + 1); - f_mode_ldreg <= 1; v_dest_counter <= 0; v_max_counter <= i_field_last - i_field_start + 1; end @@ -674,27 +789,144 @@ always @(posedge i_clk) begin end if (do_load_register_done) begin - $display("ALU %0d: [%d] resetting variables after loading register", phase, i_cycle_ctr); v_dest_counter <= 0; v_max_counter <= 0; - f_mode_ldreg <= 0; end + /* + * P-mode + * + */ + + if (start_in_p_mode && op_set_p) begin + $display("ALU %0d: [%d] loading P= %h", phase, i_cycle_ctr, i_imm_value); + P <= i_imm_value; + end + + /* * * jump mode * */ - if (start_in_jmp_mode) begin - $display("ALU %0d: [%d] jmp mode started (i_ins_decoded %b)", phase, i_cycle_ctr, i_ins_decoded); - $display("ALU %0d: [%d] stall the decoder",phase, i_cycle_ctr); - f_mode_jmp <= 1; - end + end +/* module 5: + * manages all that is linked with the program counter + */ + +// wire [19:0] goyes_off; +// wire [19:0] goyes_pc; + +// wire [0:0] is_jmp_rel2; +// wire [0:0] is_rtn_rel2; +// wire [0:0] jmp_carry_test; +// wire [0:0] exec_rtn_rel2; +// wire [0:0] set_jmp_rel2; +// wire [0:0] exec_jmp_rel2; + +// wire [0:0] set_unc_jmp; +// wire [0:0] exec_unc_jmp; +// wire [0:0] exec_unc_rtn; +// wire [0:0] pop_pc; +// // wire [0:0] reload_pc; +// wire [0:0] push_pc; + + +// assign goyes_off = {{12{i_imm_value[3]}}, i_imm_value, jump_off[3:0]}; +// assign goyes_pc = jump_bse + goyes_off; +// // rtnyes is already handled by i_ins_test_go +// assign is_rtn_rel2 = (alu_op == `ALU_OP_JMP_REL2) && (goyes_off == 0); +// assign is_jmp_rel2 = (alu_op == `ALU_OP_JMP_REL2) && !(goyes_off == 0); +// assign jmp_carry_test = (i_test_carry && (CARRY == i_carry_val)); +// assign exec_rtn_rel2 = is_rtn_rel2 && jmp_carry_test && alu_done; +// // assign set_jmp_rel2 = is_jmp_rel2 && jmp_carry_test && alu_finish; +// assign exec_jmp_rel2 = is_jmp_rel2 && jmp_carry_test && alu_done; +// // assign set_unc_jmp = is_alu_op_unc_jump && alu_finish; +// // assign exec_unc_jmp = is_alu_op_unc_jump && alu_done; +// assign exec_unc_rtn = i_pop && i_ins_rtn; + +// assign pop_pc = i_pop && i_ins_rtn && +// ((!i_ins_test_go) || +// (i_ins_test_go && CARRY)); + +// assign reload_pc = (exec_unc_jmp || pop_pc || just_reset || exec_jmp_rel2); +// assign push_pc = update_pc && i_push && alu_finish; + + +wire [19:0] next_pc; +wire [0:0] update_pc; +wire [0:0] reload_pc; +wire [0:0] pop_pc; +wire [0:0] pc_lines_cleanup; + +assign next_pc = /*(set_unc_jmp || set_jmp_rel2)?jump_pc:*/PC + 1; +assign update_pc = (!i_reset && just_reset) /*!o_alu_stall_dec || exec_unc_jmp || exec_jmp_rel2 */; +assign pop_pc = i_pop && i_ins_rtn && ((!i_ins_test_go) || (i_ins_test_go && CARRY)); +assign reload_pc = (!i_reset && just_reset) /*|| (exec_unc_jmp || pop_pc || exec_jmp_rel2)*/; + +assign pc_lines_cleanup = alu_active && phase_0; + +always @(posedge i_clk) begin + + /* + * initializes default values + */ + if (i_reset) begin + PC <= ~0; + o_bus_load_pc <= 0; + rstk_ptr <= 0; + end + + /* + * Similarly to the data registers, + * initializes the RSTK while the PC is first loaded + * + */ + if (alu_initializing) + RSTK[v_dest_counter_ptr] <= 0; + + /** + * + * Update the PC. + * Request the new PC be loaded to the other modules through + * the bus if necessary + * + */ + + if (update_pc) begin + $display("ALU_PC %0d: [%d] update pc to %h", phase, i_cycle_ctr, next_pc); + PC <= /*pop_pc ? RSTK[rstk_ptr - 1] : */next_pc; + end + + if (reload_pc) begin + $display("ALU_PC %0d: [%d] $$$$ RELOADING PC to %h $$$$", phase, i_cycle_ctr, next_pc); + o_bus_address <= pop_pc ? RSTK[rstk_ptr-1] : next_pc; + o_bus_load_pc <= 1; + end + +// // $display("pop %b && rtn %b && ((!go %b) || (go %b && c %b))", +// // i_pop, i_ins_rtn, !i_ins_test_go, i_ins_test_go, c_carry); +// if (pop_pc) begin +// $display("POP RSTK[%0d] to PC %5h", rstk_ptr-1, RSTK[rstk_ptr - 1]); +// RSTK[rstk_ptr - 1] <= 0; +// rstk_ptr <= rstk_ptr - 1; +// end + +// if (push_pc) begin +// $display("PUSH PC %5h to RSTK[%0d]", PC, rstk_ptr); +// RSTK[rstk_ptr] <= PC; +// rstk_ptr <= rstk_ptr + 1; +// end + + if (pc_lines_cleanup && o_bus_load_pc) + o_bus_load_pc <= 0; + +end @@ -734,72 +966,72 @@ assign do_alu_shpc = alu_active && i_en_alu_dump; `endif -wire do_busclean; -wire do_alu_init; -wire do_alu_prep; -wire do_alu_calc; -wire do_alu_save; -wire do_alu_pc; -wire do_alu_mode; +// wire do_busclean; +// wire do_alu_init; +// wire do_alu_prep; +// wire do_alu_calc; +// wire do_alu_save; +// wire do_alu_pc; +// wire do_alu_mode; -assign do_busclean = alu_active && i_en_alu_dump; -assign do_alu_init = alu_active && i_en_alu_init && i_ins_alu_op && !alu_run && - !write_done && !do_exec_p_eq && !o_bus_config; -assign do_alu_prep = alu_active && i_en_alu_prep && alu_run; -assign do_alu_calc = alu_active && i_en_alu_calc && alu_run; -assign do_alu_save = alu_active && i_en_alu_save && alu_run; -assign do_alu_pc = alu_active && i_en_alu_save; -assign do_alu_mode = alu_active && i_en_alu_save && i_ins_set_mode; +// assign do_busclean = alu_active && i_en_alu_dump; +// assign do_alu_init = alu_active && i_en_alu_init && i_ins_alu_op && !alu_run && +// !write_done && !do_exec_p_eq && !o_bus_config; +// assign do_alu_prep = alu_active && i_en_alu_prep && alu_run; +// assign do_alu_calc = alu_active && i_en_alu_calc && alu_run; +// assign do_alu_save = alu_active && i_en_alu_save && alu_run; +// assign do_alu_pc = alu_active && i_en_alu_save; +// assign do_alu_mode = alu_active && i_en_alu_save && i_ins_set_mode; -wire do_go_init; -wire do_go_prep; +// wire do_go_init; +// wire do_go_prep; -assign do_go_init = alu_active && i_en_alu_save && i_ins_test_go; -assign do_go_prep = alu_active && i_en_alu_prep && i_ins_test_go; +// assign do_go_init = alu_active && i_en_alu_save && i_ins_test_go; +// assign do_go_prep = alu_active && i_en_alu_prep && i_ins_test_go; // now for the fine tuning ;-) // save one cycle on P= n! -wire is_alu_op_copy; -wire is_reg_dest_p; -wire is_reg_src1_imm; -wire do_exec_p_eq; +// wire is_alu_op_copy; +// wire is_reg_dest_p; +// wire is_reg_src1_imm; +// wire do_exec_p_eq; -assign is_alu_op_copy = (i_alu_op == `ALU_OP_COPY); -assign is_reg_dest_p = (i_reg_dest == `ALU_REG_P); -assign is_reg_src1_imm = (i_reg_src1 == `ALU_REG_IMM); -assign do_exec_p_eq = alu_active && i_en_alu_save && i_ins_alu_op && is_alu_op_copy && is_reg_dest_p && is_reg_src1_imm; +// assign is_alu_op_copy = (i_alu_op == `ALU_OP_COPY); +// assign is_reg_dest_p = (i_reg_dest == `ALU_REG_P); +// assign is_reg_src1_imm = (i_reg_src1 == `ALU_REG_IMM); +// assign do_exec_p_eq = alu_active && i_en_alu_save && i_ins_alu_op && is_alu_op_copy && is_reg_dest_p && is_reg_src1_imm; // the decoder may request the ALU to not stall it -wire bus_commands; -assign bus_commands = o_bus_config ; +// wire bus_commands; +// assign bus_commands = o_bus_config ; -assign o_alu_stall_dec = alu_initializing || - (alu_run && (!i_alu_no_stall || alu_finish || i_ins_mem_xfr)) || - i_stalled || bus_commands || stall_modes; +// assign o_alu_stall_dec = alu_initializing || +// (alu_run && (!i_alu_no_stall || alu_finish || i_ins_mem_xfr)) || +// i_stalled || bus_commands || stall_modes; -wire alu_start; -wire alu_finish; -wire [3:0] f_next; +// wire alu_start; +// wire alu_finish; +// wire [3:0] f_next; -assign alu_start = f_cur == f_first; -assign alu_finish = f_cur == f_last; -assign f_next = (f_cur + 1) & 4'hF; +// assign alu_start = f_cur == f_first; +// assign alu_finish = f_cur == f_last; +// assign f_next = (f_cur + 1) & 4'hF; /* * test things on alu_op */ -wire is_alu_op_unc_jump; -assign is_alu_op_unc_jump = ((alu_op == `ALU_OP_JMP_REL3) || - (alu_op == `ALU_OP_JMP_REL4) || - (alu_op == `ALU_OP_JMP_ABS5) || - i_ins_rtn); -wire is_alu_op_test; -assign is_alu_op_test = ((alu_op == `ALU_OP_TEST_EQ) || - (alu_op == `ALU_OP_TEST_NEQ)); +// wire is_alu_op_unc_jump; +// assign is_alu_op_unc_jump = ((alu_op == `ALU_OP_JMP_REL3) || +// (alu_op == `ALU_OP_JMP_REL4) || +// (alu_op == `ALU_OP_JMP_ABS5) || +// i_ins_rtn); +// wire is_alu_op_test; +// assign is_alu_op_test = ((alu_op == `ALU_OP_TEST_EQ) || +// (alu_op == `ALU_OP_TEST_NEQ)); /***************************************************************************** * @@ -818,14 +1050,14 @@ always @(posedge i_clk) begin // $display("ALU STALLED"); `endif -`ifdef ALU_DEBUG_DBG - $display("iad %b | AD %b | ad %b | ADD %b | add %b | ADJ %b | adj %b | ADP %b | adp %b", - i_alu_debug, - `ALU_DEBUG, i_alu_debug, - `ALU_DEBUG_DUMP, alu_debug_dump, - `ALU_DEBUG_JUMP, alu_debug_jump, - `ALU_DEBUG_PC, alu_debug_pc ); -`endif +// `ifdef ALU_DEBUG_DBG +// $display("iad %b | AD %b | ad %b | ADD %b | add %b | ADJ %b | adj %b | ADP %b | adp %b", +// i_alu_debug, +// `ALU_DEBUG, i_alu_debug, +// `ALU_DEBUG_DUMP, alu_debug_dump, +// `ALU_DEBUG_JUMP, alu_debug_jump, +// `ALU_DEBUG_PC, alu_debug_pc ); +// `endif `ifdef SIM if (do_reg_dump && alu_debug_dump) begin @@ -891,344 +1123,300 @@ end * ****************************************************************************/ -wire [0:0] is_mem_read; -wire [0:0] is_mem_write; -wire [0:0] is_mem_xfer; -wire [4:0] mem_reg; -assign is_mem_read = (i_reg_src1 == `ALU_REG_DAT0) || (i_reg_src1 == `ALU_REG_DAT1); -assign is_mem_write = (i_reg_dest == `ALU_REG_DAT0) || (i_reg_dest == `ALU_REG_DAT1); -assign is_mem_xfer = is_mem_read || is_mem_write; -assign mem_reg = is_mem_read?i_reg_src1:i_reg_dest; +// wire [0:0] is_mem_read; +// wire [0:0] is_mem_write; +// wire [0:0] is_mem_xfer; +// wire [4:0] mem_reg; +// assign is_mem_read = (i_reg_src1 == `ALU_REG_DAT0) || (i_reg_src1 == `ALU_REG_DAT1); +// assign is_mem_write = (i_reg_dest == `ALU_REG_DAT0) || (i_reg_dest == `ALU_REG_DAT1); +// assign is_mem_xfer = is_mem_read || is_mem_write; +// assign mem_reg = is_mem_read?i_reg_src1:i_reg_dest; -always @(posedge i_clk) begin +// always @(posedge i_clk) begin - if (i_reset) begin - alu_op <= 0; - reg_dest <= 0; - reg_src1 <= 0; - reg_src2 <= 0; - f_last <= 0; - end +// if (i_reset) begin +// alu_op <= 0; +// reg_dest <= 0; +// reg_src1 <= 0; +// reg_src2 <= 0; +// f_last <= 0; +// end - // this happens in phase 3, right after the instruction decoder (in phase 2) is finished - if (do_alu_init) begin +// // this happens in phase 3, right after the instruction decoder (in phase 2) is finished +// if (do_alu_init) begin -`ifdef SIM - if (alu_debug) - $display({"ALU_INIT 3: run %b | done %b | stall %b | op %d | s %h | l %h ", - "| ialu %b | dest %d | src1 %d | src2 %d | imm %h"}, - alu_run, alu_done, o_alu_stall_dec, i_alu_op,i_field_start, i_field_last, - i_ins_alu_op, i_reg_dest, i_reg_src1, i_reg_src2, i_imm_value); -`endif +// `ifdef SIM +// if (alu_debug) +// $display({"ALU_INIT 3: run %b | done %b | stall %b | op %d | s %h | l %h ", +// "| ialu %b | dest %d | src1 %d | src2 %d | imm %h"}, +// alu_run, alu_done, o_alu_stall_dec, i_alu_op,i_field_start, i_field_last, +// i_ins_alu_op, i_reg_dest, i_reg_src1, i_reg_src2, i_imm_value); +// `endif - alu_op <= i_alu_op; - reg_dest <= i_reg_dest; - reg_src1 <= i_reg_src1; - reg_src2 <= i_reg_src2; - f_last <= i_field_last; +// alu_op <= i_alu_op; +// reg_dest <= i_reg_dest; +// reg_src1 <= i_reg_src1; +// reg_src2 <= i_reg_src2; +// f_last <= i_field_last; - end -end +// end +// end /* * handles f_start, alu_run and alu_done */ -always @(posedge i_clk) begin +// always @(posedge i_clk) begin - if (i_reset) begin - alu_run <= 0; - alu_done <= 0; - f_first <= 0; - f_cur <= 0; - end +// if (i_reset) begin +// alu_run <= 0; +// alu_done <= 0; +// f_first <= 0; +// f_cur <= 0; +// end - if (alu_initializing) - f_cur <= f_cur + 1; +// if (alu_initializing) +// f_cur <= f_cur + 1; - if (do_alu_init) begin - $display("ALU %0d - ------------------------------------------------- DO_ALU_INIT", phase); - alu_run <= 1; - f_first <= i_field_start; - f_cur <= i_field_start; +// if (do_alu_init) begin +// $display("ALU %0d - ------------------------------------------------- DO_ALU_INIT", phase); +// alu_run <= 1; +// f_first <= i_field_start; +// f_cur <= i_field_start; - alu_go_test <= is_alu_op_test; - end +// alu_go_test <= is_alu_op_test; +// end - if (do_alu_prep) begin - // $display("ALU_TEST 1: tf %b | nxt %h", test_finish, f_next); - alu_done <= 0; - end +// if (do_alu_prep) begin +// // $display("ALU_TEST 1: tf %b | nxt %h", test_finish, f_next); +// alu_done <= 0; +// end - if (do_alu_calc) begin - // $display("ALU_TEST 2: tf %b | nxt %h", test_finish, f_next); - alu_done <= alu_finish; - // f_next <= (f_start + 1) & 4'hF; - end +// if (do_alu_calc) begin +// // $display("ALU_TEST 2: tf %b | nxt %h", test_finish, f_next); +// alu_done <= alu_finish; +// // f_next <= (f_start + 1) & 4'hF; +// end - if (do_alu_save) begin - // $display("ALU_TEST 3: tf %b | nxt %h", test_finish, f_next); - f_cur <= f_next; - end +// if (do_alu_save) begin +// // $display("ALU_TEST 3: tf %b | nxt %h", test_finish, f_next); +// f_cur <= f_next; +// end - if (do_alu_save && alu_done) begin - alu_run <= 0; - alu_done <= 0; - end +// if (do_alu_save && alu_done) begin +// alu_run <= 0; +// alu_done <= 0; +// end -end +// end -always @(posedge i_clk) begin +// always @(posedge i_clk) begin - if (i_reset) begin - p_src1 <= 0; - p_src2 <= 0; - p_carry <= 0; - jump_bse <= 0; - end +// if (i_reset) begin +// p_src1 <= 0; +// p_src2 <= 0; +// p_carry <= 0; +// jump_bse <= 0; +// end - if (do_alu_prep) begin - if (alu_debug) begin - `ifdef SIM - $display("ALU_PREP 1: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | imm %h", - alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, i_imm_value); - `endif - end +// if (do_alu_prep) begin +// if (alu_debug) begin +// `ifdef SIM +// $display("ALU_PREP 1: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | imm %h", +// alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, i_imm_value); +// `endif +// end - /* - * source 1 - */ - case (alu_op) - `ALU_OP_ZERO: begin end // no source required - `ALU_OP_COPY, - `ALU_OP_EXCH, - `ALU_OP_RST_BIT, - `ALU_OP_SET_BIT, - `ALU_OP_2CMPL, - `ALU_OP_DEC, - `ALU_OP_ADD, - `ALU_OP_TEST_EQ, - `ALU_OP_TEST_NEQ, - `ALU_OP_JMP_REL2, - `ALU_OP_JMP_REL3, - `ALU_OP_JMP_REL4, - `ALU_OP_JMP_ABS5, - `ALU_OP_CLR_MASK: - case (reg_src1) - `ALU_REG_A: p_src1 <= A[f_cur]; - `ALU_REG_B: p_src1 <= B[f_cur]; - `ALU_REG_C: p_src1 <= C[f_cur]; - `ALU_REG_D: p_src1 <= D[f_cur]; - `ALU_REG_R0: p_src1 <= R0[f_cur]; - `ALU_REG_R1: p_src1 <= R1[f_cur]; - `ALU_REG_R2: p_src1 <= R2[f_cur]; - `ALU_REG_R3: p_src1 <= R3[f_cur]; - `ALU_REG_R4: p_src1 <= R4[f_cur]; - `ALU_REG_D0: p_src1 <= D0[f_cur[2:0]]; - `ALU_REG_D1: p_src1 <= D1[f_cur[2:0]]; - `ALU_REG_P: p_src1 <= P; - `ALU_REG_DAT0, - `ALU_REG_DAT1: p_src1 <= i_bus_nibble_in; - `ALU_REG_HST: p_src1 <= HST; - `ALU_REG_IMM: p_src1 <= i_imm_value; - `ALU_REG_ZERO: p_src1 <= 0; - default: $display("#### SRC_1 UNHANDLED REGISTER %0d", reg_src1); - endcase - default: $display("#### SRC_1 UNHANDLED OPERATION %0d", alu_op); - endcase +// /* +// * source 1 +// */ +// case (alu_op) +// `ALU_OP_ZERO: begin end // no source required +// `ALU_OP_COPY, +// `ALU_OP_EXCH, +// `ALU_OP_RST_BIT, +// `ALU_OP_SET_BIT, +// `ALU_OP_2CMPL, +// `ALU_OP_DEC, +// `ALU_OP_ADD, +// `ALU_OP_TEST_EQ, +// `ALU_OP_TEST_NEQ, +// `ALU_OP_JMP_REL2, +// `ALU_OP_JMP_REL3, +// `ALU_OP_JMP_REL4, +// `ALU_OP_JMP_ABS5, +// `ALU_OP_CLR_MASK: +// case (reg_src1) +// `ALU_REG_A: p_src1 <= A[f_cur]; +// `ALU_REG_B: p_src1 <= B[f_cur]; +// `ALU_REG_C: p_src1 <= C[f_cur]; +// `ALU_REG_D: p_src1 <= D[f_cur]; +// `ALU_REG_R0: p_src1 <= R0[f_cur]; +// `ALU_REG_R1: p_src1 <= R1[f_cur]; +// `ALU_REG_R2: p_src1 <= R2[f_cur]; +// `ALU_REG_R3: p_src1 <= R3[f_cur]; +// `ALU_REG_R4: p_src1 <= R4[f_cur]; +// `ALU_REG_D0: p_src1 <= D0[f_cur[2:0]]; +// `ALU_REG_D1: p_src1 <= D1[f_cur[2:0]]; +// `ALU_REG_P: p_src1 <= P; +// `ALU_REG_DAT0, +// `ALU_REG_DAT1: p_src1 <= i_bus_nibble_in; +// `ALU_REG_HST: p_src1 <= HST; +// `ALU_REG_IMM: p_src1 <= i_imm_value; +// `ALU_REG_ZERO: p_src1 <= 0; +// default: $display("#### SRC_1 UNHANDLED REGISTER %0d", reg_src1); +// endcase +// default: $display("#### SRC_1 UNHANDLED OPERATION %0d", alu_op); +// endcase - /* - * source 2 - */ - case (alu_op) - `ALU_OP_ZERO, - `ALU_OP_COPY, - `ALU_OP_RST_BIT, - `ALU_OP_SET_BIT, - `ALU_OP_2CMPL, - `ALU_OP_DEC, - `ALU_OP_JMP_REL2, - `ALU_OP_JMP_REL3, - `ALU_OP_JMP_REL4, - `ALU_OP_JMP_ABS5: begin end // no need for a 2nd operand - `ALU_OP_EXCH, - `ALU_OP_ADD, - `ALU_OP_TEST_EQ, - `ALU_OP_TEST_NEQ, - `ALU_OP_CLR_MASK: begin - case (reg_src2) - `ALU_REG_A: p_src2 <= A[f_cur]; - `ALU_REG_B: p_src2 <= B[f_cur]; - `ALU_REG_C: p_src2 <= C[f_cur]; - `ALU_REG_D: p_src2 <= D[f_cur]; - `ALU_REG_R0: p_src2 <= R0[f_cur]; - `ALU_REG_R1: p_src2 <= R1[f_cur]; - `ALU_REG_R2: p_src2 <= R2[f_cur]; - `ALU_REG_R3: p_src2 <= R3[f_cur]; - `ALU_REG_R4: p_src2 <= R4[f_cur]; - `ALU_REG_D0: p_src2 <= D0[f_cur[2:0]]; - `ALU_REG_D1: p_src2 <= D1[f_cur[2:0]]; - `ALU_REG_P: p_src2 <= P; - `ALU_REG_HST: p_src2 <= HST; - `ALU_REG_IMM: p_src2 <= i_imm_value; - `ALU_REG_ZERO: p_src2 <= 0; - default: $display("#### SRC_2 UNHANDLED REGISTER %0d", reg_src2); - endcase - end - default: $display("#### SRC_2 UNHANDLED OPERATION %0d", alu_op); - endcase +// /* +// * source 2 +// */ +// case (alu_op) +// `ALU_OP_ZERO, +// `ALU_OP_COPY, +// `ALU_OP_RST_BIT, +// `ALU_OP_SET_BIT, +// `ALU_OP_2CMPL, +// `ALU_OP_DEC, +// `ALU_OP_JMP_REL2, +// `ALU_OP_JMP_REL3, +// `ALU_OP_JMP_REL4, +// `ALU_OP_JMP_ABS5: begin end // no need for a 2nd operand +// `ALU_OP_EXCH, +// `ALU_OP_ADD, +// `ALU_OP_TEST_EQ, +// `ALU_OP_TEST_NEQ, +// `ALU_OP_CLR_MASK: begin +// case (reg_src2) +// `ALU_REG_A: p_src2 <= A[f_cur]; +// `ALU_REG_B: p_src2 <= B[f_cur]; +// `ALU_REG_C: p_src2 <= C[f_cur]; +// `ALU_REG_D: p_src2 <= D[f_cur]; +// `ALU_REG_R0: p_src2 <= R0[f_cur]; +// `ALU_REG_R1: p_src2 <= R1[f_cur]; +// `ALU_REG_R2: p_src2 <= R2[f_cur]; +// `ALU_REG_R3: p_src2 <= R3[f_cur]; +// `ALU_REG_R4: p_src2 <= R4[f_cur]; +// `ALU_REG_D0: p_src2 <= D0[f_cur[2:0]]; +// `ALU_REG_D1: p_src2 <= D1[f_cur[2:0]]; +// `ALU_REG_P: p_src2 <= P; +// `ALU_REG_HST: p_src2 <= HST; +// `ALU_REG_IMM: p_src2 <= i_imm_value; +// `ALU_REG_ZERO: p_src2 <= 0; +// default: $display("#### SRC_2 UNHANDLED REGISTER %0d", reg_src2); +// endcase +// end +// default: $display("#### SRC_2 UNHANDLED OPERATION %0d", alu_op); +// endcase - // setup p_carry - // $display("fs %h | fs=0 %b | cc %b | npc %b", f_start, (f_start == 0), c_carry, (f_start == 0)?1'b1:c_carry); - case (alu_op) - `ALU_OP_2CMPL: p_carry <= alu_start?1'b1:c_carry; - `ALU_OP_DEC: p_carry <= alu_start?1'b0:c_carry; - `ALU_OP_ADD: p_carry <= alu_start?1'b0:c_carry; - `ALU_OP_TEST_NEQ: p_carry <= alu_start?1'b0:c_carry; - endcase +// // setup p_carry +// // $display("fs %h | fs=0 %b | cc %b | npc %b", f_start, (f_start == 0), c_carry, (f_start == 0)?1'b1:c_carry); +// case (alu_op) +// `ALU_OP_2CMPL: p_carry <= alu_start?1'b1:c_carry; +// `ALU_OP_DEC: p_carry <= alu_start?1'b0:c_carry; +// `ALU_OP_ADD: p_carry <= alu_start?1'b0:c_carry; +// `ALU_OP_TEST_NEQ: p_carry <= alu_start?1'b0:c_carry; +// endcase - // prepare jump base - case (alu_op) - `ALU_OP_JMP_REL2, - `ALU_OP_JMP_REL3, - `ALU_OP_JMP_REL4: - begin - // the address of the first digit of the offset - if (!i_push && alu_start) - jump_bse <= PC - 1; - // doc says address of the next instruction, but appears to be off by 1 - if (i_push) - jump_bse <= PC; - end - endcase +// // prepare jump base +// case (alu_op) +// `ALU_OP_JMP_REL2, +// `ALU_OP_JMP_REL3, +// `ALU_OP_JMP_REL4: +// begin +// // the address of the first digit of the offset +// if (!i_push && alu_start) +// jump_bse <= PC - 1; +// // doc says address of the next instruction, but appears to be off by 1 +// if (i_push) +// jump_bse <= PC; +// end +// endcase - end -end +// end +// end -always @(posedge i_clk) begin +// always @(posedge i_clk) begin - if (i_reset) begin - c_res1 <= 0; - c_res2 <= 0; - c_carry <= 0; - is_zero <= 0; - jump_off <= 0; - end +// if (i_reset) begin +// c_res1 <= 0; +// c_res2 <= 0; +// c_carry <= 0; +// is_zero <= 0; +// jump_off <= 0; +// end - if (do_alu_calc) begin - `ifdef SIM - if (alu_debug) - $display("ALU_CALC 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | dest %d | psrc1 %h | psrc2 %h | p_carry %b", - alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, reg_dest, p_src1, p_src2, p_carry); - if (alu_debug_jump) - $display("ALU_JUMP 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | jbs %5h | jof %5h | jpc %5h | fin %b", - alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, jump_bse, jump_off, jump_pc, alu_finish); - `endif +// if (do_alu_calc) begin +// `ifdef SIM +// if (alu_debug) +// $display("ALU_CALC 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | dest %d | psrc1 %h | psrc2 %h | p_carry %b", +// alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, reg_dest, p_src1, p_src2, p_carry); +// if (alu_debug_jump) +// $display("ALU_JUMP 2: run %b | done %b | stall %b | op %d | f %h | c %h | l %h | jbs %5h | jof %5h | jpc %5h | fin %b", +// alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, f_last, jump_bse, jump_off, jump_pc, alu_finish); +// `endif - if(alu_start) - case (alu_op) - `ALU_OP_JMP_REL2, - `ALU_OP_JMP_REL3, - `ALU_OP_JMP_REL4, - `ALU_OP_JMP_ABS5: jump_off <= { 16'b0, p_src1 }; - endcase +// if(alu_start) +// case (alu_op) +// `ALU_OP_JMP_REL2, +// `ALU_OP_JMP_REL3, +// `ALU_OP_JMP_REL4, +// `ALU_OP_JMP_ABS5: jump_off <= { 16'b0, p_src1 }; +// endcase - // main case - case (alu_op) - `ALU_OP_ZERO: c_res1 <= 0; - `ALU_OP_EXCH: - begin - c_res1 <= p_src2; - c_res2 <= p_src1; - end - `ALU_OP_COPY, - `ALU_OP_RST_BIT, - `ALU_OP_SET_BIT: c_res1 <= p_src1; - `ALU_OP_2CMPL: begin - c_carry <= (~p_src1 == 4'hf) && p_carry ; - c_res1 <= ~p_src1 + {3'b000, p_carry}; - is_zero <= ((~p_src1 + {3'b000, p_carry}) == 0) && alu_start?1:is_zero; - end - `ALU_OP_DEC: - {c_carry, c_res1} <= p_src1 + 4'b1111 + {4'b0000, p_carry}; - `ALU_OP_ADD: - {c_carry, c_res1} <= p_src1 + p_src2 + {4'b0000, p_carry}; - `ALU_OP_TEST_NEQ: - c_carry <= !(p_src1 == p_src2) || p_carry; - `ALU_OP_JMP_REL2: begin end // there is no middle part - `ALU_OP_JMP_REL3, - `ALU_OP_JMP_REL4, - `ALU_OP_JMP_ABS5: jump_off[f_cur*4+:4] <= p_src1; - `ALU_OP_CLR_MASK: c_res1 <= p_src1 & ~p_src2; - default: $display("#### CALC 2 UNHANDLED OPERATION %0d", alu_op); - endcase +// // main case +// case (alu_op) +// `ALU_OP_ZERO: c_res1 <= 0; +// `ALU_OP_EXCH: +// begin +// c_res1 <= p_src2; +// c_res2 <= p_src1; +// end +// `ALU_OP_COPY, +// `ALU_OP_RST_BIT, +// `ALU_OP_SET_BIT: c_res1 <= p_src1; +// `ALU_OP_2CMPL: begin +// c_carry <= (~p_src1 == 4'hf) && p_carry ; +// c_res1 <= ~p_src1 + {3'b000, p_carry}; +// is_zero <= ((~p_src1 + {3'b000, p_carry}) == 0) && alu_start?1:is_zero; +// end +// `ALU_OP_DEC: +// {c_carry, c_res1} <= p_src1 + 4'b1111 + {4'b0000, p_carry}; +// `ALU_OP_ADD: +// {c_carry, c_res1} <= p_src1 + p_src2 + {4'b0000, p_carry}; +// `ALU_OP_TEST_NEQ: +// c_carry <= !(p_src1 == p_src2) || p_carry; +// `ALU_OP_JMP_REL2: begin end // there is no middle part +// `ALU_OP_JMP_REL3, +// `ALU_OP_JMP_REL4, +// `ALU_OP_JMP_ABS5: jump_off[f_cur*4+:4] <= p_src1; +// `ALU_OP_CLR_MASK: c_res1 <= p_src1 & ~p_src2; +// default: $display("#### CALC 2 UNHANDLED OPERATION %0d", alu_op); +// endcase - if (alu_finish) - case (alu_op) - `ALU_OP_JMP_REL2: jump_off <= { {12{p_src1[3]}}, p_src1, jump_off[3:0] }; - `ALU_OP_JMP_REL3: jump_off <= { {8{p_src1[3]}}, p_src1, jump_off[7:0] }; - `ALU_OP_JMP_REL4: jump_off <= { {4{p_src1[3]}}, p_src1, jump_off[11:0] }; - endcase +// if (alu_finish) +// case (alu_op) +// `ALU_OP_JMP_REL2: jump_off <= { {12{p_src1[3]}}, p_src1, jump_off[3:0] }; +// `ALU_OP_JMP_REL3: jump_off <= { {8{p_src1[3]}}, p_src1, jump_off[7:0] }; +// `ALU_OP_JMP_REL4: jump_off <= { {4{p_src1[3]}}, p_src1, jump_off[11:0] }; +// endcase - // $display("-------C- SRC1 %b %h | ~SRC1 %b %h | PC %b | RES1 %b %h | CC %b", - // p_src1, p_src1, ~p_src1, ~p_src1, p_carry, - // (~p_src1) + p_carry, (~p_src1) + p_carry, - // (~p_src1) == 4'hf ); - end +// // $display("-------C- SRC1 %b %h | ~SRC1 %b %h | PC %b | RES1 %b %h | CC %b", +// // p_src1, p_src1, ~p_src1, ~p_src1, p_carry, +// // (~p_src1) + p_carry, (~p_src1) + p_carry, +// // (~p_src1) == 4'hf ); +// end - if (do_go_init) begin - // $display("GO_INIT 3: imm %h", i_imm_value); - jump_off <= { {16{1'b0}}, i_imm_value}; - end -end +// if (do_go_init) begin +// // $display("GO_INIT 3: imm %h", i_imm_value); +// jump_off <= { {16{1'b0}}, i_imm_value}; +// end +// end -/****************************************************************************** - * save alu registers after calculations - * - * this is the only place the registers can be updated ! - * - * - * - * - * - * - *****************************************************************************/ - -reg [0:0] alu_initializing; - -always @(posedge i_clk) begin - - /* - * Initialization of all registers - * This happens at the same time the first LOAD_PC command goes out - * - */ - - if (i_reset) begin - alu_initializing <= 1; - CARRY <= 0; - P <= 0; - end - - if (alu_initializing) begin - A[f_cur] <= 0; - B[f_cur] <= 0; - C[f_cur] <= 0; - D[f_cur] <= 0; - D0[f_cur[2:0]] <= 0; - D1[f_cur[2:0]] <= 0; - R0[f_cur] <= 0; - R1[f_cur] <= 0; - R2[f_cur] <= 0; - R3[f_cur] <= 0; - R4[f_cur] <= 0; - ST[f_cur] <= 0; - HST[f_cur[1:0]] <= 0; - alu_initializing <= (f_cur != 15); - end /* * @@ -1236,16 +1424,16 @@ always @(posedge i_clk) begin * */ - if (do_alu_save || do_go_prep) begin - if (alu_debug_jump) begin - `ifdef SIM - $display({"ALU_JUMP 3: run %b | done %b | stall %b | op %d | f %h | ", - "c %h | l %h | bse %5h | jof %5h | jpc %5h | fin %b"}, - alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, - f_last, jump_bse, jump_off, jump_pc, alu_finish); - `endif - end - end + // if (do_alu_save || do_go_prep) begin + // if (alu_debug_jump) begin + // `ifdef SIM + // $display({"ALU_JUMP 3: run %b | done %b | stall %b | op %d | f %h | ", + // "c %h | l %h | bse %5h | jof %5h | jpc %5h | fin %b"}, + // alu_run, alu_done, o_alu_stall_dec, alu_op, f_first, f_cur, + // f_last, jump_bse, jump_off, jump_pc, alu_finish); + // `endif + // end + // end /* * @@ -1253,9 +1441,9 @@ always @(posedge i_clk) begin * */ - if (do_exec_p_eq) begin - P <= i_imm_value; - end + // if (do_exec_p_eq) begin + // P <= i_imm_value; + // end /* * normal way for the ALU to save results. @@ -1263,164 +1451,122 @@ always @(posedge i_clk) begin * */ - if (do_alu_save) begin - `ifdef SIM - if (alu_debug) begin - $display({"ALU_SAVE 3: run %b | done %b | stall %b | op %d | f %h | c %h | l %h |", - " dest %d | cres1 %h | cres2 %h | psrc1 %h | psrc2 %h | c_carry %b"}, - alu_run, alu_done, o_alu_stall_dec, alu_op, - f_first, f_cur, f_last, reg_dest, c_res1, c_res2, p_src1, p_src2, c_carry); + // if (do_alu_save) begin + // `ifdef SIM + // if (alu_debug) begin + // $display({"ALU_SAVE 3: run %b | done %b | stall %b | op %d | f %h | c %h | l %h |", + // " dest %d | cres1 %h | cres2 %h | psrc1 %h | psrc2 %h | c_carry %b"}, + // alu_run, alu_done, o_alu_stall_dec, alu_op, + // f_first, f_cur, f_last, reg_dest, c_res1, c_res2, p_src1, p_src2, c_carry); - end - `endif + // end + // `endif - case (alu_op) - `ALU_OP_ZERO, - `ALU_OP_COPY, - `ALU_OP_EXCH, // does the first assign - `ALU_OP_2CMPL, - `ALU_OP_DEC, - `ALU_OP_ADD, - `ALU_OP_CLR_MASK: - case (reg_dest) - `ALU_REG_A: A[f_cur] <= c_res1; - `ALU_REG_B: B[f_cur] <= c_res1; - `ALU_REG_C: C[f_cur] <= c_res1; - `ALU_REG_D: D[f_cur] <= c_res1; - `ALU_REG_R0: R0[f_cur] <= c_res1; - `ALU_REG_R1: R1[f_cur] <= c_res1; - `ALU_REG_R2: R2[f_cur] <= c_res1; - `ALU_REG_R3: R3[f_cur] <= c_res1; - `ALU_REG_R4: R4[f_cur] <= c_res1; - `ALU_REG_D0: D0[f_cur[2:0]] <= c_res1; - `ALU_REG_D1: D1[f_cur[2:0]] <= c_res1; - `ALU_REG_ST: ST[f_cur*4+:4] <= c_res1; - `ALU_REG_P: P <= c_res1; - `ALU_REG_DAT0, - `ALU_REG_DAT1: o_bus_nibble_out <= c_res1; - `ALU_REG_HST: HST <= c_res1; - `ALU_REG_ADDR: begin end // done down below where o_bus_addr is accessible - default: $display("#### ALU_SAVE invalid register %0d for op %0d", reg_dest, alu_op); - endcase - `ALU_OP_RST_BIT, - `ALU_OP_SET_BIT: - case (reg_dest) - `ALU_REG_ST: ST[c_res1] <= alu_op==`ALU_OP_SET_BIT?1:0; - default: $display("#### ALU_SAVE invalid register %0d for op %0d", reg_dest, alu_op); - endcase - `ALU_OP_TEST_EQ, - `ALU_OP_TEST_NEQ, - `ALU_OP_JMP_REL2, - `ALU_OP_JMP_REL3, - `ALU_OP_JMP_REL4, - `ALU_OP_JMP_ABS5: begin end // nothing to save, handled by PC management below - default: $display("#### ALU_SAVE UNHANDLED OP %0d", alu_op); - endcase + // case (alu_op) + // `ALU_OP_ZERO, + // `ALU_OP_COPY, + // `ALU_OP_EXCH, // does the first assign + // `ALU_OP_2CMPL, + // `ALU_OP_DEC, + // `ALU_OP_ADD, + // `ALU_OP_CLR_MASK: + // case (reg_dest) + // `ALU_REG_A: A[f_cur] <= c_res1; + // `ALU_REG_B: B[f_cur] <= c_res1; + // `ALU_REG_C: C[f_cur] <= c_res1; + // `ALU_REG_D: D[f_cur] <= c_res1; + // `ALU_REG_R0: R0[f_cur] <= c_res1; + // `ALU_REG_R1: R1[f_cur] <= c_res1; + // `ALU_REG_R2: R2[f_cur] <= c_res1; + // `ALU_REG_R3: R3[f_cur] <= c_res1; + // `ALU_REG_R4: R4[f_cur] <= c_res1; + // `ALU_REG_D0: D0[f_cur[2:0]] <= c_res1; + // `ALU_REG_D1: D1[f_cur[2:0]] <= c_res1; + // `ALU_REG_ST: ST[f_cur*4+:4] <= c_res1; + // `ALU_REG_P: P <= c_res1; + // `ALU_REG_DAT0, + // `ALU_REG_DAT1: o_bus_nibble_out <= c_res1; + // `ALU_REG_HST: HST <= c_res1; + // `ALU_REG_ADDR: begin end // done down below where o_bus_addr is accessible + // default: $display("#### ALU_SAVE invalid register %0d for op %0d", reg_dest, alu_op); + // endcase + // `ALU_OP_RST_BIT, + // `ALU_OP_SET_BIT: + // case (reg_dest) + // `ALU_REG_ST: ST[c_res1] <= alu_op==`ALU_OP_SET_BIT?1:0; + // default: $display("#### ALU_SAVE invalid register %0d for op %0d", reg_dest, alu_op); + // endcase + // `ALU_OP_TEST_EQ, + // `ALU_OP_TEST_NEQ, + // `ALU_OP_JMP_REL2, + // `ALU_OP_JMP_REL3, + // `ALU_OP_JMP_REL4, + // `ALU_OP_JMP_ABS5: begin end // nothing to save, handled by PC management below + // default: $display("#### ALU_SAVE UNHANDLED OP %0d", alu_op); + // endcase - /* - * in case of exch, we need to update src2 to finish the exchange - */ - case (alu_op) - `ALU_OP_EXCH: // 2nd assign, with src2 - case (reg_src2) - `ALU_REG_A: A[f_cur] <= c_res2; - `ALU_REG_B: B[f_cur] <= c_res2; - `ALU_REG_C: C[f_cur] <= c_res2; - `ALU_REG_D: D[f_cur] <= c_res2; - `ALU_REG_D0: D0[f_cur[2:0]] <= c_res2; - `ALU_REG_D1: D1[f_cur[2:0]] <= c_res2; - `ALU_REG_R0: R0[f_cur] <= c_res2; - `ALU_REG_R1: R1[f_cur] <= c_res2; - `ALU_REG_R2: R2[f_cur] <= c_res2; - `ALU_REG_R3: R3[f_cur] <= c_res2; - `ALU_REG_R4: R4[f_cur] <= c_res2; - // `ALU_REG_ST: ST[f_start*4+:4] <= c_res2; - // `ALU_REG_P: P <= c_res2; - // `ALU_REG_HST: HST <= c_res2; - endcase - endcase - end + // /* + // * in case of exch, we need to update src2 to finish the exchange + // */ + // case (alu_op) + // `ALU_OP_EXCH: // 2nd assign, with src2 + // case (reg_src2) + // `ALU_REG_A: A[f_cur] <= c_res2; + // `ALU_REG_B: B[f_cur] <= c_res2; + // `ALU_REG_C: C[f_cur] <= c_res2; + // `ALU_REG_D: D[f_cur] <= c_res2; + // `ALU_REG_D0: D0[f_cur[2:0]] <= c_res2; + // `ALU_REG_D1: D1[f_cur[2:0]] <= c_res2; + // `ALU_REG_R0: R0[f_cur] <= c_res2; + // `ALU_REG_R1: R1[f_cur] <= c_res2; + // `ALU_REG_R2: R2[f_cur] <= c_res2; + // `ALU_REG_R3: R3[f_cur] <= c_res2; + // `ALU_REG_R4: R4[f_cur] <= c_res2; + // // `ALU_REG_ST: ST[f_start*4+:4] <= c_res2; + // // `ALU_REG_P: P <= c_res2; + // // `ALU_REG_HST: HST <= c_res2; + // endcase + // endcase + // end /* * update carry */ - if (do_alu_save) begin - case (alu_op) - `ALU_OP_2CMPL: CARRY <= !is_zero; - `ALU_OP_DEC, - `ALU_OP_ADD, - `ALU_OP_TEST_EQ, - `ALU_OP_TEST_NEQ: CARRY <= c_carry; - endcase - end + // if (do_alu_save) begin + // case (alu_op) + // `ALU_OP_2CMPL: CARRY <= !is_zero; + // `ALU_OP_DEC, + // `ALU_OP_ADD, + // `ALU_OP_TEST_EQ, + // `ALU_OP_TEST_NEQ: CARRY <= c_carry; + // endcase + // end // do whatever is requested by the RTN instruction - if (alu_active && i_ins_rtn) begin +// if (alu_active && i_ins_rtn) begin - if (i_set_xm) - HST[`ALU_HST_XM] <= 1; +// if (i_set_xm) +// HST[`ALU_HST_XM] <= 1; - if (i_set_carry) - CARRY <= i_carry_val; +// if (i_set_carry) +// CARRY <= i_carry_val; - end +// end -end +// end -/****************************************************************************** - * - * facility to detect that we just came out of reset - * - *****************************************************************************/ -reg [0:0] just_reset; +// wire [0:0] read_done; +// wire [0:0] setup_load_dp_read; +// wire [0:0] setup_load_dp_write; -always @(posedge i_clk) begin - - if (i_reset) - just_reset <= 1; - - if (just_reset && do_alu_pc) begin - just_reset <= 0; - $display("---------------------------------------- CLEARING JUST_RESET"); - end - -end - -/****************************************************************************** - * - * WRITE TO MEMORY - * - * - * Request the D0 or D1 pointers to be loaded to other - * modules through the bus - * - * - * - * - *****************************************************************************/ - -reg [0:0] write_done; -reg [1:0] extra_cycles; - -wire [0:0] read_done; -wire [0:0] read_done_t; -wire [0:0] setup_load_dp_read; -wire [0:0] setup_load_dp_write; -wire [0:0] setup_load_dp; -wire [0:0] no_extra_cycles; -wire [1:0] cycles_to_go; - -assign read_done_t = is_mem_read && do_alu_save && ((f_cur +1) == f_last); -assign read_done = (phase == 3) && i_stalled && is_mem_read && !do_alu_save && (f_cur == f_last); -assign setup_load_dp_read = do_alu_init && is_mem_read && !read_done; -assign setup_load_dp_write = do_alu_init && is_mem_write && !write_done; -assign setup_load_dp = setup_load_dp_read || setup_load_dp_write; -assign no_extra_cycles = (extra_cycles == 0); -assign cycles_to_go = extra_cycles - 1; - - reg [3:0] _f; - reg [3:0] _l; +// assign read_done_t = is_mem_read && do_alu_save && ((f_cur +1) == f_last); +// assign read_done = (phase == 3) && i_stalled && is_mem_read && !do_alu_save && (f_cur == f_last); +// assign setup_load_dp_read = do_alu_init && is_mem_read && !read_done; +// assign setup_load_dp_write = do_alu_init && is_mem_write && !write_done; +// assign setup_load_dp = setup_load_dp_read || setup_load_dp_write; +// assign no_extra_cycles = (extra_cycles == 0); +// assign cycles_to_go = extra_cycles - 1; /***************************************************************************** * @@ -1428,174 +1574,30 @@ assign cycles_to_go = extra_cycles - 1; * ****************************************************************************/ -wire is_bus_config; -assign is_bus_config = (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR); -wire send_config; -assign send_config = alu_active && (phase == 1) && i_ins_alu_op && alu_run && alu_finish; -wire clean_after_config; -assign clean_after_config = alu_active && (phase == 3) && o_bus_config && !alu_run; +// wire is_bus_config; +// assign is_bus_config = (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR); +// wire send_config; +// assign send_config = alu_active && (phase == 1) && i_ins_alu_op && alu_run && alu_finish; +// wire clean_after_config; +// assign clean_after_config = alu_active && (phase == 3) && o_bus_config && !alu_run; -always @(posedge i_clk) begin - if (i_reset) - o_bus_config <= 0; +// always @(posedge i_clk) begin +// if (i_reset) +// o_bus_config <= 0; - // $display("send_config %b | is_bus_cfg %b | i_ins_cfg %b", send_config, is_bus_config, i_ins_config); - if (send_config && is_bus_config && i_ins_config) begin - $display("ALU %0d - =========================== ALU start configure mode", phase); - o_bus_config <= 1; - end +// // $display("send_config %b | is_bus_cfg %b | i_ins_cfg %b", send_config, is_bus_config, i_ins_config); +// if (send_config && is_bus_config && i_ins_config) begin +// $display("ALU %0d - =========================== ALU start configure mode", phase); +// o_bus_config <= 1; +// end - if (clean_after_config) begin - $display("ALU %0d - --------------------------- ALU end configure mode %b", phase, i_stalled); - o_bus_config <= 0; - end +// if (clean_after_config) begin +// $display("ALU %0d - --------------------------- ALU end configure mode %b", phase, i_stalled); +// o_bus_config <= 0; +// end -end - -/***************************************************************************** - * - * Handles all changes to PC - * - ****************************************************************************/ - -wire [19:0] next_pc; -wire [19:0] goyes_off; -wire [19:0] goyes_pc; - -wire [0:0] is_jmp_rel2; -wire [0:0] is_rtn_rel2; -wire [0:0] jmp_carry_test; -wire [0:0] exec_rtn_rel2; -wire [0:0] set_jmp_rel2; -wire [0:0] exec_jmp_rel2; - -wire [0:0] update_pc; -wire [0:0] set_unc_jmp; -wire [0:0] exec_unc_jmp; -wire [0:0] exec_unc_rtn; -wire [0:0] pop_pc; -wire [0:0] reload_pc; -wire [0:0] push_pc; - - -assign goyes_off = {{12{i_imm_value[3]}}, i_imm_value, jump_off[3:0]}; -assign goyes_pc = jump_bse + goyes_off; -// rtnyes is already handled by i_ins_test_go -assign is_rtn_rel2 = (alu_op == `ALU_OP_JMP_REL2) && (goyes_off == 0); -assign is_jmp_rel2 = (alu_op == `ALU_OP_JMP_REL2) && !(goyes_off == 0); -assign jmp_carry_test = (i_test_carry && (CARRY == i_carry_val)); -assign exec_rtn_rel2 = is_rtn_rel2 && jmp_carry_test && alu_done; -assign set_jmp_rel2 = is_jmp_rel2 && jmp_carry_test && alu_finish; -assign exec_jmp_rel2 = is_jmp_rel2 && jmp_carry_test && alu_done; - - -assign set_unc_jmp = is_alu_op_unc_jump && alu_finish; -assign exec_unc_jmp = is_alu_op_unc_jump && alu_done; -assign exec_unc_rtn = i_pop && i_ins_rtn; - -assign pop_pc = i_pop && i_ins_rtn && - ((!i_ins_test_go) || - (i_ins_test_go && CARRY)); - -assign next_pc = (set_unc_jmp || set_jmp_rel2)?jump_pc:PC + 1; -assign update_pc = !o_alu_stall_dec || exec_unc_jmp || exec_jmp_rel2 || just_reset; -assign reload_pc = (exec_unc_jmp || pop_pc || just_reset || exec_jmp_rel2); -assign push_pc = update_pc && i_push && alu_finish; - -always @(posedge i_clk) begin - - /* - * initializes the PC - * - */ - - if (i_reset) begin - PC <= ~0; - o_bus_load_pc <= 0; - rstk_ptr <= 0; - end - - /* - * Similarly to the data registers, - * initializes the RSTK while the PC is first loaded - * - */ - if (alu_initializing) - RSTK[f_cur[2:0]] <= 0; - - - // necessary for the write to memory above - // otherwise we get a conflict on o_bus_address - // if (setup_load_dp) - // case (mem_reg[0]) - // 0: o_bus_address <= D0; - // 1: o_bus_address <= D1; - // endcase - - // this is moved here for access conflicts to o_bus_address - if (do_alu_save && (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR)) begin - o_bus_address[f_cur*4+:4] <= c_res1; - end - - /** - * - * Update the PC. - * Request the new PC be loaded to the other modules through - * the bus if necessary - * - */ - - if (do_alu_pc) begin - // $display("DO ALU PC"); -`ifdef SIM - if (alu_debug_pc) - $display({"ALU_PC 3: !stl %b | nx %5h | done %b | fin %b | ", - "uncjmp %b | ins_rtn %b | push %b | imm %h | ", - "c_test %b | jmpr2 %b | rtn[n]c %b |", - "j_bs %h | go_off %h | go_pc %h | update %b | PC <= %h"}, - !o_alu_stall_dec, next_pc, alu_done, alu_finish, - is_alu_op_unc_jump, i_ins_rtn, i_push, i_imm_value, - jmp_carry_test, exec_jmp_rel2, exec_rtn_rel2, - jump_bse, goyes_off, goyes_pc, update_pc, pop_pc ? RSTK[rstk_ptr - 1] : next_pc); -`endif - - // this may do wierd things with C=RSTK... - if (update_pc) begin - PC <= pop_pc ? RSTK[rstk_ptr - 1] : next_pc; - end - - if (reload_pc) begin - // $display("ALU_PC 3: $$$$ RELOADING PC $$$$"); - o_bus_address <= pop_pc ? RSTK[rstk_ptr-1] : next_pc; - o_bus_load_pc <= 1; - end - - // $display("pop %b && rtn %b && ((!go %b) || (go %b && c %b))", - // i_pop, i_ins_rtn, !i_ins_test_go, i_ins_test_go, c_carry); - if (pop_pc) begin - $display("POP RSTK[%0d] to PC %5h", rstk_ptr-1, RSTK[rstk_ptr - 1]); - RSTK[rstk_ptr - 1] <= 0; - rstk_ptr <= rstk_ptr - 1; - end - - if (push_pc) begin - $display("PUSH PC %5h to RSTK[%0d]", PC, rstk_ptr); - RSTK[rstk_ptr] <= PC; - rstk_ptr <= rstk_ptr + 1; - end - end - - /* - * - * Deactivate the load_pc or load_dp enables on the next clock - * - */ - - if (do_busclean && o_bus_load_pc) - o_bus_load_pc <= 0; - -end +// end /***************************************************************************** * @@ -1603,16 +1605,16 @@ end * ****************************************************************************/ -always @(posedge i_clk) begin - if (i_reset) - DEC <= 0; +// always @(posedge i_clk) begin +// if (i_reset) +// DEC <= 0; - // changing calculation modes - if (do_alu_mode) begin - $display("SETTING MODE TO %s", i_mode_dec?"DEC":"HEX"); - DEC <= i_mode_dec; - end -end +// // changing calculation modes +// if (do_alu_mode) begin +// $display("SETTING MODE TO %s", i_mode_dec?"DEC":"HEX"); +// DEC <= i_mode_dec; +// end +// end endmodule diff --git a/saturn_bus_ctrl.v b/saturn_bus_ctrl.v index ddd0da8..7ddff1f 100644 --- a/saturn_bus_ctrl.v +++ b/saturn_bus_ctrl.v @@ -220,6 +220,13 @@ assign do_READ_PC_TST = !i_alu_busy && LC_pc_read; assign do_READ_PC_0 = phase_1 && do_READ_PC_TST; assign do_READ_PC_STR = do_READ_PC_TST; +/* + * common to both reading and writing to the dp pointer + */ + +wire [0:0] xfr_done; +assign xfr_done = (o_data_ptr == (i_xfr_cnt + 1)); + /* * read from the DP pointer */ @@ -260,7 +267,7 @@ assign cmd_DP_WRITE_0 = phase_0 && cmd_DP_WRITE_TST; // sets cmd_DP_WRITE_F0 assign cmd_DP_WRITE_STR = cmd_DP_WRITE_0; assign cmd_DP_WRITE_US0 = phase_2 && cmd_DP_WRITE_F0 && !cmd_DP_WRITE_F1 && o_stall_alu; // after all nibbles were sent -assign cmd_DP_WRITE_1 = phase_3 && (o_data_ptr == (i_xfr_cnt + 1)) && cmd_DP_WRITE_F0 && !cmd_DP_WRITE_F1; // sets cmd_DP_WRITE_F1 +assign cmd_DP_WRITE_1 = phase_3 && xfr_done && cmd_DP_WRITE_F0 && !cmd_DP_WRITE_F1; // sets cmd_DP_WRITE_F1 assign cmd_DP_WRITE_US1 = phase_2 && cmd_DP_WRITE_F1; assign cmd_DP_WRITE_C = phase_3 && cmd_DP_WRITE_F1; @@ -268,7 +275,7 @@ assign cmd_DP_WRITE_C = phase_3 && cmd_DP_WRITE_F1; wire [0:0] do_WRITE_DP_TST; wire [0:0] do_WRITE_DP_0; wire [0:0] do_WRITE_DP_STR; -assign do_WRITE_DP_TST = !o_stall_alu && i_cmd_dp_write && LC_dp_write; +assign do_WRITE_DP_TST = !o_stall_alu && i_cmd_dp_write && LC_dp_write && !xfr_done; assign do_WRITE_DP_STR = phase_0 && do_WRITE_DP_TST; assign do_WRITE_DP_0 = phase_0 && do_WRITE_DP_TST; diff --git a/saturn_core.v b/saturn_core.v index c3c8a87..618358a 100644 --- a/saturn_core.v +++ b/saturn_core.v @@ -484,7 +484,7 @@ saturn_core saturn ( .o_phase (core_phase) ); -test_rom rom ( +saturn_test_rom rom ( .i_phase (core_phase), .i_reset (core_bus_reset), diff --git a/saturn_decoder_registers.v b/saturn_decoder_registers.v index aa6dc00..e57cacc 100644 --- a/saturn_decoder_registers.v +++ b/saturn_decoder_registers.v @@ -196,7 +196,7 @@ always @(posedge i_clk) begin if (do_block_80Cx) begin o_reg_dest <= `ALU_REG_C; o_reg_src1 <= `ALU_REG_P; - o_reg_src2 <= 0; + o_reg_src2 <= `ALU_REG_NOPE; end if (do_block_81Af0x) begin diff --git a/saturn_test_rom.v b/saturn_test_rom.v index 024ede4..fd67445 100644 --- a/saturn_test_rom.v +++ b/saturn_test_rom.v @@ -21,13 +21,15 @@ `ifndef _SATURN_TEST_ROM `define _SATURN_TEST_ROM +`include "def-buscmd.v" + /****************************************************************************** * * test rom * ****************************************************************************/ -module test_rom ( +module saturn_test_rom ( i_phase, i_reset, @@ -72,8 +74,8 @@ assign s_dp_read = (last_bus_cmd == `BUSCMD_DP_READ); assign s_dp_write = (last_bus_cmd == `BUSCMD_DP_WRITE); initial begin -// $readmemh("rom-gx-r.hex", rom, 0, 2**`ROMBITS-1); - $readmemh("testrom-2.hex", rom, 0, 2**`ROMBITS-1); + $readmemh("rom-gx-r.hex", rom, 0, 2**`ROMBITS-1); +// $readmemh("testrom-2.hex", rom, 0, 2**`ROMBITS-1); // $monitor("rst %b | strb %b | c/d %b | bus_i %h | bus_o %h | last %h | slpc %b | addr_c %0d | lpc %5h | ldp %5h", // i_reset, i_bus_strobe, i_bus_cmd_data, i_bus_data_in, o_bus_data_out, // last_bus_cmd, s_load_pc, addr_c, local_pc, local_dp);