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

simh 3.10-RC1a

3.10 is mostly an attempt to get aligned with the current head of the
GitHub 4.0 sources. While the core libraries and SCP have diverged too
far for real forward and backward compatibility, enough 4.0 workalikes
have been added to allow much closer convergence of the two streams.

3.10 will provide the basis for my future simulation work.
This commit is contained in:
Bob Supnik
2018-06-04 07:59:42 -07:00
committed by Mark Pizzolato
parent 140ab5b350
commit 3fada8da5a
75 changed files with 5555 additions and 24986 deletions

View File

@@ -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.
17-Mar-16 PLB Added GRAPHICS-2 support for PDP-7 UNIX
10-Mar-16 RMS Added 3-cycle databreak set/show routines
26-Feb-16 RMS Added RB09 to PDP-7 for Unix "v0" and RM09 to PDP-9
13-Sep-15 RMS Added DR15C
@@ -82,6 +83,7 @@
Type 550/555 DECtape
Type 24 serial drum
RB09 fixed head disk (Unix V0 only)
Bell Labs GRAPHICS-2 (Unix V0 only)
PDP9 32K KE09A EAE KSR-33 Teletype
KF09A auto pri intr PC09A paper tape reader and punch
@@ -105,7 +107,7 @@
TC59D magnetic tape
TC15/TU56 DECtape
LT15/LT19 additional Teletypes
DR15C parallel interface to UC15
DR15C parallel interface to UC15
??Indicates not implemented. The PDP-4 manual refers to a memory
??extension control; there is no documentation on it.
@@ -142,6 +144,7 @@
#define TYPE550 0 /* DECtape */
#define DRM 0 /* drum */
#define RB 0 /* fixed head disk */
#define GRAPHICS2 0 /* BTL display */
#elif defined (PDP9)
#define ADDRSIZE 15
#define TYPE647 0 /* sixbit printer */
@@ -162,6 +165,7 @@
#define MTA 0 /* magtape */
#define TC02 0 /* DECtape */
#define TTY1 16 /* second Teletype(s) */
#define UC15 0 /* UC15 */
#define BRMASK 0377400 /* bounds mask */
#define BRMASK_XVM 0777400 /* bounds mask, XVM */
#endif
@@ -287,6 +291,29 @@ typedef struct {
#define DEV_MT 073 /* magtape */
#define DEV_DTA 075 /* dectape */
#ifdef GRAPHICS2
/* Bell Telephone Labs GRAPHICS-2 Display System ("as large as the PDP-7")
* Used by PDP-7 UNIX as a "Glass TTY"
*/
#define DEV_G2D1 005 /* Display Ctrl 1 */
#define DEV_G2D 006 /* (Display Ctrl 2) */
#define DEV_G2LP 007 /* (Light Pen) */
#define DEV_G2DS 010 /* (Display Status) */
#define DEV_G2D3 014 /* (Display Ctrl 3) */
#define DEV_G2D4 034 /* (Display Ctrl 4) */
#define DEV_G2UNK 042 /* (???) */
#define DEV_G2KB 043 /* Keyboard */
#define DEV_G2BB 044 /* Button Box */
#define DEV_G2IM 045 /* (PDP7 int. mask) */
/* PDP-7/9 to 201A Data Phone Interface
* (status bits retrieved with G2DS IOT)
* used for UNIX to GCOS Remote Job Entry
*/
#define DEV_DP 047 /* (Data Phone) */
#endif
/* Interrupt system
The interrupt system can be modelled on either the flag driven system
@@ -433,6 +460,7 @@ typedef struct {
#define INT_V_TTI 0 /* console keyboard */
#define INT_V_TTO 1 /* console output */
#define INT_V_PTP 2 /* paper tape punch */
#define INT_V_G2 3 /* BTL GRAPHICS-2 */
#define INT_TTI (1 << INT_V_TTI)
#define INT_TTO (1 << INT_V_TTO)
@@ -442,6 +470,15 @@ typedef struct {
#define API_TTO 4
#define API_PTP 4
#ifdef GRAPHICS2
/*
* A PDP-9 version existed,
* but we're only interested simulating a PDP-7 without API
*/
#define INT_G2 (1 << INT_V_G2)
#define API_G2 4
#endif
/* Interrupt macros */
#define SET_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] | INT_##dv
@@ -452,7 +489,7 @@ typedef struct {
This allows software to have a single definition for the interrupt bit position,
regardless of level. The standard macros cannot be used. */
#define INT_V_DR 7 /* to left of all */
#define INT_V_DR 9 /* to left of all */
#define INT_DR (1 << INT_V_DR)
#define API_DR0 0
#define API_DR1 1
@@ -522,4 +559,10 @@ t_stat show_3cyc_reg (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 clk_cosched (int32 wait);
/* Translation tables */
extern const int32 asc_to_baud[128];
extern const char baud_to_asc[64];
extern const char fio_to_asc[64];
#endif

339
PDP18B/pdp18b_dr15.c Normal file
View File

@@ -0,0 +1,339 @@
/* pdp18b_dr15.c: DR15C simulator
Copyright (c) 2016, 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"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not 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.
dr PDP-15 DR15C interface for UC15 system
The DR15C provides control communications with the DR11Cs in the UC15.
Its state consists of an 18b register (the Task Control Block Pointer),
a one bit flag (TCBP acknowledge, not wired to interrupt), four interrupt
requests wired to API, four interrupt vectors for the API levels, and an
API interrupt enable/disable flag.
The PDP15 and UC15 use a master/save communications protocol.
- The PDP15 initiates a request to the PDP11 by writing TCBP and
clearing TCBP acknowledge. This alerts/interrupts the PDP11.
- The PDP11 reads TCBP. This sets TCBP acknowledge.
- The PDP11 processes the request.
- The PDP11 signals completion by writing a vector into one of
four API request levels.
- The PDP15 is interrupted, and the request is considered complete.
The DR15 must "call out" to the UC15 to signal two conditions:
- a new TCBP has been written
- API requests have been updated
The UC15 must "call in" to the DR15 for two reasons:
- the TCBP has been read
- an API interrupt is requested
The DR15 and UC15 use a shared memory section and ATOMIC operations
to communicate. Shared state is maintained in shared memory, with one
side having read/write access, the other read-only. Actions are
implemented by setting signals with an atomic compare-and-swap.
The signals may be polled with non-atomic operations but must be
verified with an atomic compare-and-swap.
Debug hooks - when DEBUG is turned on, the simulator will print
information relating to PIREX operation.
*/
#include "pdp18b_defs.h"
#include "sim_shmem.h"
#include "uc15_defs.h"
/* Declarations */
extern int32 int_hwre[API_HLVL+1];
extern int32 api_vec[API_HLVL][32];
extern int32 *M;
extern UNIT cpu_unit;
uint32 dr15_tcbp = 0; /* buffer = TCB ptr */
int32 dr15_tcb_ack = 0; /* TCBP write ack */
int32 dr15_ie = 0; /* int enable */
uint32 dr15_int_req = 0; /* int req 0-3 */
int32 dr15_poll = 3; /* polling interval */
SHMEM *uc15_shmem = NULL; /* shared state identifier */
int32 *uc15_shstate = NULL; /* shared state base */
SHMEM *pdp15_shmem = NULL; /* PDP15 mem identifier */
DEVICE dr15_dev;
int32 dr60 (int32 dev, int32 pulse, int32 AC);
int32 dr61 (int32 dev, int32 pulse, int32 AC);
t_stat dr15_reset (DEVICE *dptr);
void dr15_set_clr_ie (int32 val);
t_stat dr15_svc (UNIT *uptr);
t_stat dr15_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat dr15_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat dr15_attach (UNIT *uptr, char *cptr);
t_stat dr15_detach (UNIT *uptr);
t_stat uc15_new_api (int32 val); /* callouts */
t_stat uc15_tcbp_wr (int32 val);
/* DR15 data structures
dr15_dev DR15 device descriptor
dr15_unit DR15 unit descriptor
dr15_reg DR15 register list
*/
DIB dr15_dib = { DEV_DR, 2 ,NULL, { &dr60, &dr61 } };
UNIT dr15_unit = {
UDATA (&dr15_svc, UNIT_FIX+UNIT_BINK+UNIT_ATTABLE, UC15_STATE_SIZE)
};
REG dr15_reg[] = {
{ ORDATA (TCBP, dr15_tcbp, ADDRSIZE) },
{ FLDATA (TCBACK, dr15_tcb_ack, 0) },
{ FLDATA (IE, dr15_ie, 0) },
{ ORDATA (REQ, dr15_int_req, 4) },
{ FLDATA (API0, int_hwre[API_DR0], INT_V_DR) },
{ FLDATA (API1, int_hwre[API_DR1], INT_V_DR) },
{ FLDATA (API2, int_hwre[API_DR2], INT_V_DR) },
{ FLDATA (API3, int_hwre[API_DR3], INT_V_DR) },
{ ORDATA (APIVEC0, api_vec[API_DR0][INT_V_DR], 7) },
{ ORDATA (APIVEC1, api_vec[API_DR1][INT_V_DR], 7) },
{ ORDATA (APIVEC2, api_vec[API_DR2][INT_V_DR], 7) },
{ ORDATA (APIVEC3, api_vec[API_DR3][INT_V_DR], 7) },
{ DRDATA (POLL, dr15_poll, 10), REG_NZ },
{ ORDATA (DEVNO, dr15_dib.dev, 6), REG_HRO },
{ NULL }
};
MTAB dr15_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", NULL, &show_devno },
{ 0 }
};
DEVICE dr15_dev = {
"DR", &dr15_unit, dr15_reg, dr15_mod,
1, 8, 10, 1, 8, 32,
&dr15_ex, &dr15_dep, &dr15_reset,
NULL, &dr15_attach, &dr15_detach,
&dr15_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG
};
/* IOT routines */
int32 dr60 (int32 dev, int32 pulse, int32 AC)
{
int32 subdev = (pulse >> 4) & 03;
if (((pulse & 01) != 0) && (dr15_tcb_ack != 0)) /* SIOA */
AC |= IOT_SKP;
if ((pulse & 02) != 0) /* CIOP */
dr15_tcb_ack = 0;
if ((pulse & 04) != 0) { /* LIOR */
dr15_tcbp = AC & AMASK; /* top bit zero */
uc15_tcbp_wr (dr15_tcbp); /* inform UC15 */
}
return AC;
}
int32 dr61 (int32 dev, int32 pulse, int32 AC)
{
int32 subdev = (pulse >> 4) & 03;
if (pulse & 01) { /* SAPIn */
if (((dr15_int_req >> subdev) & 01) != 0)
AC = AC | IOT_SKP;
}
if (pulse & 02) {
if (subdev == 0) /* RDRS */
AC |= dr15_ie;
else if (subdev == 1)
dr15_set_clr_ie (AC & 1);
}
if (pulse & 04) { /* CAPI */
int32 old_int_req = dr15_int_req;
dr15_int_req &= ~(1 << subdev); /* clear local req */
int_hwre[subdev] &= ~INT_DR; /* clear hwre req */
if (dr15_int_req != old_int_req) /* state change? */
uc15_new_api (dr15_int_req); /* inform UC15 */
}
return AC;
}
/* Set/clear interrupt enable */
void dr15_set_clr_ie (int32 val)
{
int32 i;
dr15_ie = val;
for (i = 0; i < 4; i++) {
if ((dr15_ie != 0) && (((dr15_int_req >> i) & 01) != 0))
int_hwre[i] |= INT_DR;
else int_hwre[i] &= ~INT_DR;
}
return;
}
/* Routines to inform UC15 of state changes */
t_stat uc15_new_api (int32 req)
{
UC15_SHARED_WR (UC15_API_SUMM, req); /* new value */
UC15_ATOMIC_CAS (UC15_API_UPD, 0, 1); /* signal UC15 */
return SCPE_OK;
}
t_stat uc15_tcbp_wr (int32 tcbp)
{
UC15_SHARED_WR (UC15_TCBP, tcbp); /* new value */
UC15_ATOMIC_CAS (UC15_TCBP_WR, 0, 1); /* signal UC15 */
if (DEBUG_PRS (dr15_dev)) {
uint32 apiv, apil, fnc, tsk;
t_bool spl;
apiv = (M[tcbp] >> 8) & 0377;
apil = M[tcbp] & 0377;
fnc = (M[tcbp + 1] >> 8) & 0377;
spl = (M[tcbp + 1] & 0200) != 0;
tsk = (M[tcbp + 1] & 0177);
fprintf (sim_deb, ">> DR15: TCB write, API = %o/%d, fnc = %o, %s task = %o, eventvar = %o\n",
apiv, apil, fnc, spl? "Spooled": "Unspooled", tsk, M[tcbp + 2]);
fprintf (sim_deb, "Additional parameters = %o %o %o %o %o\n",
M[tcbp + 3], M[tcbp + 4], M[tcbp + 5], M[tcbp + 6], M[tcbp + 7]);
}
return SCPE_OK;
}
/* Routine to poll for state changes from UC15 */
t_stat dr15_svc (UNIT *uptr)
{
int32 i, t;
uint32 old_int_req = dr15_int_req;
t = UC15_SHARED_RD (UC15_TCBP_RD); /* TCBP read? */
if ((t != 0) && UC15_ATOMIC_CAS (UC15_TCBP_RD, 1, 0)) /* for real? clear */
dr15_tcb_ack = 1; /* set ack */
for (i = 0; i < 4; i++) { /* API req */
t = UC15_SHARED_RD (UC15_API_REQ + (i * UC15_API_VEC_MUL));
if ((t != 0) && /* API req? for real? */
UC15_ATOMIC_CAS (UC15_API_REQ + (i * UC15_API_VEC_MUL), 1, 0)) {
api_vec[i][INT_V_DR] = UC15_SHARED_RD (UC15_API_VEC + (i * UC15_API_VEC_MUL)) & 0177;
dr15_int_req |= (1u << i);
if (dr15_ie != 0)
int_hwre[i] |= INT_DR;
if (DEBUG_PRS (dr15_dev))
fprintf (sim_deb, ">>DR15: API request, API = %o/%d\n",
api_vec[i][INT_V_DR], i);
} /* end if changed */
} /* end for */
if (dr15_int_req != old_int_req) /* changes? */
uc15_new_api (dr15_int_req); /* inform UC15 */
sim_activate (uptr, dr15_poll); /* next poll */
return SCPE_OK;
}
/* Reset routine
Aside from performing a device reset, this routine sets up shared
UC15 state and shared PDP15 main memory. It also writes the size
of PDP15 main memory (in PDP11 bytes) into the shared state region.
*/
t_stat dr15_reset (DEVICE *dptr)
{
int32 i;
t_stat r;
void *basead;
dr15_int_req = 0; /* clear API req */
dr15_ie = 1; /* IE inits to 1 */
dr15_tcb_ack = 1; /* TCBP ack inits to 1 */
dr15_int_req = 0;
for (i = 0; i < 4; i++) { /* clear intr and vectors */
int_hwre[i] &= ~INT_DR;
api_vec[i][INT_V_DR] = 0;
}
sim_cancel (dptr->units);
if ((dptr->flags & DEV_DIS) != 0) /* disabled? */
return SCPE_OK;
if (uc15_shmem == NULL) { /* allocate shared state */
r = sim_shmem_open ("UC15SharedState", UC15_STATE_SIZE * sizeof (int32), &uc15_shmem, &basead);
if (r != SCPE_OK)
return r;
uc15_shstate = (int32 *) basead;
}
if (pdp15_shmem == NULL) { /* allocate shared memory */
r = sim_shmem_open ("PDP15MainMemory", MAXMEMSIZE * sizeof (int32), &pdp15_shmem, &basead);
if (r != SCPE_OK)
return r;
free (M); /* release normal memory */
M = (int32 *) basead;
}
UC15_SHARED_WR (UC15_PDP15MEM, cpu_unit.capac << 1); /* write mem size to shared state */
uc15_new_api (dr15_int_req); /* inform UC15 of new API (and mem) */
sim_activate (dptr->units, dr15_poll); /* start polling */
return SCPE_OK;
}
/* Shared state ex/mod routines for debug */
t_stat dr15_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
{
if (addr >= UC15_STATE_SIZE)
return SCPE_NXM;
if (vptr != NULL) {
if (uc15_shmem != NULL)
*vptr = UC15_SHARED_RD ((int32) addr);
else *vptr = 0;
}
return SCPE_OK;
}
t_stat dr15_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
if (addr >= UC15_STATE_SIZE)
return SCPE_NXM;
if (uc15_shmem != NULL)
UC15_SHARED_WR ((int32) addr, (int32) val);
return SCPE_OK;
}
/* Fake attach routine to kill attach attempts */
t_stat dr15_attach (UNIT *uptr, char *cptr)
{
return SCPE_NOFNC;
}
/* Shutdown detach routine to release shared memories */
t_stat dr15_detach (UNIT *uptr)
{
if ((sim_switches & SIM_SW_SHUT) == 0) /* only if shutdown */
return SCPE_NOFNC;
sim_shmem_close (uc15_shmem); /* release shared state */
sim_shmem_close (pdp15_shmem); /* release shared mem */
return SCPE_OK;
}

View File

@@ -1154,7 +1154,7 @@ switch (fnc) { /* at speed, check fnc *
if (ba >= uptr->hwmark)
uptr->hwmark = ba + 1;
}
/* /* ignore hdr */
/* ignore hdr */
sim_activate (uptr, DT_WSIZE * dt_ltime);
if (M[DT_WC] == 0)
dt_substate = DTO_WCO;

603
PDP18B/pdp18b_g2tty.c Normal file
View File

@@ -0,0 +1,603 @@
/* pdp18b_g2tty.c: PDP-7/9 Bell Labs "GRAPHIC-2" subsystem as a TTY via TELNET
from 13-Sep-15 version of pdp18b_tt1.c
Copyright (c) 1993-2015, Robert M Supnik
Copyright (c) 2016, Philip L Budne
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not 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.
Doug McIlroy had this to say about the Bell Labs PDP-7 Ken Thompson
created UNIX on:
The pdp7 was cast off by the visual and acoustics research department.
Bill Ninke et al. built graphic II on it -- a graphics attachment as big
as the pdp7 itself. The disk was an amazing thing about 2' in diameter,
mounted on a horizontal axis. Mystery crashes bedeviled it until somebody
realized that the axis was perpendicular to the loading dock 4 floors
below. A 90-degree turn solved the problem.
GRAPHICS-2 was a command list based graphics display system,
and included a light pen, a "button box" and status bits
for a "dataphone" interface to speak to a GECOS system.
The UNIX-7 system driver only uses text display, and reserves 269
words (holding two characters each; the buffer is 273 words, but
three contain display "setup" commands, and the final word in the
buffer must be a display "TRAP" instruction that ends the display
list).
The UNIX system code triggers a refresh every 10 60Hz "ticks" of
the real time clock. This driver attempts to do detect new text
and send it to a user who has TELNETed in.
Thoughts on implementing a web interface:
538 characters redisplaying at 6Hz (every 10 "ticks") gives a
bandwith requirement of only 26Kbit, and most refreshes won't
change the screen and could be suppressed. So it seems like it
would be reasonable to create a web interface.
Make a SIMH TCP server port which implements a tiny HTTP server.
The base URL serves up a skeletal page with (lighted) buttons,
and a "display window".
And either:
1) Use "AJAX": an (invisible) <iframe> on in the HTML served by the
"base URL" keeps a never-ending connection that is sent "script"
tags to alter the "screen" (div) contents, and light push buttons.
Keypresses and buttons could be implemented using "onclick"
actions which trigger a GET (or a POST) on a URLs which
open new (temporary) HTTP connections to SIMH. The key/button
press URL could contain a session UUID which has to match
a value sent in the initial page.
2) Have the "home" page HTML establish a bi-directional WebSocket
connection to Encapsulate all the traffic (screen contents,
button lighting, key & button presses).
The graphics system responds as ten PDP-7 "devices";
UNIX only uses six, and only three of the six are simulated here
(and *JUST* enough of those to figure out the text being displayed),
as two SIMH DEVICES, G2OUT and G2IN:
G2OUT:
G2D1 005 GRAPHICS-2 display output
G2IN:
G2KB 043 GRAPHICS-2 keyboard
G2BB 044 GRAPHICS-2 button box (lighted bush buttons)
20-Mar-16 PLB Works, mostly
19-Mar-16 PLB Working (up to a screen full)
17-Mar-16 PLB Cloned from 13-Sep-15 version of pdp18b_tt1.c
*/
/*
* GRAPHICS-2 was vector graphics hardware, UNIX-7 uses it as a
* "Glass TTY" for a "second seat".
*
* This simulation ONLY handles text display; the one program
* found that uses the "capt" (capture?) call to set a user
* supplied display list will not work here.
*
* When the display buffer or screen is filled, the UNIX "display"
* driver lights "push button 7" (PB7), and waits for the user to
* press the button. UNIX then clears the screen, and output
* continues. If the program outputs a "Form Feed" character the
* display is also cleared.
*
* This simulation automatically presses PB7 when lit, without
* bothering the user (a more accurate simulation might prompt
* the user to press any key)!
*/
#include "pdp18b_defs.h"
#ifdef GRAPHICS2
#include "sim_tmxr.h"
int debug = 0;
/* hardware registers */
uint8 g2kb_done = 0; /* keyboard flag */
uint32 g2kb_buf = 0; /* keyboard buffer */
uint8 g2bb_flag = 0; /* button flag */
uint32 g2bb_bbuf = 0; /* button buffer */
uint32 g2bb_lbuf = 0; /* button lights buffer */
uint32 g2out_addr = 0; /* display address */
#define PB7 02000
/* not hardware registers: */
uint32 g2out_count = 0;
uint8 g2out_stuffcr = 0; /* need to stuff a CR */
/* keep old and new version of characters to display
* a count & checksum of the "old" screen contents might suffice,
* time will tell....
*/
uint8 g2out_which = 0;
#define OLD g2out_which
#define NEW (g2out_which ^ 1)
#define MAXBUFCHARS 700 /* larger than kernel display list */
static struct dspbuf {
uint16 count;
char buffer[MAXBUFCHARS]; /* 7-bit ASCII */
} g2out_dspbufs[2];
/* terminal mux data */
TMLN g2_ldsc = { 0 }; /* line descriptor */
TMXR g2_desc = { 1, 0, 0, &g2_ldsc }; /* mux descriptor */
/* kernel display lists always start like this: */
static const int32 g2_expect[3] = {
0065057, /* PARAM: clear blink, clear light pen, scale=1, intensity=3 */
0147740, /* X-Y: invisible, no delay, Y=01740 (992) */
0160000 /* X-Y: invisible, settling delay, X=0 */
};
extern int32 *M;
extern int32 int_hwre[API_HLVL+1];
extern int32 api_vec[API_HLVL][32];
extern int32 tmxr_poll;
extern int32 stop_inst;
/* SIMH G2IN DEVICE */
t_bool g2kb_test_done ();
void g2kb_set_done ();
void g2kb_clr_done ();
int32 g2kb_iot (int32 dev, int32 pulse, int32 dat); /* device 043 */
t_bool g2bb_test_flag ();
void g2bb_set_flag ();
void g2bb_clr_flag ();
int32 g2bb_iot (int32 dev, int32 pulse, int32 dat); /* device 044 */
t_stat g2in_svc (UNIT *uptr);
/* SIMH G2OUT DEVICE */
int32 g2d1_iot (int32 dev, int32 pulse, int32 dat); /* device 05 */
static void g2out_clear ();
static void g2out_process_display_list ();
static int g2out_send_new ();
/* both G2IN/G2OUT: */
t_stat g2_attach (UNIT *uptr, CONST char *cptr);
t_stat g2_detach (UNIT *uptr);
t_stat g2_reset (DEVICE *dptr);
/****************************************************************
* SIMH G2IN (keyboard/buttons) DEVICE data structures
*
* g2in_dev G2IN device descriptor
* g2in_unit G2IN unit descriptor
* g2in_reg G2IN register list
* g2in_mod G2IN modifiers list
*/
DIB g2in_dib = { DEV_G2KB, 2, NULL, { &g2kb_iot, &g2bb_iot } };
UNIT g2in_unit = {
UDATA (&g2in_svc, UNIT_IDLE|UNIT_ATTABLE, 0), KBD_POLL_WAIT
};
REG g2in_reg[] = {
{ ORDATA (KBBUF, g2kb_buf, 1) },
{ ORDATA (KBDONE, g2kb_done, 1) },
{ FLDATA (INT, int_hwre[API_G2], INT_V_G2) },
{ DRDATA (TIME, g2in_unit.wait, 24), REG_NZ + PV_LEFT },
{ ORDATA (BBBBUF, g2bb_bbuf, 1) }, /* button box button buffer */
{ ORDATA (BBFLAG, g2bb_flag, 1) }, /* button box IRQ */
{ ORDATA (BBLBUF, g2bb_lbuf, 1) }, /* button box lights buffer */
{ NULL }
};
MTAB g2in_mod[] = {
{ UNIT_ATT, UNIT_ATT, "summary", NULL,
NULL, &tmxr_show_summ, (void *) &g2_desc },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
&tmxr_dscln, NULL, (void *) &g2_desc },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
NULL, &tmxr_show_cstat, (void *) &g2_desc },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
NULL, &tmxr_show_cstat, (void *) &g2_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
&tmxr_set_log, &tmxr_show_log, &g2_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
&tmxr_set_nolog, NULL, &g2_desc },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
NULL, &show_devno, NULL },
{ 0 }
};
/* SIMH G2IN device descriptor (GRAPHICS-2 keyboard & button box) */
DEVICE g2in_dev = {
"G2IN", /* name */
&g2in_unit, /* units */
g2in_reg, g2in_mod, /* registers, modifiers */
1, /* numunits */
10, 31, /* aradix, awidth */
1, 8, 8, /* aincr, dradix, dwidth */
&tmxr_ex, &tmxr_dep, &g2_reset, /* examine, deposit, reset */
NULL, &g2_attach, &g2_detach, /* boot, attach, detach */
&g2in_dib, DEV_MUX|DEV_DISABLE|DEV_DIS /* ctxt, flags */
};
/****************************************************************
* SIMH G2OUT (display output) DEVICE data structures
* Only needed to hold "iot" routine, since DIB's can't represent
* devices with register sets as sparse as GRAPHICS-2
*
* g2out_dev G2OUT device descriptor
* g2out_unit G2OUT unit descriptor
* g2out_reg G2OUT register list
* g2out_mod G2OUT modifiers list
*/
DIB g2out_dib = { DEV_G2D1, 1, NULL, { &g2d1_iot } };
UNIT g2out_unit = { UDATA (NULL, 0, 0) };
REG g2out_reg[] = {
{ ORDATA (DPYADDR, g2out_addr, 1) },
{ NULL }
};
MTAB g2out_mod[] = {
{ MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &g2_desc },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
NULL, &show_devno, NULL },
{ 0 }
};
/* SIMH G2OUT device descriptor (simulates just one of many display IOTs!) */
DEVICE g2out_dev = {
"G2OUT", /* name */
&g2out_unit, /* units */
g2out_reg, g2out_mod, /* registers, modifiers */
1, /* numunits */
10, 31, /* aradix, awidth */
1, 8, 8, /* aincr, dradix, dwidth */
NULL, NULL, &g2_reset, /* examine, deposit, reset */
NULL, NULL, NULL, /* boot, attach, detach */
&g2out_dib, DEV_DISABLE|DEV_DIS /* ctxt, flags */
};
/****************************************************************
* IOT routines
*/
/* Keyboard input IOT routine */
/* real device could have done bitwise decode?! */
int32 g2kb_iot (int32 dev, int32 pulse, int32 dat)
{
if (pulse == 001) { /* sck */
if (g2kb_done) {
dat = dat | IOT_SKP;
}
}
else if (pulse == 002) { /* lck */
dat = dat | g2kb_buf; /* return buffer */
}
else if (pulse == 004) { /* cck */
g2kb_clr_done (); /* clear flag */
}
return dat;
}
/* Button Box IOT routine */
int32 g2bb_iot (int32 dev, int32 pulse, int32 dat)
{
if (pulse == 001) { /* "spb" -- skip on push button flag */
if (g2bb_flag)
dat = dat | IOT_SKP;
}
else if (pulse == 002) /* "lpb"/"opb" -- or push buttons */
dat = dat | g2bb_bbuf; /* return buttons */
else if (pulse == 004) { /* "cpb" -- clear push button flag */
g2bb_clr_flag (); /* clear flag */
}
else if (pulse == 024) { /* "wbl" -- write buttons lights */
if (dat == 0)
g2out_clear(); /* UNIX has ack'ed button press */
g2bb_lbuf = dat;
}
return dat;
}
/* Input side Unit service */
t_stat g2in_svc (UNIT *uptr)
{
int32 ln, c;
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return SCPE_OK;
if (g2bb_lbuf & PB7) { /* button 7 lit? */
/* yes: try sending anything new */
g2out_process_display_list();
g2out_send_new();
g2bb_bbuf |= PB7; /* press it to clear screen! */
g2bb_set_flag ();
}
sim_activate (uptr, clk_cosched (tmxr_poll)); /* continue poll */
ln = tmxr_poll_conn (&g2_desc); /* look for connect */
if (ln >= 0) /* got one? rcv enab */
g2_ldsc.rcve = 1;
tmxr_poll_rx (&g2_desc); /* poll for input */
if (g2_ldsc.conn) { /* connected? */
tmxr_poll_tx (&g2_desc); /* PLB: poll xmt */
if ((c = tmxr_getc_ln (&g2_ldsc))) { /* get char */
if (c & SCPE_BREAK) /* break? */
c = 0;
else {
c &= 0177;
if (c == '\r') /* translate CR but not ESC! */
c = '\n';
else if ((c & 0155) == 055) /* kernel swaps around -?/= */
c ^= 020; /* pre-swap!! */
}
g2kb_buf = c;
g2kb_set_done ();
}
} /* connected */
else {
/* not connected; next connection sees entire "screen" */
g2out_stuffcr = 0;
}
return SCPE_OK;
}
/* Interrupt handling routines */
t_bool g2kb_test_done ()
{
return g2kb_done != 0;
}
void g2kb_set_done ()
{
g2kb_done = 1;
SET_INT (G2);
return;
}
void g2kb_clr_done ()
{
g2kb_done = 0;
CLR_INT (G2);
return;
}
t_bool g2bb_test_flag ()
{
return g2bb_flag != 0;
}
void g2bb_set_flag ()
{
g2bb_flag = 1;
SET_INT (G2);
return;
}
void g2bb_clr_flag ()
{
g2bb_flag = 0;
CLR_INT (G2);
return;
}
/****************************************************************
* SIMH G2OUT (Display Output) DEVICE routines
*/
/* helper to put 7-bit display character */
static void g2pc(char c) {
//if (debug) putchar(c);
tmxr_putc_ln (&g2_ldsc, c);
}
/* send a character from the display. adds CR after LF */
/* returns 1 if "c" was sent; 0 means try again later */
static int g2out_putchar(char c)
{
if (!g2_ldsc.conn || !g2_ldsc.xmte) /* connected, tx enabled? */
return 0;
if (g2out_stuffcr) { /* need to stuff a CR? */
g2pc ('\r');
g2out_stuffcr = 0;
if (!g2_ldsc.xmte) /* full? */
return 0; /* yes: wait until next time */
}
g2pc (c);
if (c == '\n') { /* was it a NL? */
if (g2_ldsc.xmte) /* transmitter enabled? */
g2pc ('\r'); /* send CR now */
else
g2out_stuffcr = 1; /* wait until next time */
}
return 1;
}
/* Device 05 IOT routine */
int32 g2d1_iot (int32 dev, int32 pulse, int32 dat)
{
/*
* UNIX text display command lists always end with a TRAP
* and display output is restarted periodicly in timer PI service code
*/
if (g2_ldsc.conn && g2_ldsc.xmte && pulse == 047) { /* conn&ready, "beg" */
g2out_addr = dat & 017777;
g2out_process_display_list();
g2out_send_new();
g2out_which ^= 1; /* swap buffers */
} /* beg IOT */
return dat;
}
/****************
* display buffer management/process
* we're informed when UNIX wants to clear the screen (PB7 lit)
* we then press the button
* UNIX does a "cpb" to ACK/clear the interrupt.
*
* *BUT* UNIX clears the screen when a FF (014) char is output,
* which just resets the buffer (and not issuing any IOTs)
*/
static void g2out_clear() {
g2out_stuffcr = 0;
g2out_which = 0;
g2out_count = 0;
g2out_dspbufs[0].count = g2out_dspbufs[1].count = 0;
}
/* interpret display list; save characters into "new" dspbuf
* quits early if display list doesn't conform to what's expected
*/
static void g2out_process_display_list() {
uint32 i;
struct dspbuf *dp = g2out_dspbufs + NEW;
dp->count = 0;
for (i = g2out_addr; i < 020000; i++) {
uint32 w = M[i] & 0777777;
int offset = i - g2out_addr;
char c;
if (w & 0400000) /* TRAP (end of display list) */
return;
/* check first three words for expected setup commands */
if (offset < sizeof(g2_expect)/sizeof(g2_expect[0])) {
if (w != g2_expect[offset])
return;
continue;
}
if (w & 0300000) /* not characters? */
return;
c = (w >> 7) & 0177;
if (c)
dp->buffer[dp->count++] = c;
c = w & 0177;
if (c)
dp->buffer[dp->count++] = c;
}
}
/* figure out what to send on TELNET connection
* truncates new->count to the number sent so far
* returns number of new characters sent
*/
static int g2out_send_new() {
struct dspbuf *old = g2out_dspbufs + OLD;
struct dspbuf *New = g2out_dspbufs + NEW;
char *cp = New->buffer;
int cur = 0;
int start;
/* nothing in newest refresh?
* COULD have had undisplayed stuff on last screen before it was cleared??
* would need to have a transmit queue??
*/
if (New->count == 0)
return 0;
if (old->count && /* have old chars */
memcmp(old->buffer, New->buffer, old->count) == 0) { /* and a prefix */
cur = old->count;
cp += cur;
}
/* loop for chars while connected & tx enabled */
start = cur;
while (cur < New->count && g2_ldsc.conn && g2_ldsc.xmte) {
if (g2out_putchar(*cp)) {
cp++;
cur++;
}
}
New->count = cur; /* only remember what's been sent */
return cur - start; /* remember number sent */
}
/****************************************************************
* subsystem common routines (used by both G2IN and G2OUT SIMH DEVICEs)
*/
/* Reset routine */
t_stat g2_reset (DEVICE *dptr)
{
if (dptr->flags & DEV_DIS) { /* sync enables */
g2in_dev.flags = g2in_dev.flags | DEV_DIS;
g2out_dev.flags = g2out_dev.flags | DEV_DIS;
}
else {
g2in_dev.flags = g2in_dev.flags & ~DEV_DIS;
g2out_dev.flags = g2out_dev.flags & ~DEV_DIS;
}
if (g2in_unit.flags & UNIT_ATT) /* if attached, */
sim_activate (&g2in_unit, tmxr_poll); /* activate */
else sim_cancel (&g2in_unit); /* else stop */
g2kb_buf = 0; /* clear buf */
g2kb_clr_done (); /* clear done */
g2bb_bbuf = 0; /* clear buttons */
g2bb_lbuf = 0; /* clear lights */
g2bb_clr_flag ();
g2out_addr = 0;
g2out_clear();
sim_cancel (&g2out_unit); /* stop poll */
return SCPE_OK;
}
/* Attach master unit */
t_stat g2_attach (UNIT *uptr, CONST char *cptr)
{
t_stat r;
r = tmxr_attach (&g2_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) /* error */
return r;
sim_activate (uptr, 0); /* start poll at once */
return SCPE_OK;
}
/* Detach master unit */
t_stat g2_detach (UNIT *uptr)
{
t_stat r = tmxr_detach (&g2_desc, uptr); /* detach */
sim_cancel (uptr); /* stop poll */
g2_ldsc.rcve = 0;
return r;
}
#endif

View File

@@ -130,7 +130,7 @@ int32 rf72 (int32 dev, int32 pulse, int32 dat);
int32 rf_iors (void);
t_stat rf_svc (UNIT *uptr);
t_stat rf_reset (DEVICE *dptr);
int32 rf_updsta (int32 new);
int32 rf_updsta (int32 newst);
t_stat rf_attach (UNIT *uptr, char *cptr);
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
@@ -316,9 +316,9 @@ return SCPE_OK;
/* Update status */
int32 rf_updsta (int32 news)
int32 rf_updsta (int32 newst)
{
rf_sta = (rf_sta | news) & ~(RFS_ERR | RFS_CLR);
rf_sta = (rf_sta | newst) & ~(RFS_ERR | RFS_CLR);
if (rf_sta & RFS_EFLGS)
rf_sta = rf_sta | RFS_ERR;
if ((rf_sta & (RFS_ERR | RFS_DON)) && (rf_sta & RFS_IE))

View File

@@ -1,6 +1,6 @@
/* pdp18b_rp.c: RP15/RP02 disk pack simulator
Copyright (c) 1993-2016, Robert M Supnik
Copyright (c) 1993-2018, 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 @@
rp RP15/RP02/RP03 disk pack
30-May-18 RMS Extra address bit only recognized on RP03 units
15-Mar-16 RMS Added RP03 support
Fixed handling of done flag
07-Mar-16 RMS Revised for dynamically allocated memory
@@ -135,9 +136,10 @@
#define DA_M_CYL 0377
#define GET_SECT(x) (((x) >> DA_V_SECT) & DA_M_SECT)
#define GET_SURF(x) (((x) >> DA_V_SURF) & DA_M_SURF)
#define GET_CYL(x) ((((x) >> DA_V_CYL) & DA_M_CYL) + \
(((x) & DA_C256)? 256: 0))
#define GET_DA(x) ((((GET_CYL (x) * RP_NUMSF) + GET_SURF (x)) * \
#define GET_CYL(x,f) ((((x) >> DA_V_CYL) & DA_M_CYL) + \
(((((x) & DA_C256) != 0) && \
(((f) & UNIT_RP03) != 0))? 256: 0))
#define GET_DA(x,f) ((((GET_CYL (x,f) * RP_NUMSF) + GET_SURF (x)) * \
RP_NUMSC) + GET_SECT (x))
/* Current cylinder */
@@ -263,7 +265,8 @@ if (pulse & 04) {
rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF)
rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_QCYL (rp_unit[u].flags))
if (GET_CYL(rp_da, rp_unit[u].flags) >=
RP_QCYL(rp_unit[u].flags))
rp_updsta (STA_NXC, 0);
}
else if (sb == 020) { /* DPCS */
@@ -332,7 +335,7 @@ if (pulse & 04) {
(f == FN_SEEK) || (f == FN_RECAL))
sim_activate (uptr, RP_MIN); /* short delay */
else {
c = GET_CYL (rp_da);
c = GET_CYL (rp_da, uptr->flags);
c = abs (c - uptr->CYL) * rp_swait; /* seek time */
sim_activate (uptr, MAX (RP_MIN, c + rp_rwait));
rp_sta = rp_sta & ~STA_DON; /* clear done */
@@ -371,7 +374,7 @@ if (f == FN_IDLE) { /* idle? */
if ((f == FN_SEEK) || (f == FN_RECAL)) { /* seek or recal? */
rp_busy = 0; /* not busy */
cyl = (f == FN_SEEK)? GET_CYL (rp_da): 0; /* get cylinder */
cyl = (f == FN_SEEK)? GET_CYL (rp_da, uptr->flags): 0; /* get cylinder */
sim_activate (uptr, MAX (RP_MIN, abs (cyl - uptr->CYL) * rp_swait));
uptr->CYL = cyl; /* on cylinder */
uptr->FUNC = FN_SEEK | FN_2ND; /* set second state */
@@ -398,16 +401,16 @@ if (GET_SECT (rp_da) >= RP_NUMSC)
rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF)
rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_QCYL (uptr->flags))
if (GET_CYL (rp_da, uptr->flags) >= RP_QCYL (uptr->flags))
rp_updsta (STA_NXC, 0);
if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
return SCPE_OK;
}
uptr->CYL = GET_CYL (rp_da); /* on cylinder */
uptr->CYL = GET_CYL (rp_da, uptr->flags); /* on cylinder */
pa = rp_ma & AMASK; /* get mem addr */
da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */
da = GET_DA (rp_da, uptr->flags) * RP_NUMWD; /* get disk addr */
wc = 01000000 - rp_wc; /* get true wc */
if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */
nexm = 1; /* set nexm flag */
@@ -456,7 +459,7 @@ if (cyl >= RP_QCYL (uptr->flags)) /* cyl ovflo wraps */
surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */
sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */
rp_da = ((cyl & DA_M_CYL) << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT);
if (cyl >= 256) /* cyl >= 8 bits? */
if ((cyl >= 256) && ((uptr->flags & UNIT_RP03) != 0)) /* cyl >= 8 bits && RP03 */
rp_da = rp_da | DA_C256;
rp_busy = 0; /* clear busy */
rp_updsta (STA_DON, 0); /* set done */

View File

@@ -99,6 +99,9 @@ extern DEVICE mt_dev;
extern DEVICE tti1_dev, tto1_dev;
extern UNIT tti1_unit, tto1_unit;
#endif
#if defined (GRAPHICS2)
extern DEVICE g2out_dev, g2in_dev;
#endif
#if defined (UC15)
extern DEVICE dr15_dev;
#endif
@@ -107,9 +110,6 @@ extern REG cpu_reg[];
extern int32 *M;
extern int32 memm;
extern int32 PC;
extern const char asc_to_baud[128];
extern const char baud_to_asc[64];
extern const char fio_to_asc[64];
/* SCP data structures and interface routines
@@ -178,6 +178,9 @@ DEVICE *sim_devices[] = {
#endif
#if defined (UC15)
&dr15_dev,
#endif
#if defined (GRAPHICS2)
&g2out_dev, &g2in_dev,
#endif
NULL
};

59
PDP18B/uc15_defs.h Normal file
View File

@@ -0,0 +1,59 @@
/* uc15_defs.h: PDP15/UC15 shared state definitions
Copyright (c) 2016, 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"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not 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.
*/
#ifndef UC15_DEFS_H_
#define UC15_DEFS_H_ 0
#define UC15_STATE_SIZE 1024 /* size (int32's) */
/* The shared state region is divided into four quadrants
000-255 PDP-15 read/write, PDP-11 read only, data
255-511 PDP-11 read/write, PDP-15 read only, data
768-1023 Event signals (locks), read/write
*/
#define PDP15_MAXMEM 0400000 /* PDP15 max mem, words */
#define UC15_PDP15MEM 0040 /* PDP15 mem size, bytes */
#define UC15_TCBP 0100 /* TCB pointer */
#define UC15_API_SUMM 0140 /* API summary */
#define UC15_API_VEC 0600 /* vectors[4] */
#define UC15_API_VEC_MUL 010 /* vector spread factor */
#define UC15_TCBP_WR 01000 /* TCBP write signal */
#define UC15_TCBP_RD 01040 /* TCBP read signal */
#define UC15_API_UPD 01100 /* API summ update */
#define UC15_API_REQ 01200 /* +1 for API req[4] */
#define UC15_SHARED_RD(p) (*(uc15_shstate + (p)))
#define UC15_SHARED_WR(p,d) *(uc15_shstate + (p)) = (d)
#define UC15_ATOMIC_CAS(p,o,n) sim_shmem_atomic_cas ((uc15_shstate + (p)), o, n)
#define UC15_ATOMIC_ADD(p,a) sim_shmem_atomic_add ((uc15_shstate + (p)), (a))
#endif