Implemented cycle counter and data bus monitoring during read/write watches/breakpoints, incremented version to 0.32

Change-Id: I408f57e66800ea58a56896ec4af5d815d1f12c34
This commit is contained in:
David Banks 2015-06-20 12:30:18 +01:00
parent 643c9b2231
commit 14e4adda94
8 changed files with 179 additions and 105 deletions

Binary file not shown.

View File

@ -67,22 +67,34 @@ unsigned char dopaddr[256] =
#define MUX_DDR DDRE
#define MUX_DIN PINE
// Hardware registers
#define OFFSET_IAL 0
#define OFFSET_IAH 1
#define OFFSET_BW_IAL 2
#define OFFSET_BW_IAH 3
#define OFFSET_BW_BAL 4
#define OFFSET_BW_BAH 5
#define OFFSET_BW_M 6
#define OFFSET_DATA 7
#define OFFSET_REG_A 8
#define OFFSET_REG_X 9
#define OFFSET_REG_Y 10
#define OFFSET_REG_P 11
#define OFFSET_REG_SPL 12
#define OFFSET_REG_SPH 13
#define OFFSET_REG_PCL 14
#define OFFSET_REG_PCH 15
#define OFFSET_DATA 2
#define OFFSET_CNTH 3
#define OFFSET_CNTL 4
#define OFFSET_CNTM 5
// Hardware fifo
#define OFFSET_BW_IAL 6
#define OFFSET_BW_IAH 7
#define OFFSET_BW_BAL 8
#define OFFSET_BW_BAH 9
#define OFFSET_BW_BD 10
#define OFFSET_BW_M 11
#define OFFSET_BW_CNTL 12
#define OFFSET_BW_CNTM 13
#define OFFSET_BW_CNTH 14
// Processor registers
#define OFFSET_REG_A 16
#define OFFSET_REG_X 17
#define OFFSET_REG_Y 18
#define OFFSET_REG_P 19
#define OFFSET_REG_SPL 20
#define OFFSET_REG_SPH 21
#define OFFSET_REG_PCL 22
#define OFFSET_REG_PCH 23
// Commands
// 000x Enable/Disable single strpping
@ -105,7 +117,7 @@ unsigned char dopaddr[256] =
// Control bits
#define CMD_MASK 0x1F
#define CMD_EDGE 0x10
#define MUXSEL_MASK 0x0F
#define MUXSEL_MASK 0x1F
#define MUXSEL_BIT 0
// Status bits
@ -113,24 +125,27 @@ unsigned char dopaddr[256] =
#define BW_ACTIVE_MASK 0x80
// Breakpoint Modes
#define BRKPT_INSTR 0
#define BRKPT_EXEC 0
#define BRKPT_READ 1
#define BRKPT_WRITE 2
#define WATCH_INSTR 3
#define WATCH_EXEC 3
#define WATCH_READ 4
#define WATCH_WRITE 5
#define UNDEFINED 6
#define B_MASK ((1<<BRKPT_READ) | (1<<BRKPT_WRITE) | (1<<BRKPT_EXEC))
#define W_MASK ((1<<WATCH_READ) | (1<<WATCH_WRITE) | (1<<WATCH_EXEC))
#define B_MEM_MASK ((1<<BRKPT_READ) | (1<<BRKPT_WRITE))
#define W_MEM_MASK ((1<<BRKPT_WRITE) | (1<<WATCH_WRITE))
#define BW_MEM_MASK ((1<<BRKPT_READ) | (1<<BRKPT_WRITE) | (1<<WATCH_READ) | (1<<WATCH_WRITE))
char *modeStrings[7] = {
"Instruction breakpoint",
"Read breakpoint",
"Write breakpoint",
"Instruction watch",
"Read watch",
"Write watch",
"Ex Breakpoint",
"Rn Breakpoint",
"Wr Breakpoint",
"Ex watch",
"Rd watch",
"Wr watch",
"Undefined"
};
@ -157,7 +172,7 @@ char *triggerStrings[NUM_TRIGGERS] = {
};
#define VERSION "0.31"
#define VERSION "0.32"
#ifdef EMBEDDED_6502
#define NUM_CMDS 25
@ -530,20 +545,41 @@ void logTrigger(int trigger) {
}
}
void logCycleCount(int offsetLow, int offsetHigh) {
unsigned long count = (((unsigned long) hwRead8(offsetHigh)) << 16) | hwRead16(offsetLow);
unsigned long countSecs = count / 1000000;
unsigned long countMicros = count % 1000000;
log0("%02ld.%06ld: ", countSecs, countMicros);
}
int logDetails() {
unsigned int i_addr = hwRead16(OFFSET_BW_IAL);
unsigned int b_addr = hwRead16(OFFSET_BW_BAL);
unsigned int b_data = hwRead8(OFFSET_BW_BD);
unsigned int mode = hwRead8(OFFSET_BW_M);
unsigned int watch = mode & 8;
// Convert from 4-bit compressed to 6 bit expanded mode representation
if (watch) {
mode = (mode & 7) << 3;
}
// Update the serial console
if (mode & W_MASK) {
logCycleCount(OFFSET_BW_CNTL, OFFSET_BW_CNTH);
}
logMode(mode);
log0(" hit at %04X", i_addr);
if (mode & BW_MEM_MASK) {
log0(" accessing %04X\n", b_addr);
if (mode & W_MEM_MASK) {
log0(" writing");
} else {
log0(" reading");
}
log0(" %04X = %02X\n", b_addr, b_data);
if (mode & B_MASK) {
logCycleCount(OFFSET_BW_CNTL, OFFSET_BW_CNTH);
}
if (mode & B_MEM_MASK) {
// It's only safe to do this for brkpts, as it makes memory accesses
disMem(i_addr);
@ -563,6 +599,7 @@ void logAddr() {
lcdAddr(memAddr);
#endif
// Update the serial console
logCycleCount(OFFSET_CNTL, OFFSET_CNTH);
#ifdef EMBEDDED_6502
//log0("%04X\n", i_addr);
disMem(memAddr);
@ -785,7 +822,7 @@ void doCmdBreak(char *params, unsigned int mode) {
}
void doCmdBreakI(char *params) {
doCmdBreak(params, 1 << BRKPT_INSTR);
doCmdBreak(params, 1 << BRKPT_EXEC);
}
void doCmdBreakR(char *params) {
@ -797,7 +834,7 @@ void doCmdBreakW(char *params) {
}
void doCmdWatchI(char *params) {
doCmdBreak(params, 1 << WATCH_INSTR);
doCmdBreak(params, 1 << WATCH_EXEC);
}
void doCmdWatchR(char *params) {
@ -835,7 +872,7 @@ void doCmdBClear(char *params, unsigned int mode) {
}
void doCmdBClearI(char *params) {
doCmdBClear(params, 1 << BRKPT_INSTR);
doCmdBClear(params, 1 << BRKPT_EXEC);
}
void doCmdBClearR(char *params) {
@ -847,7 +884,7 @@ void doCmdBClearW(char *params) {
}
void doCmdWClearI(char *params) {
doCmdBClear(params, 1 << WATCH_INSTR);
doCmdBClear(params, 1 << WATCH_EXEC);
}
void doCmdWClearR(char *params) {

View File

@ -44,10 +44,10 @@ ENTITY WatchEvents IS
PORT (
clk : IN STD_LOGIC;
srst : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(35 DOWNTO 0);
din : IN STD_LOGIC_VECTOR(71 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(35 DOWNTO 0);
dout : OUT STD_LOGIC_VECTOR(71 DOWNTO 0);
full : OUT STD_LOGIC;
empty : OUT STD_LOGIC
);
@ -59,10 +59,10 @@ COMPONENT wrapped_WatchEvents
PORT (
clk : IN STD_LOGIC;
srst : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(35 DOWNTO 0);
din : IN STD_LOGIC_VECTOR(71 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(35 DOWNTO 0);
dout : OUT STD_LOGIC_VECTOR(71 DOWNTO 0);
full : OUT STD_LOGIC;
empty : OUT STD_LOGIC
);
@ -98,7 +98,7 @@ END COMPONENT;
c_count_type => 0,
c_data_count_width => 10,
c_default_value => "BlankString",
c_din_width => 36,
c_din_width => 72,
c_din_width_axis => 1,
c_din_width_rach => 32,
c_din_width_rdch => 64,
@ -106,7 +106,7 @@ END COMPONENT;
c_din_width_wdch => 64,
c_din_width_wrch => 2,
c_dout_rst_val => "0",
c_dout_width => 36,
c_dout_width => 72,
c_enable_rlocs => 0,
c_enable_rst_sync => 1,
c_error_injection_type => 0,
@ -179,7 +179,7 @@ END COMPONENT;
c_overflow_low => 0,
c_preload_latency => 0,
c_preload_regs => 1,
c_prim_fifo_type => "512x36",
c_prim_fifo_type => "512x72",
c_prog_empty_thresh_assert_val => 4,
c_prog_empty_thresh_assert_val_axis => 1022,
c_prog_empty_thresh_assert_val_rach => 1022,

View File

@ -52,8 +52,8 @@
<!-- -->
<property xil_pn:name="PROP_DesignName" xil_pn:value="WatchEvents" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan3e" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2015-06-11T21:55:14" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="644897288B5B4D69FBBB8BE6A3296EA1" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2015-06-20T07:31:35" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="D9477A1DD499DA00CBCF8BE78B7D99A6" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
</properties>

View File

@ -1,5 +1,5 @@
#!/opt/Xilinx/14.7/ISE_DS/ISE/bin/lin/xtclsh
project open AtomBusMon.xise
project open AtomCpuMon.xise
process run "Generate Programming File"
project close
exit

View File

@ -1,5 +1,5 @@
#!/opt/Xilinx/14.7/ISE_DS/ISE/bin/lin/xtclsh
project open AtomBusMon.xise
project open AtomCpuMon.xise
project clean
project close
exit

View File

@ -103,6 +103,7 @@ begin
mon : entity work.BusMonCore port map (
clock49 => clock49,
Addr => Addr_int,
Data => Data,
Phi2 => busmon_clk,
RNW => R_W_n_int,
Sync => Sync_int,
@ -128,7 +129,7 @@ begin
WrOut => memory_wr,
AddrOut => memory_addr,
DataOut => memory_dout,
DataIn => memory_din
DataIn => memory_din
);
GenT65Core: if UseT65Core generate

View File

@ -26,13 +26,14 @@ entity BusMonCore is
generic (
num_comparators : integer := 8;
reg_width : integer := 42;
fifo_width : integer := 36
fifo_width : integer := 72
);
port (
clock49 : in std_logic;
-- 6502 Signals
Addr : in std_logic_vector(15 downto 0);
Data : in std_logic_vector(7 downto 0);
Phi2 : in std_logic;
RNW : in std_logic;
Sync : in std_logic;
@ -40,9 +41,11 @@ entity BusMonCore is
nRST : inout std_logic;
-- 6502 Registers
-- unused in pure bus monitor mode
Regs : in std_logic_vector(63 downto 0);
-- 6502 Memory Read/Write
-- unused in pure bus monitor mode
RdOut : out std_logic;
WrOut : out std_logic;
AddrOut : out std_logic_vector(15 downto 0);
@ -80,48 +83,56 @@ end BusMonCore;
architecture behavioral of BusMonCore is
signal clock_avr : std_logic;
signal nrst_avr : std_logic;
signal lcd_rw_int : std_logic;
signal lcd_db_in : std_logic_vector(7 downto 4);
signal lcd_db_out : std_logic_vector(7 downto 4);
signal dy_counter : std_logic_vector(31 downto 0);
signal dy_data : y2d_type ;
signal clock_avr : std_logic;
signal nrst_avr : std_logic;
signal lcd_rw_int : std_logic;
signal lcd_db_in : std_logic_vector(7 downto 4);
signal lcd_db_out : std_logic_vector(7 downto 4);
signal dy_counter : std_logic_vector(31 downto 0);
signal dy_data : y2d_type ;
signal mux : std_logic_vector(7 downto 0);
signal muxsel : std_logic_vector(3 downto 0);
signal cmd_edge : std_logic;
signal cmd_edge1 : std_logic;
signal cmd_edge2 : std_logic;
signal cmd : std_logic_vector(3 downto 0);
signal mux : std_logic_vector(7 downto 0);
signal muxsel : std_logic_vector(4 downto 0);
signal cmd_edge : std_logic;
signal cmd_edge1 : std_logic;
signal cmd_edge2 : std_logic;
signal cmd : std_logic_vector(3 downto 0);
signal addr_sync : std_logic_vector(15 downto 0);
signal addr_inst : std_logic_vector(15 downto 0);
signal addr_sync : std_logic_vector(15 downto 0);
signal addr_inst : std_logic_vector(15 downto 0);
signal Addr1 : std_logic_vector(15 downto 0);
signal Data1 : std_logic_vector(7 downto 0);
signal single : std_logic;
signal reset : std_logic;
signal step : std_logic;
signal cycleCount : std_logic_vector(23 downto 0);
signal cycleCount_inst : std_logic_vector(23 downto 0);
signal bw_status : std_logic_vector(fifo_width - 16 - 1 downto 0);
signal bw_status1 : std_logic_vector(fifo_width - 16 - 1 downto 0);
signal single : std_logic;
signal reset : std_logic;
signal step : std_logic;
signal bw_status : std_logic_vector(3 downto 0);
signal bw_status1 : std_logic_vector(3 downto 0);
signal brkpt_reg : std_logic_vector(num_comparators * reg_width - 1 downto 0);
signal brkpt_enable : std_logic;
signal brkpt_active : std_logic;
signal brkpt_active1 : std_logic;
signal watch_active : std_logic;
signal fifo_din : std_logic_vector(fifo_width - 1 downto 0);
signal fifo_dout : std_logic_vector(fifo_width - 1 downto 0);
signal fifo_empty : std_logic;
signal fifo_rd : std_logic;
signal fifo_wr : std_logic;
signal fifo_rst : std_logic;
signal brkpt_reg : std_logic_vector(num_comparators * reg_width - 1 downto 0);
signal brkpt_enable : std_logic;
signal brkpt_active : std_logic;
signal brkpt_active1 : std_logic;
signal watch_active : std_logic;
signal fifo_din : std_logic_vector(fifo_width - 1 downto 0);
signal fifo_dout : std_logic_vector(fifo_width - 1 downto 0);
signal fifo_empty : std_logic;
signal fifo_rd : std_logic;
signal fifo_wr : std_logic;
signal fifo_rst : std_logic;
signal memory_rd : std_logic;
signal memory_wr : std_logic;
signal addr_dout_reg : std_logic_vector(23 downto 0);
signal din_reg : std_logic_vector(7 downto 0);
signal memory_rd : std_logic;
signal memory_wr : std_logic;
signal addr_dout_reg : std_logic_vector(23 downto 0);
signal din_reg : std_logic_vector(7 downto 0);
signal Rdy_int : std_logic;
begin
@ -202,7 +213,7 @@ begin
portdout(1) => muxsel(1),
portdout(2) => muxsel(2),
portdout(3) => muxsel(3),
portdout(4) => open,
portdout(4) => muxsel(4),
portdout(5) => open,
portdout(6) => open,
portdout(7) => open,
@ -230,8 +241,12 @@ begin
empty => fifo_empty
);
fifo_din <= bw_status1 & addr_inst;
-- The fifo is writen the cycle after the break point
-- Addr1 is the address bus delayed by 1 cycle
-- DataWr1 is the data being written delayed by 1 cycle
-- DataRd is the data being read, that is already one cycle late
-- bw_state1(1) is 1 for writes, and 0 for reads
fifo_din <= cycleCount_inst & "0000" & bw_status1 & Data1 & Addr1 & addr_inst;
lcd_rw <= lcd_rw_int;
lcd_db <= lcd_db_out when lcd_rw_int = '0' else (others => 'Z');
@ -250,20 +265,29 @@ begin
mux <= addr_inst(7 downto 0) when muxsel = 0 else
addr_inst(15 downto 8) when muxsel = 1 else
fifo_dout(7 downto 0) when muxsel = 2 else
fifo_dout(15 downto 8) when muxsel = 3 else
fifo_dout(23 downto 16) when muxsel = 4 else
fifo_dout(31 downto 24) when muxsel = 5 else
"0000" & fifo_dout(35 downto 32) when muxsel = 6 else
din_reg when muxsel = 7 else
Regs(7 downto 0) when muxsel = 8 else
Regs(15 downto 8) when muxsel = 9 else
Regs(23 downto 16) when muxsel = 10 else
Regs(31 downto 24) when muxsel = 11 else
Regs(39 downto 32) when muxsel = 12 else
Regs(47 downto 40) when muxsel = 13 else
Regs(55 downto 48) when muxsel = 14 else
Regs(63 downto 56) when muxsel = 15 else
din_reg when muxsel = 2 else
cycleCount(23 downto 16) when muxsel = 3 else
cycleCount(7 downto 0) when muxsel = 4 else
cycleCount(15 downto 8) when muxsel = 5 else
fifo_dout(7 downto 0) when muxsel = 6 else
fifo_dout(15 downto 8) when muxsel = 7 else
fifo_dout(23 downto 16) when muxsel = 8 else
fifo_dout(31 downto 24) when muxsel = 9 else
fifo_dout(39 downto 32) when muxsel = 10 else
fifo_dout(47 downto 40) when muxsel = 11 else
fifo_dout(55 downto 48) when muxsel = 12 else
fifo_dout(63 downto 56) when muxsel = 13 else
fifo_dout(71 downto 64) when muxsel = 14 else
Regs(7 downto 0) when muxsel = 16 else
Regs(15 downto 8) when muxsel = 17 else
Regs(23 downto 16) when muxsel = 18 else
Regs(31 downto 24) when muxsel = 19 else
Regs(39 downto 32) when muxsel = 20 else
Regs(47 downto 40) when muxsel = 21 else
Regs(55 downto 48) when muxsel = 22 else
Regs(63 downto 56) when muxsel = 23 else
"10101010";
-- Combinatorial set of comparators to decode breakpoint/watch addresses
@ -279,12 +303,12 @@ begin
variable reg_mode_waw : std_logic;
variable bactive : std_logic;
variable wactive : std_logic;
variable status : std_logic_vector(19 downto 0);
variable status : std_logic_vector(3 downto 0);
variable trigval : std_logic;
begin
bactive := '0';
wactive := '0';
status := "00001010101010101010";
status := (others => '0');
if (brkpt_enable = '1') then
for i in 0 to num_comparators - 1 loop
reg_addr := brkpt_reg(i * reg_width + 15 downto i * reg_width);
@ -302,30 +326,30 @@ begin
if (Sync = '1') then
if (reg_mode_bi = '1') then
bactive := '1';
status := "0001" & Addr;
status := "0001";
end if;
if (reg_mode_wi = '1') then
wactive := '1';
status := "1001" & Addr;
status := "1001";
end if;
else
if (RNW = '1') then
if (reg_mode_bar = '1') then
bactive := '1';
status := "0010" & Addr;
status := "0010";
end if;
if (reg_mode_war = '1') then
wactive := '1';
status := "1010" & Addr;
status := "1010";
end if;
else
if (reg_mode_baw = '1') then
bactive := '1';
status := "0100" & Addr;
status := "0100";
end if;
if (reg_mode_waw = '1') then
wactive := '1';
status := "1100" & Addr;
status := "1100";
end if;
end if;
end if;
@ -353,6 +377,13 @@ begin
begin
if rising_edge(Phi2) then
-- Cycle counter, wraps every 16s at 1MHz
if (nRST = '0') then
cycleCount <= (others => '0');
elsif (Rdy_int = '1') then
cycleCount <= cycleCount + 1;
end if;
-- Command processing
cmd_edge1 <= cmd_edge;
cmd_edge2 <= cmd_edge1;
@ -411,9 +442,9 @@ begin
end if;
if ((single = '0') or (cmd_edge2 = '0' and cmd_edge1 = '1' and cmd = "1000")) then
Rdy <= (not brkpt_active);
Rdy_int <= (not brkpt_active);
else
Rdy <= (not Sync);
Rdy_int <= (not Sync);
end if;
-- 6502 Reset needs to be open collector
@ -426,6 +457,7 @@ begin
-- Latch instruction address for the whole cycle
if (Sync = '1') then
addr_inst <= Addr;
cycleCount_inst <= cycleCount;
end if;
-- Breakpoints and Watches written to the FIFO
@ -433,6 +465,7 @@ begin
bw_status1 <= bw_status;
if watch_active = '1' or (brkpt_active = '1' and brkpt_active1 = '0') then
fifo_wr <= '1';
Addr1 <= Addr;
end if;
end if;
@ -441,13 +474,16 @@ begin
fallingProcess: process (Phi2)
begin
if falling_edge(Phi2) then
-- Latch the data bus for use in watches
Data1 <= Data;
-- Latch memory read in response to a read command
if (memory_rd = '1') then
din_reg <= DataIn;
end if;
end if;
end process;
Rdy <= Rdy_int;
RdOut <= memory_rd;
WrOut <= memory_wr;
AddrOut <= addr_dout_reg(23 downto 8);