mirror of
https://github.com/aap/pdp6.git
synced 2026-01-29 21:31:11 +00:00
re-implemented memory
This commit is contained in:
76
src/apr.c
76
src/apr.c
@@ -348,9 +348,9 @@ set_mc_rq(Apr *apr, bool value)
|
||||
{
|
||||
apr->mc_rq = value; // 7-9
|
||||
if(value && (apr->mc_rd || apr->mc_wr))
|
||||
membus0 |= MEMBUS_RQ_CYC;
|
||||
apr->membus.c12 |= MEMBUS_RQ_CYC;
|
||||
else
|
||||
membus0 &= ~MEMBUS_RQ_CYC;
|
||||
apr->membus.c12 &= ~MEMBUS_RQ_CYC;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -358,9 +358,9 @@ set_mc_wr(Apr *apr, bool value)
|
||||
{
|
||||
apr->mc_wr = value; // 7-9
|
||||
if(value)
|
||||
membus0 |= MEMBUS_WR_RQ;
|
||||
apr->membus.c12 |= MEMBUS_WR_RQ;
|
||||
else
|
||||
membus0 &= ~MEMBUS_WR_RQ;
|
||||
apr->membus.c12 &= ~MEMBUS_WR_RQ;
|
||||
set_mc_rq(apr, apr->mc_rq); // 7-9
|
||||
}
|
||||
|
||||
@@ -369,9 +369,9 @@ set_mc_rd(Apr *apr, bool value)
|
||||
{
|
||||
apr->mc_rd = value; // 7-9
|
||||
if(value)
|
||||
membus0 |= MEMBUS_RD_RQ;
|
||||
apr->membus.c12 |= MEMBUS_RD_RQ;
|
||||
else
|
||||
membus0 &= ~MEMBUS_RD_RQ;
|
||||
apr->membus.c12 &= ~MEMBUS_RD_RQ;
|
||||
set_mc_rq(apr, apr->mc_rq); // 7-9
|
||||
}
|
||||
|
||||
@@ -404,15 +404,15 @@ relocate(Apr *apr)
|
||||
apr->rla += apr->rlr;
|
||||
|
||||
// 7-2, 7-10
|
||||
membus0 &= ~0007777777761LL;
|
||||
membus0 |= ma_fmc_select ? MEMBUS_MA_FMC_SEL1 : MEMBUS_MA_FMC_SEL0;
|
||||
membus0 |= (apr->ma&01777) << 4;
|
||||
membus0 |= ((word)apr->rla&017) << 14;
|
||||
membus0 |= apr->rla & 0020 ? MEMBUS_MA21_1|MEMBUS_MA21 : MEMBUS_MA21_0;
|
||||
membus0 |= apr->rla & 0040 ? MEMBUS_MA20_1 : MEMBUS_MA20_0;
|
||||
membus0 |= apr->rla & 0100 ? MEMBUS_MA19_1 : MEMBUS_MA19_0;
|
||||
membus0 |= apr->rla & 0200 ? MEMBUS_MA18_1 : MEMBUS_MA18_0;
|
||||
membus0 |= apr->ma & 01 ? MEMBUS_MA35_1 : MEMBUS_MA35_0;
|
||||
apr->membus.c12 &= ~0007777777761LL;
|
||||
apr->membus.c12 |= ma_fmc_select ? MEMBUS_MA_FMC_SEL1 : MEMBUS_MA_FMC_SEL0;
|
||||
apr->membus.c12 |= (apr->ma&01777) << 4;
|
||||
apr->membus.c12 |= ((word)apr->rla&017) << 14;
|
||||
apr->membus.c12 |= apr->rla & 0020 ? MEMBUS_MA21_1|MEMBUS_MA21 : MEMBUS_MA21_0;
|
||||
apr->membus.c12 |= apr->rla & 0040 ? MEMBUS_MA20_1 : MEMBUS_MA20_0;
|
||||
apr->membus.c12 |= apr->rla & 0100 ? MEMBUS_MA19_1 : MEMBUS_MA19_0;
|
||||
apr->membus.c12 |= apr->rla & 0200 ? MEMBUS_MA18_1 : MEMBUS_MA18_0;
|
||||
apr->membus.c12 |= apr->ma & 01 ? MEMBUS_MA35_1 : MEMBUS_MA35_0;
|
||||
return ma_ok;
|
||||
}
|
||||
|
||||
@@ -2748,13 +2748,11 @@ pulse(it0){
|
||||
|
||||
pulse(mai_addr_ack){
|
||||
trace("MAI ADDR ACK\n");
|
||||
nextpulse(apr, mc_addr_ack); // 7-8
|
||||
curpulse(apr, mc_addr_ack); // 7-8
|
||||
}
|
||||
|
||||
pulse(mai_rd_rs){
|
||||
trace("MAI RD RS\n");
|
||||
/* we do this here instead of whenever MC RD is set; 7-6, 7-9 */
|
||||
apr->mb = membus1;
|
||||
if(apr->ma == apr->mas)
|
||||
apr->mi = apr->mb; // 7-7
|
||||
if(!apr->mc_stop)
|
||||
@@ -2795,8 +2793,8 @@ pulse(mc_wr_rs){
|
||||
trace("MC WR RS\n");
|
||||
if(apr->ma == apr->mas)
|
||||
apr->mi = apr->mb; // 7-7
|
||||
membus1 = apr->mb; // 7-8
|
||||
membus0 |= MEMBUS_WR_RS; // 7-8
|
||||
apr->membus.c34 |= apr->mb; // 7-8
|
||||
apr->membus.c12 |= MEMBUS_WR_RS; // 7-8
|
||||
if(!apr->mc_stop)
|
||||
nextpulse(apr, mc_rs_t0); // 7-8
|
||||
}
|
||||
@@ -3012,6 +3010,16 @@ pulse(key_manual){
|
||||
nextpulse(apr, kt0); // 5-2
|
||||
}
|
||||
|
||||
void
|
||||
curpulse(Apr *apr, Pulse *p)
|
||||
{
|
||||
if(apr->ncurpulses >= MAXPULSE){
|
||||
fprint(stderr, "error: too many current pulses\n");
|
||||
exit(1);
|
||||
}
|
||||
apr->clist[apr->ncurpulses++] = p;
|
||||
}
|
||||
|
||||
void
|
||||
nextpulse(Apr *apr, Pulse *p)
|
||||
{
|
||||
@@ -3072,13 +3080,14 @@ aprmain(void *p)
|
||||
|
||||
apr->iobus.c12_prev = apr->iobus.c12;
|
||||
apr->iobus.c34_prev = apr->iobus.c34;
|
||||
membus0_last = membus0;
|
||||
apr->membus.c12_prev = apr->membus.c12;
|
||||
apr->membus.c34_prev = apr->membus.c34;
|
||||
|
||||
for(i = 0; i < apr->ncurpulses; i++)
|
||||
apr->clist[i](apr);
|
||||
|
||||
updatebus(&apr->iobus);
|
||||
membus0_pulse = (membus0_last ^ membus0) & membus0;
|
||||
updatebus(&apr->membus);
|
||||
|
||||
/* This is simplified, we have no IOT RESET,
|
||||
* IOT INIT SET UP or IOT FINAL SETUP really.
|
||||
@@ -3126,23 +3135,30 @@ aprmain(void *p)
|
||||
}
|
||||
apr->iobus.c34 &= ~(IOBUS_PULSES | IOBUS_IOB_RESET);
|
||||
|
||||
|
||||
/* Pulses to memory */
|
||||
if(membus0_pulse & (MEMBUS_WR_RS | MEMBUS_RQ_CYC)){
|
||||
wakemem();
|
||||
membus0 &= ~MEMBUS_WR_RS;
|
||||
if(apr->membus.c12_pulse & (MEMBUS_WR_RS | MEMBUS_RQ_CYC)){
|
||||
wakemem(&apr->membus);
|
||||
apr->membus.c12 &= ~MEMBUS_WR_RS;
|
||||
}
|
||||
|
||||
/* Pulses from memory */
|
||||
if(membus0 & MEMBUS_MAI_ADDR_ACK){
|
||||
membus0 &= ~MEMBUS_MAI_ADDR_ACK;
|
||||
if(apr->membus.c12 & MEMBUS_MAI_ADDR_ACK){
|
||||
apr->membus.c12 &= ~MEMBUS_MAI_ADDR_ACK;
|
||||
apr->extpulse &= ~EXT_NONEXIT_MEM;
|
||||
nextpulse(apr, mai_addr_ack);
|
||||
}
|
||||
if(membus0 & MEMBUS_MAI_RD_RS){
|
||||
membus0 &= ~MEMBUS_MAI_RD_RS;
|
||||
if(apr->membus.c12 & MEMBUS_MAI_RD_RS){
|
||||
apr->membus.c12 &= ~MEMBUS_MAI_RD_RS;
|
||||
nextpulse(apr, mai_rd_rs);
|
||||
}
|
||||
if(apr->mc_rd && apr->membus.c34){
|
||||
/* 7-6, 7-9 */
|
||||
apr->mb |= apr->membus.c34;
|
||||
apr->membus.c34 = 0;
|
||||
}
|
||||
|
||||
/* TODO: do this differently because the
|
||||
* memory might have been busy. */
|
||||
if(apr->extpulse & EXT_NONEXIT_MEM){
|
||||
apr->extpulse &= ~EXT_NONEXIT_MEM;
|
||||
if(apr->mc_rq && !apr->mc_stop)
|
||||
|
||||
13
src/main.c
13
src/main.c
@@ -539,6 +539,7 @@ Apr apr;
|
||||
Tty tty;
|
||||
Ptr ptr;
|
||||
Ptp ptp;
|
||||
Mem *coremems[4];
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@@ -660,10 +661,20 @@ main(int argc, char *argv[])
|
||||
extra_l = e; e += 1;
|
||||
|
||||
initapr(&apr);
|
||||
initmem();
|
||||
// initmem();
|
||||
coremems[0] = makecoremem("mem_0");
|
||||
coremems[1] = makecoremem("mem_1");
|
||||
coremems[2] = makecoremem("mem_2");
|
||||
coremems[3] = makecoremem("mem_3");
|
||||
attachmem(makefastmem(0), 0, &apr.membus, -1);
|
||||
attachmem(coremems[0], 0, &apr.membus, 0);
|
||||
attachmem(coremems[1], 0, &apr.membus, 1);
|
||||
attachmem(coremems[2], 0, &apr.membus, 2);
|
||||
attachmem(coremems[3], 0, &apr.membus, 3);
|
||||
inittty(&tty, &apr.iobus);
|
||||
initptr(&ptr, &apr.iobus);
|
||||
initptp(&ptp, &apr.iobus);
|
||||
showmem(&apr.membus);
|
||||
|
||||
for(;;){
|
||||
start = SDL_GetTicks();
|
||||
|
||||
301
src/mem.c
301
src/mem.c
@@ -1,16 +1,9 @@
|
||||
#include "pdp6.h"
|
||||
#include <ctype.h>
|
||||
|
||||
word memory[256*1024];
|
||||
//hword maxmem = 256*1024;
|
||||
hword maxmem = 64*1024;
|
||||
word fmem[16];
|
||||
word membus0, membus1;
|
||||
word membus0_last, membus0_pulse;
|
||||
word *hold;
|
||||
Membus memterm;
|
||||
|
||||
void
|
||||
readmem(char *file, word *mem, word size)
|
||||
readmem(const char *file, word *mem, word size)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[100], *s;
|
||||
@@ -37,62 +30,260 @@ readmem(char *file, word *mem, word size)
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void
|
||||
initmem(void)
|
||||
{
|
||||
readmem("../mem", memory, maxmem);
|
||||
readmem("../fmem", fmem, 16);
|
||||
}
|
||||
/* Both functions below are very confusing. I'm sorry.
|
||||
* The schematics cannot be converted to C in a straightfoward way
|
||||
* but I tried my best. */
|
||||
|
||||
void
|
||||
dumpmem(void)
|
||||
/* This is based on the 161C memory */
|
||||
static int
|
||||
wakecore(Mem *mem, Membus *bus)
|
||||
{
|
||||
hword a;
|
||||
FILE *f;
|
||||
bool p2, p3;
|
||||
CMem *core;
|
||||
core = mem->module;
|
||||
|
||||
if(f = fopen("memdump", "w"), f == nil)
|
||||
return;
|
||||
for(a = 0; a < 16; a++)
|
||||
fprint(f, "%02o: %012llo\n", a, fmem[a]);
|
||||
for(a = 0; a < maxmem; a++){
|
||||
if(memory[a]){
|
||||
fprint(f, "%06o: ", a);
|
||||
fprint(f, "%012llo\n", memory[a]);
|
||||
/* If not connected to a bus, find out which to connect to.
|
||||
* Lower numbers have higher priority but proc 2 and 3 have
|
||||
* the same priority and requests are alternated between them.
|
||||
* If no request is made, we should already be connected to a bus */
|
||||
pthread_mutex_lock(&core->mutex);
|
||||
if(core->cmc_p_act < 0){
|
||||
if(mem->bus[0]->c12 & MEMBUS_RQ_CYC)
|
||||
core->cmc_p_act = 0;
|
||||
else if(mem->bus[1]->c12 & MEMBUS_RQ_CYC)
|
||||
core->cmc_p_act = 1;
|
||||
else{
|
||||
p2 = !!(mem->bus[2]->c12 & MEMBUS_RQ_CYC);
|
||||
p3 = !!(mem->bus[3]->c12 & MEMBUS_RQ_CYC);
|
||||
if(p2 && p3){
|
||||
if(core->cmc_last_proc == 2)
|
||||
core->cmc_p_act = 3;
|
||||
else if(core->cmc_last_proc == 3)
|
||||
core->cmc_p_act = 2;
|
||||
}else{
|
||||
if(p2)
|
||||
core->cmc_p_act = 2;
|
||||
else if(p3)
|
||||
core->cmc_p_act = 3;
|
||||
else{
|
||||
pthread_mutex_unlock(&core->mutex);
|
||||
return 1; /* no request at all? */
|
||||
}
|
||||
}
|
||||
core->cmc_last_proc = core->cmc_p_act;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
pthread_mutex_unlock(&core->mutex);
|
||||
|
||||
/* The executing thread can only service requests from its own processor
|
||||
* due to synchronization with the processor's pulse cycle. */
|
||||
if(bus != mem->bus[core->cmc_p_act])
|
||||
return 1;
|
||||
|
||||
if(core->cmc_aw_rq && bus->c12 & MEMBUS_RQ_CYC){
|
||||
/* accept cycle request */
|
||||
core->cmc_aw_rq = 0;
|
||||
//trace(" accepting memory cycle from proc %d\n", core->cmc_p_act);
|
||||
|
||||
core->cmb = 0;
|
||||
core->cma = 0;
|
||||
core->cma_rd_rq = 0;
|
||||
core->cma_wr_rq = 0;
|
||||
core->cmc_pse_sync = 0;
|
||||
|
||||
/* strobe address and send acknowledge */
|
||||
core->cma |= bus->c12>>4 & 037777;
|
||||
core->cma_rd_rq |= !!(bus->c12 & MEMBUS_RD_RQ);
|
||||
core->cma_wr_rq |= !!(bus->c12 & MEMBUS_WR_RQ);
|
||||
//trace(" sending ADDR ACK\n");
|
||||
bus->c12 |= MEMBUS_MAI_ADDR_ACK;
|
||||
|
||||
/* read and send read restart */
|
||||
if(core->cma_rd_rq){
|
||||
core->cmb |= core->core[core->cma];
|
||||
bus->c34 |= core->cmb & FW;
|
||||
bus->c12 |= MEMBUS_MAI_RD_RS;
|
||||
//trace(" sending RD RS\n");
|
||||
if(core->cma_wr_rq)
|
||||
core->cmb = 0;
|
||||
else
|
||||
core->cmc_p_act = -1;
|
||||
}
|
||||
core->cmc_pse_sync = 1;
|
||||
if(!core->cma_wr_rq)
|
||||
goto end;
|
||||
}
|
||||
/* write restart */
|
||||
if(core->cmc_pse_sync && bus->c12_pulse & MEMBUS_WR_RS){
|
||||
//trace(" accepting WR RS\n");
|
||||
core->cmc_p_act = -1;
|
||||
core->cmb |= bus->c34 & FW;
|
||||
bus->c34 = 0;
|
||||
end:
|
||||
//trace(" writing\n");
|
||||
core->core[core->cma] = core->cmb;
|
||||
core->cmc_p_act = -1; /* this seems unnecessary */
|
||||
core->cmc_aw_rq = 1;
|
||||
}
|
||||
//if(core->cmc_p_act < 0)
|
||||
// trace(" now disconnected from proc\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When a cycle is requested we acknowledge the address
|
||||
* by pulsing the processor through the bus.
|
||||
* A read is completed immediately and signalled by a second pulse.
|
||||
* A write is completed on a second call. */
|
||||
// TODO: implement this properly... according to the manual
|
||||
void
|
||||
wakemem(void)
|
||||
/* This is based on the 162 memory */
|
||||
static int
|
||||
wakeff(Mem *mem, Membus *bus)
|
||||
{
|
||||
hword a;
|
||||
if(membus0_pulse & MEMBUS_RQ_CYC){
|
||||
a = membus0>>4 & 037777;
|
||||
if(membus0 & MEMBUS_MA21_1) a |= 0040000;
|
||||
if(membus0 & MEMBUS_MA20_1) a |= 0100000;
|
||||
if(membus0 & MEMBUS_MA19_1) a |= 0200000;
|
||||
if(membus0 & MEMBUS_MA18_1) a |= 0400000;
|
||||
if(a >= maxmem ||
|
||||
membus0 & MEMBUS_MA_FMC_SEL1 && a >= 16)
|
||||
return;
|
||||
FMem *ff;
|
||||
hword fma;
|
||||
bool fma_rd_rq, fma_wr_rq;
|
||||
bool fmc_wr_sel;
|
||||
ff = mem->module;
|
||||
|
||||
membus0 |= MEMBUS_MAI_ADDR_ACK;
|
||||
hold = membus0 & MEMBUS_MA_FMC_SEL1 ? &fmem[a] : &memory[a];
|
||||
if(membus0 & MEMBUS_RD_RQ){
|
||||
membus1 = *hold & FW;
|
||||
membus0 |= MEMBUS_MAI_RD_RS;
|
||||
if(!(membus0 & MEMBUS_WR_RQ))
|
||||
hold = nil;
|
||||
/* Only respond to one processor */
|
||||
if(bus != mem->bus[ff->fmc_p_sel])
|
||||
return 1;
|
||||
|
||||
fma_rd_rq = !!(bus->c12 & MEMBUS_RD_RQ);
|
||||
fma_wr_rq = !!(bus->c12 & MEMBUS_WR_RQ);
|
||||
if(!ff->fmc_act && bus->c12 & MEMBUS_RQ_CYC){
|
||||
//trace(" accepting memory cycle from proc %d\n", ff->fmc_p_sel);
|
||||
ff->fmc_act = 1;
|
||||
|
||||
fma = bus->c12>>4 & 017;
|
||||
//trace(" sending ADDR ACK\n");
|
||||
bus->c12 |= MEMBUS_MAI_ADDR_ACK;
|
||||
|
||||
if(fma_rd_rq){
|
||||
bus->c34 |= ff->ff[fma] & FW;
|
||||
bus->c12 |= MEMBUS_MAI_RD_RS;
|
||||
//trace(" sending RD RS\n");
|
||||
if(!fma_wr_rq)
|
||||
goto end;
|
||||
}
|
||||
if(fma_wr_rq){
|
||||
ff->ff[fma] = 0;
|
||||
ff->fmc_wr = 1;
|
||||
}
|
||||
}
|
||||
if(membus0 & MEMBUS_WR_RS && hold){
|
||||
*hold = membus1 & FW;
|
||||
hold = nil;
|
||||
fmc_wr_sel = ff->fmc_act && !fma_rd_rq;
|
||||
if(fmc_wr_sel && ff->fmc_wr && bus->c34){
|
||||
//trace(" writing\n");
|
||||
ff->ff[fma] |= bus->c34 & FW;
|
||||
bus->c34 = 0;
|
||||
}
|
||||
if(bus->c12_pulse & MEMBUS_WR_RS){
|
||||
//trace(" accepting WR RS\n");
|
||||
end:
|
||||
ff->fmc_act = 0;
|
||||
ff->fmc_wr = 0;
|
||||
}
|
||||
//if(!ff->fmc_act)
|
||||
// trace(" now available again\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
wakemem(Membus *bus)
|
||||
{
|
||||
int sel;
|
||||
int nxm;
|
||||
|
||||
if(bus->c12 & MEMBUS_MA_FMC_SEL1){
|
||||
nxm = bus->fmem->wake(bus->fmem, bus);
|
||||
if(nxm)
|
||||
goto core;
|
||||
}else{
|
||||
core:
|
||||
sel = 0;
|
||||
if(bus->c12 & MEMBUS_MA21_1) sel |= 001;
|
||||
if(bus->c12 & MEMBUS_MA20_1) sel |= 002;
|
||||
if(bus->c12 & MEMBUS_MA19_1) sel |= 004;
|
||||
if(bus->c12 & MEMBUS_MA18_1) sel |= 010;
|
||||
if(bus->cmem[sel])
|
||||
nxm = bus->cmem[sel]->wake(bus->cmem[sel], bus);
|
||||
else
|
||||
nxm = 1;
|
||||
}
|
||||
/* TODO: do something when memory didn't respond */
|
||||
}
|
||||
|
||||
/* Allocate a 16k core memory module and
|
||||
* a memory bus attachment. */
|
||||
Mem*
|
||||
makecoremem(const char *file)
|
||||
{
|
||||
CMem *core;
|
||||
Mem *mem;
|
||||
|
||||
core = malloc(sizeof(CMem));
|
||||
memset(core, 0, sizeof(CMem));
|
||||
core->filename = file;
|
||||
pthread_mutex_init(&core->mutex, nil);
|
||||
core->cmc_aw_rq = 1;
|
||||
core->cmc_p_act = -1;
|
||||
core->cmc_last_proc = 2;
|
||||
readmem(core->filename, core->core, 040000);
|
||||
|
||||
mem = malloc(sizeof(Mem));
|
||||
mem->module = core;
|
||||
mem->bus[0] = &memterm;
|
||||
mem->bus[1] = &memterm;
|
||||
mem->bus[2] = &memterm;
|
||||
mem->bus[3] = &memterm;
|
||||
mem->wake = wakecore;
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
Mem*
|
||||
makefastmem(int p)
|
||||
{
|
||||
FMem *ff;
|
||||
Mem *mem;
|
||||
|
||||
ff = malloc(sizeof(FMem));
|
||||
memset(ff, 0, sizeof(FMem));
|
||||
ff->fmc_p_sel = p;
|
||||
|
||||
mem = malloc(sizeof(Mem));
|
||||
mem->module = ff;
|
||||
mem->bus[0] = &memterm;
|
||||
mem->bus[1] = &memterm;
|
||||
mem->bus[2] = &memterm;
|
||||
mem->bus[3] = &memterm;
|
||||
mem->wake = wakeff;
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/* Attach mem to bus for processor p.
|
||||
* If n < 0, it is attached as fast memory,
|
||||
* else at addresses starting at n<<14. */
|
||||
void
|
||||
attachmem(Mem *mem, int p, Membus *bus, int n)
|
||||
{
|
||||
if(n < 0)
|
||||
bus->fmem = mem;
|
||||
else
|
||||
bus->cmem[n] = mem;
|
||||
mem->bus[p] = bus;
|
||||
}
|
||||
|
||||
void
|
||||
showmem(Membus *bus)
|
||||
{
|
||||
int i;
|
||||
CMem *core;
|
||||
FMem *ff;
|
||||
|
||||
if(bus->fmem){
|
||||
ff = bus->fmem->module;
|
||||
printf("fastmem: proc %d\n", ff->fmc_p_sel);
|
||||
}
|
||||
for(i = 0; i < 16; i++)
|
||||
if(bus->cmem[i]){
|
||||
core = bus->cmem[i]->module;
|
||||
printf("%06o %06o %s\n", i<<14, (i+1 << 14)-1, core->filename);
|
||||
}
|
||||
}
|
||||
|
||||
79
src/pdp6.h
79
src/pdp6.h
@@ -2,6 +2,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define nelem(a) (sizeof(a)/sizeof(a[0]))
|
||||
#define nil NULL
|
||||
@@ -12,6 +15,7 @@ typedef uint64_t word;
|
||||
typedef uint32_t hword;
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
typedef int8_t i8;
|
||||
typedef uint8_t u8;
|
||||
typedef unsigned char uchar;
|
||||
typedef uchar bool;
|
||||
@@ -106,13 +110,18 @@ enum Opcode {
|
||||
|
||||
};
|
||||
|
||||
typedef struct Mem Mem;
|
||||
typedef struct Membus Membus;
|
||||
typedef struct FMem FMem;
|
||||
typedef struct CMem CMem;
|
||||
typedef struct Busdev Busdev;
|
||||
typedef struct IOBus IOBus;
|
||||
typedef struct Apr Apr;
|
||||
|
||||
/*
|
||||
* Memory
|
||||
*/
|
||||
|
||||
void initmem(void);
|
||||
void dumpmem(void);
|
||||
void wakemem(void);
|
||||
// 7-2, 7-10
|
||||
enum {
|
||||
MEMBUS_MA21 = 0000000000001,
|
||||
@@ -135,12 +144,61 @@ enum {
|
||||
MEMBUS_MAI_RD_RS = 0200000000000,
|
||||
MEMBUS_MAI_ADDR_ACK = 0400000000000,
|
||||
};
|
||||
/* 0 is cable 1 & 2 (above bits); 1 is cable 3 & 4 (data) */
|
||||
extern word membus0, membus1;
|
||||
/* record the state of membus0 of the last pulse step
|
||||
* to recognize pulses or edges */
|
||||
extern word membus0_last, membus0_pulse;
|
||||
|
||||
/* A memory module connected to up to 4 Membuses */
|
||||
struct Mem
|
||||
{
|
||||
void *module;
|
||||
Membus *bus[4];
|
||||
int (*wake)(Mem *mem, Membus *bus);
|
||||
};
|
||||
|
||||
struct Membus
|
||||
{
|
||||
/* c12 are cables 1 and 2, c34 3 and 4.
|
||||
* c??_prev records the previous state of the bus
|
||||
* and c??_pulse is used to detect leading edges. */
|
||||
word c12, c12_prev, c12_pulse;
|
||||
word c34, c34_prev, c34_pulse;
|
||||
/* cycle counter to implement NXM timeout */
|
||||
int numcyc;
|
||||
|
||||
Mem *fmem; /* fast memory */
|
||||
Mem *cmem[16]; /* 16 16k core modules */
|
||||
};
|
||||
extern Membus memterm; /* terminator */
|
||||
void wakemem(Membus *bus);
|
||||
|
||||
/* Fast memory 162, 16 words */
|
||||
struct FMem
|
||||
{
|
||||
word ff[16];
|
||||
i8 fmc_p_sel;
|
||||
bool fmc_act;
|
||||
bool fmc_wr;
|
||||
};
|
||||
Mem *makefastmem(int p);
|
||||
|
||||
/* Core memory 161C, 16k words */
|
||||
struct CMem
|
||||
{
|
||||
const char *filename;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
word core[040000];
|
||||
word cmb;
|
||||
hword cma;
|
||||
bool cma_rd_rq, cma_wr_rq;
|
||||
bool cmc_aw_rq;
|
||||
i8 cmc_p_act;
|
||||
u8 cmc_last_proc;
|
||||
bool cmc_pse_sync;
|
||||
};
|
||||
Mem *makecoremem(const char *file);
|
||||
|
||||
void attachmem(Mem *mem, int p, Membus *bus, int n);
|
||||
void readmem(const char *file, word *mem, word size);
|
||||
void showmem(Membus *bus);
|
||||
|
||||
/*
|
||||
* IO bus
|
||||
@@ -191,7 +249,6 @@ enum {
|
||||
#define IOB_DATAI (bus->c34 & IOBUS_IOB_DATAI)
|
||||
|
||||
/* A peripheral device connected to an IO bus */
|
||||
typedef struct Busdev Busdev;
|
||||
struct Busdev
|
||||
{
|
||||
void *dev;
|
||||
@@ -199,7 +256,6 @@ struct Busdev
|
||||
u8 req;
|
||||
};
|
||||
|
||||
typedef struct IOBus IOBus;
|
||||
struct IOBus
|
||||
{
|
||||
/* c12 are cables 1 and 2, c34 3 and 4.
|
||||
@@ -222,7 +278,6 @@ void recalc_req(IOBus *bus);
|
||||
/* Arithmetic Processor 166 */
|
||||
#define CPA (0000>>2)
|
||||
#define PI (0004>>2)
|
||||
typedef struct Apr Apr;
|
||||
|
||||
typedef void Pulse(Apr *apr);
|
||||
#define pulse(p) static void p(Apr *apr)
|
||||
@@ -230,6 +285,7 @@ typedef void Pulse(Apr *apr);
|
||||
struct Apr
|
||||
{
|
||||
IOBus iobus;
|
||||
Membus membus;
|
||||
|
||||
hword ir;
|
||||
word mi;
|
||||
@@ -336,6 +392,7 @@ struct Apr
|
||||
int ncurpulses, nnextpulses;
|
||||
};
|
||||
void initapr(Apr *apr);
|
||||
void curpulse(Apr *apr, Pulse *p);
|
||||
void nextpulse(Apr *apr, Pulse *p);
|
||||
void *aprmain(void *p);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user