3b2: WE32106 Math Acceleration Unit (MAU)

This change adds support for the WE32106 Math Acceleration Unit (MAU).
The WE32106 is an IEEE-754 1985 compatible floating point math
acceleration unit that was an optional component on the 3B2/310 and
3B2/400.

The MAU is implemented using software floating point routines.  As
always, there may be bugs, but the MAU currently passes extensive
floating point tests with exactly the same results as a real 3B2/400
equipped with a physical MAU, so I hope these are few.
This commit is contained in:
Seth Morabito 2019-06-29 08:44:14 -07:00
parent 47bac1f665
commit 571c8f96a5
11 changed files with 3964 additions and 40 deletions

View file

@ -178,9 +178,6 @@ static DEBTAB cpu_deb_tab[] = {
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK|UNIT_IDLE, MAXMEMSIZE) };
#define UNIT_V_EXHALT (UNIT_V_UF + 0) /* halt to console */
#define UNIT_EXHALT (1u << UNIT_V_EXHALT)
/*
* TODO: This works fine for now, but the moment we want to emulate
* SCSI (0x0100) or EPORTS (0x0102) we're in trouble!
@ -236,7 +233,11 @@ DEVICE cpu_dev = {
0, /* Debug control flags */
cpu_deb_tab, /* Debug flag names */
&cpu_set_size, /* Memory size change */
NULL /* Logical names */
NULL, /* Logical names */
NULL, /* Help routine */
NULL, /* Attach Help Routine */
NULL, /* Help Context */
&cpu_description /* Device Description */
};
#define HWORD_OP_COUNT 11
@ -259,12 +260,12 @@ mnemonic hword_ops[HWORD_OP_COUNT] = {
mnemonic ops[256] = {
{0x00, 0, OP_NONE, NA, "halt", -1, -1, -1, -1},
{0x01, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x02, 2, OP_COPR, WD, "SPOPRD", -1, -1, -1, -1},
{0x03, 3, OP_COPR, WD, "SPOPD2", -1, -1, -1, -1},
{0x02, 2, OP_COPR, WD, "SPOPRD", 1, -1, -1, -1},
{0x03, 3, OP_COPR, WD, "SPOPD2", 1, -1, -1, 2},
{0x04, 2, OP_DESC, WD, "MOVAW", 0, -1, -1, 1},
{0x05, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x06, 2, OP_COPR, WD, "SPOPRT", -1, -1, -1, -1},
{0x07, 3, OP_COPR, WD, "SPOPT2", -1, -1, -1, -1},
{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},
{0x09, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x0a, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
@ -276,11 +277,11 @@ mnemonic ops[256] = {
{0x10, 1, OP_DESC, WD, "SAVE", 0, -1, -1, -1},
{0x11, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x12, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x13, 2, OP_COPR, WD, "SPOPWD", -1, -1, -1, -1},
{0x13, 2, OP_COPR, WD, "SPOPWD", -1, -1, -1, 1},
{0x14, 1, OP_BYTE, NA, "EXTOP", -1, -1, -1, -1},
{0x15, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x16, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x17, 2, OP_COPR, WD, "SPOPWT", -1, -1, -1, -1},
{0x17, 2, OP_COPR, WD, "SPOPWT", -1, -1, -1, 1},
{0x18, 1, OP_DESC, WD, "RESTORE", 0, -1, -1, -1},
{0x19, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x1a, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
@ -291,8 +292,8 @@ mnemonic ops[256] = {
{0x1f, 1, OP_DESC, BT, "SWAPBI", -1, -1, -1, 0}, /* 3-122 252 */
{0x20, 1, OP_DESC, WD, "POPW", -1, -1, -1, 0},
{0x21, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x22, 2, OP_COPR, WD, "SPOPRS", -1, -1, -1, -1},
{0x23, 3, OP_COPR, WD, "SPOPS2", -1, -1, -1, -1},
{0x22, 2, OP_COPR, WD, "SPOPRS", 1, -1, -1, -1},
{0x23, 3, OP_COPR, WD, "SPOPS2", 1, -1, -1, 2},
{0x24, 1, OP_DESC, NA, "JMP", -1, -1, -1, 0},
{0x25, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x26, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
@ -308,7 +309,7 @@ mnemonic ops[256] = {
{0x30, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, /* Two-byte instructions */
{0x31, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x32, 1, OP_COPR, WD, "SPOP", -1, -1, -1, -1},
{0x33, 2, OP_COPR, WD, "SPOPWS", -1, -1, -1, -1},
{0x33, 2, OP_COPR, WD, "SPOPWS", -1, -1, -1, 1},
{0x34, 1, OP_DESC, WD, "JSB", -1, -1, -1, 0},
{0x35, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
{0x36, 1, OP_HALF, NA, "BSBH", -1, -1, -1, 0},
@ -1709,6 +1710,9 @@ t_stat sim_instr(void)
/* Generic index */
uint32 i;
/* Used by oprocessor instructions */
uint32 coprocessor_word;
operand *src1, *src2, *src3, *dst;
stop_reason = 0;
@ -1868,6 +1872,11 @@ t_stat sim_instr(void)
* Operate on the decoded instruction.
*/
/* Special case for coprocessor instructions */
if (cpu_instr->mn->mode == OP_COPR) {
coprocessor_word = cpu_instr->operands[0].embedded.w;
}
/* Get the operands */
if (cpu_instr->mn->src_op1 >= 0) {
src1 = &cpu_instr->operands[cpu_instr->mn->src_op1];
@ -2834,18 +2843,40 @@ t_stat sim_instr(void)
pc_incr = 0;
break;
case SPOP:
sim_debug(TRACE_DBG, &cpu_dev, "SPOP\n");
/* Memory fault is signaled when no support processor is
active */
if (mau_broadcast(coprocessor_word, 0, 0) != SCPE_OK) {
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
break;
case SPOPD2:
case SPOPS2:
case SPOPT2:
sim_debug(TRACE_DBG, &cpu_dev, "SPOP{D|S|T}2\n");
a = cpu_effective_address(src1);
b = cpu_effective_address(dst);
if (mau_broadcast(coprocessor_word, a, b) != SCPE_OK) {
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
break;
case SPOPRD:
case SPOPRS:
case SPOPRT:
sim_debug(TRACE_DBG, &cpu_dev, "SPOPR{D|S|T}\n");
a = cpu_effective_address(src1);
if (mau_broadcast(coprocessor_word, a, 0) != SCPE_OK) {
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
break;
case SPOPWD:
case SPOPWS:
case SPOPWT:
/* Memory fault is signaled when no support processor is
active */
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
sim_debug(TRACE_DBG, &cpu_dev, "SPOPW{D|S|T}\n");
a = cpu_effective_address(dst);
if (mau_broadcast(coprocessor_word, 0, a) != SCPE_OK) {
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
}
break;
case SUBW2:
case SUBH2:
@ -3682,20 +3713,19 @@ static SIM_INLINE void add(t_uint64 a, t_uint64 b, operand *dst)
void cpu_abort(uint8 et, uint8 isc)
{
/* We don't trap Integer Overflow if the OE bit is not set */
if ((R[NUM_PSW] & PSW_OE_MASK) || isc != INTEGER_OVERFLOW) {
R[NUM_PSW] &= ~(PSW_ET_MASK); /* Clear ET */
R[NUM_PSW] &= ~(PSW_ISC_MASK); /* Clear ISC */
R[NUM_PSW] |= et; /* Set ET */
R[NUM_PSW] |= (uint32) (isc << PSW_ISC); /* Set ISC */
/* TODO: We no longer use ABORT_TRAP or ABORT_EXC, so
* it would be nice to clean this up. */
if (et == 3 && (isc == BREAKPOINT_TRAP ||
isc == INTEGER_OVERFLOW ||
isc == TRACE_TRAP)) {
longjmp(save_env, ABORT_TRAP);
} else {
longjmp(save_env, ABORT_EXC);
}
if ((R[NUM_PSW] & PSW_OE_MASK) == 0 && isc == INTEGER_OVERFLOW) {
return;
}
R[NUM_PSW] &= ~(PSW_ET_MASK); /* Clear ET */
R[NUM_PSW] &= ~(PSW_ISC_MASK); /* Clear ISC */
R[NUM_PSW] |= et; /* Set ET */
R[NUM_PSW] |= (uint32) (isc << PSW_ISC); /* Set ISC */
longjmp(save_env, ABORT_EXC);
}
CONST char *cpu_description(DEVICE *dptr)
{
return "WE32100";
}

View file

@ -377,7 +377,7 @@ typedef struct _operand {
* An inst is a combination of a decoded instruction and
* 0 to 4 operands. Also used for history record keeping.
*/
typedef struct _instr {
typedef struct {
mnemonic *mn;
uint32 psw;
uint32 sp;
@ -401,6 +401,7 @@ t_stat cpu_show_cio(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat cpu_set_halt(UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_clear_halt(UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_boot(int32 unit_num, DEVICE *dptr);
CONST char *cpu_description(DEVICE *dptr);
t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs);

View file

@ -60,6 +60,9 @@ 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)
/* -t flag: Translate a virtual address */
#define EX_T_FLAG 1 << 19
/* -v flag for examine routine */
@ -163,6 +166,7 @@ noret __libc_longjmp (jmp_buf buf, int val);
#define PKT_DBG 0x0400
#define ERR_MSG 0x0800
#define CACHE_DBG 0x1000
#define DECODE_DBG 0x2000
/* Data types operated on by instructions. NB: These integer values
have meaning when decoding instructions, so this is not just an
@ -405,6 +409,11 @@ extern uint32 read_w(uint32 va, uint8 acc);
extern void write_b(uint32 va, uint8 val);
extern void write_h(uint32 va, uint16 val);
extern void write_w(uint32 va, uint32 val);
extern void pwrite_w(uint32 pa, uint32 val);
extern uint32 pread_w(uint32 pa);
/* global symbols from the MAU */
extern t_stat mau_broadcast(uint32 cmd, uint32 src, uint32 dst);
/* Globally scoped CPU functions */
extern void cpu_abort(uint8 et, uint8 isc);

3470
3B2/3b2_mau.c Normal file

File diff suppressed because it is too large Load diff

375
3B2/3b2_mau.h Normal file
View file

@ -0,0 +1,375 @@
/* 3b2_mmu.c: AT&T 3B2 Model 400 Math Acceleration Unit (WE32106 MAU)
Header
Copyright (c) 2019, 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.
---------------------------------------------------------------------
This file is part of a simulation of the WE32106 Math Acceleration
Unit. The WE32106 MAU is an IEEE-754 compabitle floating point
hardware math accelerator that was available as an optional
component on the AT&T 3B2/310 and 3B2/400, and a standard component
on the 3B2/500, 3B2/600, and 3B2/1000.
Portions of this code are derived from the SoftFloat 2c library by
John R. Hauser. Functions derived from SoftFloat 2c are clearly
marked in the comments.
Legal Notice
============
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat
was made possible in part by the International Computer Science
Institute, located at Suite 600, 1947 Center Street, Berkeley,
California 94704. Funding was partially provided by the National
Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a
fixed-point vector processor in collaboration with the University
of California at Berkeley, overseen by Profs. Nelson Morgan and
John Wawrzynek.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable
effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS
THAT WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS
SOFTWARE IS RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND
WILL TOLERATE ALL LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE
TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR THE
INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER
SCIENCE INSTITUTE (possibly via similar legal notice) AGAINST ALL
LOSSES, COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND
CLIENTS DUE TO THE SOFTWARE, OR INCURRED BY ANYONE DUE TO A
DERIVATIVE WORK THEY CREATE USING ANY PART OF THE SOFTWARE.
The following are expressly permitted, even for commercial
purposes:
(1) distribution of SoftFloat in whole or in part, as long as this
and other legal notices remain and are prominent, and provided also
that, for a partial distribution, prominent notice is given that it
is a subset of the original; and
(2) inclusion or use of SoftFloat in whole or in part in a
derivative work, provided that the use restrictions above are met
and the minimal documentation requirements stated in the source
code are satisfied.
---------------------------------------------------------------------
Data Types
==========
The WE32106 MAU stores values using IEEE-754 1985 types, plus a
non-standard Decimal type.
- Decimal Type - 18 BCD digits long. Each digit is 4 bits wide.
Sign is encoded in byte 0.
3322 2222 2222 1111 1111 1100 0000 0000
1098 7654 3210 9876 5432 1098 7654 3210
+-------------------+----+----+----+----+
| unused | D18| D17| D16| D15| High Word
+----+----+----+----+----+----+----+----+
| D14| D13| D12| D11| D10| D09| D08| D07| Middle Word
+----+----+----+----+----+----+----+----+
| D06| D05| D04| D03| D02| D01| D00|sign| Low Word
+----+----+----+----+----+----+----+----+
Sign: 0: Positive Infinity 10: Positive Number
1: Negative Infinity 11: Negative Number
2: Positive NaN 12: Positive Number
3: Negative NaN 13: Negative Number
4-9: Trapping NaN 14-15: Positive Number
- Extended Precision (80-bit) - exponent biased by 16383
3 322222222221111 1 111110000000000
1 098765432109876 5 432109876543210
+-----------------+-+---------------+
| unused |S| Exponent | High Word
+-+---------------+-+---------------+
|J| Fraction (high word) | Middle Word
+-+---------------------------------+
| Fraction (low word) | Low Word
+-----------------------------------+
- Double Precision (64-bit) - exponent biased by 1023
3 3222222222 211111111110000000000
1 0987654321 098765432109876543210
+-+----------+---------------------+
|S| Exponent | Fraction (high) | High Word
+-+----------+---------------------+
| Fraction (low) | Low Word
+----------------------------------+
- Single Precision (32-bit) - exponent biased by 127
3 32222222 22211111111110000000000
1 09876543 21098765432109876543210
+-+--------+-----------------------+
|S| Exp | Fraction |
+-+--------+-----------------------+
*/
#ifndef _3B2_MAU_H
#define _3B2_MAU_H
#include "3b2_defs.h"
#define SRC_LEN_INVALID 0
#define SRC_LEN_SINGLE 1
#define SRC_LEN_DOUBLE 2
#define SRC_LEN_TRIPLE 3
#define MAU_ASR_RC_SHIFT 22
#define MAU_ASR_PR 0x20u /* Partial Remainder */
#define MAU_ASR_QS 0x40u /* Divide By Zero Sticky */
#define MAU_ASR_US 0x80u /* Underflow Sticky */
#define MAU_ASR_OS 0x100u /* Overflow Sticky */
#define MAU_ASR_IS 0x200u /* Invalid Operation Sticky */
#define MAU_ASR_PM 0x400u /* Inexact Mask */
#define MAU_ASR_QM 0x800u /* Divide by Zero Mask */
#define MAU_ASR_UM 0x1000u /* Underflow Mask */
#define MAU_ASR_OM 0x2000u /* Overflow Mask */
#define MAU_ASR_IM 0x4000u /* Invalid Operation Mask */
#define MAU_ASR_UO 0x10000u /* Unordered */
#define MAU_ASR_CSC 0x20000u /* Context Switch Control */
#define MAU_ASR_PS 0x40000u /* Inexact Sticky */
#define MAU_ASR_IO 0x80000u /* Integer Overflow */
#define MAU_ASR_Z 0x100000u /* Zero Flag */
#define MAU_ASR_N 0x200000u /* Negative Flag */
#define MAU_ASR_RC 0x400000u /* Round Control */
#define MAU_ASR_NTNC 0x1000000u /* Nontrapping NaN Control */
#define MAU_ASR_ECP 0x2000000u /* Exception Condition */
#define MAU_ASR_RA 0x80000000u /* Result Available */
#define MAU_RC_RN 0 /* Round toward Nearest */
#define MAU_RC_RP 1 /* Round toward Plus Infin. */
#define MAU_RC_RM 2 /* Round toward Neg. Infin. */
#define MAU_RC_RZ 3 /* Round toward Zero */
#define SFP_SIGN(V) (((V) >> 31) & 1)
#define SFP_EXP(V) (((V) >> 23) & 0xff)
#define SFP_FRAC(V) ((V) & 0x7fffff)
#define DFP_SIGN(V) (((V) >> 63) & 1)
#define DFP_EXP(V) (((V) >> 52) & 0x7ff)
#define DFP_FRAC(V) ((V) & 0xfffffffffffffull)
#define XFP_SIGN(V) (((V)->sign_exp >> 15) & 1)
#define XFP_EXP(V) ((V)->sign_exp & 0x7fff)
#define XFP_FRAC(V) ((V)->frac)
#define XFP_IS_NORMAL(V) ((V)->frac & 0x8000000000000000ull)
#define DEFAULT_XFP_NAN_SIGN_EXP 0xffff
#define DEFAULT_XFP_NAN_FRAC 0xc000000000000000ull
#define SFP_IS_TRAPPING_NAN(V) (((((V) >> 22) & 0x1ff) == 0x1fe) && \
((V) & 0x3fffff))
#define DFP_IS_TRAPPING_NAN(V) (((((V) >> 51) & 0xfff) == 0xffe) && \
((V) & 0x7ffffffffffffull))
#define XFP_IS_NAN(V) ((((V)->sign_exp & 0x7fff) == 0x7fff) && \
(t_uint64)((V)->frac << 1))
#define XFP_IS_TRAPPING_NAN(V) ((((V)->sign_exp) & 0x7fff) && \
((((V)->frac) & ~(0x4000000000000000ull)) << 1) && \
(((V)->frac) == ((V)->frac & ~(0x4000000000000000ull))))
#define PACK_DFP(SIGN,EXP,FRAC) ((((t_uint64)(SIGN))<<63) + \
(((t_uint64)(EXP))<<52) + \
((t_uint64)(FRAC)))
#define PACK_SFP(SIGN,EXP,FRAC) (((uint32)(SIGN)<<31) + \
((uint32)(EXP)<<23) + \
((uint32)(FRAC)))
#define PACK_XFP(SIGN,EXP,FRAC,V) do { \
(V)->frac = (FRAC); \
(V)->sign_exp = ((uint16)(SIGN) << 15) + (EXP); \
} while (0)
#define PACK_XFP_S(SIGN,EXP,FRAC,S,V) do { \
(V)->frac = (FRAC); \
(V)->sign_exp = ((uint16)(SIGN) << 15) + (EXP); \
(V)->s = (S) != 0; \
} while (0)
#define MAU_RM ((RM)((mau_state.asr >> 22) & 3))
typedef enum {
M_ADD = 0x02,
M_SUB = 0x03,
M_DIV = 0x04,
M_REM = 0x05,
M_MUL = 0x06,
M_MOVE = 0x07,
M_RDASR = 0x08,
M_WRASR = 0x09,
M_CMP = 0x0a,
M_CMPE = 0x0b,
M_ABS = 0x0c,
M_SQRT = 0x0d,
M_RTOI = 0x0e,
M_FTOI = 0x0f,
M_ITOF = 0x10,
M_DTOF = 0x11,
M_FTOD = 0x12,
M_NOP = 0x13,
M_EROF = 0x14,
M_NEG = 0x17,
M_LDR = 0x18,
M_CMPS = 0x1a,
M_CMPES = 0x1b
} mau_opcodes;
typedef enum {
M_OP3_F0_SINGLE,
M_OP3_F1_SINGLE,
M_OP3_F2_SINGLE,
M_OP3_F3_SINGLE,
M_OP3_F0_DOUBLE,
M_OP3_F1_DOUBLE,
M_OP3_F2_DOUBLE,
M_OP3_F3_DOUBLE,
M_OP3_F0_TRIPLE,
M_OP3_F1_TRIPLE,
M_OP3_F2_TRIPLE,
M_OP3_F3_TRIPLE,
M_OP3_MEM_SINGLE,
M_OP3_MEM_DOUBLE,
M_OP3_MEM_TRIPLE,
M_OP3_NONE
} op3_spec;
/* Specifier bytes for Operands 1 and 2 */
typedef enum {
M_OP_F0,
M_OP_F1,
M_OP_F2,
M_OP_F3,
M_OP_MEM_SINGLE,
M_OP_MEM_DOUBLE,
M_OP_MEM_TRIPLE,
M_OP_NONE
} op_spec;
/*
* Not-a-Number Type
*/
typedef struct {
t_bool sign;
t_uint64 high;
t_uint64 low;
} NAN_T;
/*
* Extended Precision (80 bits).
*
* Note that an undocumented feature of the WE32106 requires the use
* of uint32 rather than uint16 for the sign and exponent components
* of the struct. Although bits 80-95 are "unused", several
* diagnostics actually expect these bits to be moved and preserved on
* word transfers. They are ignored and discarded by math routines,
* however.
*
* The 's' field holds the Sticky bit used by rounding.
*/
typedef struct {
uint32 sign_exp; /* Sign and Exponent */
t_uint64 frac; /* Fraction/Significand/Mantissa */
t_bool s; /* Sticky bit */
} XFP;
typedef struct {
uint32 h;
t_uint64 l;
} DEC;
/*
* Supported rounding modes.
*/
typedef enum {
ROUND_NEAREST,
ROUND_PLUS_INF,
ROUND_MINUS_INF,
ROUND_ZERO
} RM;
/*
* Double Precision (64 bits)
*/
typedef t_uint64 DFP;
/*
* Single Precision (32 bits)
*/
typedef uint32 SFP;
/*
* MAU state
*/
typedef struct {
uint32 cmd;
/* Exception */
uint32 exception;
/* Status register */
uint32 asr;
t_bool trapping_nan;
/* Generate a Non-Trapping NaN */
t_bool ntnan;
/* Source (from broadcast) */
uint32 src;
/* Destination (from broadcast) */
uint32 dst;
uint8 opcode;
uint8 op1;
uint8 op2;
uint8 op3;
/* Data Register */
XFP dr;
/* Operand Registers */
XFP f0;
XFP f1;
XFP f2;
XFP f3;
} MAU_STATE;
extern DEVICE mau_dev;
t_stat mau_reset(DEVICE *dptr);
t_stat mau_attach(UNIT *uptr, CONST char *cptr);
t_stat mau_detach(UNIT *uptr);
t_stat mau_broadcast(uint32 cmd, uint32 src, uint32 dst);
CONST char *mau_description(DEVICE *dptr);
#endif

View file

@ -52,11 +52,32 @@ REG mmu_reg[] = {
};
DEVICE mmu_dev = {
"MMU", &mmu_unit, mmu_reg, NULL,
1, 16, 8, 4, 16, 32,
NULL, NULL, &mmu_init,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
"MMU", /* name */
&mmu_unit, /* units */
mmu_reg, /* registers */
NULL, /* modifiers */
1, /* #units */
16, /* address radix */
8, /* address width */
4, /* address incr */
16, /* data radix */
32, /* data width */
NULL, /* examine routine */
NULL, /* deposit routine */
&mmu_init, /* reset routine */
NULL, /* boot routine */
NULL, /* attach routine */
NULL, /* detach routine */
NULL, /* context */
DEV_DEBUG, /* flags */
0, /* debug control flags */
sys_deb_tab, /* debug flag names */
NULL, /* memory size change */
NULL, /* logical name */
NULL, /* help routine */
NULL, /* attach help routine */
NULL, /* help context */
&mmu_description /* device description */
};
/*
@ -1083,3 +1104,8 @@ 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

@ -322,6 +322,7 @@ extern DEVICE mmu_dev;
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);
/* Physical memory read/write */
uint8 pread_b(uint32 pa);

View file

@ -38,6 +38,7 @@
#include "3b2_ctc.h"
#include "3b2_ports.h"
#include "3b2_ni.h"
#include "3b2_mau.h"
#include "3b2_sysdev.h"
char sim_name[] = "AT&T 3B2 Model 400";
@ -53,6 +54,7 @@ extern instr *cpu_instr;
DEVICE *sim_devices[] = {
&cpu_dev,
&mmu_dev,
&mau_dev,
&timer_dev,
&tod_dev,
&nvram_dev,
@ -86,6 +88,7 @@ const char *sim_stop_messages[] = {
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);

View file

@ -220,6 +220,10 @@
RelativePath="..\3B2\3b2_iu.c"
>
</File>
<File
RelativePath="..\3B2\3b2_mau.c"
>
</File>
<File
RelativePath="..\3B2\3b2_mmu.c"
>
@ -508,6 +512,10 @@
RelativePath="..\3B2\3b2_iu.h"
>
</File>
<File
RelativePath="..\3B2\3b2_mau.h"
>
</File>
<File
RelativePath="..\3B2\3b2_mmu.h"
>

View file

@ -328,8 +328,8 @@ ATT3B2_LIB = $(LIB_DIR)ATT3B2-$(ARCH).OLB
ATT3B2_SOURCE = $(ATT3B2_DIR)3B2_CPU.C,$(ATT3B2_DIR)3B2_DMAC.C,\
$(ATT3B2_DIR)3B2_ID.C,$(ATT3B2_DIR)3B2_IF.C,\
$(ATT3B2_DIR)3B2_IO.C,$(ATT3B2_DIR)3B2_IU.C,\
$(ATT3B2_DIR)3B2_MMU.C,$(ATT3B2_DIR)3B2_SYS.C,\
$(ATT3B2_DIR)3B2_SYSDEV.C
$(ATT3B2_DIR)3B2_MAU.C,$(ATT3B2_DIR)3B2_MMU.C,\
$(ATT3B2_DIR)3B2_SYS.C,$(ATT3B2_DIR)3B2_SYSDEV.C
ATT3B2_OPTIONS = /INCL=($(SIMH_DIR),$(ATT3B2_DIR))/DEF=($(CC_DEFS))
# MITS Altair Simulator Definitions.

View file

@ -1920,7 +1920,8 @@ ATT3B2 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_mmu.c \
${ATT3B2D}/3b2_id.c ${ATT3B2D}/3b2_dmac.c \
${ATT3B2D}/3b2_sys.c ${ATT3B2D}/3b2_io.c \
${ATT3B2D}/3b2_ports.c ${ATT3B2D}/3b2_ctc.c \
${ATT3B2D}/3b2_ni.c ${ATT3B2D}/3b2_sysdev.c
${ATT3B2D}/3b2_ni.c ${ATT3B2D}/3b2_mau.c \
${ATT3B2D}/3b2_sysdev.c
ATT3B2_OPT = -DUSE_INT64 -DUSE_ADDR64 -I ${ATT3B2D} ${NETWORK_OPT}
#
# Build everything (not the unsupported/incomplete or experimental simulators)