Revision feabfcc6514f3fb411605a6982bc539a220b8fe6 authored by Mike Stewart on 07 August 2021, 22:38:19 UTC, committed by Mike Stewart on 07 August 2021, 22:38:19 UTC
1 parent 9587743
PAR.cpp
/****************************************************************************
* PAR - PARITY GENERATION AND TEST subsystem
*
* AUTHOR: John Pultorak
* DATE: 9/22/01
* FILE: PAR.cpp
*
* NOTES: see header file.
*
*****************************************************************************
*/
#include "PAR.h"
#include "SEQ.h"
#include "BUS.h"
#include "MBF.h"
#include "ADR.h"
#include "MEM.h"
regP PAR::register_P;
regP2 PAR::register_P2;
regG15 PAR::register_G15; // memory buffer register bit 15
regPALM PAR::register_PALM; // PARITY ALARM FF
unsigned PAR::conv_WP[] =
{ BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 };
void
PAR::execRP_WE()
{
// Write parity into memory.
MEM::MEM_PARITY_BUS = PAR::register_G15.read();
}
// IMPLEMENTATION NOTE: It has been empirically determined that the following
// control signals are mutually exclusive (there is never more than one of these
// generated at any time):
// GP, WGX, RP2, SBWG, CLG
// NOTE: WP clears register_P before writing into it. Strictly speaking, WPx isn't
// supposed to clear the register (should OR into the register), but in the counter
// sequences where WPx is used, register_P is always cleared in the previous TP by
// asserting WP with default zeroes on the write bus.
void
PAR::execWP_WP()
{
// set all bits except parity bit
register_P.writeShift(BUS::glbl_WRITE_BUS, PAR::conv_WP);
// now set parity bit; in the actual AGC, this is
// a single operation.
if (SEQ::isAsserted(RG))
register_P.writeField(16, 16, register_G15.read());
else
register_P.writeField(16, 16, 0); // clear parity bit
}
void
PAR::execWP_WPx()
{
// set all bits except parity bit
register_P.writeShift(BUS::glbl_WRITE_BUS, PAR::conv_WP);
// now set parity bit; in the actual AGC, this is
// a single operation.
if (SEQ::isAsserted(RG))
register_P.writeField(16, 16, register_G15.read());
else
register_P.writeField(16, 16, 0); // clear parity bit
}
void
PAR::execWP_WP2()
{
register_P2.write(gen1_15Parity(register_P.read()));
}
void
PAR::execWP_RP2()
{
register_G15.write(register_P2.read());
}
void
PAR::execWP_GP()
{
register_G15.write(gen1_15Parity(register_P.read()));
}
void
PAR::execWP_SBWG()
{
register_G15.write(MEM::MEM_PARITY_BUS); // load memory bit 16 (parity) into G15
}
void
PAR::execWP_WGx()
{
// This is only used in PINC, MINC, and SHINC. Does not clear G
// register; writes (ORs) into G from RWBus and writes into parity
// from 1-15 generator. All done in one operation, although I show
// it in two steps here. The sequence calls CLG in a previous TP.
register_G15.write(PAR::gen1_15Parity(register_P.read()));
}
void
PAR::execWP_CLG()
{
register_G15.write(0);
}
void
PAR::execWP_GENRST()
{
register_PALM.write(0);
}
void
PAR::execWP_TP()
{
if (ADR::GTR_27() && genP_15Parity(register_P.read()))
register_PALM.write(genP_15Parity(register_P.read()));
}
void
PAR::CLR_PALM()
{
// asynchronous clear for PARITY ALARM (from MON)
register_PALM.clear();
}
unsigned
PAR::gen1_15Parity(unsigned r)
{
//check the lower 15 bits of 'r' and return the odd parity;
//bit 16 is ignored.
unsigned evenParity = (1 & (r >> 0)) ^ (1 & (r >> 1)) ^ (1 & (r >> 2))
^ (1 & (r >> 3)) ^ (1 & (r >> 4)) ^ (1 & (r >> 5)) ^ (1 & (r >> 6))
^ (1 & (r >> 7)) ^ (1 & (r >> 8)) ^ (1 & (r >> 9)) ^ (1 & (r >> 10))
^ (1 & (r >> 11)) ^ (1 & (r >> 12)) ^ (1 & (r >> 13)) ^ (1 & (r >> 14));
return ~evenParity & 1; // odd parity
}
unsigned
PAR::genP_15Parity(unsigned r)
{
//check all 16 bits of 'r' and return the odd parity
unsigned evenParity = (1 & (r >> 0)) ^ (1 & (r >> 1)) ^ (1 & (r >> 2))
^ (1 & (r >> 3)) ^ (1 & (r >> 4)) ^ (1 & (r >> 5)) ^ (1 & (r >> 6))
^ (1 & (r >> 7)) ^ (1 & (r >> 8)) ^ (1 & (r >> 9)) ^ (1 & (r >> 10))
^ (1 & (r >> 11)) ^ (1 & (r >> 12)) ^ (1 & (r >> 13)) ^ (1 & (r >> 14))
^ (1 & (r >> 15));
return ~evenParity & 1; // odd parity
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...