MCODE Timing Allerlei



#2

Hi, in my recent endevor to learn more about MCODE I came about the question 'which instruction is faster - WRIT 3(x) or A=C ALL'.

First let me thank Ken (in case he is listening) for his fantastic book, the creator of the SDK41 as without it I would have no chance whatsoever and Diego for his wonderful Nov32 (it sometimes wants some extra TLC but that is okay, we all do :-) )

My hypothesis was that each instruction should take the same amount of time as long as they are only one byte long. As I could not find any timing tables, I thought about a way to time MCODE instructions. This created a set of other questions, to some of which I have not found the answer. However, I felt it was a good point in time to share some of my trials - to generate some knowing smiles and chuckles for those who know how to program MCODE (as compared to me who does not) and for the amusement of the masses in general :-)

Here is my approach

  1. Create a MCODE function PPSPEED that stors its absolute start address into say reg M (we will use this to find the page number)
  2. Create a MCODE function 'SPEED' which consists of a loop 3FF times (max that can be loaded via LDIS&X) over ~60 (64 is max jump distance with short jumps) instructions we want to time
  3. Create a FOCAL program 'GP' that uses PPSPEED to find the page at which SPEED is located
  4. Create a FOCAL program 'CPY' that copies the value at the first step in the testing loop of SPEED ~60 times so we can easily test different instructions
  5. Creat a FOCAL program 'TST' that then runs SPEED and takes the time it takes

The above group of programs will allow to measure relative speed (which is the thing I am mostly concerned anyway). Its biggest drawback is that I did not figure out a way to place a byte into a page directly. Any hints hereto would be most appreciated.

To use the program one

  1. Places the code of the instruction one wants to test via 'HEXEDIT' in the right place (p09A) I use HEPAX here
  2. run 'CPY' (which calls 'GP' to find the right page)
  3. run 'TST' which leaves the total execution time in x

So far, my tests seem to indicate that my hypothesis is (at least to first order approximation) correct, which surprises me. So I assume that I have made a mistake, which is why I post...

Please find below the code for the various programs and a summary of the questions that have bubbled up:

  1. Is there a simple way to get the PC into C? I have used a roundabout way via a relative XQ which works but is not pretty. (see 'PPSPEED')
  2. Is there a way to programatically write a byte into MLDL memory (I am using NoV32 here)?
  3. Can it be correct that instructions like NOP and WRIT 3(x) take almost exactly the same amount of time?

Thanks so much for listening and for any kind advice you might offer.

Cheers

Peter


* PPSPEED.SRC
* Assembled by A41
* Mon May 19 23:47:12 2008
;***************** Start of PPSPEED rom ****************
.TITLE "PPSPEED"
.JDA
;**********************************
;* FAT for PPSPEED ROM *
;**********************************
0000 001 XROM 1 ;XROM number
0001 002 FCNS 2 ;Header + 1 function
0002 000089 DEFR4K [Header] 0089 ;first executable of header
0004 000096 DEFR4K [Speed] 0096 ;first executable of function
0006 000 NOP ;FAT termination
0007 000 NOP ;FAT termination
;***********************************
.FILLTO 0081
;******** Start of Code ************
;**** Header
.NAME "PPSPEED"
*0082 084 #084 ; "D"
*0083 005 #005 ; "E"
*0084 005 #005 ; "E"
*0085 010 #010 ; "P"
*0086 013 #013 ; "S"
*0087 010 #010 ; "P"
*0088 010 #010 ; "P"
0089 37903C08C [Header] ?NCXQREL [TEMP] 008C ;not elegant, but it works...
008C 04E [TEMP] C=0 ALL ;Would love to hear better ideas
008D 270 RAMSLCT
008E 1B0 POPADR
008F 168 WRIT 5(M)
0090 3E0 RTN
;**** SPEED Function
.NAME "SPEED"
*0091 084 #084 ; "D"
*0092 005 #005 ; "E"
*0093 005 #005 ; "E"
*0094 010 #010 ; "P"
*0095 013 #013 ; "S"
0096 178 [Speed] READ 5(M) ;select status registers
0097 1303FF LDIS&X 3FF ;use alpha reg so we
0099 168 WRIT 5(M) ;can test A,B,C reg instr.
009A 000 [START] NOP ;this is the area where
009B 000 NOP ;will repeat the instruction
009C 000 NOP ;to be tested
... ... ... ;it fits 59 times in here
00D4 000 NOP ;before the jump gets too
00D5 000 NOP ;far
00D6 178 READ 5(M)
00D7 266 C=C-1 S&X
00D8 01F JC (end) +3 00DB
00D9 168 WRIT 5(M)
00DA 203 JNC [START] -64 009A
00DB 3E0 (end) RTN


LBL TST      ;get the overall time the instructions take
TIME ;it will be run 59*3ff times = 60,357
SPEED ;this takes roughly 11 seconds
TIME
X<>Y
HMS-
Fix 6
View X
RTN

LBL CPY ;copy the byte at first step of loop p09Ah 59 times down
12
WSIZE ;so that we ARCLH 3 digits
XEQ 'GP' ;get the MLDL page and alpha control string
155.213 ;09B : 0D5 is the code area for our test instruction
Sto 00
Lbl 00
Rcl 00
Int
ARCLH ;this CCD function appends the hex equiv of X
CODE ;any code will do, I use the HEPAX one
COPYROM ;this is a hepax function but I believe others exist
ABSP ;dell the address
ABSP
ABSP
ISG 00
GTO 00
RTN

LBL 'GP' ;find the page that SPEED is located in
CLA
PPSPEED ;this stores its location into M
Rcl M
DECODE ;again, any will do, this is HEPAX
ASHF ;isolate the page number
ATOX
ATOX
'00 ;prepare the alpha control string
XTOA
'->09A ;-> means append
XTOA
'->09A
XTOA
RTN


#3

All one-word instructions take a single cycle (56 clock periods) except CXISA, which takes two.

All two-word instructions take two cycles.


#4

thanks Eric, that was my hypothesis. Any thoughts on how to write a byte directly into MLDL? Can I RAMSLCT the memory of the MLDL and then WRIT to it?

Cheers

Peter


#5

Peter,

for writing to MLDL memory, use the WROM instruction (or WRIT S&X), hex $040. This is the write equivalent of FETCH S&X. WROM writes the word in C-S&X to the address in C[3..6]. RAMSLCT or PRPHSLCT does not work, since the memory is not treated as a register or peripheral. The actual instruction 040 is a NOP for the NUT processor and is implemented inside the MLDL device.

For getting your own program counter, use the mainframe function PCTOC at $00D7, it has the following code:

PCTOC       00D7 1B0 ... ... POPADR  
00D8 170 ... ... PUSHADR
00D9 3E0 ... ... RTN
This is probably faster than calling your local subroutine.

Good to see some HP41 mcode discussions here!

Meindert


#6

Thanks Meindert for your great help, this was exactly what I was looking for!

Will try later on tonight to streamline the idea (with your PCTOC tip and WROM tip, I can replace the whole set of Focal programs PG and CPY. Well, thanks to Erics response we also know the answer already so don't need to time any instructions anymore but it still is a great exercise!)

Thanks again and have a great day

Cheers

Peter


#7

Quote:
Well, thanks to Erics response we also know the answer already so don't need to time any instructions anymore

Well, I'm very confident of my answer, but I'm not infallible. Don't design any safety-critical systems using the Nut processor and then blame me if my instruction timing information is wrong and someone gets injured or killed. :-)

My understanding of the processor timings on the various pre-Saturn processors is from a combination of reverse-engineering work with oscilliscopes and logic analyzers, patents, and in a few cases HP internal specifications. It's taken a long time, but I think I'm just about to the point of having all the information necessary to simulate ALL of the APD/CVD calculators introduced from 1972 to 1983 except the HP-10.

#8

Hi,

many thanks for the clarification:-)

Until now, I thought that timings of the nut would

depend on the type of operation, like in the Saturn CPU.

Good to know that I still can learn something new,

at least for me, and even better as this knowledge

simplifies things, as I don't have to think about

instruction timings for the HP-41 anymore;-)

On the Saturn (CPU), instruction timings

are a very important topic, at least for me...

BR

Raymond

#9

Hi,

Thanks to all the great info and as an 'exercise for the interested reader' I replaced most of the focal programs with one MCODE program which now a)figures out in which page it sits and b)copies a user supplied hex code for the test-instruction into the SPEED MCODE program are for testing.

And, es Eric had already explained, all one byte instructions take up the same amount of time. Interestingly enough though, I did not get 2x the time for the CXISA / Fetch S&X instruction, but only a small percentage longer. Could it be that the time for the FETCH instruction has something to do with the MLDL - and as I use a NoV32, could that be 'faster' than some older MLDL's?

I thought that with the design I have set-up for the SPEED function, that the majority of the time should be spend executing the test instruction (60,357 times) vs ~5000 'looping instructions'.

However, on my normal CV with NoV32 the NOP, just as any other instruction seems to take about 10.45 sec (that's the time that passes between the two TIME statements). For the CXISA statement it is 10.61sec. Longer than for any other, but not twice.

So my question is: Where am I going wrong?

Cheers

Peter

First, this is the new CPY Mcode function that I have simply added after the SPEED function. It takes care of identifying the right page and then copying the hex code passed in Reg X into the loop in SPEED

                               .NAME  "CPY"	;copy values into MLDL
*00E7 099 #099 ; "Y"
*00E8 010 #010 ; "P"
*00E9 003 #003 ; "C"
00EA 35D000 [CPY] ?NCXQ [PCTOC] 00D7 ;get PC into C[6:3]
00EC 03C RCR 3 ;move page number into 3
00ED 13009A LDIS&X 09A ;address of first test instructions
00EF 1BC RCR 11 ;move it into C[6:3]
00F0 0BA A<>C M ;save to A
00F1 0F8 READ 3(x) ;should have format of 000000000hhh
00F2 0A6 A<>C S&X ;S&X should have hhh so now A has right format for WRIT S&X
00F3 13003A LDIS&X 03A ;=58d the number of test instructions - loop counter
00F5 0AE A<>C ALL
00F6 040 [Loop] WROM
00F7 1A6 A=A-1 S&X
00F8 02F JC [Done] +5 00FD
00F9 03C RCR 3
00FA 226 C=C+1 S&X ;increment adress to write to
00FB 1BC RCR 11
00FC 3D3 JNC [Loop] -6 00F6
00FD 3E0 [Done] RTN

and this is the simple FOCAL program to steer the whole testing:

Lbl 'TST
10
WSIZE
'HEX:'
PMTH ;CCD hex input function. hex value in dec in x
CLA
ARCLH ;CCD function-put hex rep of x val into Alpha
CODE
CPY ;this is my copy MCODE function
'START ;to let the user know the test starts
AVIEW
TIME ;take time
SPEED ;run ~60k the test instruction
TIME ;Get Time again
X<>Y
HMS- ;calc total run time of SPEED + some portion of TIME
Tone 9
VIEW x
STOP
GTO TST

#10

About instruction timing:

The HP41 has a fixed instruction loop, consisting of 56 clocks. So all instructions should take 56 clocks (56 being the length of the NUT's registers). There should be no variations apart from changing the clock frequency, and this is not depending on the speed of external peripherals. Since the NUT's oscillator is a simpel RC network and not an XTAL, the exact frequency could possibly depend a bit on power consumption.

When fetching an instruction, the address is issued by the NUT during clocks 16-31 on the ISA line. The ROM (or peripheral, MLDL) responds by returning the 10-bit instruction on ISA during clocks 46-55. When this is really an instruction, the NUT drives SYNC high. When this is data, or the second word of an instruction (LDI, GO/XQ) SYNC will remain low while tranferring the 10 bits.

The NUT then has time to actually execute the instruction, until the address of the next instruction must be present in ISA.


The FETCH S&X instruction works a bit different. During the first cycle the FETCH instruction itself must be read from the ROM. During the second complete cycle the data itself (what you wanted to FETCH) is read from the ROM.

I happened to find a trace (from a real HP41!) that I made of the HP41 system ROM, when checking the ROM entry points. See if this makes any sense. The FETCH S&X should really take twice as long!

Meindert


         |50   |00       |10       |20       |30       |40
67890123450123456789012345678901234567890123456789012345
SYNC ----------______________________________________________
ISA --_--________________________--------__-________________ 01B 27F8
DATA ________________________-__----------_-_____-----_______0.00/01F05FF9.0.00


|50 |00 |10 |20 |30 |40
67890123450123456789012345678901234567890123456789012345
SYNC ----------______________________________________________
ISA ____--__--________________-__----------_-_______________ 330 5FF9
DATA ________________________-__----------_-_____-----_______0.00/01F05FF9.0.00


|50 |00 |10 |20 |30 |40
67890123450123456789012345678901234567890123456789012345
SYNC ________________________________________________________
ISA --_--_--_-________________-__--------__-________________ 2DB 27F9
DATA ________________________-__----------_-_____-----_______0.00/01F05FF9.0.00


|50 |00 |10 |20 |30 |40
67890123450123456789012345678901234567890123456789012345
SYNC ----------______________________________________________
ISA _--__---_-_________________-_--------__-________________ 2E6 27FA
DATA ____________--_--_--_-__-__----------_-_____-----_______0.00/01F05FF9.2.DB


RMCK15 27F4 222 ... ... C=C+1 @R
27F5 01B ... ... JNC +03 27F8
27F6 229 0CA ... ?NC GO 328A
LBL_27F8 27F8 330 ... ... FETCH S&X
27F9 2E6 ... ... ?C#0 S&X
27FA 3D3 ... ... JNC -06 27F4


#11

Quote:
The NUT then has time to actually execute the instruction, until the address of the next instruction must be present in ISA.
Isn't it a little less time? - There are only two cycles between SYNC going down and the first bit of the new content of the DATA-line. DATA should be updatet at this point in relation to the instruction.

#12

That is indeed a correct observation,

Meindert

#13

The execution of most instructions occurs during the entire 56-bit cycle that starts one bit times after the instruction word fetch is completed. The processor has a small amount of pipelining; it is fetching the next instruction while completing the execution of the current instruction.

The exceptions are instructions that change the program flow, such as branches, subroutine calls, returns, and the like, since they have to complete by the 16th bit time of the cycle in order to present the correct ROM address for the next instruction fetch.


#14

Hi, first thanks for all the great info, I am always amazed by the depth of knowledge from you guys!

Secondly, I was trying to make sense of the wired result I got from the time-loop and discovered something interesting which might or might not be a different behavior between NoV32 and HEPAX:

Meindert put me on the track for this one by explaining to me that WROM / 040 is actually an instruction implemented in the MLDL.

As of now, I think that this instructions is implemented differently within NoV32 and the original HEPAX:

In NoV32 it seems that the WROM instruction deletes C[6:3] while in the original HEPAX the WROM instruction leaves C unaltered.

Could someone maybe confirm/refute the above tests?

(The way I did come up with this conclusion is having a WRIT 3(x) statement before the WROM instruction and a WRIT 2(y) right after it. Not very elegant but quick, using the DECODE to see what was written. BTW - while doing all of this, my respect for the pioneers is MCODE is growing tremendously. Today I operate with a HEPAX + CCD + SDK41 and it is relatively easy to enter the MCODE, do some CODEing or DECODEing, get the right hex-codes for all the jumps from a quick a41, etc. When you guys developed all the tools and knowledge, you had an Oscilloscope as your best 'tool'!!! I can't even imagine how painstakingly it must have been.)


#15

Peter,

Changing C after the WROM instruction is very unlikely. In some implementations however it was required to have a NOP after a WROM. If you disassemble the DAVID Assembler, you will find a NOP after every WROM. Even then I can not understand why C would be changed.
Can you do another test with a NOP after the WROM?

And for Mcoding, we did have the David Assembler in the old days! (and I did not have a scope at that time). I think the David Assmbler is much quicker when creating a small mcode program than SDK41 and moving files up and down from a PC.

Meindert


#16

Quote:
... If you disassemble the DAVID Assembler, you will find a NOP after every WROM ...
As far as I remember, the reason for the NOP after WROM was one of the MLDL-type devices, which needed 2 words for WROM (Was it the Procoder?).

Maybe it did collect the bits of DATA-line in the next word after decoding a 040 - I don't know. Most MLDL devices collect the bits of DATA in the same word where they find the 040 and are able to do it in one word.

But there is no reason (and no way) to change register C. For the processor it is a NOP and MLDL-Hardware should not write to the DATA-line.

#17

Meindert, Winfried,

Thanks for all your great info. I will go back tonight and check again.

Last night I tried halve a dozen different ways with the exact same code (modulo Errare Humanum Est) in two hp41's side by side (one was a 41cv + X/F + AdvHEPAX the other a cx with the NoV32 (HEPAX + plus CCD)

As far as I could tell they had the exact same code (checked a few times) yet NoV32 seems to leave C[6:3] with 0's after the WROM instruction while the AdvHEPAX did not. I had left it in a loop so there is the possibility of other factors influencing the different outcome between NoV32 and AdvHEPAX.

I will separate them out tonight as standalone instructions, add the NOP after the WROM and test again and post the result.

Thanks again, this is great fun!

Cheers

Peter


#18

Hi all,

Thanks for your mail Peter, and sorry not hooking this thread on an early stage.

First, (as I've repeatedly stated a number of times before) I have almost no knowledge regarding M-code.

Obviously I can tell every detail regarding NoVRAM functionality.

At first glance, it seems that the test you're running are stored (and executed) from the RAM portion of NoVRAM. Please confirm the last.

I'll have to dive into NoVRAM's PIC code for a while to get a detailed answer. In the meanwhile it would be helpful if you can perform same test with your M-code into NoVRAM's Flash ROM.

Fortunately this is more easy now than a few weeks ago:

http://www.hpmuseum.org/cgi-sys/cgiwrap/hpmuseum/forum.cgi?read=136917#136917

You'll need to remove the CCD copy from your NoVRAM though, but this will also help to set a more similar testing scenario for both NoVRAM and HEPAX, as CCD is not present in your CV.

I'll fit my scuba suit to check inside NoVRAM code... ;-) and will post back with a more detailled descrition of the steps NoVRAM performs in order to simulate WROM (WRITE s&x) (H'040) instruction.

Best wishes from the Canary Islands.

Diego.


#19

Diego,

no worries. I will perform the suggested steps as well and report back with results.

And - please - don't humble me even further by claiming that you don't know anything about MCODE! What would that mean for me - negative knowledge? :-)

best wishes to the Canary islands

Cheers

Peter

#20

Diego,

as it turns out I 'only' have a NoVram (and I never updated the software, as this one 'eats' batteries...)

However, I did confirm that at least this particular NoVram clears the C reg after a WROM (040h) and no amount of NOPs before or after changes that...

When you get a chance, please email/post your new RAM2ROM code etc but I'm not sure I understood entirely what you'd like me to do. Can I run the code from flash as well? In any case, once I have your new .hex and .exe files, I will copy the rom image as described in the thread and try to see if I can use my function once it has been copied into flash.

The code I use is below - it basically locates a 'save' place in my rom earlier to write a hhh word to and writes the C reg out to x-reg before the WROM and to y-reg after.

One thought is that my NoVram is maybe a very early one (I think it is one from the earlier/earliest batches) and it also never got an upgrade in software and you might have posted some updates. So this potential problem might already be fixed...

In any case, you in your scuba gear and me with a life vest and a rubber ring for sure will get to the bottom of this :-)

Cheers

Peter

			.NAME	"WRTST"	;Test of WROM
*010D 094 #094 ; "T"
*010E 013 #013 ; "S"
*010F 014 #014 ; "T"
*0110 012 #012 ; "R"
*0111 017 #017 ; "W"
0112 1A0 [WRTST] A=B=C=0
0113 35D000 ?NCXQ [PCTOC] 00D7 ;get PC into C[6:3]
0115 03C RCR 3 ;move page number into 3
0116 13009A LDIS&X 09A ;address of first test instructions
0118 1BC RCR 11 ;move it into C[6:3]
0119 130330 LDIS&X 330 ;FETCH S&X
011B 0E8 WRIT 3(X)
011C 040 [TST] WROM
011D 0A8 WRIT 2(Y)
011E 3E0 RTN

#21

Don't know Diegos answer, but the combination of

Quote:
... this one 'eats' batteries ...)
and
Quote:
... One thought is that my NoVram is maybe a very early one (I think it is one from the earlier/earliest batches) and it also never got an upgrade in software and you might have posted some updates ...
might be the solution.


I have to correct my statement:
Quote:
But there is no reason (and no way) to change register C. For the processor it is a NOP and MLDL-Hardware should not write to the DATA-line.

It is possible, that the CPU doesn't care which command was executed and always reads the DATA-line into C if bits are drawn to low by any peripheral device. A memory chip or module is alway decoding the commands and only answers on DATA-line if it is selected and a read-command is executed. The module or chip (and not the CPU) is responsible for executing commands related to it. By this way it might be possible, that a MLDL-type device changes data in register C by driving the DATA-line to low while a WROM is executed.

If this is not done with intention, it might even happen randomly because the "battery eater" draws down all lines.


You should decide whether you want to collect a device with a early software version or use it and update the software. If you use it like it is and it really changes C, you will get unexpected errors with other MCODE programs which are using the WROM-command.
#22

Hi again,

First a detailed (not too much) description on how NoVRAM handles WROM intruction.

_______________________________________________________________________________

Glossary:

Cycle: Time between two consecutive Phase0 pulses from Phi2. It always takes 56 pulses (bit time), about 155.55uSec @360KHz nominal NUT clock. Most instructions takes only one Cycle.

Phase: Every one of said 56 bit time between two consecutive Phi2 pulses counting from rising edge to rising edge of Phi2. Phases are numbered from Ph0 to Ph55. Phase duration is 2.77usec @360KHz

Phase0: (Ph0) First bit Phase. Inmmediatelly following the falling edge of SYNC signal on a Fetch Cycle.

Fetch: A Cycle in which NUT "fetches" its ROM (or MLDL RAM) to find next instruction to execute. SYNC line is hold high during Ph46 o Ph55 of a Fetch Cycle. ISA line sends the fetched Word during these 10 Phases.

c: NUT accumulator register. It holds 14 BCD digits in 14 nibbles, named c[13:0]. "c" register is sent on the DATA line at every Cycle starting at Ph02 Less Significant Bit first.

Word: 10bits going to be writen to or read from memory. WROM instruction takes its Word from "c" register bits 0 to 9, this corresponds with BCD digits c[2:0]. Note that the two last bits from c[2] are not used.

Address: 16bits referring the memory position where the Word has to be writen to or read from. WROM takes its Address from "c" register bits 12 to 27. This corresponds with BCD digits [6:3]

_____________________________________________________________________________

WROM execution sequence on NoVRAM with HEPAX emulation as of Apr. '08 version.

NOTE: NoVRAM always reads both DATA Ph14 to Ph29 (c[6:3]) and ISA (Ph16 to Ph31) 16 bits addresses, and DATA Ph2 to Ph11 (c[2:0]) Word; and keeps them for every Cycle.

1. At some point, previous intructions must have placed the corresponding Address and Word into appropriate nibbles at "c" register.

2. NUT start a Fetch Cycle.

3. WROM (H'040) instruction is sent to NUT at ISA line Ph46 to Ph55 (i.e. at the *end* of this new Fetch Cycle). Word c[2:0] (Ph2-Ph11) and Address c[6:3] (Ph14-Ph29) have been sent by NUT but they won't be used as NoVRAM has no means to know that it's going to be a WROM until Ph55 finishes (In fact NoVRAM detects WROM at Ph11 during the following cycle). Consequently, both Word and Address will be read from the next Cycle.

4. NUT does nothing as WORM is a NOP. NUT keeps running and start another Fetch Cycle. Note that c register contents remains unaltered because NUT has only received and "executed" a NOP (H'040).

5. At Ph11 NoVRAM detects previous intruction was WROM and confirms it was a Fetch cycle. It reads Address from DATA Ph14 to Ph29 and sent it to its RAM.

6. As Ph26 to Ph29 (Address higher nibble) is read, NoVRAM checks if the received Address correspond to one of its own RAM pages and if that particular page has not been write protected by RAMTOG (H'1F0) instruction. If everything matches NoVRAM procceds with RAM write sequence and send the Word (which has also been read from DATA at Ph2 to Ph11) to the RAM chip during Phases Ph31 to Ph39. In case Address does not points to our RAM or RAM is write protected writting is aborted.

7. Due to the fact that RAM is writen during this Cycle (the following one to the WROM instruction) it is not possible to read from this RAM. Thus NUT will more likely receive a NOP (H'000) if the following Fetch Cycle points to RAM regardless what the next Address contents might be.

8. During the whole process DATA line is an input from NoVRAM's point of view. It doesn't send a bit at any moment.

_________________________________________________________________________________

The above description is consistent with the fact that WROM intruction should be followed by a NOP. But as far as I can see, does not explain how c[6:3] might be erased (or modified in any other way) by NoVRAM code. Mostly when, according to your last post, c[6:3] is zeroed regardless the number of NOPS you place before or after WROM instruction. Which leads me to another question: Is all of c register zeroed? or just c[6:3]. And yet another one for testing: What if you replace WROM with another NOP (H'000)? Obviously it won't write into RAM but, does it still erase c register?

Seems that we'll (I'll) have a lot of work ahead to find out what the h**k is cooking there... ;-)

Regarding the "battery eating" issue, it has nothing to do with NoVRAM operation. Excessive battery drain occured during Light and Deep Sleep, and was effectively fixed in the latest versions.

Best from Spain.

Diego.

Edited: 24 May 2008, 3:43 p.m.

#23

Hi all,

Well, I printed off a copy of Ken Emery's M-code for beginners... (I know... I'd have done years ago... shame on me)

Once I understood what your program "WRTST" does, I wrote a modified version which can be executed from the Flash ROM portion of the NoVRAM and (of course) writes into the RAM portion.

I placed it into page #C.

Basically it takes a "coded" (you must key it in) number from "X" register (so that you can modify it within certain limits) and WROM at specified address.

I've used:

"X"= 1.000009100 E-23 (which writes 177 at RAM address H'9100)

and

"X"= 1.000009101 E23 (which writes 023 at RAM address H'9101)

Since "X" register is used to set Address and Word I used "Z" and "Y" as the pre-WROM and post-WROM copies of NUT "c" register. So, once WRTST is finished you can check by RDN if things have gone as suppossed.

			.NAME	"WRTST"	;Test of WROM
*C10D 094 #094 ; "T"
*C10E 013 #013 ; "S"
*C10F 014 #014 ; "T"
*C110 012 #012 ; "R"
*C111 017 #017 ; "W"
C112 1A0 [WRTST] A=B=C=0
C113 0F8 READ 3(X) ;get Address into c[6:3] and Word into c[2:0]
C114 068 WRIT 1(Z) ;saves a pre-WROM copy of c
C115 040 WROM ;actually Writes RAM
C116 0A8 WRIT 2(Y) ;saves a post-WROM copy of c
C117 3E0 RTN

It works as expected, and you get the corresponding values at H'9100 and H'9101 as well as the "c" register copies into both "Z" and "Y".

At this point we know that whatever is the cause of the bug, it relies on the differences between reading the WROM instruction from RAM or from ROM. It may take a few days, but I'll catch it... you can bet!... ;-)

Cheers.

Edited: 25 May 2008, 5:34 p.m.


#24

Quote:
 C115 040		        WROM	        ;actually Writes RAM
C116 0A8 WRIT 2(Y) ;saves a post-WROM

Just one question: Why does "WRIT Y" without a NOP between it and WROM work? - You explained above, that WROM needs two words and:
Quote:
Due to the fact that RAM is writen during this Cycle (the following one to the WROM instruction) it is not possible to read from this RAM. Thus NUT will more likely receive a NOP (H'000) if the following Fetch Cycle points to RAM regardless what the next Address contents might be.

#25

Hi Winfried,

Quoting: (myself... ;-)

Quote:
Due to the fact that RAM is writen during this Cycle (the following one to the WROM instruction) it is not possible to read from this RAM. Thus NUT will more likely receive a NOP (H'000) if the following Fetch Cycle points to RAM regardless what the next Address contents might be.

..and again:

Quote:
I wrote a modified version which can be executed from the Flash ROM portion of the NoVRAM and (of course) writes into the RAM portion.

I placed it into page #C.


Just to avoid the Fetch Cycle into RAM is why I've placed this into ROM.

Hope this clarifies the idea.

Best regards.

Diego.

Edited: 25 May 2008, 8:01 p.m.

#26

Hi all, Peter,

Got it fixed. Will mail you tomorrow. (Little late here just now)

Best regards.

Diego.


#27

Diego, is this bug somewhat related to my WROM-problem of messing with the key assignment registers? Ref: Earlier thread


#28

Hi Geir,

I can't follow your link above, anyhow, if you were triying to write RAM from a program resident into RAM, the answer is yes, you'd be in trouble with this.

I'll place the new files at my web page with details in a day or two, and will keep you all informed of the update by posting here.

Thanks for your continued support.

Diego.

PS. As I used RAM2ROM.HEX yesterday to produce some testing .ROM images I noticed that the version I have meiled to some of you may well be an outdated one (yes, I know... I'm an organizational mess, my sincere apologies on that) Current version will also be placed at my web in short.


#29

Quote:
Hi Geir,

I can't follow your link above, anyhow, if you were triying to write RAM from a program resident into RAM, the answer is yes, you'd be in trouble with this.

I'll place the new files at my web page with details in a day or two, and will keep you all informed of the update by posting here.


For the NoV-32 as well?

Quote:
PS. As I used RAM2ROM.HEX yesterday to produce some testing .ROM images I noticed that the version I have meiled to some of you may well be an outdated one (yes, I know... I'm an organizational mess, my sincere apologies on that) Current version will also be placed at my web in short.

Diego, any organizational mess is seriously outweighed by your value to my spare time. You are excused, plenty :-)

#30

Then my next question is: how much time do instructions have that change the C register? The C register is presented starting at bit time 2 ...

Meindert


#31

Arithmetic/logical/shift instructions that modify C (or A or B, for that matter) take exactly one cycle (56 bit times).

The DATA line output during execution of such instructions isn't necessarily identical to the C value either before or after the instruction. That was not a design requirement as it was not expected that any memory or peripheral chips would use the data present during the execution of those instructions. The specification only guarantees the data line to present the correct C value during the DADD=C, PFAD=C, and DATA=C instructions, and the some of the instructions intended for use with peripheral devices. As a side effect of the implementation, it also happens to have the C value for most other instructions not of the arithmetic/logical/shift classes.

#32

A MLDL-type device takes the address an the data from the DATA-line when executing a WROM. The collection of this data ist done parallel to decoding address and instruction from ISA. If you change the content of register C in the word before the WROM-instruction, the result of this operation is used.

This means: Register C and the signal of the DATA-line hast to be changed (at least for the first bit) before bit 2 of the word starting with SYNC going down after the last bit of the instruction.

Example:

C=0 S&X

C=C+1 S&X

WROM

This will write 001 to the MLDL and the only bit in C which is changed is the first bit which should be shifted out at DATA-line at bit time 2 of the same 56 bit cycle which has the instruction WROM at the end.


#33

This is very interesting. The way I have implemented WROM in the MLDL2000 is a little bit different, since the writing to MLDL memory is done at a much later bit time:
- during SYNC: read in instruction

- bit 1: check if this is WROM (or bankswitch or FETCH)

- DATA is shited in

- ISA address is shifted in

- at bit 32 the state machine triggers the address conversion (reading the Settings Registers) and checking for Write Protect etc

- one bit time later the actual writing to MLDL memory is done

This means that my instructions are executed not immediately after the SYNC, and I use the DATA that was shifted out after the appearance of the WROM instruction. Since I do the write itself in only a few bit times (including administration) this can never influence the next cycle. If needed, the state machine immediately does a normal ROM read (in bit time 34 and 35), if the WROM was executed from MLDL memory, the ISA address was saved in parallel.
Therefore no NOP is required after WROM in my MLDL2000 implementation.

In case of a FETCH instruction I also take the DATA that appears after the instruction.

ENBANK instructions are executed immediately in MLDL2000, since no parameters from DATA are needed.

Hope this explains some more MLDL internals ...

Meindert


#34

Hi Meindert,

the late writing is possible, because reg C or DATA will be the same in the next 56 bit cycle. But what will happen, if you do a FETCH just after the WROM at the same address? Do you get the new or the old content?

I used this sometimes in my software (MBK ProfiSET OS for example) to check, whether there is RAM or ROM at this address. I did it by reading, inverting, writing and reading again on the same address. The result of comparing old and new content tells which kind of memory is present.

At those days, I had not to care about other MLDL hardware because we wanted to sell our hardware ;)

Cheers
Winfried


#35

Winfried,

The FETCH instruction itself does not change C, so no harm is done. And for the FETCH the data is returned on ISA, not on DATA itself. Also, FETCH is not really a special case, since the address of the data to be FETCHed just appears on ISA. I only decode FETCH to prevent executing code from an I/O area, while just reading is OK.

Meindert


Possibly Related Threads...
Thread Author Replies Views Last Post
  HP-41 MCODE: The Last Function - at last! Ángel Martin 0 138 11-08-2013, 05:11 AM
Last Post: Ángel Martin
  41-MCODE: Auto XEQ+ALPHA possible? Ángel Martin 5 256 05-29-2013, 06:15 AM
Last Post: Ángel Martin
  HP 41 Mcode related Questions Michael Fehlhammer 4 234 05-10-2013, 07:09 PM
Last Post: Michael Fehlhammer
  41-MCODE: Breaking the FAT barrier. Ángel Martin 0 114 09-03-2012, 06:31 AM
Last Post: Ángel Martin
  41-MCODE: Dr. Jekyll & Mr. Hyde Ángel Martin 9 357 07-09-2012, 09:41 AM
Last Post: Monte Dalrymple
  HP41C: Factorial (kind of) in MCODE Frido Bohn 7 311 05-26-2012, 09:18 AM
Last Post: Frido Bohn
  41-MCODE: SOLVE & INTEG - 4k ROM Ángel Martin 9 355 04-19-2012, 05:29 AM
Last Post: fhub
  41-MCODE: a weekend challenge Ángel Martin 3 169 03-19-2012, 06:49 AM
Last Post: Mike (Stgt)
  41-MCODE trivia: backwards or forwards? Ángel Martin 3 166 03-05-2012, 04:38 PM
Last Post: Håkan Thörngren
  32-bit MCODE tool chain for the HP41 incl. D41 now MichaelG 4 204 02-12-2012, 08:57 PM
Last Post: Kerem Kapkin (Silicon Valley, CA)

Forum Jump: