unit timer_dw;
interface
function GetTimer_1:dword; {счетчик в 1 мкс (0,5 ч.)}
function GetTimer_50:dword; {счетчик в 50 мкс (1 сут.)}
function GetTimer_1000:dword; {счетчик в 1 мс (20 сут.) }
function GetCPUtick:int64; {счетчик в тактах проц. }
function GetCPUfreq:dword; {частота процессора в кГц}
function GetDelta:dword; {погрешность частоты в кГц }
procedure InitTimer; {реинициализация таймера}
implementation
uses WinDos;
var
b1,b50,b1000,delta : longint; {коэффициенты деления}
C1,c50,c1000 : longint; {маски}
function GetCPUfreq:dword; {частота процессора в кГц}
begin
GetCPUfreq := b1000;
end;
function GetDelta:dword; {погрешность частоты в кГц }
begin
GetDelta := delta;
end;
function GetTimer_1:dword; assembler;
asm
db $0f,$31 {rdtsc}
and edx,c1
div b1
end;
function GetTimer_50:dword; assembler;
asm
db $0f,$31 {rdtsc}
and edx,c50
div b50
end;
function GetTimer_1000:dword; assembler;
asm
db $0f,$31 {rdtsc}
and edx,c1000
div b1000
end;
function GetCPUtick:int64;
var q : int64;
begin
asm
db $0f,$31 {rdtsc}
mov dword ptr [q],eax
mov dword ptr [q+4],edx
end;
getCPUtick := q;
end;
function GetLessFF(n:longint):longint;{возвращение бинарное}
{число вида 00...0011...11 меньшее заданного}
var i,j : longint;
begin
j := 1;
repeat
i := j;
j := j*2;
until j > n;
GetLessFF := i-1;
end;
procedure InitTimer;
const
n = 8; {количество измерений}
Const1 : extended = 0.0182; {част.стнд.таймера в кГц}
var
i,j : longint;
t : array[0..n]of extended; {результаты измерения тактов}
d : array[0..n]of extended; {результаты измерения времени, мс}
t0,t1 : extended;
h_,m_,s_,d_,d1_ : word; {для определения времени}
sti,sta : extended; {сумма тиков; сумма тактов}
begin
t0 := getCPUtick;
sti := 0;
for i := 0 to n do begin {формируем массив измерений}
GetTime(h_,m_,s_,d_);
repeat
GetTime(h_,m_,s_,d1_);
until d1_ <> d_;
t[i] := getCPUtick-t0;
if d1_ > d_ then
d[i] := (d1_-d_)*10
else
d[i] := ((d1_+100)-d_)*10;
sti := sti + d[i];
end;
sti := sti - d[0]; {время измерения в мс}
sta := t[n] - t[0]; {время измерения в тактах}
if ((n/sti*0.8) > Const1) or { если Const1 }
((n/sti*1.2) < Const1) then { отличается }
Const1 := n/sti; { более 20% }
for i := 0 to n-1 do begin {вычисляем за 1 тик}
t[i] := (t[i+1]-t[i]);
end;
for i := 1 to n-1 do {сортируем массив}
for j := n-1 downto i do
if t[j] < t[j-1] then
begin
t0 := t[j]; t[j] := t[j-1]; t[j-1] := t0;
end;
j := n div 4; {отбрасываем ~ по 1/4 с каждой стороны}
t0 := 0;
for i := j to n-1-j do { берем середину }
t0 := t0 + t[i]; { отсортированного массива }
t0 := t0 / (n-j-j); {ср.кол-во тактов за тик}
t1 := t0 * Const1; {ср.кол-во тактов за мс}
b1000 := round(t1); { вычисляем }
b50 := round(t1 / 20); { коэффициенты }
b1 := round(t1 / 1000); { деления }
c1 := GetLessFF( b1); { вычисляем }
c50 := GetLessFF( b50); { значения }
c1000 := GetLessFF(b1000); { маски }
t1 := 0;
for i := j to n-1-j do { оцениваем }
t1 := t1 + sqr(t[i]-t0); {погрешность}
delta := round(sqrt(t1/(n-j-j))*Const1);{ измерения }
end;
begin
InitTimer;
end.