3B2: Rev 3 Development Base

This change introduces initial support for the AT&T 3B2 Rev 3 platform, based
around the WE32200 CPU with up to 64MB of RAM and SCSI disk and tape support.

This simulator is experimental and not yet supported. It will not be built by
default, but can be built with:

     make 3b2-600

Or by using the 3B2-600 Windows Visual Studio project.
This commit is contained in:
Seth Morabito 2021-08-09 11:07:21 -07:00
parent acd5ae6579
commit c0beba5498
38 changed files with 6084 additions and 802 deletions

View file

@ -28,13 +28,34 @@
from the author.
*/
#include "3b2_defs.h"
#include "3b2_cpu.h"
#include "rom_rev2_bin.h"
/*
* This is an implementation of the WE32100 and WE32200 CPUs, used in
* the Rev 2 (e.g. 3B2/400) and Rev 3 (e.g. 3B2/600G) AT&T 3B2
* systems, respectively.
*
* The WE32000 series of microprocessors were a fully 32-bit general
* purpose CISC architecture purposely designed to run UNIX.
*
* The architecture is fully described in the following books:
*
* - "WE 32100 Microprocessor Information Manual" (AT&T, 1985)
* - "WE 32200 Microprocessor Information Manual" (AT&T, 1988)
*
*/
#include <sim_defs.h>
#include "3b2_defs.h"
#include "3b2_cpu.h"
#if defined(REV3)
#include "rom_rev3_bin.h"
#else
#include "rom_rev2_bin.h"
#endif
#define MAX_SUB_RETURN_SKIP 9
uint32 rom_size = BOOT_CODE_SIZE;
/* Static function declarations */
static uint32 cpu_effective_address(operand * op);
static uint32 cpu_read_op(operand * op);
@ -100,7 +121,7 @@ volatile int32 stop_reason;
volatile uint32 abort_reason;
/* Register data */
uint32 R[16];
uint32 R[NUM_REGISTERS];
/* Other global CPU state */
uint8 cpu_int_ipl = 0; /* Interrupt IPL level */
@ -108,7 +129,7 @@ uint8 cpu_int_vec = 0; /* Interrupt vector */
t_bool cpu_nmi = FALSE; /* If set, there has been an NMI */
int32 pc_incr = 0; /* Length (in bytes) of instruction
currently being executed */
currently being executed */
t_bool cpu_ex_halt = FALSE; /* Flag to halt on exceptions /
traps */
t_bool cpu_km = FALSE; /* If true, kernel mode has been forced
@ -137,13 +158,20 @@ BITFIELD psw_bits[] = {
BIT(CD), /* Cache Disable */
BIT(QIE), /* Quick-Interrupt Enable */
BIT(CFD), /* Cache Flush Disable */
#if defined(REV3)
BIT(X), /* Extend Carry / Borrow */
BIT(AR), /* Additional Register Save */
BIT(EXUC), /* Exception/User Call Option */
BIT(EA), /* Enable Arbitrary Alignment */
BITNCF(2), /* Unused */
#else
BITNCF(6), /* Unused */
#endif
ENDBITS
};
/* Registers. */
REG cpu_reg[] = {
{ HRDATAD (PC, R[NUM_PC], 32, "Program Counter") },
{ HRDATAD (R0, R[0], 32, "General purpose register 0") },
{ HRDATAD (R1, R[1], 32, "General purpose register 1") },
{ HRDATAD (R2, R[2], 32, "General purpose register 2") },
@ -159,6 +187,27 @@ REG cpu_reg[] = {
{ HRDATAD (SP, R[NUM_SP], 32, "Stack Pointer") },
{ HRDATAD (PCBP, R[NUM_PCBP], 32, "Process Control Block Pointer") },
{ HRDATAD (ISP, R[NUM_ISP], 32, "Interrupt Stack Pointer") },
{ HRDATAD (PC, R[NUM_PC], 32, "Program Counter") },
#if defined(REV3)
{ HRDATAD (R16, R[16], 32, "General purpose register 16")},
{ HRDATAD (R17, R[17], 32, "General purpose register 17")},
{ HRDATAD (R18, R[18], 32, "General purpose register 18")},
{ HRDATAD (R19, R[19], 32, "General purpose register 19")},
{ HRDATAD (R20, R[20], 32, "General purpose register 20")},
{ HRDATAD (R21, R[21], 32, "General purpose register 21")},
{ HRDATAD (R22, R[22], 32, "General purpose register 22")},
{ HRDATAD (R23, R[23], 32, "General purpose register 23")},
{ HRDATAD (R24, R[24], 32, "Privileged register 24")},
{ HRDATAD (R25, R[25], 32, "Privileged register 25")},
{ HRDATAD (R26, R[26], 32, "Privileged register 26")},
{ HRDATAD (R27, R[27], 32, "Privileged register 27")},
{ HRDATAD (R28, R[28], 32, "Privileged register 28")},
{ HRDATAD (R29, R[29], 32, "Privileged register 29")},
{ HRDATAD (R30, R[30], 32, "Privileged register 30")},
{ HRDATAD (R31, R[31], 32, "Privileged register 31")},
#endif
{ HRDATAD (IPL, cpu_int_ipl, 8, "Current CPU IPL bits")},
{ HRDATAD (VEC, cpu_int_vec, 8, "Current CPU interrupt vector")},
{ NULL }
};
@ -176,7 +225,9 @@ static DEBTAB cpu_deb_tab[] = {
{ NULL, 0, NULL }
};
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK|UNIT_IDLE, MAXMEMSIZE) };
UNIT cpu_unit = {
UDATA (NULL, UNIT_FIX|UNIT_BINK|UNIT_IDLE, DEFMEMSIZE)
};
/*
* The following commands deposit a small calibration program into
@ -239,22 +290,34 @@ static const char *att3b2_clock_precalibrate_commands[] = {
NULL
};
/*
* TODO: This works fine for now, but the moment we want to emulate
* SCSI (0x0100) or EPORTS (0x0102) we're in trouble!
*/
const char *cio_names[8] = {
"", "SBD", "NI", "PORTS",
"*VOID*", "CTC", "NAU", "*VOID*"
CONST cio_device cio_entries[] = {
{0x0001, "SBD"}, /* System Board */
{0x0002, "NI"}, /* Network Interface Card (ethernet) */
{0x0003, "PORTS"}, /* Serial I/O Card */
{0x0005, "CTC"}, /* Cartridge Tape Controller */
{0x0100, "SCSI"}, /* SCSI disk and tape controller */
{0} /* END */
};
MTAB cpu_mod[] = {
#if defined(REV2)
{ UNIT_MSIZE, (1u << 20), NULL, "1M",
&cpu_set_size, NULL, NULL, "Set Memory to 1M bytes" },
{ UNIT_MSIZE, (1u << 21), NULL, "2M",
&cpu_set_size, NULL, NULL, "Set Memory to 2M bytes" },
#endif
{ UNIT_MSIZE, (1u << 22), NULL, "4M",
&cpu_set_size, NULL, NULL, "Set Memory to 4M bytes" },
#if defined(REV3)
{ UNIT_MSIZE, (1u << 23), NULL, "8M",
&cpu_set_size, NULL, NULL, "Set Memory to 8M bytes" },
{ UNIT_MSIZE, (1u << 24), NULL, "16M",
&cpu_set_size, NULL, NULL, "Set Memory to 16M bytes" },
{ UNIT_MSIZE, (1u << 25), NULL, "32M",
&cpu_set_size, NULL, NULL, "Set Memory to 32M bytes" },
{ UNIT_MSIZE, (1u << 26), NULL, "64M",
&cpu_set_size, NULL, NULL, "Set Memory to 64M bytes" },
#endif
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
&cpu_set_hist, &cpu_show_hist, NULL, "Displays instruction history" },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL,
@ -265,10 +328,14 @@ MTAB cpu_mod[] = {
NULL, &cpu_show_cio, NULL, "Display CIO configuration" },
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
{ UNIT_EXHALT, UNIT_EXHALT, "Halt on Exception", "EXHALT",
NULL, NULL, NULL, "Enables Halt on exceptions and traps" },
{ UNIT_EXHALT, 0, "No halt on exception", "NOEXHALT",
NULL, NULL, NULL, "Disables Halt on exceptions and traps" },
{ UNIT_EXBRK, UNIT_EXBRK, "Break on exceptions", "EXBRK",
NULL, NULL, NULL, "Enable break on exceptions and traps" },
{ UNIT_EXBRK, 0, "No break on exceptions", "NOEXBRK",
NULL, NULL, NULL, "Disable break on exceptions and traps" },
{ UNIT_OPBRK, UNIT_OPBRK, "Break on invalid opcodes", "OPBRK",
NULL, NULL, NULL, "Enable break on invalid opcodes" },
{ UNIT_OPBRK, 0, "No break on invalid opcodes", "NOOPBRK",
NULL, NULL, NULL, "Disable break on invalid opcodes" },
{ 0 }
};
@ -301,8 +368,6 @@ DEVICE cpu_dev = {
&cpu_description /* Device Description */
};
#define HWORD_OP_COUNT 11
mnemonic hword_ops[HWORD_OP_COUNT] = {
{0x3009, 0, OP_NONE, NA, "MVERNO", -1, -1, -1, -1},
{0x300d, 0, OP_NONE, NA, "ENBVJMP", -1, -1, -1, -1},
@ -314,6 +379,9 @@ mnemonic hword_ops[HWORD_OP_COUNT] = {
{0x3045, 0, OP_NONE, NA, "RETG", -1, -1, -1, -1},
{0x3061, 0, OP_NONE, NA, "GATE", -1, -1, -1, -1},
{0x30ac, 0, OP_NONE, NA, "CALLPS", -1, -1, -1, -1},
#if defined(REV3)
{0x30c0, 0, OP_NONE, NA, "UCALLPS", -1, -1, -1, -1},
#endif
{0x30c8, 0, OP_NONE, NA, "RETPS", -1, -1, -1, -1}
};
@ -328,7 +396,11 @@ mnemonic ops[256] = {
{0x06, 2, OP_COPR, WD, "SPOPRT", 1, -1, -1, -1},
{0x07, 3, OP_COPR, WD, "SPOPT2", 1, -1, -1, 2},
{0x08, 0, OP_NONE, NA, "RET", -1, -1, -1, -1},
#if defined(REV3)
{0x09, 3, OP_DESC, WD, "CASWI", 0, 1, -1, 2},
#else
{0x09, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
#endif
{0x0a, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x0b, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x0c, 2, OP_DESC, WD, "MOVTRW", 0, -1, -1, 1},
@ -650,12 +722,23 @@ t_stat cpu_show_stack(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
t_stat cpu_show_cio(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
uint32 i;
uint32 i, j;
fprintf(st, " SLOT DEVICE\n");
fprintf(st, "---------------------\n");
for (i = 0; i < CIO_SLOTS; i++) {
fprintf(st, " %d %s\n", i, cio_names[cio[i].id & 0x7]);
/* Find the matching entry for this slot */
for (j = 0; cio_entries[j].id != 0; j++) {
if (cio_entries[j].id == cio[i].id) {
break;
}
}
if (cio_entries[j].id == 0) {
fprintf(st, " %d\n", i);
} else {
fprintf(st, " %d %s\n", i, cio_entries[j].name);
}
}
return SCPE_OK;
@ -669,7 +752,7 @@ void cpu_load_rom()
return;
}
for (i = 0; i < BOOT_CODE_SIZE; i++) {
for (i = 0; i < rom_size; i++) {
val = BOOT_CODE_ARRAY[i];
sc = (~(i & 3) << 3) & 0x1f;
mask = 0xffu << sc;
@ -790,32 +873,31 @@ t_stat cpu_reset(DEVICE *dptr)
if (!sim_is_running) {
/* Clear registers */
for (i = 0; i < 16; i++) {
for (i = 0; i < NUM_REGISTERS; i++) {
R[i] = 0;
}
/* Allocate memory */
if (ROM == NULL) {
ROM = (uint32 *) calloc(BOOT_CODE_SIZE >> 2, sizeof(uint32));
if (ROM == NULL) {
return SCPE_MEM;
}
memset(ROM, 0, BOOT_CODE_SIZE >> 2);
/* Allocate ROM */
if (ROM != NULL) {
free(ROM);
}
if (RAM == NULL) {
RAM = (uint32 *) calloc((size_t)(MEM_SIZE >> 2), sizeof(uint32));
if (RAM == NULL) {
return SCPE_MEM;
}
memset(RAM, 0, (size_t)(MEM_SIZE >> 2));
sim_vm_is_subroutine_call = cpu_is_pc_a_subroutine_call;
ROM = (uint32 *) calloc((size_t)(rom_size >> 2), sizeof(uint32));
if (ROM == NULL) {
return SCPE_MEM;
}
cpu_load_rom();
/* Allocate RAM */
if (RAM != NULL) {
free(RAM);
}
RAM = (uint32 *) calloc((size_t)(MEM_SIZE >> 2), sizeof(uint32));
if (RAM == NULL) {
return SCPE_MEM;
}
sim_vm_is_subroutine_call = cpu_is_pc_a_subroutine_call;
}
abort_context = C_NONE;
@ -894,7 +976,7 @@ t_stat fprint_sym_m(FILE *of, t_addr addr, t_value *val)
if (inst == 0x30) {
/* Scan to find opcode */
inst = 0x3000 | (int8) val[vp++];
inst = 0x3000 | (uint8) val[vp++];
for (i = 0; i < HWORD_OP_COUNT; i++) {
if (hword_ops[i].opcode == inst) {
mn = &hword_ops[i];
@ -1415,7 +1497,7 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number, int8 *etyp
operand *oper = &instr->operands[op_number];
/* Read in the descriptor byte */
desc = read_b(pa + offset++, ACC_OF);
desc = read_b(pa + offset++, ACC_IF);
oper->mode = (desc >> 4) & 0xf;
oper->reg = desc & 0xf;
@ -1434,10 +1516,10 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number, int8 *etyp
case 4: /* Word Immediate, Register Mode */
switch (oper->reg) {
case 15: /* Word Immediate */
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u;
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_IF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 24u;
oper->data = oper->embedded.w;
break;
default: /* Register mode */
@ -1448,8 +1530,8 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number, int8 *etyp
case 5: /* Halfword Immediate, Register Deferred Mode */
switch (oper->reg) {
case 15: /* Halfword Immediate */
oper->embedded.h = (uint16) read_b(pa + offset++, ACC_OF);
oper->embedded.h |= ((uint16) read_b(pa + offset++, ACC_OF)) << 8u;
oper->embedded.h = (uint16) read_b(pa + offset++, ACC_IF);
oper->embedded.h |= ((uint16) read_b(pa + offset++, ACC_IF)) << 8u;
oper->data = oper->embedded.h;
break;
case 11: /* INVALID */
@ -1463,7 +1545,7 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number, int8 *etyp
case 6: /* Byte Immediate, FP Short Offset */
switch (oper->reg) {
case 15: /* Byte Immediate */
oper->embedded.b = read_b(pa + offset++, ACC_OF);
oper->embedded.b = read_b(pa + offset++, ACC_IF);
oper->data = oper->embedded.b;
break;
default: /* FP Short Offset */
@ -1475,10 +1557,10 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number, int8 *etyp
case 7: /* Absolute, AP Short Offset */
switch (oper->reg) {
case 15: /* Absolute */
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u;
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_IF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 24u;
oper->data = oper->embedded.w;
break;
default: /* AP Short Offset */
@ -1489,30 +1571,30 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number, int8 *etyp
break;
case 8: /* Word Displacement */
case 9: /* Word Displacement Deferred */
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u;
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_IF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 24u;
oper->data = oper->embedded.w;
break;
case 10: /* Halfword Displacement */
case 11: /* Halfword Displacement Deferred */
oper->embedded.h = read_b(pa + offset++, ACC_OF);
oper->embedded.h |= ((uint16) read_b(pa + offset++, ACC_OF)) << 8u;
oper->embedded.h = read_b(pa + offset++, ACC_IF);
oper->embedded.h |= ((uint16) read_b(pa + offset++, ACC_IF)) << 8u;
oper->data = oper->embedded.h;
break;
case 12: /* Byte Displacement */
case 13: /* Byte Displacement Deferred */
oper->embedded.b = read_b(pa + offset++, ACC_OF);
oper->embedded.b = read_b(pa + offset++, ACC_IF);
oper->data = oper->embedded.b;
break;
case 14: /* Absolute Deferred, Extended-Operand */
switch (oper->reg) {
case 15: /* Absolute Deferred */
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u;
oper->embedded.w = (uint32) read_b(pa + offset++, ACC_IF);
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 8u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 16u;
oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_IF)) << 24u;
break;
case 0:
case 2:
@ -1613,21 +1695,21 @@ uint8 decode_instruction(instr *instr)
case OP_NONE:
break;
case OP_BYTE:
instr->operands[0].embedded.b = read_b(pa + offset++, ACC_OF);
instr->operands[0].embedded.b = read_b(pa + offset++, ACC_IF);
instr->operands[0].mode = 6;
instr->operands[0].reg = 15;
break;
case OP_HALF:
instr->operands[0].embedded.h = read_b(pa + offset++, ACC_OF);
instr->operands[0].embedded.h |= read_b(pa + offset++, ACC_OF) << 8;
instr->operands[0].embedded.h = read_b(pa + offset++, ACC_IF);
instr->operands[0].embedded.h |= read_b(pa + offset++, ACC_IF) << 8;
instr->operands[0].mode = 5;
instr->operands[0].reg = 15;
break;
case OP_COPR:
instr->operands[0].embedded.w = (uint32) read_b(pa + offset++, ACC_OF);
instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_OF) << 8;
instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_OF) << 16;
instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_OF) << 24;
instr->operands[0].embedded.w = (uint32) read_b(pa + offset++, ACC_IF);
instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_IF) << 8;
instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_IF) << 16;
instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_IF) << 24;
instr->operands[0].mode = 4;
instr->operands[0].reg = 15;
@ -1725,11 +1807,11 @@ static SIM_INLINE void cpu_context_switch_1(uint32 new_pcbp)
void cpu_on_interrupt(uint16 vec)
{
uint32 new_pcbp;
uint32 new_pcbp, new_pcbp_ptr;
sim_debug(IRQ_MSG, &cpu_dev,
"[%08x] [cpu_on_interrupt] vec=%02x (%d)\n",
R[NUM_PC], vec, vec);
"[%08x] [cpu_on_interrupt] vec=%02x (%d) csr_data = %x\n",
R[NUM_PC], vec, vec, csr_data);
/*
* "If a nonmaskable interrupt request is received, an auto-vector
@ -1741,6 +1823,7 @@ void cpu_on_interrupt(uint16 vec)
vec = 0;
}
cpu_nmi = FALSE;
cpu_km = TRUE;
if (R[NUM_PSW] & PSW_QIE_MASK) {
@ -1750,7 +1833,8 @@ void cpu_on_interrupt(uint16 vec)
return;
}
new_pcbp = read_w(0x8c + (4 * vec), ACC_AF);
new_pcbp_ptr = (uint32)0x8c + (4 * (uint32)vec);
new_pcbp = read_w(new_pcbp_ptr, ACC_AF);
/* Save the old PCBP */
irq_push_word(R[NUM_PCBP]);
@ -1810,7 +1894,7 @@ t_stat sim_instr(void)
return STOP_ESTK;
}
if (cpu_unit.flags & UNIT_EXHALT) {
if (cpu_unit.flags & UNIT_EXBRK) {
return STOP_EX;
}
@ -1906,7 +1990,7 @@ t_stat sim_instr(void)
/* Set the correct IRQ state */
cpu_calc_ints();
if (PSW_CUR_IPL < cpu_int_ipl) {
if (cpu_nmi || (PSW_CUR_IPL < cpu_int_ipl)) {
cpu_on_interrupt(cpu_int_vec);
for (i = 0; i < CIO_SLOTS; i++) {
if (cio[i].intr &&
@ -1933,7 +2017,8 @@ t_stat sim_instr(void)
}
/* Reset the TM bits */
R[NUM_PSW] |= PSW_TM_MASK;
/* TODO: Figure out why we were doing this! */
/* R[NUM_PSW] |= PSW_TM_MASK; */
/* Record the instruction for history */
if (cpu_hist_size > 0) {
@ -2139,6 +2224,7 @@ t_stat sim_instr(void)
case BPT:
case HALT:
trap = BREAKPOINT_TRAP;
stop_reason = STOP_IBKPT;
break;
case BRH:
pc_incr = sign_extend_h(dst->embedded.h);
@ -2189,6 +2275,25 @@ t_stat sim_instr(void)
R[NUM_AP] = a;
pc_incr = 0;
break;
#if defined(REV3)
case CASWI:
a = cpu_read_op(src1);
b = cpu_read_op(src2);
c = cpu_read_op(dst);
result = c - b;
if (result == 0) {
cpu_write_op(src2, c);
} else {
cpu_write_op(dst, a);
}
cpu_set_n_flag((int32)result < 0);
cpu_set_z_flag(result == 0);
cpu_set_c_flag((uint32)b > (uint32)c);
cpu_set_v_flag_op(result, dst);
break;
#endif
case CFLUSH:
break;
case CALLPS:
@ -2384,7 +2489,7 @@ t_stat sim_instr(void)
cpu_set_c_flag(0);
break;
case MVERNO:
R[0] = WE32100_VER;
R[0] = CPU_VERSION;
break;
case ENBVJMP:
if (cpu_execution_level() != EX_LVL_KERN) {
@ -2483,21 +2588,21 @@ t_stat sim_instr(void)
result = a >> b;
/* Ensure the MSB is copied appropriately */
switch (op_type(src2)) {
case WD:
if (a & 0x80000000) {
result |= shift_32_table[b + 1];
}
break;
case HW:
if (a & 0x8000) {
result |= shift_16_table[b + 1];
}
break;
case BT:
if (a & 0x80) {
result |= shift_8_table[b + 1];
}
break;
case WD:
if (a & 0x80000000) {
result |= shift_32_table[b + 1];
}
break;
case HW:
if (a & 0x8000) {
result |= shift_16_table[b + 1];
}
break;
case BT:
if (a & 0x80) {
result |= shift_8_table[b + 1];
}
break;
}
cpu_write_op(dst, result);
cpu_set_nz_flags(result, dst);
@ -2549,6 +2654,20 @@ t_stat sim_instr(void)
/* Finish push of PC and PSW */
R[NUM_SP] += 8;
pc_incr = 0;
#if defined(REV3)
/*
* NB: The WE32200 processor manual claims that this is
* not a privileged instruction, and that it can be run
* from any processor level. This is not true. Tests in
* the Rev 3 off-line processor diagnostics check to
* ensure that there is an exception raised when calling
* GATE in a non-privileged context.
*/
if (cpu_execution_level() != EX_LVL_KERN) {
cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE);
}
#endif
break;
case MCOMW:
case MCOMH:
@ -3098,7 +3217,13 @@ t_stat sim_instr(void)
cpu_set_v_flag_op(a, dst);
break;
default:
stop_reason = STOP_OPCODE;
if (cpu_unit.flags & UNIT_OPBRK) {
stop_reason = STOP_OPCODE;
}
sim_debug(EXECUTE_MSG, &cpu_dev,
"[%08x] Illegal Opcode 0x%x\n",
R[NUM_PC], inst.mn->opcode);
cpu_abort(NORMAL_EXCEPTION, ILLEGAL_OPCODE);
break;
};
@ -3237,6 +3362,7 @@ static SIM_INLINE void cpu_perform_gate(uint32 index1, uint32 index2)
{
uint32 gate_l2, new_psw;
abort_context = C_NORMAL_GATE_VECTOR;
cpu_km = TRUE;
gate_l2 = read_w(index1, ACC_AF) + index2;
@ -3262,6 +3388,7 @@ static SIM_INLINE void cpu_perform_gate(uint32 index1, uint32 index2)
R[NUM_PSW] = new_psw;
cpu_km = FALSE;
abort_context = C_NONE;
}
/*
@ -3329,7 +3456,9 @@ static uint32 cpu_effective_address(operand *op)
return read_w(R[op->reg] + sign_extend_b(op->embedded.b), ACC_AF);
}
stop_reason = STOP_OPCODE;
if (cpu_unit.flags & UNIT_OPBRK) {
stop_reason = STOP_OPCODE;
}
return 0;
}
@ -3507,9 +3636,13 @@ static void cpu_write_op(operand * op, t_uint64 val)
return;
}
/* Registers always get the full 32-bits written */
R[op->reg] = (uint32) val;
/* Registers always get the full 32-bits written, EXCEPT for
* the PSW, which has some Read-Only fields. */
if (op->reg == NUM_PSW) {
WRITE_PSW((uint32) val);
} else {
R[op->reg] = (uint32) val;
}
return;
}
@ -3566,19 +3699,25 @@ static void cpu_calc_ints()
}
/* If none was found, look for system board interrupts */
#if defined(REV3)
// TODO: Rev 3 interrupt support
cpu_int_ipl = cpu_int_vec = 0;
#else
if (csr_data & CSRPIR8) {
cpu_int_ipl = cpu_int_vec = CPU_PIR8_IPL;
cpu_int_ipl = cpu_int_vec = CPU_IPL_8;
} else if (csr_data & CSRPIR9) {
cpu_int_ipl = cpu_int_vec = CPU_PIR9_IPL;
cpu_int_ipl = cpu_int_vec = CPU_IPL_9;
} else if (id_int() || (csr_data & CSRDISK)) {
cpu_int_ipl = cpu_int_vec = CPU_ID_IF_IPL;
cpu_int_ipl = cpu_int_vec = CPU_IPL_11;
} else if ((csr_data & CSRUART) || (csr_data & CSRDMA)) {
cpu_int_ipl = cpu_int_vec = CPU_IU_DMA_IPL;
cpu_int_ipl = cpu_int_vec = CPU_IPL_13;
} else if ((csr_data & CSRCLK) || (csr_data & CSRTIMO)) {
cpu_int_ipl = cpu_int_vec = CPU_TMR_IPL;
cpu_int_ipl = cpu_int_vec = CPU_IPL_15;
} else {
cpu_int_ipl = cpu_int_vec = 0;
}
#endif
}
/*
@ -3642,27 +3781,27 @@ static SIM_INLINE t_bool cpu_v_flag()
static SIM_INLINE void cpu_set_z_flag(t_bool val)
{
if (val) {
R[NUM_PSW] = R[NUM_PSW] | PSW_Z_MASK;
R[NUM_PSW] |= PSW_Z_MASK;
} else {
R[NUM_PSW] = R[NUM_PSW] & ~PSW_Z_MASK;
R[NUM_PSW] &= ~PSW_Z_MASK;
}
}
static SIM_INLINE void cpu_set_n_flag(t_bool val)
{
if (val) {
R[NUM_PSW] = R[NUM_PSW] | PSW_N_MASK;
R[NUM_PSW] |= PSW_N_MASK;
} else {
R[NUM_PSW] = R[NUM_PSW] & ~PSW_N_MASK;
R[NUM_PSW] &= ~PSW_N_MASK;
}
}
static SIM_INLINE void cpu_set_c_flag(t_bool val)
{
if (val) {
R[NUM_PSW] = R[NUM_PSW] | PSW_C_MASK;
R[NUM_PSW] |= PSW_C_MASK;
} else {
R[NUM_PSW] = R[NUM_PSW] & ~PSW_C_MASK;
R[NUM_PSW] &= ~PSW_C_MASK;
}
}
@ -3688,12 +3827,12 @@ static SIM_INLINE void cpu_set_v_flag_op(t_uint64 val, operand *op)
static SIM_INLINE void cpu_set_v_flag(t_bool val)
{
if (val) {
R[NUM_PSW] = R[NUM_PSW] | PSW_V_MASK;
R[NUM_PSW] |= PSW_V_MASK;
if (R[NUM_PSW] & PSW_OE_MASK) {
cpu_abort(NORMAL_EXCEPTION, INTEGER_OVERFLOW);
}
} else {
R[NUM_PSW] = R[NUM_PSW] & ~PSW_V_MASK;
R[NUM_PSW] &= ~PSW_V_MASK;
}
}
@ -3825,19 +3964,28 @@ void cpu_abort(uint8 et, uint8 isc)
CONST char *cpu_description(DEVICE *dptr)
{
#if defined(REV3)
return "3B2/600G CPU (WE 32200)";
#else
return "3B2/400 CPU (WE 32100)";
#endif
}
t_stat cpu_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
#if defined(REV3)
fprintf(st, "3B2/600G CPU Help\n\n");
fprintf(st, "The 3B2/600G CPU simulates a WE 32200 at 24 MHz.\n\n");
#else
fprintf(st, "3B2/400 CPU Help\n\n");
fprintf(st, "The 3B2/400 CPU simulates a WE 32100 at 10 MHz.\n\n");
#endif
fprintf(st, "CPU options include the size of main memory.\n\n");
if (dptr->modifiers) {
MTAB *mptr;
for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) {
if (mptr->valid == &cpu_set_size) {
fprintf(st, " sim> SET CPU %4s set memory size = %sB\n",
fprintf(st, " sim> SET CPU %3s set memory size = %sB\n",
mptr->mstring, mptr->mstring);
}
}
@ -3860,8 +4008,11 @@ t_stat cpu_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr
fprintf(st, " sim> SET CPU HISTORY=n enable history, length = n\n");
fprintf(st, " sim> SHOW CPU HISTORY print CPU history\n");
fprintf(st, " sim> SHOW CPU HISTORY=n print last n entries of CPU history\n\n");
fprintf(st, "Additional docuentation for the 3B2/400 Simulator is available on the web:\n\n");
#if defined(REV3)
fprintf(st, "Additional documentation for the 3B2/600G Simulator is available on the web:\n\n");
#else
fprintf(st, "Additional documentation for the 3B2/400 Simulator is available on the web:\n\n");
#endif
fprintf(st, " https://loomcom.com/3b2/emulator.html\n\n");
return SCPE_OK;

View file

@ -67,7 +67,7 @@
#define NEW_PCB_FAULT 4
#define GATE_VECTOR_FAULT 6
/* Processor Exceptions */
/* Process Exceptions */
#define GATE_PCB_FAULT 1
/* Stack Exceptions */
@ -91,8 +91,8 @@
#define PRIVILEGED_REGISTER 15
#define PSW_ET 0
#define PSW_TM 2u
#define PSW_ISC 3u
#define PSW_TM 2
#define PSW_ISC 3
#define PSW_I 7
#define PSW_R 8
#define PSW_PM 9
@ -127,6 +127,10 @@
#define PSW_CFD_MASK (1u << PSW_CFD)
#define PSW_CUR_IPL (((R[NUM_PSW] & PSW_IPL_MASK) >> PSW_IPL) & 0xf)
/* A helper to set the PSW, preserving read-only fields */
#define PSW_RO_MASK 0x17f /* ET, TM, ISC, and R are read-only! */
#define WRITE_PSW(V) (R[NUM_PSW] = ((R[NUM_PSW] & PSW_RO_MASK) | ((V) & ~PSW_RO_MASK)))
/* Exceptional conditions handled within the instruction loop */
#define ABORT_EXC 1 /* CPU exception */
@ -152,12 +156,19 @@
#define NUM_PC 15
/* System board interrupt priority levels */
#define CPU_PIR8_IPL 8
#define CPU_PIR9_IPL 9
#define CPU_ID_IF_IPL 11
#define CPU_IU_DMA_IPL 13
#define CPU_TMR_IPL 15
#define CPU_IPL_8 8
#define CPU_IPL_9 9
#define CPU_IPL_11 11
#define CPU_IPL_13 13
#define CPU_IPL_15 15
/* Processor permission levels */
#define L_KERNEL 0
#define L_EXEC 1
#define L_SUPER 2
#define L_USER 3
/* Currently selected processor permission level */
#define CPU_CM (cpu_km ? L_KERNEL : ((R[NUM_PSW] >> PSW_CM) & 3))
/* Data types operated on by instructions. NB: These integer values
@ -172,9 +183,6 @@
#define NA -1
/* Processor Version Number */
#define WE32100_VER 0x1A
/*
*
* Mode Syntax Mode Reg. Bytes Notes
@ -224,13 +232,29 @@ typedef enum {
SPOPRT = 0x06,
SPOPT2 = 0x07,
RET = 0x08,
#if defined(REV3)
CASWI = 0x09,
SETX = 0x0A,
CLRX = 0x0B,
#endif
MOVTRW = 0x0C,
#if defined(REV3)
TEDTH = 0x0D,
PACKB = 0x0E,
UNPACKB = 0x0F,
#endif
SAVE = 0x10,
SPOPWD = 0x13,
EXTOP = 0x14,
SPOPWT = 0x17,
RESTORE = 0x18,
#if defined(REV3)
DTH = 0x19,
#endif
SWAPWI = 0x1C,
#if defined(REV3)
TGEDTH = 0x1D,
#endif
SWAPHI = 0x1E,
SWAPBI = 0x1F,
POPW = 0x20,
@ -239,9 +263,15 @@ typedef enum {
JMP = 0x24,
CFLUSH = 0x27,
TSTW = 0x28,
#if defined(REV3)
DTB = 0x29,
#endif
TSTH = 0x2A,
TSTB = 0x2B,
CALL = 0x2C,
#if defined(REV3)
TGDTH = 0x2D,
#endif
BPT = 0x2E,
WAIT = 0x2F,
EMB = 0x30, /* Multi-byte */
@ -254,6 +284,9 @@ typedef enum {
BITH = 0x3A,
BITB = 0x3B,
CMPW = 0x3C,
#if defined(REV3)
TNEDTH = 0x3D,
#endif
CMPH = 0x3E,
CMPB = 0x3F,
RGEQ = 0x40,
@ -266,6 +299,9 @@ typedef enum {
BLH = 0x4A,
BLB = 0x4B,
RLEQ = 0x4C,
#if defined(REV3)
TEDTB = 0x4D,
#endif
BLEH = 0x4E,
BLEB = 0x4F,
RGEQU = 0x50,
@ -278,6 +314,9 @@ typedef enum {
BLUH = 0x5A,
BLUB = 0x5B,
RLEQU = 0x5C,
#if defined(REV3)
TGEDTB = 0x5D,
#endif
BLEUH = 0x5E,
BLEUB = 0x5F,
RVC = 0x60,
@ -290,12 +329,14 @@ typedef enum {
BVSH = 0x6A,
BVSB = 0x6B,
REQLU = 0x6C,
#if defined(REV3)
TGDTB = 0x6D,
#endif
BEH_D = 0x6E,
BEB_D = 0x6F,
NOP = 0x70,
NOP3 = 0x72,
NOP2 = 0x73,
BNEQ = 0x74,
RNEQ = 0x74,
BNEH = 0x76,
BNEB = 0x77,
@ -303,6 +344,9 @@ typedef enum {
BRH = 0x7A,
BRB = 0x7B,
REQL = 0x7C,
#if defined(REV3)
TNEDTB = 0x7D,
#endif
BEH = 0x7E,
BEB = 0x7F,
CLRW = 0x80,
@ -323,10 +367,17 @@ typedef enum {
DECW = 0x94,
DECH = 0x96,
DECB = 0x97,
#if defined(REV3)
RETQINT = 0x98,
SUBPB2 = 0x9B,
#endif
ADDW2 = 0x9C,
ADDH2 = 0x9E,
ADDB2 = 0x9F,
PUSHW = 0xA0,
#if defined(REV3)
ADDPB2 = 0xA3,
#endif
MODW2 = 0xA4,
MODH2 = 0xA6,
MODB2 = 0xA7,
@ -363,10 +414,16 @@ typedef enum {
LLSB3 = 0xD3,
LRSW3 = 0xD4,
ROTW = 0xD8,
#if defined(REV3)
SUBPB3 = 0xDB,
#endif
ADDW3 = 0xDC,
ADDH3 = 0xDE,
ADDB3 = 0xDF,
PUSHAW = 0xE0,
#if defined(REV3)
ADDPB3 = 0xE3,
#endif
MODW3 = 0xE4,
MODH3 = 0xE6,
MODB3 = 0xE7,
@ -446,8 +503,22 @@ typedef enum {
OP_COPR /* Coprocessor instruction */
} op_mode;
/* Describes a mnemonic */
typedef struct _mnemonic {
/* Describes a CPU opcode.
*
* e.g.:
*
* {0x09, 3, OP_DESC, WD, "CASWI", 0, 1, -1, 2}
*
* - Opcode 0x09.
* - Followed by three operands.
* - Operands use descriptor bytes.
* - Default data type is word (32 bit).
* - Operand 0 is source 1.
* - Operand 1 is source 2.
* - Operand 2 is destination.
*
*/
typedef struct {
uint16 opcode;
int8 op_count; /* Number of operands */
op_mode mode; /* Dispatch mode */
@ -462,7 +533,7 @@ typedef struct _mnemonic {
/*
* Structure that describes each operand in a decoded instruction
*/
typedef struct _operand {
typedef struct {
uint8 mode; /* Embedded data addressing mode */
uint8 reg; /* Operand register (0-15) */
int8 dtype; /* Default type for the operand */
@ -491,6 +562,18 @@ typedef struct {
operand operands[4];
} instr;
/*
* A mapping of CIO identifier word to CIO device name.
*
* Each CIO expansion card in a 3B2 system identifies itself with a
* well-knon 16-bit value, used by drivers to identify the type of
* card installed in each slot.
*/
typedef struct {
uint16 id;
const char name[8];
} cio_device;
/* Function prototypes */
t_stat sys_boot(int32 flag, CONST char *ptr);
t_stat cpu_svc(UNIT *uptr);

View file

@ -56,9 +56,6 @@
#define VTOC_BLOCK 0
#define ATOW(arr,i) ((uint32)arr[i+3] + ((uint32)arr[i+2] << 8) + \
((uint32)arr[i+1] << 16) + ((uint32)arr[i] << 24))
/* Static function declarations */
static t_stat ctc_show_cqueue(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
static t_stat ctc_show_rqueue(FILE *st, UNIT *uptr, int32 val, CONST void *desc);

View file

@ -33,23 +33,34 @@
#include "sim_defs.h"
#include "sim_tmxr.h"
#include "sim_disk.h"
#include <setjmp.h>
#include "3b2_cpu.h"
#if defined(REV3)
#include "3b2_rev3_defs.h"
#include "3b2_rev3_csr.h"
#include "3b2_rev3_mmu.h"
#include "3b2_rev2_mau.h" /* Use Rev 2 MAU until Rev 3 is implemented */
#include "3b2_scsi.h"
#else
#include "3b2_rev2_defs.h"
#include "3b2_rev2_csr.h"
#include "3b2_rev2_mau.h"
#include "3b2_rev2_mmu.h"
#include "3b2_rev2_stddev.h"
#include "3b2_rev2_sys.h"
#include "3b2_id.h"
#include "3b2_ctc.h"
#endif
#include "3b2_sys.h"
#include "3b2_cpu.h"
#include "3b2_io.h"
#include "3b2_stddev.h"
#include "3b2_mem.h"
#include "3b2_dmac.h"
#include "3b2_if.h"
#include "3b2_iu.h"
#include "3b2_ports.h"
#include "3b2_ctc.h"
#include "3b2_ni.h"
#ifndef FALSE
@ -81,12 +92,39 @@ noret __libc_longjmp(jmp_buf buf, int val);
#define UNUSED(x) ((void)((x)))
#endif
#define UNIT_V_EXHALT (UNIT_V_UF + 0)
#define UNIT_EXHALT (1u << UNIT_V_EXHALT)
#define ATOW(arr, i) \
((uint32)(arr)[i + 3] + ((uint32)(arr)[i + 2] << 8) + \
((uint32)(arr)[i + 1] << 16) + ((uint32)(arr)[i] << 24))
#define ATOH(arr, i) ((uint32)(arr)[i + 1] + ((uint32)(arr)[i] << 8))
#define CSRBIT(bit, sc) \
{ \
if (sc) { \
csr_data |= (bit); \
} else { \
csr_data &= ~(bit); \
} \
}
#define UNIT_V_EXBRK (UNIT_V_UF + 0)
#define UNIT_V_OPBRK (UNIT_V_UF + 1)
#define UNIT_EXBRK (1u << UNIT_V_EXBRK)
#define UNIT_OPBRK (1u << UNIT_V_OPBRK)
#define EX_V_FLAG 1 << 21
#define PHYS_MEM_BASE 0x2000000
#define MSIZ_512K 0x80000
#define MSIZ_1M 0x100000
#define MSIZ_2M 0x200000
#define MSIZ_4M 0x400000
#define MSIZ_8M 0x800000
#define MSIZ_16M 0x1000000
#define MSIZ_32M 0x2000000
#define MSIZ_64M 0x4000000
/* Simulator stop codes */
#define STOP_RSRV 1
#define STOP_IBKPT 2 /* Breakpoint encountered */
@ -115,25 +153,29 @@ noret __libc_longjmp(jmp_buf buf, int val);
#define CACHE_DBG 0x1000
#define DECODE_DBG 0x2000
#define TIMER_SANITY 0
#define TIMER_INTERVAL 1
#define TIMER_BUS 2
/* Global symbols */
extern volatile int32 stop_reason;
extern CIO_STATE cio[CIO_SLOTS];
extern uint32 rom_size;
extern instr *cpu_instr;
extern t_bool cpu_nmi;
extern uint32 *ROM;
extern uint32 *RAM;
extern uint32 R[16];
extern uint32 R[NUM_REGISTERS];
extern REG cpu_reg[];
extern UNIT cpu_unit;
extern uint8 fault;
extern t_bool cpu_km;
extern uint32 R[16];
extern char sim_name[];
extern REG *sim_PC;
extern int32 sim_emax;
extern uint16 csr_data;
extern int32 tmxr_poll;
extern DEBTAB sys_deb_tab[];

View file

@ -1,6 +1,6 @@
/* 3b2_dmac.c: AT&T 3B2 Model 400 AM9517A DMA Controller Implementation
/* 3b2_dmac.c: AT&T 3B2 DMA Controller Implementation
Copyright (c) 2017, Seth J. Morabito
Copyright (c) 2021, Seth J. Morabito
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@ -54,7 +54,9 @@ DEVICE dmac_dev = {
};
dmac_dma_handler device_dma_handlers[] = {
#if defined(REV2)
{DMA_ID_CHAN, IDBASE+ID_DATA_REG, &id_drq, dmac_generic_dma, id_after_dma},
#endif
{DMA_IF_CHAN, IFBASE+IF_DATA_REG, &if_state.drq, dmac_generic_dma, if_after_dma},
{DMA_IUA_CHAN, IUBASE+IUA_DATA_REG, &iu_console.drq, iu_dma_console, NULL},
{DMA_IUB_CHAN, IUBASE+IUB_DATA_REG, &iu_contty.drq, iu_dma_contty, NULL},
@ -62,10 +64,16 @@ dmac_dma_handler device_dma_handlers[] = {
};
uint32 dma_address(uint8 channel, uint32 offset, t_bool r) {
uint32 addr;
addr = (PHYS_MEM_BASE + dma_state.channels[channel].addr + offset);
/* The top bit of the page address is a R/W bit, so we mask it here */
addr |= (uint32) (((uint32)dma_state.channels[channel].page & 0x7f) << 16);
uint32 addr, page;
addr = (PHYS_MEM_BASE + (uint32)(dma_state.channels[channel].addr) + offset);
#if defined (REV3)
page = (uint32)dma_state.channels[channel].page;
#else
/* In Rev 2, the top bit of the page address is a R/W bit, so
we mask it here */
page = (uint32)dma_state.channels[channel].page & 0x7f;
#endif
addr |= page << 16;
return addr;
}
@ -91,7 +99,7 @@ uint32 dmac_read(uint32 pa, size_t size)
{
uint8 reg, base, data;
base =(uint8) (pa >> 12);
base = (uint8) (pa >> 12);
reg = pa & 0xff;
switch (base) {
@ -202,6 +210,9 @@ void dmac_program(uint8 reg, uint8 val)
case 7:
chan_num = 3;
break;
default:
chan_num = 0;
break;
}
channel = &dma_state.channels[chan_num];
@ -315,32 +326,35 @@ void dmac_page_update(uint8 base, uint8 reg, uint8 val)
return;
}
/* The actual register is a 32-bit, byte-addressed register, so
that address 4x000 is the highest byte, 4x003 is the lowest
byte. */
#if defined(REV2)
/* In Rev2 systems, the actual register is a 32-bit,
byte-addressed register, so that address 4x000 is the highest
byte, 4x003 is the lowest byte. */
shift = -(reg - 3) * 8;
#endif
switch (base) {
#if defined (REV2)
case DMA_ID:
sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 0 = %x\n", val);
dma_state.channels[DMA_ID_CHAN].page &= ~(0xff << shift);
dma_state.channels[DMA_ID_CHAN].page |= (val << shift);
dma_state.channels[DMA_ID_CHAN].page |= ((uint16)val << shift);
break;
#endif
case DMA_IF:
sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 1 = %x\n", val);
dma_state.channels[DMA_IF_CHAN].page &= ~(0xff << shift);
dma_state.channels[DMA_IF_CHAN].page |= (val << shift);
dma_state.channels[DMA_IF_CHAN].page |= ((uint16)val << shift);
break;
case DMA_IUA:
sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 2 = %x\n", val);
dma_state.channels[DMA_IUA_CHAN].page &= ~(0xff << shift);
dma_state.channels[DMA_IUA_CHAN].page |= (val << shift);
dma_state.channels[DMA_IUA_CHAN].page |= ((uint16)val << shift);
break;
case DMA_IUB:
sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 3 = %x\n", val);
dma_state.channels[DMA_IUB_CHAN].page &= ~(0xff << shift);
dma_state.channels[DMA_IUB_CHAN].page |= (val << shift);
dma_state.channels[DMA_IUB_CHAN].page |= ((uint16)val << shift);
break;
}
}
@ -353,14 +367,15 @@ void dmac_write(uint32 pa, uint32 val, size_t size)
reg = pa & 0xff;
switch (base) {
case DMA_C: /* 0x48xxx */
case DMA_C:
dmac_program(reg, (uint8) val);
break;
case DMA_ID: /* 0x45xxx */
case DMA_IUA: /* 0x46xxx */
case DMA_IUB: /* 0x47xxx */
case DMA_IF: /* 0x4Exxx */
#if defined (REV2)
case DMA_ID:
#endif
case DMA_IUA:
case DMA_IUB:
case DMA_IF:
dmac_page_update(base, reg, (uint8) val);
break;
}
@ -386,10 +401,13 @@ void dmac_generic_dma(uint8 channel, uint32 service_address)
break;
case DMA_MODE_WRITE:
sim_debug(EXECUTE_MSG, &dmac_dev,
"[%08x] [dmac_generic_dma channel=%d] write: %d bytes from %08x\n",
"[%08x] [dmac_generic_dma channel=%d] write: %d bytes to %08x from %08x (page=%04x addr=%08x)\n",
R[NUM_PC], channel,
chan->wcount + 1,
dma_address(channel, 0, TRUE));
dma_address(channel, 0, TRUE),
service_address,
dma_state.channels[channel].page,
dma_state.channels[channel].addr);
for (; i >= 0; i--) {
chan->wcount_c--;
addr = dma_address(channel, chan->ptr, TRUE);
@ -401,10 +419,11 @@ void dmac_generic_dma(uint8 channel, uint32 service_address)
break;
case DMA_MODE_READ:
sim_debug(EXECUTE_MSG, &dmac_dev,
"[%08x] [dmac_generic_dma channel=%d] read: %d bytes to %08x\n",
"[%08x] [dmac_generic_dma channel=%d] read: %d bytes from %08x to %08x\n",
R[NUM_PC], channel,
chan->wcount + 1,
dma_address(channel, 0, TRUE));
dma_address(channel, 0, TRUE),
service_address);
for (; i >= 0; i--) {
chan->wcount_c = i;
addr = dma_address(channel, chan->ptr++, TRUE);
@ -425,7 +444,7 @@ void dmac_generic_dma(uint8 channel, uint32 service_address)
*/
void dmac_service_drqs()
{
dmac_dma_handler *h;
volatile dmac_dma_handler *h;
for (h = &device_dma_handlers[0]; h->drq != NULL; h++) {
/* Only trigger if the channel has a DRQ set and its channel's

View file

@ -1,6 +1,6 @@
/* 3b2_dmac.h: AT&T 3B2 Model 400 AM9517A DMA Controller Header
/* 3b2_dmac.h: AT&T 3B2 DMA Controller Header
Copyright (c) 2017, Seth J. Morabito
Copyright (c) 2021, Seth J. Morabito
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@ -40,7 +40,7 @@
#define DMA_IF_READ (IFBASE + IF_DATA_REG)
typedef struct {
uint8 page;
uint16 page;
uint16 addr; /* Original addr */
uint16 wcount; /* Original wcount */
uint16 addr_c; /* Current addr */

View file

@ -32,7 +32,6 @@
#define __3B2_ID_H__
#include "sim_defs.h"
#include "sim_disk.h"
#define ID0 0
#define ID1 1

View file

@ -63,6 +63,7 @@ UNIT if_unit = {
};
REG if_reg[] = {
{ HRDATAD (IRQ, if_irq, 1, "IRQ Set") },
{ NULL }
};
@ -86,13 +87,17 @@ t_bool if_irq = FALSE;
static SIM_INLINE void if_set_irq()
{
if_irq = TRUE;
#if defined(REV2)
csr_data |= CSRDISK;
#endif
}
static SIM_INLINE void if_clear_irq()
{
if_irq = FALSE;
#if defined(REV2)
csr_data &= ~CSRDISK;
#endif
}
static SIM_INLINE void if_activate(uint32 delay)
@ -289,20 +294,24 @@ void if_handle_command()
case IF_WRITE_SEC:
case IF_WRITE_SEC_M:
if_state.cmd_type = 2;
#if defined(REV2)
if (((if_state.cmd & IF_U_FLAG) >> 1) != if_state.side) {
head_switch_delay = IF_HSW_DELAY;
if_state.side = (if_state.cmd & IF_U_FLAG) >> 1;
}
#endif
break;
case IF_READ_ADDR:
case IF_READ_TRACK:
case IF_WRITE_TRACK:
if_state.cmd_type = 3;
#if defined(REV2)
if (((if_state.cmd & IF_U_FLAG) >> 1) != if_state.side) {
head_switch_delay = IF_HSW_DELAY;
if_state.side = (if_state.cmd & IF_U_FLAG) >> 1;
}
#endif
break;
case IF_FORCE_INT:
@ -517,7 +526,9 @@ void if_handle_command()
if ((if_state.cmd & 0xf) == 0) {
if_cancel_pending_irq();
#if defined(REV2)
if_clear_irq(); /* TODO: Confirm this is right */
#endif
} else if ((if_state.cmd & 0x8) == 0x8) {
if_state.status |= IF_DRQ;
if_set_irq();
@ -583,6 +594,18 @@ void if_write(uint32 pa, uint32 val, size_t size)
}
}
#if defined(REV3)
uint32 if_csr_read(uint32 pa, size_t size)
{
return (uint32)(if_state.csr);
}
void if_csr_write(uint32 pa, uint32 val, size_t size)
{
if_state.csr = val & 0xff;
}
#endif
CONST char *if_description(DEVICE *dptr)
{
return "Integrated Floppy Disk";

View file

@ -44,6 +44,9 @@ typedef struct {
uint8 read_addr_ptr;
int8 step_dir;
t_bool drq;
#if defined(REV3)
uint8 csr;
#endif
} IF_STATE;
/* Status Bits */
@ -114,6 +117,10 @@ t_stat if_attach(UNIT *uptr, CONST char *cptr);
t_stat if_detach(UNIT *uptr);
uint32 if_read(uint32 pa, size_t size);
void if_write(uint32 pa, uint32 val, size_t size);
#if defined(REV3)
uint32 if_csr_read(uint32 pa, size_t size);
void if_csr_write(uint32 pa, uint32 val, size_t size);
#endif
void if_handle_command();
void if_after_dma();
CONST char *if_description(DEVICE *dptr);

View file

@ -33,15 +33,34 @@
CIO_STATE cio[CIO_SLOTS] = {{0}};
struct iolink iotable[] = {
#if defined(REV3)
iolink iotable[] = {
{ MMUBASE, MMUBASE+MMUSIZE, &mmu_read, &mmu_write },
{ IFBASE, IFBASE+IFSIZE, &if_read, &if_write },
{ IFCSRBASE, IFCSRBASE+IFCSRSIZE, &if_csr_read, &if_csr_write },
{ FLTLBASE, FLTLSIZE, &flt_read, &flt_write },
{ FLTHBASE, FLTHSIZE, &flt_read, &flt_write },
{ NVRBASE, NVRBASE+NVRSIZE, &nvram_read, &nvram_write },
{ TIMERBASE, TIMERBASE+TIMERSIZE, &timer_read, &timer_write },
{ CSRBASE, CSRBASE+CSRSIZE, &csr_read, &csr_write },
{ IUBASE, IUBASE+IUSIZE, &iu_read, &iu_write },
{ DMAIUABASE, DMAIUABASE+DMAIUASIZE, &dmac_read, &dmac_write },
{ DMAIUBBASE, DMAIUBBASE+DMAIUBSIZE, &dmac_read, &dmac_write },
{ DMACBASE, DMACBASE+DMACSIZE, &dmac_read, &dmac_write },
{ DMAIFBASE, DMAIFBASE+DMAIFSIZE, &dmac_read, &dmac_write },
{ TODBASE, TODBASE+TODSIZE, &tod_read, &tod_write },
{ 0, 0, NULL, NULL}
};
#else
iolink iotable[] = {
{ MMUBASE, MMUBASE+MMUSIZE, &mmu_read, &mmu_write },
{ IFBASE, IFBASE+IFSIZE, &if_read, &if_write },
{ IDBASE, IDBASE+IDSIZE, &id_read, &id_write },
{ DMAIDBASE, DMAIDBASE+DMAIDSIZE, &dmac_read, &dmac_write },
{ NVRBASE, NVRBASE+NVRSIZE, &nvram_read, &nvram_write },
{ TIMERBASE, TIMERBASE+TIMERSIZE, &timer_read, &timer_write },
{ NVRAMBASE, NVRAMBASE+NVRAMSIZE, &nvram_read, &nvram_write },
{ CSRBASE, CSRBASE+CSRSIZE, &csr_read, &csr_write },
{ IUBASE, IUBASE+IUSIZE, &iu_read, &iu_write },
{ DMAIDBASE, DMAIDBASE+DMAIDSIZE, &dmac_read, &dmac_write },
{ DMAIUABASE, DMAIUABASE+DMAIUASIZE, &dmac_read, &dmac_write },
{ DMAIUBBASE, DMAIUBBASE+DMAIUBSIZE, &dmac_read, &dmac_write },
{ DMACBASE, DMACBASE+DMACSIZE, &dmac_read, &dmac_write },
@ -49,6 +68,7 @@ struct iolink iotable[] = {
{ TODBASE, TODBASE+TODSIZE, &tod_read, &tod_write },
{ 0, 0, NULL, NULL}
};
#endif
void cio_clear(uint8 cid)
{
@ -358,10 +378,70 @@ t_bool cio_rqueue_avail(uint8 cid, uint32 qnum, uint32 esize)
uint32 io_read(uint32 pa, size_t size)
{
struct iolink *p;
iolink *p;
uint8 cid, reg, data;
/* Special devices */
#if defined (REV3)
/*
* NOTE: Not Yet Implemented, but: If 0x4BF00 is accessed and does
* not result in an error, the system assumes there are two MMUs
* installed. I think 0x4b000 is where a second MMU would live in
* IO space if there were multiple MMUs.
*/
if ((pa == MADDR_SLOT_0) ||
(pa == MADDR_SLOT_1) ||
(pa == MADDR_SLOT_2) ||
(pa == MADDR_SLOT_3)) {
switch(MEM_SIZE) {
case MSIZ_4M:
/* Configure with one 4MB boards */
if (pa < MADDR_SLOT_1) {
return MEMID_4M;
}
break;
case MSIZ_8M:
/* Configure with two 4MB boards */
if (pa < MADDR_SLOT_2) {
return MEMID_4M;
}
break;
case MSIZ_16M:
/* Configure with four 4MB boards */
return MEMID_4M;
case MSIZ_32M:
/* Configure with two 16MB boards */
if (pa < MADDR_SLOT_2) {
return MEMID_16M;
}
break;
case MSIZ_64M:
/* Configure with four 16MB boards */
return MEMID_16M;
default:
return 0;
}
return 0;
}
if (pa >= VCACHE_BOTTOM && pa < VCACHE_TOP) {
CSRBIT(CSRTIMO, TRUE);
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
return 0;
}
if (pa >= BUB_BOTTOM && pa < BUB_TOP) {
CSRBIT(CSRTIMO, TRUE);
/* TODO: I don't remember why we do this! */
if ((pa & 0xfff) == 3) {
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
/* TODO: Implement BUB */
return 1;
}
#else
if (pa == MEMSIZE_REG) {
/* The following values map to memory sizes:
@ -383,6 +463,7 @@ uint32 io_read(uint32 pa, size_t size)
return 0;
}
}
#endif
/* CIO board area */
if (pa >= CIO_BOTTOM && pa < CIO_TOP) {
@ -522,7 +603,7 @@ uint32 io_read(uint32 pa, size_t size)
void io_write(uint32 pa, uint32 val, size_t size)
{
struct iolink *p;
iolink *p;
uint8 cid, reg;
/* Feature Card Area */

View file

@ -190,12 +190,12 @@ typedef struct {
uint32 address;
} cio_entry;
struct iolink {
typedef struct {
uint32 low;
uint32 high;
uint32 (*read)(uint32 pa, size_t size);
void (*write)(uint32 pa, uint32 val, size_t size);
};
} iolink;
/* Example pump structure
* ----------------------

320
3B2/3b2_mem.c Normal file
View file

@ -0,0 +1,320 @@
/* 3b2_mem.c: AT&T 3B2 memory access routines
Copyright (c) 2021, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#include "3b2_defs.h"
#include "3b2_mem.h"
t_bool addr_is_rom(uint32 pa)
{
return (pa < rom_size);
}
t_bool addr_is_mem(uint32 pa)
{
return (pa >= PHYS_MEM_BASE &&
pa < (PHYS_MEM_BASE + MEM_SIZE));
}
t_bool addr_is_io(uint32 pa)
{
#if defined(REV3)
return ((pa >= IO_BOTTOM && pa < IO_TOP) ||
(pa >= CIO_BOTTOM && pa < CIO_TOP) ||
(pa >= VCACHE_BOTTOM && pa < VCACHE_TOP) ||
(pa >= BUB_BOTTOM && pa < BUB_TOP));
#else
return ((pa >= IO_BOTTOM && pa < IO_TOP) ||
(pa >= CIO_BOTTOM && pa < CIO_TOP));
#endif
}
/* Read Word (Physical Address) */
uint32 pread_w(uint32 pa)
{
uint32 *m;
uint32 index;
if (pa & 3) {
sim_debug(READ_MSG, &mmu_dev,
"[%08x] Cannot read physical address. ALIGNMENT ISSUE: %08x\n",
R[NUM_PC], pa);
CSRBIT(CSRALGN, TRUE);
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
return io_read(pa, 32);
}
if (addr_is_rom(pa)) {
m = ROM;
index = pa >> 2;
} else if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
} else {
return 0;
}
return m[index];
}
/*
* Write Word (Physical Address)
*/
void pwrite_w(uint32 pa, uint32 val)
{
if (pa & 3) {
sim_debug(WRITE_MSG, &mmu_dev,
"[%08x] Cannot write physical address. ALIGNMENT ISSUE: %08x\n",
R[NUM_PC], pa);
CSRBIT(CSRALGN, TRUE);
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
io_write(pa, val, 32);
return;
}
if (addr_is_mem(pa)) {
RAM[(pa - PHYS_MEM_BASE) >> 2] = val;
return;
}
}
/*
* Read Halfword (Physical Address)
*/
uint16 pread_h(uint32 pa)
{
uint32 *m;
uint32 index;
if (pa & 1) {
sim_debug(READ_MSG, &mmu_dev,
"[%08x] Cannot read physical address. ALIGNMENT ISSUE %08x\n",
R[NUM_PC], pa);
CSRBIT(CSRALGN, TRUE);
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
return (uint16) io_read(pa, 16);
}
if (addr_is_rom(pa)) {
m = ROM;
index = pa >> 2;
} else if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
} else {
return 0;
}
if (pa & 2) {
return m[index] & HALF_MASK;
} else {
return (m[index] >> 16) & HALF_MASK;
}
}
/*
* Write Halfword (Physical Address)
*/
void pwrite_h(uint32 pa, uint16 val)
{
uint32 *m;
uint32 index;
uint32 wval = (uint32)val;
if (pa & 1) {
sim_debug(WRITE_MSG, &mmu_dev,
"[%08x] Cannot write physical address %08x, ALIGNMENT ISSUE\n",
R[NUM_PC], pa);
CSRBIT(CSRALGN, TRUE);
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
io_write(pa, val, 16);
return;
}
if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
} else {
return;
}
if (pa & 2) {
m[index] = (m[index] & ~HALF_MASK) | wval;
} else {
m[index] = (m[index] & HALF_MASK) | (wval << 16);
}
}
/*
* Read Byte (Physical Address)
*/
uint8 pread_b(uint32 pa)
{
uint32 data;
int32 sc = (~(pa & 3) << 3) & 0x1f;
if (addr_is_io(pa)) {
return (uint8)(io_read(pa, 8));
}
if (addr_is_rom(pa)) {
data = ROM[pa >> 2];
} else if (addr_is_mem(pa)) {
data = RAM[(pa - PHYS_MEM_BASE) >> 2];
} else {
return 0;
}
return (data >> sc) & BYTE_MASK;
}
/* Write Byte (Physical Address) */
void pwrite_b(uint32 pa, uint8 val)
{
uint32 *m;
int32 index;
int32 sc = (~(pa & 3) << 3) & 0x1f;
uint32 mask = 0xffu << sc;
if (addr_is_io(pa)) {
io_write(pa, val, 8);
return;
}
if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
m[index] = (m[index] & ~mask) | (uint32) (val << sc);
return;
}
}
/* Read Byte (Virtual Address) */
uint8 read_b(uint32 va, uint8 r_acc)
{
return pread_b(mmu_xlate_addr(va, r_acc));
}
/* Write Byte (Virtual Address) */
void write_b(uint32 va, uint8 val)
{
pwrite_b(mmu_xlate_addr(va, ACC_W), val);
}
/* Read Halfword (Virtual Address) */
uint16 read_h(uint32 va, uint8 r_acc)
{
return pread_h(mmu_xlate_addr(va, r_acc));
}
/* Write Halfword (Virtual Address) */
void write_h(uint32 va, uint16 val)
{
pwrite_h(mmu_xlate_addr(va, ACC_W), val);
}
/* Read Word (Virtual Address) */
uint32 read_w(uint32 va, uint8 r_acc)
{
return pread_w(mmu_xlate_addr(va, r_acc));
}
/* Write Word (Virtual Address) */
void write_w(uint32 va, uint32 val)
{
pwrite_w(mmu_xlate_addr(va, ACC_W), val);
}
t_stat read_operand(uint32 va, uint8 *val)
{
uint32 pa;
t_stat succ;
succ = mmu_decode_va(va, ACC_IF, TRUE, &pa);
if (succ == SCPE_OK) {
*val = pread_b(pa);
} else {
*val = 0;
}
return succ;
}
t_stat examine(uint32 va, uint8 *val)
{
uint32 pa;
t_stat succ;
succ = mmu_decode_va(va, 0, FALSE, &pa);
if (succ == SCPE_OK) {
if (addr_is_rom(pa) || addr_is_mem(pa)) {
*val = pread_b(pa);
return SCPE_OK;
} else {
*val = 0;
return SCPE_NXM;
}
} else {
*val = 0;
return succ;
}
}
t_stat deposit(uint32 va, uint8 val)
{
uint32 pa;
t_stat succ;
succ = mmu_decode_va(va, 0, FALSE, &pa);
if (succ == SCPE_OK) {
if (addr_is_mem(pa)) {
pwrite_b(pa, val);
return SCPE_OK;
} else {
return SCPE_NXM;
}
} else {
return succ;
}
}

62
3B2/3b2_mem.h Normal file
View file

@ -0,0 +1,62 @@
/* 3b2_mem.h: AT&T 3B2 3B2 memory access routines
Copyright (c) 2021, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#ifndef _3B2_MEM_H_
#define _3B2_MEM_H_
#include "sim_defs.h"
uint32 pread_w(uint32 pa);
void pwrite_w(uint32 pa, uint32 val);
uint8 pread_b(uint32 pa);
void pwrite_b(uint32 pa, uint8 val);
uint16 pread_h(uint32 pa);
void pwrite_h(uint32 pa, uint16 val);
uint8 read_b(uint32 va, uint8 r_acc);
uint16 read_h(uint32 va, uint8 r_acc);
uint32 read_w(uint32 va, uint8 r_acc);
void write_b(uint32 va, uint8 val);
void write_h(uint32 va, uint16 val);
void write_w(uint32 va, uint32 val);
t_stat read_operand(uint32 va, uint8 *val);
t_stat examine(uint32 va, uint8 *val);
t_stat deposit(uint32 va, uint8 val);
t_bool addr_is_rom(uint32 pa);
t_bool addr_is_mem(uint32 pa);
t_bool addr_is_io(uint32 pa);
t_stat mmu_decode_va(uint32 va, uint8 r_acc, t_bool fc, uint32 *pa);
void mmu_enable();
void mmu_disable();
#endif /* _3B2_MEM_H_ */

179
3B2/3b2_rev2_csr.c Normal file
View file

@ -0,0 +1,179 @@
/* 3b2_rev2_csr.c: AT&T 3B2 Rev 2 Control and Status Register
Copyright (c) 2017, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#include "3b2_defs.h"
#include "3b2_rev2_csr.h"
uint16 csr_data;
BITFIELD csr_bits[] = {
BIT(IOF),
BIT(DMA),
BIT(DISK),
BIT(UART),
BIT(PIR9),
BIT(PIR8),
BIT(CLK),
BIT(IFLT),
BIT(ITIM),
BIT(FLOP),
BIT(NA),
BIT(LED),
BIT(ALGN),
BIT(RRST),
BIT(PARE),
BIT(TIMO),
ENDBITS
};
UNIT csr_unit = {
UDATA(NULL, UNIT_FIX, CSRSIZE)
};
REG csr_reg[] = {
{ HRDATADF(DATA, csr_data, 16, "CSR Data", csr_bits) },
{ NULL }
};
DEVICE csr_dev = {
"CSR", &csr_unit, csr_reg, NULL,
1, 16, 8, 4, 16, 32,
&csr_ex, &csr_dep, &csr_reset,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
};
t_stat csr_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
{
return SCPE_OK;
}
t_stat csr_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw)
{
return SCPE_OK;
}
t_stat csr_reset(DEVICE *dptr)
{
csr_data = 0;
return SCPE_OK;
}
uint32 csr_read(uint32 pa, size_t size)
{
uint32 reg = pa - CSRBASE;
sim_debug(READ_MSG, &csr_dev,
"[%08x] CSR=%04x\n",
R[NUM_PC], csr_data);
switch (reg) {
case 0x2:
if (size == 8) {
return (csr_data >> 8) & 0xff;
} else {
return csr_data;
}
case 0x3:
return csr_data & 0xff;
default:
return 0;
}
}
void csr_write(uint32 pa, uint32 val, size_t size)
{
uint32 reg = pa - CSRBASE;
switch (reg) {
case 0x03: /* Clear Bus Timeout Error */
csr_data &= ~CSRTIMO;
break;
case 0x07: /* Clear Memory Parity Error */
csr_data &= ~CSRPARE;
break;
case 0x0b: /* Set System Reset Request */
full_reset();
cpu_boot(0, &cpu_dev);
break;
case 0x0f: /* Clear Memory Alignment Fault */
csr_data &= ~CSRALGN;
break;
case 0x13: /* Set Failure LED */
csr_data |= CSRLED;
break;
case 0x17: /* Clear Failure LED */
csr_data &= ~CSRLED;
break;
case 0x1b: /* Set Floppy Motor On */
csr_data |= CSRFLOP;
break;
case 0x1f: /* Clear Floppy Motor On */
csr_data &= ~CSRFLOP;
break;
case 0x23: /* Set Inhibit Timers */
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] SET INHIBIT TIMERS\n", R[NUM_PC]);
csr_data |= CSRITIM;
break;
case 0x27: /* Clear Inhibit Timers */
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] CLEAR INHIBIT TIMERS\n", R[NUM_PC]);
/* A side effect of clearing the timer inhibit bit is to cause
* a simulated "tick" of any active timers. This is a hack to
* make diagnostics pass. This is not 100% accurate, but it
* makes SVR3 and DGMON tests happy.
*/
timer_tick();
csr_data &= ~CSRITIM;
break;
case 0x2b: /* Set Inhibit Faults */
csr_data |= CSRIFLT;
break;
case 0x2f: /* Clear Inhibit Faults */
csr_data &= ~CSRIFLT;
break;
case 0x33: /* Set PIR9 */
csr_data |= CSRPIR9;
break;
case 0x37: /* Clear PIR9 */
csr_data &= ~CSRPIR9;
break;
case 0x3b: /* Set PIR8 */
csr_data |= CSRPIR8;
break;
case 0x3f: /* Clear PIR8 */
csr_data &= ~CSRPIR8;
break;
default:
break;
}
}

44
3B2/3b2_rev2_csr.h Normal file
View file

@ -0,0 +1,44 @@
/* 3b2_rev2_csr.h: AT&T 3B2 Rev 2 Control and Status Register
Copyright (c) 2021, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#ifndef _3B2_REV2_CSR_H_
#define _3B2_REV2_CSR_H_
#include "sim_defs.h"
/* CSR */
t_stat csr_svc(UNIT *uptr);
t_stat csr_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
t_stat csr_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw);
t_stat csr_reset(DEVICE *dptr);
uint32 csr_read(uint32 pa, size_t size);
void csr_write(uint32 pa, uint32 val, size_t size);
#endif /* 3B2_REV2_CSR_H_ */

View file

@ -33,14 +33,20 @@
#include "sim_defs.h"
#define MAXMEMSIZE (1 << 22) /* 4 MB */
#define NUM_REGISTERS 16
#define DEFMEMSIZE MSIZ_4M
#define MAXMEMSIZE MSIZ_4M
#define HWORD_OP_COUNT 11
#define CPU_VERSION 0x1A /* Version encoded in WE32100 */
#define TODBASE 0x41000
#define TODSIZE 0x40
#define TIMERBASE 0x42000
#define TIMERSIZE 0x20
#define NVRAMBASE 0x43000
#define NVRAMSIZE 0x1000
#define NVRBASE 0x43000
#define NVRSIZE 0x1000
#define CSRBASE 0x44000
#define CSRSIZE 0x100
#define IFBASE 0x4d000
@ -75,7 +81,12 @@
#define CSRDMA 0x0002 /* DMA Interrupt */
#define CSRIOF 0x0001 /* I/O Board Fail */
/* Memory */
#define MEMSIZE_REG 0x4C003
#define MEMID_512K 0
#define MEMID_1M 2
#define MEMID_2M 1
#define MEMID_4M 3
/* DMA Controller */
#define DMACBASE 0x48000
@ -108,4 +119,6 @@
#define DMA_C 0x48
#define DMA_IF 0x4E
extern uint16 csr_data;
#endif /* _3B2_REV2_DEFS_H_ */

View file

@ -242,10 +242,10 @@ REG mau_reg[] = {
};
MTAB mau_mod[] = {
{ UNIT_EXHALT, UNIT_EXHALT, "Halt on Exception", "EXHALT",
NULL, NULL, NULL, "Enables Halt on floating point exceptions" },
{ UNIT_EXHALT, 0, "No halt on Exception", "NOEXHALT",
NULL, NULL, NULL, "Disables Halt on floating point exceptions" },
{ UNIT_EXBRK, UNIT_EXBRK, "Break on exceptions", "EXBRK",
NULL, NULL, NULL, "Enables break on floating point exceptions" },
{ UNIT_EXBRK, 0, "No break on exceptions", "NOEXBRK",
NULL, NULL, NULL, "Disables break on floating point exceptions" },
{ 0 }
};
@ -416,7 +416,7 @@ static SIM_INLINE void abort_on_fault()
* in the CPU's PSW).
*/
if ((mau_state.asr & MAU_ASR_IO) && (R[NUM_PSW] & PSW_OE_MASK)) {
if (mau_unit.flags & UNIT_EXHALT) {
if (mau_unit.flags & UNIT_EXBRK) {
stop_reason = STOP_EX;
}
sim_debug(TRACE_DBG, &mau_dev,
@ -427,7 +427,7 @@ static SIM_INLINE void abort_on_fault()
/* Otherwise, check for other exceptions. */
if (mau_exception_present()) {
if (mau_unit.flags & UNIT_EXHALT) {
if (mau_unit.flags & UNIT_EXBRK) {
stop_reason = STOP_EX;
}
sim_debug(TRACE_DBG, &mau_dev,

View file

@ -494,207 +494,6 @@ void mmu_write(uint32 pa, uint32 val, size_t size)
}
}
t_bool addr_is_rom(uint32 pa)
{
return (pa < BOOT_CODE_SIZE);
}
t_bool addr_is_mem(uint32 pa)
{
return (pa >= PHYS_MEM_BASE &&
pa < (PHYS_MEM_BASE + MEM_SIZE));
}
t_bool addr_is_io(uint32 pa)
{
return ((pa >= IO_BOTTOM && pa < IO_TOP) ||
(pa >= CIO_BOTTOM && pa < CIO_TOP));
}
/*
* Raw physical reads and writes.
*
* The WE32100 is a BIG-endian machine, meaning that words are
* arranged in increasing address from most-significant byte to
* least-significant byte.
*/
/*
* Read Word (Physical Address)
*/
uint32 pread_w(uint32 pa)
{
uint32 *m;
uint32 index;
if (pa & 3) {
sim_debug(READ_MSG, &mmu_dev,
"[%08x] Cannot read physical address. ALIGNMENT ISSUE: %08x\n",
R[NUM_PC], pa);
csr_data |= CSRALGN;
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
return io_read(pa, 32);
}
if (addr_is_rom(pa)) {
m = ROM;
index = pa >> 2;
} else if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
} else {
return 0;
}
return m[index];
}
/*
* Write Word (Physical Address)
*/
void pwrite_w(uint32 pa, uint32 val)
{
if (pa & 3) {
sim_debug(WRITE_MSG, &mmu_dev,
"[%08x] Cannot write physical address. ALIGNMENT ISSUE: %08x\n",
R[NUM_PC], pa);
csr_data |= CSRALGN;
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
io_write(pa, val, 32);
return;
}
if (addr_is_mem(pa)) {
RAM[(pa - PHYS_MEM_BASE) >> 2] = val;
return;
}
}
/*
* Read Halfword (Physical Address)
*/
uint16 pread_h(uint32 pa)
{
uint32 *m;
uint32 index;
if (pa & 1) {
sim_debug(READ_MSG, &mmu_dev,
"[%08x] Cannot read physical address. ALIGNMENT ISSUE %08x\n",
R[NUM_PC], pa);
csr_data |= CSRALGN;
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
return (uint16) io_read(pa, 16);
}
if (addr_is_rom(pa)) {
m = ROM;
index = pa >> 2;
} else if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
} else {
return 0;
}
if (pa & 2) {
return m[index] & HALF_MASK;
} else {
return (m[index] >> 16) & HALF_MASK;
}
}
/*
* Write Halfword (Physical Address)
*/
void pwrite_h(uint32 pa, uint16 val)
{
uint32 *m;
uint32 index;
uint32 wval = (uint32)val;
if (pa & 1) {
sim_debug(WRITE_MSG, &mmu_dev,
"[%08x] Cannot write physical address %08x, ALIGNMENT ISSUE\n",
R[NUM_PC], pa);
csr_data |= CSRALGN;
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
if (addr_is_io(pa)) {
io_write(pa, val, 16);
return;
}
if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
} else {
return;
}
if (pa & 2) {
m[index] = (m[index] & ~HALF_MASK) | wval;
} else {
m[index] = (m[index] & HALF_MASK) | (wval << 16);
}
}
/*
* Read Byte (Physical Address)
*/
uint8 pread_b(uint32 pa)
{
uint32 data;
int32 sc = (~(pa & 3) << 3) & 0x1f;
if (addr_is_io(pa)) {
return (uint8)(io_read(pa, 8));
}
if (addr_is_rom(pa)) {
data = ROM[pa >> 2];
} else if (addr_is_mem(pa)) {
data = RAM[(pa - PHYS_MEM_BASE) >> 2];
} else {
return 0;
}
return (data >> sc) & BYTE_MASK;
}
/*
* Write Byte (Physical Address)
*/
void pwrite_b(uint32 pa, uint8 val)
{
uint32 *m;
int32 index;
int32 sc = (~(pa & 3) << 3) & 0x1f;
uint32 mask = 0xffu << sc;
if (addr_is_io(pa)) {
io_write(pa, val, 8);
return;
}
if (addr_is_mem(pa)) {
m = RAM;
index = (pa - PHYS_MEM_BASE) >> 2;
m[index] = (m[index] & ~mask) | (uint32) (val << sc);
return;
}
}
/* Helper functions for MMU decode. */
/*
@ -987,59 +786,6 @@ t_stat mmu_decode_va(uint32 va, uint8 r_acc, t_bool fc, uint32 *pa)
}
}
t_stat examine(uint32 va, uint8 *val) {
uint32 pa;
t_stat succ;
succ = mmu_decode_va(va, 0, FALSE, &pa);
if (succ == SCPE_OK) {
if (addr_is_rom(pa) || addr_is_mem(pa)) {
*val = pread_b(pa);
return SCPE_OK;
} else {
*val = 0;
return SCPE_NXM;
}
} else {
*val = 0;
return succ;
}
}
t_stat deposit(uint32 va, uint8 val) {
uint32 pa;
t_stat succ;
succ = mmu_decode_va(va, 0, FALSE, &pa);
if (succ == SCPE_OK) {
if (addr_is_mem(pa)) {
pwrite_b(pa, val);
return SCPE_OK;
} else {
return SCPE_NXM;
}
} else {
return succ;
}
}
t_stat read_operand(uint32 va, uint8 *val) {
uint32 pa;
t_stat succ;
succ = mmu_decode_va(va, ACC_OF, TRUE, &pa);
if (succ == SCPE_OK) {
*val = pread_b(pa);
} else {
*val = 0;
}
return succ;
}
uint32 mmu_xlate_addr(uint32 va, uint8 r_acc)
{
uint32 pa;
@ -1072,40 +818,6 @@ void mmu_disable()
mmu_state.enabled = FALSE;
}
/*
* MMU Virtual Read and Write Functions
*/
uint8 read_b(uint32 va, uint8 r_acc)
{
return pread_b(mmu_xlate_addr(va, r_acc));
}
uint16 read_h(uint32 va, uint8 r_acc)
{
return pread_h(mmu_xlate_addr(va, r_acc));
}
uint32 read_w(uint32 va, uint8 r_acc)
{
return pread_w(mmu_xlate_addr(va, r_acc));
}
void write_b(uint32 va, uint8 val)
{
pwrite_b(mmu_xlate_addr(va, ACC_W), val);
}
void write_h(uint32 va, uint16 val)
{
pwrite_h(mmu_xlate_addr(va, ACC_W), val);
}
void write_w(uint32 va, uint32 val)
{
pwrite_w(mmu_xlate_addr(va, ACC_W), val);
}
CONST char *mmu_description(DEVICE *dptr)
{
return "WE32101";

View file

@ -214,12 +214,6 @@
#define ACC_IFAD 12 /* Instruction fetch after discontinuity */
#define ACC_IF 13 /* Instruction fetch */
/* Memory access levels */
#define L_KERNEL 0
#define L_EXEC 1
#define L_SUPER 2
#define L_USER 3
/* Pluck out Virtual Address fields */
#define SID(va) (((va) >> 30) & 3)
#define SSL(va) (((va) >> 17) & 0x1fff)
@ -371,12 +365,6 @@ t_stat mmu_decode_vaddr(uint32 vaddr, uint8 r_acc,
#define SHOULD_UPDATE_PD_M_BIT(pd) \
(r_acc == ACC_W && !((pd) & PD_M_MASK))
/* Special functions for reading operands and examining memory
safely */
t_stat read_operand(uint32 va, uint8 *val);
t_stat examine(uint32 va, uint8 *val);
t_stat deposit(uint32 va, uint8 val);
/* Dispatch to the MMU when enabled, or to physical RW when
disabled */
uint8 read_b(uint32 va, uint8 r_acc);

View file

@ -1,4 +1,4 @@
/* 3b2_rev2_defs.h: AT&T 3B2 Rev 2 (Model 400) system implementation
/* 3b2_rev2_sys.c: AT&T 3B2 Rev 2 (Model 400) system definition
Copyright (c) 2017, Seth J. Morabito
@ -29,15 +29,8 @@
*/
#include "3b2_defs.h"
#include "3b2_rev2_sys.h"
char sim_name[] = "AT&T 3B2 Model 400";
REG *sim_PC = &cpu_reg[0];
/* All opcodes are 1 or 2 bytes. Operands may be up to 6 bytes, and
there may be up to 3 operands, for a maximum of 20 bytes */
int32 sim_emax = 20;
char sim_name[] = "AT&T 3B2/400";
DEVICE *sim_devices[] = {
&cpu_dev,
@ -60,20 +53,6 @@ DEVICE *sim_devices[] = {
NULL
};
const char *sim_stop_messages[SCPE_BASE] = {
"Unknown error",
"Reserved Instruction",
"Breakpoint",
"Invalid Opcode",
"IRQ",
"Exception/Trap",
"Exception Stack Too Deep",
"Unimplemented MMU Feature",
"System Powered Off",
"Infinite Loop",
"Simulator Error"
};
void full_reset()
{
cpu_reset(&cpu_dev);
@ -89,109 +68,3 @@ void full_reset()
ctc_reset(&ctc_dev);
ni_reset(&ni_dev);
}
t_stat sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
{
int32 i;
uint32 addr = 0;
int32 cnt = 0;
if ((*cptr != 0) || (flag != 0)) {
return SCPE_ARG;
}
addr = R[NUM_PC];
while ((i = getc (fileref)) != EOF) {
pwrite_b(addr, (uint8)i);
addr++;
cnt++;
}
printf ("%d Bytes loaded.\n", cnt);
return SCPE_OK;
}
t_stat parse_sym(CONST char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw)
{
DEVICE *dptr;
t_stat r;
int32 k, num, vp;
int32 len = 4;
if (sw & (int32) SWMASK ('B')) {
len = 1;
} else if (sw & (int32) SWMASK ('H')) {
len = 2;
} else if (sw & (int32) SWMASK ('W')) {
len = 4;
}
// Parse cptr
num = (int32) get_uint(cptr, 16, WORD_MASK, &r);
if (r != SCPE_OK) {
return r;
}
if (uptr == NULL) {
uptr = &cpu_unit;
}
dptr = find_dev_from_unit(uptr);
if (dptr == NULL) {
return SCPE_IERR;
}
vp = 0;
for (k = len - 1; k >= 0; k--) {
val[vp++] = (num >> (k * 8)) & 0xff;
}
return -(vp - 1);
}
t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{
uint32 len = 4;
int32 k, vp, num;
unsigned int c;
num = 0;
vp = 0;
if (sw & (int32) SWMASK('M')) {
return fprint_sym_m(of, addr, val);
}
if (sw & (int32) SWMASK ('B')) {
len = 1;
} else if (sw & (int32) SWMASK ('H')) {
len = 2;
} else if (sw & (int32) SWMASK ('W')) {
len = 4;
}
if (sw & (int32) SWMASK('C')) {
len = 16;
for (k = (int32) len - 1; k >= 0; k--) {
c = (unsigned int)val[vp++];
if (c >= 0x20 && c < 0x7f) {
fprintf(of, "%c", c);
} else {
fprintf(of, ".");
}
}
return -(vp - 1);
}
for (k = len - 1; k >= 0; k--) {
num = num | (((int32) val[vp++]) << (k * 8));
}
fprint_val(of, (uint32) num, 16, len * 8, PV_RZRO);
return -(vp - 1);
}

265
3B2/3b2_rev3_csr.c Normal file
View file

@ -0,0 +1,265 @@
/* 3b2_rev3_csr.c: AT&T 3B2/600G Control and Status Register
Copyright (c) 2020, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#include "3b2_defs.h"
uint32 csr_data;
BITFIELD csr_bits[] = {
BIT(UTIM),
BIT(PWDN),
BIT(OI15),
BIT(IUINT),
BIT(IUDMA),
BIT(PIR9),
BIT(PIR8),
BIT(IUTIM),
BIT(ISTY),
BIT(IUBUS),
BIT(IFLT),
BIT(ISBER),
BIT(IBUS),
BIT(IBUB),
BIT(FECC),
BIT(THERM),
BIT(FLED),
BIT(PSPWR),
BIT(FLSPD),
BIT(FLSD1),
BIT(FLMOT),
BIT(FLDEN),
BIT(FLSZ),
BIT(SBER),
BIT(MBER),
BIT(UBFL),
BIT(TIMO),
BIT(FLTFR),
BIT(DALGN),
BIT(STTIM),
BIT(ABRT),
BIT(RSTR),
ENDBITS
};
UNIT csr_unit = {
UDATA(NULL, UNIT_FIX, CSRSIZE)
};
REG csr_reg[] = {
{ HRDATADF(DATA, csr_data, 32, "CSR Data", csr_bits) },
{ NULL }
};
DEVICE csr_dev = {
"CSR", &csr_unit, csr_reg, NULL,
1, 16, 8, 4, 16, 32,
&csr_ex, &csr_dep, &csr_reset,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
};
t_stat csr_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
{
return SCPE_OK;
}
t_stat csr_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw)
{
return SCPE_OK;
}
t_stat csr_reset(DEVICE *dptr)
{
/* Accordig to the technical reference manual, the CSR is NOT
cleared on reset */
return SCPE_OK;
}
uint32 csr_read(uint32 pa, size_t size)
{
uint32 reg = (pa - CSRBASE) & 0xff;
switch (reg & 0xf0) {
case 0x00:
return csr_data & 0xff;
case 0x20:
return (csr_data >> 8) & 0xff;
case 0x40:
return (csr_data >> 16) & 0xff;
case 0x60:
return (csr_data >> 24) & 0xff;
default:
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] CSR READ. Warning, unexpected register = %02x)\n",
R[NUM_PC], reg);
return 0;
}
}
void csr_write(uint32 pa, uint32 val, size_t size)
{
uint32 reg = pa - CSRBASE;
switch (reg) {
case 0x00:
CSRBIT(CSRCLK, val);
break;
case 0x04:
CSRBIT(CSRPWRDN, val);
break;
case 0x08:
CSRBIT(CSROPINT15, val);
break;
case 0x0c:
CSRBIT(CSRUART, val);
break;
case 0x10:
CSRBIT(CSRDMA, val);
break;
case 0x14:
CSRBIT(CSRPIR9, val);
break;
case 0x18:
CSRBIT(CSRPIR8, val);
break;
case 0x1c:
CSRBIT(CSRITIM, val);
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] CSR WRITE. Inhibit Interval Timer = %d\n",
R[NUM_PC], val);
if (csr_data & CSRITIM) {
timer_disable(TIMER_INTERVAL);
} else {
timer_enable(TIMER_INTERVAL);
}
break;
case 0x20:
CSRBIT(CSRISTIM, val);
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] CSR WRITE. Inhibit Sanity Timer = %d\n",
R[NUM_PC], val);
if (csr_data & CSRISTIM) {
timer_disable(TIMER_SANITY);
} else {
timer_enable(TIMER_SANITY);
}
break;
case 0x24:
CSRBIT(CSRITIMO, val);
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] CSR WRITE. Inhibit Bus Timer = %d\n",
R[NUM_PC], val);
if (csr_data & CSRITIMO) {
timer_disable(TIMER_BUS);
} else {
timer_enable(TIMER_BUS);
}
break;
case 0x28:
CSRBIT(CSRICPUFLT, val);
break;
case 0x2c:
CSRBIT(CSRISBERR, val);
break;
case 0x30:
CSRBIT(CSRIIOBUS, val);
break;
case 0x34:
CSRBIT(CSRIBUB, val);
break;
case 0x38:
CSRBIT(CSRFECC, val);
break;
case 0x3c:
CSRBIT(CSRTHERM, val);
cpu_nmi = val ? TRUE : FALSE; /* Immediate NMI */
break;
case 0x40:
CSRBIT(CSRLED, val);
break;
case 0x44:
CSRBIT(CSRPWRSPDN, val);
break;
case 0x48:
CSRBIT(CSRFLPFST, val);
break;
case 0x4c: /* Floppy Side 1: Set when Cleared */
if_state.side = (val & 1) ? 0 : 1;
CSRBIT(CSRFLPS1, val & 1);
break;
case 0x50:
CSRBIT(CSRFLPMO, val);
break;
case 0x54:
CSRBIT(CSRFLPDEN, val);
break;
case 0x58:
CSRBIT(CSRFLPSZ, val);
break;
case 0x5c:
CSRBIT(CSRSBERR, val);
break;
case 0x60:
CSRBIT(CSRMBERR, val);
break;
case 0x64:
CSRBIT(CSRUBUBF, val);
break;
case 0x68:
CSRBIT(CSRTIMO, val);
break;
case 0x6c:
CSRBIT(CSRFRF, val);
break;
case 0x70:
CSRBIT(CSRALGN, val);
break;
case 0x74:
CSRBIT(CSRSTIMO, val);
cpu_nmi = val ? TRUE : FALSE; /* Immediate NMI */
break;
case 0x78:
CSRBIT(CSRABRT, val);
cpu_nmi = val ? TRUE : FALSE; /* Immediate NMI */
break;
case 0x7c:
/* System reset request */
cpu_boot(0, &cpu_dev);
break;
default:
/* Do nothing */
break;
}
}

43
3B2/3b2_rev3_csr.h Normal file
View file

@ -0,0 +1,43 @@
/* 3b2_rev3_csr.h: AT&T 3B2/600G Control and Status Register
Copyright (c) 2020, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#ifndef _3B2_400_CSR_H_
#define _3B2_400_CSR_H_
#include "sim_defs.h"
t_stat csr_svc(UNIT *uptr);
t_stat csr_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
t_stat csr_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw);
t_stat csr_reset(DEVICE *dptr);
uint32 csr_read(uint32 pa, size_t size);
void csr_write(uint32 pa, uint32 val, size_t size);
#endif

138
3B2/3b2_rev3_defs.h Normal file
View file

@ -0,0 +1,138 @@
/* 3b2_rev3_defs.h: AT&T 3B2 Rev 3 (Model 600G) Simulator Definitions
Copyright (c) 2021, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#ifndef _3B2_REV3_DEFS_H_
#define _3B2_REV3_DEFS_H_
#include "sim_defs.h"
#define NUM_REGISTERS 32
#define DEFMEMSIZE MSIZ_4M
#define MAXMEMSIZE MSIZ_64M
#define HWORD_OP_COUNT 12
#define CPU_VERSION 0x1F /* Version encoded in WE32200 */
/* Memory */
#define MEMID_4M 6
#define MEMID_16M 7
#define MADDR_SLOT_0 0x4d000
#define MADDR_SLOT_1 0x4d004
#define MADDR_SLOT_2 0x4d008
#define MADDR_SLOT_3 0x4d00c
#define IFCSRBASE 0x40000
#define IFCSRSIZE 0x100
#define TIMERBASE 0x41000
#define TIMERSIZE 0x20
#define NVRBASE 0x42000
#define NVRSIZE 0x2000
#define CSRBASE 0x44000
#define CSRSIZE 0x100
#define DMAIFBASE 0x45000
#define DMAIFSIZE 0x5
#define DMAIUABASE 0x46000
#define DMAIUASIZE 0x5
#define DMAIUBBASE 0x47000
#define DMAIUBSIZE 0x5
#define DMACBASE 0x48000
#define DMACSIZE 0x11
#define IFBASE 0x4a000
#define IFSIZE 0x10
#define TODBASE 0x4e000
#define TODSIZE 0x40
#define MMUBASE 0x4f000
#define MMUSIZE 0x1000
#define FLTLBASE 0x4c000
#define FLTLSIZE 0x10
#define FLTHBASE 0x4d000
#define FLTHSIZE 0x10
#define VCACHE_BOTTOM 0x1c00000
#define VCACHE_TOP 0x2000000
#define BUB_BOTTOM 0x6000000
#define BUB_TOP 0x1a000000
#define IF_STATUS_REG 0
#define IF_CMD_REG 0
#define IF_TRACK_REG 1
#define IF_SECTOR_REG 2
#define IF_DATA_REG 3
#define DMA_IF_CHAN 1
#define DMA_IUA_CHAN 2
#define DMA_IUB_CHAN 3
#define DMA_IF 0x45
#define DMA_IUA 0x46
#define DMA_IUB 0x47
#define DMA_C 0x48
/* CSR Flags */
#define CSRCLK 1u /* UNIX Interval Timer Timeout */
#define CSRPWRDN (1u << 1) /* Power Down Request */
#define CSROPINT15 (1u << 2) /* Oper. Interrupt Level 15 */
#define CSRUART (1u << 3) /* DUART Interrupt */
#define CSRDMA (1u << 4) /* DUART DMA Complete Interrupt */
#define CSRPIR9 (1u << 5) /* Programmed Interrupt 9 */
#define CSRPIR8 (1u << 6) /* Programmed Interrupt 8 */
#define CSRITIM (1u << 7) /* Inhibit UNIX Interval Timer */
#define CSRISTIM (1u << 8) /* Inhibit System Sanity Timer */
#define CSRITIMO (1u << 9) /* Inhibit Bus Timer */
#define CSRICPUFLT (1u << 10) /* Inhibit Faults to CPU */
#define CSRISBERR (1u << 11) /* Inhibit Single Bit Error Rpt */
#define CSRIIOBUS (1u << 12) /* Inhibit Integral 3B2 I/O Bus */
#define CSRIBUB (1u << 13) /* Inhibit 4 BUB Slots */
#define CSRFECC (1u << 14) /* Force ECC Syndrome */
#define CSRTHERM (1u << 15) /* Thermal Shutdown Request */
#define CSRLED (1u << 16) /* Failure LED */
#define CSRPWRSPDN (1u << 17) /* Power Down -- Power Supply */
#define CSRFLPFST (1u << 18) /* Floppy Speed Fast */
#define CSRFLPS1 (1u << 19) /* Floppy Side 1 */
#define CSRFLPMO (1u << 20) /* Floppy Motor On */
#define CSRFLPDEN (1u << 21) /* Floppy Density */
#define CSRFLPSZ (1u << 22) /* Floppy Size */
#define CSRSBERR (1u << 23) /* Single Bit Error */
#define CSRMBERR (1u << 24) /* Multiple Bit Error */
#define CSRUBUBF (1u << 25) /* Ubus/BUB Received Fail */
#define CSRTIMO (1u << 26) /* Bus Timer Timeout */
#define CSRFRF (1u << 27) /* Fault Registers Frozen */
#define CSRALGN (1u << 28) /* Data Alignment Error */
#define CSRSTIMO (1u << 29) /* Sanity Timer Timeout */
#define CSRABRT (1u << 30) /* Abort Switch Activated */
#define CSRRRST (1u << 31) /* System Reset Request */
extern DEVICE flt_dev;
extern DEVICE ha_dev;
extern uint32 csr_data;
#endif

31
3B2/3b2_rev3_mau.c Normal file
View file

@ -0,0 +1,31 @@
/* 3b2_rev3_mau.c: WE32206 Math Accelration Unit Implementation
Copyright (c) 2021, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
/* Stub file. Not Yet Implemented. */

36
3B2/3b2_rev3_mau.h Normal file
View file

@ -0,0 +1,36 @@
/* 3b2_rev3_mau.h: WE32206 Math Accelration Unit Header
Copyright (c) 2021, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#ifndef _3B2_REV3_MAU_H_
#define _3B2_REV3_MAU_H_
/* Stub file. Not Yet Implemented. */
#endif

1207
3B2/3b2_rev3_mmu.c Normal file

File diff suppressed because it is too large Load diff

356
3B2/3b2_rev3_mmu.h Normal file
View file

@ -0,0 +1,356 @@
/* 3b2_rev3_mmu.h: AT&T 3B2/600G MMU (WE32201) Header
Copyright (c) 2020, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#ifndef _3B2_1000_MMU_H_
#define _3B2_1000_MMU_H_
#include "sim_defs.h"
#define MMU_SRS 4 /* Section RAM array size (words) */
#define MMU_SDCS 8 /* SD Cache H/L array size */
#define MMU_PDCS 64 /* PD Cache H/L array size */
#define MMU_IDNCS 16 /* ID Number Cache array size */
/* Register address offsets */
#define MMU_SDCL 0 /* SDC - Low Bits */
#define MMU_SDCH 1 /* SDC - High Bits */
#define MMU_PDCL 2 /* PDC - Low Bits */
#define MMU_PDCH 3 /* PDC - High Bits */
#define MMU_FDCR 4 /* Flush Data Cache Register */
#define MMU_SRAMA 6 /* Section RAM A */
#define MMU_SRAMB 7 /* Section RAM B */
#define MMU_FC 8 /* Fault Code */
#define MMU_FA 9 /* Fault Address */
#define MMU_CONF 10 /* Configuration */
#define MMU_VAR 11 /* Virtual Address Register */
#define MMU_IDC 12 /* ID Number Cache */
#define MMU_IDNR 13 /* ID Number Register */
#define MMU_FIDNR 14 /* Flush ID Number Register */
#define MMU_VR 15 /* Version Register */
#define MMU_CONF_M (mmu_state.conf & 0x1)
#define MMU_CONF_R ((mmu_state.conf & 0x2) >> 1)
#define MMU_CONF_C ((mmu_state.conf & 0x4) >> 1)
#define MMU_CONF_PS ((mmu_state.conf & 0x18) >> 3)
#define MMU_CONF_MCE ((mmu_state.conf & 0x20) >> 5)
#define MMU_CONF_DCE ((mmu_state.conf & 0x40) >> 6)
/* Shift and mask the flag bits for the current CPU mode */
#define MMU_PERM(f) ((f >> ((3 - (CPU_CM)) * 2)) & 3)
/* Codes set in the MMU Fault register */
#define MMU_F_MISS_MEM 1
#define MMU_F_RM_UPD 2
#define MMU_F_SDTLEN 3
#define MMU_F_PW 4
#define MMU_F_PDTLEN 5
#define MMU_F_INV_SD 6
#define MMU_F_SEG_NOT_PRES 7
#define MMU_F_PDT_NOT_PRES 9
#define MMU_F_PAGE_NOT_PRES 10
#define MMU_F_INDIRECT 11
#define MMU_F_ACC 13
#define MMU_F_SEG_OFFSET 14
/* Access Request types */
#define ACC_MT 0 /* Move Translated */
#define ACC_SPW 1 /* Support processor write */
#define ACC_SPF 3 /* Support processor fetch */
#define ACC_IR 7 /* Interlocked read */
#define ACC_AF 8 /* Address fetch */
#define ACC_OF 9 /* Operand fetch */
#define ACC_W 10 /* Write */
#define ACC_IFAD 12 /* Instruction fetch after discontinuity */
#define ACC_IF 13 /* Instruction fetch */
/* Pluck out Virtual Address fields */
#define SID(va) (((va) >> 30) & 3)
#define SSL(va) (((va) >> 17) & 0x1fff)
#define SOT(va) (va & 0x1ffff)
/* PSL will be either:
* - Bits 11-16 (2K pages: MMU_CONF_PS = 0)
* - Bits 12-16 (4K pages: MMU_CONF_PS = 1)
* - Bits 13-16 (8K pages: MMU_CONF_PS = 2)
*/
#define PSL(va) (((va) >> (11 + MMU_CONF_PS)) & (0x3f >> MMU_CONF_PS))
#define PSL_C(va) (((va) & pd_psl_masks[MMU_CONF_PS]))
/* POT will be either:
* - Bits 0-10 (2K pages: MMU_CONF_PS = 0)
* - Bits 0-11 (4K pages: MMU_CONF_PS = 1)
* - Bits 0-12 (8K pages: MMU_CONF_PS = 2)
*/
#define POT(va) ((va) & (0x1fff >> (2 - (MMU_CONF_PS))))
/* Get the maximum length of an SSL from SRAMB */
#define SRAMB_LEN(va) (mmu_state.sec[SID(va)].len)
/* Pluck out Segment Descriptor fields */
#define SD_PRESENT(sd_lo) ((sd_lo) & 1)
#define SD_MODIFIED(sd_lo) (((sd_lo) >> 1) & 1)
#define SD_CONTIG(sd_lo) (((sd_lo) >> 2) & 1)
#define SD_VALID(sd_lo) (((sd_lo) >> 6) & 1)
#define SD_INDIRECT(sd_lo) (((sd_lo) >> 7) & 1)
#define SD_MAX_OFF(sd_lo) (((sd_lo) >> 18) & 0x3f)
#define SD_ACC(sd_lo) (((sd_lo) >> 24) & 0xff)
#define SD_SEG_ADDR(sd_hi) ((sd_hi) & 0xfffffff8u)
#define SD_P_MASK 0x1
#define SD_M_MASK 0x2
#define SD_C_MASK 0x4
#define SD_CACHE_MASK 0x8
#define SD_R_MASK 0x20
#define SD_V_MASK 0x40
#define SD_MAX_OFF_MASK 0xfc0000
#define SD_ACC_MASK 0xff000000u
#define SD_ADDR_MASK 0xfffffff8u
#define SD_VADDR_MASK 0xfff00000u
#define SD_RES_MASK 0xfffc00efu
#define SDC_VADDR_MASK 0xfff
#define SDC_ACC_MASK 0xff000000u
#define SDC_MAX_OFF_MASK 0x001f8000
#define SDC_G_MASK 0x1
#define SDC_C_MASK 0x2
#define SDC_CACHE_MASK 0x4
#define SDC_M_MASK 0x400000
#define SDC_R_MASK 0x800000
#define PD_P_MASK 0x1
#define PD_M_MASK 0x2
#define PD_W_MASK 0x10
#define PD_R_MASK 0x20
#define PD_PADDR_MASK 0xfffff800u
#define PDC_PADDR_MASK 0x1fffff
#define PDC_C_MASK 0x2
#define PDC_W_MASK 0x200000
#define PDC_M_MASK 0x400000
#define PDC_R_MASK 0x800000
#define PDC_G_MASK 0x40000000
#define PDC_U_MASK 0x80000000u
#define MAX_INDIRECTS 3
#define PD_ADDR(pd) (pd & (pd_addr_masks[MMU_CONF_PS]))
#define SD_ADDR(va) (mmu_state.sec[SID(va)].addr + (SSL(va) * 8))
#define SDC_IDX(va) ((uint8)((va) >> 17) & 7)
/* Convert from sd to sd cache entry */
#define SD_TO_SDCH(hi,lo) ((hi) & SD_ADDR_MASK | \
((lo) & SD_C_MASK) >> 1 | \
((lo) & SD_CACHE_MASK) >> 1 | \
(SDC_G_MASK))
#define SD_TO_SDCL(lo,va) (((lo) & SD_ACC_MASK) | \
((lo) & SD_MAX_OFF_MASK) >> 3 | \
((lo) & SD_R_MASK) << 18 | \
((lo) & SD_M_MASK) << 21 | \
((va) & SD_VADDR_MASK) >> 20)
/* Convert from sd cache entry to sd */
#define SDCE_TO_SDH(hi) ((hi) & SD_ADDR_MASK)
#define SDCE_TO_SDL(hi,lo) (((lo) & SDC_ACC_MASK) | \
((lo) & SDC_MAX_OFF_MASK) << 3 | \
((lo) & SDC_R_MASK) >> 18 | \
((lo) & SDC_M_MASK) >> 21 | \
((hi) & SDC_C_MASK) << 1 | \
((hi) & SDC_CACHE_MASK) << 1 | \
SD_V_MASK | SD_P_MASK)
/* Convert from pd cache entry to pd */
#define PDCE_TO_PD(pdcl) (((pdcl & PDC_PADDR_MASK) << 11) | \
((pdcl & PDC_W_MASK) >> 17) | \
((pdcl & PDC_M_MASK) >> 21) | \
((pdcl & PDC_R_MASK) >> 18) | \
PD_P_MASK)
/* Convert from pd to pd cache entry (low word) */
#define PD_TO_PDCL(pd, sd_lo) (((pd & PD_PADDR_MASK) >> 11) | \
((pd & PD_W_MASK) << 17) | \
((pd & PD_M_MASK) << 21) | \
((pd & PD_R_MASK) << 18) | \
(sd_lo & SD_ACC_MASK))
/* Convert from va to pd cache entry (high word / tag) */
#define VA_TO_PDCH(va, sd_lo) ((1 << 30) | \
(mmu_state.cidnr[SID(va)] << 26) | \
((va & 0xfffff800u) >> 6) | \
((sd_lo & SD_CACHE_MASK) >> 1) | \
((sd_lo & SD_C_MASK) >> 1))
/* Maximum offset (in bytes) of a paged segment */
#define MAX_SEG_OFF(w) (((SD_MAX_OFF(w) + 1) * ((MMU_CONF_PS + 1) * 2048)) - 1)
#define IDNC_TAG(val) ((val) & 0xfffffff8)
#define IDNC_U(val) ((val) & 0x1)
/* Fault codes */
#define MMU_FAULT(f) { \
if (fc) { \
mmu_state.fcode = ((((uint32)r_acc)<<7) | \
(((uint32)(CPU_CM))<<5) | \
(f & 0x1f)); \
mmu_state.faddr = va; \
} \
}
typedef struct {
uint32 addr;
uint32 len;
} mmu_sec;
/*
* Segment Descriptor Cache Entry Format
* =====================================
*
* The Segment Descriptor Cache is a directly mapped cache, indexed by
* bits 19, 18, and 17 of the virtual address. Some notes:
*
* - "Acc", "R", "M", "Max Offset", "Address", "$", and "C" are all
* copied from the SD in main memory.
* - "VAddr" holds bits 20-31 of the virtual address
* - "Address" holds a pointer (word-aligned, so the top 30 bits) to
* a page descriptor table in paged mode, or a segment in
* contiguous segment mode.
* - "Max Offset" holds the number of pages minus one in the
* segment. Depending on current page size, various bits of this
* field will be ignored:
* o Bits 20-15 are used for 2K pages
* o Bits 20-16 are used for 4K pages
* o Bits 20-17 are used for 8K pages
*
* Low Word (bits 0-31)
* --------------------
*
* 31 24 23 22 21 20 15 14 12 11 0
* +-------+---+---+---+------------+------+--------------------------+
* | Acc | R | M | - | Max Offset | - | VAddr |
* +-------+---+---+---+------------+------+--------------------------+
*
* High Word (bits 32-63)
* ----------------------
*
* 31 3 2 1 0
* +------------------------------------------------------+---+---+---+
* | Address | $ | C | G |
* +------------------------------------------------------+---+---+---+
*
*
* Page Descriptor Cache Entry Format
* ==================================
*
* The Page Descriptor Cache is a fully associative cache, with a
* tag constructed from the "G" and "IDN" bits, and bits 31-11 of
* the virtual address.
*
* Depending on the current page size and access mode, various bits of
* "VAddr" are ignored.
*
* o Multi-context mode, all ops except single-entry flush:
* VAddr bits 29-11 are used.
* o Multi-context mode, single-entry flush:
* VAddr bits 31-11 are used.
* o Single-context mode, all ops:
* Vaddr bits 31-11 are used.
* o In ALL CASES:
* + 2KB Page Size: Bits 11-12 are used.
* + 4KB Page Size: Bit 11 ignored, 12 used.
* + 8KB Page Size: Bits 11-12 ignored.
*
* Low Word (bits 0-31)
* --------------------
*
* 31 24 23 22 21 20 0
* +-------+---+---+---+----------------------------------------------+
* | Acc | R | M | W | Physical Address |
* +-------+---+---+---+----------------------------------------------+
*
*
* High Word (bits 32-63)
* ----------------------
*
* 31 30 29 26 25 5 4 3 2 1 0
* +---+---+---------+----------------------------+-------+---+---+---+
* | U | G | IDN | (31) VAddr (11)| - | $ | C | - |
* +---+---+---------+----------------------------+-------+---+---+---+
*
*/
typedef struct _mmu_state {
t_bool enabled; /* Global enabled/disabled flag */
t_bool flush_u; /* If true, flush all but last cached entry */
uint32 last_cached; /* The index of the last cached PDC entry */
uint32 sdcl[MMU_SDCS]; /* SDC low bits (0-31) */
uint32 sdch[MMU_SDCS]; /* SDC high bits (32-63) */
uint32 pdcl[MMU_PDCS]; /* PDC low bits (0-31) */
uint32 pdch[MMU_PDCS]; /* PDC high bits (32-63) */
uint32 sra[4]; /* Section RAM A */
uint32 srb[4]; /* Section RAM B */
uint32 cidnr[4]; /* Current ID Number Registers */
uint32 idnc[16]; /* ID Number Cache */
mmu_sec sec[4]; /* Section descriptors decoded from
Section RAM A and B */
uint32 fcode; /* Fault Code Register */
uint32 faddr; /* Fault Address Register */
uint32 conf; /* Configuration Register */
uint32 var; /* Virtual Address Register */
} MMU_STATE;
t_stat mmu_init(DEVICE *dptr);
uint32 mmu_read(uint32 pa, size_t size);
void mmu_write(uint32 pa, uint32 val, size_t size);
CONST char *mmu_description(DEVICE *dptr);
/* Virtual memory translation */
uint32 mmu_xlate_addr(uint32 va, uint8 r_acc);
t_stat mmu_decode_vaddr(uint32 vaddr, uint8 r_acc,
t_bool fc, uint32 *pa);
t_stat mmu_decode_va(uint32 va, uint8 r_acc, t_bool fc, uint32 *pa);
void mmu_enable();
void mmu_disable();
t_stat mmu_show_sdt(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat mmu_show_sdc(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat mmu_show_pdc(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
#endif /* _3B2_1000_MMU_H_ */

70
3B2/3b2_rev3_sys.c Normal file
View file

@ -0,0 +1,70 @@
/* 3b2_rev3_sys.c: AT&T 3B2/600G system definition
Copyright (c) 2020, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#include "3b2_defs.h"
#include "3b2_sys.h"
char sim_name[] = "AT&T 3B2/600G";
DEVICE *sim_devices[] = {
&cpu_dev,
&csr_dev,
&flt_dev,
&mmu_dev,
&mau_dev,
&timer_dev,
&tod_dev,
&nvram_dev,
&tti_dev,
&tto_dev,
&contty_dev,
&iu_timer_dev,
&dmac_dev,
&if_dev,
&ha_dev,
&ports_dev,
&ni_dev,
NULL
};
void full_reset()
{
cpu_reset(&cpu_dev);
mau_reset(&mau_dev);
tti_reset(&tti_dev);
contty_reset(&contty_dev);
iu_timer_reset(&iu_timer_dev);
timer_reset(&timer_dev);
if_reset(&if_dev);
ha_reset(&ha_dev);
csr_reset(&csr_dev);
ports_reset(&ports_dev);
ni_reset(&ni_dev);
}

1464
3B2/3b2_scsi.c Normal file

File diff suppressed because it is too large Load diff

260
3B2/3b2_scsi.h Normal file
View file

@ -0,0 +1,260 @@
/* 3b2_scsi.h: AT&T 3B2 SCSI (CM195W) Host Adapter
Copyright (c) 2020, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#ifndef _3B2_SCSI_H_
#define _3B2_SCSI_H_
#include "sim_defs.h"
/* CIO Opcodes */
#define HA_BOOT 0x0a
#define HA_READ_BLK 0x0b
#define HA_CNTRL 0x20
#define HA_VERS 0x40
#define HA_DL_EEDT 0x42
#define HA_UL_EEDT 0x43
#define HA_EDSD 0x44
#define HA_RESET 0x45
#define HA_TESTRDY 0x00
#define HA_FORMAT 0x04
#define HA_WRITE 0x0a
#define HA_INQUIRY 0x12
#define HA_MODESNS 0x1a
#define HA_RDCPCTY 0x25
#define HA_READ 0x08
#define HA_READEXT 0x28
#define HA_WRTEXT 0x2a
#define HA_VERIFY 0x2f
#define HA_PDLS_OFF 0x28
/* CIO Status */
#define CIO_TIMEOUT 0x65
#define HA_BOOT_ADDR 0x2004000
#define HA_PDINFO_ADDR 0x2004400
#define HA_ID 0x0100
#define HA_IPL 12
#define HA_GOOD 0x00
#define HA_CKCON 0x02
#define HA_DSD_DISK 0x100
#define HA_DSD_TAPE 0x101
#define HA_VERSION 0x01
#define SCQRESIZE 24
#define RAPP_LEN (SCQRESIZE - 8)
#define SCQCESIZE 16
#define CAPP_LEN (SCQCESIZE - 8)
#define FC_TC(x) (((x) >> 3) & 7)
#define FC_LU(x) ((x) & 7)
#define HA_EDT_LEN 1024
#define HA_BLKSZ 512
#define HA_MAX_CMD 12
#define INQUIRY_MAX 36
#define HA_STAT(ha_stat,cio_stat) { \
ha_state.reply.ssb = (ha_stat); \
ha_state.reply.status = (cio_stat); \
}
#define HA_MAX_DTYPE 1
/* CDC Wren IV 327 MB Hard Disk (AT&T KS-23483,L3) */
#define SD327_DTYPE 0
#define SD327_PQUAL 0x00
#define SD327_SCSI 1
#define SD327_BLK 512
#define SD327_LBN 640396
#define SD327_MANU "AT&T"
#define SD327_DESC "KS23483"
#define SD327_REV "0001" /* TODO: Find real rev */
#define SD327_TPZ 9
#define SD327_ASEC 3
#define SD327_ATPZ 0
#define SD327_ATPU 0
#define SD327_SPT 46
#define SD327_CYL 1549
#define SD327_HEADS 9
#define SD327_PREC 1200
#define SD327_RWC 1200
#define SD327_STEP 15
#define SD327_LZ 1549
#define SD327_RPM 3600
/* Wangtek 120MB cartridge tape (AT&T KS-23465) */
#define ST120_DTYPE 1
#define ST120_PQUAL 0x00
#define ST120_SCSI 1
#define ST120_BLK 512
#define ST120_LBN 266004
#define ST120_MANU "WANGTEK"
#define ST120_DESC "KS23465"
#define ST120_REV "CX17"
#define ST120_DENS 5
#define UNIT_V_DTYPE (SCSI_V_UF + 0)
#define UNIT_M_DTYPE 0x1f
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
#define HA_DISK(d) { \
SCSI_DISK, d##_PQUAL, d##_SCSI, FALSE, d##_BLK, \
d##_LBN, d##_MANU, d##_DESC, d##_REV, #d, 0 \
}
#define HA_TAPE(d) { \
SCSI_TAPE, d##_PQUAL, d##_SCSI, TRUE, d##_BLK, \
d##_LBN, d##_MANU, d##_DESC, d##_REV, #d, 0 \
}
#define HA_SIZE(d) d##_LBN
/* Hardware Notes
* ==============
*
* Disk Drive
* ----------
*
* We emulate a 300-Megabyte Hard Disk, AT&T part number KS23483,L3.
*
* This is the same as a CDC/Imprimis Wren IV 94171-327
*
* 512 bytes per block
* 1,520 cylinders
* 2 alternate cylinders (1518 available)
* 46 Sectors per Track
* 3 Alternate Sectors per Track (43 available)
* 9 tracks per cylinder (9 heads)
*
* Formatted Size: 587,466 blocks
*
*
* Tape Drive
* ----------
*
* Wangtek 5099EN (AT&T Part number KS23417,L2)
*
* DC600A cartridge tape
*
* 512 bytes per block
* 9 tracks
* 13,956 blocks per track
*
* Formatted Size: 125,604 blocks
*
*/
#define HA_JOB_QUICK 0
#define HA_JOB_EXPRESS 1
#define HA_JOB_FULL 2
typedef uint8 ha_jobtype;
typedef struct {
uint32 addr;
uint32 len;
} haddr;
/*
* SCSI Command Request
*/
typedef struct {
uint8 op; /* Destructured from the cmd byte array */
uint8 tc;
uint8 lu;
uint32 timeout;
uint8 dlen;
haddr daddr[48]; /* Support up to 48 transfer addresses */
uint32 dma_lst;
uint16 cmd_len;
uint8 cmd[HA_MAX_CMD];
} ha_req;
/*
* SCSI Command Response
*/
typedef struct {
ha_jobtype type; /* Job type */
t_bool pending; /* Pending or completed? */
uint8 status; /* Result Status */
uint8 op; /* Command Opcode */
uint8 subdev; /* XXTTTLLL; T=Target, L=LUN */
uint8 ssb; /* SCSI Status Byte */
uint32 addr; /* Response address */
uint32 len; /* Response length */
} ha_resp;
#define PUMP_NONE 0
#define PUMP_SYSGEN 1
#define PUMP_COMPLETE 2
/*
* General SCSI HA internal state.
*/
typedef struct {
uint8 cid; /* Card Backsplane Slot # */
uint32 pump_state;
uint32 haddr; /* Host address for read/write */
uint32 hlen; /* Length for read or write */
t_bool initialized; /* Card has been initialized */
t_bool frq; /* Fast Request Queue enabled */
uint8 edt[HA_EDT_LEN]; /* Equipped Device Table */
ha_req request; /* Current job request */
ha_resp reply; /* Current job reply */
} HA_STATE;
t_stat ha_show_type(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat ha_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat ha_reset(DEVICE *dptr);
t_stat ha_svc(UNIT *uptr);
t_stat ha_rq_svc(UNIT *uptr);
t_stat ha_attach(UNIT *uptr, CONST char *cptr);
t_stat ha_detach(UNIT *uptr);
void ha_fast_queue_check();
void ha_sysgen(uint8 cid);
void ha_express(uint8 cid);
void ha_full(uint8 cid);
/* Fast Completion */
void ha_fcm_express();
#endif /* _3B2_SCSI_H_ */

View file

@ -39,7 +39,7 @@
*/
#include "3b2_defs.h"
#include "3b2_rev2_stddev.h"
#include "3b2_stddev.h"
DEBTAB sys_deb_tab[] = {
{ "INIT", INIT_MSG, "Init" },
@ -57,171 +57,10 @@ uint32 *NVRAM = NULL;
int32 tmxr_poll = 16667;
/* CSR */
uint16 csr_data;
BITFIELD csr_bits[] = {
BIT(IOF),
BIT(DMA),
BIT(DISK),
BIT(UART),
BIT(PIR9),
BIT(PIR8),
BIT(CLK),
BIT(IFLT),
BIT(ITIM),
BIT(FLOP),
BIT(NA),
BIT(LED),
BIT(ALGN),
BIT(RRST),
BIT(PARE),
BIT(TIMO),
ENDBITS
};
UNIT csr_unit = {
UDATA(NULL, UNIT_FIX, CSRSIZE)
};
REG csr_reg[] = {
{ HRDATADF(DATA, csr_data, 16, "CSR Data", csr_bits) },
{ NULL }
};
DEVICE csr_dev = {
"CSR", &csr_unit, csr_reg, NULL,
1, 16, 8, 4, 16, 32,
&csr_ex, &csr_dep, &csr_reset,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
};
t_stat csr_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
{
return SCPE_OK;
}
t_stat csr_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw)
{
return SCPE_OK;
}
t_stat csr_reset(DEVICE *dptr)
{
csr_data = 0;
return SCPE_OK;
}
uint32 csr_read(uint32 pa, size_t size)
{
uint32 reg = pa - CSRBASE;
sim_debug(READ_MSG, &csr_dev,
"[%08x] CSR=%04x\n",
R[NUM_PC], csr_data);
switch (reg) {
case 0x2:
if (size == 8) {
return (csr_data >> 8) & 0xff;
} else {
return csr_data;
}
case 0x3:
return csr_data & 0xff;
default:
return 0;
}
}
void csr_write(uint32 pa, uint32 val, size_t size)
{
uint32 reg = pa - CSRBASE;
switch (reg) {
case 0x03: /* Clear Bus Timeout Error */
csr_data &= ~CSRTIMO;
break;
case 0x07: /* Clear Memory Parity Error */
csr_data &= ~CSRPARE;
break;
case 0x0b: /* Set System Reset Request */
full_reset();
cpu_boot(0, &cpu_dev);
break;
case 0x0f: /* Clear Memory Alignment Fault */
csr_data &= ~CSRALGN;
break;
case 0x13: /* Set Failure LED */
csr_data |= CSRLED;
break;
case 0x17: /* Clear Failure LED */
csr_data &= ~CSRLED;
break;
case 0x1b: /* Set Floppy Motor On */
csr_data |= CSRFLOP;
break;
case 0x1f: /* Clear Floppy Motor On */
csr_data &= ~CSRFLOP;
break;
case 0x23: /* Set Inhibit Timers */
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] SET INHIBIT TIMERS\n", R[NUM_PC]);
csr_data |= CSRITIM;
break;
case 0x27: /* Clear Inhibit Timers */
sim_debug(WRITE_MSG, &csr_dev,
"[%08x] CLEAR INHIBIT TIMERS\n", R[NUM_PC]);
/* A side effect of clearing the timer inhibit bit is to cause
* a simulated "tick" of any active timers. This is a hack to
* make diagnostics pass. This is not 100% accurate, but it
* makes SVR3 and DGMON tests happy.
*/
if (TIMERS[0].gate && TIMERS[0].enabled) {
TIMERS[0].val = TIMERS[0].divider - 1;
}
if (TIMERS[1].gate && TIMERS[1].enabled) {
TIMERS[1].val = TIMERS[1].divider - 1;
}
if (TIMERS[2].gate && TIMERS[2].enabled) {
TIMERS[2].val = TIMERS[2].divider - 1;
}
csr_data &= ~CSRITIM;
break;
case 0x2b: /* Set Inhibit Faults */
csr_data |= CSRIFLT;
break;
case 0x2f: /* Clear Inhibit Faults */
csr_data &= ~CSRIFLT;
break;
case 0x33: /* Set PIR9 */
csr_data |= CSRPIR9;
break;
case 0x37: /* Clear PIR9 */
csr_data &= ~CSRPIR9;
break;
case 0x3b: /* Set PIR8 */
csr_data |= CSRPIR8;
break;
case 0x3f: /* Clear PIR8 */
csr_data &= ~CSRPIR8;
break;
default:
break;
}
}
/* NVRAM */
UNIT nvram_unit = {
UDATA(NULL, UNIT_FIX+UNIT_BINK, NVRAMSIZE)
UDATA(NULL, UNIT_FIX+UNIT_BINK, NVRSIZE)
};
REG nvram_reg[] = {
@ -246,7 +85,7 @@ t_stat nvram_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
return SCPE_ARG;
}
if (addr >= NVRAMSIZE) {
if (addr >= NVRSIZE) {
return SCPE_NXM;
}
@ -263,7 +102,7 @@ t_stat nvram_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw)
return SCPE_ARG;
}
if (addr >= NVRAMSIZE) {
if (addr >= NVRSIZE) {
return SCPE_NXM;
}
@ -275,8 +114,8 @@ t_stat nvram_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw)
t_stat nvram_reset(DEVICE *dptr)
{
if (NVRAM == NULL) {
NVRAM = (uint32 *)calloc(NVRAMSIZE >> 2, sizeof(uint32));
memset(NVRAM, 0, sizeof(uint32) * NVRAMSIZE >> 2);
NVRAM = (uint32 *)calloc(NVRSIZE >> 2, sizeof(uint32));
memset(NVRAM, 0, sizeof(uint32) * NVRSIZE >> 2);
nvram_unit.filebuf = NVRAM;
}
@ -345,7 +184,7 @@ t_stat nvram_detach(UNIT *uptr)
uint32 nvram_read(uint32 pa, size_t size)
{
uint32 offset = pa - NVRAMBASE;
uint32 offset = pa - NVRBASE;
uint32 data = 0;
uint32 sc = (~(offset & 3) << 3) & 0x1f;
@ -370,7 +209,7 @@ uint32 nvram_read(uint32 pa, size_t size)
void nvram_write(uint32 pa, uint32 val, size_t size)
{
uint32 offset = pa - NVRAMBASE;
uint32 offset = pa - NVRBASE;
uint32 index = offset >> 2;
uint32 sc, mask;
@ -464,6 +303,61 @@ t_stat timer_reset(DEVICE *dptr) {
return SCPE_OK;
}
static void timer_activate(uint8 ctrnum)
{
struct timer_ctr *ctr;
ctr = &TIMERS[ctrnum];
switch (ctrnum) {
case TIMER_SANITY:
#ifdef REV3
if ((csr_data & CSRISTIM) == 0) {
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] SANITY TIMER: Activating after %d steps\n",
R[NUM_PC], ctr->val);
sim_activate_abs(&timer_unit[ctrnum], ctr->val);
ctr->val--;
} else {
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] SANITY TIMER: Currently disabled, not starting\n",
R[NUM_PC]);
}
#endif
break;
case TIMER_INTERVAL:
if ((csr_data & CSRITIM) == 0) {
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] INTERVAL TIMER: Activating after %d ms\n",
R[NUM_PC], ctr->val);
sim_activate_after_abs(&timer_unit[ctrnum], ctr->val);
ctr->val--;
} else {
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] INTERVAL TIMER: Currently disabled, not starting\n",
R[NUM_PC]);
}
break;
case TIMER_BUS:
#ifdef REV3
if ((csr_data & CSRITIMO) == 0) {
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] BUS TIMER: Activating after %d steps\n",
R[NUM_PC], ctr->val);
sim_activate_abs(&timer_unit[ctrnum], (ctr->val - 2));
ctr->val -= 2;
} else {
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] BUS TIMER: Currently disabled, not starting\n",
R[NUM_PC]);
}
#endif
break;
default:
break;
}
}
t_stat timer_set_shutdown(UNIT *uptr, int32 val, CONST char* cptr, void* desc)
{
struct timer_ctr *sanity = (struct timer_ctr *)timer_unit[0].tmr;
@ -478,6 +372,18 @@ t_stat timer_set_shutdown(UNIT *uptr, int32 val, CONST char* cptr, void* desc)
return SCPE_OK;
}
void timer_enable(uint8 ctrnum) {
timer_activate(ctrnum);
}
void timer_disable(uint8 ctrnum)
{
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] Disabling timer %d\n",
R[NUM_PC], ctrnum);
sim_cancel(&timer_unit[ctrnum]);
}
/*
* Sanity Timer
*/
@ -687,6 +593,21 @@ void timer_write(uint32 pa, uint32 val, size_t size)
}
}
void timer_tick()
{
if (TIMERS[0].gate && TIMERS[0].enabled) {
TIMERS[0].val = TIMERS[0].divider - 1;
}
if (TIMERS[1].gate && TIMERS[1].enabled) {
TIMERS[1].val = TIMERS[1].divider - 1;
}
if (TIMERS[2].gate && TIMERS[2].enabled) {
TIMERS[2].val = TIMERS[2].divider - 1;
}
}
/*
* MM58174A Time Of Day Clock
*
@ -955,3 +876,54 @@ t_stat tod_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr
return SCPE_OK;
}
#if defined(REV3)
/*
* Fault Register
*
* The Fault Register is composed of two 32-bit registers at addresses
* 0x4C000 and 0x4D000. These latch state of the last address to cause
* a CPU fault.
*
* Bits 00-25: Physical memory address bits 00-25
*/
uint32 flt_1 = 0;
uint32 flt_2 = 0;
UNIT flt_unit = {
UDATA(NULL, UNIT_FIX+UNIT_BINK, 8)
};
REG flt_reg[] = {
{ NULL }
};
DEVICE flt_dev = {
"FLT", &flt_unit, flt_reg, NULL,
1, 16, 8, 4, 16, 32,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, DEV_DEBUG, 0, sys_deb_tab, NULL, NULL,
NULL, NULL, NULL,
NULL
};
uint32 flt_read(uint32 pa, size_t size)
{
sim_debug(READ_MSG, &flt_dev,
"[%08x] Read from FLT Register at %x\n",
R[NUM_PC], pa);
return 0;
}
void flt_write(uint32 pa, uint32 val, size_t size)
{
sim_debug(WRITE_MSG, &flt_dev,
"[%08x] Write to FLT Register at %x (val=%x)\n",
R[NUM_PC], pa, val);
return;
}
#endif

View file

@ -77,10 +77,13 @@ void nvram_write(uint32 pa, uint32 val, size_t size);
t_stat timer_reset(DEVICE *dptr);
uint32 timer_read(uint32 pa, size_t size);
void timer_write(uint32 pa, uint32 val, size_t size);
void timer_tick();
t_stat timer0_svc(UNIT *uptr);
t_stat timer1_svc(UNIT *uptr);
t_stat timer2_svc(UNIT *uptr);
t_stat timer_set_shutdown(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
void timer_disable(uint8 ctrnum);
void timer_enable(uint8 ctrnum);
/* CSR */
t_stat csr_svc(UNIT *uptr);
@ -120,4 +123,11 @@ t_stat tod_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr
uint32 tod_read(uint32 pa, size_t size);
void tod_write(uint32, uint32 val, size_t size);
#if defined(REV3)
/* Fault Register */
uint32 flt_read(uint32 pa, size_t size);
void flt_write(uint32 pa, uint32 val, size_t size);
#endif
#endif /* _3B2_REV2_SYSDEV_H_ */

157
3B2/3b2_sys.c Normal file
View file

@ -0,0 +1,157 @@
/* 3b2_sys.c: AT&T 3B2 common system definitions
Copyright (c) 2021, Seth J. Morabito
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 THE AUTHORS OR COPYRIGHT HOLDERS
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 the author shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the author.
*/
#include "3b2_defs.h"
REG *sim_PC = &cpu_reg[NUM_PC];
/* All opcodes are 1 or 2 bytes. Operands may be up to 6 bytes, and
there may be up to 3 operands, for a maximum of 20 bytes */
int32 sim_emax = 20;
const char *sim_stop_messages[SCPE_BASE] = {
"Unknown error",
"Reserved Instruction",
"Breakpoint",
"Invalid Opcode",
"IRQ",
"Exception/Trap",
"Exception Stack Too Deep",
"Unimplemented MMU Feature",
"System Powered Off",
"Infinite Loop",
"Simulator Error"
};
t_stat sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
{
int32 i;
uint32 addr = 0;
int32 cnt = 0;
if ((*cptr != 0) || (flag != 0)) {
return SCPE_ARG;
}
addr = R[NUM_PC];
while ((i = getc (fileref)) != EOF) {
pwrite_b(addr, (uint8)i);
addr++;
cnt++;
}
printf ("%d Bytes loaded.\n", cnt);
return SCPE_OK;
}
t_stat parse_sym(CONST char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw)
{
DEVICE *dptr;
t_stat r;
int32 k, num, vp;
int32 len = 4;
if (sw & (int32) SWMASK ('B')) {
len = 1;
} else if (sw & (int32) SWMASK ('H')) {
len = 2;
} else if (sw & (int32) SWMASK ('W')) {
len = 4;
}
// Parse cptr
num = (int32) get_uint(cptr, 16, WORD_MASK, &r);
if (r != SCPE_OK) {
return r;
}
if (uptr == NULL) {
uptr = &cpu_unit;
}
dptr = find_dev_from_unit(uptr);
if (dptr == NULL) {
return SCPE_IERR;
}
vp = 0;
for (k = len - 1; k >= 0; k--) {
val[vp++] = (num >> (k * 8)) & 0xff;
}
return -(vp - 1);
}
t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{
uint32 len = 4;
int32 k, vp, num;
unsigned int c;
num = 0;
vp = 0;
if (sw & (int32) SWMASK('M')) {
return fprint_sym_m(of, addr, val);
}
if (sw & (int32) SWMASK ('B')) {
len = 1;
} else if (sw & (int32) SWMASK ('H')) {
len = 2;
} else if (sw & (int32) SWMASK ('W')) {
len = 4;
}
if (sw & (int32) SWMASK('C')) {
len = 16;
for (k = (int32) len - 1; k >= 0; k--) {
c = (unsigned int)val[vp++];
if (c >= 0x20 && c < 0x7f) {
fprintf(of, "%c", c);
} else {
fprintf(of, ".");
}
}
return -(vp - 1);
}
for (k = len - 1; k >= 0; k--) {
num = num | (((int32) val[vp++]) << (k * 8));
}
fprint_val(of, (uint32) num, 16, len * 8, PV_RZRO);
return -(vp - 1);
}

View file

@ -0,0 +1,627 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="3B2-600"
ProjectGUID="{A7AE7747-DFA0-49F5-9D6C-9094657A8EE3}"
RootNamespace="3B2-600"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\BIN\NT\$(PlatformName)-$(ConfigurationName)"
IntermediateDirectory="..\BIN\NT\Project\simh\$(ProjectName)\$(PlatformName)-$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
Description="Check for required build dependencies &amp; git commit id"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE ROM"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;REV3"
KeepComments="false"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
ShowIncludes="false"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="libcmtd.lib wsock32.lib winmm.lib Iphlpapi.lib pcrestaticd.lib SDL2-StaticD.lib SDL2_ttf-StaticD.lib freetype2412MT_D.lib libpng16.lib zlib.lib dxguid.lib Imm32.lib Version.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="../../windows-build/lib/Debug/"
GenerateDebugInformation="true"
SubSystem="1"
StackReserveSize="10485760"
StackCommitSize="10485760"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description="Running Available Tests"
CommandLine="Post-Build-Event.cmd 3B2-600 &quot;$(TargetDir)$(TargetName).exe&quot;"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\BIN\NT\$(PlatformName)-$(ConfigurationName)"
IntermediateDirectory="..\BIN\NT\Project\simh\$(ProjectName)\$(PlatformName)-$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
Description="Check for required build dependencies &amp; git commit id"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE ROM"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;REV3"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="libcmt.lib wsock32.lib winmm.lib Iphlpapi.lib pcrestatic.lib SDL2-Static.lib SDL2_ttf-Static.lib freetype2412MT.lib libpng16.lib zlib.lib dxguid.lib Imm32.lib Version.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="../../windows-build/lib/Release/"
GenerateDebugInformation="false"
SubSystem="1"
StackReserveSize="10485760"
StackCommitSize="10485760"
OptimizeReferences="2"
EnableCOMDATFolding="2"
LinkTimeCodeGeneration="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description="Running Available Tests"
CommandLine="Post-Build-Event.cmd 3B2-600 &quot;$(TargetDir)$(TargetName).exe&quot;"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
<File
RelativePath="..\3B2\3b2_cpu.c"
>
</File>
<File
RelativePath="..\3B2\3b2_dmac.c"
>
</File>
<File
RelativePath="..\3B2\3b2_if.c"
>
</File>
<File
RelativePath="..\3B2\3b2_io.c"
>
</File>
<File
RelativePath="..\3B2\3b2_iu.c"
>
</File>
<File
RelativePath="..\3B2\3b2_mem.c"
>
</File>
<File
RelativePath="..\3B2\3b2_ni.c"
>
</File>
<File
RelativePath="..\3B2\3b2_ports.c"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_mau.c"
>
</File>
<File
RelativePath="..\3B2\3b2_rev3_csr.c"
>
</File>
<File
RelativePath="..\3B2\3b2_rev3_mmu.c"
>
</File>
<File
RelativePath="..\3B2\3b2_rev3_sys.c"
>
</File>
<File
RelativePath="..\3B2\3b2_scsi.c"
>
</File>
<File
RelativePath="..\3B2\3b2_stddev.c"
>
</File>
<File
RelativePath="..\3B2\3b2_sys.c"
>
</File>
<File
RelativePath="..\..\windows-build\pthreads\pthread.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="HAVE_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;__CLEANUP_C;$(NOINHERIT)"
CompileAs="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
WholeProgramOptimization="false"
PreprocessorDefinitions="HAVE_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;__CLEANUP_C;$(NOINHERIT)"
CompileAs="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\scp.c"
>
</File>
<File
RelativePath="..\sim_console.c"
>
</File>
<File
RelativePath="..\sim_disk.c"
>
</File>
<File
RelativePath="..\sim_ether.c"
>
</File>
<File
RelativePath="..\sim_fio.c"
>
</File>
<File
RelativePath="..\sim_scsi.c"
>
</File>
<File
RelativePath="..\sim_serial.c"
>
</File>
<File
RelativePath="..\sim_sock.c"
>
</File>
<File
RelativePath="..\sim_tape.c"
>
</File>
<File
RelativePath="..\sim_timer.c"
>
</File>
<File
RelativePath="..\sim_tmxr.c"
>
</File>
<File
RelativePath="..\sim_video.c"
>
</File>
<Filter
Name="slirp"
>
<File
RelativePath="..\slirp\arp_table.c"
>
</File>
<File
RelativePath="..\slirp\bootp.c"
>
</File>
<File
RelativePath="..\slirp\bootp.h"
>
</File>
<File
RelativePath="..\slirp\cksum.c"
>
</File>
<File
RelativePath="..\slirp\debug.h"
>
</File>
<File
RelativePath="..\slirp\dnssearch.c"
>
</File>
<File
RelativePath="..\slirp_glue\glib_qemu_stubs.c"
>
</File>
<File
RelativePath="..\slirp\if.c"
>
</File>
<File
RelativePath="..\slirp\if.h"
>
</File>
<File
RelativePath="..\slirp\ip.h"
>
</File>
<File
RelativePath="..\slirp\ip_icmp.c"
>
</File>
<File
RelativePath="..\slirp\ip_icmp.h"
>
</File>
<File
RelativePath="..\slirp\ip_input.c"
>
</File>
<File
RelativePath="..\slirp\ip_output.c"
>
</File>
<File
RelativePath="..\slirp\libslirp.h"
>
</File>
<File
RelativePath="..\slirp\main.h"
>
</File>
<File
RelativePath="..\slirp\mbuf.c"
>
</File>
<File
RelativePath="..\slirp\mbuf.h"
>
</File>
<File
RelativePath="..\slirp\misc.c"
>
</File>
<File
RelativePath="..\slirp\misc.h"
>
</File>
<File
RelativePath="..\slirp\sbuf.c"
>
</File>
<File
RelativePath="..\slirp\sbuf.h"
>
</File>
<File
RelativePath="..\slirp_glue\sim_slirp.c"
>
</File>
<File
RelativePath="..\slirp\slirp.c"
>
</File>
<File
RelativePath="..\slirp\slirp.h"
>
</File>
<File
RelativePath="..\slirp\slirp_config.h"
>
</File>
<File
RelativePath="..\slirp\socket.c"
>
</File>
<File
RelativePath="..\slirp\socket.h"
>
</File>
<File
RelativePath="..\slirp\tcp.h"
>
</File>
<File
RelativePath="..\slirp\tcp_input.c"
>
</File>
<File
RelativePath="..\slirp\tcp_output.c"
>
</File>
<File
RelativePath="..\slirp\tcp_subr.c"
>
</File>
<File
RelativePath="..\slirp\tcp_timer.c"
>
</File>
<File
RelativePath="..\slirp\tcp_timer.h"
>
</File>
<File
RelativePath="..\slirp\tcp_var.h"
>
</File>
<File
RelativePath="..\slirp\tcpip.h"
>
</File>
<File
RelativePath="..\slirp\tftp.c"
>
</File>
<File
RelativePath="..\slirp\tftp.h"
>
</File>
<File
RelativePath="..\slirp\udp.c"
>
</File>
<File
RelativePath="..\slirp\udp.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc"
>
<File
RelativePath="..\3B2\3b2_cpu.h"
>
</File>
<File
RelativePath="..\3B2\3b2_ctc.h"
>
</File>
<File
RelativePath="..\3B2\3b2_defs.h"
>
</File>
<File
RelativePath="..\3B2\3b2_dmac.h"
>
</File>
<File
RelativePath="..\3B2\3b2_id.h"
>
</File>
<File
RelativePath="..\3B2\3b2_if.h"
>
</File>
<File
RelativePath="..\3B2\3b2_io.h"
>
</File>
<File
RelativePath="..\3B2\3b2_iu.h"
>
</File>
<File
RelativePath="..\3B2\3b2_mem.h"
>
</File>
<File
RelativePath="..\3B2\3b2_ni.h"
>
</File>
<File
RelativePath="..\3B2\3b2_ports.h"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_csr.h"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_defs.h"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_mau.h"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_mmu.h"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_sys.h"
>
</File>
<File
RelativePath="..\3B2\3b2_stddev.h"
>
</File>
<File
RelativePath="..\3B2\3b2_sys.h"
>
</File>
<File
RelativePath="..\scp.h"
>
</File>
<File
RelativePath="..\sim_console.h"
>
</File>
<File
RelativePath="..\sim_defs.h"
>
</File>
<File
RelativePath="..\sim_disk.h"
>
</File>
<File
RelativePath="..\sim_ether.h"
>
</File>
<File
RelativePath="..\sim_fio.h"
>
</File>
<File
RelativePath="..\sim_rev.h"
>
</File>
<File
RelativePath="..\sim_serial.h"
>
</File>
<File
RelativePath="..\sim_sock.h"
>
</File>
<File
RelativePath="..\sim_tape.h"
>
</File>
<File
RelativePath="..\sim_timer.h"
>
</File>
<File
RelativePath="..\sim_tmxr.h"
>
</File>
<File
RelativePath="..\sim_video.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -41,7 +41,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG"
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;REV2"
KeepComments="false"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
@ -125,7 +125,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG"
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;REV2"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@ -219,6 +219,10 @@
RelativePath="..\3B2\3b2_iu.c"
>
</File>
<File
RelativePath="..\3B2\3b2_sys.c"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_mau.c"
>
@ -227,6 +231,10 @@
RelativePath="..\3B2\3b2_rev2_mmu.c"
>
</File>
<File
RelativePath="..\3B2\3b2_mem.c"
>
</File>
<File
RelativePath="..\3B2\3b2_ni.c"
>
@ -240,7 +248,11 @@
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_stddev.c"
RelativePath="..\3B2\3b2_rev2_csr.c"
>
</File>
<File
RelativePath="..\3B2\3b2_stddev.c"
>
</File>
<File
@ -515,6 +527,10 @@
RelativePath="..\3B2\3b2_iu.h"
>
</File>
<File
RelativePath="..\3B2\3b2_sys.h"
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_mau.h"
>
@ -523,6 +539,10 @@
RelativePath="..\3B2\3b2_rev2_mmu.h"
>
</File>
<File
RelativePath="..\3B2\3b2_mem.h"
>
</File>
<File
RelativePath="..\3B2\3b2_ni.h"
>
@ -536,7 +556,11 @@
>
</File>
<File
RelativePath="..\3B2\3b2_rev2_stddev.h"
RelativePath="..\3B2\3b2_rev2_csr.h"
>
</File>
<File
RelativePath="..\3B2\3b2_stddev.h"
>
</File>
<File

View file

@ -373,6 +373,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tt2500", "tt2500.vcproj", "
{D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "3B2-600", "3B2-600.vcproj", "{A7AE7747-DFA0-49F5-9D6C-9094657A8EE3}"
ProjectSection(ProjectDependencies) = postProject
{D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -679,6 +684,10 @@ Global
{5CC55A0C-32F3-429F-8661-2E82BF999217}.Debug|Win32.Build.0 = Debug|Win32
{5CC55A0C-32F3-429F-8661-2E82BF999217}.Release|Win32.ActiveCfg = Release|Win32
{5CC55A0C-32F3-429F-8661-2E82BF999217}.Release|Win32.Build.0 = Release|Win32
{A7AE7747-DFA0-49F5-9D6C-9094657A8EE3}.Debug|Win32.ActiveCfg = Debug|Win32
{A7AE7747-DFA0-49F5-9D6C-9094657A8EE3}.Debug|Win32.Build.0 = Debug|Win32
{A7AE7747-DFA0-49F5-9D6C-9094657A8EE3}.Release|Win32.ActiveCfg = Release|Win32
{A7AE7747-DFA0-49F5-9D6C-9094657A8EE3}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -2032,14 +2032,25 @@ KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \
KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT}
ATT3B2D = ${SIMHD}/3B2
ATT3B2M400 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_rev2_sys.c \
${ATT3B2D}/3b2_rev2_stddev.c ${ATT3B2D}/3b2_rev2_mmu.c \
${ATT3B2D}/3b2_rev2_mau.c ${ATT3B2D}/3b2_iu.c \
${ATT3B2D}/3b2_if.c ${ATT3B2D}/3b2_id.c \
ATT3B2M400 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_sys.c \
${ATT3B2D}/3b2_rev2_sys.c ${ATT3B2D}/3b2_rev2_mmu.c \
${ATT3B2D}/3b2_rev2_mau.c ${ATT3B2D}/3b2_rev2_csr.c \
${ATT3B2D}/3b2_stddev.c ${ATT3B2D}/3b2_mem.c \
${ATT3B2D}/3b2_iu.c ${ATT3B2D}/3b2_if.c \
${ATT3B2D}/3b2_id.c ${ATT3B2D}/3b2_dmac.c \
${ATT3B2D}/3b2_io.c ${ATT3B2D}/3b2_ports.c \
${ATT3B2D}/3b2_ctc.c ${ATT3B2D}/3b2_ni.c
ATT3B2M400_OPT = -DUSE_INT64 -DUSE_ADDR64 -DREV2 -I ${ATT3B2D} ${NETWORK_OPT}
ATT3B2M600 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_sys.c \
${ATT3B2D}/3b2_rev3_sys.c ${ATT3B2D}/3b2_rev3_mmu.c \
${ATT3B2D}/3b2_rev2_mau.c ${ATT3B2D}/3b2_rev3_csr.c \
${ATT3B2D}/3b2_stddev.c ${ATT3B2D}/3b2_mem.c \
${ATT3B2D}/3b2_iu.c ${ATT3B2D}/3b2_if.c \
${ATT3B2D}/3b2_dmac.c ${ATT3B2D}/3b2_io.c \
${ATT3B2D}/3b2_ports.c ${ATT3B2D}/3b2_ctc.c \
${ATT3B2D}/3b2_ports.c ${ATT3B2D}/3b2_scsi.c \
${ATT3B2D}/3b2_ni.c
ATT3B2_OPT = -DUSE_INT64 -DUSE_ADDR64 -I ${ATT3B2D} ${NETWORK_OPT}
ATT3B2M600_OPT = -DUSE_INT64 -DUSE_ADDR64 -DREV3 -I ${ATT3B2D} ${NETWORK_OPT}
SIGMAD = ${SIMHD}/sigma
SIGMA = ${SIGMAD}/sigma_cpu.c ${SIGMAD}/sigma_sys.c ${SIGMAD}/sigma_cis.c \
@ -2106,7 +2117,7 @@ ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
all : ${ALL}
EXPERIMENTAL = cdc1700
EXPERIMENTAL = cdc1700 3b2-600
experimental : ${EXPERIMENTAL}
@ -2740,11 +2751,20 @@ endif
${BIN}3b2${EXE} : ${ATT3B2M400} ${SIM} ${BUILD_ROMS}
${MKDIRBIN}
${CC} ${ATT3B2M400} ${SIM} ${ATT3B2_OPT} ${CC_OUTSPEC} ${LDFLAGS}
${CC} ${ATT3B2M400} ${SIM} ${ATT3B2M400_OPT} ${CC_OUTSPEC} ${LDFLAGS}
ifneq (,$(call find_test,${ATT3B2D},3b2))
$@ $(call find_test,${ATT3B2D},3b2) ${TEST_ARG}
endif
3b2-600 : ${BIN}3b2-600${EXE}
${BIN}3b2-600${EXE} : ${ATT3B2M600} ${SIM} ${BUILD_ROMS}
${MKDIRBIN}
${CC} ${ATT3B2M600} ${SCSI} ${SIM} ${ATT3B2M600_OPT} ${CC_OUTSPEC} ${LDFLAGS}
ifneq (,$(call find_test,${ATT3B2D},3b2-600))
$@ $(call find_test,${ATT3B2D},3b2-600) ${TEST_ARG}
endif
i7090 : ${BIN}i7090${EXE}
${BIN}i7090${EXE} : ${I7090} ${SIM}