@@ -246,46 +246,65 @@ fn test_sequence_flags_current_flag_state() {
246246 assert_eq ! ( flags. drain_flag_changes( ) , vec![ u6!( 0o52 ) ] ) ;
247247}
248248
249+ /// ControlRegisterDiagnostics is only for generating debug
250+ /// information. They must not be used for control/execution
251+ /// purposes.
252+ #[ derive( Debug ) ]
253+ pub struct CurrentInstructionDiagnostics {
254+ pub current_instruction : Instruction ,
255+ pub instruction_address : Address ,
256+ }
257+
249258#[ derive( Debug ) ]
250259pub struct ControlRegisters {
260+ pub diagnostic_only : CurrentInstructionDiagnostics ,
261+
251262 // Arithmetic Element registers (A-E) are actually in V-memory.
263+ /// Contents of the simulated N register.
252264 pub n : Instruction ,
253265 pub n_sym : Option < SymbolicInstruction > ,
266+
267+ /// The P register is the program counter for the current sequence.
254268 pub p : Address ,
269+
270+ /// Contents of the simulaterd Q register.
255271 pub q : Address ,
256272
257- // The k register (User guide 4-3.1) holds the current sequence
258- // number (User guide 5-24). k is Option<SequenceNumber> in order
259- // to allow the (emulated) control unit to recognise a CODABO
260- // button as indicating a need to change sequence from the control
261- // unit's initial state to sequence 0.
262- //
263- // This likely doesn't reflect the actual operation of the TX-2
264- // very well, and better understanding of the real operation of
265- // the machine will likely change this.
266- //
267- // I think that perhaps section 12-2.6.2 of Volume 2 of the
268- // technical manual may explain how the real TX-2 avoided this
269- // problem, but I don't think I understand what that section says.
270- // The text is:
271- //
272- // """12-2.6.2 XPS FLIP-FLOP LOGIC. This flip-floop inhibits the
273- // X Memory strobe pulse into X when the register selected has the
274- // same address or the current program counter, is not register 0,
275- // and this is the first reference to this register since the last
276- // sequence change. In this case all the cores of the register
277- // are clearered and only "junk" (with a 50-50 chance of a bad
278- // parity) would be strobed into X. If XPS¹, then a clear pulse
279- // is substituted for the strobe pulse.
280- //
281- // The flip-flop is set whenever a sequence change occurs, and is
282- // cleared the first time thereafter that the program counter
283- // register is referenced during a PK cycle (if ever). See Fig
284- // 12-8."""
273+ /// The k register (User guide 4-3.1) holds the current sequence
274+ /// number (User guide 5-24). k is Option<SequenceNumber> in order
275+ /// to allow the (emulated) control unit to recognise a CODABO
276+ /// button as indicating a need to change sequence from the control
277+ /// unit's initial state to sequence 0.
278+ ///
279+ /// This likely doesn't reflect the actual operation of the TX-2
280+ /// very well, and better understanding of the real operation of
281+ /// the machine will likely change this.
282+ ///
283+ /// I think that perhaps section 12-2.6.2 of Volume 2 of the
284+ /// technical manual may explain how the real TX-2 avoided this
285+ /// problem, but I don't think I understand what that section says.
286+ /// The text is:
287+ ///
288+ /// """12-2.6.2 XPS FLIP-FLOP LOGIC. This flip-floop inhibits the
289+ /// X Memory strobe pulse into X when the register selected has the
290+ /// same address or the current program counter, is not register 0,
291+ /// and this is the first reference to this register since the last
292+ /// sequence change. In this case all the cores of the register
293+ /// are clearered and only "junk" (with a 50-50 chance of a bad
294+ /// parity) would be strobed into X. If XPS¹, then a clear pulse
295+ /// is substituted for the strobe pulse.
296+ ///
297+ /// The flip-flop is set whenever a sequence change occurs, and is
298+ /// cleared the first time thereafter that the program counter
299+ /// register is referenced during a PK cycle (if ever). See Fig
300+ /// 12-8."""
285301 pub k : Option < SequenceNumber > ,
286302
287- spr : Address , // Start Point Register
303+ /// Start Point Register
304+ spr : Address ,
288305
306+ /// Index registers.
307+ ///
289308 /// Index register 0 is the Toggle Start point.
290309 /// Index registers 40-77 are program counters for the sequences.
291310 ///
@@ -294,14 +313,21 @@ pub struct ControlRegisters {
294313 /// 3-68 of the User Handbook (section 3-3.1) as being signed
295314 /// integers.
296315 pub index_regs : [ Signed18Bit ; 0o100 ] , // AKA the X memory
297- f_memory : [ SystemConfiguration ; 32 ] , // the F memory
316+
317+ /// the F memory
318+ f_memory : [ SystemConfiguration ; 32 ] ,
319+
320+ /// The flags; these indicate which sequences are runnable.
298321 flags : SequenceFlags ,
299322 current_sequence_is_runnable : bool ,
323+
324+ /// prev_hold is set when the instruction we most previously
325+ /// executed had the "hold" bit set.
326+ prev_hold : bool ,
300327 // TODO: we may be able to eliminate prev_hold by moving the logic
301328 // that's currently at the beginning of fetch_instruction() so
302329 // that it occurs at the end of execute_instruction() instead.
303330 // See the comment at the top of fetch_instruction().
304- prev_hold : bool ,
305331}
306332
307333impl ControlRegisters {
@@ -317,6 +343,10 @@ impl ControlRegisters {
317343 } ;
318344
319345 let mut result = ControlRegisters {
346+ diagnostic_only : CurrentInstructionDiagnostics {
347+ current_instruction : Instruction :: invalid ( ) ,
348+ instruction_address : Address :: from ( u18 ! ( 0o777_777 ) ) ,
349+ } ,
320350 n : Instruction :: invalid ( ) , // not a valid instruction
321351 n_sym : None ,
322352 p : Address :: default ( ) ,
@@ -921,6 +951,7 @@ impl ControlUnit {
921951 // Calculate the address from which we will fetch the
922952 // instruction, and the increment the program counter.
923953 let p_physical_address = Address :: from ( self . regs . p . split ( ) . 0 ) ;
954+ self . regs . diagnostic_only . instruction_address = p_physical_address;
924955 event ! (
925956 Level :: TRACE ,
926957 "Fetching instruction from physical address {p_physical_address:>012o}"
@@ -931,7 +962,7 @@ impl ControlUnit {
931962 } else {
932963 MetaBitChange :: None
933964 } ;
934- let instruction_word = match mem. fetch ( ctx, & p_physical_address, & meta_op) {
965+ let instruction_word: Unsigned36Bit = match mem. fetch ( ctx, & p_physical_address, & meta_op) {
935966 Ok ( ( inst, extra_bits) ) => {
936967 if extra_bits. meta && self . trap . trap_on_marked_instruction ( ) {
937968 self . raise_trap ( ) ;
@@ -975,6 +1006,10 @@ impl ControlUnit {
9751006 p_physical_address
9761007 ) ;
9771008 }
1009+ // Several things update the N register, so we update
1010+ // `current_instruction` directly here instead of inside
1011+ // update_n_register().
1012+ self . regs . diagnostic_only . current_instruction = Instruction :: from ( instruction_word) ;
9781013 self . update_n_register ( instruction_word) ?;
9791014 Ok ( ( ) )
9801015 }
@@ -1632,8 +1667,8 @@ impl ControlUnit {
16321667 if let Some ( current_seq) = self . regs . k {
16331668 event ! (
16341669 Level :: DEBUG ,
1635- "dismissing current sequence (reason: {}) " ,
1636- reason
1670+ "dismissing current sequence {current_seq:o} (reason: {reason}) while executing instruction from {:o} " ,
1671+ self . regs . diagnostic_only . instruction_address ,
16371672 ) ;
16381673 self . regs . flags . lower ( & current_seq) ;
16391674 self . regs . current_sequence_is_runnable = false ;
0 commit comments