To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.roboticsOpen lugnet.robotics in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / 21974
21973  |  21975
Subject: 
Re: nop in NQC?
Newsgroups: 
lugnet.robotics
Date: 
Wed, 7 Jan 2004 21:32:59 GMT
Viewed: 
909 times
  
"John Hansen" <JohnBinder@aol.com> wrote in message
news:Hr4HAJ.LIy@lugnet.com...
<snipped>
Or you can just forget all that.  I ran the same test with the order
changed and the 3rd NOP of the 5 I tried was always the fastest
(regardless of which one I used).  Modifying the program to try each
of 5 different options in 10 different orders yielded these results:

A different measurement scheme gives better accuracy on the 'nop'
timing.

Just about every opcode takes the same amount of time. Priimarily
because there's so much common overhead (90% of the effort) spent in the
firmware (switching between tasks, etc) before it gets to the "guts" of
actually implementing a single opcode. Measuring with a more
sophisticated time measurement program, the individual 'nop' opcodes
take the following time (units are milliseconds per opcode):

2.80  void NOP1() { Wait(0); }
2.78  void NOP2() { Wait(-1); }
2.72  void NOP3() { asm { 0x27, 1 }
2.68  void NOP4() { asm { 0x10 }; }
2.98  void NOP5() { asm { 0x14, 0, 0, 0, 0 }; }
2.82  variable1 = variable2
2.99  counter0  = counter1

My measurement technique was to subtract the time to execute an "repeat
500" on an empty loop with the time to do a "repeat 500" loop containing
20 instances of the opcode being measured. The result is the time to
xecute 10,000 'nop's. All the different 'nop's take about the same mount
of time! It really doesn't matter which is used!

I added two extra types of "nop". One is simple ssignment of a counter
variable (address range 0..2) and the other is assignment of a regular
ariable (3..31). Counter variable assignment takes more time because the
firmware checks to see if the new value triggers an 'event'. This is orn
out by the 2.82 vs 2.99 difference.

I suspect a partial cause of your timing inaccuracy is inaccuracy in the
FastTimer". The firmware manages two resolutions of timers that are
incremented at interrupt level. One is for the four timers and uses a
100 millisecond tick. The second is an internal 0 to 99 timer on a 1
msec time basis. The FastTimer is calculated on non-interrupt by
combining the two values (i.e. FastTimer = (100MsecTimer * 10) +
(1MsecTimer / 10)). Under the right circumstances a bad result occurs
when the 1MsecTimer wraps to zero in the middle of the calculatiion.
Perhaps your program is such that this always occurs with the 'nop' in
the third position in the list.

Another and probably more important cause of your timing inaccuracy is
that a 10 msec timer is too course resolution to measure a single 'nop'.
The test sequence in your program is only three instructions (read start
timer, nop, read end-time) which is right on the border of only taking
10 msec to execute. Individual measurement values are going to be 0, 1
or 2 depending upon where in the current 10-msec tick timing for a
single 'nop' starts. The internal timing in your loop may favor the
third 'nop' for many 0 readings. I confirmed this by checking for zero
timings at the end of each iteration of the loop. Results from switching
order of NOP3 and NOP4 in your original code are:
  3, 44, 86, 26, 3 [counts are the number of 0 timings in the loop]
  2, 45, 87, 32, 9
In both cases, the third item has the most zero readings.


My test program follows.
//=====================================================
//Program to test timing for various 'nop's
//=====================================================

__nolist void NOP1() { Wait(0); }
__nolist void NOP2() { Wait(-1); }
__nolist void NOP3() { asm { 0x27, 1 }; }
__nolist void NOP4() { asm { 0x10 }; }
__nolist void NOP5() { asm { 0x14, 0, 0, 0, 0 }; }

int counter0, counter1, counter2; // counter variables
int variable0, variable1;
int nIdleLoop;
int nTimeWait0, nTimeWaitMinusOne, nTimeBranchNext, nTimeAlive,
nTimeAssign;
int nTimeVariable, nTimeCounter;

#define kLoopCount 500

task main()
{
  counter0 = 0;
  counter1 = 0;
  counter2 = 0;
  variable0 = 0;
  variable1 = 0;

  ClearTimer (0);
  repeat (kLoopCount)
  {
  }
  nIdleLoop = Timer(0);

  ClearTimer (0);
  repeat (kLoopCount)
  {
    NOP1();NOP1();NOP1();NOP1();NOP1();
    NOP1();NOP1();NOP1();NOP1();NOP1();
    NOP1();NOP1();NOP1();NOP1();NOP1();
    NOP1();NOP1();NOP1();NOP1();NOP1();
  }
  nTimeWait0 = Timer(0) - nIdleLoop;


  ClearTimer (0);
  repeat (kLoopCount)
  {
    NOP2();NOP2();NOP2();NOP2();NOP2();
    NOP2();NOP2();NOP2();NOP2();NOP2();
    NOP2();NOP2();NOP2();NOP2();NOP2();
    NOP2();NOP2();NOP2();NOP2();NOP2();
  }
  nTimeWaitMinusOne = Timer(0) - nIdleLoop;


  ClearTimer (0);
  repeat (kLoopCount)
  {
    NOP3();NOP3();NOP3();NOP3();NOP3();
    NOP3();NOP3();NOP3();NOP3();NOP3();
    NOP3();NOP3();NOP3();NOP3();NOP3();
    NOP3();NOP3();NOP3();NOP3();NOP3();
  }
  nTimeBranchNext = Timer(0) - nIdleLoop;


  ClearTimer (0);
  repeat (kLoopCount)
  {
    NOP4();NOP4();NOP4();NOP4();NOP4();
    NOP4();NOP4();NOP4();NOP4();NOP4();
    NOP4();NOP4();NOP4();NOP4();NOP4();
    NOP4();NOP4();NOP4();NOP4();NOP4();
  }
  nTimeAlive = Timer(0) - nIdleLoop;


  ClearTimer (0);
  repeat (kLoopCount)
  {
    NOP5();NOP5();NOP5();NOP5();NOP5();
    NOP5();NOP5();NOP5();NOP5();NOP5();
    NOP5();NOP5();NOP5();NOP5();NOP5();
    NOP5();NOP5();NOP5();NOP5();NOP5();
  }
  nTimeAssign = Timer(0) - nIdleLoop;


  ClearTimer (0);
  repeat (kLoopCount)
  {
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
    variable0 = variable1;variable0 = variable1;
  }
  nTimeVariable = Timer(0) - nIdleLoop;


  ClearTimer (0);
  repeat (kLoopCount)
  {
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
    counter0 = counter1;counter0 = counter1;
  }
  nTimeCounter = Timer(0) - nIdleLoop;
}



Message has 1 Reply:
  Re: nop in NQC?
 
(...) Doh! Now I really feel sheepish. Please forgive my public display of idiocy. John Hansen (21 years ago, 8-Jan-04, to lugnet.robotics)

2 Messages in This Thread:

Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR