1
0
mirror of https://github.com/simh/simh.git synced 2026-04-09 22:39:04 +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

@@ -25,6 +25,8 @@
cpu CVAX central processor
17-May-03 RMS Fixed operand order in EMODx
23-Apr-03 RMS Revised for 32b/64b t_addr
05-Jan-02 RMS Added memory size restore support
25-Dec-02 RMS Added instruction history (from Mark Pizzolato)
29-Sep-02 RMS Revised to build dib_tab dynamically
@@ -307,12 +309,12 @@ extern void op_polyd (int32 *opnd, int32 acc);
extern void op_polyg (int32 *opnd, int32 acc);
extern int32 op_emulate (int32 *opnd, int32 cc, int32 opc, int32 acc);
extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);
extern int32 Read (t_addr va, int32 lnt, int32 acc);
extern void Write (t_addr va, int32 val, int32 lnt, int32 acc);
extern int32 ReadB (t_addr pa);
extern int32 WriteB (t_addr pa, int32 val);
extern int32 Test (t_addr va, int32 acc, int32 *status);
extern int32 ReadLP (t_addr pa);
extern int32 Read (uint32 va, int32 lnt, int32 acc);
extern void Write (uint32 va, int32 val, int32 lnt, int32 acc);
extern int32 ReadB (uint32 pa);
extern int32 WriteB (uint32 pa, int32 val);
extern int32 Test (uint32 va, int32 acc, int32 *status);
extern int32 ReadLP (uint32 pa);
extern int32 eval_int (void);
extern int32 get_vector (int32 lvl);
extern void set_map_reg (void);
@@ -322,8 +324,8 @@ extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_boot (int32 unitno, DEVICE *dptr);
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_show_virt (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
@@ -512,7 +514,7 @@ for ( ;; ) {
int32 spec, disp, rn, index, numspec;
int32 vfldrp1, brdisp, flg, mstat;
int32 i, j, r, rh, temp;
t_addr va, iad;
uint32 va, iad;
int32 opnd[OPND_SIZE]; /* operand queue */
if (cpu_astop) {
@@ -2120,8 +2122,8 @@ case ACBG:
/* EMODF
op0 = extension
op1 = multiplier
op0 = multiplier
op1 = extension
op2 = multiplicand
op3:op4 = integer destination (int.wl)
op5:op6 = floating destination (flt.wl)
@@ -2139,8 +2141,8 @@ case EMODF:
/* EMODD, EMODG
op0 = extension
op1:op2 = multiplier
op0:op1 = multiplier
op2 = extension
op3:op4 = multiplicand
op5:op6 = integer destination (int.wl)
op7:op8 = floating destination (flt.wq)
@@ -2315,7 +2317,7 @@ ASTLVL = 4;
MSER = 0;
CADR = 0;
mapen = 0;
if (M == NULL) M = calloc (MEMSIZE >> 2, sizeof (int32));
if (M == NULL) M = calloc (((uint32) MEMSIZE) >> 2, sizeof (int32));
if (M == NULL) return SCPE_MEM;
pcq_r = find_reg ("PCQ", NULL, dptr);
if (pcq_r) pcq_r->qptr = 0;
@@ -2356,9 +2358,10 @@ return SCPE_OK;
/* Memory examine */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
{
int32 st;
uint32 addr = (uint32) exta;
if (vptr == NULL) return SCPE_ARG;
if (sw & SWMASK ('V')) addr = Test (addr, RD, &st);
@@ -2372,9 +2375,10 @@ return SCPE_NXM;
/* Memory deposit */
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
{
int32 st;
uint32 addr = (uint32) exta;
if (sw & SWMASK ('V')) addr = Test (addr, RD, &st);
else addr = addr & PAMASK;
@@ -2393,7 +2397,7 @@ return SCPE_NXM;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i, clim;
uint32 i, clim;
uint32 *nM = NULL;
if ((val <= 0) || (val > MAXMEMSIZE)) return SCPE_ARG;
@@ -2402,7 +2406,7 @@ if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE))
return SCPE_OK;
nM = calloc (val >> 2, sizeof (uint32));
if (nM == NULL) return SCPE_MEM;
clim = (((t_addr) val) < MEMSIZE)? val: MEMSIZE;
clim = (uint32) ((((uint32) val) < MEMSIZE)? val: MEMSIZE);
for (i = 0; i < clim; i = i + 4) nM[i >> 2] = M[i >> 2];
free (M);
M = nM;
@@ -2414,7 +2418,7 @@ return SCPE_OK; }
t_stat cpu_show_virt (UNIT *uptr, int32 val, char *cptr, void *desc)
{
t_stat r;
t_addr va, pa;
uint32 va, pa;
int32 st;
static const char *mm_str[] = {
"Access control violation",
@@ -2426,7 +2430,7 @@ static const char *mm_str[] = {
"Process PTE translation not valid" };
if (cptr == NULL) return SCPE_ARG;
va = (t_addr) get_uint (cptr, 16, 0xFFFFFFFF, &r);
va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r);
if (r != SCPE_OK) return SCPE_ARG;
pa = Test (va, RD, &st);
if (st == PR_OK) printf ("Virtual %-X = physical %-X\n", va, pa);

View File

@@ -1,6 +1,6 @@
/* vax_cpu1.c: VAX complex instructions
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"),
@@ -101,15 +101,15 @@ extern int32 ibcnt, ppc;
extern int32 cpu_log;
extern FILE *sim_log;
extern int32 Read (t_addr va, int32 lnt, int32 acc);
extern void Write (t_addr va, int32 val, int32 lnt, int32 acc);
extern int32 Test (t_addr va, int32 acc, int32 *status);
extern int32 ReadLP (t_addr pa);
extern void WriteLP (t_addr pa, int32 val);
extern int32 Read (uint32 va, int32 lnt, int32 acc);
extern void Write (uint32 va, int32 val, int32 lnt, int32 acc);
extern int32 Test (uint32 va, int32 acc, int32 *status);
extern int32 ReadLP (uint32 pa);
extern void WriteLP (uint32 pa, int32 val);
extern void set_map_reg (void);
extern void zap_tb (int stb);
extern void zap_tb_ent (t_addr va);
extern t_bool chk_tb_ent (t_addr va);
extern void zap_tb_ent (uint32 va);
extern t_bool chk_tb_ent (uint32 va);
extern int32 ReadIPR (int32 rg);
extern void WriteIPR (int32 rg, int32 val);
extern jmp_buf save_env;

View File

@@ -1,6 +1,6 @@
/* vax_defs.h: VAX architecture definitions file
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"),
@@ -26,10 +26,18 @@
The author gratefully acknowledges the help of Stephen Shirron, Antonio
Carlini, and Kevin Peterson in providing specifications for the Qbus VAX's
19-May-03 RMS Revised for new conditional compilation scheme
14-Jul-02 RMS Added infinite loop message
30-Apr-02 RMS Added CLR_TRAPS macro
*/
#ifndef _VAX_DEFS_H
#define _VAX_DEFS_H 0
#ifndef VM_VAX
#define VM_VAX 0
#endif
#include "sim_defs.h"
#include <setjmp.h>
@@ -563,3 +571,5 @@ enum opcodes {
/* Model dependent definitions */
#include "vaxmod_defs.h"
#endif /* _VAX_DEFS_H */

View File

@@ -1,14 +1,14 @@
To: Users
From: Bob Supnik
Subj: VAX Simulator Usage
Date: 15-Nov-2002
Date: 15-Jun-2003
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2002, written by Robert M Supnik
Copyright (c) 1993-2002, Robert M Supnik
Original code published in 1993-2003, written by Robert M Supnik
Copyright (c) 1993-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"),
@@ -36,12 +36,10 @@ This memorandum documents the VAX simulator.
1. Simulator Files
To compile the VAX, you must define USE_INT64 as part of the compilation
To compile the VAX, you must define VM_VAX and USE_INT64 as part of the compilation
command line.
sim/ dec_dz.h
dec_pt.h
sim_defs.h
sim/ sim_defs.h
sim_ether.h
sim_rev.h
sim_sock.h
@@ -65,6 +63,7 @@ sim/vax/ vax_defs.h
sim/pdp11/ pdp11_mscp.h
pdp11_uqssp.h
pdp11_xq.h
pdp11_xq_bootrom.h
pdp11_dz.c
pdp11_lp.c
pdp11_pt.c
@@ -100,9 +99,10 @@ RQD fourth RQDX3 MSCP controller with four drives
TS TSV11/TSV05 magnetic tape controller with one drive
TQ TQK50 TMSCP magnetic tape controller with four drives
XQ DELQA/DEQNA Ethernet controller
XQB second DELQA/DEQNA Ethernet controller
The PTR, PTP, LPT, DZ, RL, RQ, RQB, RQC, RQD, TS, TQ, and XQ devices can
be set DISABLED. RQB, RQC, and RQD are disabled by default.
The PTR, PTP, LPT, DZ, RL, RQ, RQB, RQC, RQD, TS, TQ, XQ, and XQB devices
can be set DISABLED. RQB, RQC, RQD, and XQB are disabled by default.
The VAX simulator implements several unique stop conditions:
@@ -227,6 +227,14 @@ using the LOAD -r command:
LOAD -r KA655.BIN -- load boot ROM image KA655.BIN
ROM accesses a use a calibrated delay that slows ROM-based execution to
about 500K instructions per second. This delay is required to make the
power-up self-test routines run correctly on very fast hosts. The delay
is controlled with the commands:
SET ROM NODELAY -- ROM runs like RAM
SET ROM DELAY -- ROM runs slowly
2.1.4 Non-volatile Memory (NVR)
The NVR consists of a single unit, representing 1KB of battery-backed up
@@ -320,7 +328,7 @@ longer recognizes the explicitly configured device. A device can be
reset to autoconfigure with the SET <device> AUTOCONFIGURE command.
The current I/O map can be displayed with the SHOW CPU IOSPACE command.
Address that have set by autoconfiguration are marked with an asterisk (*).
Addresses that have set by autoconfiguration are marked with an asterisk (*).
All devices support the SHOW ADDRESS and SHOW VECTOR commands, which display
the device address and vector, respectively.
@@ -780,9 +788,10 @@ Error handling is as follows:
OS I/O error report error and stop
2.8 DELQA/DEQNA Ethernet Controller (XQ)
2.8 DELQA/DEQNA Qbus Ethernet Controllers (XQ, XQB)
XQ simulates the DELQA/DEQNA 10Mbps Ethernet controller. Options allow
The simulator implements two DELQA/DEQNA Qbus Ethernet controllers (XQ,
XQB). Initially, XQ is enabled, and XQB is disabled. Options allow
control of the MAC address, the controller mode, and the sanity timer.
SET XQ MAC=<mac-address> ex. 08-00-2B-AA-BB-CC

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* vax_io.c: VAX Qbus IO 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"),
@@ -25,7 +25,9 @@
qba Qbus adapter
22-Dec-02 RMS Addec console halt support
19-Apr-03 RMS Added optimized byte and word DMA routines
12-Mar-03 RMS Added logical name support
22-Dec-02 RMS Added console halt support
12-Oct-02 RMS Added autoconfigure support
Added SHOW IO space routine
29-Sep-02 RMS Added dynamic table support
@@ -101,12 +103,12 @@ extern int32 ssc_bto;
extern jmp_buf save_env;
extern DEVICE *sim_devices[];
extern int32 ReadB (t_addr pa);
extern int32 ReadW (t_addr pa);
extern int32 ReadL (t_addr pa);
extern int32 WriteB (t_addr pa, int32 val);
extern int32 WriteW (t_addr pa, int32 val);
extern int32 WriteL (t_addr pa, int32 val);
extern int32 ReadB (uint32 pa);
extern int32 ReadW (uint32 pa);
extern int32 ReadL (uint32 pa);
extern int32 WriteB (uint32 pa, int32 val);
extern int32 WriteW (uint32 pa, int32 val);
extern int32 WriteL (uint32 pa, int32 val);
extern FILE *sim_log;
t_stat dbl_rd (int32 *data, int32 addr, int32 access);
@@ -409,7 +411,7 @@ return;
int32 cqmem_rd (int32 pa)
{
int32 qa = pa & CQMAMASK; /* Qbus addr */
t_addr ma;
uint32 ma;
if (map_addr (qa, &ma)) return M[ma >> 2]; /* map addr */
MACH_CHECK (MCHK_READ); /* err? mcheck */
@@ -419,7 +421,7 @@ return 0;
void cqmem_wr (int32 pa, int32 val, int32 lnt)
{
int32 qa = pa & CQMAMASK; /* Qbus addr */
t_addr ma;
uint32 ma;
if (map_addr (qa, &ma)) { /* map addr */
if (lnt < L_LONG) {
@@ -434,7 +436,7 @@ return;
/* Map an address via the translation map */
t_bool map_addr (t_addr qa, t_addr *ma)
t_bool map_addr (uint32 qa, uint32 *ma)
{
int32 qblk = (qa >> VA_V_VPN); /* Qbus blk */
int32 qmma = ((qblk << 2) & CQMAPAMASK) + cq_mbr; /* map entry */
@@ -511,40 +513,64 @@ return qba_reset (&qba_dev);
map_WriteL - store longword buffer into memory
*/
int32 map_readB (t_addr ba, int32 bc, uint8 *buf)
int32 map_readB (uint32 ba, int32 bc, uint8 *buf)
{
int32 i;
t_addr ma;
uint32 ma, dat;
for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
*buf = ReadB (ma);
ma = ma + 1; }
if ((ba | bc) & 03) { /* check alignment */
for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
*buf = ReadB (ma);
ma = ma + 1; }
}
else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
dat = ReadL (ma); /* get lw */
*buf++ = dat & BMASK; /* low 8b */
*buf++ = (dat >> 8) & BMASK; /* next 8b */
*buf++ = (dat >> 16) & BMASK; /* next 8b */
*buf = (dat >> 24) & BMASK;
ma = ma + 4; }
}
return 0;
}
int32 map_readW (t_addr ba, int32 bc, uint16 *buf)
int32 map_readW (uint32 ba, int32 bc, uint16 *buf)
{
int32 i;
t_addr ma;
uint32 ma,dat;
ba = ba & ~01;
bc = bc & ~01;
for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
*buf = ReadW (ma);
ma = ma + 2; }
if ((ba | bc) & 03) { /* check alignment */
for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
*buf = ReadW (ma);
ma = ma + 2; }
}
else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
dat = ReadL (ma); /* get lw */
*buf++ = dat & WMASK; /* low 16b */
*buf = (dat >> 16) & WMASK; /* high 16b */
ma = ma + 4; }
}
return 0;
}
int32 map_readL (t_addr ba, int32 bc, uint32 *buf)
int32 map_readL (uint32 ba, int32 bc, uint32 *buf)
{
int32 i;
t_addr ma;
uint32 ma;
ba = ba & ~03;
bc = bc & ~03;
@@ -557,40 +583,64 @@ for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by lw */
return 0;
}
int32 map_writeB (t_addr ba, int32 bc, uint8 *buf)
int32 map_writeB (uint32 ba, int32 bc, uint8 *buf)
{
int32 i;
t_addr ma;
uint32 ma, dat;
for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
WriteB (ma, *buf);
ma = ma + 1; }
if ((ba | bc) & 03) { /* check alignment */
for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
WriteB (ma, *buf);
ma = ma + 1; }
}
else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
dat = (uint32) *buf++; /* get low 8b */
dat = dat | (((uint32) *buf++) << 8); /* merge next 8b */
dat = dat | (((uint32) *buf++) << 16); /* merge next 8b */
dat = dat | (((uint32) *buf) << 24); /* merge hi 8b */
WriteL (ma, dat); /* store lw */
ma = ma + 4; }
}
return 0;
}
int32 map_writeW (t_addr ba, int32 bc, uint16 *buf)
int32 map_writeW (uint32 ba, int32 bc, uint16 *buf)
{
int32 i;
t_addr ma;
uint32 ma, dat;
ba = ba & ~01;
bc = bc & ~01;
for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
WriteW (ma, *buf);
ma = ma + 2; }
if ((ba | bc) & 03) { /* check alignment */
for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
WriteW (ma, *buf);
ma = ma + 2; }
}
else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */
if ((ma & VA_M_OFF) == 0) { /* need map? */
if (!map_addr (ba + i, &ma) || /* inv or NXM? */
!ADDR_IS_MEM (ma)) return (bc - i); }
dat = (uint32) *buf++; /* get low 16b */
dat = dat | (((uint32) *buf) << 16); /* merge hi 16b */
WriteL (ma, dat); /* store lw */
ma = ma + 4; }
}
return 0;
}
int32 map_writeL (t_addr ba, int32 bc, uint32 *buf)
int32 map_writeL (uint32 ba, int32 bc, uint32 *buf)
{
int32 i;
t_addr ma;
uint32 ma;
ba = ba & ~03;
bc = bc & ~03;
@@ -722,9 +772,11 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
(curr->ba < (dibp->ba + dibp->lnt))) ||
((end >= dibp->ba) && /* overlap end? */
(end < (dibp->ba + dibp->lnt)))) {
printf ("Device %s address conflict at %08X\n", dptr->name, dibp->ba);
printf ("Device %s address conflict at %08X\n",
sim_dname (dptr), dibp->ba);
if (sim_log) fprintf (sim_log,
"Device %s address conflict at %08X\n", dptr->name, dibp->ba);
"Device %s address conflict at %08X\n",
sim_dname (dptr), dibp->ba);
return TRUE; } }
return FALSE;
}
@@ -797,7 +849,7 @@ for (i = 0; dib_tab[i] != NULL; i++) { /* print table */
fprintf (st, "%08X - %08X%c\t%s\n", dib_tab[i]->ba,
dib_tab[i]->ba + dib_tab[i]->lnt - 1,
(dptr && (dptr->flags & DEV_FLTA))? '*': ' ',
dptr? dptr->name: "CPU");
dptr? sim_dname (dptr): "CPU");
}
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* vax_mm.c - VAX memory management 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"),
@@ -23,6 +23,8 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
01-Jun-03 RMS Fixed compilation problem with USE_ADDR64
This module contains the instruction simulators for
Read - read virtual
@@ -95,19 +97,19 @@ t_stat tlb_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat tlb_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat tlb_reset (DEVICE *dptr);
TLBENT fill (t_addr va, int32 lnt, int32 acc, int32 *stat);
int32 ReadB (t_addr pa);
void WriteB (t_addr pa, int32 val);
int32 ReadW (t_addr pa);
void WriteW (t_addr pa, int32 val);
int32 ReadL (t_addr pa);
void WriteL (t_addr pa, int32 val);
int32 ReadLP (t_addr pa);
void WriteLP (t_addr pa, int32 val);
extern int32 ReadIO (t_addr pa, int32 lnt);
extern void WriteIO (t_addr pa, int32 val, int32 lnt);
extern int32 ReadReg (t_addr pa, int32 lnt);
extern void WriteReg (t_addr pa, int32 val, int32 lnt);
TLBENT fill (uint32 va, int32 lnt, int32 acc, int32 *stat);
int32 ReadB (uint32 pa);
void WriteB (uint32 pa, int32 val);
int32 ReadW (uint32 pa);
void WriteW (uint32 pa, int32 val);
int32 ReadL (uint32 pa);
void WriteL (uint32 pa, int32 val);
int32 ReadLP (uint32 pa);
void WriteLP (uint32 pa, int32 val);
extern int32 ReadIO (uint32 pa, int32 lnt);
extern void WriteIO (uint32 pa, int32 val, int32 lnt);
extern int32 ReadReg (uint32 pa, int32 lnt);
extern void WriteReg (uint32 pa, int32 val, int32 lnt);
/* TLB data structures
@@ -156,7 +158,7 @@ DEVICE tlb_dev = {
returned data, right justified in 32b longword
*/
int32 Read (t_addr va, int32 lnt, int32 acc)
int32 Read (uint32 va, int32 lnt, int32 acc)
{
int32 vpn, off, tbi, pa;
int32 pa1, bo, sc, wl, wh;
@@ -209,7 +211,7 @@ else { wl = ReadL (pa); /* word cross lw */
none
*/
void Write (t_addr va, int32 val, int32 lnt, int32 acc)
void Write (uint32 va, int32 val, int32 lnt, int32 acc)
{
int32 vpn, off, tbi, pa;
int32 pa1, bo, sc, wl, wh;
@@ -289,7 +291,7 @@ return va & PAMASK; /* ret phys addr */
returned data, right justified in 32b longword
*/
int32 ReadB (t_addr pa)
int32 ReadB (uint32 pa)
{
int32 dat;
@@ -300,7 +302,7 @@ else { mchk_ref = REF_V;
return ((dat >> ((pa & 3) << 3)) & BMASK);
}
int32 ReadW (t_addr pa)
int32 ReadW (uint32 pa)
{
int32 dat;
@@ -311,7 +313,7 @@ else { mchk_ref = REF_V;
return ((dat >> ((pa & 2)? 16: 0)) & WMASK);
}
int32 ReadL (t_addr pa)
int32 ReadL (uint32 pa)
{
if (ADDR_IS_MEM (pa)) return M[pa >> 2];
mchk_ref = REF_V;
@@ -319,7 +321,7 @@ if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG);
return ReadReg (pa, L_LONG);
}
int32 ReadLP (t_addr pa)
int32 ReadLP (uint32 pa)
{
if (ADDR_IS_MEM (pa)) return M[pa >> 2];
mchk_va = pa;
@@ -337,7 +339,7 @@ return ReadReg (pa, L_LONG);
none
*/
void WriteB (t_addr pa, int32 val)
void WriteB (uint32 pa, int32 val)
{
if (ADDR_IS_MEM (pa)) {
int32 id = pa >> 2;
@@ -350,7 +352,7 @@ else { mchk_ref = REF_V;
return;
}
void WriteW (t_addr pa, int32 val)
void WriteW (uint32 pa, int32 val)
{
if (ADDR_IS_MEM (pa)) {
int32 id = pa >> 2;
@@ -362,7 +364,7 @@ else { mchk_ref = REF_V;
return;
}
void WriteL (t_addr pa, int32 val)
void WriteL (uint32 pa, int32 val)
{
if (ADDR_IS_MEM (pa)) M[pa >> 2] = val;
else { mchk_ref = REF_V;
@@ -371,7 +373,7 @@ else { mchk_ref = REF_V;
return;
}
void WriteLP (t_addr pa, int32 val)
void WriteLP (uint32 pa, int32 val)
{
if (ADDR_IS_MEM (pa)) M[pa >> 2] = val;
else { mchk_va = pa;
@@ -398,7 +400,7 @@ return;
p2 = va; \
ABORT ((param & PR_TNV)? ABORT_TNV: ABORT_ACV); }
TLBENT fill (t_addr va, int32 lnt, int32 acc, int32 *stat)
TLBENT fill (uint32 va, int32 lnt, int32 acc, int32 *stat)
{
int32 ptidx = (((uint32) va) >> 7) & ~03;
int32 tlbpte, ptead, pte, tbi, vpn;
@@ -500,7 +502,7 @@ return FALSE;
t_stat tlb_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
{
int32 tlbn = uptr - tlb_unit;
int32 idx = addr >> 1;
int32 idx = (uint32) addr >> 1;
if (idx >= VA_TBSIZE) return SCPE_NXM;
if (addr & 1) *vptr = ((uint32) (tlbn? stlb[idx].pte: ptlb[idx].pte));
@@ -513,7 +515,7 @@ return SCPE_OK;
t_stat tlb_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
int32 tlbn = uptr - tlb_unit;
int32 idx = addr >> 1;
int32 idx = (uint32) addr >> 1;
if (idx >= VA_TBSIZE) return SCPE_NXM;
if (addr & 1) {

View File

@@ -27,6 +27,7 @@
tto terminal output
clk 100Hz and TODR clock
25-Apr-03 RMS Revised for extended file support
02-Mar-02 RMS Added SET TTI CTRL-C
22-Dec-02 RMS Added console halt capability
01-Nov-02 RMS Added 7B/8B capability to terminal
@@ -93,7 +94,7 @@ REG tti_reg[] = {
{ FLDATA (INT, int_req[IPL_TTI], INT_V_TTI) },
{ FLDATA (DONE, tti_csr, CSR_V_DONE) },
{ FLDATA (IE, tti_csr, CSR_V_IE) },
{ DRDATA (POS, tti_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
@@ -130,7 +131,7 @@ REG tto_reg[] = {
{ FLDATA (INT, int_req[IPL_TTO], INT_V_TTO) },
{ FLDATA (DONE, tto_csr, CSR_V_DONE) },
{ FLDATA (IE, tto_csr, CSR_V_IE) },
{ DRDATA (POS, tto_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ NULL } };

View File

@@ -1,6 +1,6 @@
/* vax_sys.c: VAX simulator interface
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"),
@@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
06-May-03 RMS Added support for second DELQA
12-Oct-02 RMS Added multiple RQ controller support
10-Oct-02 RMS Added DELQA support
21-Sep-02 RMS Extended symbolic ex/mod to all byte devices
@@ -33,17 +34,23 @@
#include "vax_defs.h"
#include <ctype.h>
extern DEVICE cpu_dev, tlb_dev;
extern DEVICE rom_dev, nvr_dev;
extern DEVICE sysd_dev, qba_dev;
extern DEVICE cpu_dev;
extern DEVICE tlb_dev;
extern DEVICE rom_dev;
extern DEVICE nvr_dev;
extern DEVICE sysd_dev;
extern DEVICE qba_dev;
extern DEVICE ptr_dev, ptp_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE csi_dev, cso_dev;
extern DEVICE lpt_dev, clk_dev;
extern DEVICE lpt_dev;
extern DEVICE clk_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
extern DEVICE rl_dev;
extern DEVICE ts_dev, tq_dev;
extern DEVICE dz_dev, xq_dev;
extern DEVICE ts_dev;
extern DEVICE tq_dev;
extern DEVICE dz_dev;
extern DEVICE xq_dev, xqb_dev;
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern uint32 *M;
@@ -52,12 +59,12 @@ extern int32 sim_switches;
extern void WriteB (int32 pa, int32 val);
extern void rom_wr (int32 pa, int32 val, int32 lnt);
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val);
int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt);
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
int32 parse_brdisp (char *cptr, t_addr addr, t_value *val,
t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val);
int32 parse_brdisp (char *cptr, uint32 addr, t_value *val,
int32 vp, int32 lnt, t_stat *r);
int32 parse_spec (char *cptr, t_addr addr, t_value *val,
int32 parse_spec (char *cptr, uint32 addr, t_value *val,
int32 vp, int32 disp, t_stat *r);
char *parse_rnum (char *cptr, int32 *rn);
int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp,
@@ -103,6 +110,7 @@ DEVICE *sim_devices[] = {
&ts_dev,
&tq_dev,
&xq_dev,
&xqb_dev,
NULL };
const char *sim_stop_messages[] = {
@@ -135,7 +143,7 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
t_stat r;
int32 i;
t_addr origin, limit;
uint32 origin, limit;
extern int32 ssc_cnf;
#define SSCCNF_BLO 0x80000000
@@ -148,7 +156,7 @@ else if (sim_switches & SWMASK ('N')) { /* NVR? */
limit = NVRBASE + NVRSIZE;
ssc_cnf = ssc_cnf & ~SSCCNF_BLO; }
else { origin = 0; /* memory */
limit = cpu_unit.capac;
limit = (uint32) cpu_unit.capac;
if (sim_switches & SWMASK ('O')) { /* origin? */
origin = (int32) get_uint (cptr, 16, 0xFFFFFFFF, &r);
if (r != SCPE_OK) return SCPE_ARG; } }
@@ -189,7 +197,7 @@ int32 *buf;
if ((sec < 2) || (wds < 16)) return SCPE_ARG;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK;
da = (uptr->capac - (sec * wds)) * sizeof (int16);
da = (int32) (uptr->capac - (sec * wds)) * sizeof (int16);
if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR;
if ((buf = malloc (wds * sizeof (int32))) == NULL) return SCPE_MEM;
buf[0] = 0x12345678;
@@ -821,9 +829,10 @@ const char* regname[] = {
if < 0, number of extra bytes retired
*/
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
t_stat fprint_sym (FILE *of, t_addr exta, t_value *val,
UNIT *uptr, int32 sw)
{
uint32 addr = (uint32) exta;
int32 c, k, num, vp, lnt, rdx;
t_stat r;
DEVICE *dptr;
@@ -869,7 +878,7 @@ return -(vp - 1);
if < 0, number of extra bytes retired
*/
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val)
{
int32 i, k, vp, inst, numspec;
int32 num, spec, rn, disp, index;
@@ -999,8 +1008,9 @@ return vp;
<= 0 -number of extra words
*/
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
t_stat parse_sym (char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw)
{
uint32 addr = (uint32) exta;
int32 k, rdx, lnt, num, vp;
t_stat r;
DEVICE *dptr;
@@ -1047,7 +1057,7 @@ return -(lnt - 1);
<= 0 -number of extra words
*/
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val)
{
int32 i, numspec, disp, opc, vp;
t_stat r;
@@ -1090,7 +1100,7 @@ return -(vp - 1);
vp = updated output pointer
*/
int32 parse_brdisp (char *cptr, t_addr addr, t_value *val, int32 vp,
int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, int32 vp,
int32 lnt, t_stat *r)
{
int32 k, dest, num;
@@ -1133,7 +1143,7 @@ return vp;
#define PARSE_LOSE { *r = SCPE_ARG; return vp; }
#define SEL_LIM(p,m,u) ((fl & SP_PLUS)? (p): ((fl & SP_MINUS)? (m): (u)))
int32 parse_spec (char *cptr, t_addr addr, t_value *val, int32 vp, int32 disp, t_stat *r)
int32 parse_spec (char *cptr, uint32 addr, t_value *val, int32 vp, int32 disp, t_stat *r)
{
int32 i, k, litsize, rn, index;
int32 num, dispsize, mode;

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

View File

@@ -85,7 +85,7 @@
#define MAXMEMMASK (MAXMEMSIZE - 1) /* max mem addr mask */
#define INITMEMSIZE (1 << 24) /* initial memory size */
#define MEMSIZE (cpu_unit.capac)
#define ADDR_IS_MEM(x) (((t_addr) (x)) < MEMSIZE)
#define ADDR_IS_MEM(x) (((uint32) (x)) < MEMSIZE)
/* Cache diagnostic space */
@@ -101,8 +101,8 @@
#define CDG_GETTAG(x) (((x) >> CDAAWIDTH) & CTGMASK)
#define CTG_V (1u << (CTGAWIDTH + 0)) /* tag valid */
#define CTG_WP (1u << (CTGAWIDTH + 1)) /* wrong parity */
#define ADDR_IS_CDG(x) ((((t_addr) (x)) >= CDGBASE) && \
(((t_addr) (x)) < (CDGBASE + CDGSIZE)))
#define ADDR_IS_CDG(x) ((((uint32) (x)) >= CDGBASE) && \
(((uint32) (x)) < (CDGBASE + CDGSIZE)))
/* Qbus I/O registers */
@@ -110,8 +110,8 @@
#define IOPAGESIZE (1u << IOPAGEAWIDTH) /* IO page length */
#define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */
#define IOPAGEBASE 0x20000000 /* IO page base */
#define ADDR_IS_IO(x) ((((t_addr) (x)) >= IOPAGEBASE) && \
(((t_addr) (x)) < (IOPAGEBASE + IOPAGESIZE)))
#define ADDR_IS_IO(x) ((((uint32) (x)) >= IOPAGEBASE) && \
(((uint32) (x)) < (IOPAGEBASE + IOPAGESIZE)))
/* Read only memory - appears twice */
@@ -119,8 +119,8 @@
#define ROMSIZE (1u << ROMAWIDTH) /* ROM length */
#define ROMAMASK (ROMSIZE - 1) /* ROM addr mask */
#define ROMBASE 0x20040000 /* ROM base */
#define ADDR_IS_ROM(x) ((((t_addr) (x)) >= ROMBASE) && \
(((t_addr) (x)) < (ROMBASE + ROMSIZE + ROMSIZE)))
#define ADDR_IS_ROM(x) ((((uint32) (x)) >= ROMBASE) && \
(((uint32) (x)) < (ROMBASE + ROMSIZE + ROMSIZE)))
/* Local register space */
@@ -161,8 +161,8 @@
#define NVRSIZE (1u << NVRAWIDTH) /* NVR length */
#define NVRAMASK (NVRSIZE - 1) /* NVR addr mask */
#define NVRBASE 0x20140400 /* NVR base */
#define ADDR_IS_NVR(x) ((((t_addr) (x)) >= NVRBASE) && \
(((t_addr) (x)) < (NVRBASE + NVRSIZE)))
#define ADDR_IS_NVR(x) ((((uint32) (x)) >= NVRBASE) && \
(((uint32) (x)) < (NVRBASE + NVRSIZE)))
/* CQBIC Qbus memory space (seen from CVAX) */
@@ -211,6 +211,8 @@
#define UNIBUS FALSE /* 22b only */
#define DEV_RDX 16 /* default device radix */
/* Device information block */
#define VEC_DEVMAX 4 /* max device vec */
@@ -223,7 +225,7 @@ struct pdp_dib {
int32 vnum; /* vectors: number */
int32 vloc; /* locator */
int32 vec; /* value */
int32 (*ack[VEC_DEVMAX])(void); /* ack routines */
int32 (*ack[VEC_DEVMAX])(void); /* ack routine */
};
typedef struct pdp_dib DIB;
@@ -386,13 +388,13 @@ typedef struct pdp_dib DIB;
/* Function prototypes for I/O */
t_bool map_addr (t_addr qa, t_addr *ma);
int32 map_readB (t_addr ba, int32 bc, uint8 *buf);
int32 map_readW (t_addr ba, int32 bc, uint16 *buf);
int32 map_readL (t_addr ba, int32 bc, uint32 *buf);
int32 map_writeB (t_addr ba, int32 bc, uint8 *buf);
int32 map_writeW (t_addr ba, int32 bc, uint16 *buf);
int32 map_writeL (t_addr ba, int32 bc, uint32 *buf);
t_bool map_addr (uint32 qa, uint32 *ma);
int32 map_readB (uint32 ba, int32 bc, uint8 *buf);
int32 map_readW (uint32 ba, int32 bc, uint16 *buf);
int32 map_readL (uint32 ba, int32 bc, uint32 *buf);
int32 map_writeB (uint32 ba, int32 bc, uint8 *buf);
int32 map_writeW (uint32 ba, int32 bc, uint16 *buf);
int32 map_writeL (uint32 ba, int32 bc, uint32 *buf);
#define Map_Addr(a,b) map_addr (a, b)
#define Map_ReadB(a,b,c,d) map_readB (a, b, c)