/*
Copyright (C) 1998-2003 T. Scott Dattalo
This file is part of gpsim.
gpsim is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
gpsim is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with gpsim; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "bitlog.h"
#include "../src/gpsim_time.h"
BoolEventLogger::BoolEventLogger(unsigned int _max_events)
: max_events(_max_events)
{
// Make sure that max_events is an even power of 2
if(max_events & (max_events - 1)) {
max_events <<= 1;
while(1) {
if(max_events && (max_events & (max_events-1)))
max_events &= max_events - 1;
else
break;
}
} else if(!max_events)
max_events = 4096;
buffer = new guint64[max_events];
gcycles = &get_cycles();
max_events--; // make the max_events a mask
index = 0;
}
void BoolEventLogger::event(bool state)
{
// If the new event is different the most recently logged one
// then we need to log this event. (Note that the event is implicitly
// logged in the "index". I.e. 1 events are at odd indices.
if(state ^ (index & 1))
{
index = (index + 1) & max_events;
buffer[index] = gcycles->get();
}
}
void BoolEventLogger::dump(int start_index, int end_index)
{
if((start_index > (int)max_events) || (start_index <= 0 ))
start_index = 0;
if(end_index == -1)
end_index = index;
if(start_index == end_index)
return;
// Loop through and dump events between the start and end points requested
do {
cout << hex << "0x" << start_index << " = 0x" << buffer[start_index];
if(start_index & 1)
cout << ": hi\n";
else
cout << ": lo\n";
start_index = (start_index + 1) & max_events;
}while ( start_index != end_index);
}
void BoolEventLogger::dump_ASCII_art(guint64 time_step,
guint64 start_time,
int end_index)
{
int start_index = get_index(start_time);
if((start_index > (int)max_events) || (start_index <= 0 )) {
start_index = 0;
start_time = buffer[0];
}
if(buffer[start_index] == 0) {
start_index = 0;
start_time = buffer[0];
}
if( (end_index > (int)max_events) || (end_index <= 0 ))
end_index = index;
if(start_index == end_index)
return;
if(time_step == 0)
time_step = 1;
// Loop through and dump events between the start and end points requested
guint64 min_pulse = buffer[end_index] - buffer[start_index];
unsigned long i = start_index;
int j = (start_index+1) & max_events;
do {
if( (buffer[j] - buffer[i]) < min_pulse )
min_pulse = (buffer[j] - buffer[i]);
i = j;
j = ++j & max_events;
}while (j != end_index);
//cout << "minimum pulse width :" << min_pulse << '\n';
if(min_pulse == 0) { // bummer - there's an error in the log
min_pulse = 1;
cout << "log error - minimum pulse width shouldn't be zero\n";
}
int num_chars = 0;
guint64 t = start_time; //buffer[start_index];
guint64 stop_time = gcycles->get();
i = start_index;
do {
if(t<=buffer[end_index])
j = get_index(t);
else
j = end_index;
switch(j-i) {
case 0:
case 1:
if(i&1)
cout <<'-';
else
cout <<'_';
break;
case 2:
cout << '|';
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
cout << (j-i);
break;
default:
cout << '*';
}
i = j;
t += time_step;
} while( t<stop_time && num_chars++<1000);
cout << '\n';
//cout << "\nend of ASCII art\n";
}
unsigned int BoolEventLogger::get_index(guint64 event_time)
{
unsigned long start_index, end_index, search_index, bstep;
end_index = index;
start_index = (index + 1) & max_events;
bstep = (max_events+1) >> 1;
search_index = (start_index + bstep) & max_events;
bstep >>= 1;
// Binary search for the event time:
do {
if(event_time < buffer[search_index])
search_index = (search_index - bstep) & max_events;
else
search_index = (search_index + bstep) & max_events;
//cout << hex << "search index "<< search_index << " buffer[search_index] " << buffer[search_index] << '\n';
bstep >>= 1;
} while(bstep);
if(event_time >= buffer[search_index])
return search_index;
else
return (--search_index & max_events);
}
//------------------------------------------------------------------------
ThreeStateEventLogger::ThreeStateEventLogger(unsigned int _max_events)
: max_events(_max_events)
{
// Make sure that max_events is an even power of 2
if(max_events & (max_events - 1)) {
max_events <<= 1;
while(1) {
if(max_events && (max_events & (max_events-1)))
max_events &= max_events - 1;
else
break;
}
} else if(!max_events)
max_events = 4096;
pTimeBuffer = new guint64[max_events];
pEventBuffer = new char[max_events];
// Initialize the time buffer
for (int i=0; i<max_events; i++)
pTimeBuffer[i] = 0;
gcycles = &get_cycles();
max_events--; // make the max_events a mask
index = max_events;
bHaveEvents = false;
}
unsigned int ThreeStateEventLogger::get_index(guint64 event_time)
{
if (!bHaveEvents)
return 0;
unsigned long start_index, end_index, search_index, bstep;
end_index = index;
start_index = (index + 1) & max_events;
bstep = (max_events+1) >> 1;
search_index = (start_index + bstep) & max_events;
bstep >>= 1;
// Binary search for the event time:
do {
if(event_time < pTimeBuffer[search_index])
search_index = (search_index - bstep) & max_events;
else
search_index = (search_index + bstep) & max_events;
bstep >>= 1;
} while(bstep);
if(event_time == pTimeBuffer[search_index])
return search_index;
if(event_time < pTimeBuffer[search_index] &&
pTimeBuffer[search_index] != Cycle_Counter::END_OF_TIME)
search_index = (--search_index & max_events);
return search_index;
}
unsigned int ThreeStateEventLogger::get_nEvents(unsigned int start_index, unsigned int stop_index)
{
return (stop_index >= start_index) ? (stop_index-start_index) : (max_events-stop_index+start_index);
}
unsigned int ThreeStateEventLogger::get_nEvents(guint64 start_time, guint64 stop_time)
{
unsigned int start_index = get_index(start_time);
unsigned int stop_index = get_index(stop_time);
return get_nEvents(start_index,stop_index);
}
void ThreeStateEventLogger::event(char state)
{
// If the new event is different the most recently logged one
// then we need to log this event. (Note that the event is implicitly
// logged in the "index". I.e. 1 events are at odd indices.
if(state != pEventBuffer[index]) {
index = (index + 1) & max_events;
pTimeBuffer[index] = gcycles->get();
pEventBuffer[index] = state;
bHaveEvents = true;
}
}
void ThreeStateEventLogger::dump(int start_index, int end_index)
{
if (!bHaveEvents)
return;
if((start_index > (int)max_events) || (start_index <= 0 ))
start_index = 0;
if(end_index == -1)
end_index = index;
if(start_index == end_index)
return;
// Loop through and dump events between the start and end points requested
do {
cout << hex << "0x" << start_index << " = 0x" << pTimeBuffer[start_index];
cout << " : " << pEventBuffer[start_index] << endl;
start_index = (start_index + 1) & max_events;
}while ( start_index != end_index);
}
void ThreeStateEventLogger::dump_ASCII_art(guint64 time_step,
guint64 start_time,
int end_index)
{
int start_index = get_index(start_time);
if((start_index > (int)max_events) || (start_index <= 0 )) {
start_index = 0;
start_time = pTimeBuffer[0];
}
if(pTimeBuffer[start_index] == 0) {
start_index = 0;
start_time = pTimeBuffer[0];
}
if( (end_index > (int)max_events) || (end_index <= 0 ))
end_index = index;
if(start_index == end_index)
return;
// Loop through and dump events between the start and end points requested
guint64 min_pulse = pTimeBuffer[end_index] - pTimeBuffer[start_index];
unsigned long i = start_index;
int j = (start_index+1) & max_events;
do {
if( (pTimeBuffer[j] - pTimeBuffer[i]) < min_pulse )
min_pulse = (pTimeBuffer[j] - pTimeBuffer[i]);
i = j;
j = ++j & max_events;
}while (j != end_index);
cout << "minimum pulse width :" << min_pulse << '\n';
if(min_pulse == 0) { // bummer - there's an error in the log
min_pulse = 1;
cout << "log error - minimum pulse width shouldn't be zero\n";
}
time_step = 0;
time_step = time_step ? time_step : ((min_pulse>2) ? min_pulse/2 : 1);
int num_chars = 0;
guint64 t = start_time; //buffer[start_index];
guint64 stop_time = gcycles->get();
i = start_index;
do {
if(t<=pTimeBuffer[end_index])
j = get_index(t);
else
j = end_index;
cout << pEventBuffer[j];
/*
switch(j-i) {
case 0:
case 1:
if(i&1)
cout <<'-';
else
cout <<'_';
break;
case 2:
cout << '|';
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
cout << (j-i);
break;
default:
cout << '*';
}
*/
i = j;
t += time_step;
} while( t<stop_time && num_chars++<1000);
cout << '\n';
//cout << "\nend of ASCII art\n";
}
syntax highlighted by Code2HTML, v. 0.9.1