1
0
mirror of https://github.com/simh/simh.git synced 2026-01-25 19:56:25 +00:00

Notes For V3.7-0

1. New Features

1.1 3.7-0

1.1.1 SCP

- Added SET THROTTLE and SET NOTHROTTLE commands to regulate simulator
  execution rate and host resource utilization.
- Added idle support (based on work by Mark Pizzolato).
- Added -e to control error processing in nested DO commands (from
  Dave Bryan).

1.1.2 HP2100

- Added Double Integer instructions, 1000-F CPU, and Floating Point
  Processor (from Dave Bryan).
- Added 2114 and 2115 CPUs, 12607B and 12578A DMA controllers, and
  21xx binary loader protection (from Dave Bryan).

1.1.3 Interdata

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state.

1.1.4 PDP-11

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (WAIT instruction executed).
- Added TA11/TU60 cassette support.

1.1.5 PDP-8

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (keyboard poll loop or jump-to-self).
- Added TA8E/TU60 cassette support.

1.1.6 PDP-1

- Added support for 16-channel sequence break system.
- Added support for PDP-1D extended features and timesharing clock.
- Added support for Type 630 data communications subsystem.

1.1.6 PDP-4/7/9/15

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (keyboard poll loop or jump-to-self).

1.1.7 VAX, VAX780

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (more than 200 cycles at IPL's 0, 1, or 3 in kernel mode).

1.1.8 PDP-10

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (operating system dependent).
- Added CD20 (CD11) support.

2. Bugs Fixed

Please see the revision history on http://simh.trailing-edge.com or
in the source module sim_rev.h.
This commit is contained in:
Bob Supnik
2007-02-03 14:59:00 -08:00
committed by Mark Pizzolato
parent 15919a2dd7
commit 53d02f7fa7
161 changed files with 18604 additions and 6903 deletions

View File

@@ -25,6 +25,13 @@
cpu PDP-4/7/9/15 central processor
26-Dec-06 RMS Fixed boundary test in KT15/XVM (reported by Andrew Warkentin)
30-Oct-06 RMS Added idle and infinite loop detection
08-Oct-06 RMS Added RDCLK instruction
Fixed bug, PC off by one on fetch mem mmgt error
PDP-15 sets API 3 on mem mmgt trap (like PI)
PDP-15 sets API 4 on CAL only if 0-3 inactive
CAF clears memory management mode register
27-Jun-06 RMS Reset clears AC, L, and MQ
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
16-Aug-05 RMS Fixed C++ declaration and cast problems
@@ -285,6 +292,7 @@
#define UNIT_RELOC (1 << UNIT_V_RELOC)
#define UNIT_XVM (1 << UNIT_V_XVM)
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#define OP_KSF 0700301
#define HIST_API 0x40000000
#define HIST_PI 0x20000000
@@ -373,6 +381,7 @@ InstHistory *hst = NULL; /* instruction history *
extern int32 sim_int_char;
extern int32 sim_interval;
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern t_bool sim_idle_enab;
extern DEVICE *sim_devices[];
extern FILE *sim_log;
@@ -383,6 +392,7 @@ t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
void cpu_caf (void);
void cpu_inst_hist (int32 addr, int32 inst);
void cpu_intr_hist (int32 flag, int32 lvl);
int32 upd_iors (void);
@@ -398,6 +408,7 @@ int32 Prot15 (int32 ma, t_bool bndchk);
int32 Reloc15 (int32 ma, int32 acc);
int32 RelocXVM (int32 ma, int32 acc);
extern t_stat fp15 (int32 ir);
extern int32 clk_task_upd (t_bool clr);
#else
#define INDEX(i,x)
#endif
@@ -530,6 +541,8 @@ MTAB cpu_mod[] = {
{ UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC+UNIT_XVM,
"XVM", "XVM", NULL },
#endif
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
#if defined (PDP4)
{ UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
#endif
@@ -566,6 +579,7 @@ t_stat sim_instr (void)
{
int32 api_int, api_usmd, skp;
int32 iot_data, device, pulse;
int32 last_IR;
t_stat reason;
extern UNIT clk_unit;
@@ -574,6 +588,7 @@ PC = PC & AMASK; /* clean variables */
LAC = LAC & LACMASK;
MQ = MQ & DMASK;
reason = 0;
last_IR = -1;
sim_rtc_init (clk_unit.wait); /* init calibration */
if (cpu_unit.flags & UNIT_NOAPI) api_enb = api_req = api_act = 0;
api_int = api_eval (&int_pend); /* eval API */
@@ -642,8 +657,18 @@ while (reason == 0) { /* loop until halted */
if (trap_pending) { /* trap pending? */
PCQ_ENTRY; /* save old PC */
MB = Jms_word (1); /* save state */
MA = ion? 0: 020; /* save in 0/20 */
ion = 0; /* interrupts off */
if (ion) { /* int on? */
ion = 0; /* interrupts off */
MA = 0; /* treat like PI */
#if defined (PDP15)
ion_defer = 2; /* free instruction */
if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */
api_act = api_act | API_ML3; /* set lev 3 active */
api_int = api_eval (&int_pend); /* re-evaluate */
}
#endif
}
else MA = 020; /* sortof like CAL */
emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */
usmd = usmd_buf = 0; /* user mode off */
Write (MA, MB, WR); /* physical write */
@@ -676,6 +701,7 @@ while (reason == 0) { /* loop until halted */
usmd = usmd_buf = 0; /* user mode off */
emir_pending = rest_pending = 0; /* emir, restore off */
xct_count = 0;
Read (MA, &IR, FE); /* fetch instruction */
goto xct_instr;
}
@@ -685,10 +711,10 @@ while (reason == 0) { /* loop until halted */
if (hst_lnt) cpu_intr_hist (HIST_PI, 0); /* record */
MB = Jms_word (usmd); /* save state */
ion = 0; /* interrupts off */
ion_defer = 2; /* free instruction */
#if defined (PDP9) /* PDP-9, */
memm = 0; /* extend off */
#else /* PDP-15 */
ion_defer = 2; /* free instruction */
if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */
api_act = api_act | API_ML3; /* set lev 3 active */
api_int = api_eval (&int_pend); /* re-evaluate */
@@ -713,10 +739,10 @@ while (reason == 0) { /* loop until halted */
xct_count = 0; /* track nested XCT's */
MA = PC; /* fetch at PC */
if (Read (MA, &IR, FE)) continue; /* fetch instruction */
PC = Incr_addr (PC); /* increment PC */
xct_instr: /* label for XCT */
if (Read (MA, &IR, FE)) continue; /* fetch instruction */
xct_instr: /* label for API, XCT */
if (hst_lnt) cpu_inst_hist (MA, IR); /* history? */
if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */
if (sim_interval) sim_interval = sim_interval - 1;
@@ -846,6 +872,7 @@ while (reason == 0) { /* loop until halted */
#if defined (PDP9)
ion_defer = 1; /* defer intr */
#endif
if (Read (MA, &IR, FE)) break; /* fetch inst, mm err? */
goto xct_instr; /* go execute */
/* CAL: opcode 00 - api_usmd records whether usmd = 1 at start of API cycle
@@ -867,7 +894,10 @@ while (reason == 0) { /* loop until halted */
#if defined (PDP9) || defined (PDP15)
usmd = usmd_buf = 0; /* clear user mode */
if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */
api_act = api_act | 010;
#if defined (PDP15) /* PDP15: if 0-3 inactive */
if ((api_act & (API_ML0|API_ML1|API_ML2|API_ML3)) == 0)
#endif
api_act = api_act | API_ML4;
api_int = api_eval (&int_pend);
}
#endif
@@ -899,9 +929,29 @@ while (reason == 0) { /* loop until halted */
case 031: /* JMP, indir */
if (Ia (MA, &MA, 1)) break;
INDEX (IR, MA);
PCQ_ENTRY; /* save old PC */
PC = MA & AMASK;
break;
/* JMP direct - check for idle */
case 030: /* JMP, dir */
INDEX (IR, MA);
PCQ_ENTRY; /* save old PC */
if (sim_idle_enab) { /* idling enabled? */
t_bool iof = (ion_inh != 0) || /* IOF if inhibited */
((ion == 0) && (api_enb == 0)); /* or PI and api off */
if (((MA ^ (PC - 2)) & AMASK) == 0) { /* 1) JMP *-1? */
if (iof && (last_IR == OP_KSF) && /* iof, prv KSF, */
!TST_INT (TTI)) /* no TTI flag? */
sim_idle (0, FALSE); /* we're idle */
}
else if (((MA ^ (PC - 1)) & AMASK) == 0) { /* 2) JMP *? */
if (iof) reason = STOP_LOOP; /* iof? inf loop */
else sim_idle (0, FALSE); /* ion? idle */
}
} /* end idle */
PC = MA & AMASK;
break;
@@ -1369,12 +1419,15 @@ while (reason == 0) { /* loop until halted */
case 017: /* mem protection */
if (PROT) { /* enabled? */
if ((pulse == 001) && prvn) PC = Incr_addr (PC);
else if ((pulse == 041) && nexm) PC = Incr_addr (PC);
else if (pulse == 002) prvn = 0;
else if (pulse == 042) usmd_buf = 1;
else if (pulse == 004) BR = LAC & BRMASK;
else if (pulse == 044) nexm = 0;
if ((pulse == 001) && prvn) /* MPSK */
PC = Incr_addr (PC);
else if ((pulse == 041) && nexm) /* MPSNE */
PC = Incr_addr (PC);
else if (pulse == 002) prvn = 0; /* MPCV */
else if (pulse == 042) usmd_buf = 1; /* MPEU */
else if (pulse == 004) /* MPLD */
BR = LAC & BRMASK;
else if (pulse == 044) nexm = 0; /* MPCNE */
}
else reason = stop_inst;
break;
@@ -1388,7 +1441,7 @@ while (reason == 0) { /* loop until halted */
if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC);
else if (pulse == 002) { /* CAF */
reset_all (1); /* reset all exc CPU */
api_enb = api_req = api_act = 0; /* reset API system */
cpu_caf (); /* CAF to CPU */
}
else if (pulse == 044) rest_pending = 1; /* DBR */
if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
@@ -1444,13 +1497,19 @@ while (reason == 0) { /* loop until halted */
case 017: /* mem protection */
if (PROT) { /* enabled? */
t = XVM? BRMASK_XVM: BRMASK;
if ((pulse == 001) && prvn) PC = Incr_addr (PC);
else if ((pulse == 041) && nexm) PC = Incr_addr (PC);
else if (pulse == 002) prvn = 0;
else if (pulse == 042) usmd_buf = 1;
else if (pulse == 004) BR = LAC & t;
else if (RELOC && (pulse == 024)) RR = LAC & t;
else if (pulse == 044) nexm = 0;
if ((pulse == 001) && prvn) /* MPSK */
PC = Incr_addr (PC);
else if ((pulse == 041) && nexm) /* MPSNE */
PC = Incr_addr (PC);
else if (pulse == 002) prvn = 0; /* MPCV */
else if (pulse == 042) /* MPEU */
usmd_buf = 1;
else if (XVM && (pulse == 062)) /* RDCLK */
iot_data = clk_task_upd (TRUE);
else if (pulse == 004) BR = LAC & t; /* MPLD */
else if (RELOC && (pulse == 024)) /* MPLR */
RR = LAC & t;
else if (pulse == 044) nexm = 0; /* MPCNE */
}
else reason = stop_inst;
break;
@@ -1464,7 +1523,7 @@ while (reason == 0) { /* loop until halted */
if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC);
else if (pulse == 002) { /* CAF */
reset_all (2); /* reset all exc CPU, FP15 */
api_enb = api_req = api_act = 0; /* reset API system */
cpu_caf (); /* CAF to CPU */
}
else if (pulse == 044) rest_pending = 1; /* DBR */
if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
@@ -1519,6 +1578,7 @@ while (reason == 0) { /* loop until halted */
} /* end switch opcode */
api_usmd = 0; /* API cycle over */
last_IR = IR; /* save IR for next */
} /* end while */
/* Simulation halted */
@@ -1835,7 +1895,7 @@ int32 Reloc15 (int32 ma, int32 rc)
int32 pa;
ma = ma & AMASK; /* 17b addressing */
if (ma >= (BR | 0377)) { /* boundary viol? */
if (ma > (BR | 0377)) { /* boundary viol? */
if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */
return -1;
}
@@ -1871,7 +1931,7 @@ else if ((MMR & MM_SH) && /* shared enabled and */
else pa = RR + (ma & 0377); /* no, ISAS reloc */
}
else {
if (ma >= (BR | 0377)) { /* normal reloc, viol? */
if (ma > (BR | 0377)) { /* normal reloc, viol? */
if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */
return -1;
}
@@ -1911,6 +1971,17 @@ sim_brk_types = sim_brk_dflt = SWMASK ('E');
return SCPE_OK;
}
/* CAF routine (CPU reset isn't called by CAF) */
void cpu_caf (void)
{
api_enb = api_req = api_act = 0; /* reset API system */
nexm = prvn = trap_pending = 0; /* reset MM system */
usmd = usmd_buf = usmd_defer = 0;
MMR = 0;
return;
}
/* Memory examine */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)

View File

@@ -1,6 +1,6 @@
/* pdp18b_defs.h: 18b PDP simulator definitions
Copyright (c) 1993-2005, Robert M Supnik
Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
30-Oct-06 RMS Added infinite loop stop
14-Jan-04 RMS Revised IO device call interface
18-Oct-03 RMS Added DECtape off reel message
18-Jul-03 RMS Added FP15 support
@@ -113,6 +114,7 @@
#define STOP_MME 7 /* mem mgt error */
#define STOP_FPDIS 8 /* fp inst, fpp disabled */
#define STOP_DTOFF 9 /* DECtape off reel */
#define STOP_LOOP 10 /* infinite loop */
/* Peripheral configuration */

View File

@@ -414,7 +414,7 @@ if (ir & FI_FP) { /* fp? */
numwd = 3; /* 3 words */
}
else { /* single */
if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */
if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */
a->lo = (a->lo + UFP_FL_SRND) & UFP_FL_SMASK;
a->hi = (a->hi + (a->lo == 0)) & UFP_FH_MASK;
if ((a->hi | a->lo) == 0) { /* carry out? */
@@ -424,7 +424,7 @@ if (ir & FI_FP) { /* fp? */
}
if (a->exp > 0377) return FP_OVF; /* sp ovf? */
if (a->exp < -0400) return FP_UNF; /* sp unf? */
wd[0] = (a->exp & 0777) | (a->lo & UFP_FL_SMASK); /* low frac'exp */
wd[0] = (a->exp & 0777) | (a->lo & UFP_FL_SMASK); /* low frac'exp */
wd[1] = (a->sign << 17) | a->hi; /* hi frac */
numwd = 2; /* 2 words */
}

View File

@@ -225,8 +225,8 @@ return SCPE_OK;
int32 lp62_iors (void)
{
return (TST_INT (LPT)? IOS_LPT: 0) |
(TST_INT (LPTSPC)? IOS_LPT1: 0);
return (TST_INT (LPT)? IOS_LPT: 0) |
(TST_INT (LPTSPC)? IOS_LPT1: 0);
}
#endif
@@ -718,7 +718,7 @@ int32 header, sb;
sb = pulse & 060; /* subopcode */
if (pulse & 01) {
if ((sb == 000) && (lp15_sta & (STA_ERR | STA_DON))) /* LPSF */
if ((sb == 000) && (lp15_sta & (STA_ERR | STA_DON))) /* LPSF */
dat = IOT_SKP | dat;
else if ((sb == 020) || (sb == 040)) { /* LPP1, LPPM */
sim_activate (&lp15_unit, lp15_unit.wait); /* activate */
@@ -732,7 +732,7 @@ if (pulse & 01) {
}
else if (sb == 060) lp15_ie = 0; /* LPDI */
}
if ((pulse & 02) && (sb == 040)) dat = dat | lp15_updsta (0); /* LPOS, LPRS */
if ((pulse & 02) && (sb == 040)) dat = dat | lp15_updsta (0); /* LPOS, LPRS */
if ((pulse & 04) && (sb == 040)) lp15_ie = 1; /* LPEI */
lp15_updsta (0); /* update status */
return dat;
@@ -799,7 +799,7 @@ for (more = 1; more != 0; ) { /* loop until ctrl */
lp15_bp = more = 0;
}
else {
if (lp15_bp < LP15_BSIZE) lp15_buf[lp15_bp++] = c[i];
if (lp15_bp < LP15_BSIZE) lp15_buf[lp15_bp++] = c[i];
else lp15_sta = lp15_sta | STA_OVF;
}
}
@@ -816,7 +816,7 @@ return SCPE_OK;
int32 lp15_updsta (int32 new)
{
lp15_sta = (lp15_sta | new) & ~(STA_CLR | STA_ERR | STA_BUSY);
if (lp15_sta & STA_EFLGS) lp15_sta = lp15_sta | STA_ERR; /* update errors */
if (lp15_sta & STA_EFLGS) lp15_sta = lp15_sta | STA_ERR; /* update errors */
if (sim_is_active (&lp15_unit)) lp15_sta = lp15_sta | STA_BUSY;
if (lp15_ie && (lp15_sta & STA_DON)) SET_INT (LPT);
else CLR_INT (LPT); /* update int */

View File

@@ -26,6 +26,7 @@
rf (PDP-9) RF09/RF09
(PDP-15) RF15/RS09
04-Oct-06 RMS Fixed bug, DSCD does not clear function register
15-May-06 RMS Fixed bug in autosize attach (reported by David Gesswein)
14-Jan-04 RMS Revised IO device call interface
Changed sim_fsize calling sequence
@@ -100,6 +101,7 @@
#define RFS_CLR 0000170 /* always clear */
#define RFS_EFLGS (RFS_HDW | RFS_APE | RFS_MXF | RFS_WCE | \
RFS_DPE | RFS_WLO | RFS_NED ) /* error flags */
#define RFS_FR (RFS_FNC|RFS_IE)
#define GET_FNC(x) (((x) >> RFS_V_FNC) & RFS_M_FNC)
#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \
((double) RF_NUMWD)))
@@ -187,8 +189,8 @@ int32 t, sb;
sb = pulse & 060; /* subopcode */
if (pulse & 01) {
if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON)))
dat = IOT_SKP | dat; /* DSSF */
if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON))) /* DSSF */
dat = IOT_SKP | dat;
else if (sb == 020) rf_reset (&rf_dev); /* DSCC */
else if (sb == 040) { /* DSCF */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
@@ -237,7 +239,7 @@ if (pulse & 02) {
(sim_is_active (&rf_unit)? 0400000: 0);
else if (sb == 040) { /* DSCD */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
else rf_sta = 0;
else rf_sta = rf_sta & RFS_FR;
rf_updsta (0);
}
else if (sb == 060) { /* DSRS */

View File

@@ -46,7 +46,8 @@
#define RP_NUMSF 20 /* surfaces/cylinder */
#define RP_NUMCY 203 /* cylinders/drive */
#define RP_NUMDR 8 /* drives/controller */
#define RP_SIZE (RP_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD) /* words/drive */
#define RP_SIZE (RP_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD)
/* words/drive */
/* Unit specific flags */
@@ -262,7 +263,8 @@ if (pulse & 01) {
if (sb == 020) dat = IOT_SKP | dat; /* DPSN */
}
if (pulse & 02) {
if (sb == 000) dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */
if (sb == 000) /* DPOU */
dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL;
else if (sb == 020) dat = dat | rp_da; /* DPOA */
else if (sb == 040) dat = dat | rp_ma; /* DPOC */
else if (sb == 060) dat = dat | rp_wc; /* DPOW */
@@ -272,9 +274,12 @@ if (pulse & 04) {
rp_updsta (0, STB_PGE);
return dat;
}
if (sb == 000) rp_sta = rp_sta & ~STA_RW; /* DPCF */
else if (sb == 020) rp_sta = rp_sta & (dat | ~STA_RW); /* DPLZ */
else if (sb == 040) rp_sta = rp_sta | (dat & STA_RW); /* DPLO */
if (sb == 000) /* DPCF */
rp_sta = rp_sta & ~STA_RW;
else if (sb == 020) /* DPLZ */
rp_sta = rp_sta & (dat | ~STA_RW);
else if (sb == 040) /* DPLO */
rp_sta = rp_sta | (dat & STA_RW);
else if (sb == 060) /* DPLF */
rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW);
rp_sta = rp_sta & ~STA_DON; /* clear done */

View File

@@ -29,6 +29,11 @@
tto teleprinter
clk clock
18-Oct-06 RMS Added PDP-15 programmable duplex control
Fixed handling of non-printable characters in KSR mode
Changed clock to be free-running
Fixed out-of-tape behavior for PDP-9 vs PDP-15
Synced keyboard to clock
30-Jun-06 RMS Fixed KSR-28 shift tracking
20-Jun-06 RMS Added KSR ASCII reader support
13-Jun-06 RMS Fixed Baudot letters/figures inversion for PDP-4
@@ -86,8 +91,11 @@ int32 ptr_err = 0, ptr_stopioe = 0, ptr_state = 0;
int32 ptp_err = 0, ptp_stopioe = 0;
int32 tti_2nd = 0; /* 2nd char waiting */
int32 tty_shift = 0; /* KSR28 shift state */
int32 tti_fdpx = 0; /* prog mode full duplex */
int32 clk_tps = 60; /* ticks/second */
int32 tmxr_poll = 16000; /* term mux poll */
uint32 clk_task_last = 0;
uint32 clk_task_timer = 0;
const int32 asc_to_baud[128] = {
000,000,000,000,000,000,000,064, /* bell */
@@ -146,6 +154,7 @@ t_stat ptr_boot (int32 unitno, DEVICE *dptr);
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 clk_task_upd (t_bool clr);
extern int32 upd_iors (void);
@@ -164,6 +173,10 @@ REG clk_reg[] = {
{ FLDATA (INT, int_hwre[API_CLK], INT_V_CLK) },
{ FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) },
{ FLDATA (ENABLE, clk_state, 0) },
#if defined (PDP15)
{ ORDATA (TASKTIMER, clk_task_timer, 18) },
{ DRDATA (TASKLAST, clk_task_last, 32), REG_HRO },
#endif
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
{ NULL }
@@ -296,7 +309,7 @@ DEVICE ptp_dev = {
DIB tti_dib = { DEV_TTI, 1, &tti_iors, { &tti } };
UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR+TTUF_HDX, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR+TTUF_HDX, 0), 0 };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, TTI_WIDTH) },
@@ -305,8 +318,11 @@ REG tti_reg[] = {
#endif
{ FLDATA (INT, int_hwre[API_TTI], INT_V_TTI) },
{ FLDATA (DONE, int_hwre[API_TTI], INT_V_TTI) },
#if defined (PDP15)
{ FLDATA (FDPX, tti_fdpx, 0) },
#endif
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), PV_LEFT },
{ NULL }
};
@@ -392,14 +408,9 @@ if (pulse & 001) { /* CLSF */
if (TST_INT (CLK)) dat = dat | IOT_SKP;
}
if (pulse & 004) { /* CLON/CLOF */
if (pulse & 040) { /* CLON */
CLR_INT (CLK); /* clear flag */
clk_state = 1; /* clock on */
if (!sim_is_active (&clk_unit)) /* already on? */
sim_activate (&clk_unit, /* start, calibr */
sim_rtc_init (clk_unit.wait));
}
else clk_reset (&clk_dev); /* CLOF */
CLR_INT (CLK); /* clear flag */
if (pulse & 040) clk_state = 1; /* CLON */
else clk_state = 0; /* CLOF */
}
return dat;
}
@@ -410,16 +421,49 @@ t_stat clk_svc (UNIT *uptr)
{
int32 t;
t = sim_rtc_calb (clk_tps); /* calibrate clock */
tmxr_poll = t; /* set mux poll */
sim_activate (&clk_unit, t); /* reactivate unit */
#if defined (PDP15)
clk_task_upd (FALSE); /* update task timer */
#endif
if (clk_state) { /* clock on? */
M[7] = (M[7] + 1) & DMASK; /* incr counter */
if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */
t = sim_rtc_calb (clk_tps); /* calibrate clock */
sim_activate (&clk_unit, t); /* reactivate unit */
tmxr_poll = t; /* set mux poll */
}
return SCPE_OK;
}
#if defined (PDP15)
/* Task timer update (PDP-15 XVM only)
The task timer increments monotonically at 100Khz. Since this can't be
simulated accurately, updates are done by interpolation since the last
reading. The timer is also updated at clock events to keep the cycle
counters from wrapping around more than once between updates. */
int32 clk_task_upd (t_bool clr)
{
uint32 delta, val, iusec10;
uint32 cur = sim_grtime ();
uint32 old = clk_task_timer;
double usec10;
if (cur > clk_task_last) delta = cur - clk_task_last;
else delta = clk_task_last - cur;
usec10 = ((((double) delta) * 100000.0) /
(((double) tmxr_poll) * ((double) clk_tps)));
iusec10 = (int32) usec10;
val = (clk_task_timer + iusec10) & DMASK;
if (clr) clk_task_timer = 0;
else clk_task_timer = val;
clk_task_last = cur;
return ((int32) val);
}
#endif
/* IORS service */
int32 clk_iors (void)
@@ -431,11 +475,16 @@ return (TST_INT (CLK)? IOS_CLK: 0);
t_stat clk_reset (DEVICE *dptr)
{
int32 t;
CLR_INT (CLK); /* clear flag */
tmxr_poll = clk_unit.wait; /* set mux poll */
if (!sim_is_running) { /* RESET? */
if (!sim_is_running) { /* RESET (not CAF)? */
t = sim_rtc_init (clk_unit.wait); /* init calibration */
tmxr_poll = t; /* set mux poll */
sim_activate_abs (&clk_unit, t); /* activate unit */
clk_state = 0; /* clock off */
sim_cancel (&clk_unit); /* stop clock */
clk_task_timer = 0;
clk_task_last = 0;
}
return SCPE_OK;
}
@@ -458,6 +507,19 @@ fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
return SCPE_OK;
}
/* Paper tape reader out-of-tape handling
The PDP-4 and PDP-7 readers behaved like most early DEC readers; when
they ran out of tape, they hung. It was up to the program to sense this
condition by running a timer.
The PDP-9 reader controller synthesized the out of tape condition by
noticing whether there was a transition on the feed hole within a window.
The out-of-tape flag was treated like the reader flag in most cases.
The PDP-15 reader controller received the out-of-tape flag as a static
condition from the reader itself and simply reported it via IORS. */
/* Paper tape reader: IOT routine */
int32 ptr (int32 dev, int32 pulse, int32 dat)
@@ -466,12 +528,15 @@ if (pulse & 001) { /* RSF */
if (TST_INT (PTR)) dat = dat | IOT_SKP;
}
if (pulse & 002) { /* RRB, RCF */
CLR_INT (PTR); /* clear done */
CLR_INT (PTR); /* clear flag */
dat = dat | ptr_unit.buf; /* return buffer */
}
if (pulse & 004) { /* RSA, RSB */
ptr_state = (pulse & 040)? 18: 0; /* set mode */
CLR_INT (PTR); /* clear done */
CLR_INT (PTR); /* clear flag */
#if !defined (PDP15) /* except on PDP15 */
ptr_err = 0; /* clear error */
#endif
ptr_unit.buf = 0; /* clear buffer */
sim_activate (&ptr_unit, ptr_unit.wait);
}
@@ -486,15 +551,15 @@ int32 temp;
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */
#if defined (IOS_PTRERR)
SET_INT (PTR); /* if err, set int */
ptr_err = 1;
SET_INT (PTR); /* if err, set flag */
ptr_err = 1; /* set error */
#endif
return IORETURN (ptr_stopioe, SCPE_UNATT);
}
}
if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
#if defined (IOS_PTRERR)
SET_INT (PTR); /* if err, set done */
ptr_err = 1;
SET_INT (PTR); /* if err, set flag */
ptr_err = 1; /* set error */
#endif
if (feof (ptr_unit.fileref)) {
if (ptr_stopioe) printf ("PTR end of file\n");
@@ -532,7 +597,12 @@ t_stat ptr_reset (DEVICE *dptr)
ptr_state = 0; /* clear state */
ptr_unit.buf = 0;
CLR_INT (PTR); /* clear flag */
ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1;
#if defined (PDP15) /* PDP15, static err */
if (((ptr_unit.flags & UNIT_ATT) == 0) || feof (ptr_unit.fileref))
ptr_err = 1;
else
#endif
ptr_err = 0; /* all other, clr err */
sim_cancel (&ptr_unit); /* deactivate unit */
return SCPE_OK;
}
@@ -555,20 +625,23 @@ t_stat ptr_attach (UNIT *uptr, char *cptr)
t_stat reason;
reason = attach_unit (uptr, cptr);
ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1;
if (reason != SCPE_OK) return reason;
ptr_err = 0; /* attach clrs error */
ptr_unit.flags = ptr_unit.flags & ~(UNIT_RASCII|UNIT_KASCII);
if (sim_switches & SWMASK ('A'))
ptr_unit.flags = ptr_unit.flags | UNIT_RASCII;
if (sim_switches & SWMASK ('K'))
ptr_unit.flags = ptr_unit.flags | UNIT_KASCII;
return reason;
return SCPE_OK;
}
/* Detach routine */
t_stat ptr_detach (UNIT *uptr)
{
#if defined (PDP15)
ptr_err = 1;
#endif
ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII;
return detach_unit (uptr);
}
@@ -606,7 +679,7 @@ for (;;) { /* word loop */
}
else if (val == OP_HLT) return STOP_HALT;
break;
}
}
else if (MEM_ADDR_OK (origin)) M[origin++] = val;
}
return SCPE_FMT;
@@ -810,7 +883,7 @@ return dat;
t_stat ptp_svc (UNIT *uptr)
{
SET_INT (PTP); /* set done flag */
SET_INT (PTP); /* set flag */
if ((ptp_unit.flags & UNIT_ATT) == 0) { /* not attached? */
ptp_err = 1; /* set error */
return IORETURN (ptp_stopioe, SCPE_UNATT);
@@ -859,7 +932,8 @@ t_stat ptp_attach (UNIT *uptr, char *cptr)
t_stat reason;
reason = attach_unit (uptr, cptr);
ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1;
if (reason != SCPE_OK) return reason;
ptp_err = 0;
ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII;
if (sim_switches & SWMASK ('A'))
ptp_unit.flags = ptp_unit.flags | UNIT_PASCII;
@@ -882,9 +956,13 @@ int32 tti (int32 dev, int32 pulse, int32 dat)
if (pulse & 001) { /* KSF */
if (TST_INT (TTI)) dat = dat | IOT_SKP;
}
if (pulse & 002) { /* KRB */
if (pulse & 002) { /* KRS/KRB */
CLR_INT (TTI); /* clear flag */
dat = dat | tti_unit.buf & TTI_MASK; /* return buffer */
#if defined (PDP15)
if (pulse & 020) tti_fdpx = 1; /* KRS? */
else tti_fdpx = 0; /* no, KRB */
#endif
}
if (pulse & 004) { /* IORS */
dat = dat | upd_iors ();
@@ -897,9 +975,9 @@ return dat;
t_stat tti_svc (UNIT *uptr)
{
#if defined (KSR28) /* Baudot... */
int32 in, c;
int32 in, c, out;
sim_activate (uptr, uptr->wait); /* continue poll */
sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */
if (tti_2nd) { /* char waiting? */
uptr->buf = tti_2nd; /* return char */
tti_2nd = 0; /* not waiting */
@@ -922,8 +1000,9 @@ else {
}
tti_2nd = c & TTI_MASK; /* save actual char */
}
if (uptr->flags & TTUF_HDX) { /* half duplex? */
sim_putchar (sim_tt_outcvt (in, TTUF_MODE_UC));
if ((uptr->flags & TTUF_HDX) && /* half duplex? */
((out = sim_tt_outcvt (in, TT_GET_MODE (uptr->flags) | TTUF_KSR)) >= 0)) {
sim_putchar (out);
tto_unit.pos = tto_unit.pos + 1;
}
}
@@ -931,13 +1010,13 @@ else {
#else /* ASCII... */
int32 c, out;
sim_activate (uptr, uptr->wait); /* continue poll */
sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
out = c & 0177; /* mask echo to 7b */
if (c & SCPE_BREAK) c = 0; /* break? */
else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR);
if ((uptr->flags & TTUF_HDX) && out && /* half duplex and */
((out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags))) >= 0)) {
if ((uptr->flags & TTUF_HDX) && !tti_fdpx && out && /* half duplex and */
((out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags) | TTUF_KSR)) >= 0)) {
sim_putchar (out); /* echo */
tto_unit.pos = tto_unit.pos + 1;
}
@@ -963,8 +1042,9 @@ t_stat tti_reset (DEVICE *dptr)
tti_unit.buf = 0; /* clear buffer */
tti_2nd = 0;
tty_shift = 0; /* clear state */
tti_fdpx = 0; /* clear dpx mode */
CLR_INT (TTI); /* clear flag */
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmxr_poll));
return SCPE_OK;
}
@@ -999,7 +1079,7 @@ else {
c = baud_to_asc[uptr->buf | (tty_shift << 5)]; /* translate */
#else
c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags));
c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR);
if (c >= 0) {
#endif

View File

@@ -23,6 +23,9 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
30-Oct-06 RMS Added infinite loop stop
18-Oct-06 RMS Re-ordered device list
02-Oct-06 RMS Added RDCLK instruction
12-Jun-06 RMS Added Fiodec, Baudot display
RMS Generalized LOAD to handle HRI, RIM, or BIN files
22-Jul-05 RMS Removed AAS, error in V1 reference manual
@@ -128,6 +131,7 @@ int32 sim_emax = 2;
DEVICE *sim_devices[] = {
&cpu_dev,
&clk_dev,
#if defined (PDP15)
&fpp_dev,
#endif
@@ -135,7 +139,6 @@ DEVICE *sim_devices[] = {
&ptp_dev,
&tti_dev,
&tto_dev,
&clk_dev,
#if defined (TYPE62)
&lp62_dev,
#endif
@@ -180,7 +183,8 @@ const char *sim_stop_messages[] = {
"Non-standard device number",
"Memory management error",
"FP15 instruction disabled",
"DECtape off reel"
"DECtape off reel",
"Infinite loop"
};
/* Binary loaders */
@@ -493,7 +497,8 @@ static const char *opcode[] = {
"SPCO", "SKP15", "RES",
"SBA", "DBA", "EBA",
"RDMM", "ORMM", "LDMM", "MPLR",
"ENB", "INH", "MPRC", "IPFH",
"ENB", "INH",
"RDCLK","MPRC", "IPFH",
"PAX", "PAL", "AAC", "PXA",
"AXS", "PXL", "PLA", "PLX",
"CLAC","CLX", "CLLR", "AXR",
@@ -529,7 +534,7 @@ static const char *opcode[] = {
"DAD", "URDAD", "UNDAD", "UUDAD",
"BZA", "BMA", "BLE", "BPA",
"BRU", "BNA", "BAC",
"ISB*", "ESB*", /* indirect */
"ISB*", "ESB*", /* indirect */
"FSB*", "URFSB*", "UNFSB*", "UUFSB*",
"DSB*", "URDSB*", "UNDSB*", "UUDSB*",
"IRS*", "ERS*",
@@ -725,7 +730,8 @@ static const int32 opc_val[] = {
0703341+I_NPI, 0707741+I_NPI, 0707742+I_NPI,
0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI,
0700032+I_NPN, 0700022+I_NPI, 0700024+I_NPI, 0701724+I_NPI,
0705521+I_NPI, 0705522+I_NPI, 0701722+I_NPI, 0701764+I_NPI,
0705521+I_NPI, 0705522+I_NPI,
0701772+I_NPN, 0701762+I_NPI, 0701764+I_NPI,
0721000+I_XR, 0722000+I_XR, 0723000+I_XR9, 0724000+I_XR,
0725000+I_XR9, 0726000+I_XR, 0730000+I_XR, 0731000+I_XR,
0734000+I_XR, 0735000+I_XR, 0736000+I_XR, 0737000+I_XR9,

View File

@@ -1,6 +1,6 @@
/* pdp15_ttx.c: PDP-15 additional terminals simulator
Copyright (c) 1993-2005, Robert M Supnik
Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,7 @@
ttix,ttox LT15/LT19 terminal input/output
30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode
22-Nov-05 RMS Revised for new terminal processing routines
29-Jun-05 RMS Added SET TTOXn DISCONNECT
21-Jun-05 RMS Fixed bug in SHOW CONN/STATS
@@ -219,7 +220,7 @@ for (ln = 0; ln < TTX_MAXL; ln++) { /* loop thru lines */
if (ttx_ldsc[ln].conn) { /* connected? */
if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */
if (temp & SCPE_BREAK) c = 0; /* break? */
else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags));
else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags) | TTUF_KSR);
ttix_buf[ln] = c;
ttix_set_done (ln);
}
@@ -280,7 +281,7 @@ int32 c, ln = uptr - ttox_unit; /* line # */
if (ttx_ldsc[ln].conn) { /* connected? */
if (ttx_ldsc[ln].xmte) { /* tx enabled? */
TMLN *lp = &ttx_ldsc[ln]; /* get line */
c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags));
c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags) | TTUF_KSR);
if (c >= 0) tmxr_putc_ln (lp, c); /* output char */
tmxr_poll_tx (&ttx_desc); /* poll xmt */
}