1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-02-07 16:51:53 +00:00

KA10: Merge branch 'larsbrinkhoff-lars/pdp6'

This commit is contained in:
Lars Brinkhoff
2019-03-10 15:24:58 -04:00
committed by Richard Cornwell
7 changed files with 450 additions and 2 deletions

14
.travis.yml Normal file
View File

@@ -0,0 +1,14 @@
os:
- linux
# - osx
language: c
dist: trusty
sudo: required
env:
- CPU=ka10 TYPE340=0
- CPU=ka10 TYPE340=1
- CPU=ki10 TYPE340=0
install: sh -ex dependencies.sh install_linux
script: make $CPU TYPE340=$TYPE340
notifications:
email: lars@nocrew.org

397
PDP10/ka10_auxcpu.c Normal file
View File

@@ -0,0 +1,397 @@
/* ka10_auxcpu.c: Auxiliary processor.
Copyright (c) 2018, Lars Brinkhoff
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
RICHARD CORNWELL 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.
This is a device which interfaces with an auxiliary processor
through shared memory and inter-processor interrupts.
*/
#include "ka10_defs.h"
#include "sim_tmxr.h"
#ifndef NUM_DEVS_AUXCPU
#define NUM_DEVS_AUXCPU 0
#endif
#if NUM_DEVS_AUXCPU > 0
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
//#include <sys/socket.h>
//#include <netinet/in.h>
//#include <netinet/tcp.h>
//#include <arpa/inet.h>
/* External bus interface. */
#define DATO 1
#define DATI 2
#define ACK 3
#define ERR 4
#define TIMEOUT 5
#define IRQ 6
/* Simulator time units for a Unibus memory cycle. */
#define AUXCPU_MEM_CYCLE 100
/* Interprocessor interrupt device. */
#define AUXCPU_DEVNUM 020
#define AUXCPU_POLL 1000
static int pia = 0;
static int status = 0;
static t_stat auxcpu_devio(uint32 dev, uint64 *data);
static t_stat auxcpu_svc (UNIT *uptr);
static t_stat auxcpu_reset (DEVICE *dptr);
static t_stat auxcpu_attach (UNIT *uptr, CONST char *ptr);
static t_stat auxcpu_detach (UNIT *uptr);
static t_stat auxcpu_attach_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
static const char *auxcpu_description (DEVICE *dptr);
UNIT auxcpu_unit[1] = {
{ UDATA (&auxcpu_svc, UNIT_IDLE|UNIT_ATTABLE, 0), 1000 },
};
static REG auxcpu_reg[] = {
{ DRDATAD (POLL, auxcpu_unit[0].wait, 24, "poll interval"), PV_LEFT },
{ NULL }
};
static MTAB auxcpu_mod[] = {
{ 0 }
};
#define DBG_TRC 1
#define DBG_CMD 2
static DEBTAB auxcpu_debug[] = {
{"TRACE", DBG_TRC, "Routine trace"},
{"CMD", DBG_CMD, "Command Processing"},
{0},
};
DEVICE auxcpu_dev = {
"AUXCPU", auxcpu_unit, auxcpu_reg, auxcpu_mod,
1, 8, 16, 2, 8, 16,
NULL, /* examine */
NULL, /* deposit */
&auxcpu_reset, /* reset */
NULL, /* boot */
auxcpu_attach, /* attach */
auxcpu_detach, /* detach */
NULL, /* context */
DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX,
DBG_CMD, /* debug control */
auxcpu_debug, /* debug flags */
NULL, /* memory size chage */
NULL, /* logical name */
NULL, /* help */
&auxcpu_attach_help, /* attach help */
NULL, /* help context */
&auxcpu_description, /* description */
};
static TMLN auxcpu_ldsc; /* line descriptor */
static TMXR auxcpu_desc = { 1, 0, 0, &auxcpu_ldsc }; /* mux descriptor */
static t_stat auxcpu_reset (DEVICE *dptr)
{
sim_debug(DBG_TRC, dptr, "auxcpu_reset()\n");
auxcpu_unit[0].flags |= UNIT_ATTABLE | UNIT_IDLE;
auxcpu_desc.packet = TRUE;
auxcpu_desc.notelnet = TRUE;
auxcpu_desc.buffered = 2048;
if (auxcpu_unit[0].flags & UNIT_ATT)
sim_activate (&auxcpu_unit[0], 1000);
else
sim_cancel (&auxcpu_unit[0]);
return SCPE_OK;
}
static t_stat auxcpu_attach (UNIT *uptr, CONST char *cptr)
{
t_stat r;
if (!cptr || !*cptr)
return SCPE_ARG;
if (!(uptr->flags & UNIT_ATTABLE))
return SCPE_NOATT;
r = tmxr_attach_ex (&auxcpu_desc, uptr, cptr, FALSE);
if (r != SCPE_OK) /* error? */
return r;
sim_debug(DBG_TRC, &auxcpu_dev, "activate connection\n");
sim_activate (uptr, 10); /* start poll */
uptr->flags |= UNIT_ATT;
return SCPE_OK;
}
static t_stat auxcpu_detach (UNIT *uptr)
{
t_stat r;
if (!(uptr->flags & UNIT_ATT))
return SCPE_OK;
sim_cancel (uptr);
r = tmxr_detach (&auxcpu_desc, uptr);
uptr->flags &= ~UNIT_ATT;
free (uptr->filename);
uptr->filename = NULL;
return r;
}
static void build (unsigned char *request, unsigned char octet)
{
request[0]++;
request[request[0]] = octet;
}
static t_stat auxcpu_svc (UNIT *uptr)
{
tmxr_poll_rx (&auxcpu_desc);
if (auxcpu_ldsc.rcve && !auxcpu_ldsc.conn) {
auxcpu_ldsc.rcve = 0;
tmxr_reset_ln (&auxcpu_ldsc);
}
/* If incoming interrput => status |= 010 */
if (status & 010)
set_interrupt(AUXCPU_DEVNUM, pia);
else
clr_interrupt(AUXCPU_DEVNUM);
if (tmxr_poll_conn(&auxcpu_desc) >= 0) {
sim_debug(DBG_CMD, &auxcpu_dev, "got connection\n");
auxcpu_ldsc.rcve = 1;
uptr->wait = AUXCPU_POLL;
}
sim_activate (uptr, uptr->wait);
return SCPE_OK;
}
static t_stat auxcpu_attach_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
const char helpString[] =
/* The '*'s in the next line represent the standard text width of a help line */
/****************************************************************************/
" The %D device connects a secondary processor that is sharing memory with the.\n"
" primary.\n\n"
" The device must be attached to a receive port, this is done by using the\n"
" ATTACH command to specify the receive port number.\n"
"\n"
"+sim> ATTACH %U port\n"
"\n"
;
return scp_help (st, dptr, uptr, flag, helpString, cptr);
return SCPE_OK;
}
static const char *auxcpu_description (DEVICE *dptr)
{
return "Auxiliary processor";
}
static int error (const char *message)
{
sim_debug (DBG_TRC, &auxcpu_dev, "%s\r\n", message);
sim_debug (DBG_TRC, &auxcpu_dev, "CLOSE\r\n");
auxcpu_ldsc.rcve = 0;
tmxr_reset_ln (&auxcpu_ldsc);
return -1;
}
static int transaction (unsigned char *request, unsigned char *response)
{
const uint8 *auxcpu_request;
size_t size;
t_stat stat;
stat = tmxr_put_packet_ln (&auxcpu_ldsc, request + 1, (size_t)request[0]);
if (stat != SCPE_OK)
return error ("Write error in transaction");
do {
tmxr_poll_rx (&auxcpu_desc);
stat = tmxr_get_packet_ln (&auxcpu_ldsc, &auxcpu_request, &size);
} while (stat != SCPE_OK || size == 0);
if (size > 7)
return error ("Malformed transaction");
memcpy (response, auxcpu_request, size);
return 0;
}
int auxcpu_read (int addr, uint64 *data)
{
unsigned char request[12];
unsigned char response[12];
sim_interval -= AUXCPU_MEM_CYCLE;
if ((auxcpu_unit[0].flags & UNIT_ATT) == 0) {
*data = 0;
return 0;
}
addr &= 037777;
memset (request, 0, sizeof request);
build (request, DATI);
build (request, addr);
build (request, addr >> 8);
build (request, addr >> 16);
transaction (request, response);
switch (response[0])
{
case ACK:
*data = (uint64)response[1];
*data |= (uint64)response[2] << 8;
*data |= (uint64)response[3] << 16;
*data |= (uint64)response[4] << 24;
*data |= (uint64)response[5] << 32;
break;
case ERR:
fprintf (stderr, "AUXCPU: Read error %06o\r\n", addr);
*data = 0;
break;
case TIMEOUT:
fprintf (stderr, "AUXCPU: Read timeout %06o\r\n", addr);
*data = 0;
break;
default:
return error ("Protocol error");
}
return 0;
}
int auxcpu_write (int addr, uint64 data)
{
unsigned char request[12];
unsigned char response[12];
sim_interval -= AUXCPU_MEM_CYCLE;
if ((ten11_unit[0].flags & UNIT_ATT) == 0) {
return 0;
}
addr &= 037777;
memset (request, 0, sizeof request);
build (request, DATO);
build (request, addr);
build (request, addr >> 8);
build (request, addr >> 16);
build (request, data);
build (request, data >> 8);
build (request, data >> 16);
build (request, data >> 24);
build (request, data >> 32);
transaction (request, response);
switch (response[0])
{
case ACK:
break;
case ERR:
fprintf (stderr, "AUXCPU: Write error %06o\r\n", addr);
break;
case TIMEOUT:
fprintf (stderr, "AUXCPU: Write timeout %06o\r\n", addr);
break;
default:
return error ("Protocol error");
}
return 0;
}
static int auxcpu_interrupt (void)
{
unsigned char request[12];
unsigned char response[12];
memset (request, 0, sizeof request);
sim_debug(DEBUG_IRQ, &auxcpu_dev, "PDP-10 interrupting the PDP-6\n");
build (request, IRQ);
transaction (request, response);
switch (response[1])
{
case ACK:
break;
case ERR:
case TIMEOUT:
fprintf (stderr, "AUXCPU: Interrupt error or timeout\r\n");
break;
default:
return error ("Protocol error");
}
return 0;
}
t_stat auxcpu_devio(uint32 dev, uint64 *data)
{
DEVICE *dptr = &auxcpu_dev;
switch(dev & 07) {
case CONO:
sim_debug(DEBUG_CONO, &auxcpu_dev, "CONO %012llo\n", *data);
pia = *data & 7;
if (*data & 010)
{
// Clear interrupt from the PDP-6.
status &= ~010;
clr_interrupt(AUXCPU_DEVNUM);
}
if (*data & 020)
auxcpu_interrupt ();
break;
case CONI:
*data = (status & 010) | pia;
sim_debug(DEBUG_CONI, &auxcpu_dev, "CONI %012llo\n", *data);
break;
case DATAI:
*data = 0;
sim_debug(DEBUG_CONI, &auxcpu_dev, "DATAI %012llo\n", *data);
break;
case DATAO:
sim_debug(DEBUG_CONI, &auxcpu_dev, "DATAO %012llo\n", *data);
break;
}
return SCPE_OK;
}
#endif

View File

@@ -217,7 +217,9 @@ int32 qua_tps = 125000;
int32 tmxr_poll = 10000;
/* Physical address range for Rubin 10-11 interface. */
#define T11RANGE(addr) ((addr) >= 03000000)
#define T11RANGE(addr) ((addr) >= 03040000)
/* Physical address range for auxiliary PDP-6. */
#define AUXCPURANGE(addr) ((addr) >= 03000000 && (addr) < 03040000)
DEVICE *rh_devs[] = {
#if (NUM_DEVS_RS > 0)
@@ -686,6 +688,7 @@ int opflags[] = {
#if ITS
#define QITS (cpu_unit[0].flags & UNIT_ITSPAGE)
#define QTEN11 (ten11_unit[0].flags & UNIT_ATT)
#define QAUXCPU (auxcpu_unit[0].flags & UNIT_ATT)
#else
#define QITS 0
#endif
@@ -1682,6 +1685,13 @@ int Mem_read_its(int flag, int cur_context, int fetch) {
}
return 0;
}
if (AUXCPURANGE(addr) && QAUXCPU) {
if (auxcpu_read (addr, &MB)) {
nxm_flag = 1;
return 1;
}
return 0;
}
if (addr >= (int)MEMSIZE) {
nxm_flag = 1;
return 1;
@@ -1716,6 +1726,13 @@ int Mem_write_its(int flag, int cur_context) {
}
return 0;
}
if (AUXCPURANGE(addr) && QAUXCPU) {
if (auxcpu_write (addr, MB)) {
nxm_flag = 1;
return 1;
}
return 0;
}
if (addr >= (int)MEMSIZE) {
nxm_flag = 1;
return 1;

View File

@@ -299,6 +299,7 @@ extern void restore_pi_hold();
extern void set_pi_hold();
extern UNIT cpu_unit[];
extern UNIT ten11_unit[];
extern UNIT auxcpu_unit[];
extern DEVICE cpu_dev;
extern DEVICE cty_dev;
extern DEVICE mt_dev;
@@ -331,6 +332,7 @@ extern DEVICE stk_dev;
extern DEVICE tk10_dev;
extern DEVICE mty_dev;
extern DEVICE ten11_dev;
extern DEVICE auxcpu_dev;
extern DEVICE wcnsls_dev; /* MIT Spacewar Consoles */
extern t_stat (*dev_tab[128])(uint32 dev, uint64 *data);
@@ -386,6 +388,8 @@ extern void ka10_lights_main (uint64);
extern void ka10_lights_set_aux (int);
extern void ka10_lights_clear_aux (int);
int auxcpu_read (int addr, uint64 *);
int auxcpu_write (int addr, uint64);
/* I/O system parameters */
#define NUM_DEVS_MT 1
@@ -407,6 +411,7 @@ extern void ka10_lights_clear_aux (int);
#define NUM_DEVS_TK10 ITS
#define NUM_DEVS_MTY ITS
#define NUM_DEVS_TEN11 ITS
#define NUM_DEVS_AUXCPU ITS
#define NUM_DEVS_DPY USE_DISPLAY
#define NUM_DEVS_WCNSLS USE_DISPLAY
#define NUM_DEVS_IMP 1

View File

@@ -154,6 +154,9 @@ DEVICE *sim_devices[] = {
#endif
#if NUM_DEVS_TEN11 > 0
&ten11_dev,
#endif
#if NUM_DEVS_AUXCPU > 0
&auxcpu_dev,
#endif
NULL
};

11
dependencies.sh Normal file
View File

@@ -0,0 +1,11 @@
install_linux() {
sudo apt-get update -myq
sudo apt-get install -y libegl1-mesa-dev libgles2-mesa-dev
sudo apt-get install -y libx11-dev libxt-dev libsdl2-dev
}
install_osx() {
true
}
"$1"

View File

@@ -1203,7 +1203,8 @@ KA10 = ${KA10D}/ka10_cpu.c ${KA10D}/ka10_sys.c ${KA10D}/ka10_df.c \
${KA10D}/ka10_dk.c ${KA10D}/ka10_cr.c ${KA10D}/ka10_cp.c \
${KA10D}/ka10_tu.c ${KA10D}/ka10_rs.c ${KA10D}/ka10_pd.c \
${KA10D}/ka10_imx.c ${KA10D}/ka10_tk10.c ${KA10D}/ka10_mty.c \
${KA10D}/ka10_imp.c ${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c
${KA10D}/ka10_imp.c ${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c \
${KA10D}/ka10_auxcpu.c
KA10_OPT = -DKA=1 -DUSE_INT64 -I $(KA10D) -DUSE_SIM_CARD ${NETWORK_OPT}
ifneq ($(TYPE340),)