Closed lucien1276 closed 10 months ago
Thanks for submitting this issue and your kind words about the emulator. You raise a very important question.
That one word-time wait for deferred commands exists for a reason. A G-15 command goes through potentially four states:
RC -- Read Command (loads the command word into registers). WTR -- Wait for Transfer (waits for the word designated by T to come around on the drum, only applies to DEFERRED commands). TR -- Transfer (execute the command; takes one word time for DEFERRED commands and T-L-1 word times for IMMEDIATE commands). WRC -- Wait to Read Command (waits for the word designated by N to come around on the drum).
And then the cycle repeats. For IMMEDIATE commands, WTR is skipped, and the processor goes directly from RC state to TR state at L+1. TR state then lasts up to but not including T.
The important thing to note about WTR is that the end of that state is detected during word time T-1 and always takes at least one word-time. If T=L+1, then T-1 is the command word time (L), but WTR doesn't start until L+1, which is too late. Therefore, WTR needs to wait for 107 word times until it can detect T-1 and allow TR to start at T.
The G-15 coding manuals (they're more like "coding cookbooks" than reference manuals) are not very explicit about DEFERRED commands requiring at least one word time between L and T. The best resource I've found for timing details like this is the Theory of Operation manual:
http://bitsavers.org/pdf/bendix/g-15/60121600_G15_Theory_Of_Operation_Nov64.pdf
The most relevant portions are the discussion on Transfer Timing (p.28) and the discussions on Relative Timing Numbers, RC-WTR-TR-WRC Control, and Deferred Commands (p.44-47). Note especially the sentence that starts at the bottom of p.45:
"This accounts for the programming restriction that any DEFERRED command will involve at least one word time in WTR, hence if T=L+1, 108 word times will be spent in the WTR state."
The way that memory addressing and command timing works with the L, T, and N numbers and the hidden COMMAND register is very clever, but also difficult to understand. It makes my head spin.
The solution to your timing problem is really simple, though. Just make your command IMMEDIATE rather than DEFERRED and change T to L+2. That will guarantee that the TR state will start on L+1 and last for one word time.
I'm going to close this issue, but please feel free to continue commenting against it, especially if you have further questions.
OK, but it's strange that in the 3 programming books there are a lot of "Ln Tn+1 Nn+2", especially when they are teaching "minimum access coding". Executed on your emulator, this is the worst case: an instruction that should take 1 word-time takes 109 word-times.
Even in their test routines there are a lot of these cases (pages 208 - 240 in the book "theory of operation").
Yes, but are you sure those commands are actually coded as DEFERRED? The coding examples and the coding sheets for the BXTST diagnostic tests are usually written in "PPR notation."
PPR assumes that, unless you override it with a "w" or "u" prefix, any command with D=31 should be assembled as immediate and all others should be assembled as deferred, except if T=L+1, in which case it will be assembled as immediate and T will be increased by one. See the Coding Manual for the Bendix G-15, under the heading "A Note Concerning the Program Preparation Routine" (p.22, PDF p.24) at http://bitsavers.org/pdf/bendix/g-15/G15_CodingManual.pdf.
I wrote a very basic disassembler to decode paper tape images and help me to undestand the BXTST diagnostics when I was debugging the emulator. That script is available in the repo at https://github.com/pkimpel/retro-g15/blob/master/software/tools/Paper-Tape-Disassembler.html.
I modified that this morning to test your assertion about the number of "Ln Tn+1 Nn+2" instances in those programs. I added three columns to the output, WTR, WRC, and TT, for the wait-for-transfer, wait-to-read-command, and total instruction times for the commands. If the command has T=L+1, the TT column entry has a "+" suffix.
I only found three cases where commands having T=L+1 were deferred. These were all in block 7 of the tape at locations 41, 67, and 70 (see PDF pages 221 and 223 in the Theory of Operation manual). They all involve one or two word registers, so the max additional rotational delay for them would only be one word time.
I did this change quickly, so the timing reported may not be correct in all cases (especially when shorter lines are involved). I've attached a unified diff of the changes and a copy of the output if you are interested in looking at it. BXTST-Disassembly-20240108.zip
PPR assumes that, unless you override it with a "w" or "u" prefix, any command with D=31 should be assembled as immediate and all others should be assembled as deferred, except if T=L+1, in which case it will be assembled as immediate and T will be increased by one.
"T will be increased by one" Now that makes sense! And I observed it a few times when I forgot the "w", without understanding. I was fighting with PPR to force deferred command all that time.
Sorry to have waste your time with this.
It wasn't a waste of my time. I am always happy to help someone with one of my emulators, and as usual, I learned something when researching this issue, and I'm pleased that we got your mystery cleared up.
First: I love your emulator. I spend all my 2 weeks of vacation playing with it. Today I started to optimize my first program using the "minimum acces coding" method. The time of execution went only from 24 seconds to 22 seconds. I then checked with the JS debugger to see why. With instructions like "L10 T11 N12 C0 S20 D28", "drum.waitFor(107) was called...
I think the call "this.drum.waitFor(1)" in case of deferred command in "processor.readCommand", line 2353, should be removed. I tried to remove it, and the execution of my optimized program went to 16 seconds. The kind of improvement I was expecting. The basic functions of the PPR seem to work fine.
Thanks again for your great work!