ControlUnit

Struct ControlUnit 

Source
pub struct ControlUnit {
    regs: ControlRegisters,
    trap: TrapCircuit,
    alarm_unit: AlarmUnit,
}
Expand description

ControlUnit simulates the operation of the Control Element of the TX-2 computer.

Fields§

§regs: ControlRegisters§trap: TrapCircuit§alarm_unit: AlarmUnit

Implementations§

Source§

impl ControlUnit

Source

pub(crate) fn op_spg( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the SPG instruction.

Source§

impl ControlUnit

Source

pub(crate) fn op_dpx( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the DPX instruction (Opcode 016, User Handbook, page 3-16).

Source

pub(crate) fn op_aux( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the AUX instruction (Opcode 010, User Handbook, page 3-22).

Source

pub(crate) fn op_rsx( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the RSX instruction (Opcode 011, User Handbook, page 3-14).

Source

pub(crate) fn op_skx(&mut self, _ctx: &Context) -> Result<OpcodeResult, Alarm>

Implements the SKX instruction (Opcode 012, User Handbook, page 3-24).

Source

pub(crate) fn op_jpx( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the JPX (jump on positive index) opcode (06).

Source

pub(crate) fn op_jnx( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the JNX (jump on positive index) opcode (07).

Source

pub(crate) fn impl_op_jpx_jnx<F: FnOnce(&Signed18Bit) -> bool>( &mut self, ctx: &Context, predicate: F, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Source§

impl ControlUnit

Source

pub(crate) fn op_opr( &mut self, ctx: &Context, mem: &mut MemoryUnit, devices: &mut DeviceManager, ) -> Result<OpcodeResult, Alarm>

OPR: Implements the IOS opcode and the AOP opcode.

Bits 2.7 and 2.8 of the N register (i.e. the instruction word) distinguish between IOS and AOP (which together are known as OPR). This decoding is described in section 7-11 (“MISCELLANEOUS OPERATION CODES”) in Volume 1 of the Technical Manual. Neither of these insructions are indexable or configurable (probably because they don’t perform a memory access).

Source

fn op_ios( &mut self, ctx: &Context, mem: &mut MemoryUnit, devices: &mut DeviceManager, ) -> Result<OpcodeResult, Alarm>

Source

fn connect_unit( ctx: &Context, devices: &mut DeviceManager, regs: &mut ControlRegisters, trap: &mut TrapCircuit, unit: Unsigned6Bit, mode: Unsigned12Bit, alarm_unit: &mut AlarmUnit, ) -> Result<(), Alarm>

Source

pub(crate) fn op_tsd( &mut self, ctx: &Context, devices: &mut DeviceManager, execution_address: Address, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Source§

impl ControlUnit

§“Jump Skip Class” opcodes
Source

pub(crate) fn op_jmp( &mut self, _ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the JMP opcode and its variations (all of which are unconditional jumps).

Source

pub(crate) fn op_skm( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

The SKM instruction. This has a number of supernumerary mnemonics. The index address field of the instruction identifies which bit (within the target word) to operate on, and the instruction configuration value determines both how to manipulate that bit, and what to do on the basis of its original value.

The SKM instruction is documented on pages 7-34 and 7-35 of the TX-2 User Handbook.

Source

pub(crate) fn op_sed( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implement the SED instruction. This is described on page 3-36 of the Users Handbook.

Source§

impl ControlUnit

Source

pub(crate) fn op_lda( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the LDA instruction (Opcode 024, User Handbook, page 3-6).

Source

pub(crate) fn op_ldb( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the LDB instruction (Opcode 025, User Handbook, page 3-6).

Source

pub(crate) fn op_ldc( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the LDC instruction (Opcode 026, User Handbook, page 3-6).

Source

pub(crate) fn op_ldd( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the LDD instruction (Opcode 027, User Handbook, page 3-6).

Source

pub(crate) fn op_lde( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the LDE instruction (Opcode 020, User Handbook, page 3-6).

Source

pub(crate) fn op_sta( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the STA instruction (Opcode 034, User Handbook, page 3-8).

Source

pub(crate) fn op_stb( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the STB instruction (Opcode 035, User Handbook, page 3-8).

Source

pub(crate) fn op_stc( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the STC instruction (Opcode 036, User Handbook, page 3-8).

Source

pub(crate) fn op_std( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the STD instruction (Opcode 036, User Handbook, page 3-8).

Source

pub(crate) fn op_ste( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<OpcodeResult, Alarm>

Implements the STE instruction (Opcode 030, User Handbook, page 3-8).

Source

fn op_store_ae_register( &mut self, ctx: &Context, register_value: Unsigned36Bit, mem: &mut MemoryUnit, update_e: &UpdateE, ) -> Result<OpcodeResult, Alarm>

Implement opcodes ST{A,B,C,D,E}.

Source

fn op_load_value( &mut self, ctx: &Context, existing: &Unsigned36Bit, mem: &mut MemoryUnit, update_e: &UpdateE, ) -> Result<Unsigned36Bit, Alarm>

Implement loads as if for opcodes LD{A,B,C,D,E}.

Source§

impl ControlUnit

Source

pub fn new( panic_on_unmasked_alarm: PanicOnUnmaskedAlarm, configuration_memory_config: ConfigurationMemorySetup, ) -> ControlUnit

Source

pub fn diagnostics(&self) -> &CurrentInstructionDiagnostics

Source

fn make_alarm(&self, details: AlarmDetails) -> Alarm

Source

fn fire_details_if_not_masked( &mut self, alarm_details: AlarmDetails, ) -> Result<(), Alarm>

Source

pub fn set_alarm_masked( &mut self, kind: AlarmKind, masked: bool, ) -> Result<(), Alarm>

Source

pub fn unmasked_alarm_active(&self) -> bool

Source

pub fn get_status_of_alarm(&self, name: &str) -> Option<AlarmStatus>

Source

pub fn get_alarm_statuses(&self) -> Vec<AlarmStatus>

Source

pub fn set_metabits_disabled(&mut self, disable: bool)

Source

pub fn codabo( &mut self, ctx: &Context, reset_mode: &ResetMode, devices: &mut DeviceManager, mem: &mut MemoryUnit, ) -> Result<(), Alarm>

There are actually 9 different CODABO buttons (see page 5-18 of the User Guide). There are also 9 corresponding RESET buttons. Each RESET button has a corresponding CODABO button. See the reset method for address assignments.

The CODABO operation leaves the Start Point Register set to the selected start point. There are also 9 reset buttons which perform a similar task.

Pressing the main CODABO button (the one which uses the Toggle Start Point register) will result in memory being cleared, F-memory being set up in a standard way, and then a program being read from the paper tape reader using the standard readin program set up on the plugboard.

The standard readin program executes the program it read in from the address specified by the program. The program executes as sequence 52 (PETR) with the PETR unit initially turned off.

The Users Handbook (page 5-18) states that flags are cleared but it doesn’t state anywhere that any registers are reset. So we don’t do that. But there’s no unit test for that, since I haven’t found (or cannot recall) a piece of documentation which states that this is so.

Source

fn preset( &mut self, ctx: &Context, devices: &mut DeviceManager, ) -> Result<(), Alarm>

Simulate the effect of the PRESET button. This is described on page 5-19 of the Users Handbook. It:

  1. clears all flags
  2. Clears all “Connect” flip-flops
  3. Set all interlocks and indicators to their proper “PRESET” value.

PRESET is supposedly interlocked so that it is ineffective unless the machine is in the STOP state. But our simulation, right now, has no representation for the STOP state.

Source

fn calaco(&mut self)

Simulate the effect of the CALACO button. This is described on page 5-19 of the Users Handbook.

Source

fn clear_alarms(&mut self)

Source

pub fn disconnect_all_devices( &mut self, ctx: &Context, devices: &mut DeviceManager, ) -> Result<(), Alarm>

Source

pub fn reset( &mut self, ctx: &Context, reset_mode: &ResetMode, mem: &mut MemoryUnit, )

There are 9 separate RESET buttons, for 8 fixed addresses and another which uses the Toggle Start Point register. There appear to be two Toggle Start Point switches, one on the front panel and a second on a remote control unit. The fixed-address RESET buttons correspond to the fixed addresses 3777710 through 3777717, inclusive.

RESET only loads the Start Point Register, nothing else.

Source

pub fn startover( &mut self, ctx: &Context, reset_mode: &ResetMode, mem: &mut MemoryUnit, )

Handle press of STARTOVER (or part of the operation of CODABO). STARTOVER does RESET and then raises flag zero.

Source

fn tsp(&self) -> Address

Return the value in the Toggle Start Register (TSP).

The TSP is a set of toggle switches on the TX-2’s console (see the TX-2 Users Handbook section 4-2.2).

For now, we haven’t made it configurable (i.e. have not emulated the hardware) yet. We just hard-code it to point at the F-memory configuration routine (which does its job and then invokes the standard tape reader).

§Caveat

We used to set this to point at the “Memory Clear / Memory Smear” program in the plugboard (see memory::get_standard_plugboard()), but that accesses addresses which are not mapped (e.g. the gap between U-memory and V-memory) and so should only be run qith QSAL disabled, which is not our default config.

We should double-check how the TX-2’s TSP was normally set and how the TX-2 behaved around this.

Source

fn trap_seq() -> Unsigned6Bit

Source

fn raise_trap(&mut self)

Source

fn change_sequence( &mut self, mem: &mut MemoryUnit, prev_seq: Option<SequenceNumber>, next_seq: SequenceNumber, )

Source

fn set_program_counter(&mut self, change: ProgramCounterChange)

Source

fn select_sequence(&mut self, mem: &mut MemoryUnit) -> RunMode

Consider whether a change of sequence is needed. If yes, perform the change.

Source

fn fetch_instruction( &mut self, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<(), Alarm>

Source

pub fn poll_hardware( &mut self, ctx: &Context, devices: &mut DeviceManager, run_mode: RunMode, ) -> Result<(RunMode, Option<Duration>), Alarm>

Source

fn update_n_register( &mut self, instruction_word: Unsigned36Bit, ) -> Result<(), Alarm>

Source

fn invalid_opcode_alarm(&self) -> Alarm

Source

fn invalid_opr_subcode(&self, bit2dot7: bool) -> Alarm

Source

fn estimate_execute_time_ns(&self, orig_inst: &Instruction) -> u64

Source

pub fn execute_instruction( &mut self, ctx: &Context, devices: &mut DeviceManager, mem: &mut MemoryUnit, poll_order_change: &mut Option<SequenceNumber>, ) -> Result<(u64, RunMode, Option<OutputEvent>), (Alarm, Address)>

Fetch and execute the next instruction pointed to by the P register. Returns the estimated number of nanoseconds needed to execute the instruction.

Source

fn get_config(&self) -> SystemConfiguration

Source

fn fetch_operand_from_address_with_exchange( &mut self, ctx: &Context, mem: &mut MemoryUnit, operand_address: &Address, existing_dest: &Unsigned36Bit, update_e: &UpdateE, ) -> Result<(Unsigned36Bit, ExtraBits), Alarm>

Source

fn fetch_operand_from_address_without_exchange( &mut self, ctx: &Context, mem: &mut MemoryUnit, operand_address: &Address, update_e: &UpdateE, ) -> Result<(Unsigned36Bit, ExtraBits), Alarm>

Source

fn memory_store_without_exchange( &mut self, ctx: &Context, mem: &mut MemoryUnit, target: &Address, value: &Unsigned36Bit, update_e: &UpdateE, meta_op: &MetaBitChange, ) -> Result<(), Alarm>

Source

fn memory_store_with_exchange( &mut self, ctx: &Context, mem: &mut MemoryUnit, target: &Address, value: &Unsigned36Bit, existing: &Unsigned36Bit, update_e: &UpdateE, meta_op: &MetaBitChange, ) -> Result<(), Alarm>

Source

fn operand_address_with_optional_defer_and_index( self: &mut ControlUnit, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<Address, Alarm>

Determine the address of the operand for instructions that use indexing.

Source

fn operand_address_with_optional_defer_without_index( self: &mut ControlUnit, ctx: &Context, mem: &mut MemoryUnit, ) -> Result<Address, Alarm>

Determine the address of the operand for instructions that do not use indexing.

Source

fn resolve_operand_address( self: &mut ControlUnit, ctx: &Context, mem: &mut MemoryUnit, initial_index_override: Option<Unsigned6Bit>, ) -> Result<Address, Alarm>

Resolve the address of the operand of the current instruction, leaving this address in the Q register.

§Arguments
  • ctx - context data for the execution of the instruction.
  • mem - the memory unit (which we would use for deferred indexing).
  • initial_index_override - source of the j bits (index register number) to be used; this is specified when processing the JNX instruction for example. If the value is None, the value is instead taken from the N register.
Source

fn write_operand_metaop(&self) -> MetaBitChange

Source

fn memory_read_and_update_with_exchange<F>( &mut self, ctx: &Context, mem: &mut MemoryUnit, target: &Address, update_e: &UpdateE, transform: F, ) -> Result<(), Alarm>
where F: FnOnce(Unsigned36Bit) -> Unsigned36Bit,

Source

fn dismiss(&mut self, reason: &str)

Source

fn dismiss_unless_held(&mut self, reason: &str) -> bool

Source

pub fn current_flag_state(&self, unit: &SequenceNumber) -> bool

Source

pub fn drain_alarm_changes(&mut self) -> BTreeMap<AlarmKind, AlarmStatus>

Source

pub fn drain_flag_changes(&mut self) -> Vec<(SequenceNumber, Signed18Bit)>

Source

pub fn inspect_registers(&self) -> &ControlRegisters

Trait Implementations§

Source§

impl Alarmer for ControlUnit

Source§

fn fire_if_not_masked<F: DiagnosticFetcher>( &mut self, alarm_instance: Alarm, get_diags: F, ) -> Result<(), Alarm>

Fire the indicated alarm if it is not masked.
Source§

fn always_fire<F: DiagnosticFetcher>( &mut self, alarm_instance: Alarm, get_diags: F, ) -> Alarm

Unconditionally fire the indicated alarm.
Source§

impl Debug for ControlUnit

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ControlUnit

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<Src, Scheme> ApproxFrom<Src, Scheme> for Src
where Scheme: ApproxScheme,

§

type Err = NoError

The error type produced by a failed conversion.
§

fn approx_from(src: Src) -> Result<Src, <Src as ApproxFrom<Src, Scheme>>::Err>

Convert the given value into an approximately equivalent representation.
§

impl<Dst, Src, Scheme> ApproxInto<Dst, Scheme> for Src
where Dst: ApproxFrom<Src, Scheme>, Scheme: ApproxScheme,

§

type Err = <Dst as ApproxFrom<Src, Scheme>>::Err

The error type produced by a failed conversion.
§

fn approx_into(self) -> Result<Dst, <Src as ApproxInto<Dst, Scheme>>::Err>

Convert the subject into an approximately equivalent representation.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, Dst> ConvAsUtil<Dst> for T

§

fn approx(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst>,

Approximate the subject with the default scheme.
§

fn approx_by<Scheme>(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst, Scheme>, Scheme: ApproxScheme,

Approximate the subject with a specific scheme.
§

impl<T> ConvUtil for T

§

fn approx_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst>,

Approximate the subject to a given type with the default scheme.
§

fn approx_as_by<Dst, Scheme>(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst, Scheme>, Scheme: ApproxScheme,

Approximate the subject to a given type with a specific scheme.
§

fn into_as<Dst>(self) -> Dst
where Self: Sized + Into<Dst>,

Convert the subject to a given type.
§

fn try_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + TryInto<Dst>,

Attempt to convert the subject to a given type.
§

fn value_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + ValueInto<Dst>,

Attempt a value conversion of the subject to a given type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<Src> TryFrom<Src> for Src

§

type Err = NoError

The error type produced by a failed conversion.
§

fn try_from(src: Src) -> Result<Src, <Src as TryFrom<Src>>::Err>

Convert the given value into the subject type.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<Src, Dst> TryInto<Dst> for Src
where Dst: TryFrom<Src>,

§

type Err = <Dst as TryFrom<Src>>::Err

The error type produced by a failed conversion.
§

fn try_into(self) -> Result<Dst, <Src as TryInto<Dst>>::Err>

Convert the subject into the destination type.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<Src> ValueFrom<Src> for Src

§

type Err = NoError

The error type produced by a failed conversion.
§

fn value_from(src: Src) -> Result<Src, <Src as ValueFrom<Src>>::Err>

Convert the given value into an exactly equivalent representation.
§

impl<Src, Dst> ValueInto<Dst> for Src
where Dst: ValueFrom<Src>,

§

type Err = <Dst as ValueFrom<Src>>::Err

The error type produced by a failed conversion.
§

fn value_into(self) -> Result<Dst, <Src as ValueInto<Dst>>::Err>

Convert the subject into an exactly equivalent representation.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,