mirror of
https://github.com/sxpert/hp-saturn
synced 2025-01-28 07:58:38 +01:00
44ca0f4a15
implement exch in ALU fix jump base calculations correct some things in debugger fix fields and registers for some instructions
261 lines
8.6 KiB
Verilog
261 lines
8.6 KiB
Verilog
|
|
/*
|
|
* debugger
|
|
*
|
|
*/
|
|
|
|
wire [19:0] new_pc;
|
|
assign new_pc = i_pc + 1;
|
|
|
|
wire run_debugger;
|
|
assign run_debugger = !i_reset && i_en_dbg && !i_stalled && !next_nibble;
|
|
|
|
wire is_short_transfer;
|
|
assign is_short_transfer = (o_field_last == 3) &&
|
|
((o_reg_dest[4:1] == 4'b0010) || (o_reg_src1[4:1] == 4'b0010));
|
|
|
|
wire p_is_dest;
|
|
wire is_load_imm;
|
|
wire is_d0_eq;
|
|
wire is_d1_eq;
|
|
wire is_p_eq;
|
|
wire is_la_hex;
|
|
wire is_lc_hex;
|
|
wire disp_nb_nibbles;
|
|
assign p_is_dest = (o_reg_dest == `ALU_REG_P);
|
|
assign is_load_imm = ((o_alu_op == `ALU_OP_COPY) ||
|
|
(o_alu_op == `ALU_OP_RST_BIT) ||
|
|
(o_alu_op == `ALU_OP_SET_BIT) ||
|
|
(o_alu_op == `ALU_OP_JMP_REL3) ||
|
|
(o_alu_op == `ALU_OP_JMP_REL4) ||
|
|
(o_alu_op == `ALU_OP_JMP_ABS5))
|
|
&& (o_reg_src1 == `ALU_REG_IMM);
|
|
assign is_d0_eq = is_load_imm && (o_reg_dest == `ALU_REG_D0);
|
|
assign is_d1_eq = is_load_imm && (o_reg_dest == `ALU_REG_D1);
|
|
assign is_p_eq = is_load_imm && p_is_dest;
|
|
assign is_la_hex = is_load_imm && (o_reg_dest == `ALU_REG_A);
|
|
assign is_lc_hex = is_load_imm && (o_reg_dest == `ALU_REG_C);
|
|
assign disp_nb_nibbles = is_d0_eq || is_d1_eq;
|
|
|
|
reg [4:0] nibble_pos;
|
|
|
|
always @(posedge i_clk) begin
|
|
if (run_debugger) begin
|
|
/*
|
|
* this whole thing is a large print statement
|
|
* THIS PART IS NEVER GENERATED
|
|
*/
|
|
`ifdef SIM
|
|
if (o_ins_decoded) begin
|
|
$write("DBG[%5d]: ", inst_counter);
|
|
$write("%5h ", o_ins_addr);
|
|
|
|
// $write("[%2d] ", o_dbg_nb_nbls);
|
|
|
|
for(nibble_pos=0; nibble_pos!=o_dbg_nb_nbls; nibble_pos=nibble_pos+1)
|
|
$write("%h", o_dbg_nibbles[nibble_pos*4+:4]);
|
|
for(nibble_pos=o_dbg_nb_nbls; nibble_pos!=22; nibble_pos=nibble_pos+1)
|
|
$write(" ");
|
|
|
|
// display decoded instruction
|
|
if (o_ins_rtn) begin
|
|
$write("RT%s", o_en_intr?"I":"N");
|
|
if (o_set_xm) $write("SXM");
|
|
if (o_set_carry) $write("%sC", o_carry_val?"S":"C");
|
|
end
|
|
if (o_ins_set_mode) begin
|
|
$write("SET%s", o_mode_dec?"DEC":"HEX");
|
|
end
|
|
if (o_ins_alu_op) begin
|
|
|
|
// reg dest...
|
|
case (o_alu_op)
|
|
`ALU_OP_JMP_REL3: $write("%s", o_push?"GOSUB":"GOTO");
|
|
`ALU_OP_JMP_REL4: $write("%s", o_push?"GOSUBL":"GOLONG");
|
|
`ALU_OP_JMP_ABS5: $write("%s", o_push?"GOSBVL":"GOVLNG");
|
|
`ALU_OP_CLR_MASK:
|
|
case (o_reg_dest)
|
|
`ALU_REG_HST:
|
|
case (o_imm_value)
|
|
4'h1: $write("XM=0");
|
|
4'h2: $write("SB=0");
|
|
4'h4: $write("SR=0");
|
|
4'h8: $write("MP=0");
|
|
default: begin
|
|
$write("CLRHST");
|
|
if (o_imm_value != 4'hF) $write("\t%1h", o_imm_value);
|
|
end
|
|
endcase
|
|
default: $write("[VLR_MASK dest:%0d]", o_reg_dest);
|
|
endcase
|
|
default:
|
|
case (o_reg_dest)
|
|
`ALU_REG_A: $write("A");
|
|
`ALU_REG_B: $write("B");
|
|
`ALU_REG_C:
|
|
if (is_lc_hex) $write("LCHEX");
|
|
else $write("C");
|
|
`ALU_REG_D: $write("D");
|
|
`ALU_REG_D0: $write("D0");
|
|
`ALU_REG_D1: $write("D1");
|
|
`ALU_REG_RSTK: $write("RSTK");
|
|
`ALU_REG_R0: $write("R0");
|
|
`ALU_REG_R1: $write("R1");
|
|
`ALU_REG_R2: $write("R2");
|
|
`ALU_REG_R3: $write("R3");
|
|
`ALU_REG_R4: $write("R4");
|
|
`ALU_REG_DAT0: $write("DAT0");
|
|
`ALU_REG_DAT1: $write("DAT1");
|
|
`ALU_REG_ST: if (o_alu_op!=`ALU_OP_ZERO) $write("ST");
|
|
`ALU_REG_P: $write("P");
|
|
default: $write("[dest:%0d]", o_reg_dest);
|
|
endcase
|
|
endcase
|
|
|
|
// operation 1
|
|
case (o_alu_op)
|
|
`ALU_OP_ZERO: if (o_reg_dest==`ALU_REG_ST)
|
|
$write("CLRST");
|
|
else $write("=0");
|
|
`ALU_OP_COPY,
|
|
`ALU_OP_AND,
|
|
`ALU_OP_OR,
|
|
`ALU_OP_INC,
|
|
`ALU_OP_DEC,
|
|
`ALU_OP_ADD,
|
|
`ALU_OP_SUB,
|
|
`ALU_OP_RST_BIT,
|
|
`ALU_OP_SET_BIT: if (!is_lc_hex)
|
|
$write("=");
|
|
`ALU_OP_2CMPL: $write("=-");
|
|
`ALU_OP_EXCH,
|
|
`ALU_OP_JMP_REL3,
|
|
`ALU_OP_JMP_REL4,
|
|
`ALU_OP_JMP_ABS5,
|
|
`ALU_OP_CLR_MASK: begin end
|
|
default: $write("[op:%0d]", o_alu_op);
|
|
endcase
|
|
|
|
// src1
|
|
case (o_alu_op)
|
|
`ALU_OP_COPY,
|
|
`ALU_OP_AND,
|
|
`ALU_OP_OR,
|
|
`ALU_OP_INC,
|
|
`ALU_OP_DEC,
|
|
`ALU_OP_ADD,
|
|
`ALU_OP_SUB,
|
|
`ALU_OP_2CMPL:
|
|
case (o_reg_src1)
|
|
`ALU_REG_A: $write("A");
|
|
`ALU_REG_B: $write("B");
|
|
`ALU_REG_C: $write("C");
|
|
`ALU_REG_D: $write("D");
|
|
`ALU_REG_D0: $write("D0");
|
|
`ALU_REG_D1: $write("D1");
|
|
`ALU_REG_RSTK: $write("RSTK");
|
|
`ALU_REG_R0: $write("R0");
|
|
`ALU_REG_R1: $write("R1");
|
|
`ALU_REG_R2: $write("R2");
|
|
`ALU_REG_R3: $write("R3");
|
|
`ALU_REG_R4: $write("R4");
|
|
`ALU_REG_DAT0: $write("DAT0");
|
|
`ALU_REG_DAT1: $write("DAT1");
|
|
`ALU_REG_ST: $write("ST");
|
|
`ALU_REG_P: $write("P");
|
|
`ALU_REG_IMM:
|
|
if (disp_nb_nibbles) $write("(%0d)", o_mem_pos);
|
|
`ALU_REG_ZERO: $write("0");
|
|
default: $write("[src1:%0d]", o_reg_src1);
|
|
endcase
|
|
`ALU_OP_RST_BIT: $write("0");
|
|
`ALU_OP_SET_BIT: $write("1");
|
|
endcase
|
|
// if ((o_alu_op == `ALU_OP_COPY) && is_short_transfer)
|
|
// $write("S");
|
|
|
|
|
|
// SRC2
|
|
case (o_alu_op)
|
|
`ALU_OP_AND,
|
|
`ALU_OP_OR,
|
|
`ALU_OP_ADD,
|
|
`ALU_OP_SUB:
|
|
case (o_alu_op)
|
|
`ALU_OP_AND: $write("&");
|
|
`ALU_OP_OR: $write("!");
|
|
`ALU_OP_ADD: $write("+");
|
|
`ALU_OP_SUB: $write("-");
|
|
default: $write("[op:%0d]", o_alu_op);
|
|
endcase
|
|
endcase
|
|
|
|
case (o_alu_op)
|
|
`ALU_OP_ZERO,
|
|
`ALU_OP_COPY: begin end
|
|
`ALU_OP_EXCH:
|
|
case (o_reg_src2)
|
|
`ALU_REG_A: $write("A");
|
|
`ALU_REG_B: $write("B");
|
|
`ALU_REG_C: $write("C");
|
|
`ALU_REG_D: $write("D");
|
|
`ALU_REG_RSTK: $write("RSTK");
|
|
`ALU_REG_IMM: $write("\t%0d", o_imm_value+1);
|
|
default: $write("[src2:%0d]", o_reg_src2);
|
|
endcase
|
|
`ALU_OP_INC: $write("+1");
|
|
`ALU_OP_DEC: $write("-1");
|
|
endcase
|
|
|
|
if (o_alu_op == `ALU_OP_EXCH)
|
|
$write("%s", is_short_transfer?"XS":"EX");
|
|
|
|
// if (!((o_reg_dest == `ALU_REG_RSTK) || (o_reg_src1 == `ALU_REG_RSTK) ||
|
|
// (o_reg_dest == `ALU_REG_ST) || (o_reg_src1 == `ALU_REG_ST ) ||
|
|
// (o_reg_dest == `ALU_REG_P) || (o_reg_src1 == `ALU_REG_P ))) begin
|
|
$write("\t");
|
|
if (o_field_valid) begin
|
|
|
|
// $write("[FT%d]", o_fields_table);
|
|
if (o_fields_table != `FT_TABLE_value)
|
|
case (o_field)
|
|
`FT_FIELD_P: $write("P");
|
|
`FT_FIELD_WP: $write("WP");
|
|
`FT_FIELD_XS: $write("XS");
|
|
`FT_FIELD_X: $write("X");
|
|
`FT_FIELD_S: $write("S");
|
|
`FT_FIELD_M: $write("M");
|
|
`FT_FIELD_B: $write("B");
|
|
`FT_FIELD_W: $write("W");
|
|
`FT_FIELD_A: $write("A");
|
|
endcase
|
|
else $write("%0d", o_field_last+1);
|
|
end else begin
|
|
// $write("@%b@", is_load_imm);
|
|
if (is_load_imm) begin
|
|
if (is_p_eq) $write("%0d", o_imm_value);
|
|
else
|
|
for(nibble_pos=(o_mem_pos - 1); nibble_pos!=31; nibble_pos=nibble_pos-1)
|
|
$write("%h", o_mem_load[nibble_pos*4+:4]);
|
|
end
|
|
else
|
|
case (o_reg_dest)
|
|
`ALU_REG_P,
|
|
`ALU_REG_ST,
|
|
`ALU_REG_HST: begin end
|
|
`ALU_REG_C:
|
|
if (o_reg_src1 == `ALU_REG_P)
|
|
$write("%0d", o_field_start);
|
|
default: $write("[%h:%h]", o_field_start, o_field_last);
|
|
endcase
|
|
end
|
|
end
|
|
$write("\t(%0d cycles)", inst_cycles);
|
|
if (o_unimplemented)
|
|
$write("\t%C[1,31mUNIMPLEMENTED%C[0m", 27, 27);
|
|
$write("\n");
|
|
end
|
|
// $display("new [%5h]--------------------------------------------------------------------", new_pc);
|
|
`endif
|
|
end
|
|
end
|