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:
David Banks
2015-06-30 14:19:19 +01:00
parent caec07483d
commit 727a1c0f2a
3 changed files with 220 additions and 159 deletions
+66 -81
View File
@@ -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
View File
@@ -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;