diff --git a/AtomCpuMon.bit b/AtomCpuMon.bit index 51f19af..710fce9 100644 Binary files a/AtomCpuMon.bit and b/AtomCpuMon.bit differ diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index 7258bc2..0e1bf2e 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -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) { diff --git a/ipcore_dir/WatchEvents.vhd b/ipcore_dir/WatchEvents.vhd index 7c888ab..b7e672c 100644 --- a/ipcore_dir/WatchEvents.vhd +++ b/ipcore_dir/WatchEvents.vhd @@ -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, diff --git a/ipcore_dir/WatchEvents.xise b/ipcore_dir/WatchEvents.xise index d8a1ff4..a5e5c1e 100644 --- a/ipcore_dir/WatchEvents.xise +++ b/ipcore_dir/WatchEvents.xise @@ -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> diff --git a/ise_build.tcl b/ise_build.tcl index 2d95570..65835c8 100755 --- a/ise_build.tcl +++ b/ise_build.tcl @@ -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 diff --git a/ise_clean.tcl b/ise_clean.tcl index 9d79f4e..52a8b7d 100755 --- a/ise_clean.tcl +++ b/ise_clean.tcl @@ -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 diff --git a/src/AtomCpuMon.vhd b/src/AtomCpuMon.vhd index 09a636a..31c59b6 100644 --- a/src/AtomCpuMon.vhd +++ b/src/AtomCpuMon.vhd @@ -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 diff --git a/src/BusMonCore.vhd b/src/BusMonCore.vhd index a7dff28..745954c 100644 --- a/src/BusMonCore.vhd +++ b/src/BusMonCore.vhd @@ -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);