From 3e7bda697ca2443dc5105f12f3625e07da740c36 Mon Sep 17 00:00:00 2001 From: David Banks Date: Thu, 18 Nov 2021 14:45:05 +0000 Subject: [PATCH] Replace special command with x interrupt control commands Change-Id: I991171d6923cdc928dd9dbb9823c43aee71661be --- firmware/AtomBusMon.c | 164 +++++++++++++++++++++++++++----------- firmware/AtomBusMon.h | 5 +- src/BusMonCore.vhd | 14 ++-- src/MC6809CpuMon.vhd | 31 +++++-- src/MOS6502CpuMonCore.vhd | 33 ++++++-- src/Z80CpuMon.vhd | 37 +++++++-- 6 files changed, 206 insertions(+), 78 deletions(-) diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index 313c87a..52a5798 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -16,14 +16,33 @@ #define VERSION "0.996" +// The X commands allows the various interrupt inputs to be overridded +// They are named after the data sheet pin name + #if defined(CPU_Z80) #define NAME "ICE-Z80" + #define XCMD0 "xbusrq" + #define XCMD1 "xint" + #define XCMD2 "xnmi" + #define XCMD3 "xres" #elif defined(CPU_6502) #define NAME "ICE-6502" + #define XCMD0 "xirq" + #define XCMD1 "xnmi" + #define XCMD2 "xres" + #define XCMD3 "xso " #elif defined(CPU_65C02) #define NAME "ICE-65C02" + #define XCMD0 "xirq" + #define XCMD1 "xnmi" + #define XCMD2 "xres" + #define XCMD3 "xso " #elif defined(CPU_6809) #define NAME "ICE-6809" + #define XCMD0 "xfiq" + #define XCMD1 "xirq" + #define XCMD2 "xnmi" + #define XCMD3 "xres" #else #error "Unsupported CPU type" #endif @@ -70,7 +89,6 @@ char *cmdStrings[] = { "load", "save", "srec", - "special", "reset", "trace", "blist", @@ -89,7 +107,11 @@ char *cmdStrings[] = { "clear", "trigger", "timermode", - "timeout" + "timeout", + XCMD0, + XCMD1, + XCMD2, + XCMD3 }; // Must be kept in step with cmdStrings (just above) @@ -125,7 +147,6 @@ void (*cmdFuncs[])(char *params) = { doCmdLoad, doCmdSave, doCmdSRec, - doCmdSpecial, doCmdReset, doCmdTrace, doCmdList, @@ -144,7 +165,11 @@ void (*cmdFuncs[])(char *params) = { doCmdClear, doCmdTrigger, doCmdTimerMode, - doCmdTimeout + doCmdTimeout, + doCmdXCmd0, + doCmdXCmd1, + doCmdXCmd2, + doCmdXCmd3 }; #if defined(EXTENDED_HELP) @@ -167,6 +192,7 @@ static const char ARGS14[] PROGMEM = "[ ]"; static const char ARGS15[] PROGMEM = "[ ]"; static const char ARGS16[] PROGMEM = " [ [ ] ]"; static const char ARGS17[] PROGMEM = "[ [ [ ] ] ]"; +static const char ARGS18[] PROGMEM = "e|c|d|f"; static const char * const argsStrings[] PROGMEM = { ARGS00, @@ -187,6 +213,7 @@ static const char * const argsStrings[] PROGMEM = { ARGS15, ARGS16, ARGS17, + ARGS18 }; // Must be kept in step with cmdStrings (just above) @@ -197,7 +224,7 @@ static const uint8_t helpMeta[] PROGMEM = { 17, 15, // help 9, 8, // continue 24, 1, // next - 32, 6, // step + 31, 6, // step 27, 7, // regs 12, 10, // dis 16, 7, // flush @@ -207,7 +234,7 @@ static const uint8_t helpMeta[] PROGMEM = { 8, 13, // compare 22, 1, // mem 26, 2, // rd - 43, 3, // wr + 42, 3, // wr #if defined(CPU_Z80) 20, 1, // io 19, 2, // in @@ -218,30 +245,33 @@ static const uint8_t helpMeta[] PROGMEM = { 15, 16, // exec 23, 14, // mode #endif - 33, 12, // test + 32, 12, // test 21, 0, // load 29, 9, // save - 31, 7, // srec - 30, 14, // special + 30, 7, // srec 28, 7, // reset - 36, 6, // trace + 35, 6, // trace 1, 7, // blist 6, 4, // breakx - 42, 4, // watchx + 41, 4, // watchx 4, 4, // breakr - 40, 4, // watchr + 39, 4, // watchr 5, 4, // breakw - 41, 4, // watchw + 40, 4, // watchw #if defined(CPU_Z80) 2, 4, // breaki - 38, 4, // watchi + 37, 4, // watchi 3, 4, // breako - 39, 4, // watcho + 38, 4, // watcho #endif 7, 0, // clear - 37, 5, // trigger - 35, 17, // timermode - 34, 14, // timeout + 36, 5, // trigger + 34, 17, // timermode + 33, 14, // timeout + 43, 18, // xcmd0 + 44, 18, // xcmd1 + 45, 18, // xcmd2 + 46, 18, // xcmd3 0, 0 }; @@ -286,8 +316,8 @@ static const uint8_t helpMeta[] PROGMEM = { // 011xx1 Unused // 011x1x Unused // 0111xx Unused -// 100xxx Special -// 1010xx Timer Mode +// 10xxxx Int Ctrl +// 1100xx Timer Mode // 00 - count cpu cycles where clken = 1 and CountCycle = 1 // 01 - count cpu cycles where clken = 1 (ignoring CountCycle) // 10 - free running timer, using busmon_clk as the source @@ -310,8 +340,8 @@ static const uint8_t helpMeta[] PROGMEM = { #define CMD_WR_IO 0x16 #define CMD_WR_IO_INC 0x17 #define CMD_EXEC_GO 0x18 -#define CMD_SPECIAL 0x20 -#define CMD_TIMER_MODE 0x28 +#define CMD_INT_CTRL 0x20 +#define CMD_TIMER_MODE 0x30 /******************************************************** * AVR Status Register Definitions @@ -609,6 +639,24 @@ static const char * triggerStrings[NUM_TRIGGERS] = { #define TRIGGER_UNDEFINED 31 +/******************************************************** + * Interrupt controls + ********************************************************/ + +static const uint8_t cmd_map[] = { 1, 3, 0, 2 }; + +static const char INTCTRL0[] PROGMEM = "Enabled"; +static const char INTCTRL1[] PROGMEM = "Conditional"; +static const char INTCTRL2[] PROGMEM = "Forced"; +static const char INTCTRL3[] PROGMEM = "Disabled"; + +static const char *int_ctrl_strings[] = { + INTCTRL0, + INTCTRL1, + INTCTRL2, + INTCTRL3 +}; + /******************************************************** * Other global variables ********************************************************/ @@ -637,15 +685,16 @@ uint8_t cmd_id = 0xff; #define MASK_CLOCK_ERROR 1 #define MASK_TIMEOUT_ERROR 2 -// Current special setting -uint8_t special = 0x00; - // Current timer mode setting uint8_t timer_mode = 0x00; uint8_t timer_prescale = 0x01; addr_t timer_resetaddr = 0xffff; unsigned long timer_offset = 0; +// Current interrupts controls +uint8_t int_ctrl = 0; + + /******************************************************** * User Command Processor ********************************************************/ @@ -2032,31 +2081,50 @@ void doCmdSRec(char *params) { } } -void logSpecial(char *function, uint8_t value) { - logs(function); - if (value) { - logstr(" inhibited\n"); - } else { - logstr(" enabled\n"); - } +void set_int_ctrl(uint8_t offset, char *params) { + // (C) 01 Conditional + // (D) 11 Disabled + // (E) 00 Enabled + // (F) 10 Forced + while (*params == ' ') { + params++; + } + if (!*params) { + uint8_t tmp = int_ctrl; + for (int i = 0; i < 4; i++) { + logs(cmdStrings[NUM_CMDS - 4 + i]); + logstr(" = "); + logpgmstr(int_ctrl_strings[tmp & 3]); + logc('\n'); + tmp >>= 2; + } + } else { + *params &= 0xdf; + if (*params >= 'C' && *params <= 'F') { + uint8_t val = cmd_map[*params - 'C']; + hwCmd(CMD_INT_CTRL, (offset << 1) | val); + int_ctrl &= (0x03 << offset) ^ 0xFF; + int_ctrl |= (val << offset); + } else { + logstr("Illegal option\n"); + } + } } -void doCmdSpecial(char *params) { - uint8_t tmp = 0xff; - parsehex2(params, &tmp); -#if defined(CPU_6809) - if (tmp <= 7) { -#else - if (tmp <= 3) { -#endif - special = tmp; - hwCmd(CMD_SPECIAL, special); - } -#if defined(CPU_6809) - logSpecial("FIRQ", special & 4); -#endif - logSpecial("NMI", special & 2); - logSpecial("IRQ", special & 1); +void doCmdXCmd0(char *params) { + set_int_ctrl(0, params); +} + +void doCmdXCmd1(char *params) { + set_int_ctrl(2, params); +} + +void doCmdXCmd2(char *params) { + set_int_ctrl(4, params); +} + +void doCmdXCmd3(char *params) { + set_int_ctrl(6, params); } void doCmdTimerMode(char *params) { diff --git a/firmware/AtomBusMon.h b/firmware/AtomBusMon.h index b507499..a6dbe6f 100644 --- a/firmware/AtomBusMon.h +++ b/firmware/AtomBusMon.h @@ -76,7 +76,6 @@ void doCmdStep(char *params); void doCmdTest(char *params); void doCmdSave(char *params); void doCmdSRec(char *params); -void doCmdSpecial(char *params); void doCmdTimerMode(char *params); void doCmdTimeout(char *params); void doCmdTrace(char *params); @@ -88,5 +87,9 @@ void doCmdWatchWrIO(char *params); void doCmdWatchWrMem(char *params); void doCmdWriteIO(char *params); void doCmdWriteMem(char *params); +void doCmdXCmd0(char *params); +void doCmdXCmd1(char *params); +void doCmdXCmd2(char *params); +void doCmdXCmd3(char *params); #endif diff --git a/src/BusMonCore.vhd b/src/BusMonCore.vhd index 177342c..b61cb67 100644 --- a/src/BusMonCore.vhd +++ b/src/BusMonCore.vhd @@ -71,8 +71,8 @@ entity BusMonCore is DataIn : in std_logic_vector(7 downto 0); Done : in std_logic; - -- Special outputs (function is CPU specific) - Special : out std_logic_vector(2 downto 0); + -- External Interrupt Control + int_ctrl : out std_logic_vector(7 downto 0) := x"00"; -- Single Step interface SS_Single : out std_logic; @@ -459,8 +459,8 @@ begin -- 0111xx Unused -- 011x1x Unused -- 011xx1 Unused - -- 100xxx Special - -- 1010xx Timer Mode + -- 10xxxx Int Ctrl + -- 1100xx Timer Mode -- 00 - count cpu cycles where clken = 1 and CountCycle = 1 -- 01 - count cpu cycles where clken = 1 (ignoring CountCycle) -- 10 - free running timer, using busmon_clk as the source @@ -551,11 +551,11 @@ begin exec <= '1'; end if; - if (cmd(5 downto 3) = "100") then - Special <= cmd(2 downto 0); + if (cmd(5 downto 4) = "10") then + int_ctrl(to_integer(unsigned(cmd(3 downto 2))) * 2 + 1 downto to_integer(unsigned(cmd(3 downto 2))) * 2) <= cmd(1 downto 0); end if; - if (cmd(5 downto 2) = "1010") then + if (cmd(5 downto 2) = "1100") then timer_mode <= cmd(1 downto 0); end if; diff --git a/src/MC6809CpuMon.vhd b/src/MC6809CpuMon.vhd index b782f55..cb76597 100644 --- a/src/MC6809CpuMon.vhd +++ b/src/MC6809CpuMon.vhd @@ -124,7 +124,7 @@ architecture behavioral of MC6809CpuMon is signal SS_Single : std_logic; signal SS_Step : std_logic; signal CountCycle : std_logic; - signal special : std_logic_vector(2 downto 0); + signal int_ctrl : std_logic_vector(7 downto 0); signal LIC_int : std_logic; @@ -140,9 +140,10 @@ architecture behavioral of MC6809CpuMon is signal data_wr : std_logic; signal nRSTout : std_logic; - signal NMI_n_masked : std_logic; - signal IRQ_n_masked : std_logic; signal FIRQ_n_masked : std_logic; + signal IRQ_n_masked : std_logic; + signal NMI_n_masked : std_logic; + signal RES_n_masked : std_logic; begin @@ -184,7 +185,7 @@ begin WrIO_n => '1', Sync => Sync_int, Rdy => open, - nRSTin => RES_n, + nRSTin => RES_n_masked, nRSTout => cpu_reset_n, CountCycle => CountCycle, trig => trig, @@ -207,14 +208,28 @@ begin DataOut => memory_dout, DataIn => memory_din, Done => memory_done, - Special => special, + int_ctrl => int_ctrl, SS_Step => SS_Step, SS_Single => SS_Single ); - FIRQ_n_masked <= FIRQ_n or special(2); - NMI_n_masked <= NMI_n or special(1); - IRQ_n_masked <= IRQ_n or special(0); + -- The two int control bits work as follows + -- 00 -> IRQ_n (enabled) + -- 01 -> IRQ_n or SS_Single (enabled when free-running) + -- 10 -> 0 (forced) + -- 11 -> 1 (disabled) + + FIRQ_n_masked <= int_ctrl(0) when int_ctrl(1) = '1' else + FIRQ_n or (int_ctrl(0) and SS_single); + + IRQ_n_masked <= int_ctrl(2) when int_ctrl(3) = '1' else + IRQ_n or (int_ctrl(2) and SS_single); + + NMI_n_masked <= int_ctrl(4) when int_ctrl(5) = '1' else + NMI_n or (int_ctrl(4) and SS_single); + + RES_n_masked <= int_ctrl(6) when int_ctrl(7) = '1' else + RES_n or (int_ctrl(6) and SS_single); -- The CPU is slightly pipelined and the register update of the last -- instruction overlaps with the opcode fetch of the next instruction. diff --git a/src/MOS6502CpuMonCore.vhd b/src/MOS6502CpuMonCore.vhd index 05aecfd..a9772e3 100644 --- a/src/MOS6502CpuMonCore.vhd +++ b/src/MOS6502CpuMonCore.vhd @@ -100,7 +100,7 @@ architecture behavioral of MOS6502CpuMonCore is signal SS_Step : std_logic; signal SS_Step_held : std_logic; signal CountCycle : std_logic; - signal special : std_logic_vector(2 downto 0); + signal int_ctrl : std_logic_vector(7 downto 0); signal memory_rd : std_logic; signal memory_rd1 : std_logic; @@ -111,8 +111,11 @@ architecture behavioral of MOS6502CpuMonCore is 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; + signal NMI_n_masked : std_logic; + signal Res_n_masked : std_logic; + signal SO_n_masked : std_logic; signal exec : std_logic; signal exec_held : std_logic; @@ -139,7 +142,7 @@ begin WrIO_n => '1', Sync => Sync_mon, Rdy => open, - nRSTin => Res_n, + nRSTin => Res_n_masked, nRSTout => cpu_reset_n, CountCycle => CountCycle, trig => trig, @@ -163,7 +166,7 @@ begin DataOut => memory_dout, DataIn => memory_din, Done => Done_mon, - Special => special, + int_ctrl => int_ctrl, SS_Step => SS_Step, SS_Single => SS_Single ); @@ -173,8 +176,24 @@ begin Done_mon <= Rdy and memory_done; 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 two int control bits work as follows + -- 00 -> IRQ_n (enabled) + -- 01 -> IRQ_n or SS_Single (enabled when free-running) + -- 10 -> 0 (forced) + -- 11 -> 1 (disabled) + + IRQ_n_masked <= int_ctrl(0) when int_ctrl(1) = '1' else + IRQ_n or (int_ctrl(0) and SS_single); + + NMI_n_masked <= int_ctrl(2) when int_ctrl(3) = '1' else + NMI_n or (int_ctrl(2) and SS_single); + + Res_n_masked <= int_ctrl(4) when int_ctrl(5) = '1' else + Res_n or (int_ctrl(4) and SS_single); + + SO_n_masked <= int_ctrl(6) when int_ctrl(7) = '1' else + SO_n or (int_ctrl(6) and SS_single); -- The CPU is slightly pipelined and the register update of the last -- instruction overlaps with the opcode fetch of the next instruction. @@ -209,7 +228,7 @@ begin inst_t65: entity work.T65 port map ( mode => "00", Abort_n => '1', - SO_n => SO_n, + SO_n => SO_n_masked, Res_n => cpu_reset_n, Enable => cpu_clken_ss, Clk => cpu_clk, diff --git a/src/Z80CpuMon.vhd b/src/Z80CpuMon.vhd index 183cdd8..0b461ec 100644 --- a/src/Z80CpuMon.vhd +++ b/src/Z80CpuMon.vhd @@ -116,7 +116,7 @@ type state_type is (idle, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa, rd_t2, r signal SS_Step : std_logic; signal SS_Step_held : std_logic; signal CountCycle : std_logic; - signal special : std_logic_vector(2 downto 0); + signal int_ctrl : std_logic_vector(7 downto 0); signal skipNextOpcode : std_logic; signal Regs : std_logic_vector(255 downto 0); @@ -150,6 +150,7 @@ type state_type is (idle, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa, rd_t2, r signal BUSRQ_n_sync : std_logic; signal INT_n_sync : std_logic; signal NMI_n_sync : std_logic; + signal RESET_n_sync : std_logic; signal Read_n : std_logic; signal Read_n0 : std_logic; @@ -218,7 +219,7 @@ begin WrIO_n => WriteIO_n, Sync => Sync, Rdy => open, - nRSTin => RESET_n, + nRSTin => RESET_n_sync, nRSTout => cpu_reset_n, CountCycle => CountCycle, trig => trig, @@ -242,7 +243,7 @@ begin DataOut => memory_dout, DataIn => memory_din, Done => memory_done, - Special => special, + int_ctrl => int_ctrl, SS_Single => SS_Single, SS_Step => SS_Step ); @@ -283,9 +284,31 @@ begin int_gen : process(CLK_n) begin if rising_edge(CLK_n) then - BUSRQ_n_sync <= BUSRQ_n; - NMI_n_sync <= NMI_n or special(1); - INT_n_sync <= INT_n or special(0); + + if int_ctrl(1) = '1' then + BUSRQ_n_sync <= int_ctrl(0); + else + BUSRQ_n_sync <= BUSRQ_n or (int_ctrl(0) and SS_single); + end if; + + if int_ctrl(3) = '1' then + INT_n_sync <= int_ctrl(2); + else + INT_n_sync <= INT_n or (int_ctrl(2) and SS_single); + end if; + + if int_ctrl(5) = '1' then + NMI_n_sync <= int_ctrl(4); + else + NMI_n_sync <= NMI_n or (int_ctrl(4) and SS_single); + end if; + + if int_ctrl(7) = '1' then + RESET_n_sync <= int_ctrl(6); + else + RESET_n_sync <= RESET_n or (int_ctrl(6) and SS_single); + end if; + end if; end process; @@ -401,7 +424,7 @@ begin BUSAK_n <= BUSAK_n_int when state = idle else mon_busak_n; -- Force the address and databus to tristate when reset is asserted - tristate_ad_n <= '0' when RESET_n = '0' else + tristate_ad_n <= '0' when RESET_n_sync = '0' else BUSAK_n_int when state = idle else mon_busak_n1;