Fix step timing, rewrite jtag to include explicit reset

This commit is contained in:
Matthew 2024-06-17 10:51:22 -05:00
parent 7dd0182407
commit 5c593c3321
7 changed files with 152 additions and 167 deletions

View File

@ -42,105 +42,99 @@ def prog_buff_test(cvw):
print() print()
def flow_control_test(): def flow_control_test(cvw):
with OpenOCD() as cvw: #time.sleep(70) # wait for OpenSBI
cvw.reset_dm()
cvw.reset_hart()
cvw.halt() cvw.halt()
cvw.read_data("DCSR") cvw.read_data("DCSR")
for _ in range(50): for _ in range(50):
cvw.step() cvw.step()
print(cvw.read_data("PCM")) print(cvw.read_data("PCM"))
cvw.resume() cvw.resume()
def register_rw_test(): def register_rw_test(cvw):
with OpenOCD() as cvw: registers = dict.fromkeys(cvw.register_translations.keys(),[])
registers = dict.fromkeys(cvw.register_translations.keys(),[]) reg_addrs = list(registers.keys())
reg_addrs = list(registers.keys())
global XLEN global XLEN
XLEN = cvw.LLEN XLEN = cvw.LLEN
global nonstandard_register_lengths global nonstandard_register_lengths
nonstandard_register_lengths = cvw.nonstandard_register_lengths nonstandard_register_lengths = cvw.nonstandard_register_lengths
cvw.reset_dm() #time.sleep(70) # wait for OpenSBI
cvw.reset_hart()
#time.sleep(70) # wait for OpenSBI cvw.halt()
cvw.halt() # dump data in all registers
for r in reg_addrs:
# dump data in all registers try:
for r in reg_addrs: data = cvw.read_data(r)
try: registers[r] = data
data = cvw.read_data(r) print(f"{r}: {data}")
registers[r] = data except Exception as e:
print(f"{r}: {data}") if e.args[0] == "exception": # Invalid register (not implemented)
except Exception as e: del registers[r]
if e.args[0] == "exception": # Invalid register (not implemented) cvw.clear_abstrcmd_err()
del registers[r]
cvw.clear_abstrcmd_err()
else:
raise e
input("Compare values to ILA, press any key to continue")
# Write random data to all registers
reg_addrs = list(registers.keys())
if random_order:
random.shuffle(reg_addrs)
test_reg_data = {}
for r in reg_addrs:
test_data = random_hex(r)
try:
cvw.write_data(r, test_data)
test_reg_data[r] = test_data
print(f"Writing {test_data} to {r}")
except Exception as e:
if e.args[0] == "not supported": # Register is read only
del registers[r]
cvw.clear_abstrcmd_err()
else:
raise e
# GPR X0 is always 0
test_reg_data["x0"] = "0x" + "0"*(cvw.LLEN//4)
# Confirm data was written correctly
reg_addrs = list(registers.keys())
if random_order:
random.shuffle(reg_addrs)
for r in reg_addrs:
try:
rdata = cvw.read_data(r)
except Exception as e:
raise e
if rdata != test_reg_data[r]:
print(f"Error: register {r} read did not return correct data: {rdata} != {test_reg_data[r]}")
else: else:
print(f"Reading {rdata} from {r}") raise e
input("Compare values to ILA, press any key to continue")
# Return all registers to original state # Write random data to all registers
reg_addrs = list(registers.keys()) reg_addrs = list(registers.keys())
for r in reg_addrs: if random_order:
print(f"Writing {registers[r]} to {r}") random.shuffle(reg_addrs)
try: test_reg_data = {}
cvw.write_data(r, registers[r]) for r in reg_addrs:
except Exception as e: test_data = random_hex(r)
try:
cvw.write_data(r, test_data)
test_reg_data[r] = test_data
print(f"Writing {test_data} to {r}")
except Exception as e:
if e.args[0] == "not supported": # Register is read only
del registers[r]
cvw.clear_abstrcmd_err()
else:
raise e raise e
# Confirm data was written correctly # GPR X0 is always 0
for r in reg_addrs: test_reg_data["x0"] = "0x" + "0"*(cvw.LLEN//4)
try:
rdata = cvw.read_data(r)
except Exception as e:
raise e
if rdata != registers[r]:
raise Exception(f"Register {r} read did not return correct data: {rdata} != {registers[r]}")
print("All writes successful")
cvw.resume() # Confirm data was written correctly
reg_addrs = list(registers.keys())
if random_order:
random.shuffle(reg_addrs)
for r in reg_addrs:
try:
rdata = cvw.read_data(r)
except Exception as e:
raise e
if rdata != test_reg_data[r]:
print(f"Error: register {r} read did not return correct data: {rdata} != {test_reg_data[r]}")
else:
print(f"Reading {rdata} from {r}")
# Return all registers to original state
reg_addrs = list(registers.keys())
for r in reg_addrs:
print(f"Writing {registers[r]} to {r}")
try:
cvw.write_data(r, registers[r])
except Exception as e:
raise e
# Confirm data was written correctly
for r in reg_addrs:
try:
rdata = cvw.read_data(r)
except Exception as e:
raise e
if rdata != registers[r]:
raise Exception(f"Register {r} read did not return correct data: {rdata} != {registers[r]}")
print("All writes successful")
cvw.resume()
def random_hex(reg_name): def random_hex(reg_name):
@ -160,8 +154,11 @@ def random_hex(reg_name):
with OpenOCD() as cvw: with OpenOCD() as cvw:
print(cvw.read_dmi("0x16"))
cvw.trst()
cvw.reset_dm() cvw.reset_dm()
cvw.reset_hart() cvw.reset_hart()
#register_rw_test() quit()
#flow_control_test() #register_rw_test(cvw)
prog_buff_test(cvw) flow_control_test(cvw)
#prog_buff_test(cvw)

View File

@ -98,7 +98,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
// [0] = 1 // [0] = 1
localparam JTAG_DEVICE_ID = 32'h1002AC05; localparam JTAG_DEVICE_ID = 32'h1002AC05;
dtm #(`ADDR_WIDTH, JTAG_DEVICE_ID) dtm (.clk, .tck, .tdi, .tms, .tdo, dtm #(`ADDR_WIDTH, JTAG_DEVICE_ID) dtm (.clk, .rst, .tck, .tdi, .tms, .tdo,
.ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady, .ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady,
.RspValid, .RspData, .RspOP); .RspValid, .RspData, .RspOP);
@ -253,7 +253,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
{2'bx,`HARTINFO}, {2'bx,`HARTINFO},
{2'bx,`ABSTRACTAUTO}, {2'bx,`ABSTRACTAUTO},
{2'bx,`NEXTDM} : State <= READ_ZERO; {2'bx,`NEXTDM} : State <= READ_ZERO;
default : State <= INVALID; default : State <= READ_ZERO;//INVALID;
endcase endcase
end end
@ -388,7 +388,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
end end
INVALID : begin INVALID : begin
RspOP <= `OP_FAILED; RspOP <= `OP_SUCCESS;//`OP_FAILED;
State <= ACK; State <= ACK;
end end
endcase endcase

View File

@ -65,7 +65,7 @@ module dmc (
assign DebugMode = (State != RUNNING); assign DebugMode = (State != RUNNING);
assign DebugStall = (State == HALTED); assign DebugStall = (State == HALTED);
assign EnterDebugMode = (State == FLUSH) & (Counter == 0); assign EnterDebugMode = (State == FLUSH) & ~|Counter;
assign ExitDebugMode = (State == HALTED) & ResumeReq; assign ExitDebugMode = (State == HALTED) & ResumeReq;
assign ForceNOP = (State == FLUSH); assign ForceNOP = (State == FLUSH);
@ -77,7 +77,7 @@ module dmc (
case (State) case (State)
RUNNING : begin RUNNING : begin
if (HaltReq) begin if (HaltReq) begin
Counter <= 0; Counter <= NOP_CYCLE_DURATION;
State <= FLUSH; State <= FLUSH;
DebugCause <= `CAUSE_HALTREQ; DebugCause <= `CAUSE_HALTREQ;
end end
@ -87,25 +87,22 @@ module dmc (
// fill the pipe with NOP before halting // fill the pipe with NOP before halting
FLUSH : begin FLUSH : begin
if (Counter == NOP_CYCLE_DURATION) if (~|Counter)
State <= HALTED; State <= HALTED;
else else
Counter <= Counter + 1; Counter <= Counter - 1;
end end
HALTED : begin HALTED : begin
if (ResumeReq) if (ResumeReq) begin
State <= RESUME; if (Step) begin
end Counter <= NOP_CYCLE_DURATION;
State <= FLUSH;
RESUME : begin DebugCause <= `CAUSE_STEP;
if (Step) begin end else begin
Counter <= 0; State <= RUNNING;
State <= FLUSH; ResumeAck <= 1;
DebugCause <= `CAUSE_STEP; end
end else begin
State <= RUNNING;
ResumeAck <= 1;
end end
end end
endcase endcase

View File

@ -31,7 +31,7 @@
module dtm #(parameter ADDR_WIDTH, parameter JTAG_DEVICE_ID) ( module dtm #(parameter ADDR_WIDTH, parameter JTAG_DEVICE_ID) (
// System clock // System clock
input logic clk, input logic clk, rst,
// External JTAG signals // External JTAG signals
input logic tck, input logic tck,
input logic tdi, input logic tdi,
@ -90,7 +90,7 @@ module dtm #(parameter ADDR_WIDTH, parameter JTAG_DEVICE_ID) (
// DTMCS // DTMCS
assign DtmcsOut = {11'b0, ErrInfo, 3'b0, Idle, DmiStat, ABits, Version}; assign DtmcsOut = {11'b0, ErrInfo, 3'b0, Idle, DmiStat, ABits, Version};
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
if (~resetn | DtmHardReset) begin if (rst | ~resetn | DtmHardReset) begin
DtmHardReset <= 0; DtmHardReset <= 0;
DmiReset <= 0; DmiReset <= 0;
end else if (UpdateDtmcs) begin end else if (UpdateDtmcs) begin
@ -103,7 +103,7 @@ module dtm #(parameter ADDR_WIDTH, parameter JTAG_DEVICE_ID) (
// DMI // DMI
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
if (~resetn | DtmHardReset) begin if (rst | ~resetn | DtmHardReset) begin
ValRspData <= 0; ValRspData <= 0;
ValRspOP <= `OP_SUCCESS; ValRspOP <= `OP_SUCCESS;
//ErrInfo <= 4; //ErrInfo <= 4;

View File

@ -48,15 +48,10 @@ module ir (
assign tdo = shift_reg[0]; assign tdo = shift_reg[0];
// Shift register // Shift register
always @(posedge clockIR) begin flop #(1) shift_regmsb (.clk(clockIR), .d(shift_reg[1] | captureIR), .q(shift_reg[0]));
shift_reg[0] <= shift_reg[1] | captureIR;
end
genvar i; genvar i;
for (i = INST_REG_WIDTH; i > 1; i = i - 1) begin for (i = INST_REG_WIDTH; i > 1; i = i - 1)
always @(posedge clockIR) begin flop #(1) shift_reg (.clk(clockIR), .d(shift_reg[i] & ~captureIR), .q(shift_reg[i-1]));
shift_reg[i-1] <= shift_reg[i] & ~captureIR;
end
end
// Instruction decoder // Instruction decoder
// 6.1.2 // 6.1.2

View File

@ -26,6 +26,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module jtag #(parameter ADDR_WIDTH, parameter DEVICE_ID) ( module jtag #(parameter ADDR_WIDTH, parameter DEVICE_ID) (
input logic rst,
// JTAG signals // JTAG signals
input logic tck, input logic tck,
input logic tdi, input logic tdi,
@ -79,7 +80,7 @@ module jtag #(parameter ADDR_WIDTH, parameter DEVICE_ID) (
assign CaptureDmi = captureDR & DmiInstr; assign CaptureDmi = captureDR & DmiInstr;
assign UpdateDmi = updateDR & DmiInstr; assign UpdateDmi = updateDR & DmiInstr;
tap tap (.tck, .tms, .resetn, .tdo_en, .captureIR, tap tap (.rst, .tck, .tms, .resetn, .tdo_en, .captureIR,
.clockIR, .updateIR, .shiftDR, .captureDR, .clockDR, .updateDR, .select); .clockIR, .updateIR, .shiftDR, .captureDR, .clockDR, .updateDR, .select);
// IR/DR input demux // IR/DR input demux
@ -103,34 +104,23 @@ module jtag #(parameter ADDR_WIDTH, parameter DEVICE_ID) (
endcase endcase
end end
always_ff @(posedge UpdateDtmcs) flopr #(32) dtmcsreg (.clk(UpdateDtmcs), .reset(rst), .d(DtmcsShiftReg[31:0]), .q(DtmcsIn));
DtmcsIn <= DtmcsShiftReg[31:0]; flopr #(34+ADDR_WIDTH) dmireg (.clk(UpdateDmi), .reset(rst), .d(DmiShiftReg[34+ADDR_WIDTH-1:0]), .q(DmiIn));
always_ff @(posedge UpdateDmi)
DmiIn <= DmiShiftReg[34+ADDR_WIDTH-1:0];
assign DtmcsShiftReg[32] = tdi_dr; assign DtmcsShiftReg[32] = tdi_dr;
assign tdo_dtmcs = DtmcsShiftReg[0]; assign tdo_dtmcs = DtmcsShiftReg[0];
for (i = 0; i < 32; i = i + 1) begin for (i = 0; i < 32; i = i + 1)
always_ff @(posedge clockDR) begin flopr #(1) dtmcsshiftreg (.clk(clockDR), .reset(rst), .d(captureDR ? DtmcsOut[i] : DtmcsShiftReg[i+1]), .q(DtmcsShiftReg[i]));
DtmcsShiftReg[i] <= captureDR ? DtmcsOut[i] : DtmcsShiftReg[i+1];
end
end
assign DmiShiftReg[34+ADDR_WIDTH] = tdi_dr; assign DmiShiftReg[34+ADDR_WIDTH] = tdi_dr;
assign tdo_dmi = DmiShiftReg[0]; assign tdo_dmi = DmiShiftReg[0];
for (i = 0; i < 34+ADDR_WIDTH; i = i + 1) begin for (i = 0; i < 34+ADDR_WIDTH; i = i + 1)
always_ff @(posedge clockDR) begin flopr #(1) dmishiftreg (.clk(clockDR), .reset(rst), .d(captureDR ? DmiOut[i] : DmiShiftReg[i+1]), .q(DmiShiftReg[i]));
DmiShiftReg[i] <= captureDR ? DmiOut[i] : DmiShiftReg[i+1];
end
end
// jtag id register // jtag id register
idreg #(DEVICE_ID) id (.tdi(tdi_dr), .clockDR, .captureDR, .tdo(tdo_idcode)); idreg #(DEVICE_ID) id (.tdi(tdi_dr), .clockDR, .captureDR, .tdo(tdo_idcode));
// bypass register // bypass register
always_ff @(posedge clockDR) begin flopr #(1) bypassreg (.clk(clockDR), .reset(rst), .d(tdi_dr & shiftDR), .q(tdo_bypass));
tdo_bypass <= tdi_dr & shiftDR;
end
endmodule endmodule

View File

@ -26,6 +26,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module tap ( module tap (
input logic rst,
input logic tck, input logic tck,
input logic tms, input logic tms,
output logic resetn, output logic resetn,
@ -40,6 +41,8 @@ module tap (
output logic select output logic select
); );
logic tckn;
enum logic [3:0] { enum logic [3:0] {
Exit2DR = 4'h0, Exit2DR = 4'h0,
Exit1DR = 4'h1, Exit1DR = 4'h1,
@ -59,36 +62,39 @@ module tap (
TLReset = 4'hF TLReset = 4'hF
} State; } State;
always @(posedge tck) begin always @(posedge rst, posedge tck) begin
case (State) if (rst)
TLReset : State <= tms ? TLReset : RunTestIdle; State <= TLReset;
RunTestIdle : State <= tms ? SelectDR : RunTestIdle; else
SelectDR : State <= tms ? SelectIR : CaptureDR; case (State)
CaptureDR : State <= tms ? Exit1DR : ShiftDR; TLReset : State <= tms ? TLReset : RunTestIdle;
ShiftDR : State <= tms ? Exit1DR : ShiftDR; RunTestIdle : State <= tms ? SelectDR : RunTestIdle;
Exit1DR : State <= tms ? UpdateDR : PauseDR; SelectDR : State <= tms ? SelectIR : CaptureDR;
PauseDR : State <= tms ? Exit2DR : PauseDR; CaptureDR : State <= tms ? Exit1DR : ShiftDR;
Exit2DR : State <= tms ? UpdateDR : ShiftDR; ShiftDR : State <= tms ? Exit1DR : ShiftDR;
UpdateDR : State <= tms ? SelectDR : RunTestIdle; Exit1DR : State <= tms ? UpdateDR : PauseDR;
SelectIR : State <= tms ? TLReset : CaptureIR; PauseDR : State <= tms ? Exit2DR : PauseDR;
CaptureIR : State <= tms ? Exit1IR : ShiftIR; Exit2DR : State <= tms ? UpdateDR : ShiftDR;
ShiftIR : State <= tms ? Exit1IR : ShiftIR; UpdateDR : State <= tms ? SelectDR : RunTestIdle;
Exit1IR : State <= tms ? UpdateIR : PauseIR; SelectIR : State <= tms ? TLReset : CaptureIR;
PauseIR : State <= tms ? Exit2IR : PauseIR; CaptureIR : State <= tms ? Exit1IR : ShiftIR;
Exit2IR : State <= tms ? UpdateIR : ShiftIR; ShiftIR : State <= tms ? Exit1IR : ShiftIR;
UpdateIR : State <= tms ? SelectDR : RunTestIdle; Exit1IR : State <= tms ? UpdateIR : PauseIR;
endcase PauseIR : State <= tms ? Exit2IR : PauseIR;
Exit2IR : State <= tms ? UpdateIR : ShiftIR;
UpdateIR : State <= tms ? SelectDR : RunTestIdle;
endcase
end end
assign tckn = ~tck;
always @(negedge tck) begin flopr #(1) resetnreg (.clk(tckn), .reset(rst), .d(~(State == TLReset)), .q(resetn));
resetn <= ~(State == TLReset); flopr #(1) tdo_enreg (.clk(tckn), .reset(rst), .d(State == ShiftIR | State == ShiftDR), .q(tdo_en));
tdo_en <= State == ShiftIR | State == ShiftDR; flopr #(1) captureIRreg (.clk(tckn), .reset(rst), .d(State == CaptureIR), .q(captureIR));
captureIR <= State == CaptureIR; flopr #(1) updateIRreg (.clk(tckn), .reset(rst), .d(State == UpdateIR), .q(updateIR));
updateIR <= State == UpdateIR; flopr #(1) shiftDRreg (.clk(tckn), .reset(rst), .d(State == ShiftDR), .q(shiftDR));
shiftDR <= State == ShiftDR; flopr #(1) captureDRreg (.clk(tckn), .reset(rst), .d(State == CaptureDR), .q(captureDR));
captureDR <= State == CaptureDR; flopr #(1) updateDRreg (.clk(tckn), .reset(rst), .d(State == UpdateDR), .q(updateDR));
updateDR <= State == UpdateDR;
end
assign clockIR = tck | State[0] | ~State[1] | ~State[3]; assign clockIR = tck | State[0] | ~State[1] | ~State[3];
assign clockDR = tck | State[0] | ~State[1] | State[3]; assign clockDR = tck | State[0] | ~State[1] | State[3];