1
0
mirror of https://github.com/simh/simh.git synced 2026-02-15 20:27:40 +00:00

Notes For V3.0-0

Because some key files have changed, V3.0 should be unzipped to a
clean directory.

1. New Features in 3.0-0

1.1 SCP and Libraries

- Added ASSIGN/DEASSIGN (logical name) commands.
- Changed RESTORE to unconditionally detach files.
- Added E11 and TPC format support to magtape library.
- Fixed bug in SHOW CONNECTIONS.
- Added USE_ADDR64 support

1.2 All magtapes

- Magtapes support SIMH format, E11 format, and TPC format (read only).
- SET <tape_unit> FORMAT=format sets the specified tape unit's format.
- SHOW <tape_unit> FORMAT displays the specified tape unit's format.
- Tape format can also be set as part of the ATTACH command, using
  the -F switch.

1.3 VAX

- VAX can be compiled without USE_INT64.
- If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support
  files > 2GB.
- VAX ROM has speed control (SET ROM DELAY/NODELAY).

2. Bugs Fixed in 3.01-0

2.1 VAX

- Fixed CVTfi bug: integer overflow not set if exponent out of range
- Fixed EMODx bugs:
  o First and second operands reversed
  o Separated fraction received wrong exponent
  o Overflow calculation on separated integer incorrect
  o Fraction not set to zero if exponent out of range
- Fixed interval timer and ROM access to pass power-up self-test even on very
  fast host processors (fixes from Mark Pizzolato).

2.2 1401

- Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS.
- Fixed MCE bug, BS off by 1 if zero suppress.
- Fixed chaining bug, D lost if return to SCP.
- Fixed H branch, branch occurs after continue.
- Added check for invalid 8 character MCW, LCA.
- Fixed magtape load-mode end of record response.

2.3 Nova

- Fixed DSK variable size interaction with restore.

2.4 PDP-1

- Fixed DT variable size interaction with restore.

2.5 PDP-11

- Fixed DT variable size interaction with restore.
- Fixed bug in MMR1 update (found by Tim Stark).
- Added XQ features and fixed bugs:
  o Corrected XQ interrupts on IE state transition (code by Tom Evans).
  o Added XQ interrupt clear on soft reset.
  o Removed XQ interrupt when setting XL or RL (multiple people).
  o Added SET/SHOW XQ STATS.
  o Added SHOW XQ FILTERS.
  o Added ability to split received packet into multiple buffers.
  o Added explicit runt and giant packet processing.

2.6 PDP-18B

- Fixed DT, RF variable size interaction with restore.
- Fixed MT bug in MTTR.

2.7 PDP-8

- Fixed DT, DF, RF, RX variable size interaction with restore.
- Fixed MT bug in SKTR.

2.8 HP2100

- Fixed bug in DP (13210A controller only), DQ read status.
- Fixed bug in DP, DQ seek complete.

2.9 GRI

- Fixed bug in SC queue pointer management.

3. New Features in 3.0 vs prior releases

N/A

4. Bugs Fixed in 3.0 vs prior releases

N/A

5. General Notes

WARNING: The RESTORE command has changed.  RESTORE will now
detach an attached file on a unit, if that unit did not have
an attached file in the saved configuration.  This is required
to assure that the unit flags and the file state are consistent.

WARNING: The compilation scheme for the PDP-10, PDP-11, and VAX
has changed.  Use one of the supplied build files, or read the
documentation carefully, before compiling any of these simulators.
This commit is contained in:
Bob Supnik
2003-06-25 09:20:00 -07:00
committed by Mark Pizzolato
parent 43385c9616
commit 4ffd3be790
215 changed files with 12913 additions and 8563 deletions

View File

@@ -1,6 +1,6 @@
/* vax_sysreg.c: VAX system registers simulator
Copyright (c) 1998-2002, Robert M Supnik
Copyright (c) 1998-2003, 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"),
@@ -33,6 +33,10 @@
cso console storage output
sysd system devices (SSC miscellany)
7-Jun-03 MP Added calibrated delay to ROM reads (from Mark Pizzolato)
Fixed calibration problems interval timer (from Mark Pizzolato)
12-May-03 RMS Fixed compilation warnings from VC.Net
23-Apr-03 RMS Revised for 32b/64b t_addr
19-Aug-02 RMS Removed unused variables (found by David Hittner)
Allowed NVR to be attached to file
30-May-02 RMS Widened POS to 32b
@@ -41,6 +45,9 @@
#include "vax_defs.h"
#define UNIT_V_NODELAY (UNIT_V_UF + 0) /* ROM access equal to RAM access */
#define UNIT_NODELAY (1u << UNIT_V_NODELAY)
/* Console storage control/status */
#define CSICSR_IMP (CSR_DONE + CSR_IE) /* console input */
@@ -156,6 +163,7 @@
extern int32 int_req[IPL_HLVL];
extern UNIT cpu_unit;
extern UNIT clk_unit;
extern jmp_buf save_env;
extern int32 p1;
extern int32 sim_switches;
@@ -182,12 +190,13 @@ uint32 tmr_sav[2] = { 0 }; /* saved inst cnt */
int32 ssc_adsm[2] = { 0 }; /* addr strobes */
int32 ssc_adsk[2] = { 0 };
int32 cdg_dat[CDASIZE >> 2]; /* cache data */
static uint32 rom_delay = 0;
t_stat rom_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat rom_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
t_stat rom_reset (DEVICE *dptr);
t_stat nvr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat nvr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
t_stat nvr_reset (DEVICE *dptr);
t_stat nvr_attach (UNIT *uptr, char *cptr);
t_stat nvr_detach (UNIT *uptr);
@@ -241,6 +250,7 @@ extern void rxcs_wr (int32 dat);
extern void txcs_wr (int32 dat);
extern void txdb_wr (int32 dat);
extern void ioreset_wr (int32 dat);
extern uint32 sim_os_msec();
/* ROM data structures
@@ -254,8 +264,13 @@ UNIT rom_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK, ROMSIZE) };
REG rom_reg[] = {
{ NULL } };
MTAB rom_mod[] = {
{ UNIT_NODELAY, UNIT_NODELAY, "fast access", "NODELAY", NULL },
{ UNIT_NODELAY, 0, "1usec calibrated access", "DELAY", NULL },
{ 0 } };
DEVICE rom_dev = {
"ROM", &rom_unit, rom_reg, NULL,
"ROM", &rom_unit, rom_reg, rom_mod,
1, 16, ROMAWIDTH, 4, 16, 32,
&rom_ex, &rom_dep, &rom_reset,
NULL, NULL, NULL,
@@ -395,13 +410,70 @@ DEVICE sysd_dev = {
/* ROM: read only memory - stored in a buffered file
Register space access routines see ROM twice
ROM access has been 'regulated' to about 1Mhz to avoid issues
with testing the interval timers in self-test. Specifically,
the VAX boot ROM (ka655.bin) contains code which presumes that
the VAX runs at a particular slower speed when code is running
from ROM (which is not cached). These assumptions are built
into instruction based timing loops. As the host platform gets
much faster than the original VAX, the assumptions embedded in
these code loops are no longer valid.
Code has been added to the ROM implementation to limit CPU speed
to about 500K instructions per second. This heads off any future
issues with the embedded timing loops.
*/
int32 rom_swapb(int32 val)
{
return ((val << 24) & 0xff000000) | (( val << 8) & 0xff0000) |
((val >> 8) & 0xff00) | ((val >> 24) & 0xff);
}
int32 rom_read_delay (int32 val)
{
uint32 i, l = rom_delay;
int32 loopval = 0;
if (rom_unit.flags & UNIT_NODELAY) return val;
/* Calibrate the loop delay factor when first used.
Do this 4 times to and use the largest value computed. */
if (rom_delay == 0) {
uint32 ts, te, c = 10000, samples = 0;
while (1) {
c = c * 2;
te = sim_os_msec();
while (te == (ts = sim_os_msec ())); /* align on ms tick */
/* This is merely a busy wait with some "work" that won't get optimized
away by a good compiler. loopval always is zero. To avoid smart compilers,
the loopval variable is referenced in the function arguments so that the
function expression is not loop invariant. It also must be referenced
by subsequent code or to avoid the whole computation being eliminated. */
for (i = 0; i < c; i++)
loopval |= (loopval + ts) ^ rom_swapb (rom_swapb (loopval + ts));
te = sim_os_msec ();
if ((te - ts) < 50) continue; /* sample big enough? */
if (rom_delay < (loopval + (c / (te - ts) / 1000) + 1))
rom_delay = loopval + (c / (te - ts) / 1000) + 1;
if (++samples >= 4) break;
c = c / 2; }
if (rom_delay < 5) rom_delay = 5; }
for (i = 0; i < l; i++)
loopval |= (loopval + val) ^ rom_swapb (rom_swapb (loopval + val));
return val + loopval;
}
int32 rom_rd (int32 pa)
{
int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2;
return rom[rg];
return rom_read_delay (rom[rg]);
}
void rom_wr (int32 pa, int32 val, int32 lnt)
@@ -418,8 +490,10 @@ return;
/* ROM examine */
t_stat rom_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
{
uint32 addr = (uint32) exta;
if ((vptr == NULL) || (addr & 03)) return SCPE_ARG;
if (addr >= ROMSIZE) return SCPE_NXM;
*vptr = rom[addr >> 2];
@@ -428,8 +502,10 @@ return SCPE_OK;
/* ROM deposit */
t_stat rom_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
{
uint32 addr = (uint32) exta;
if (addr & 03) return SCPE_ARG;
if (addr >= ROMSIZE) return SCPE_NXM;
rom[addr >> 2] = (uint32) val;
@@ -468,8 +544,10 @@ return;
/* NVR examine */
t_stat nvr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
{
uint32 addr = (uint32) exta;
if ((vptr == NULL) || (addr & 03)) return SCPE_ARG;
if (addr >= NVRSIZE) return SCPE_NXM;
*vptr = nvr[addr >> 2];
@@ -478,8 +556,10 @@ return SCPE_OK;
/* NVR deposit */
t_stat nvr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
{
uint32 addr = (uint32) exta;
if (addr & 03) return SCPE_ARG;
if (addr >= NVRSIZE) return SCPE_NXM;
nvr[addr >> 2] = (uint32) val;
@@ -711,8 +791,8 @@ return;
struct reglink { /* register linkage */
int32 low; /* low addr */
int32 high; /* high addr */
t_stat (*read)(); /* read routine */
void (*write)(); }; /* write routine */
t_stat (*read)(int32 pa); /* read routine */
void (*write)(int32 pa, int32 val, int32 lnt); }; /* write routine */
struct reglink regtable[] = {
{ CQMAPBASE, CQMAPBASE+CQMAPSIZE, &cqmap_rd, &cqmap_wr },
@@ -1031,13 +1111,31 @@ return;
clock events per second. Instead, a gross hack is used. When
a timer is started, the clock interval is inspected.
if (int < 0 and small) then testing timer, count instructions
if (int < 0 and small) then testing timer, count instructions.
Small is determined by when the requested interval is less
than the size of a 100hz system clock tick.
if (int >= 0 or large) then counting a real interval, schedule
clock events at 100Hz using calibrated line clock delay
and when the remaining time value gets small enough, behave
like the small case above.
If the interval register is read, then its value between events
is interpolated using the current instruction count versus the
count when the most recent event started.
count when the most recent event started, the result is scaled
to the calibrated system clock, unless the interval being timed
is less than a calibrated system clock tick (or the calibrated
clock is running very slowly) at which time the result will be
the elapsed instruction count.
The powerup TOY Test sometimes fails its tolerance test. This was
due to varying system load causing varying calibration values to be
used at different times while referencing the TIR. While timing long
intervals, we now synchronize the stepping (and calibration) of the
system tick with the opportunity to reference the value. This gives
precise tolerance measurement values (when interval timers are used
to measure the system clock), regardless of other load issues on the
host system which might cause varying values of the system clock's
calibration factor.
*/
int32 tmr_tir_rd (int32 tmr, t_bool interp)
@@ -1046,6 +1144,9 @@ uint32 delta;
if (interp || (tmr_csr[tmr] & TMR_CSR_RUN)) { /* interp, running? */
delta = sim_grtime () - tmr_sav[tmr]; /* delta inst */
if ((tmr_inc[tmr] == TMR_INC) && /* scale large int */
(tmr_poll > TMR_INC))
delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll);
if (delta >= tmr_inc[tmr]) delta = tmr_inc[tmr] - 1;
return tmr_tir[tmr] + delta; }
return tmr_tir[tmr];
@@ -1117,12 +1218,27 @@ return;
void tmr_sched (int32 tmr)
{
int32 clk_time = sim_is_active (&clk_unit) - 1;
int32 tmr_time;
tmr_sav[tmr] = sim_grtime (); /* save intvl base */
if (tmr_tir[tmr] > (0xFFFFFFFFu - TMR_INC)) { /* short interval? */
tmr_inc[tmr] = (~tmr_tir[tmr] + 1); /* inc = interval */
sim_activate (&sysd_unit[tmr], tmr_inc[tmr]); }
tmr_time = tmr_inc[tmr]; }
else { tmr_inc[tmr] = TMR_INC; /* usec/interval */
sim_activate (&sysd_unit[tmr], tmr_poll); } /* use calib clock */
tmr_time = tmr_poll; }
if (tmr_time == 0) tmr_time = 1;
if ((tmr_inc[tmr] = TMR_INC) && (tmr_time > clk_time)) {
/* Align scheduled event to be identical to the event for the next clock
tick. This lets us always see a consistent calibrated value, both for
this scheduling, AND for any query of the current timer register that
may happen in tmr_tir_rd (). This presumes that sim_activate will
queue the interval timer behind the event for the clock tick. */
tmr_inc[tmr] = (uint32) (((double) clk_time * TMR_INC) / tmr_poll);
tmr_time = clk_time; }
sim_activate (&sysd_unit[tmr], tmr_time);
return;
}