Replace special command with x interrupt control commands

Change-Id: I991171d6923cdc928dd9dbb9823c43aee71661be
This commit is contained in:
David Banks 2021-11-18 14:45:05 +00:00
parent 1244eaf607
commit 3e7bda697c
6 changed files with 206 additions and 78 deletions

View File

@ -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 = "[ <value> ]";
static const char ARGS15[] PROGMEM = "[ <command> ]";
static const char ARGS16[] PROGMEM = "<op1> [ <op2> [ <op3> ] ]";
static const char ARGS17[] PROGMEM = "[ <source> [ <prescale> [ <reset address> ] ] ]";
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) {

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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,

View File

@ -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;