From efdd41a239a772aa17cadf4d7fbecdd233694e34 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 15 Jun 2019 17:50:29 +0100 Subject: [PATCH] 6502: Added special command to inhibit IRQ/NMI Change-Id: I6ba8a1b3b92e5852382d35eee7a59b6a9d7e63e8 --- firmware/AtomBusMon.c | 43 ++++++++++++++--- firmware/AtomBusMon.h | 1 + src/BusMonCore.vhd | 97 ++++++++++++++++++++------------------- src/MOS6502CpuMonCore.vhd | 64 ++++++++++++++------------ 4 files changed, 121 insertions(+), 84 deletions(-) diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index cd3940c..5c97305 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -10,7 +10,7 @@ * VERSION and NAME are used in the start-up message ********************************************************/ -#define VERSION "0.73" +#define VERSION "0.74" #if (CPU == Z80) #define NAME "ICE-T80" @@ -28,9 +28,9 @@ #ifdef CPUEMBEDDED #if (CPU == Z80) - #define NUM_CMDS 30 + #define NUM_CMDS 31 #else - #define NUM_CMDS 23 + #define NUM_CMDS 24 #endif #else #define NUM_CMDS 14 @@ -59,6 +59,7 @@ char *cmdStrings[NUM_CMDS] = { #endif "test", "srec", + "special", #endif "reset", "trace", @@ -99,6 +100,7 @@ void (*cmdFuncs[NUM_CMDS])(char *params) = { #endif doCmdTest, doCmdSRec, + doCmdSpecial, #endif doCmdReset, doCmdTrace, @@ -132,9 +134,14 @@ void (*cmdFuncs[NUM_CMDS])(char *params) = { #define CMD_EDGE 0x20 // Commands are placed on bits 4..0 -// Currently bits 6 and 7 are unused #define CMD_MASK 0x3F +// Bits 7..6 are the special function output bits +// On the 6502, these are used to mask IRQ and NMI +#define SPECIAL_0 6 +#define SPECIAL_1 7 +#define SPECIAL_MASK ((1< 0) { + while (count-- > 0) { data = getHex(); if (addr < addrlo) { addrlo = addr; @@ -1157,6 +1164,30 @@ void doCmdSRec(char *params) { } +void logSpecial(char *function, int value) { + log0("%s", function); + if (value) { + log0(" inhibited\n"); + } else { + log0(" enabled\n"); + } +} + +void doCmdSpecial(char *params) { +#if (CPU == 6502) + int special = -1; + sscanf(params, "%x", &special); + if (special >= 0 && special <= 3) { + CTRL_PORT &= ~SPECIAL_MASK; + CTRL_PORT = (CTRL_PORT & ~SPECIAL_MASK) | (special << SPECIAL_0); + } + logSpecial("NMI", CTRL_PORT & (1 << SPECIAL_1)); + logSpecial("IRQ", CTRL_PORT & (1 << SPECIAL_0)); +#else + log0("Special functions not implemented\n"); +#endif +} + #endif // CPUEMBEDDED void doCmdTrace(char *params) { diff --git a/firmware/AtomBusMon.h b/firmware/AtomBusMon.h index e1cfee8..e631bfb 100644 --- a/firmware/AtomBusMon.h +++ b/firmware/AtomBusMon.h @@ -57,6 +57,7 @@ void doCmdReset(char *params); void doCmdStep(char *params); void doCmdTest(char *params); void doCmdSRec(char *params); +void doCmdSpecial(char *params); void doCmdTrace(char *params); void doCmdTrigger(char *params); void doCmdWatchI(char *params); diff --git a/src/BusMonCore.vhd b/src/BusMonCore.vhd index 04c56e5..86e8137 100644 --- a/src/BusMonCore.vhd +++ b/src/BusMonCore.vhd @@ -2,15 +2,15 @@ -- Copyright (c) 2015 David Banks -- -------------------------------------------------------------------------------- --- ____ ____ --- / /\/ / --- /___/ \ / --- \ \ \/ --- \ \ +-- ____ ____ +-- / /\/ / +-- /___/ \ / +-- \ \ \/ +-- \ \ -- / / Filename : BusMonCore.vhd -- /___/ /\ Timestamp : 30/05/2015 --- \ \ / \ --- \___\/\___\ +-- \ \ / \ +-- \___\/\___\ -- --Design Name: AtomBusMon --Device: XC3S250E @@ -51,7 +51,7 @@ entity BusMonCore is nRSTout : out std_logic; CountCycle : in std_logic; - + -- CPU Registers -- unused in pure bus monitor mode Regs : in std_logic_vector(255 downto 0); @@ -66,14 +66,17 @@ entity BusMonCore is DataOut : out std_logic_vector(7 downto 0); DataIn : in std_logic_vector(7 downto 0); Done : in std_logic; - + + -- Special outputs (function is CPU specific) + Special : out std_logic_vector(1 downto 0); + -- Single Step interface SS_Single : out std_logic; SS_Step : out std_logic; - + -- External trigger inputs trig : in std_logic_vector(1 downto 0); - + -- HD44780 LCD lcd_rs : out std_logic; lcd_rw : out std_logic; @@ -103,7 +106,7 @@ end BusMonCore; architecture behavioral of BusMonCore is 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); @@ -131,15 +134,15 @@ architecture behavioral of BusMonCore is signal bw_status : std_logic_vector(3 downto 0); signal bw_status1 : std_logic_vector(3 downto 0); - + signal auto_inc : 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; @@ -164,7 +167,7 @@ architecture behavioral of BusMonCore is signal unused_b7 : std_logic; signal unused_d6 : std_logic; signal unused_d7 : std_logic; - + begin inst_oho_dy1 : entity work.Oho_Dy1 port map ( @@ -181,7 +184,7 @@ begin dy_ser => tcclk, dy_rclk => tmosi ); - + Inst_AVR8: entity work.AVR8 generic map( CDATAMEMSIZE => avr_data_mem_size, @@ -224,9 +227,9 @@ begin portbout(3) => cmd(3), portbout(4) => cmd(4), portbout(5) => cmd_edge, - portbout(6) => unused_b6, - portbout(7) => unused_b7, - + portbout(6) => Special(0), + portbout(7) => Special(1), + -- Status Port portdin(0) => '0', portdin(1) => '0', @@ -236,7 +239,7 @@ begin portdin(5) => '0', portdin(6) => sw1, portdin(7) => fifo_empty_n, - + portdout(0) => muxsel(0), portdout(1) => muxsel(1), portdout(2) => muxsel(2), @@ -249,11 +252,11 @@ begin -- Mux Port portein => mux, porteout => open, - + spi_mosio => open, spi_scko => open, spi_misoi => '0', - + rxd => avr_RxD, txd => avr_TxD ); @@ -271,7 +274,7 @@ begin ); fifo_wr_en <= fifo_wr and busmon_clken; fifo_rd_en <= fifo_rd and busmon_clken; - + -- 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 @@ -288,7 +291,7 @@ begin led8 <= not brkpt_active; -- green nrst_avr <= nsw2; - + -- OHO DY1 Display for Testing dy_data(0) <= hex & "0000" & Addr(3 downto 0); dy_data(1) <= hex & "0000" & Addr(7 downto 4); @@ -304,13 +307,13 @@ begin 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(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(8 * to_integer(unsigned(muxsel(4 downto 0))) + 7 downto 8 * to_integer(unsigned(muxsel(4 downto 0)))); -- Combinatorial set of comparators to decode breakpoint/watch addresses @@ -324,7 +327,7 @@ begin 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_wmw : std_logic; variable reg_mode_wir : std_logic; variable reg_mode_wiw : std_logic; variable reg_mode_wx : std_logic; @@ -402,7 +405,7 @@ begin brkpt_active <= bactive; bw_status <= status; end process; - + -- CPU Control Commands -- 0000x Enable/Disable single strpping -- 0001x Enable/Disable breakpoints / watches @@ -435,7 +438,7 @@ begin elsif (CountCycle = '1') then cycleCount <= cycleCount + 1; end if; - + -- Command processing cmd_edge1 <= cmd_edge; cmd_edge2 <= cmd_edge1; @@ -451,11 +454,11 @@ begin if (cmd(4 downto 1) = "0000") then single <= cmd(0); end if; - + if (cmd(4 downto 1) = "0001") then brkpt_enable <= cmd(0); end if; - + if (cmd(4 downto 1) = "0010") then brkpt_reg <= cmd(0) & brkpt_reg(brkpt_reg'length - 1 downto 1); end if; @@ -463,14 +466,14 @@ begin if (cmd(4 downto 1) = "0110") then addr_dout_reg <= cmd(0) & addr_dout_reg(addr_dout_reg'length - 1 downto 1); end if; - + if (cmd(4 downto 1) = "0011") then reset <= cmd(0); end if; if (cmd(4 downto 0) = "01001") then fifo_rd <= '1'; - end if; + end if; if (cmd(4 downto 0) = "01010") then fifo_rst <= '1'; @@ -478,26 +481,26 @@ begin if (cmd(4 downto 1) = "1000") then memory_rd <= '1'; - auto_inc <= cmd(0); + auto_inc <= cmd(0); end if; if (cmd(4 downto 1) = "1001") then memory_wr <= '1'; - auto_inc <= cmd(0); + auto_inc <= cmd(0); end if; if (cmd(4 downto 1) = "1010") then io_rd <= '1'; - auto_inc <= cmd(0); + auto_inc <= cmd(0); end if; if (cmd(4 downto 1) = "1011") then io_wr <= '1'; - auto_inc <= cmd(0); + auto_inc <= cmd(0); end if; - + end if; - + -- Auto increment the memory address reg the cycle after a rd/wr if (auto_inc = '1' and Done = '1') then addr_dout_reg(23 downto 8) <= addr_dout_reg(23 downto 8) + 1; @@ -507,22 +510,22 @@ begin if (brkpt_active = '1') then single <= '1'; end if; - + if ((single = '0') or (cmd_edge2 = '0' and cmd_edge1 = '1' and cmd = "01000")) then Rdy_int <= (not brkpt_active); - SS_Step <= (not brkpt_active); + SS_Step <= (not brkpt_active); else Rdy_int <= (not Sync); end if; - + nRSTout <= not reset; - + -- 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 brkpt_active1 <= brkpt_active; bw_status1 <= bw_status; @@ -547,7 +550,7 @@ begin end if; end if; end process; - + Rdy <= Rdy_int; RdMemOut <= memory_rd; WrMemOut <= memory_wr; @@ -558,5 +561,3 @@ begin SS_Single <= single; end behavioral; - - diff --git a/src/MOS6502CpuMonCore.vhd b/src/MOS6502CpuMonCore.vhd index 680760f..21c7a0c 100644 --- a/src/MOS6502CpuMonCore.vhd +++ b/src/MOS6502CpuMonCore.vhd @@ -2,15 +2,15 @@ -- Copyright (c) 2015 David Banks -- -------------------------------------------------------------------------------- --- ____ ____ --- / /\/ / --- /___/ \ / --- \ \ \/ --- \ \ +-- ____ ____ +-- / /\/ / +-- /___/ \ / +-- \ \ \/ +-- \ \ -- / / Filename : AtomBusMon.vhd -- /___/ /\ Timestamp : 30/05/2015 --- \ \ / \ --- \___\/\___\ +-- \ \ / \ +-- \___\/\___\ -- --Design Name: AtomBusMon --Device: XC3S250E @@ -35,11 +35,11 @@ entity MOS6502CpuMonCore is busmon_clken : in std_logic; cpu_clk : in std_logic; cpu_clken : in std_logic; - + -- 6502 Signals IRQ_n : in std_logic; NMI_n : in std_logic; - Sync : out std_logic; + Sync : out std_logic; Addr : out std_logic_vector(15 downto 0); R_W_n : out std_logic; Din : in std_logic_vector(7 downto 0); @@ -51,11 +51,11 @@ entity MOS6502CpuMonCore is -- External trigger inputs trig : in std_logic_vector(1 downto 0); - + -- Serial Console avr_RxD : in std_logic; avr_TxD : out std_logic; - + -- GODIL Switches sw1 : in std_logic; nsw2 : in std_logic; @@ -83,8 +83,6 @@ architecture behavioral of MOS6502CpuMonCore is signal Sync_int : std_logic; signal hold : std_logic; signal Addr_int : std_logic_vector(23 downto 0); - signal IRQ_n_sync : std_logic; - signal NMI_n_sync : std_logic; signal cpu_addr_us: unsigned (15 downto 0); signal cpu_dout_us: unsigned (7 downto 0); @@ -95,6 +93,7 @@ architecture behavioral of MOS6502CpuMonCore is signal SS_Single : std_logic; signal SS_Step : std_logic; signal CountCycle : std_logic; + signal special : std_logic_vector(1 downto 0); signal memory_rd : std_logic; signal memory_rd1 : std_logic; @@ -105,9 +104,12 @@ architecture behavioral of MOS6502CpuMonCore is signal memory_dout : std_logic_vector(7 downto 0); signal memory_din : std_logic_vector(7 downto 0); signal memory_done : std_logic; - + + signal NMI_n_masked : std_logic; + signal IRQ_n_masked : std_logic; + begin - + mon : entity work.BusMonCore generic map ( avr_data_mem_size => avr_data_mem_size, @@ -154,12 +156,15 @@ begin DataOut => memory_dout, DataIn => memory_din, Done => memory_done, + Special => special, SS_Step => SS_Step, SS_Single => SS_Single ); Wr_n_int <= R_W_n_int; Rd_n_int <= not R_W_n_int; Data <= Din when R_W_n_int = '1' else Dout_int; + NMI_n_masked <= NMI_n or special(1); + IRQ_n_masked <= IRQ_n or special(0); -- The CPU is slightly pipelined and the register update of the last -- instruction overlaps with the opcode fetch of the next instruction. @@ -172,7 +177,7 @@ begin -- -- To hide this from the user single stepping, all we need to do is to -- also pipeline the value of the program counter by one stage to compensate. - + last_pc_gen : process(cpu_clk) begin if rising_edge(cpu_clk) then @@ -183,7 +188,7 @@ begin end if; end if; end process; - + Regs1( 47 downto 0) <= Regs( 47 downto 0); Regs1( 63 downto 48) <= last_PC; Regs1(255 downto 64) <= (others => '0'); @@ -199,8 +204,8 @@ begin Enable => cpu_clken_ss, Clk => cpu_clk, Rdy => '1', - IRQ_n => IRQ_n, - NMI_n => NMI_n, + IRQ_n => IRQ_n_masked, + NMI_n => NMI_n_masked, R_W_n => R_W_n_int, Sync => Sync_int, A => Addr_int, @@ -208,22 +213,22 @@ begin DO => Dout_int, Regs => Regs ); - end generate; - + end generate; + GenAlanDCore: if UseAlanDCore generate inst_r65c02: entity work.r65c02 port map ( reset => Res_n_in, clk => cpu_clk, enable => cpu_clken_ss, - nmi_n => NMI_n, - irq_n => IRQ_n, + nmi_n => NMI_n_masked, + irq_n => IRQ_n_masked, di => unsigned(Din), do => cpu_dout_us, addr => cpu_addr_us, nwe => R_W_n_int, sync => Sync_int, sync_irq => open, - Regs => Regs + Regs => Regs ); Dout_int <= std_logic_vector(cpu_dout_us); Addr_int(15 downto 0) <= std_logic_vector(cpu_addr_us); @@ -246,7 +251,7 @@ begin end if; end if; end process; - + -- Only count cycles when the 6809 is actually running CountCycle <= not hold; @@ -263,16 +268,15 @@ begin end if; end if; end process; - + R_W_n <= '1' when memory_rd1 = '1' else '0' when memory_wr1 = '1' else R_W_n_int; Addr <= memory_addr1 when (memory_rd1 = '1' or memory_wr1 = '1') else Addr_int(15 downto 0); Sync <= Sync_int; - + Dout <= memory_dout when memory_wr1 = '1' else Dout_int; - + memory_done <= memory_rd1 or memory_wr1; memory_din <= Din; - + end behavioral; -