mirror of
https://github.com/hoglet67/AtomBusMon.git
synced 2026-04-21 09:17:04 +00:00
Implemented IO watches/breakpoints; fixed a bug with stepping through CB/DD/ED/FD prefixed opcodes which have 2 M1 cycles; version not 0.47
Change-Id: Iad5cb406bd96a8020ccb65be5cd440bebec20481
This commit is contained in:
+66
-81
@@ -25,18 +25,20 @@ use work.OhoPack.all ;
|
||||
entity BusMonCore is
|
||||
generic (
|
||||
num_comparators : integer := 8;
|
||||
reg_width : integer := 42;
|
||||
reg_width : integer := 46;
|
||||
fifo_width : integer := 72
|
||||
);
|
||||
port (
|
||||
clock49 : in std_logic;
|
||||
|
||||
-- 6502 Signals
|
||||
-- CPU Signals
|
||||
Addr : in std_logic_vector(15 downto 0);
|
||||
Data : in std_logic_vector(7 downto 0);
|
||||
Phi2 : in std_logic;
|
||||
Rd_n : in std_logic;
|
||||
Wr_n : in std_logic;
|
||||
RdIO_n : in std_logic;
|
||||
WrIO_n : in std_logic;
|
||||
Sync : in std_logic;
|
||||
Rdy : out std_logic;
|
||||
nRSTin : in std_logic;
|
||||
@@ -44,11 +46,11 @@ entity BusMonCore is
|
||||
|
||||
CountCycle : in std_logic;
|
||||
|
||||
-- 6502 Registers
|
||||
-- CPU Registers
|
||||
-- unused in pure bus monitor mode
|
||||
Regs : in std_logic_vector(255 downto 0);
|
||||
|
||||
-- 6502 Memory Read/Write
|
||||
-- CPU Memory Read/Write
|
||||
-- unused in pure bus monitor mode
|
||||
RdMemOut : out std_logic;
|
||||
WrMemOut : out std_logic;
|
||||
@@ -296,52 +298,22 @@ begin
|
||||
|
||||
Regs(8 * to_integer(unsigned(muxsel(4 downto 0))) + 7 downto 8 * to_integer(unsigned(muxsel(4 downto 0))));
|
||||
|
||||
-- Regs( 15 downto 8) when muxsel = 33 else
|
||||
-- Regs( 23 downto 16) when muxsel = 34 else
|
||||
-- Regs( 31 downto 24) when muxsel = 35 else
|
||||
-- Regs( 39 downto 32) when muxsel = 36 else
|
||||
-- Regs( 47 downto 40) when muxsel = 37 else
|
||||
-- Regs( 55 downto 48) when muxsel = 38 else
|
||||
-- Regs( 63 downto 56) when muxsel = 39 else
|
||||
-- Regs( 7 downto 64) when muxsel = 40 else
|
||||
-- Regs( 15 downto 72) when muxsel = 41 else
|
||||
-- Regs( 23 downto 80) when muxsel = 42 else
|
||||
-- Regs( 31 downto 88) when muxsel = 43 else
|
||||
-- Regs( 39 downto 96) when muxsel = 44 else
|
||||
-- Regs( 47 downto 104) when muxsel = 45 else
|
||||
-- Regs( 55 downto 112) when muxsel = 46 else
|
||||
-- Regs( 63 downto 120) when muxsel = 47 else
|
||||
-- Regs( 7 downto 128) when muxsel = 48 else
|
||||
-- Regs( 15 downto 136) when muxsel = 49 else
|
||||
-- Regs( 23 downto 144) when muxsel = 50 else
|
||||
-- Regs( 31 downto 24) when muxsel = 51 else
|
||||
-- Regs( 39 downto 32) when muxsel = 52 else
|
||||
-- Regs( 47 downto 40) when muxsel = 53 else
|
||||
-- Regs( 55 downto 48) when muxsel = 54 else
|
||||
-- Regs( 63 downto 56) when muxsel = 55 else
|
||||
-- Regs( 7 downto 0) when muxsel = 56 else
|
||||
-- Regs( 15 downto 8) when muxsel = 57 else
|
||||
-- Regs( 23 downto 16) when muxsel = 58 else
|
||||
-- Regs( 31 downto 24) when muxsel = 59 else
|
||||
-- Regs( 39 downto 32) when muxsel = 60 else
|
||||
-- Regs( 47 downto 40) when muxsel = 61 else
|
||||
-- Regs( 55 downto 48) when muxsel = 62 else
|
||||
-- Regs( 63 downto 56) when muxsel = 63 else
|
||||
--
|
||||
--
|
||||
-- "10101010";
|
||||
|
||||
-- Combinatorial set of comparators to decode breakpoint/watch addresses
|
||||
brkpt_active_process: process (brkpt_reg, brkpt_enable, Addr, Sync)
|
||||
brkpt_active_process: process (brkpt_reg, brkpt_enable, Addr, Sync, Rd_n, Wr_n, RdIO_n, WrIO_n)
|
||||
variable i : integer;
|
||||
variable reg_addr : std_logic_vector(15 downto 0);
|
||||
variable reg_mask : std_logic_vector(15 downto 0);
|
||||
variable reg_mode_bi : std_logic;
|
||||
variable reg_mode_bar : std_logic;
|
||||
variable reg_mode_baw : std_logic;
|
||||
variable reg_mode_wi : std_logic;
|
||||
variable reg_mode_war : std_logic;
|
||||
variable reg_mode_waw : std_logic;
|
||||
variable reg_mode_bmr : std_logic;
|
||||
variable reg_mode_bmw : std_logic;
|
||||
variable reg_mode_bir : std_logic;
|
||||
variable reg_mode_biw : std_logic;
|
||||
variable reg_mode_bx : std_logic;
|
||||
variable reg_mode_wmr : std_logic;
|
||||
variable reg_mode_wmw : std_logic;
|
||||
variable reg_mode_wir : std_logic;
|
||||
variable reg_mode_wiw : std_logic;
|
||||
variable reg_mode_wx : std_logic;
|
||||
variable reg_mode_all : std_logic_vector(9 downto 0);
|
||||
variable bactive : std_logic;
|
||||
variable wactive : std_logic;
|
||||
variable status : std_logic_vector(3 downto 0);
|
||||
@@ -354,47 +326,60 @@ begin
|
||||
for i in 0 to num_comparators - 1 loop
|
||||
reg_addr := brkpt_reg(i * reg_width + 15 downto i * reg_width);
|
||||
reg_mask := brkpt_reg(i * reg_width + 31 downto i * reg_width + 16);
|
||||
reg_mode_bi := brkpt_reg(i * reg_width + 32);
|
||||
reg_mode_bar := brkpt_reg(i * reg_width + 33);
|
||||
reg_mode_baw := brkpt_reg(i * reg_width + 34);
|
||||
reg_mode_wi := brkpt_reg(i * reg_width + 35);
|
||||
reg_mode_war := brkpt_reg(i * reg_width + 36);
|
||||
reg_mode_waw := brkpt_reg(i * reg_width + 37);
|
||||
trigval := brkpt_reg(i * reg_width + 38 + to_integer(unsigned(trig)));
|
||||
if (trigval = '1' and ((Addr and reg_mask) = reg_addr or
|
||||
(reg_mode_bi = '0' and reg_mode_bar = '0' and reg_mode_baw = '0' and
|
||||
(reg_mode_wi = '0' and reg_mode_war = '0' and reg_mode_waw = '0')))) then
|
||||
reg_mode_bmr := brkpt_reg(i * reg_width + 32);
|
||||
reg_mode_wmr := brkpt_reg(i * reg_width + 33);
|
||||
reg_mode_bmw := brkpt_reg(i * reg_width + 34);
|
||||
reg_mode_wmw := brkpt_reg(i * reg_width + 35);
|
||||
reg_mode_bir := brkpt_reg(i * reg_width + 36);
|
||||
reg_mode_wir := brkpt_reg(i * reg_width + 37);
|
||||
reg_mode_biw := brkpt_reg(i * reg_width + 38);
|
||||
reg_mode_wiw := brkpt_reg(i * reg_width + 39);
|
||||
reg_mode_bx := brkpt_reg(i * reg_width + 40);
|
||||
reg_mode_wx := brkpt_reg(i * reg_width + 41);
|
||||
reg_mode_all := brkpt_reg(i * reg_width + 41 downto i * reg_width + 32);
|
||||
trigval := brkpt_reg(i * reg_width + 42 + to_integer(unsigned(trig)));
|
||||
if (trigval = '1' and ((Addr and reg_mask) = reg_addr or (reg_mode_all = "0000000000"))) then
|
||||
if (Sync = '1') then
|
||||
if (reg_mode_bi = '1') then
|
||||
if (reg_mode_bx = '1') then
|
||||
bactive := '1';
|
||||
status := "0001";
|
||||
end if;
|
||||
if (reg_mode_wi = '1') then
|
||||
status := "1000";
|
||||
elsif (reg_mode_wx = '1') then
|
||||
wactive := '1';
|
||||
status := "1001";
|
||||
end if;
|
||||
else
|
||||
if (Rd_n = '0') then
|
||||
if (reg_mode_bar = '1') then
|
||||
bactive := '1';
|
||||
status := "0010";
|
||||
end if;
|
||||
if (reg_mode_war = '1') then
|
||||
wactive := '1';
|
||||
status := "1010";
|
||||
end if;
|
||||
elsif (Rd_n = '0') then
|
||||
if (reg_mode_bmr = '1') then
|
||||
bactive := '1';
|
||||
status := "0000";
|
||||
elsif (reg_mode_wmr = '1') then
|
||||
wactive := '1';
|
||||
status := "0001";
|
||||
end if;
|
||||
if (Wr_n = '0') then
|
||||
if (reg_mode_baw = '1') then
|
||||
bactive := '1';
|
||||
status := "0100";
|
||||
end if;
|
||||
if (reg_mode_waw = '1') then
|
||||
wactive := '1';
|
||||
status := "1100";
|
||||
end if;
|
||||
elsif (Wr_n = '0') then
|
||||
if (reg_mode_bmw = '1') then
|
||||
bactive := '1';
|
||||
status := "0010";
|
||||
elsif (reg_mode_wmw = '1') then
|
||||
wactive := '1';
|
||||
status := "0011";
|
||||
end if;
|
||||
end if;
|
||||
elsif (RdIO_n = '0') then
|
||||
if (reg_mode_bir = '1') then
|
||||
bactive := '1';
|
||||
status := "0100";
|
||||
elsif (reg_mode_wir = '1') then
|
||||
wactive := '1';
|
||||
status := "0101";
|
||||
end if;
|
||||
elsif (WrIO_n = '0') then
|
||||
if (reg_mode_biw = '1') then
|
||||
bactive := '1';
|
||||
status := "0110";
|
||||
elsif (reg_mode_wiw = '1') then
|
||||
wactive := '1';
|
||||
status := "0111";
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
@@ -515,7 +500,7 @@ begin
|
||||
Rdy_int <= (not Sync);
|
||||
end if;
|
||||
|
||||
-- 6502 Reset needs to be open collector
|
||||
-- CPU Reset needs to be open collector
|
||||
if (reset = '1') then
|
||||
nRSTout <= '0';
|
||||
else
|
||||
|
||||
+39
-13
@@ -98,6 +98,7 @@ signal SS_Single : std_logic;
|
||||
signal SS_Step : std_logic;
|
||||
signal SS_Step_held : std_logic;
|
||||
signal CountCycle : std_logic;
|
||||
signal skipNextOpcode : std_logic;
|
||||
|
||||
signal Regs : std_logic_vector(255 downto 0);
|
||||
signal io_not_mem : std_logic;
|
||||
@@ -119,8 +120,14 @@ signal Read_n0 : std_logic;
|
||||
signal Read_n1 : std_logic;
|
||||
signal Write_n : std_logic;
|
||||
signal Write_n0 : std_logic;
|
||||
signal ReadIO_n : std_logic;
|
||||
signal ReadIO_n0 : std_logic;
|
||||
signal ReadIO_n1 : std_logic;
|
||||
signal WriteIO_n : std_logic;
|
||||
signal WriteIO_n0 : std_logic;
|
||||
signal Sync : std_logic;
|
||||
signal Sync0 : std_logic;
|
||||
signal Mem_IO_n : std_logic;
|
||||
signal nRST : std_logic;
|
||||
|
||||
signal MemState : std_logic_vector(2 downto 0);
|
||||
@@ -145,6 +152,8 @@ begin
|
||||
Phi2 => busmon_clk,
|
||||
Rd_n => Read_n,
|
||||
Wr_n => Write_n,
|
||||
RdIO_n => ReadIO_n,
|
||||
WrIO_n => WriteIO_n,
|
||||
Sync => Sync,
|
||||
Rdy => Rdy,
|
||||
nRSTin => RESET_n_int,
|
||||
@@ -217,7 +226,7 @@ begin
|
||||
elsif rising_edge(CLK_n) then
|
||||
NMI_n_sync <= NMI_n;
|
||||
INT_n_sync <= INT_n;
|
||||
if (M1_n_int = '0' and TState = "001") then
|
||||
if (Sync0 = '1') then
|
||||
-- stop at the end of T1 instruction fetch
|
||||
SS_Step_held <= '0';
|
||||
elsif (SS_Step = '1') then
|
||||
@@ -227,19 +236,33 @@ begin
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- Logic to ignore the second M1 in multi-byte opcodes
|
||||
skip_opcode_latch : process(CLK_n)
|
||||
begin
|
||||
if rising_edge(CLK_n) then
|
||||
if (M1_n_int = '0' and WAIT_n_int = '1' and TState = "010") then
|
||||
if (skipNextOpcode = '0' and (Data = x"CB" or Data = x"DD" or Data = x"ED" or Data = x"FD")) then
|
||||
skipNextOpcode <= '1';
|
||||
else
|
||||
skipNextOpcode <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- For instruction breakpoints, we make the monitoring decision as early as possibe
|
||||
-- to allow time to stop the current instruction, which is possible because we don't
|
||||
-- really care about the data (it's re-read from memory by the disassembler).
|
||||
Sync0 <= not M1_n_int when TState = "001" else '0';
|
||||
Sync0 <= '1' when M1_n_int = '0' and TState = "001" and skipNextOpcode = '0' else '0';
|
||||
|
||||
-- For reads/write breakpoints we make the monitoring decision in the middle of T2
|
||||
-- For memory reads/write breakpoints we make the monitoring decision in the middle of T2
|
||||
-- but only if WAIT_n is '1' so we catch the right data.
|
||||
Read_n0 <= not (WAIT_n_int and (not RD_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "010" else '1';
|
||||
Write_n0 <= not (WAIT_n_int and (not WR_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "010" else '1';
|
||||
|
||||
-- These are useful for debugging IO Requests:
|
||||
-- Read_n0 <= not (WAIT_n_int and (not RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "010" else '1';
|
||||
-- Write_n0 <= not ( ( RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "011" else '1';
|
||||
ReadIO_n0 <= not (WAIT_n_int and (not RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "010" else '1';
|
||||
WriteIO_n0 <= not ( ( RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "011" else '1';
|
||||
|
||||
-- Hold the monitoring decision so it is valid on the rising edge of the clock
|
||||
-- For instruction fetches and writes, the monitor sees these at the start of T3
|
||||
@@ -247,10 +270,13 @@ begin
|
||||
watch_gen : process(CLK_n)
|
||||
begin
|
||||
if falling_edge(CLK_n) then
|
||||
Sync <= Sync0;
|
||||
Read_n1 <= Read_n0;
|
||||
Read_n <= Read_n1;
|
||||
Write_n <= Write_n0;
|
||||
Sync <= Sync0;
|
||||
Read_n1 <= Read_n0;
|
||||
Read_n <= Read_n1;
|
||||
Write_n <= Write_n0;
|
||||
ReadIO_n1 <= ReadIO_n0;
|
||||
ReadIO_n <= ReadIO_n1;
|
||||
WriteIO_n <= WriteIO_n0;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
@@ -258,7 +284,7 @@ begin
|
||||
ex_data_latch : process(CLK_n)
|
||||
begin
|
||||
if rising_edge(CLK_n) then
|
||||
if (Sync = '1' or Write_n = '0') then
|
||||
if (Sync = '1' or Write_n = '0' or WriteIO_n = '0') then
|
||||
ex_data <= Data;
|
||||
end if;
|
||||
end if;
|
||||
@@ -268,7 +294,7 @@ begin
|
||||
rd_data_latch : process(CLK_n)
|
||||
begin
|
||||
if falling_edge(CLK_n) then
|
||||
if (Read_n1 = '0') then
|
||||
if (Read_n1 = '0' or ReadIO_n1 = '0') then
|
||||
rd_data <= Data;
|
||||
end if;
|
||||
memory_din <= Data;
|
||||
@@ -276,7 +302,7 @@ begin
|
||||
end process;
|
||||
|
||||
-- Mux the data seen by the bus monitor appropriately
|
||||
mon_data <= rd_data when Read_n <= '0' else ex_data;
|
||||
mon_data <= rd_data when Read_n <= '0' or ReadIO_n = '0' else ex_data;
|
||||
|
||||
-- Memory access
|
||||
Addr <= memory_addr when (state /= idle) else Addr_int;
|
||||
|
||||
Reference in New Issue
Block a user